⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp.c

📁 Intel XScale PXA255 引导Linux的Redboot 版bootloader源代码!
💻 C
📖 第 1 页 / 共 2 页
字号:
    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 */		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;		    s->ack_pending = 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 || s->ack_pending) {		    /*		     * we can't send an ack if our write packet is holding outgoing		     * data pending an incoming ack.		     */		    if (s->data_bytes == 0) {			BSPLOG(bsp_log("Sending ack: new[%x] old[%x]\n", s->ack, ack));			__timer_cancel(&s->timer);			tcp_send(s, TCP_FLAG_ACK, 0);			s->ack_pending = 0;		    } else			s->ack_pending = 1;		}		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 */			if (tcp->flags & TCP_FLAG_FIN) {			    BSPLOG(bsp_log("_FIN_WAIT_1 --> _TIME_WAIT\n"));			    s->ack++;			    s->state = _TIME_WAIT;			    tcp_send(s, TCP_FLAG_ACK, 0);			} else {			    s->state = _FIN_WAIT_2;			    BSPLOG(bsp_log("_FIN_WAIT_1 --> _FIN_WAIT_2\n"));			}		    }		}		if (tcp->flags & TCP_FLAG_FIN) {		    BSPLOG(bsp_log("_FIN_WAIT_1 --> _CLOSING\n"));		    __timer_cancel(&s->timer);		    s->ack++;		    s->state = _CLOSING;		    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;		    tcp_send(s, TCP_FLAG_ACK, 0);		}		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"));		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);}void__tcp_poll(void){    __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));    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;#if 0    s->pkt.eth_hdr = (eth_header_t *)s->pkt.buf;    s->pkt.ip_hdr  = (ip_header_t *)(s->pkt.eth_hdr + 1);#else    s->pkt.ip_hdr  = (ip_header_t *)s->pkt.buf;#endif    s->pkt.tcp_hdr = (tcp_header_t *)(s->pkt.ip_hdr + 1);    s->next = tcp_list;#if 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;}/* * Block while waiting for all data to be transmitted. */void__tcp_drain(tcp_socket_t *s){    BSPLOG(bsp_log("__tcp_drain.\n"));    while (s->state != _CLOSED && s->data_bytes)			__tcp_poll();    BSPLOG(bsp_log("__tcp_drain done.\n"));}/* * Close the tcp connection. */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);}/* * Wait for connection to be fully closed. */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"));}/* * Read up to 'len' bytes without blocking. */int__tcp_read(tcp_socket_t *s, char *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;	    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   += 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;	    }	}    }    return nread;}int__tcp_write(tcp_socket_t *s, char *buf, int len){    tcp_header_t *tcp = s->pkt.tcp_hdr;    if (len <= 0)	return 0;    if (s->state != _ESTABLISHED && s->state != _CLOSE_WAIT)	return -1;    if (s->data_bytes)	return 0;    if (len > MAX_TCP_DATA)	len = MAX_TCP_DATA;    memcpy(tcp + 1, buf, len);    s->data_bytes = len;    tcp_send(s, TCP_FLAG_ACK, 0);    return len;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -