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

📄 tcp.c

📁 minux的源代码,一个非常小的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
ipaddr_t remaddr;
{
	tcp_conn_t *tcp_conn;
	int i, state;

#if DEBUG & 256
 { where(); printf("find_conn_entry(locport= %u, locaddr= ", ntohs(locport)); 
	writeIpAddr(locaddr);
	printf("\nremport= %u, remaddr= ", ntohs(remport));
	writeIpAddr(remaddr); printf(")\n"); }
#endif
assert(remport);
assert(remaddr);
	for (i=TCP_PORT_NR, tcp_conn= tcp_conn_table+i; i<TCP_CONN_NR;
		i++, tcp_conn++)
		/* the first TCP_PORT_NR connection are reserved for
			RSTs */
	{
		if (tcp_conn->tc_flags == TCF_EMPTY)
			continue;
		if (tcp_conn->tc_locport != locport ||
			tcp_conn->tc_locaddr != locaddr ||
			tcp_conn->tc_remport != remport ||
			tcp_conn->tc_remaddr != remaddr)
			continue;
		if (tcp_conn->tc_mainuser)
			return tcp_conn;
		state= tcp_conn->tc_state;
		if (state != TCS_CLOSED)
		{
			tcp_close_connection(tcp_conn, ENOCONN);
		}
		return tcp_conn;
	}
	return NULL;
}

PRIVATE void read_ip_packets(tcp_port)
tcp_port_t *tcp_port;
{
	int result;

	do
	{
		tcp_port->tp_flags |= TPF_READ_IP;
#if DEBUG & 256
 { where(); printf("doing ip_read\n"); }
#endif
		result= ip_read(tcp_port->tp_ipfd, TCP_MAX_DATAGRAM);
		if (result == NW_SUSPEND)
		{
			tcp_port->tp_flags |= TPF_READ_SP;
			return;
		}
assert(result == NW_OK);
		tcp_port->tp_flags &= ~TPF_READ_IP;
	} while(!(tcp_port->tp_flags & TPF_READ_IP));
}

/*
process_inc_fragm
*/

PRIVATE void process_inc_fragm(tcp_port, data)
tcp_port_t *tcp_port;
acc_t *data;
{
	acc_t *ip_pack, *tcp_pack;
	ip_hdr_t *ip_hdr;
	tcp_hdr_t *tcp_hdr;
	tcp_conn_t *tcp_conn;
	int pack_len, ip_hdr_len;

	pack_len= bf_bufsize(data);
	if ((u16_t)~tcp_pack_oneCsum(data, pack_len))
	{
		data= bf_packIffLess(data, IP_MIN_HDR_SIZE);
		ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
#if DEBUG
 { where(); printf("checksum error in tcp_pack\n");
   printf("tcp_pack_oneCsum(...)= 0x%x (%d) length= %d\n", 
    (u16_t)~tcp_pack_oneCsum(data, pack_len),
    (u16_t)~tcp_pack_oneCsum(data, pack_len), pack_len);
    printf("src ip_addr= "); writeIpAddr(ip_hdr->ih_src); printf("\n"); }
#endif
		bf_afree(data);
		return;
	}

	data= bf_packIffLess(data, IP_MIN_HDR_SIZE);
	ip_hdr= (ip_hdr_t *)ptr2acc_data(data);
	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
	ip_pack= bf_cut(data, 0, ip_hdr_len);

	pack_len -= ip_hdr_len;

	tcp_pack= bf_cut(data, ip_hdr_len, pack_len);
	bf_afree(data);

	tcp_pack= bf_packIffLess(tcp_pack, TCP_MIN_HDR_SIZE);
	tcp_hdr= (tcp_hdr_t *)ptr2acc_data(tcp_pack);

	tcp_conn= find_best_conn(ip_hdr, tcp_hdr);
assert(tcp_conn);
#if DEBUG & 256
 { where(); tcp_print_pack(ip_hdr, tcp_hdr); printf("\n");
   tcp_print_conn(tcp_conn); printf("\n"); }
#endif

	tcp_hdr->th_chksum= pack_len;	/* tcp_pack size in chksum field */
#if DEBUG & 256
 { where(); printf("calling tcp_frag2conn(...)\n"); }
#endif
	tcp_frag2conn(tcp_conn, ip_pack, tcp_pack);
}

/*
find_best_conn
*/

