debug("%p new state: %s\n", c->utcp, strstate[state]);
}
+static bool fin_wanted(struct utcp_connection *c, uint32_t seq) {
+ if(seq != c->snd.last)
+ return false;
+ switch(c->state) {
+ case FIN_WAIT_1:
+ case CLOSING:
+ case LAST_ACK:
+ return true;
+ default:
+ return false;
+ }
+}
+
static inline void list_connections(struct utcp *utcp) {
debug("%p has %d connections:\n", utcp, utcp->nconnections);
for(int i = 0; i < utcp->nconnections; i++)
c->snd.nxt += seglen;
left -= seglen;
- if(c->state != ESTABLISHED && seglen && c->snd.nxt == c->snd.last) {
- switch(c->state) {
- case FIN_WAIT_1:
- case CLOSING:
- seglen--;
- pkt->hdr.ctl |= FIN;
- break;
- default:
- break;
- }
+ if(seglen && fin_wanted(c, c->snd.nxt)) {
+ seglen--;
+ pkt->hdr.ctl |= FIN;
}
print_packet(c->utcp, "send", pkt, sizeof pkt->hdr + seglen);
default:
// TODO: implement
+#ifdef UTCP_DEBUG
abort();
+#endif
+ break;
}
free(pkt);
case TIME_WAIT:
break;
default:
+#ifdef UTCP_DEBUG
abort();
+#endif
+ break;
}
// 1b. Drop packets with a sequence number not in our receive window.
set_state(c, CLOSED);
return 0;
default:
+#ifdef UTCP_DEBUG
abort();
+#endif
+ break;
}
}
// Ehm, no. We should never receive a second SYN.
goto reset;
default:
+#ifdef UTCP_DEBUG
abort();
+#endif
+ return 0;
}
// SYN counts as one sequence number
case SYN_SENT:
case SYN_RECEIVED:
// This should never happen.
+#ifdef UTCP_DEBUG
abort();
+#endif
+ return 0;
case ESTABLISHED:
case FIN_WAIT_1:
case FIN_WAIT_2:
// Ehm no, We should never receive more data after a FIN.
goto reset;
default:
+#ifdef UTCP_DEBUG
abort();
+#endif
+ return 0;
}
ssize_t rxd;
case SYN_SENT:
case SYN_RECEIVED:
// This should never happen.
+#ifdef UTCP_DEBUG
abort();
+#endif
+ break;
case ESTABLISHED:
set_state(c, CLOSE_WAIT);
break;
// Ehm, no. We should never receive a second FIN.
goto reset;
default:
+#ifdef UTCP_DEBUG
abort();
+#endif
+ break;
}
// FIN counts as one sequence number
}
uint16_t utcp_get_mtu(struct utcp *utcp) {
- return utcp->mtu;
+ return utcp ? utcp->mtu : 0;
}
void utcp_set_mtu(struct utcp *utcp, uint16_t mtu) {
// TODO: handle overhead of the header
- utcp->mtu = mtu;
+ if(utcp)
+ utcp->mtu = mtu;
}
int utcp_get_user_timeout(struct utcp *u) {
- return u->timeout;
+ return u ? u->timeout : 0;
}
void utcp_set_user_timeout(struct utcp *u, int timeout) {
- u->timeout = timeout;
+ if(u)
+ u->timeout = timeout;
}
size_t utcp_get_sndbuf(struct utcp_connection *c) {
- return c->sndbuf.maxsize;
+ return c ? c->sndbuf.maxsize : 0;
}
size_t utcp_get_sndbuf_free(struct utcp_connection *c) {
- if(c->state == ESTABLISHED || c->state == CLOSE_WAIT)
+ if(c && (c->state == ESTABLISHED || c->state == CLOSE_WAIT))
return buffer_free(&c->sndbuf);
else
return 0;
}
void utcp_set_sndbuf(struct utcp_connection *c, size_t size) {
+ if(!c)
+ return;
c->sndbuf.maxsize = size;
if(c->sndbuf.maxsize != size)
c->sndbuf.maxsize = -1;
}
bool utcp_get_nodelay(struct utcp_connection *c) {
- return c->nodelay;
+ return c ? c->nodelay : false;
}
void utcp_set_nodelay(struct utcp_connection *c, bool nodelay) {
- c->nodelay = nodelay;
+ if(c)
+ c->nodelay = nodelay;
}
bool utcp_get_keepalive(struct utcp_connection *c) {
- return c->keepalive;
+ return c ? c->keepalive : false;
}
void utcp_set_keepalive(struct utcp_connection *c, bool keepalive) {
- c->keepalive = keepalive;
+ if(c)
+ c->keepalive = keepalive;
}
size_t utcp_get_outq(struct utcp_connection *c) {
- return seqdiff(c->snd.nxt, c->snd.una);
+ return c ? seqdiff(c->snd.nxt, c->snd.una) : 0;
}
void utcp_set_recv_cb(struct utcp_connection *c, utcp_recv_t recv) {
- c->recv = recv;
+ if(c)
+ c->recv = recv;
}
void utcp_set_poll_cb(struct utcp_connection *c, utcp_poll_t poll) {
- c->poll = poll;
+ if(c)
+ c->poll = poll;
}