aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Ghigonis <laurent@p1sec.com>2012-11-29 09:22:37 +0100
committerLaurent Ghigonis <laurent@p1sec.com>2012-11-29 09:22:37 +0100
commit386cb32df2308c2511085dd4f2a586457c5b4ad6 (patch)
tree13eace84e8dfc0175266a899a35649a425fc5d3a
parentadd a unittest for testing sending are receiving pkts (diff)
downloadglouglou-386cb32df2308c2511085dd4f2a586457c5b4ad6.tar.xz
glouglou-386cb32df2308c2511085dd4f2a586457c5b4ad6.zip
sending and receiving packets implemented and tested in unittest
-rw-r--r--libglouglou/libglouglou.c113
-rw-r--r--libglouglou/libglouglou.h22
-rw-r--r--libglouglou/tests/sendrecv.c14
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)