aos/usr/echoserver/main.c
2022-06-02 21:25:20 +02:00

171 lines
5.0 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <aos/aos.h>
#include <aos/simpleslab.h>
#include <aos/deferred.h>
#include <aos/ump_net.h>
#include <aos/ump_net_client.h>
// Echo Protocol: https://datatracker.ietf.org/doc/html/rfc862
#define PORT_ECHO 7
static uint16_t listen_port = PORT_ECHO;
// UDP echo server
#define BUF_SIZE 1500
struct echo_buf {
uint32_t src_ip;
uint16_t src_port;
struct ump_net_call call;
uint8_t payload[BUF_SIZE];
};
static struct simpleslab_allocator slabs;
static uint8_t slab_buf[sizeof(struct echo_buf) * 128];
static void udp_listen_callback (void *arg, errval_t err, uint16_t src_port) {
if (err_is_fail(err)) {
printf("Failed to listen on UDP port %d:\n", listen_port);
err_print_calltrace(err);
return;
}
DEBUG_PRINTF("Listening on UDP port %d.\n", src_port);
}
static void net_reply_callback (void *arg, errval_t err) {
struct echo_buf *echo_buf = arg;
simpleslab_free(&slabs, echo_buf);
if (err_is_fail(err)) {
DEBUG_ERR(err, "failed to send packet");
}
}
static struct ump_net_ev_udp_recv net_udp_recv;
static void net_recv_packet (void *arg, size_t payload_size, void *payload) {
struct echo_buf *echo_buf = arg;
//printf("Echo server: Received payload: '%.*s'\n", payload_size, &echo_buf->payload);
// Send reply
ump_net_udp_send(
&echo_buf->call,
net_udp_recv.src_ip,
listen_port, net_udp_recv.src_port,
payload_size, &echo_buf->payload,
net_reply_callback, echo_buf
);
}
static void handle_udp_recv (void *arg, struct ump_net_ev_udp_recv *udp_recv, size_t payload_size) {
if (payload_size > BUF_SIZE) {
printf("Echo server: ERROR: Packet too big\n");
} else {
struct echo_buf *echo_buf = simpleslab_alloc(&slabs);
if (echo_buf == NULL) {
printf("Echo server: WARN: All buffers full, dropping packet\n");
} else {
net_udp_recv = *udp_recv;
ump_net_recv_payload(&echo_buf->payload, net_recv_packet, echo_buf);
return;
}
}
ump_net_recv_payload(NULL, NULL, NULL);
}
// TCP echo server
#define TCP_MAX_CONNECTIONS 100
struct tcp_conn {
struct tcp_tcb tcb;
uint8_t rcv_buf[4*4096];
uint8_t snd_buf[4*4096];
};
static int tcp_connection_count = 0;
static void tcp_listen_callback (void *arg, errval_t err, uint16_t src_port) {
if (err_is_fail(err)) {
printf("Failed to listen on TCP port %d:\n", listen_port);
err_print_calltrace(err);
return;
}
DEBUG_PRINTF("Listening on TCP port %d.\n", src_port);
}
static void tcp_receive_available_handler (void *arg) {
struct tcp_conn *conn = arg;
uint8_t buf[2048];
while (true) {
uint32_t read_size = ump_net_tcp_receive(&conn->tcb, buf, sizeof(buf));
if (read_size == 0) break;
debug_printf("TCP received: '%.*s'\n", read_size, buf);
}
}
static void tcp_send_available_handler (void *arg) {
// struct tcp_conn *conn = arg;
debug_printf("tcp_send_available_handler\n");
}
static void tcp_destroy_handler (void *arg) {
struct tcp_conn *conn = arg;
debug_printf("TCP connection destroyed for %x, port %d\n", conn->tcb.remote_ip, conn->tcb.remote_port);
free(conn);
tcp_connection_count--;
}
static void handle_tcp_connect (
void *arg, struct ump_net_ev_tcp_recv *tcp_recv,
uint32_t remote_ip, uint16_t remote_port, uint16_t local_port
) {
debug_printf("Received connection attempt from %x, port %d\n", remote_ip, remote_port);
if (tcp_connection_count > TCP_MAX_CONNECTIONS) {
ump_net_tcp_refuse(tcp_recv);
} else {
struct tcp_conn *conn = malloc(sizeof(struct tcp_conn));
if (conn == NULL) {
ump_net_tcp_refuse(tcp_recv);
} else {
tcp_connection_count++;
ump_net_tcp_accept(
tcp_recv, &conn->tcb,
tcp_receive_available_handler,
tcp_send_available_handler,
tcp_destroy_handler,
conn,
conn->rcv_buf, sizeof(conn->rcv_buf),
conn->snd_buf, sizeof(conn->snd_buf)
);
}
}
}
int main (int argc, char *argv[]) {
errval_t err;
struct waitset *default_ws = get_default_waitset();
if (argc >= 2) {
listen_port = strtol(argv[1], NULL, 10);
}
simpleslab_init(&slabs, sizeof(struct echo_buf), slab_buf, sizeof(slab_buf));
err = ump_net_init(default_ws);
if (err_is_fail(err)) USER_PANIC_ERR(err, "Failed to connect to net server");
struct ump_net_call call_udp_listen;
ump_net_udp_listen(&call_udp_listen, listen_port, handle_udp_recv, NULL, udp_listen_callback, NULL);
struct ump_net_call call_tcp_listen;
ump_net_tcp_listen(&call_tcp_listen, listen_port, handle_tcp_connect, NULL, tcp_listen_callback, NULL);
while (true) {
err = event_dispatch(default_ws);
if (err_is_fail(err)) {
DEBUG_ERR(err, "in event_dispatch");
abort();
}
}
}