aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libglouglou/libglouglou.c23
-rw-r--r--libglouglou/libglouglou.h1
-rw-r--r--libglouglou/sendbuf.c117
-rw-r--r--libglouglou/sendbuf.h21
4 files changed, 161 insertions, 1 deletions
diff --git a/libglouglou/libglouglou.c b/libglouglou/libglouglou.c
index c2c284a..c9c0df8 100644
--- a/libglouglou/libglouglou.c
+++ b/libglouglou/libglouglou.c
@@ -13,6 +13,7 @@
#include <signal.h>
#include "libglouglou.h"
+#include "sendbuf.h"
#define error(fmt, ...) \
if (_verbosity >= 0) \
@@ -58,6 +59,7 @@ gg_server_start(struct event_base *ev_base, char *ip, int port,
struct gg_server *srv;
struct sockaddr_in sock_addr;
struct event *ev;
+ struct sendbuf *sbuf;
int s;
int sock_on = 1;
@@ -68,6 +70,13 @@ gg_server_start(struct event_base *ev_base, char *ip, int port,
srv->handle_conn = handle_conn;
srv->handle_packet = handle_packet;
srv->usrdata = usrdata;
+
+ sbuf = sendbuf_init(ev_base, PACKET_SNDBUF_MAX * 2, PACKET_SNDBUF_MAX, 200,
+ cb_srv_send, srv);
+ if (!sbuf)
+ goto err;
+ srv->sbuf = sbuf;
+
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0)
goto err;
@@ -99,12 +108,24 @@ err:
}
int
+cb_srv_send(void *data, int size, void *usrdata)
+{
+ struct gg_server *srv;
+
+ srv = usrdata;
+}
+
+int
gg_server_send(struct gg_server *srv, struct gg_packet *pkt, struct gg_user *usr)
{
static struct gg_packet *newpkt;
int size;
- newpkt = pkt_encode(pkt, &size);
+ // XXX IN PROGRESS get size before
+ newpkt = sendbuf_gettoken(srv->sndbuf, size);
+
+ pkt_encode(pkt, &size, newpkt);
+
if (!newpkt)
return -1;
return server_send(srv, usr, newpkt, size);
diff --git a/libglouglou/libglouglou.h b/libglouglou/libglouglou.h
index 8ee890f..63fa93a 100644
--- a/libglouglou/libglouglou.h
+++ b/libglouglou/libglouglou.h
@@ -12,6 +12,7 @@
#define PACKET_VERSION 1
#define PACKET_BUFFER_SIZE 16384
+#define PACKET_SNDBUF_MAX 500
#define GG_PKTARG_MAX 30
#define PACKET_HEADER_SIZE 2
diff --git a/libglouglou/sendbuf.c b/libglouglou/sendbuf.c
new file mode 100644
index 0000000..078d6a6
--- /dev/null
+++ b/libglouglou/sendbuf.c
@@ -0,0 +1,117 @@
+#include "sendbuf.h"
+
+/*
+ * Public
+ */
+
+/*
+ * Create a sendbuf
+ * send_func should return the number of successfuly sent bytes
+ */
+struct sendbuf *
+sendbuf_init(struct event_base *ev_base, int size, int sndbuf_max, int msec_max,
+ int (*send_func)(void *, int, void *), void *usrdata)
+{
+ struct sendbuf *sbuf = NULL;
+ struct event ev_timer;
+ struct timeval *tv;
+ void *buffer;
+ void *data;
+
+ sbuf = calloc(1, sizeof(struct sendbuf));
+ if (!sbuf)
+ return NULL;
+ sbuf->ev_base = ev_base;
+ sbuf->sndbuf_max = sndbuf_max;
+ sbuf->msec_max = msec_max;
+ sbuf->usrdata = usrdata;
+ sbuf->send_func = send_func;
+ sbuf->buffer_size = size;
+ sbuf->buffer = malloc(sbuf->buffer_size);
+ if (!sbuf->buffer)
+ goto err;
+
+ ev_timer = evtimer_new(ev_base, cb_timer, sbuf);
+ sbuf->ev_timer = ev_timer;
+ sbuf->ev_timer_tv.tv_usec = msec_max * 1000;
+ evtimer_add(ev, &sbuf->ev_timer_tv);
+
+ return sbuf;
+
+err:
+ sendbuf_shutdown(sbuf);
+ return NULL;
+}
+
+void
+sendbuf_shutdown(struct sendbuf *sbuf)
+{
+ if (sbuf->send_timer)
+ event_del(sbuf->send_timer);
+ if (sbuf->buffer && sbuf->send_func)
+ flushbuf(sbuf);
+ if (sbuf->buffer)
+ free(sbuf->buffer);
+ free(sbuf);
+}
+
+/*
+ * Returns a buffer to write data to be sent
+ * might return NULL if the sendbuf is temporary full
+ */
+void *
+sendbuf_getoken(struct sendbuf *sbuf, int size)
+{
+ if (sbuf->buffer_pos + size >= sbuf->buffer_size)
+ if (flushbuf(sbuf) == -1)
+ return NULL;
+
+ return sbuf->buffer_pos;
+}
+
+/*
+ * Private
+ */
+
+/*
+ * Note that you can still add data to the buffer even if flushing is in
+ * progress
+ */
+int
+flushbuf(struct sendbuf *sbuf)
+{
+ int sent;
+ int sent_total;
+ int len;
+
+ sbuf->flushing = 1;
+
+ do {
+ pos = sbuf->buffer + sbuf->flushed_len;
+ if (sbuf->buffer_pos > sbuf->sndbuf_max)
+ tosend = sbuf->sndbuf_max;
+ else
+ tosend = sbuf->buffer_pos;
+ sent = sbuf->send_func(sbuf->buffer + pos, tosend, sbuf->usrdata);
+ sbuf->flushed_len = sbuf->flushed_len + sent;
+ if (sent == -1) {
+ // XXX handle erorr
+ } else if (sent < tosend) {
+ return -1;
+ }
+ } while (sbuf->flushed_len < sbuf->buffer_pos)
+
+ sbuf->flushing = 0;
+ sbuf->flushed_len = 0;
+ return 0;
+}
+
+void
+cb_timer(evutil_socket_t fd, short what, void *arg)
+{
+ struct sendbuf *sbuf;
+
+ sbuf = arg;
+ flushbuf(sbuf);
+ evtimer_add(sbuf->ev_timer, &sbuf->ev_timer_tv);
+}
diff --git a/libglouglou/sendbuf.h b/libglouglou/sendbuf.h
new file mode 100644
index 0000000..90dc4bc
--- /dev/null
+++ b/libglouglou/sendbuf.h
@@ -0,0 +1,21 @@
+#include <event.h>
+
+struct sendbuf {
+ struct event_base *ev_base;
+ struct event *ev_timer;
+ struct timeval ev_timer_tv;
+ int sndbuf_max;
+ int msec_max;
+ int (*send_func)(void *, int, void *);
+ void *usrdata;
+ void *buffer;
+ int buffer_size;
+ int buffer_pos;
+ int flushing;
+ int flushed_len;
+};
+
+struct sendbuf *sendbuf_init(struct event_base *, int, int,
+ int (*send_func)(void *, int, void *), void *);
+void sendbuf_shutdown(struct sendbuf *);
+void *sendbuf_gettoken(struct sendbuf *, int);