PRIVATE tcp_conn_t *find_best_conn(ip_hdr, tcp_hdr)
ip_hdr_t *ip_hdr;
tcp_hdr_t *tcp_hdr;
{
	
	int best_level, new_level;
	tcp_conn_t *best_conn, *listen_conn, *tcp_conn;
	tcp_fd_t *tcp_fd;
	int i;
	ipaddr_t locaddr;
	ipaddr_t remaddr;
	tcpport_t locport;
	tcpport_t remport;

	locaddr= ip_hdr->ih_dst;
	remaddr= ip_hdr->ih_src;
	locport= tcp_hdr->th_dstport;
	remport= tcp_hdr->th_srcport;
	if (!remport)	/* This can interfere with a listen, so we reject it
			 * by clearing the requested port 
			 */
		locport= 0;
		
#if DEBUG & 256
 { where(); printf("find_best_conn(locport= %u, locaddr= ",
	ntohs(locport)); writeIpAddr(locaddr);
	printf("\nremport= %u, remaddr= ", ntohs(remport));
	writeIpAddr(remaddr); printf(")\n"); }
#endif
	best_level= 0;
	best_conn= NULL;
	listen_conn= NULL;
	for (i= TCP_PORT_NR, tcp_conn= tcp_conn_table+i;
		i<TCP_CONN_NR; i++, tcp_conn++)
		/* the first TCP_PORT_NR connection are reserved for
			RSTs */
	{
		if (!(tcp_conn->tc_flags & TCF_INUSE))
			continue;
		/* First fast check for open connections. */
		if (tcp_conn->tc_locaddr == locaddr && 
			tcp_conn->tc_locport == locport &&
			tcp_conn->tc_remport == remport &&
			tcp_conn->tc_remaddr == remaddr &&
			tcp_conn->tc_mainuser)
			return tcp_conn;

		/* Now check for listens and abandoned connections. */
		if (tcp_conn->tc_locaddr != locaddr)
		{
#if DEBUG
 { where(); printf("conn %d: wrong locaddr\n",i); }
#endif
			continue;
		}
		new_level= 0;
		if (tcp_conn->tc_locport)
		{
			if (locport != tcp_conn->tc_locport)
			{
#if DEBUG & 256
 { where(); printf("conn %d: wrong locport(%u)\n",i,
	ntohs(tcp_conn->tc_locport)); }
#endif
				continue;
			}
			new_level += 4;
		}
		if (tcp_conn->tc_remport)
		{
			if (remport != tcp_conn->tc_remport)
			{
#if DEBUG & 256
 { where(); printf("conn %d: wrong remport\n",i); }
#endif
				continue;
			}
			new_level += 1;
		}
		if (tcp_conn->tc_remaddr)
		{
			if (remaddr != tcp_conn->tc_remaddr)
			{
#if DEBUG & 256
 { where(); printf("conn %d: wrong remaddr\n",i); }
#endif
				continue;
			}
			new_level += 2;
		}
		if (new_level<best_level)
			continue;
		if (new_level != 7 && tcp_conn->tc_state != TCS_LISTEN)
			continue;
		if (new_level == 7 && !tcp_conn->tc_mainuser)
			/* We found an abandoned connection */
		{
assert (!best_conn);
			best_conn= tcp_conn;
			continue;
		}
		if (!(tcp_hdr->th_flags & THF_SYN))
			continue;
		best_level= new_level;
		listen_conn= tcp_conn;
	}
	if (!best_conn && !listen_conn)
	{
#if DEBUG & 256
 { where(); printf("refusing connection for locport= %u, locaddr= ",
	ntohs(locport)); writeIpAddr(locaddr);
	printf("\nremport= %u, remaddr= ", ntohs(remport));
	writeIpAddr(remaddr); printf("\n"); }
#endif
		for (i=0, tcp_conn= tcp_conn_table; i<TCP_PORT_NR;
			i++, tcp_conn++)
			/* find valid port to send RST */
			if ((tcp_conn->tc_flags & TCF_INUSE) &&
				tcp_conn->tc_locaddr==locaddr)
			{
				break;
			}
assert (tcp_conn);
assert (tcp_conn->tc_state == TCS_CLOSED);
		tcp_conn->tc_locport= locport;
		tcp_conn->tc_locaddr= locaddr;
		tcp_conn->tc_remport= remport;
		tcp_conn->tc_remaddr= remaddr;
assert (!tcp_conn->tc_mainuser);
assert (!tcp_conn->tc_readuser);
assert (!tcp_conn->tc_writeuser);
		return tcp_conn;

	}
	if (best_conn)
	{
assert(!best_conn->tc_mainuser);
		if (!listen_conn)
			return best_conn;
		tcp_fd= listen_conn->tc_mainuser;

assert(tcp_fd && tcp_fd == listen_conn->tc_connuser &&
	tcp_fd->tf_conn == listen_conn);

		if (best_conn->tc_state != TCS_CLOSED)
			tcp_close_connection(best_conn, ENOCONN);
		best_conn->tc_state= TCS_LISTEN;
#if DEBUG
 { where(); tcp_write_state(best_conn); }
#endif
		best_conn->tc_mainuser= best_conn->tc_connuser=
			tcp_fd;
		best_conn->tc_flags= listen_conn->tc_flags;
		tcp_fd->tf_conn= best_conn;
		listen_conn->tc_flags= TCF_EMPTY;
#if DEBUG & 16
 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", 
	listen_conn-tcp_conn_table, listen_conn->tc_flags); }
#endif
		return best_conn;
	}
assert (listen_conn);
	return listen_conn;
}


PUBLIC void tcp_reply_ioctl(tcp_fd, reply)
tcp_fd_t *tcp_fd;
int reply;
{
#if DEBUG & 256
 { where(); printf("tcp_reply_ioctl called\n"); }
#endif
#if DEBUG
 if (!(tcp_fd->tf_flags & TFF_IOCTL_IP))
 { where(); printf("not TFF_IOCTL_IP\n"); }
#endif
assert (tcp_fd->tf_flags & TFF_IOCTL_IP);
#if DEBUG
if (tcp_fd->tf_ioreq != NWIOTCPSHUTDOWN && tcp_fd->tf_ioreq != NWIOTCPLISTEN &&
	tcp_fd->tf_ioreq != NWIOTCPCONN)
 { where(); printf("wrong value in ioreq (0x%lx)\n", tcp_fd->tf_ioreq); }
#endif
assert (tcp_fd->tf_ioreq == NWIOTCPSHUTDOWN ||
	tcp_fd->tf_ioreq == NWIOTCPLISTEN || tcp_fd->tf_ioreq == NWIOTCPCONN);
	
	tcp_fd->tf_flags &= ~TFF_IOCTL_IP;
	reply_thr_get (tcp_fd, reply, TRUE);
}

PUBLIC void tcp_reply_write(tcp_fd, reply)
tcp_fd_t *tcp_fd;
size_t reply;
{
	assert (tcp_fd->tf_flags & TFF_WRITE_IP);

	tcp_fd->tf_flags &= ~TFF_WRITE_IP;
	reply_thr_get (tcp_fd, reply, FALSE);
}

PUBLIC void tcp_reply_read(tcp_fd, reply)
tcp_fd_t *tcp_fd;
size_t reply;
{
	assert (tcp_fd->tf_flags & TFF_READ_IP);

#if DEBUG & 256
 { where(); printf("tcp_reply_read(.., %d)\n", reply); }
#endif
	tcp_fd->tf_flags &= ~TFF_READ_IP;
	reply_thr_put (tcp_fd, reply, FALSE);
}

PUBLIC int tcp_write(fd, count)
int fd;
size_t count;
{
	tcp_fd_t *tcp_fd;
	tcp_conn_t *tcp_conn;

	tcp_fd= &tcp_fd_table[fd];

	assert (tcp_fd->tf_flags & TFF_INUSE);

	if (!(tcp_fd->tf_flags & TFF_CONNECTED))
	{
		reply_thr_get (tcp_fd, ENOTCONN, FALSE);
		return NW_OK;
	}
	tcp_conn= tcp_fd->tf_conn;
	if (tcp_conn->tc_flags & TCF_FIN_SENT)
	{
#if DEBUG & 16
 { where(); printf("replying ESHUTDOWN for connection %d and fd %d\n",
	tcp_conn-tcp_conn_table, tcp_fd-tcp_fd_table); }
#endif
		reply_thr_get (tcp_fd, ESHUTDOWN, FALSE);
		return NW_OK;
	}

	tcp_fd->tf_flags |= TFF_WRITE_IP;
	tcp_fd->tf_write_offset= 0;
	tcp_fd->tf_write_count= count;

	if (tcp_conn->tc_writeuser)
		return NW_SUSPEND;

	tcp_conn->tc_writeuser= tcp_fd;
	tcp_restart_fd_write (tcp_conn);
	if (!(tcp_fd->tf_flags & TFF_WRITE_IP))
		return NW_OK;
	else
		return NW_SUSPEND;
}

