diff options
author | Laurent Ghigonis <laurent@p1sec.com> | 2012-11-29 07:42:17 +0100 |
---|---|---|
committer | Laurent Ghigonis <laurent@p1sec.com> | 2012-11-29 07:42:17 +0100 |
commit | 18274274dac64d3ef2174b0782b270bc485f3016 (patch) | |
tree | 32b3defd32c3eb40d50c6b3c55b4f0b8477b515f /libglouglou | |
parent | fix error handling in "make run_loop (diff) | |
download | glouglou-18274274dac64d3ef2174b0782b270bc485f3016.tar.xz glouglou-18274274dac64d3ef2174b0782b270bc485f3016.zip |
improve connection handling between server and client.
better API.
skeletion for packet_decode()
Diffstat (limited to 'libglouglou')
-rw-r--r-- | libglouglou/libglouglou.c | 95 | ||||
-rw-r--r-- | libglouglou/libglouglou.h | 16 | ||||
-rw-r--r-- | libglouglou/tests/connect.c | 29 |
3 files changed, 111 insertions, 29 deletions
diff --git a/libglouglou/libglouglou.c b/libglouglou/libglouglou.c index a0b85ee..24ba33e 100644 --- a/libglouglou/libglouglou.c +++ b/libglouglou/libglouglou.c @@ -28,8 +28,8 @@ void cb_cli_receive(evutil_socket_t, short, void *); */ struct gg_server * gg_server_start(struct event_base *ev_base, char *ip, int port, - int (*handle_conn)(struct gg_server *, int, struct sockaddr_in *), - int (*handle_packet)(struct gg_server *, struct gg_packet *)) + int (*handle_conn)(struct gg_server *, struct gg_user *), + int (*handle_packet)(struct gg_server *, struct gg_user *, struct gg_packet *)) { struct gg_server *srv; struct sockaddr_in sock_addr; @@ -121,19 +121,39 @@ user_add(struct gg_server *srv, struct sockaddr_in *remote) return usr; } +struct gg_packet * +pkt_decode(char **buf, int *buf_len) +{ + char *p; + int len; + + p = *buf; + len = *buf_len; + + // XXX IN PROGRESS + + *buf = p; + *buf_len = len; + return NULL; +} + void cb_srv_receive(evutil_socket_t fd, short what, void *arg) { struct gg_server *srv; struct gg_user *usr; + struct gg_packet *pkt; struct sockaddr_in remote; + socklen_t remote_len; char buf[16384]; - socklen_t len; - int rv; + char *buf_p; + int buf_len; + int len; srv = arg; - rv = recvfrom(fd, buf, sizeof(buf), 0, - (struct sockaddr *)&remote, &len); - if (rv < 0) { + remote_len = sizeof(struct sockaddr_in); + len = recvfrom(fd, buf, sizeof(buf), 0, + (struct sockaddr *)&remote, &remote_len); + if (len < 0) { printf("libglouglou: cb_srv_receive: recvfrom failed\n"); return; } @@ -141,10 +161,22 @@ void cb_srv_receive(evutil_socket_t fd, short what, void *arg) if (!usr) { usr = user_add(srv, &remote); if (srv->handle_conn) - srv->handle_conn(srv, usr->id, &remote); + srv->handle_conn(srv, usr); printf("srv: New user %d !\n", usr->id); + if (sendto(srv->sock, "", strlen(""), 0, + (struct sockaddr *)&remote, remote_len) == -1) + printf("srv: send failed: %s\n", strerror(errno)); } else { - printf("srv: Incoming data for existing user !\n"); + printf("srv: Incoming data from existing user !\n"); + buf_p = buf; + buf_len = len; + while ((pkt = pkt_decode(&buf_p, &buf_len))) + if (srv->handle_packet) + srv->handle_packet(srv, usr, pkt); + if (buf_len > 0) { + /* XXX store incomplete packet for next recv */ + printf("srv: incomplete packet, dropped %d bytes !\n", buf_len); + } } } @@ -157,7 +189,7 @@ void cb_srv_receive(evutil_socket_t fd, short what, void *arg) */ struct gg_client * gg_client_connect(struct event_base *ev_base, char *ip, int port, - int (*handle_conn)(struct gg_client *, int), + int (*handle_conn)(struct gg_client *), int (*handle_packet)(struct gg_client *, struct gg_packet *)) { struct gg_client *cli; @@ -188,8 +220,9 @@ gg_client_connect(struct event_base *ev_base, char *ip, int port, event_add(ev, NULL); cli->ev = ev; - sendto(s, "", strlen(""), 0, - (struct sockaddr *)&sock_addr, sizeof(struct sockaddr)); + if (sendto(s, "", strlen(""), 0, + (struct sockaddr *)&sock_addr, sizeof(struct sockaddr_in)) == -1) + printf("cli: send failed: %s\n", strerror(errno)); return cli; @@ -222,7 +255,43 @@ gg_client_disconnect(struct gg_client *cli) void cb_cli_receive(evutil_socket_t fd, short what, void *arg) { - printf("cli: Incoming data !\n"); + struct gg_client *cli; + struct gg_packet *pkt; + struct sockaddr_in remote; + socklen_t remote_len; + char buf[16384]; + char *buf_p; + int buf_len; + int len; + + cli = arg; + len = recvfrom(fd, buf, sizeof(buf), 0, + (struct sockaddr *)&remote, &remote_len); + if (len < 0) { + printf("libglouglou: cb_cli_receive: recvfrom failed\n"); + return; + } + + switch (cli->status) { + case GG_CLIENT_STATUS_DISCONNECTED: + printf("cli: Connected !\n"); + cli->status = GG_CLIENT_STATUS_CONNECTED; + if (cli->handle_conn) + cli->handle_conn(cli); + break; + case GG_CLIENT_STATUS_CONNECTED: + printf("cli: Incoming data !\n"); + buf_p = buf; + buf_len = len; + while ((pkt = pkt_decode(&buf_p, &buf_len))) + if (cli->handle_packet) + cli->handle_packet(cli, pkt); + if (buf_len > 0) { + /* XXX store incomplete packet for next recv */ + printf("cli: incomplete packet, dropped %d bytes !\n", buf_len); + } + break; + } } /* diff --git a/libglouglou/libglouglou.h b/libglouglou/libglouglou.h index 03ed2f1..aa602da 100644 --- a/libglouglou/libglouglou.h +++ b/libglouglou/libglouglou.h @@ -55,6 +55,7 @@ struct gg_user { LIST_ENTRY(gg_user) entry; int id; struct sockaddr_in addr; + char *buf[16384]; }; struct gg_server { @@ -62,8 +63,8 @@ struct gg_server { int port; struct event *ev; int sock; - int (*handle_conn)(struct gg_server *, int, struct sockaddr_in *); - int (*handle_packet)(struct gg_server *, struct gg_packet *); + int (*handle_conn)(struct gg_server *, struct gg_user *); + int (*handle_packet)(struct gg_server *, struct gg_user *, struct gg_packet *); LIST_HEAD(, gg_user) user_list; int user_id_count; }; @@ -71,21 +72,24 @@ struct gg_server { struct gg_client { const char *ip; int port; + 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); + int (*handle_conn)(struct gg_client *); int (*handle_packet)(struct gg_client *, struct gg_packet *); }; struct gg_server *gg_server_start(struct event_base *, char *, int, - int (*handle_conn)(struct gg_server *, int, struct sockaddr_in *), - int (*handle_packet)(struct gg_server *, struct gg_packet *)); + 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 *); 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), + 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 *); void gg_client_disconnect(struct gg_client *); diff --git a/libglouglou/tests/connect.c b/libglouglou/tests/connect.c index 8184e2d..b8f4d1f 100644 --- a/libglouglou/tests/connect.c +++ b/libglouglou/tests/connect.c @@ -2,12 +2,20 @@ #include "../libglouglou.h" -int connect_ok = 0; +int srv_connect_ok = 0; +int cli_connect_ok = 0; int -handle_conn(struct gg_server *srv, int client_id, struct sockaddr_in *addr) +srv_handle_conn(struct gg_server *srv, struct gg_user *usr, struct sockaddr_in *addr) { - connect_ok = 1; + srv_connect_ok = 1; + return 0; +} + +int +cli_handle_conn(struct gg_client *cli) +{ + cli_connect_ok = 1; return 0; } @@ -17,20 +25,21 @@ main(void) struct event_base *ev_base; ev_base = event_base_new(); - if (!gg_server_start(ev_base, "127.0.0.1", 12345, handle_conn, NULL)) { + if (!gg_server_start(ev_base, "127.0.0.1", 12345, srv_handle_conn, NULL)) { printf("error: gg_server_start returned NULL\n"); return 1; } - if (!gg_client_connect(ev_base, "127.0.0.1", 12345, NULL, NULL)) { + if (!gg_client_connect(ev_base, "127.0.0.1", 12345, cli_handle_conn, NULL)) { printf("error: gg_client_connect returned NULL\n"); return 1; } event_base_loop(ev_base, EVLOOP_ONCE); + event_base_loop(ev_base, EVLOOP_ONCE); - if (connect_ok == 0) { - printf("error: connect_ok == 0\n"); - return 1; - } + if (srv_connect_ok == 0) + printf("error: srv_connect_ok == 0\n"); + if (cli_connect_ok == 0) + printf("error: cli_connect_ok == 0\n"); - return 0; + return (!srv_connect_ok || !cli_connect_ok); } |