From 386cb32df2308c2511085dd4f2a586457c5b4ad6 Mon Sep 17 00:00:00 2001 From: Laurent Ghigonis Date: Thu, 29 Nov 2012 09:22:37 +0100 Subject: sending and receiving packets implemented and tested in unittest --- libglouglou/libglouglou.c | 113 ++++++++++++++++++++++++++++++++++++++----- libglouglou/libglouglou.h | 22 ++++++--- libglouglou/tests/sendrecv.c | 14 +++++- 3 files changed, 127 insertions(+), 22 deletions(-) diff --git a/libglouglou/libglouglou.c b/libglouglou/libglouglou.c index 24ba33e..41f2a8e 100644 --- a/libglouglou/libglouglou.c +++ b/libglouglou/libglouglou.c @@ -54,6 +54,7 @@ gg_server_start(struct event_base *ev_base, char *ip, int port, sock_addr.sin_family = AF_INET; sock_addr.sin_addr.s_addr = inet_addr(ip); sock_addr.sin_port = htons(port); + addrcpy(&srv->addr, &sock_addr); if (bind(s, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) @@ -73,9 +74,24 @@ err: } int -gg_server_send(struct gg_server *s, int client_id, struct gg_packet *p) +gg_server_send(struct gg_server *srv, struct gg_packet *pkt, int size, struct gg_user *usr) { - return -1; + struct gg_user *u; + + if (usr) { + if (sendto(srv->sock, pkt, size, 0, + (struct sockaddr *)&usr->addr, sizeof(struct sockaddr_in)) == -1) { + printf("gg_server_send failed: %s", strerror(errno)); + return -1; + } + } else { + LIST_FOREACH(u, &srv->user_list, entry) { + if (sendto(srv->sock, pkt, size, 0, + (struct sockaddr *)&u->addr, sizeof(struct sockaddr_in)) == -1) + printf("gg_server_send failed: %s", strerror(errno)); + } + } + return 0; } void @@ -124,17 +140,83 @@ user_add(struct gg_server *srv, struct sockaddr_in *remote) struct gg_packet * pkt_decode(char **buf, int *buf_len) { - char *p; + struct gg_packet *pkt, *newpkt = NULL; int len; + int packet_len; - p = *buf; len = *buf_len; - // XXX IN PROGRESS + if (len < PACKET_HEADER_SIZE) + goto incomplete; + if (len > PACKET_BUFFER_SIZE) + goto invalid; + pkt = (struct gg_packet *)*buf; + if (pkt->ver != PACKET_VERSION) + goto invalid; + if (pkt->type < PACKET_TYPE_MIN || pkt->type > PACKET_TYPE_MAX) + goto invalid; + + newpkt = xmalloc(sizeof(struct gg_packet)); + newpkt->ver = pkt->ver; + newpkt->type = pkt->type; + switch(pkt->type) { + case PACKET_NEWCONN: + packet_len = PACKET_NEWCONN_SIZE; + if (len < packet_len) + goto invalid; + newpkt->newconn_id = pkt->newconn_id; + newpkt->newconn_src = ntohl(pkt->newconn_src); + newpkt->newconn_dst = ntohl(pkt->newconn_dst); + newpkt->newconn_proto = pkt->newconn_proto; + newpkt->newconn_size = ntohs(pkt->newconn_size); + break; + case PACKET_DELCONN: + packet_len = PACKET_NEWCONN_SIZE; + if (len < packet_len) + goto invalid; + newpkt->delconn_id = pkt->delconn_id; + break; + case PACKET_DATA: + packet_len = PACKET_NEWCONN_SIZE; + if (len < packet_len) + goto invalid; + newpkt->data_connid = pkt->data_connid; + newpkt->data_size = ntohs(pkt->data_size); + break; + case PACKET_NAME: + packet_len = PACKET_NEWCONN_SIZE; + if (len < packet_len) + goto invalid; + if (len < packet_len + pkt->name_len) + goto invalid; + if (strnlen((char *)pkt->name_fqdn, len) != pkt->name_len) + goto invalid; + newpkt->name_addr = ntohl(pkt->name_addr); + newpkt->name_len = pkt->name_len; + strncpy((char *)newpkt->name_fqdn, (char *)pkt->name_fqdn, + pkt->name_len); + break; + goto invalid; + } - *buf = p; + *buf = *buf + packet_len; + *buf_len = len - packet_len; + return newpkt; + +incomplete: + printf("pkt_decode: incomplete packet\n"); + if (newpkt) + free(newpkt); *buf_len = len; return NULL; + +invalid: + printf("pkt_decode: invalid packet\n"); + if (newpkt) + free(newpkt); + *buf = NULL; + *buf_len = 0; + return NULL; } void cb_srv_receive(evutil_socket_t fd, short what, void *arg) @@ -144,7 +226,7 @@ void cb_srv_receive(evutil_socket_t fd, short what, void *arg) struct gg_packet *pkt; struct sockaddr_in remote; socklen_t remote_len; - char buf[16384]; + char buf[PACKET_BUFFER_SIZE]; char *buf_p; int buf_len; int len; @@ -170,7 +252,7 @@ void cb_srv_receive(evutil_socket_t fd, short what, void *arg) printf("srv: Incoming data from existing user !\n"); buf_p = buf; buf_len = len; - while ((pkt = pkt_decode(&buf_p, &buf_len))) + while (buf_len > 0 && (pkt = pkt_decode(&buf_p, &buf_len))) if (srv->handle_packet) srv->handle_packet(srv, usr, pkt); if (buf_len > 0) { @@ -215,6 +297,7 @@ gg_client_connect(struct event_base *ev_base, char *ip, int port, sock_addr.sin_family = AF_INET; sock_addr.sin_addr.s_addr=inet_addr(ip); sock_addr.sin_port=htons(port); + addrcpy(&cli->addr, &sock_addr); ev = event_new(ev_base, s, EV_READ|EV_PERSIST, cb_cli_receive, cli); event_add(ev, NULL); @@ -234,9 +317,14 @@ err: } int -gg_client_send(struct gg_client *c, struct gg_packet *p) +gg_client_send(struct gg_client *cli, struct gg_packet *pkt, int size) { - return -1; + if (sendto(cli->sock, pkt, size, 0, + (struct sockaddr *)&cli->addr, sizeof(struct sockaddr_in)) == -1) { + printf("gg_client_send failed: %s", strerror(errno)); + return -1; + } + return 0; } void @@ -259,12 +347,13 @@ void cb_cli_receive(evutil_socket_t fd, short what, void *arg) struct gg_packet *pkt; struct sockaddr_in remote; socklen_t remote_len; - char buf[16384]; + char buf[PACKET_BUFFER_SIZE]; char *buf_p; int buf_len; int len; cli = arg; + remote_len = sizeof(struct sockaddr_in); len = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&remote, &remote_len); if (len < 0) { @@ -283,7 +372,7 @@ void cb_cli_receive(evutil_socket_t fd, short what, void *arg) printf("cli: Incoming data !\n"); buf_p = buf; buf_len = len; - while ((pkt = pkt_decode(&buf_p, &buf_len))) + while (buf_len > 0 && (pkt = pkt_decode(&buf_p, &buf_len))) if (cli->handle_packet) cli->handle_packet(cli, pkt); if (buf_len > 0) { diff --git a/libglouglou/libglouglou.h b/libglouglou/libglouglou.h index aa602da..418e565 100644 --- a/libglouglou/libglouglou.h +++ b/libglouglou/libglouglou.h @@ -2,20 +2,24 @@ #include "contrib/queue.h" #define PACKET_VERSION 1 +#define PACKET_BUFFER_SIZE 16384 #define DNSNAME_MAX 20 struct gg_packet { +#define PACKET_HEADER_SIZE 2 u_int8_t ver; u_int8_t type; /* XXX nicer way for _SIZE ... ? */ +#define PACKET_TYPE_MIN 0 +#define PACKET_TYPE_MAX 3 #define PACKET_NEWCONN 0 -#define PACKET_NEWCONN_SIZE (2 + sizeof((struct packet *)0)->pdat.newconn) +#define PACKET_NEWCONN_SIZE (PACKET_HEADER_SIZE + sizeof((struct gg_packet *)0)->pdat.newconn) #define PACKET_DELCONN 1 -#define PACKET_DELCONN_SIZE (2 + sizeof((struct packet *)0)->pdat.delconn) +#define PACKET_DELCONN_SIZE (PACKET_HEADER_SIZE + sizeof((struct gg_packet *)0)->pdat.delconn) #define PACKET_DATA 2 -#define PACKET_DATA_SIZE (2 + sizeof((struct packet *)0)->pdat.data) +#define PACKET_DATA_SIZE (PACKET_HEADER_SIZE + sizeof((struct gg_packet *)0)->pdat.data) #define PACKET_NAME 3 -#define PACKET_NAME_SIZE ((2 + sizeof((struct packet *)0)->pdat.name) - DNSNAME_MAX) +#define PACKET_NAME_SIZE ((PACKET_HEADER_SIZE + sizeof((struct gg_packet *)0)->pdat.name) - DNSNAME_MAX) union { struct newconn { @@ -61,6 +65,7 @@ struct gg_user { struct gg_server { const char *ip; int port; + struct sockaddr_in addr; struct event *ev; int sock; int (*handle_conn)(struct gg_server *, struct gg_user *); @@ -72,11 +77,12 @@ struct gg_server { struct gg_client { const char *ip; int port; + struct sockaddr_in addr; + struct event *ev; + int sock; int status; #define GG_CLIENT_STATUS_DISCONNECTED 0 #define GG_CLIENT_STATUS_CONNECTED 1 - struct event *ev; - int sock; int (*handle_conn)(struct gg_client *); int (*handle_packet)(struct gg_client *, struct gg_packet *); }; @@ -85,13 +91,13 @@ struct gg_client { struct gg_server *gg_server_start(struct event_base *, char *, int, int (*handle_conn)(struct gg_server *, struct gg_user *), int (*handle_packet)(struct gg_server *, struct gg_user *, struct gg_packet *)); -int gg_server_send(struct gg_server *, int, struct gg_packet *); +int gg_server_send(struct gg_server *, struct gg_packet *, int, struct gg_user *); void gg_server_stop(struct gg_server *); struct gg_client *gg_client_connect(struct event_base *, char *, int, int (*handle_conn)(struct gg_client *), int (*handle_packet)(struct gg_client *, struct gg_packet *)); -int gg_client_send(struct gg_client *, struct gg_packet *); +int gg_client_send(struct gg_client *, struct gg_packet *, int); void gg_client_disconnect(struct gg_client *); void *xmalloc(size_t); diff --git a/libglouglou/tests/sendrecv.c b/libglouglou/tests/sendrecv.c index f4702e8..0127cb4 100644 --- a/libglouglou/tests/sendrecv.c +++ b/libglouglou/tests/sendrecv.c @@ -8,7 +8,7 @@ int cli_recv_ok = 0; int srv_handle_packet(struct gg_server *srv, struct gg_user *usr, struct gg_packet *pkt) { - if (usr->id == 1) + if (pkt->type == PACKET_NEWCONN) srv_recv_ok = 1; return 0; } @@ -16,7 +16,8 @@ srv_handle_packet(struct gg_server *srv, struct gg_user *usr, struct gg_packet * int cli_handle_packet(struct gg_client *cli, struct gg_packet *pkt) { - cli_recv_ok = 1; + if (pkt->type == PACKET_NEWCONN) + cli_recv_ok = 1; return 0; } @@ -42,6 +43,15 @@ main(void) event_base_loop(ev_base, EVLOOP_ONCE); event_base_loop(ev_base, EVLOOP_ONCE); + pkt.ver = PACKET_VERSION; + pkt.type = PACKET_NEWCONN; + + gg_server_send(srv, &pkt, PACKET_NEWCONN_SIZE, NULL); + event_base_loop(ev_base, EVLOOP_ONCE); + + gg_client_send(cli, &pkt, PACKET_NEWCONN_SIZE); + event_base_loop(ev_base, EVLOOP_ONCE); + if (srv_recv_ok == 0) printf("error: srv_recv_ok == 0\n"); if (cli_recv_ok == 0) -- cgit v1.2.3-59-g8ed1b