aboutsummaryrefslogtreecommitdiffstats
path: root/libglouglou/libglouglou.c
diff options
context:
space:
mode:
Diffstat (limited to 'libglouglou/libglouglou.c')
-rw-r--r--libglouglou/libglouglou.c113
1 files changed, 101 insertions, 12 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) {