aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Ghigonis <laurent@p1sec.com>2012-11-29 07:42:17 +0100
committerLaurent Ghigonis <laurent@p1sec.com>2012-11-29 07:42:17 +0100
commit18274274dac64d3ef2174b0782b270bc485f3016 (patch)
tree32b3defd32c3eb40d50c6b3c55b4f0b8477b515f
parentfix error handling in "make run_loop (diff)
downloadglouglou-18274274dac64d3ef2174b0782b270bc485f3016.tar.xz
glouglou-18274274dac64d3ef2174b0782b270bc485f3016.zip
improve connection handling between server and client.
better API. skeletion for packet_decode()
-rw-r--r--libglouglou/libglouglou.c95
-rw-r--r--libglouglou/libglouglou.h16
-rw-r--r--libglouglou/tests/connect.c29
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);
}