X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=utcp.c;h=f48460d6f7aa6bf1686fec55cb6841139b62070f;hb=88fac696ff9e360c47e20a8fc8a397004e1ba49e;hp=5962820805d60f822a3a16d28b4098c604bb380f;hpb=153fb78c9727b4ab60ad8cdbf6a994ea2f9611c8;p=utcp diff --git a/utcp.c b/utcp.c index 5962820..f48460d 100644 --- a/utcp.c +++ b/utcp.c @@ -32,6 +32,27 @@ #include "utcp_priv.h" +#ifndef EBADMSG +#define EBADMSG 104 +#endif + +#ifndef SHUT_RDWR +#define SHUT_RDWR 2 +#endif + +#ifdef poll +#undef poll +#endif + +#ifndef timersub +#define timersub(a, b, r) do {\ + (r)->tv_sec = (a)->tv_sec - (b)->tv_sec;\ + (r)->tv_usec = (a)->tv_usec - (b)->tv_usec;\ + if((r)->tv_usec < 0)\ + (r)->tv_sec--, (r)->tv_usec += 1000000;\ +} while (0) +#endif + #ifdef UTCP_DEBUG #include @@ -255,21 +276,25 @@ static void ack(struct utcp_connection *c, bool sendatleastone) { struct { struct hdr hdr; - char data[c->utcp->mtu]; - } pkt; + char data[]; + } *pkt; - pkt.hdr.src = c->src; - pkt.hdr.dst = c->dst; - pkt.hdr.ack = c->rcv.nxt; - pkt.hdr.wnd = c->snd.wnd; - pkt.hdr.ctl = ACK; - pkt.hdr.aux = 0; + pkt = malloc(sizeof pkt->hdr + c->utcp->mtu); + if(!pkt->data) + return; + + pkt->hdr.src = c->src; + pkt->hdr.dst = c->dst; + pkt->hdr.ack = c->rcv.nxt; + pkt->hdr.wnd = c->snd.wnd; + pkt->hdr.ctl = ACK; + pkt->hdr.aux = 0; do { uint32_t seglen = left > c->utcp->mtu ? c->utcp->mtu : left; - pkt.hdr.seq = c->snd.nxt; + pkt->hdr.seq = c->snd.nxt; - memcpy(pkt.data, data, seglen); + memcpy(pkt->data, data, seglen); c->snd.nxt += seglen; data += seglen; @@ -280,16 +305,18 @@ static void ack(struct utcp_connection *c, bool sendatleastone) { case FIN_WAIT_1: case CLOSING: seglen--; - pkt.hdr.ctl |= FIN; + pkt->hdr.ctl |= FIN; break; default: break; } } - print_packet(c->utcp, "send", &pkt, sizeof pkt.hdr + seglen); - c->utcp->send(c->utcp, &pkt, sizeof pkt.hdr + seglen); + print_packet(c->utcp, "send", pkt, sizeof pkt->hdr + seglen); + c->utcp->send(c->utcp, pkt, sizeof pkt->hdr + seglen); } while(left); + + free(pkt); } ssize_t utcp_send(struct utcp_connection *c, const void *data, size_t len) { @@ -932,11 +959,15 @@ static void retransmit(struct utcp_connection *c) { struct { struct hdr hdr; - char data[c->utcp->mtu]; - } pkt; + char data[]; + } *pkt; - pkt.hdr.src = c->src; - pkt.hdr.dst = c->dst; + pkt = malloc(sizeof pkt->hdr + c->utcp->mtu); + if(!pkt) + return; + + pkt->hdr.src = c->src; + pkt->hdr.dst = c->dst; switch(c->state) { case LISTEN: @@ -944,27 +975,27 @@ static void retransmit(struct utcp_connection *c) { break; case SYN_SENT: - pkt.hdr.seq = c->snd.iss; - pkt.hdr.ack = 0; - pkt.hdr.wnd = c->rcv.wnd; - pkt.hdr.ctl = SYN; - print_packet(c->utcp, "rtrx", &pkt, sizeof pkt.hdr); - utcp->send(utcp, &pkt, sizeof pkt.hdr); + pkt->hdr.seq = c->snd.iss; + pkt->hdr.ack = 0; + pkt->hdr.wnd = c->rcv.wnd; + pkt->hdr.ctl = SYN; + print_packet(c->utcp, "rtrx", pkt, sizeof pkt->hdr); + utcp->send(utcp, pkt, sizeof pkt->hdr); break; case SYN_RECEIVED: - pkt.hdr.seq = c->snd.nxt; - pkt.hdr.ack = c->rcv.nxt; - pkt.hdr.ctl = SYN | ACK; - print_packet(c->utcp, "rtrx", &pkt, sizeof pkt.hdr); - utcp->send(utcp, &pkt, sizeof pkt.hdr); + pkt->hdr.seq = c->snd.nxt; + pkt->hdr.ack = c->rcv.nxt; + pkt->hdr.ctl = SYN | ACK; + print_packet(c->utcp, "rtrx", pkt, sizeof pkt->hdr); + utcp->send(utcp, pkt, sizeof pkt->hdr); break; case ESTABLISHED: case FIN_WAIT_1: - pkt.hdr.seq = c->snd.una; - pkt.hdr.ack = c->rcv.nxt; - pkt.hdr.ctl = ACK; + pkt->hdr.seq = c->snd.una; + pkt->hdr.ack = c->rcv.nxt; + pkt->hdr.ctl = ACK; uint32_t len = seqdiff(c->snd.nxt, c->snd.una); if(c->state == FIN_WAIT_1) len--; @@ -972,17 +1003,19 @@ static void retransmit(struct utcp_connection *c) { len = utcp->mtu; else { if(c->state == FIN_WAIT_1) - pkt.hdr.ctl |= FIN; + pkt->hdr.ctl |= FIN; } - memcpy(pkt.data, c->sndbuf, len); - print_packet(c->utcp, "rtrx", &pkt, sizeof pkt.hdr + len); - utcp->send(utcp, &pkt, sizeof pkt.hdr + len); + memcpy(pkt->data, c->sndbuf, len); + print_packet(c->utcp, "rtrx", pkt, sizeof pkt->hdr + len); + utcp->send(utcp, pkt, sizeof pkt->hdr + len); break; default: // TODO: implement abort(); } + + free(pkt); } /* Handle timeouts. @@ -1022,6 +1055,9 @@ int utcp_timeout(struct utcp *utcp) { retransmit(c); } + if(c->poll && c->sndbufsize < c->maxsndbufsize / 2) + c->poll(c, c->maxsndbufsize - c->sndbufsize); + if(timerisset(&c->conn_timeout) && timercmp(&c->conn_timeout, &next, <)) next = c->conn_timeout; @@ -1097,6 +1133,10 @@ size_t utcp_get_sndbuf(struct utcp_connection *c) { return c->maxsndbufsize; } +size_t utcp_get_sndbuf_free(struct utcp_connection *c) { + return c->maxsndbufsize - c->sndbufsize; +} + void utcp_set_sndbuf(struct utcp_connection *c, size_t size) { c->maxsndbufsize = size; if(c->maxsndbufsize != size) @@ -1122,3 +1162,11 @@ void utcp_set_keepalive(struct utcp_connection *c, bool keepalive) { size_t utcp_get_outq(struct utcp_connection *c) { return seqdiff(c->snd.nxt, c->snd.una); } + +void utcp_set_recv_cb(struct utcp_connection *c, utcp_recv_t recv) { + c->recv = recv; +} + +void utcp_set_poll_cb(struct utcp_connection *c, utcp_poll_t poll) { + c->poll = poll; +}