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 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 101 insertions(+), 12 deletions(-) (limited to 'libglouglou/libglouglou.c') 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) { -- cgit v1.2.3-59-g8ed1b