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

📄 socket.c

📁 一个Windows下的Linux专用虚拟机
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1995 Danny Gasparovski. *  * Please read the file COPYRIGHT for the  * terms and conditions of the copyright. */#define WANT_SYS_IOCTL_H#include "slirp.h"#include "ip_icmp.h"#include "main.h"voidso_init(){	/* Nothing yet */}struct socket *solookup(head, laddr, lport, faddr, fport)	struct socket *head;	struct in_addr laddr;	u_int lport;	struct in_addr faddr;	u_int fport;{	struct socket *so;		for (so = head->so_next; so != head; so = so->so_next) {		if (so->so_lport == lport && 		    so->so_laddr.s_addr == laddr.s_addr &&		    so->so_faddr.s_addr == faddr.s_addr &&		    so->so_fport == fport)		   break;	}		if (so == head)	   return (struct socket *)NULL;	return so;	}/* * Create a new socket, initialise the fields * It is the responsibility of the caller to * insque() it into the correct linked-list */struct socket *socreate(){  struct socket *so;	  so = (struct socket *)malloc(sizeof(struct socket));  if(so) {    memset(so, 0, sizeof(struct socket));    so->so_state = SS_NOFDREF;    so->s = -1;  }  return(so);}/* * remque and free a socket, clobber cache */voidsofree(so)	struct socket *so;{  if (so->so_emu==EMU_RSH && so->extra) {	sofree(so->extra);	so->extra=NULL;  }  if (so == tcp_last_so)    tcp_last_so = &tcb;  else if (so == udp_last_so)    udp_last_so = &udb;	  m_free(so->so_m);	  if(so->so_next && so->so_prev)     remque(so);  /* crashes if so is not in a queue */  free(so);}/* * Read from so's socket into sb_snd, updating all relevant sbuf fields * NOTE: This will only be called if it is select()ed for reading, so * a read() of 0 (or less) means it's disconnected */intsoread(so)	struct socket *so;{	int n, nn, lss, total;	struct sbuf *sb = &so->so_snd;	int len = sb->sb_datalen - sb->sb_cc;	struct iovec iov[2] = { {0}, };	int mss = so->so_tcpcb->t_maxseg;		DEBUG_CALL("soread");	DEBUG_ARG("so = %lx", (long )so);		/* 	 * No need to check if there's enough room to read.	 * soread wouldn't have been called if there weren't	 */		len = sb->sb_datalen - sb->sb_cc;		iov[0].iov_base = sb->sb_wptr;	if (sb->sb_wptr < sb->sb_rptr) {		iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;		/* Should never succeed, but... */		if (iov[0].iov_len > len)		   iov[0].iov_len = len;		if (iov[0].iov_len > mss)		   iov[0].iov_len -= iov[0].iov_len%mss;		n = 1;	} else {		iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr;		/* Should never succeed, but... */		if (iov[0].iov_len > len) iov[0].iov_len = len;		len -= iov[0].iov_len;		if (len) {			iov[1].iov_base = sb->sb_data;			iov[1].iov_len = sb->sb_rptr - sb->sb_data;			if(iov[1].iov_len > len)			   iov[1].iov_len = len;			total = iov[0].iov_len + iov[1].iov_len;			if (total > mss) {				lss = total%mss;				if (iov[1].iov_len > lss) {					iov[1].iov_len -= lss;					n = 2;				} else {					lss -= iov[1].iov_len;					iov[0].iov_len -= lss;					n = 1;				}			} else				n = 2;		} else {			if (iov[0].iov_len > mss)			   iov[0].iov_len -= iov[0].iov_len%mss;			n = 1;		}	}	#ifdef HAVE_READV	nn = readv(so->s, (struct iovec *)iov, n);	DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));#else	nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);#endif		if (nn <= 0) {		if (nn < 0 && (errno == EINTR || errno == EAGAIN))			return 0;		else {			DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));			sofcantrcvmore(so);			tcp_sockclosed(sototcpcb(so));			return -1;		}	}	#ifndef HAVE_READV	/*	 * If there was no error, try and read the second time round	 * We read again if n = 2 (ie, there's another part of the buffer)	 * and we read as much as we could in the first read	 * We don't test for <= 0 this time, because there legitimately	 * might not be any more data (since the socket is non-blocking),	 * a close will be detected on next iteration.	 * A return of -1 wont (shouldn't) happen, since it didn't happen above	 *	 * Dan Aloni says: actually it can return -1 here...	 */	if (n == 2 && nn == iov[0].iov_len) {            int ret;            ret = recv(so->s, iov[1].iov_base, iov[1].iov_len,0);            if (ret > 0)                nn += ret;        }		DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));#endif		/* Update fields */	sb->sb_cc += nn;	sb->sb_wptr += nn;	if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))		sb->sb_wptr -= sb->sb_datalen;	return nn;}	/* * Get urgent data *  * When the socket is created, we set it SO_OOBINLINE, * so when OOB data arrives, we soread() it and everything * in the send buffer is sent as urgent data */voidsorecvoob(so)	struct socket *so;{	struct tcpcb *tp = sototcpcb(so);	DEBUG_CALL("sorecvoob");	DEBUG_ARG("so = %lx", (long)so);		/*	 * We take a guess at how much urgent data has arrived.	 * In most situations, when urgent data arrives, the next	 * read() should get all the urgent data.  This guess will	 * be wrong however if more data arrives just after the	 * urgent data, or the read() doesn't return all the 	 * urgent data.	 */	soread(so);	tp->snd_up = tp->snd_una + so->so_snd.sb_cc;	tp->t_force = 1;	tcp_output(tp);	tp->t_force = 0;}/* * Send urgent data * There's a lot duplicated code here, but... */intsosendoob(so)	struct socket *so;{	struct sbuf *sb = &so->so_rcv;	char buff[2048]; /* XXX Shouldn't be sending more oob data than this */		int n, len;		DEBUG_CALL("sosendoob");	DEBUG_ARG("so = %lx", (long)so);	DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);		if (so->so_urgc > 2048)	   so->so_urgc = 2048; /* XXXX */		if (sb->sb_rptr < sb->sb_wptr) {		/* We can send it directly */		n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */		so->so_urgc -= n;				DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));	} else {		/* 		 * Since there's no sendv or sendtov like writev,		 * we must copy all data to a linear buffer then		 * send it all		 */		len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;		if (len > so->so_urgc) len = so->so_urgc;		memcpy(buff, sb->sb_rptr, len);		so->so_urgc -= len;		if (so->so_urgc) {			n = sb->sb_wptr - sb->sb_data;			if (n > so->so_urgc) n = so->so_urgc;			memcpy((buff + len), sb->sb_data, n);			so->so_urgc -= n;			len += n;		}		n = send(so->s, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */#ifdef DEBUG		if (n != len)		   DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));#endif				DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));	}		sb->sb_cc -= n;	sb->sb_rptr += n;	if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))		sb->sb_rptr -= sb->sb_datalen;		return n;}/* * Write data from so_rcv to so's socket,  * updating all sbuf field as necessary */intsowrite(so)	struct socket *so;{	int  n,nn;	struct sbuf *sb = &so->so_rcv;	int len = sb->sb_cc;	struct iovec iov[2] = { {0}, };		DEBUG_CALL("sowrite");	DEBUG_ARG("so = %lx", (long)so);		if (so->so_urgc) {		sosendoob(so);		if (sb->sb_cc == 0)			return 0;	}	/*	 * No need to check if there's something to write,	 * sowrite wouldn't have been called otherwise	 */	        len = sb->sb_cc;		iov[0].iov_base = sb->sb_rptr;	if (sb->sb_rptr < sb->sb_wptr) {		iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;		/* Should never succeed, but... */		if (iov[0].iov_len > len) iov[0].iov_len = len;		n = 1;	} else {		iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;		if (iov[0].iov_len > len) iov[0].iov_len = len;		len -= iov[0].iov_len;		if (len) {			iov[1].iov_base = sb->sb_data;			iov[1].iov_len = sb->sb_wptr - sb->sb_data;			if (iov[1].iov_len > len) iov[1].iov_len = len;			n = 2;		} else			n = 1;	}	/* Check if there's urgent data to send, and if so, send it */#ifdef HAVE_READV	nn = writev(so->s, (const struct iovec *)iov, n);		DEBUG_MISC((dfd, "  ... wrote nn = %d bytes\n", nn));#else	nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0);#endif	/* This should never happen, but people tell me it does *shrug* */	if (nn < 0 && (errno == EAGAIN || errno == EINTR))		return 0;		if (nn <= 0) {		DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",			so->so_state, errno));		sofcantsendmore(so);		tcp_sockclosed(sototcpcb(so));		return -1;	}	#ifndef HAVE_READV	if (n == 2 && nn == iov[0].iov_len) {            int ret;            ret = send(so->s, iov[1].iov_base, iov[1].iov_len,0);            if (ret > 0)                nn += ret;        }        DEBUG_MISC((dfd, "  ... wrote nn = %d bytes\n", nn));#endif		/* Update sbuf */	sb->sb_cc -= nn;

⌨️ 快捷键说明

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