mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Rename test/unittests to tests/ and test/ to bin/
This commit is contained in:
parent
ecfd688117
commit
9a690580c9
92 changed files with 38 additions and 39 deletions
228
bin/echo_server.c
Normal file
228
bin/echo_server.c
Normal file
|
@ -0,0 +1,228 @@
|
|||
/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
/*
|
||||
* echo_server.c -- QUIC server that echoes back input line by line
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <netinet/in.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lsquic.h"
|
||||
#include "test_common.h"
|
||||
#include "prog.h"
|
||||
|
||||
#include "../src/liblsquic/lsquic_logger.h"
|
||||
|
||||
|
||||
struct lsquic_conn_ctx;
|
||||
|
||||
struct echo_server_ctx {
|
||||
TAILQ_HEAD(, lsquic_conn_ctx) conn_ctxs;
|
||||
unsigned max_reqs;
|
||||
int n_conn;
|
||||
struct sport_head sports;
|
||||
struct prog *prog;
|
||||
};
|
||||
|
||||
struct lsquic_conn_ctx {
|
||||
TAILQ_ENTRY(lsquic_conn_ctx) next_connh;
|
||||
lsquic_conn_t *conn;
|
||||
struct echo_server_ctx *server_ctx;
|
||||
};
|
||||
|
||||
|
||||
static lsquic_conn_ctx_t *
|
||||
echo_server_on_new_conn (void *stream_if_ctx, lsquic_conn_t *conn)
|
||||
{
|
||||
struct echo_server_ctx *server_ctx = stream_if_ctx;
|
||||
lsquic_conn_ctx_t *conn_h = calloc(1, sizeof(*conn_h));
|
||||
conn_h->conn = conn;
|
||||
conn_h->server_ctx = server_ctx;
|
||||
TAILQ_INSERT_TAIL(&server_ctx->conn_ctxs, conn_h, next_connh);
|
||||
LSQ_NOTICE("New connection!");
|
||||
print_conn_info(conn);
|
||||
return conn_h;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
echo_server_on_conn_closed (lsquic_conn_t *conn)
|
||||
{
|
||||
lsquic_conn_ctx_t *conn_h = lsquic_conn_get_ctx(conn);
|
||||
if (conn_h->server_ctx->n_conn)
|
||||
{
|
||||
--conn_h->server_ctx->n_conn;
|
||||
LSQ_NOTICE("Connection closed, remaining: %d", conn_h->server_ctx->n_conn);
|
||||
if (0 == conn_h->server_ctx->n_conn)
|
||||
prog_stop(conn_h->server_ctx->prog);
|
||||
}
|
||||
else
|
||||
LSQ_NOTICE("Connection closed");
|
||||
TAILQ_REMOVE(&conn_h->server_ctx->conn_ctxs, conn_h, next_connh);
|
||||
free(conn_h);
|
||||
}
|
||||
|
||||
|
||||
struct lsquic_stream_ctx {
|
||||
lsquic_stream_t *stream;
|
||||
struct echo_server_ctx *server_ctx;
|
||||
char buf[0x100];
|
||||
size_t buf_off;
|
||||
};
|
||||
|
||||
|
||||
static lsquic_stream_ctx_t *
|
||||
echo_server_on_new_stream (void *stream_if_ctx, lsquic_stream_t *stream)
|
||||
{
|
||||
lsquic_stream_ctx_t *st_h = malloc(sizeof(*st_h));
|
||||
st_h->stream = stream;
|
||||
st_h->server_ctx = stream_if_ctx;
|
||||
st_h->buf_off = 0;
|
||||
lsquic_stream_wantread(stream, 1);
|
||||
return st_h;
|
||||
}
|
||||
|
||||
|
||||
static struct lsquic_conn_ctx *
|
||||
find_conn_h (const struct echo_server_ctx *server_ctx, lsquic_stream_t *stream)
|
||||
{
|
||||
struct lsquic_conn_ctx *conn_h;
|
||||
lsquic_conn_t *conn;
|
||||
|
||||
conn = lsquic_stream_conn(stream);
|
||||
TAILQ_FOREACH(conn_h, &server_ctx->conn_ctxs, next_connh)
|
||||
if (conn_h->conn == conn)
|
||||
return conn_h;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
echo_server_on_read (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
|
||||
{
|
||||
struct lsquic_conn_ctx *conn_h;
|
||||
size_t nr;
|
||||
|
||||
nr = lsquic_stream_read(stream, st_h->buf + st_h->buf_off++, 1);
|
||||
if (0 == nr)
|
||||
{
|
||||
LSQ_NOTICE("EOF: closing connection");
|
||||
lsquic_stream_shutdown(stream, 2);
|
||||
conn_h = find_conn_h(st_h->server_ctx, stream);
|
||||
lsquic_conn_close(conn_h->conn);
|
||||
}
|
||||
else if ('\n' == st_h->buf[ st_h->buf_off - 1 ])
|
||||
{
|
||||
/* Found end of line: echo it back */
|
||||
lsquic_stream_wantwrite(stream, 1);
|
||||
lsquic_stream_wantread(stream, 0);
|
||||
}
|
||||
else if (st_h->buf_off == sizeof(st_h->buf))
|
||||
{
|
||||
/* Out of buffer space: line too long */
|
||||
LSQ_NOTICE("run out of buffer space");
|
||||
lsquic_stream_shutdown(stream, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Keep reading */;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
echo_server_on_write (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
|
||||
{
|
||||
lsquic_stream_write(stream, st_h->buf, st_h->buf_off);
|
||||
st_h->buf_off = 0;
|
||||
lsquic_stream_flush(stream);
|
||||
lsquic_stream_wantwrite(stream, 0);
|
||||
lsquic_stream_wantread(stream, 1);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
echo_server_on_stream_close (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
|
||||
{
|
||||
struct lsquic_conn_ctx *conn_h;
|
||||
LSQ_NOTICE("%s called", __func__);
|
||||
conn_h = find_conn_h(st_h->server_ctx, stream);
|
||||
LSQ_WARN("%s: TODO: free connection handler %p", __func__, conn_h);
|
||||
free(st_h);
|
||||
}
|
||||
|
||||
|
||||
const struct lsquic_stream_if server_echo_stream_if = {
|
||||
.on_new_conn = echo_server_on_new_conn,
|
||||
.on_conn_closed = echo_server_on_conn_closed,
|
||||
.on_new_stream = echo_server_on_new_stream,
|
||||
.on_read = echo_server_on_read,
|
||||
.on_write = echo_server_on_write,
|
||||
.on_close = echo_server_on_stream_close,
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
usage (const char *prog)
|
||||
{
|
||||
const char *const slash = strrchr(prog, '/');
|
||||
if (slash)
|
||||
prog = slash + 1;
|
||||
printf(
|
||||
"Usage: %s [opts]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
, prog);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int opt, s;
|
||||
struct prog prog;
|
||||
struct echo_server_ctx server_ctx;
|
||||
|
||||
memset(&server_ctx, 0, sizeof(server_ctx));
|
||||
server_ctx.prog = &prog;
|
||||
TAILQ_INIT(&server_ctx.sports);
|
||||
TAILQ_INIT(&server_ctx.conn_ctxs);
|
||||
|
||||
prog_init(&prog, LSENG_SERVER, &server_ctx.sports,
|
||||
&server_echo_stream_if, &server_ctx);
|
||||
|
||||
while (-1 != (opt = getopt(argc, argv, PROG_OPTS "hn:")))
|
||||
{
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
server_ctx.n_conn = atoi(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
prog_print_common_options(&prog, stdout);
|
||||
exit(0);
|
||||
default:
|
||||
if (0 != prog_set_opt(&prog, opt, optarg))
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != prog_prep(&prog))
|
||||
{
|
||||
LSQ_ERROR("could not prep");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
LSQ_DEBUG("entering event loop");
|
||||
|
||||
s = prog_run(&prog);
|
||||
prog_cleanup(&prog);
|
||||
|
||||
exit(0 == s ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue