debug(c, "accepted %p %p\n", c, recv, priv);
c->recv = recv;
c->priv = priv;
+ c->do_poll = true;
set_state(c, ESTABLISHED);
}
if(hdr.ctl & SYN && !(hdr.ctl & ACK) && utcp->accept) {
// If we don't want to accept it, send a RST back
- if((utcp->pre_accept && !utcp->pre_accept(utcp, hdr.dst))) {
+ if((utcp->listen && !utcp->listen(utcp, hdr.dst))) {
len = 1;
goto reset;
}
if(c->state == CLOSED) {
debug(c, "got packet for closed connection\n");
- return 0;
+ goto reset;
}
// It is for an existing connection.
}
}
- if(hdr.ctl & ACK && (seqdiff(hdr.ack, c->snd.last) > 0 || seqdiff(hdr.ack, c->snd.una) < 0)) {
- debug(c, "packet ack seqno out of range, %u <= %u < %u\n", c->snd.una, hdr.ack, c->snd.una + c->sndbuf.used);
-
- // Ignore unacceptable RST packets.
- if(hdr.ctl & RST) {
- return 0;
- }
-
- goto reset;
- }
-
// 2. Handle RST packets
if(hdr.ctl & RST) {
// 3. Advance snd.una
+ if(seqdiff(hdr.ack, c->snd.last) > 0 || seqdiff(hdr.ack, c->snd.una) < 0) {
+ debug(c, "packet ack seqno out of range, %u <= %u < %u\n", c->snd.una, hdr.ack, c->snd.una + c->sndbuf.used);
+ goto reset;
+ }
+
advanced = seqdiff(hdr.ack, c->snd.una);
if(advanced) {
c->snd.last++;
set_state(c, FIN_WAIT_1);
} else {
+ c->do_poll = true;
set_state(c, ESTABLISHED);
}
return 0;
case ESTABLISHED:
+ break;
+
case FIN_WAIT_1:
case FIN_WAIT_2:
+ if(c->reapable) {
+ // We already closed the connection and are not interested in more data.
+ goto reset;
+ }
+
break;
case CLOSE_WAIT:
hdr.src = c->src;
hdr.dst = c->dst;
hdr.seq = c->snd.nxt;
- hdr.ack = 0;
+ hdr.ack = c->rcv.nxt;
hdr.wnd = 0;
hdr.ctl = RST;
}
int utcp_close(struct utcp_connection *c) {
- if(c->rcvbuf.used) {
- return reset_connection(c) ? 0 : -1;
- }
-
if(utcp_shutdown(c, SHUT_RDWR) && errno != ENOTCONN) {
return -1;
}
return false;
}
-struct utcp *utcp_init(utcp_accept_t accept, utcp_pre_accept_t pre_accept, utcp_send_t send, void *priv) {
+struct utcp *utcp_init(utcp_accept_t accept, utcp_listen_t listen, utcp_send_t send, void *priv) {
if(!send) {
errno = EFAULT;
return NULL;
}
utcp->accept = accept;
- utcp->pre_accept = pre_accept;
+ utcp->listen = listen;
utcp->send = send;
utcp->priv = priv;
utcp->timeout = DEFAULT_USER_TIMEOUT; // sec
}
}
-void utcp_set_accept_cb(struct utcp *utcp, utcp_accept_t accept, utcp_pre_accept_t pre_accept) {
+void utcp_set_accept_cb(struct utcp *utcp, utcp_accept_t accept, utcp_listen_t listen) {
if(utcp) {
utcp->accept = accept;
- utcp->pre_accept = pre_accept;
+ utcp->listen = listen;
}
}