X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=utcp.c;h=97c43637f4ce52ceb74efd978c278f3e0df1eafb;hb=4368d8c9956242f0bdc00d43ebf32a72332522c1;hp=65885287f599631b045c563b2564ef3301a893d3;hpb=14892644247e46fc06f805d2653733bbdf45fb17;p=utcp diff --git a/utcp.c b/utcp.c index 6588528..97c4363 100644 --- a/utcp.c +++ b/utcp.c @@ -29,101 +29,7 @@ #include #include -#define UTCP_INTERNAL -#include "utcp.h" - -#define PREP(l) char pkt[(l) + sizeof struct hdr]; struct hdr *hdr = &pkt; - -#define SYN 1 -#define ACK 2 -#define FIN 4 -#define RST 8 - -struct hdr { - uint16_t src; // Source port - uint16_t dst; // Destination port - uint32_t seq; // Sequence number - uint32_t ack; // Acknowledgement number - uint32_t wnd; // Window size - uint16_t ctl; // Flags (SYN, ACK, FIN, RST) - uint16_t aux; // other stuff -}; - -enum state { - CLOSED, - LISTEN, - SYN_SENT, - SYN_RECEIVED, - ESTABLISHED, - FIN_WAIT_1, - FIN_WAIT_2, - CLOSE_WAIT, - CLOSING, - LAST_ACK, - TIME_WAIT -}; - -const char *strstate[] = { - "CLOSED", - "LISTEN", - "SYN_SENT", - "SYN_RECEIVED", - "ESTABLISHED", - "FIN_WAIT_1", - "FIN_WAIT_2", - "CLOSE_WAIT", - "CLOSING", - "LAST_ACK", - "TIME_WAIT" -}; - -struct utcp_connection { - void *priv; - struct utcp *utcp; - bool reapable; - - uint16_t src; - uint16_t dst; - enum state state; - - // The following two structures form the TCB - - struct { - uint32_t una; - uint32_t nxt; - uint32_t wnd; - uint32_t iss; - } snd; - - struct { - uint32_t nxt; - uint32_t wnd; - uint32_t irs; - } rcv; - - utcp_recv_t recv; - - struct timeval conn_timeout; - struct timeval rtrx_timeout; - - char *sndbuf; - uint32_t sndbufsize; -}; - -struct utcp { - void *priv; - - utcp_accept_t accept; - utcp_pre_accept_t pre_accept; - utcp_send_t send; - - uint16_t mtu; - int timeout; - - struct utcp_connection **connections; - int nconnections; - int nallocated; -}; +#include "utcp_priv.h" static void set_state(struct utcp_connection *c, enum state state) { c->state = state; @@ -167,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. @@ -232,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; } @@ -254,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 @@ -344,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); } @@ -406,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; @@ -1064,8 +973,49 @@ void utcp_exit(struct utcp *utcp) { free(utcp); } -int utcp_set_connection_timeout(struct utcp *u, int timeout) { - int prev = u->timeout; +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_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); }