PUBLIC int tcp_read(fd, count)
int fd;
size_t count;
{
	tcp_fd_t *tcp_fd;
	tcp_conn_t *tcp_conn;

#if DEBUG & 256
 { where(); printf("tcp_read(%d, %u)\n", fd, count); }
#endif
	tcp_fd= &tcp_fd_table[fd];

	assert (tcp_fd->tf_flags & TFF_INUSE);

	if (!(tcp_fd->tf_flags & TFF_CONNECTED))
	{
		reply_thr_put (tcp_fd, ENOTCONN, FALSE);
		return NW_OK;
	}
	tcp_conn= tcp_fd->tf_conn;

	tcp_fd->tf_flags |= TFF_READ_IP;
	tcp_fd->tf_read_offset= 0;
	tcp_fd->tf_read_count= count;

	if (tcp_conn->tc_readuser)
		return NW_SUSPEND;

	tcp_conn->tc_readuser= tcp_fd;
	tcp_restart_fd_read (tcp_conn);
	if (!(tcp_fd->tf_flags & TFF_READ_IP))
		return NW_OK;
	else
		return NW_SUSPEND;
}

/*
tcp_restart_connect

reply the success or failure of a connect to the user.
*/


PUBLIC void tcp_restart_connect(tcp_fd)
tcp_fd_t *tcp_fd;
{
	tcp_conn_t *tcp_conn;
	int reply;

#if DEBUG & 256
 { where(); printf("tcp_restart_connect called\n"); }
#endif
assert (tcp_fd->tf_flags & TFF_IOCTL_IP);
assert (tcp_fd->tf_ioreq == NWIOTCPLISTEN || tcp_fd->tf_ioreq == NWIOTCPCONN);

	tcp_conn= tcp_fd->tf_conn;

assert (tcp_conn->tc_connuser == tcp_fd);

	if (tcp_conn->tc_state == TCS_CLOSED)
		reply= tcp_conn->tc_error;
	else
	{
		tcp_fd->tf_flags |= TFF_CONNECTED;
		reply= NW_OK;
	}
	tcp_conn->tc_connuser= 0;
#if DEBUG & 256
 { where(); printf("tcp_conn_table[%d].tc_connuser= 0x%x\n", tcp_conn-
	tcp_conn_table, tcp_conn->tc_connuser); }
#endif
	tcp_reply_ioctl (tcp_fd, reply);
}

PUBLIC void tcp_close(fd)
int fd;
{
	tcp_fd_t *tcp_fd;
	tcp_conn_t *tcp_conn;

	tcp_fd= &tcp_fd_table[fd];

#if DEBUG
 { if (!(tcp_fd->tf_flags & TFF_INUSE)) { where(); printf("not inuse\n"); }
   if (tcp_fd->tf_flags & TFF_IOCTL_IP) { where(); printf("ioctl ip\n"); }
   if (tcp_fd->tf_flags & TFF_READ_IP) { where(); printf("read ip\n"); }
   if (tcp_fd->tf_flags & TFF_WRITE_IP) { where(); printf("write ip\n"); }
 }
#endif
assert (tcp_fd->tf_flags & TFF_INUSE);
assert (!(tcp_fd->tf_flags & (TFF_IOCTL_IP|TFF_READ_IP|TFF_WRITE_IP)));

	tcp_fd->tf_flags &= ~TFF_INUSE;
	if (!tcp_fd->tf_conn)
		return;

	tcp_conn= tcp_fd->tf_conn;
	close_mainuser(tcp_conn, tcp_fd);
	tcp_shutdown (tcp_conn);
}

PUBLIC int tcp_cancel(fd, which_operation)
int fd;
int which_operation;
{
	tcp_fd_t *tcp_fd;
	tcp_conn_t *tcp_conn;
	int i;
	int type;

#if DEBUG & 256
 { where(); printf("tcp_cancel(%d, %d)\n", fd, which_operation); }
#endif
	tcp_fd= &tcp_fd_table[fd];

	assert (tcp_fd->tf_flags & TFF_INUSE);

	tcp_conn= tcp_fd->tf_conn;

	switch (which_operation)
	{
	case SR_CANCEL_WRITE:
assert (tcp_fd->tf_flags & TFF_WRITE_IP);
		tcp_fd->tf_flags &= ~TFF_WRITE_IP;
		if (tcp_conn->tc_writeuser == tcp_fd)
		{
			tcp_conn->tc_writeuser= 0;
			tcp_restart_fd_write (tcp_conn);
		}
		if (tcp_fd->tf_write_count)
			reply_thr_get (tcp_fd, tcp_fd->tf_write_count, FALSE);
		else
			reply_thr_get (tcp_fd, EINTR, FALSE);

⌨️ 快捷键说明

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