// Author(s): gthomas
// Contributors: gthomas
// Date: 2000-07-14
-// Purpose:
-// Description:
-//
+// Purpose:
+// Description:
+//
// This code is part of RedBoot (tm).
//
//####DESCRIPTIONEND####
#include <cyg/hal/hal_if.h>
#define MAX_TCP_SEGMENT (ETH_MAX_PKTLEN - (sizeof(eth_header_t) + sizeof(ip_header_t)))
-#define MAX_TCP_DATA (MAX_TCP_SEGMENT - sizeof(tcp_header_t))
+#define MAX_TCP_DATA (MAX_TCP_SEGMENT - sizeof(tcp_header_t))
/* sequence number comparison macros */
static char *
flags_to_str(octet f)
{
- static char str[7], *p;
-
- p = str;
-
- if (f & TCP_FLAG_FIN)
- *p++ = 'F';
- if (f & TCP_FLAG_SYN)
- *p++ = 'S';
- if (f & TCP_FLAG_RST)
- *p++ = 'R';
- if (f & TCP_FLAG_PSH)
- *p++ = 'P';
- if (f & TCP_FLAG_ACK)
- *p++ = 'A';
- if (f & TCP_FLAG_URG)
- *p++ = 'U';
- *p = '\0';
- return str;
+ static char str[7], *p;
+
+ p = str;
+
+ if (f & TCP_FLAG_FIN)
+ *p++ = 'F';
+ if (f & TCP_FLAG_SYN)
+ *p++ = 'S';
+ if (f & TCP_FLAG_RST)
+ *p++ = 'R';
+ if (f & TCP_FLAG_PSH)
+ *p++ = 'P';
+ if (f & TCP_FLAG_ACK)
+ *p++ = 'A';
+ if (f & TCP_FLAG_URG)
+ *p++ = 'U';
+ *p = '\0';
+ return str;
}
#endif
static void
tcp_send(tcp_socket_t *s, int flags, int resend)
{
- tcp_header_t *tcp;
- ip_header_t *ip;
- pktbuf_t *pkt = &s->pkt;
- unsigned short cksum;
- dword tcp_magic;
- int tcp_magic_size = sizeof(tcp_magic);
-
- ip = pkt->ip_hdr;
- tcp = pkt->tcp_hdr;
-
- if (flags & TCP_FLAG_SYN) {
- /* If SYN, assume no data and send MSS option in tcp header */
- pkt->pkt_bytes = sizeof(tcp_header_t) + 4;
- tcp->hdr_len = 6;
- tcp_magic = htonl(0x02040000 | MAX_TCP_DATA);
- memcpy((unsigned char *)(tcp+1), &tcp_magic, tcp_magic_size);
- s->data_bytes = 0;
- } else {
- pkt->pkt_bytes = s->data_bytes + sizeof(tcp_header_t);
- tcp->hdr_len = 5;
- }
-
- /* tcp header */
- tcp->reserved = 0;
- tcp->seqnum = htonl(s->seq);
- tcp->acknum = htonl(s->ack);
- tcp->checksum = 0;
-
- if (!resend) {
- tcp->src_port = htons(s->our_port);
- tcp->dest_port = htons(s->his_port);
- tcp->flags = flags;
- /* always set PUSH flag if sending data */
- if (s->data_bytes)
- tcp->flags |= TCP_FLAG_PSH;
- tcp->window = htons(MAX_TCP_DATA);
- tcp->urgent = 0;
+ tcp_header_t *tcp;
+ ip_header_t *ip;
+ pktbuf_t *pkt = &s->pkt;
+ unsigned short cksum;
+ dword tcp_magic;
+ int tcp_magic_size = sizeof(tcp_magic);
+
+ ip = pkt->ip_hdr;
+ tcp = pkt->tcp_hdr;
+
+ if (flags & TCP_FLAG_SYN) {
+ /* If SYN, assume no data and send MSS option in tcp header */
+ pkt->pkt_bytes = sizeof(tcp_header_t) + 4;
+ tcp->hdr_len = 6;
+ tcp_magic = htonl(0x02040000 | MAX_TCP_DATA);
+ memcpy((unsigned char *)(tcp+1), &tcp_magic, tcp_magic_size);
+ s->data_bytes = 0;
+ } else {
+ pkt->pkt_bytes = s->data_bytes + sizeof(tcp_header_t);
+ tcp->hdr_len = 5;
+ }
- /* fill in some pseudo-header fields */
- memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t));
- memcpy(ip->destination, s->his_addr.ip_addr, sizeof(ip_addr_t));
- ip->protocol = IP_PROTO_TCP;
- }
+ /* tcp header */
+ tcp->reserved = 0;
+ tcp->seqnum = htonl(s->seq);
+ tcp->acknum = htonl(s->ack);
+ tcp->checksum = 0;
+
+ if (!resend) {
+ tcp->src_port = htons(s->our_port);
+ tcp->dest_port = htons(s->his_port);
+ tcp->flags = flags;
+ /* always set PUSH flag if sending data */
+ if (s->data_bytes)
+ tcp->flags |= TCP_FLAG_PSH;
+ tcp->window = htons(MAX_TCP_DATA);
+ tcp->urgent = 0;
+
+ /* fill in some pseudo-header fields */
+ memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t));
+ memcpy(ip->destination, s->his_addr.ip_addr, sizeof(ip_addr_t));
+ ip->protocol = IP_PROTO_TCP;
+ }
- /* another pseudo-header field */
- ip->length = htons(pkt->pkt_bytes);
+ /* another pseudo-header field */
+ ip->length = htons(pkt->pkt_bytes);
- /* compute tcp checksum */
- cksum = __sum((word *)tcp, pkt->pkt_bytes, __pseudo_sum(ip));
- tcp->checksum = htons(cksum);
+ /* compute tcp checksum */
+ cksum = __sum((word *)tcp, pkt->pkt_bytes, __pseudo_sum(ip));
+ tcp->checksum = htons(cksum);
- __ip_send(pkt, IP_PROTO_TCP, &s->his_addr);
+ __ip_send(pkt, IP_PROTO_TCP, &s->his_addr);
- // HACK! If this delay is not present, then if the target system sends
- // back data (not just an ACK), then somehow we miss it :-(
- CYGACC_CALL_IF_DELAY_US(2*1000);
+ // HACK! If this delay is not present, then if the target system sends
+ // back data (not just an ACK), then somehow we miss it :-(
+ CYGACC_CALL_IF_DELAY_US(2*1000);
- BSPLOG(bsp_log("tcp_send: state[%d] flags[%s] ack[%x] data[%d].\n",
- s->state, flags_to_str(tcp->flags), s->ack, s->data_bytes));
+ BSPLOG(bsp_log("tcp_send: state[%d] flags[%s] ack[%x] data[%d].\n",
+ s->state, flags_to_str(tcp->flags), s->ack, s->data_bytes));
- if (s->state == _TIME_WAIT) {
- // If 'reuse' is set on socket, close after 1 second, otherwise 2 minutes
- __timer_set(&s->timer, s->reuse ? 1000 : 120000, do_close, s);
- }
- else if ((tcp->flags & (TCP_FLAG_FIN | TCP_FLAG_SYN)) || s->data_bytes)
- __timer_set(&s->timer, 1000, do_retrans, s);
+ if (s->state == _TIME_WAIT) {
+ // If 'reuse' is set on socket, close after 1 second, otherwise 2 minutes
+ __timer_set(&s->timer, s->reuse ? 1000 : 120000, do_close, s);
+ }
+ else if ((tcp->flags & (TCP_FLAG_FIN | TCP_FLAG_SYN)) || s->data_bytes)
+ __timer_set(&s->timer, 1000, do_retrans, s);
}
static pktbuf_t ack_pkt;
-static word ack_buf[ETH_MIN_PKTLEN/sizeof(word)];
+static union {
+ word w[ETH_MIN_PKTLEN / sizeof(word)];
+ struct {
+ ip_header_t ip;
+ tcp_header_t tcp;
+ };
+} ack_buf;
/*
* Send an ack.
static void
send_ack(tcp_socket_t *s)
{
- tcp_header_t *tcp;
- ip_header_t *ip;
- unsigned short cksum;
-
- ack_pkt.buf = ack_buf;
- ack_pkt.bufsize = sizeof(ack_buf);
- ack_pkt.ip_hdr = ip = (ip_header_t *)ack_buf;
- ack_pkt.tcp_hdr = tcp = (tcp_header_t *)(ip + 1);
- ack_pkt.pkt_bytes = sizeof(tcp_header_t);
-
- /* tcp header */
- tcp->hdr_len = 5;
- tcp->reserved = 0;
- tcp->seqnum = htonl(s->seq);
- tcp->acknum = htonl(s->ack);
- tcp->checksum = 0;
-
- tcp->src_port = htons(s->our_port);
- tcp->dest_port = htons(s->his_port);
- tcp->flags = TCP_FLAG_ACK;
-
- tcp->window = htons(MAX_TCP_DATA);
- tcp->urgent = 0;
-
- /* fill in some pseudo-header fields */
- memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t));
- memcpy(ip->destination, s->his_addr.ip_addr, sizeof(ip_addr_t));
- ip->protocol = IP_PROTO_TCP;
-
- /* another pseudo-header field */
- ip->length = htons(sizeof(tcp_header_t));
-
- /* compute tcp checksum */
- cksum = __sum((word *)tcp, sizeof(*tcp), __pseudo_sum(ip));
- tcp->checksum = htons(cksum);
-
- __ip_send(&ack_pkt, IP_PROTO_TCP, &s->his_addr);
+ tcp_header_t *tcp;
+ ip_header_t *ip;
+ unsigned short cksum;
+
+ ack_pkt.buf = ack_buf.w;
+ ack_pkt.bufsize = sizeof(ack_buf.w);
+ ack_pkt.ip_hdr = ip = &ack_buf.ip;
+ ack_pkt.tcp_hdr = tcp = &ack_buf.tcp;//(tcp_header_t *)(ip + 1);
+ ack_pkt.pkt_bytes = sizeof(tcp_header_t);
+
+ /* tcp header */
+ tcp->hdr_len = 5;
+ tcp->reserved = 0;
+ tcp->seqnum = htonl(s->seq);
+ tcp->acknum = htonl(s->ack);
+ tcp->checksum = 0;
+
+ tcp->src_port = htons(s->our_port);
+ tcp->dest_port = htons(s->his_port);
+ tcp->flags = TCP_FLAG_ACK;
+
+ tcp->window = htons(MAX_TCP_DATA);
+ tcp->urgent = 0;
+
+ /* fill in some pseudo-header fields */
+ memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t));
+ memcpy(ip->destination, s->his_addr.ip_addr, sizeof(ip_addr_t));
+ ip->protocol = IP_PROTO_TCP;
+
+ /* another pseudo-header field */
+ ip->length = htons(sizeof(tcp_header_t));
+
+ /* compute tcp checksum */
+ cksum = __sum((word *)tcp, sizeof(*tcp), __pseudo_sum(ip));
+ tcp->checksum = htons(cksum);
+
+ __ip_send(&ack_pkt, IP_PROTO_TCP, &s->his_addr);
}
static void
send_reset(pktbuf_t *pkt, ip_route_t *r)
{
- ip_header_t *ip = pkt->ip_hdr;
- tcp_header_t *tcp = pkt->tcp_hdr;
- dword seq, ack;
- word src, dest;
- word cksum;
-
- seq = ntohl(tcp->acknum);
- ack = ntohl(tcp->seqnum);
- src = ntohs(tcp->dest_port);
- dest = ntohs(tcp->src_port);
-
- tcp = (tcp_header_t *)(ip + 1);
- pkt->pkt_bytes = sizeof(tcp_header_t);
-
- /* tcp header */
- tcp->hdr_len = 5;
- tcp->reserved = 0;
- tcp->seqnum = htonl(seq);
- tcp->acknum = htonl(ack);
- tcp->window = htons(1024);
- tcp->urgent = 0;
- tcp->checksum = 0;
- tcp->src_port = htons(src);
- tcp->dest_port = htons(dest);
- tcp->flags = TCP_FLAG_RST | TCP_FLAG_ACK;
-
- /* fill in some pseudo-header fields */
- memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t));
- memcpy(ip->destination, r->ip_addr, sizeof(ip_addr_t));
- ip->protocol = IP_PROTO_TCP;
- ip->length = htons(pkt->pkt_bytes);
-
- /* compute tcp checksum */
- cksum = __sum((word *)tcp, pkt->pkt_bytes, __pseudo_sum(ip));
- tcp->checksum = htons(cksum);
-
- __ip_send(pkt, IP_PROTO_TCP, r);
+ ip_header_t *ip = pkt->ip_hdr;
+ tcp_header_t *tcp = pkt->tcp_hdr;
+ dword seq, ack;
+ word src, dest;
+ word cksum;
+
+ seq = ntohl(tcp->acknum);
+ ack = ntohl(tcp->seqnum);
+ src = ntohs(tcp->dest_port);
+ dest = ntohs(tcp->src_port);
+
+ tcp = (tcp_header_t *)(ip + 1);
+ pkt->pkt_bytes = sizeof(tcp_header_t);
+
+ /* tcp header */
+ tcp->hdr_len = 5;
+ tcp->reserved = 0;
+ tcp->seqnum = htonl(seq);
+ tcp->acknum = htonl(ack);
+ tcp->window = htons(1024);
+ tcp->urgent = 0;
+ tcp->checksum = 0;
+ tcp->src_port = htons(src);
+ tcp->dest_port = htons(dest);
+ tcp->flags = TCP_FLAG_RST | TCP_FLAG_ACK;
+
+ /* fill in some pseudo-header fields */
+ memcpy(ip->source, __local_ip_addr, sizeof(ip_addr_t));
+ memcpy(ip->destination, r->ip_addr, sizeof(ip_addr_t));
+ ip->protocol = IP_PROTO_TCP;
+ ip->length = htons(pkt->pkt_bytes);
+
+ /* compute tcp checksum */
+ cksum = __sum((word *)tcp, pkt->pkt_bytes, __pseudo_sum(ip));
+ tcp->checksum = htons(cksum);
+
+ __ip_send(pkt, IP_PROTO_TCP, r);
}
static void
unlink_socket(tcp_socket_t *s)
{
- tcp_socket_t *prev, *tp;
-
- for (prev = NULL, tp = tcp_list; tp; prev = tp, tp = tp->next)
- if (tp == s) {
- BSPLOG(bsp_log("unlink tcp socket.\n"));
- if (prev)
- prev->next = s->next;
- else
- tcp_list = s->next;
- }
+ tcp_socket_t *prev, *tp;
+
+ for (prev = NULL, tp = tcp_list; tp; prev = tp, tp = tp->next)
+ if (tp == s) {
+ BSPLOG(bsp_log("unlink tcp socket.\n"));
+ if (prev)
+ prev->next = s->next;
+ else
+ tcp_list = s->next;
+ }
}
/*
static void
do_retrans(void *p)
{
- BSPLOG(bsp_log("tcp do_retrans.\n"));
- tcp_send((tcp_socket_t *)p, 0, 1);
+ BSPLOG(bsp_log("tcp do_retrans.\n"));
+ tcp_send((tcp_socket_t *)p, 0, 1);
}
static void
do_close(void *p)
{
- BSPLOG(bsp_log("tcp do_close.\n"));
- /* close connection */
- ((tcp_socket_t *)p)->state = _CLOSED;
- unlink_socket(p);
+ BSPLOG(bsp_log("tcp do_close.\n"));
+ /* close connection */
+ ((tcp_socket_t *)p)->state = _CLOSED;
+ unlink_socket(p);
}
static void
free_rxlist(tcp_socket_t *s)
{
- pktbuf_t *p;
+ pktbuf_t *p;
- BSPLOG(bsp_log("tcp free_rxlist.\n"));
+ BSPLOG(bsp_log("tcp free_rxlist.\n"));
- while ((p = s->rxlist) != NULL) {
- s->rxlist = p->next;
- __pktbuf_free(p);
- }
+ while ((p = s->rxlist) != NULL) {
+ s->rxlist = p->next;
+ __pktbuf_free(p);
+ }
}
static void
do_reset(tcp_socket_t *s)
{
- /* close connection */
- s->state = _CLOSED;
- __timer_cancel(&s->timer);
- free_rxlist(s);
- unlink_socket(s);
+ /* close connection */
+ s->state = _CLOSED;
+ __timer_cancel(&s->timer);
+ free_rxlist(s);
+ unlink_socket(s);
}
static int
handle_data(tcp_socket_t *s, pktbuf_t *pkt)
{
- tcp_header_t *tcp = pkt->tcp_hdr;
- unsigned int diff, seq;
- int data_len;
- char *data_ptr;
- pktbuf_t *p;
-
- data_len = pkt->pkt_bytes - (tcp->hdr_len << 2);
- data_ptr = ((char *)tcp) + (tcp->hdr_len << 2);
-
- seq = ntohl(tcp->seqnum);
-
- BSPLOG(bsp_log("tcp data: seq[%x] len[%d].\n", seq, data_len));
-
- if (SEQ_LE(seq, s->ack)) {
- /*
- * Figure difference between which byte we're expecting and which byte
- * is sent first. Adjust data length and data pointer accordingly.
- */
- diff = s->ack - seq;
- data_len -= diff;
- data_ptr += diff;
-
- if (data_len > 0) {
- /* queue the new data */
- s->ack += data_len;
- pkt->next = NULL;
- if ((p = s->rxlist) != NULL) {
- while (p->next)
- p = p->next;
- p->next = pkt;
- BSPLOG(bsp_log("tcp data: Add pkt[%x] len[%d].\n",
- pkt, data_len));
- } else {
- s->rxlist = pkt;
- s->rxcnt = data_len;
- s->rxptr = data_ptr;
- BSPLOG(bsp_log("tcp data: pkt[%x] len[%d].\n",
- pkt, data_len));
- }
- return 1;
+ tcp_header_t *tcp = pkt->tcp_hdr;
+ unsigned int diff, seq;
+ int data_len;
+ char *data_ptr;
+ pktbuf_t *p;
+
+ data_len = pkt->pkt_bytes - (tcp->hdr_len << 2);
+ data_ptr = ((char *)tcp) + (tcp->hdr_len << 2);
+
+ seq = ntohl(tcp->seqnum);
+
+ BSPLOG(bsp_log("tcp data: seq[%x] len[%d].\n", seq, data_len));
+
+ if (SEQ_LE(seq, s->ack)) {
+ /*
+ * Figure difference between which byte we're expecting and which byte
+ * is sent first. Adjust data length and data pointer accordingly.
+ */
+ diff = s->ack - seq;
+ data_len -= diff;
+ data_ptr += diff;
+
+ if (data_len > 0) {
+ /* queue the new data */
+ s->ack += data_len;
+ pkt->next = NULL;
+ if ((p = s->rxlist) != NULL) {
+ while (p->next)
+ p = p->next;
+ p->next = pkt;
+ BSPLOG(bsp_log("tcp data: Add pkt[%x] len[%d].\n",
+ pkt, data_len));
+ } else {
+ s->rxlist = pkt;
+ s->rxcnt = data_len;
+ s->rxptr = data_ptr;
+ BSPLOG(bsp_log("tcp data: pkt[%x] len[%d].\n",
+ pkt, data_len));
+ }
+ return 1;
+ }
}
- }
- return 0;
+ return 0;
}
static void
handle_ack(tcp_socket_t *s, pktbuf_t *pkt)
{
- tcp_header_t *tcp = pkt->tcp_hdr;
- dword ack;
- int advance;
- char *dp;
+ tcp_header_t *tcp = pkt->tcp_hdr;
+ dword ack;
+ int advance;
+ char *dp;
- /* process ack value in packet */
- ack = ntohl(tcp->acknum);
+ /* process ack value in packet */
+ ack = ntohl(tcp->acknum);
- BSPLOG(bsp_log("Rcvd tcp ACK %x\n", ack));
+ BSPLOG(bsp_log("Rcvd tcp ACK %x\n", ack));
- if (SEQ_GT(ack, s->seq)) {
- __timer_cancel(&s->timer);
- advance = ack - s->seq;
- if (advance > s->data_bytes)
- advance = s->data_bytes;
-
- BSPLOG(bsp_log("seq advance %d", advance));
-
- if (advance > 0) {
- s->seq += advance;
- s->data_bytes -= advance;
- if (s->data_bytes) {
- /* other end ack'd only part of the pkt */
- BSPLOG(bsp_log(" %d bytes left", s->data_bytes));
- dp = (char *)(s->pkt.tcp_hdr + 1);
- memcpy(dp, dp + advance, s->data_bytes);
- }
+ if (SEQ_GT(ack, s->seq)) {
+ __timer_cancel(&s->timer);
+ advance = ack - s->seq;
+ if (advance > s->data_bytes)
+ advance = s->data_bytes;
+
+ BSPLOG(bsp_log("seq advance %d", advance));
+
+ if (advance > 0) {
+ s->seq += advance;
+ s->data_bytes -= advance;
+ if (s->data_bytes) {
+ /* other end ack'd only part of the pkt */
+ BSPLOG(bsp_log(" %d bytes left", s->data_bytes));
+ dp = (char *)(s->pkt.tcp_hdr + 1);
+ memcpy(dp, dp + advance, s->data_bytes);
+ }
+ }
}
- }
- BSPLOG(bsp_log("\n"));
+ BSPLOG(bsp_log("\n"));
}
void
__tcp_handler(pktbuf_t *pkt, ip_route_t *r)
{
- tcp_header_t *tcp = pkt->tcp_hdr;
- ip_header_t *ip = pkt->ip_hdr;
- tcp_socket_t *prev,*s;
- dword ack;
- int queued = 0;
-
- /* set length for pseudo sum calculation */
- ip->length = htons(pkt->pkt_bytes);
-
- if (__sum((word *)tcp, pkt->pkt_bytes, __pseudo_sum(ip)) == 0) {
- for (prev = NULL, s = tcp_list; s; prev = s, s = s->next) {
- if (s->our_port == ntohs(tcp->dest_port)) {
- if (s->his_port == 0)
- break;
- if (s->his_port == ntohs(tcp->src_port) &&
- !memcmp(r->ip_addr, s->his_addr.ip_addr, sizeof(ip_addr_t)))
- break;
- }
- }
-
- if (s) {
- /* found the socket this packet belongs to */
-
- /* refresh his ethernet address */
- memcpy(s->his_addr.enet_addr, r->enet_addr, sizeof(enet_addr_t));
-
- if (s->state != _SYN_RCVD && tcp->flags & TCP_FLAG_RST) {
- BSPLOG(bsp_log("TCP_FLAG_RST rcvd\n"));
- do_reset(s);
- __pktbuf_free(pkt);
- return;
- }
-
- switch (s->state) {
-
- case _SYN_SENT:
- /* active open not supported */
- if (tcp->flags != (TCP_FLAG_SYN | TCP_FLAG_ACK)) {
- do_reset(s);
- __pktbuf_free(pkt);
- return;
- }
- s->state = _ESTABLISHED;
- s->ack = ntohl(tcp->seqnum) + 1;
- s->seq = ntohl(tcp->acknum);
- __timer_cancel(&s->timer);
- send_ack(s);
- break;
-
- case _LISTEN:
- if (tcp->flags & TCP_FLAG_SYN) {
- s->state = _SYN_RCVD;
- s->ack = ntohl(tcp->seqnum) + 1;
- s->his_port = ntohs(tcp->src_port);
- memcpy(s->his_addr.ip_addr, r->ip_addr, sizeof(ip_addr_t));
- s->data_bytes = 0;
-
- BSPLOG(bsp_log("SYN from %d.%d.%d.%d:%d (seq %x)\n",
- s->his_addr.ip_addr[0],s->his_addr.ip_addr[1],
- s->his_addr.ip_addr[2],s->his_addr.ip_addr[3],
- s->his_port, ntohl(tcp->seqnum)));
-
- tcp_send(s, TCP_FLAG_SYN | TCP_FLAG_ACK, 0);
- }
- else
- send_reset(pkt, r);
- break;
-
- case _SYN_RCVD:
- BSPLOG(bsp_log("_SYN_RCVD timer cancel.\n"));
- __timer_cancel(&s->timer);
-
- /* go back to _LISTEN state if reset */
- if (tcp->flags & TCP_FLAG_RST) {
- s->state = _LISTEN;
-
- BSPLOG(bsp_log("_SYN_RCVD --> _LISTEN\n"));
-
- } else if (tcp->flags & TCP_FLAG_SYN) {
- /* apparently our SYN/ACK was lost? */
- tcp_send(s, 0, 1);
-
- BSPLOG(bsp_log("retransmitting SYN/ACK\n"));
-
- } else if ((tcp->flags & TCP_FLAG_ACK) &&
- ntohl(tcp->acknum) == (s->seq + 1)) {
- /* we've established the connection */
- s->state = _ESTABLISHED;
- s->seq++;
-
- BSPLOG(bsp_log("ACK received - connection established\n"));
+ tcp_header_t *tcp = pkt->tcp_hdr;
+ ip_header_t *ip = pkt->ip_hdr;
+ tcp_socket_t *prev,*s;
+ dword ack;
+ int queued = 0;
+
+ /* set length for pseudo sum calculation */
+ ip->length = htons(pkt->pkt_bytes);
+
+ if (__sum((word *)tcp, pkt->pkt_bytes, __pseudo_sum(ip)) == 0) {
+ for (prev = NULL, s = tcp_list; s; prev = s, s = s->next) {
+ if (s->our_port == ntohs(tcp->dest_port)) {
+ if (s->his_port == 0)
+ break;
+ if (s->his_port == ntohs(tcp->src_port) &&
+ !memcmp(r->ip_addr, s->his_addr.ip_addr, sizeof(ip_addr_t)))
+ break;
+ }
}
- break;
-
- case _ESTABLISHED:
- case _CLOSE_WAIT:
- ack = s->ack; /* save original ack */
- if (tcp->flags & TCP_FLAG_ACK)
- handle_ack(s, pkt);
- queued = handle_data(s, pkt);
+ if (s) {
+ /* found the socket this packet belongs to */
- if ((tcp->flags & TCP_FLAG_FIN) &&
- ntohl(tcp->seqnum) == s->ack) {
+ /* refresh his ethernet address */
+ memcpy(s->his_addr.enet_addr, r->enet_addr, sizeof(enet_addr_t));
- BSPLOG(bsp_log("FIN received - going to _CLOSE_WAIT\n"));
+ if (s->state != _SYN_RCVD && tcp->flags & TCP_FLAG_RST) {
+ BSPLOG(bsp_log("TCP_FLAG_RST rcvd\n"));
+ do_reset(s);
+ __pktbuf_free(pkt);
+ return;
+ }
- s->ack++;
- s->state = _CLOSE_WAIT;
- }
- /*
- * Send an ack if neccessary.
- */
- if (s->ack != ack || pkt->pkt_bytes > (tcp->hdr_len << 2))
- send_ack(s);
- break;
-
- case _LAST_ACK:
- if (tcp->flags & TCP_FLAG_ACK) {
- handle_ack(s, pkt);
- if (ntohl(tcp->acknum) == (s->seq + 1)) {
- BSPLOG(bsp_log("_LAST_ACK --> _CLOSED\n"));
- s->state = _CLOSED;
- unlink_socket(s);
- }
- }
- break;
-
- case _FIN_WAIT_1:
- if (tcp->flags & TCP_FLAG_ACK) {
- handle_ack(s, pkt);
- if (ntohl(tcp->acknum) == (s->seq + 1)) {
- /* got ACK for FIN packet */
- s->seq++;
- if (tcp->flags & TCP_FLAG_FIN) {
- BSPLOG(bsp_log("_FIN_WAIT_1 --> _TIME_WAIT\n"));
- s->ack++;
- s->state = _TIME_WAIT;
- send_ack(s);
- } else {
- s->state = _FIN_WAIT_2;
- BSPLOG(bsp_log("_FIN_WAIT_1 --> _FIN_WAIT_2\n"));
+ switch (s->state) {
+
+ case _SYN_SENT:
+ /* active open not supported */
+ if (tcp->flags != (TCP_FLAG_SYN | TCP_FLAG_ACK)) {
+ do_reset(s);
+ __pktbuf_free(pkt);
+ return;
+ }
+ s->state = _ESTABLISHED;
+ s->ack = ntohl(tcp->seqnum) + 1;
+ s->seq = ntohl(tcp->acknum);
+ __timer_cancel(&s->timer);
+ send_ack(s);
+ break;
+
+ case _LISTEN:
+ if (tcp->flags & TCP_FLAG_SYN) {
+ s->state = _SYN_RCVD;
+ s->ack = ntohl(tcp->seqnum) + 1;
+ s->his_port = ntohs(tcp->src_port);
+ memcpy(s->his_addr.ip_addr, r->ip_addr, sizeof(ip_addr_t));
+ s->data_bytes = 0;
+
+ BSPLOG(bsp_log("SYN from %d.%d.%d.%d:%d (seq %x)\n",
+ s->his_addr.ip_addr[0],s->his_addr.ip_addr[1],
+ s->his_addr.ip_addr[2],s->his_addr.ip_addr[3],
+ s->his_port, ntohl(tcp->seqnum)));
+
+ tcp_send(s, TCP_FLAG_SYN | TCP_FLAG_ACK, 0);
+ }
+ else
+ send_reset(pkt, r);
+ break;
+
+ case _SYN_RCVD:
+ BSPLOG(bsp_log("_SYN_RCVD timer cancel.\n"));
+ __timer_cancel(&s->timer);
+
+ /* go back to _LISTEN state if reset */
+ if (tcp->flags & TCP_FLAG_RST) {
+ s->state = _LISTEN;
+
+ BSPLOG(bsp_log("_SYN_RCVD --> _LISTEN\n"));
+
+ } else if (tcp->flags & TCP_FLAG_SYN) {
+ /* apparently our SYN/ACK was lost? */
+ tcp_send(s, 0, 1);
+
+ BSPLOG(bsp_log("retransmitting SYN/ACK\n"));
+
+ } else if ((tcp->flags & TCP_FLAG_ACK) &&
+ ntohl(tcp->acknum) == (s->seq + 1)) {
+ /* we've established the connection */
+ s->state = _ESTABLISHED;
+ s->seq++;
+
+ BSPLOG(bsp_log("ACK received - connection established\n"));
+ }
+ break;
+
+ case _ESTABLISHED:
+ case _CLOSE_WAIT:
+ ack = s->ack; /* save original ack */
+ if (tcp->flags & TCP_FLAG_ACK)
+ handle_ack(s, pkt);
+
+ queued = handle_data(s, pkt);
+
+ if ((tcp->flags & TCP_FLAG_FIN) &&
+ ntohl(tcp->seqnum) == s->ack) {
+
+ BSPLOG(bsp_log("FIN received - going to _CLOSE_WAIT\n"));
+
+ s->ack++;
+ s->state = _CLOSE_WAIT;
+ }
+ /*
+ * Send an ack if neccessary.
+ */
+ if (s->ack != ack || pkt->pkt_bytes > (tcp->hdr_len << 2))
+ send_ack(s);
+ break;
+
+ case _LAST_ACK:
+ if (tcp->flags & TCP_FLAG_ACK) {
+ handle_ack(s, pkt);
+ if (ntohl(tcp->acknum) == (s->seq + 1)) {
+ BSPLOG(bsp_log("_LAST_ACK --> _CLOSED\n"));
+ s->state = _CLOSED;
+ unlink_socket(s);
+ }
+ }
+ break;
+
+ case _FIN_WAIT_1:
+ if (tcp->flags & TCP_FLAG_ACK) {
+ handle_ack(s, pkt);
+ if (ntohl(tcp->acknum) == (s->seq + 1)) {
+ /* got ACK for FIN packet */
+ s->seq++;
+ if (tcp->flags & TCP_FLAG_FIN) {
+ BSPLOG(bsp_log("_FIN_WAIT_1 --> _TIME_WAIT\n"));
+ s->ack++;
+ s->state = _TIME_WAIT;
+ send_ack(s);
+ } else {
+ s->state = _FIN_WAIT_2;
+ BSPLOG(bsp_log("_FIN_WAIT_1 --> _FIN_WAIT_2\n"));
+ }
+ break; /* All done for now */
+ }
+ }
+ /* At this point, no ACK for FIN has been seen, so check for
+ simultaneous close */
+ if (tcp->flags & TCP_FLAG_FIN) {
+ BSPLOG(bsp_log("_FIN_WAIT_1 --> _CLOSING\n"));
+ __timer_cancel(&s->timer);
+ s->ack++;
+ s->state = _CLOSING;
+ /* FIN is resent so the timeout and retry for this packet
+ will also take care of timeout and resend of the
+ previously sent FIN (which got us to FIN_WAIT_1). While
+ not technically correct, resending FIN only causes a
+ duplicate FIN (same sequence number) which should be
+ ignored by the other end. */
+ tcp_send(s, TCP_FLAG_FIN | TCP_FLAG_ACK, 0);
+ }
+ break;
+
+ case _FIN_WAIT_2:
+ queued = handle_data(s, pkt);
+ if (tcp->flags & TCP_FLAG_FIN) {
+ BSPLOG(bsp_log("_FIN_WAIT_2 --> _TIME_WAIT\n"));
+ s->ack++;
+ s->state = _TIME_WAIT;
+ send_ack(s);
+ }
+ break;
+
+ case _CLOSING:
+ if (tcp->flags & TCP_FLAG_ACK) {
+ handle_ack(s, pkt);
+ if (ntohl(tcp->acknum) == (s->seq + 1)) {
+ /* got ACK for FIN packet */
+ BSPLOG(bsp_log("_CLOSING --> _TIME_WAIT\n"));
+ __timer_cancel(&s->timer);
+ s->state = _TIME_WAIT;
+ }
+ }
+ break;
+
+ case _TIME_WAIT:
+ BSPLOG(bsp_log("_TIME_WAIT resend.\n"));
+ if (tcp->flags & TCP_FLAG_FIN)
+ tcp_send(s, 0, 1); /* just resend ack */
+ break;
}
- break; /* All done for now */
- }
- }
- /* At this point, no ACK for FIN has been seen, so check for
- simultaneous close */
- if (tcp->flags & TCP_FLAG_FIN) {
- BSPLOG(bsp_log("_FIN_WAIT_1 --> _CLOSING\n"));
- __timer_cancel(&s->timer);
- s->ack++;
- s->state = _CLOSING;
- /* FIN is resent so the timeout and retry for this packet
- will also take care of timeout and resend of the
- previously sent FIN (which got us to FIN_WAIT_1). While
- not technically correct, resending FIN only causes a
- duplicate FIN (same sequence number) which should be
- ignored by the other end. */
- tcp_send(s, TCP_FLAG_FIN | TCP_FLAG_ACK, 0);
- }
- break;
-
- case _FIN_WAIT_2:
- queued = handle_data(s, pkt);
- if (tcp->flags & TCP_FLAG_FIN) {
- BSPLOG(bsp_log("_FIN_WAIT_2 --> _TIME_WAIT\n"));
- s->ack++;
- s->state = _TIME_WAIT;
- send_ack(s);
+ } else {
+ BSPLOG(bsp_log("Unexpected segment from: %d.%d.%d.%d:%d\n",
+ r->ip_addr[0], r->ip_addr[1], r->ip_addr[3],
+ r->ip_addr[4], ntohs(tcp->src_port)));
+ send_reset(pkt, r);
}
- break;
-
- case _CLOSING:
- if (tcp->flags & TCP_FLAG_ACK) {
- handle_ack(s, pkt);
- if (ntohl(tcp->acknum) == (s->seq + 1)) {
- /* got ACK for FIN packet */
- BSPLOG(bsp_log("_CLOSING --> _TIME_WAIT\n"));
- __timer_cancel(&s->timer);
- s->state = _TIME_WAIT;
- }
- }
- break;
-
- case _TIME_WAIT:
- BSPLOG(bsp_log("_TIME_WAIT resend.\n"));
- if (tcp->flags & TCP_FLAG_FIN)
- tcp_send(s, 0, 1); /* just resend ack */
- break;
- }
- } else {
- BSPLOG(bsp_log("Unexpected segment from: %d.%d.%d.%d:%d\n",
- r->ip_addr[0], r->ip_addr[1], r->ip_addr[3],
- r->ip_addr[4], ntohs(tcp->src_port)));
- send_reset(pkt, r);
}
- }
- if (!queued)
- __pktbuf_free(pkt);
+ if (!queued)
+ __pktbuf_free(pkt);
}
void
__tcp_poll(void)
{
- __enet_poll();
- __timer_poll();
+ __enet_poll();
+ __timer_poll();
}
int
__tcp_listen(tcp_socket_t *s, word port)
{
- BSPLOG(bsp_log("tcp_listen: s[%p] port[%x]\n", s, port));
+ BSPLOG(bsp_log("tcp_listen: s[%p] port[%x]\n", s, port));
- memset(s, 0, sizeof(tcp_socket_t));
- s->state = _LISTEN;
- s->our_port = port;
- s->pkt.buf = (word *)s->pktbuf;
- s->pkt.bufsize = ETH_MAX_PKTLEN;
- s->pkt.ip_hdr = (ip_header_t *)s->pkt.buf;
- s->pkt.tcp_hdr = (tcp_header_t *)(s->pkt.ip_hdr + 1);
+ memset(s, 0, sizeof(tcp_socket_t));
+ s->state = _LISTEN;
+ s->our_port = port;
+ s->pkt.buf = (word *)s->pktbuf;
+ s->pkt.bufsize = ETH_MAX_PKTLEN;
+ s->pkt.ip_hdr = (ip_header_t *)s->pkt.buf;
+ s->pkt.tcp_hdr = (tcp_header_t *)(s->pkt.ip_hdr + 1);
- s->next = tcp_list;
+ s->next = tcp_list;
#if 0
- /* limit to one open socket at a time */
- if (s->next) {
- BSPLOG(bsp_log("tcp_listen: recursion error\n"));
- BSPLOG(while(1));
- }
+ /* limit to one open socket at a time */
+ if (s->next) {
+ BSPLOG(bsp_log("tcp_listen: recursion error\n"));
+ BSPLOG(while(1));
+ }
#endif
-
- tcp_list = s;
- return 0;
+ tcp_list = s;
+
+ return 0;
}
/*
__tcp_so_reuseaddr(tcp_socket_t *s)
{
// BSPLOG(bsp_log("__tcp_so_reuseaddr.\n"));
- s->reuse = 0x01;
+ s->reuse = 0x01;
}
/*
__tcp_drain(tcp_socket_t *s)
{
// BSPLOG(bsp_log("__tcp_drain.\n"));
- while (s->state != _CLOSED && s->data_bytes)
- __tcp_poll();
+ while (s->state != _CLOSED && s->data_bytes)
+ __tcp_poll();
// BSPLOG(bsp_log("__tcp_drain done.\n"));
}
static void
do_abort(void *s)
{
- BSPLOG(bsp_log("do_abort: send RST\n"));
- tcp_send((tcp_socket_t *)s, TCP_FLAG_ACK | TCP_FLAG_RST, 0);
- __timer_cancel(&abort_timer);
- ((tcp_socket_t *)s)->state = _CLOSED;
- free_rxlist((tcp_socket_t *)s);
- unlink_socket((tcp_socket_t *)s);
+ BSPLOG(bsp_log("do_abort: send RST\n"));
+ tcp_send((tcp_socket_t *)s, TCP_FLAG_ACK | TCP_FLAG_RST, 0);
+ __timer_cancel(&abort_timer);
+ ((tcp_socket_t *)s)->state = _CLOSED;
+ free_rxlist((tcp_socket_t *)s);
+ unlink_socket((tcp_socket_t *)s);
}
void
__tcp_abort(tcp_socket_t *s, unsigned long delay)
{
- __timer_set(&abort_timer, delay, do_abort, s);
+ __timer_set(&abort_timer, delay, do_abort, s);
}
/*
void
__tcp_close(tcp_socket_t *s)
{
- __tcp_drain(s);
- if (s->state == _ESTABLISHED || s->state == _SYN_RCVD) {
- BSPLOG(bsp_log("__tcp_close: going to _FIN_WAIT_1\n"));
- s->state = _FIN_WAIT_1;
- tcp_send(s, TCP_FLAG_ACK | TCP_FLAG_FIN, 0);
- } else if (s->state == _CLOSE_WAIT) {
-
- BSPLOG(bsp_log("__tcp_close: going to _LAST_ACK\n"));
-
- s->state = _LAST_ACK;
- tcp_send(s, TCP_FLAG_ACK | TCP_FLAG_FIN, 0);
- }
- free_rxlist(s);
+ __tcp_drain(s);
+ if (s->state == _ESTABLISHED || s->state == _SYN_RCVD) {
+ BSPLOG(bsp_log("__tcp_close: going to _FIN_WAIT_1\n"));
+ s->state = _FIN_WAIT_1;
+ tcp_send(s, TCP_FLAG_ACK | TCP_FLAG_FIN, 0);
+ } else if (s->state == _CLOSE_WAIT) {
+
+ BSPLOG(bsp_log("__tcp_close: going to _LAST_ACK\n"));
+
+ s->state = _LAST_ACK;
+ tcp_send(s, TCP_FLAG_ACK | TCP_FLAG_FIN, 0);
+ }
+ free_rxlist(s);
}
void
__tcp_close_wait(tcp_socket_t *s)
{
- BSPLOG(bsp_log("__tcp_close_wait.\n"));
- while (s->state != _CLOSED)
- __tcp_poll();
- BSPLOG(bsp_log("__tcp_close_wait done.\n"));
+ BSPLOG(bsp_log("__tcp_close_wait.\n"));
+ while (s->state != _CLOSED)
+ __tcp_poll();
+ BSPLOG(bsp_log("__tcp_close_wait done.\n"));
}
int
__tcp_read(tcp_socket_t *s, void *buf, int len)
{
- int nread;
- pktbuf_t *pkt;
- tcp_header_t *tcp;
-
- if (len <= 0 || s->rxcnt == 0)
- return 0;
-
- if (s->state != _ESTABLISHED && s->rxcnt == 0)
- return -1;
-
- nread = 0;
- while (len) {
- if (len < s->rxcnt) {
- memcpy(buf, s->rxptr, len);
- BSPLOG(bsp_log("tcp_read: read %d bytes.\n", len));
- s->rxptr += len;
- s->rxcnt -= len;
- nread += len;
+ int nread;
+ pktbuf_t *pkt;
+ tcp_header_t *tcp;
+
+ if (len <= 0 || s->rxcnt == 0)
+ return 0;
+
+ if (s->state != _ESTABLISHED && s->rxcnt == 0)
+ return -1;
+
+ nread = 0;
+ while (len) {
+ if (len < s->rxcnt) {
+ memcpy(buf, s->rxptr, len);
+ BSPLOG(bsp_log("tcp_read: read %d bytes.\n", len));
+ s->rxptr += len;
+ s->rxcnt -= len;
+ nread += len;
+
+ BSPLOG(bsp_log("tcp_read: %d bytes left in rxlist head.\n",
+ s->rxcnt));
+
+ break;
+ } else {
+ memcpy(buf, s->rxptr, s->rxcnt);
+ BSPLOG(bsp_log("tcp_read: read %d bytes. pkt[%x] freed.\n",
+ s->rxcnt, s->rxlist));
+ nread += s->rxcnt;
+ buf = (char *)buf + s->rxcnt;
+ len -= s->rxcnt;
+
+ /* setup for next packet in list */
+ pkt = s->rxlist;
+ s->rxlist = pkt->next;
+ __pktbuf_free(pkt);
+
+ if ((pkt = s->rxlist) != NULL) {
+ tcp = pkt->tcp_hdr;
+ s->rxcnt = pkt->pkt_bytes - (tcp->hdr_len << 2);
+ s->rxptr = ((char *)tcp) + (tcp->hdr_len << 2);
+
+ BSPLOG(bsp_log("tcp_read: next pkt[%x] has %d bytes.\n",
+ s->rxlist, s->rxcnt));
+ } else {
- BSPLOG(bsp_log("tcp_read: %d bytes left in rxlist head.\n",
- s->rxcnt));
+ BSPLOG(bsp_log("tcp_read: no more data.\n"));
- break;
- } else {
- memcpy(buf, s->rxptr, s->rxcnt);
- BSPLOG(bsp_log("tcp_read: read %d bytes. pkt[%x] freed.\n",
- s->rxcnt, s->rxlist));
- nread += s->rxcnt;
- buf = (char *)buf + s->rxcnt;
- len -= s->rxcnt;
-
- /* setup for next packet in list */
- pkt = s->rxlist;
- s->rxlist = pkt->next;
- __pktbuf_free(pkt);
-
- if ((pkt = s->rxlist) != NULL) {
- tcp = pkt->tcp_hdr;
- s->rxcnt = pkt->pkt_bytes - (tcp->hdr_len << 2);
- s->rxptr = ((char *)tcp) + (tcp->hdr_len << 2);
-
- BSPLOG(bsp_log("tcp_read: next pkt[%x] has %d bytes.\n",
- s->rxlist, s->rxcnt));
- } else {
-
- BSPLOG(bsp_log("tcp_read: no more data.\n"));
-
- s->rxcnt = 0;
- break;
- }
+ s->rxcnt = 0;
+ break;
+ }
+ }
}
- }
- return nread;
+ return nread;
}
int
__tcp_write(tcp_socket_t *s, void *buf, int len)
{
- tcp_header_t *tcp = s->pkt.tcp_hdr;
+ tcp_header_t *tcp = s->pkt.tcp_hdr;
- if (len <= 0)
- return 0;
+ if (len <= 0)
+ return 0;
- if (s->state != _ESTABLISHED && s->state != _CLOSE_WAIT)
- return -1;
+ if (s->state != _ESTABLISHED && s->state != _CLOSE_WAIT)
+ return -1;
- if (s->data_bytes)
- return 0;
+ if (s->data_bytes)
+ return 0;
- if (len > MAX_TCP_DATA)
- len = MAX_TCP_DATA;
+ if (len > MAX_TCP_DATA)
+ len = MAX_TCP_DATA;
- memcpy(tcp + 1, buf, len);
- s->data_bytes = len;
+ memcpy(tcp + 1, buf, len);
+ s->data_bytes = len;
- tcp_send(s, TCP_FLAG_ACK, 0);
+ tcp_send(s, TCP_FLAG_ACK, 0);
- return len;
+ return len;
}
/*
int
__tcp_write_block(tcp_socket_t *s, void *buf, int len)
{
- int total = 0;
- int n;
-
- while (len) {
- if (s->state == _CLOSE_WAIT) {
- // This connection is tring to close
- // This connection is breaking
- if (s->data_bytes == 0 && s->rxcnt == 0)
- __tcp_close(s);
- }
- if (s->state == _CLOSED) {
- // The connection is gone!
- return -1;
- }
- n = __tcp_write(s, buf, len);
- if (n > 0) {
- len -= n;
- buf = (char *)buf + n;
- total += n;
- }
- __tcp_poll();
- }
- __tcp_drain(s);
- return total;
+ int total = 0;
+ int n;
+
+ while (len) {
+ if (s->state == _CLOSE_WAIT) {
+ // This connection is tring to close
+ // This connection is breaking
+ if (s->data_bytes == 0 && s->rxcnt == 0)
+ __tcp_close(s);
+ }
+ if (s->state == _CLOSED) {
+ // The connection is gone!
+ return -1;
+ }
+ n = __tcp_write(s, buf, len);
+ if (n > 0) {
+ len -= n;
+ buf = (char *)buf + n;
+ total += n;
+ }
+ __tcp_poll();
+ }
+ __tcp_drain(s);
+ return total;
}
/*
* Establish a new [outgoing] connection, with a timeout.
*/
-int
-__tcp_open(tcp_socket_t *s, struct sockaddr_in *host,
- word port, int timeout, int *err)
+int
+__tcp_open(tcp_socket_t *s, struct sockaddr_in *host,
+ word port, int timeout, int *err)
{
- // Fill in socket details
- memset(s, 0, sizeof(tcp_socket_t));
- s->state = _SYN_SENT;
- s->our_port = port;
- s->his_port = host->sin_port;
- s->pkt.buf = (word *)s->pktbuf;
- s->pkt.bufsize = ETH_MAX_PKTLEN;
- s->pkt.ip_hdr = (ip_header_t *)s->pkt.buf;
- s->pkt.tcp_hdr = (tcp_header_t *)(s->pkt.ip_hdr + 1);
- s->seq = (port << 16) | 0xDE77;
- s->ack = 0;
- if (__arp_lookup((ip_addr_t *)&host->sin_addr, &s->his_addr) < 0) {
- diag_printf("%s: Can't find address of server\n", __FUNCTION__);
- return -1;
- }
- s->next = tcp_list;
- tcp_list = s;
-
- // Send off the SYN packet to open the connection
- tcp_send(s, TCP_FLAG_SYN, 0);
- // Wait for connection to establish
- while (s->state != _ESTABLISHED) {
- if (s->state == _CLOSED) {
- diag_printf("TCP open - host closed connection\n");
- return -1;
- }
- if (--timeout <= 0) {
- diag_printf("TCP open - connection timed out\n");
- return -1;
- }
- MS_TICKS_DELAY();
- __tcp_poll();
- }
- return 0;
+ // Fill in socket details
+ memset(s, 0, sizeof(tcp_socket_t));
+ s->state = _SYN_SENT;
+ s->our_port = port;
+ s->his_port = host->sin_port;
+ s->pkt.buf = (word *)s->pktbuf;
+ s->pkt.bufsize = ETH_MAX_PKTLEN;
+ s->pkt.ip_hdr = (ip_header_t *)s->pkt.buf;
+ s->pkt.tcp_hdr = (tcp_header_t *)(s->pkt.ip_hdr + 1);
+ s->seq = (port << 16) | 0xDE77;
+ s->ack = 0;
+ if (__arp_lookup((ip_addr_t *)&host->sin_addr, &s->his_addr) < 0) {
+ diag_printf("%s: Can't find address of server\n", __FUNCTION__);
+ return -1;
+ }
+ s->next = tcp_list;
+ tcp_list = s;
+
+ // Send off the SYN packet to open the connection
+ tcp_send(s, TCP_FLAG_SYN, 0);
+ // Wait for connection to establish
+ while (s->state != _ESTABLISHED) {
+ if (s->state == _CLOSED) {
+ diag_printf("TCP open - host closed connection\n");
+ return -1;
+ }
+ if (--timeout <= 0) {
+ diag_printf("TCP open - connection timed out\n");
+ return -1;
+ }
+ MS_TICKS_DELAY();
+ __tcp_poll();
+ }
+ return 0;
}
-
-