From 4368d8c9956242f0bdc00d43ebf32a72332522c1 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 16 Aug 2014 18:31:06 +0200 Subject: [PATCH] Add socket option functions names similar to setsockopt()/ioctl() ones. --- test.c | 2 +- utcp.c | 79 +++++++++++++++++++++++++++++++++++++++-------------- utcp.h | 24 ++++++++++++++-- utcp_priv.h | 7 +++++ 4 files changed, 88 insertions(+), 24 deletions(-) diff --git a/test.c b/test.c index cda5f17..38240db 100644 --- a/test.c +++ b/test.c @@ -86,7 +86,7 @@ int main(int argc, char *argv[]) { if(!u) return 1; - utcp_set_connection_timeout(u, 10); + utcp_set_user_timeout(u, 10); if(!server) c = utcp_connect(u, 1, do_recv, NULL); diff --git a/utcp.c b/utcp.c index 966295a..97c4363 100644 --- a/utcp.c +++ b/utcp.c @@ -73,6 +73,10 @@ static inline void list_connections(struct utcp *utcp) { fprintf(stderr, " %u -> %u state %s\n", utcp->connections[i]->src, utcp->connections[i]->dst, strstate[utcp->connections[i]->state]); } +static int32_t seqdiff(uint32_t a, uint32_t b) { + return a - b; +} + // Connections are stored in a sorted list. // This gives O(log(N)) lookup time, O(N log(N)) insertion time and O(N) deletion time. @@ -138,16 +142,20 @@ static struct utcp_connection *allocate_connection(struct utcp *utcp, uint16_t s else utcp->nallocated *= 2; struct utcp_connection **new_array = realloc(utcp->connections, utcp->nallocated * sizeof *utcp->connections); - if(!new_array) { - errno = ENOMEM; + if(!new_array) return NULL; - } utcp->connections = new_array; } struct utcp_connection *c = calloc(1, sizeof *c); - if(!c) { - errno = ENOMEM; + if(!c) + return NULL; + + c->sndbufsize = DEFAULT_SNDBUFSIZE; + c->maxsndbufsize = DEFAULT_MAXSNDBUFSIZE; + c->sndbuf = malloc(c->sndbufsize); + if(!c->sndbuf) { + free(c); return NULL; } @@ -160,10 +168,6 @@ static struct utcp_connection *allocate_connection(struct utcp *utcp, uint16_t s c->snd.nxt = c->snd.iss + 1; c->rcv.wnd = utcp->mtu; c->utcp = utcp; - c->sndbufsize = 65536; - c->sndbuf = malloc(c->sndbufsize); - if(!c->sndbuf) - c->sndbufsize = 0; // Add it to the sorted list of connections @@ -250,16 +254,19 @@ ssize_t utcp_send(struct utcp_connection *c, const void *data, size_t len) { return -1; } - uint32_t bufused = c->snd.nxt - c->snd.una; + uint32_t bufused = seqdiff(c->snd.nxt, c->snd.una); /* Check our send buffer. * - If it's big enough, just put the data in there. - * - If not, decide whether to enlarge. (TODO, now we just always enlarge) + * - If not, decide whether to enlarge if possible. * - Cap len so it doesn't overflow our buffer. */ - if(len > c->sndbufsize - bufused) { - c->sndbufsize *= 2; + if(len > c->sndbufsize - bufused && c->sndbufsize < c->maxsndbufsize) { + if(c->sndbufsize > c->maxsndbufsize / 2) + c->sndbufsize = c->maxsndbufsize; + else + c->sndbufsize *= 2; c->sndbuf = realloc(c->sndbuf, c->sndbufsize); } @@ -312,10 +319,6 @@ static void swap_ports(struct hdr *hdr) { hdr->dst = tmp; } -static int32_t seqdiff(uint32_t a, uint32_t b) { - return a - b; -} - int utcp_recv(struct utcp *utcp, const void *data, size_t len) { if(!utcp) { errno = EFAULT; @@ -970,13 +973,49 @@ void utcp_exit(struct utcp *utcp) { free(utcp); } +uint16_t utcp_get_mtu(struct utcp *utcp) { + return utcp->mtu; +} + void utcp_set_mtu(struct utcp *utcp, uint16_t mtu) { // TODO: handle overhead of the header utcp->mtu = mtu; } -int utcp_set_connection_timeout(struct utcp *u, int timeout) { - int prev = u->timeout; +int utcp_get_user_timeout(struct utcp *u) { + return u->timeout; +} + +void utcp_set_user_timeout(struct utcp *u, int timeout) { u->timeout = timeout; - return prev; +} + +size_t utcp_get_sndbuf(struct utcp_connection *c) { + return c->maxsndbufsize; +} + +void utcp_set_sndbuf(struct utcp_connection *c, size_t size) { + c->maxsndbufsize = size; + if(c->maxsndbufsize != size) + c->maxsndbufsize = -1; +} + +bool utcp_get_nodelay(struct utcp_connection *c) { + return c->nodelay; +} + +void utcp_set_nodelay(struct utcp_connection *c, bool nodelay) { + c->nodelay = nodelay; +} + +bool utcp_get_keepalive(struct utcp_connection *c) { + return c->keepalive; +} + +void utcp_set_keepalive(struct utcp_connection *c, bool keepalive) { + c->keepalive = keepalive; +} + +size_t utcp_get_outq(struct utcp_connection *c) { + return seqdiff(c->snd.nxt, c->snd.una); } diff --git a/utcp.h b/utcp.h index b189a24..707cabe 100644 --- a/utcp.h +++ b/utcp.h @@ -47,8 +47,6 @@ typedef int (*utcp_recv_t)(struct utcp_connection *connection, const void *data, extern struct utcp *utcp_init(utcp_accept_t accept, utcp_pre_accept_t pre_accept, utcp_send_t send, void *priv); extern void utcp_exit(struct utcp *utcp); -extern void utcp_set_mtu(struct utcp *utcp, uint16_t mtu); - extern struct utcp_connection *utcp_connect(struct utcp *utcp, uint16_t port, utcp_recv_t recv, void *priv); extern void utcp_accept(struct utcp_connection *utcp, utcp_recv_t recv, void *priv); extern ssize_t utcp_send(struct utcp_connection *connection, const void *data, size_t len); @@ -57,6 +55,26 @@ extern int utcp_close(struct utcp_connection *connection); extern int utcp_abort(struct utcp_connection *connection); extern int utcp_shutdown(struct utcp_connection *connection, int how); extern int utcp_timeout(struct utcp *utcp); -extern int utcp_set_connection_timeout(struct utcp *utcp, int seconds); + +// Global socket options + +extern int utcp_get_user_timeout(struct utcp *utcp); +extern void utcp_set_user_timeout(struct utcp *utcp, int seconds); + +extern uint16_t utcp_get_mtu(struct utcp *utcp); +extern void utcp_set_mtu(struct utcp *utcp, uint16_t mtu); + +// Per-socket options + +extern size_t utcp_get_sndbuf(struct utcp_connection *connection); +extern void utcp_set_sndbuf(struct utcp_connection *connection, size_t size); + +extern bool utcp_get_nodelay(struct utcp_connection *connection); +extern void utcp_set_nodelay(struct utcp_connection *connection, bool nodelay); + +extern bool utcp_get_keepalive(struct utcp_connection *connection); +extern void utcp_set_keepalive(struct utcp_connection *connection, bool keepalive); + +extern size_t utcp_get_outq(struct utcp_connection *connection); #endif diff --git a/utcp_priv.h b/utcp_priv.h index 5a72ce9..6c13863 100644 --- a/utcp_priv.h +++ b/utcp_priv.h @@ -30,6 +30,9 @@ #define FIN 4 #define RST 8 +#define DEFAULT_SNDBUFSIZE 4096 +#define DEFAULT_MAXSNDBUFSIZE 131072 + struct hdr { uint16_t src; // Source port uint16_t dst; // Destination port @@ -73,6 +76,9 @@ struct utcp_connection { struct utcp *utcp; bool reapable; + bool nodelay; + bool keepalive; + uint16_t src; uint16_t dst; enum state state; @@ -99,6 +105,7 @@ struct utcp_connection { char *sndbuf; uint32_t sndbufsize; + uint32_t maxsndbufsize; }; struct utcp { -- 2.39.2