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

📄 socket.c

📁 一个Windows下的Linux专用虚拟机
💻 C
📖 第 1 页 / 共 2 页
字号:
	sb->sb_rptr += nn;	if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))		sb->sb_rptr -= sb->sb_datalen;		/*	 * If in DRAIN mode, and there's no more data, set	 * it CANTSENDMORE	 */	if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)		sofcantsendmore(so);		return nn;}/* * recvfrom() a UDP socket */voidsorecvfrom(so)	struct socket *so;{	struct sockaddr_in addr;	socklen_t addrlen = sizeof(struct sockaddr_in);		DEBUG_CALL("sorecvfrom");	DEBUG_ARG("so = %lx", (long)so);		if (so->so_type == IPPROTO_ICMP) {   /* This is a "ping" reply */	  char buff[256];	  int len;			  len = recvfrom(so->s, buff, 256, 0, 			 (struct sockaddr *)&addr, &addrlen);	  /* XXX Check if reply is "correct"? */#ifdef WSAECONNRESET	  /*	   * WSAECONNRESET: Connection reset by peer. An existing	   * connection was forcibly closed by the remote host	   * WIN32: Connection is closed after "ping" replay.	   * Hack: It's not an error, it's good response here.	   */          if (len == -1 && errno == WSAECONNRESET) {	    icmp_reflect(so->so_m);	    so->so_m = 0; /* Don't m_free() it again! */	  } else#endif	  if(len == -1 || len == 0) {	    u_char code=ICMP_UNREACH_PORT;	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;	    	    DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",			errno,strerror(errno)));	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));	  } else {	    icmp_reflect(so->so_m);	    so->so_m = 0; /* Don't m_free() it again! */	  }	  /* No need for this socket anymore, udp_detach it */	  udp_detach(so);	} else {                            	/* A "normal" UDP packet */	  struct mbuf *m;	  int len;	  unsigned long n;	  if (!(m = m_get())) return;	  m->m_data += if_maxlinkhdr;			  /* 	   * XXX Shouldn't FIONREAD packets destined for port 53,	   * but I don't know the max packet size for DNS lookups	   */	  len = M_FREEROOM(m);	  /* if (so->so_fport != htons(53)) { */	  ioctlsocket(so->s, FIONREAD, &n);	  	  if (n > len) {	    n = (m->m_data - m->m_dat) + m->m_len + n + 1;	    m_inc(m, n);	    len = M_FREEROOM(m);	  }	  /* } */			  m->m_len = recvfrom(so->s, m->m_data, len, 0,			      (struct sockaddr *)&addr, &addrlen);	  DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n", 		      m->m_len, errno,strerror(errno)));	  if(m->m_len<0) {	    u_char code=ICMP_UNREACH_PORT;	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;	    	    DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));	    m_free(m);	  } else {	  /*	   * Hack: domain name lookup will be used the most for UDP,	   * and since they'll only be used once there's no need	   * for the 4 minute (or whatever) timeout... So we time them	   * out much quicker (10 seconds  for now...)	   */	    if (so->so_expire) {	      if (so->so_fport == htons(53))		so->so_expire = curtime + SO_EXPIREFAST;	      else		so->so_expire = curtime + SO_EXPIRE;	    }	    /*		if (m->m_len == len) {	     *			m_inc(m, MINCSIZE);	     *			m->m_len = 0;	     *		}	     */	    	    /* 	     * If this packet was destined for CTL_ADDR,	     * make it look like that's where it came from, done by udp_output	     */	    udp_output(so, m, &addr);	  } /* rx error */	} /* if ping packet */}/* * sendto() a socket */intsosendto(so, m)	struct socket *so;	struct mbuf *m;{	int ret;	struct sockaddr_in addr;	DEBUG_CALL("sosendto");	DEBUG_ARG("so = %lx", (long)so);	DEBUG_ARG("m = %lx", (long)m);	        addr.sin_family = AF_INET;	if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {	  /* It's an alias */	  switch(ntohl(so->so_faddr.s_addr) & 0xff) {	  case CTL_DNS:	    addr.sin_addr = cached_dns_addr();	    break;	  case CTL_ALIAS:	  default:	    addr.sin_addr = loopback_addr;	    break;	  }	} else	  addr.sin_addr = so->so_faddr;	addr.sin_port = so->so_fport;	DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));		/* Don't care what port we get */	ret = sendto(so->s, m->m_data, m->m_len, 0,		     (struct sockaddr *)&addr, sizeof (struct sockaddr));	if (ret < 0)		return -1;		/*	 * Kill the socket if there's no reply in 4 minutes,	 * but only if it's an expirable socket	 */	if (so->so_expire)		so->so_expire = curtime + SO_EXPIRE;	so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */	return 0;}/* * XXX This should really be tcp_listen */struct socket *solisten(port, laddr, lport, flags)	u_int port;	u_int32_t laddr;	u_int lport;	int flags;{	struct sockaddr_in addr;	struct socket *so;	socklen_t addrlen = sizeof(addr);	int s, opt = 1;	DEBUG_CALL("solisten");	DEBUG_ARG("port = %d", port);	DEBUG_ARG("laddr = %x", laddr);	DEBUG_ARG("lport = %d", lport);	DEBUG_ARG("flags = %x", flags);		if ((so = socreate()) == NULL) {	  /* free(so);      Not sofree() ??? free(NULL) == NOP */	  return NULL;	}		/* Don't tcp_attach... we don't need so_snd nor so_rcv */	if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {		free(so);		return NULL;	}	insque(so,&tcb);		/* 	 * SS_FACCEPTONCE sockets must time out.	 */	if (flags & SS_FACCEPTONCE)	   so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;		so->so_state = (SS_FACCEPTCONN|flags);	so->so_lport = lport; /* Kept in network format */	so->so_laddr.s_addr = laddr; /* Ditto */	addr.sin_family = AF_INET;	addr.sin_addr.s_addr = INADDR_ANY;	addr.sin_port = port;		if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||	    (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||	    (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||	    (listen(s,1) < 0)) {		int tmperrno = errno; /* Don't clobber the real reason we failed */				close(s);		sofree(so);		/* Restore the real errno */#ifdef _WIN32		WSASetLastError(tmperrno);#else		errno = tmperrno;#endif		return NULL;	}	setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));		getsockname(s,(struct sockaddr *)&addr,&addrlen);	so->so_fport = addr.sin_port;	/* Translate connections from localhost to the alias hostname */	if (is_localhost(addr.sin_addr))	   so->so_faddr = alias_addr;	else	   so->so_faddr = addr.sin_addr;	so->s = s;	return so;}/*  * Data is available in so_rcv * Just write() the data to the socket * XXX not yet... */voidsorwakeup(so)	struct socket *so;{/*	sowrite(so); *//*	FD_CLR(so->s,&writefds); */}	/* * Data has been freed in so_snd * We have room for a read() if we want to * For now, don't read, it'll be done in the main loop */voidsowwakeup(so)	struct socket *so;{	/* Nothing, yet */}/* * Various session state calls * XXX Should be #define's * The socket state stuff needs work, these often get call 2 or 3 * times each when only 1 was needed */voidsoisfconnecting(so)	register struct socket *so;{	so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE|			  SS_FCANTSENDMORE|SS_FWDRAIN);	so->so_state |= SS_ISFCONNECTING; /* Clobber other states */}voidsoisfconnected(so)        register struct socket *so;{	so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF);	so->so_state |= SS_ISFCONNECTED; /* Clobber other states */}voidsofcantrcvmore(so)	struct  socket *so;{	if ((so->so_state & SS_NOFDREF) == 0) {		shutdown(so->s,0);		if(global_writefds) {		  FD_CLR(so->s,global_writefds);		}	}	so->so_state &= ~(SS_ISFCONNECTING);	if (so->so_state & SS_FCANTSENDMORE)	   so->so_state = SS_NOFDREF; /* Don't select it */ /* XXX close() here as well? */	else	   so->so_state |= SS_FCANTRCVMORE;}voidsofcantsendmore(so)	struct socket *so;{	if ((so->so_state & SS_NOFDREF) == 0) {            shutdown(so->s,1);           /* send FIN to fhost */            if (global_readfds) {                FD_CLR(so->s,global_readfds);            }            if (global_xfds) {                FD_CLR(so->s,global_xfds);            }	}	so->so_state &= ~(SS_ISFCONNECTING);	if (so->so_state & SS_FCANTRCVMORE)	   so->so_state = SS_NOFDREF; /* as above */	else	   so->so_state |= SS_FCANTSENDMORE;}voidsoisfdisconnected(so)	struct socket *so;{/*	so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); *//*	close(so->s); *//*	so->so_state = SS_ISFDISCONNECTED; */	/*	 * XXX Do nothing ... ?	 */}/* * Set write drain mode * Set CANTSENDMORE once all data has been write()n */voidsofwdrain(so)	struct socket *so;{	if (so->so_rcv.sb_cc)		so->so_state |= SS_FWDRAIN;	else		sofcantsendmore(so);}

⌨️ 快捷键说明

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