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

📄 httcp.c

📁 firtext搜索引擎源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		    HTTRACE(PROT_TRACE, "HTDoConnect. WOULD BLOCK `%s'\n" _ hostname);#ifndef _WINSOCKAPI_		    HTHost_register(host, net, HTEvent_CONNECT);#endif /* _WINSOCKAPI_ */		    return HT_WOULD_BLOCK;		}#ifdef _WINSOCKAPI_		/*		 * yovavm@contact.com		 *		 * According to Microsoft docs, the error code WSAEALREADY is 		 * described as:		 * "A nonblocking connect call is in progress on the specified		 *  socket. Note In order to preserve backward compatibility, 		 *  this error is reported as WSAEINVAL to Windows Sockets 1.1		 *  applications that link to either Winsock.dll or		 *  Wsock32.dll."		 */		if (NETCALL_INVAL(socerrno)) {		    host->tcpstate = TCP_CONNECTED;		    HTTRACE(PROT_TRACE, "Connection to HTHost %p is already in progress.\n" _ host);		    break;		}#endif /* _WINSOCKAPI_ */		if (socerrno == EISCONN) {		    host->tcpstate = TCP_CONNECTED;		    HTTRACE(PROT_TRACE, "HTHost %p going to state TCP_CONNECTED.\n" _ host);		    break;		}		if (NETCALL_DEADSOCKET(socerrno))     /* We lost the socket */		{		    host->tcpstate = TCP_NEED_SOCKET;		    HTTRACE(PROT_TRACE, "HTHost %p going to state TCP_NEED_SOCKET.\n" _ host);		    break;		}		if (HTHost_retry(host)) {		    host->connecttime = HTGetTimeInMillis() - host->connecttime;		    /* Added EINVAL `invalid argument' as this is what I 		       get back from a non-blocking connect where I should 		       get `connection refused' on BSD. SVR4 gives SIG_PIPE */		    if (HT_HOSTUNREACHABLE(socerrno))		        host->connecttime += TCP_DELAY;		    else		        host->connecttime += TCP_PENALTY;		    HTDNS_updateWeigths(host->dns, HTHost_home(host), host->connecttime);		}		host->tcpstate = TCP_ERROR;				HTTRACE(PROT_TRACE, "HTHost %p going to state TCP_ERROR.\n" _ host);	    } else {		host->tcpstate = TCP_CONNECTED;		HTTRACE(PROT_TRACE, "HTHost %p going to state TCP_CONNECTED.\n" _ host);	    }	    break;	  case TCP_CONNECTED:	    HTHost_unregister(host, net, HTEvent_CONNECT);	    if (HTHost_retry(host)) {		host->connecttime = HTGetTimeInMillis() - host->connecttime;		HTDNS_updateWeigths(host->dns, HTHost_home(host), host->connecttime);	    }	    HTHost_setRetry(host, 0);	    host->tcpstate = TCP_IN_USE;	    HTTRACE(PROT_TRACE, "HTHost %p connected.\n" _ host);	    return HT_OK;	    break;	  /* Once a host is connected, subsequent connections are immediately OK */	  case TCP_IN_USE:	      if ((status = HTHost_addNet(host, net)) == HT_PENDING) {		  HTTRACE(PROT_TRACE, "HTDoConnect. Pending...\n");		  return HT_PENDING;	      }	      HTChannel_upSemaphore(host->channel);	      return HT_OK;	  case TCP_DNS_ERROR:	    HTHost_setRetry(host, 0);	    host->tcpstate = TCP_BEGIN;	    HTTRACE(PROT_TRACE, "HTHost %p going to state TCP_BEGIN.\n" _ host);	    return HT_NO_HOST;	    break;	  case TCP_NEED_BIND:	  case TCP_NEED_LISTEN:	  case TCP_ERROR:	    if (HTChannel_socket(host->channel) != INVSOC) {		NETCLOSE(HTChannel_socket(host->channel));		if (HTHost_isPersistent(host)) {	 /* Inherited socket */		    HTHost_setPersistent(host, NO, HT_TP_SINGLE);		    host->tcpstate = TCP_NEED_SOCKET;		    HTTRACE(PROT_TRACE, "HTHost %p going to state TCP_NEED_SOCKET.\n" _ host);		    break;		}	    }	    /* Do we have more homes to try? */	    HTHost_decreaseRetry(host);	    if (HT_HOSTUNREACHABLE(socerrno) && HTHost_retry(host) > 0) {	        HTRequest_addSystemError(request, ERR_NON_FATAL, socerrno, NO,"connect");		host->tcpstate = TCP_DNS;		HTTRACE(PROT_TRACE, "HTHost %p going to state TCP_DNS.\n" _ host);		break;	    }	    HTRequest_addSystemError(request, ERR_FATAL, socerrno, NO, "connect");	    HTDNS_delete(hostname);	    HTHost_setRetry(host, 0);	    host->tcpstate = TCP_BEGIN;	    HTTRACE(PROT_TRACE, "HTHost %p going to state TCP_BEGIN.\n" _ host);	    return HT_ERROR;	    break;	}    }}/*	HTDoAccept()**	------------**	This function makes a non-blocking accept which will turn up as ready**	read in the select.**	Returns**		HT_ERROR	Error has occured or interrupted**		HT_OK		if connected**		HT_WOULD_BLOCK  if operation would have blocked*/PUBLIC int HTDoAccept (HTNet * listening, HTNet * accepting){    HTHost * host = HTNet_host(listening);    HTRequest * request = HTNet_request(accepting);    int size = sizeof(host->sock_addr);    int status;    if (!request || HTNet_socket(listening)==INVSOC) {	HTTRACE(PROT_TRACE, "HTDoAccept.. Invalid socket\n");	return HT_ERROR;    }    status = accept(HTNet_socket(listening), (struct sockaddr *) &host->sock_addr, &size);    if (NETCALL_ERROR(status))    {	if (NETCALL_WOULDBLOCK(socerrno))	{	    HTTRACE(PROT_TRACE, "HTDoAccept.. WOULD BLOCK %d\n" _ HTNet_socket(listening));	    HTHost_register(host, listening, HTEvent_ACCEPT);	    return HT_WOULD_BLOCK;	}	HTRequest_addSystemError(request, ERR_WARN, socerrno, YES, "accept");	HTTRACE(PROT_TRACE, "HTDoAccept.. Accept failed\n");	return HT_ERROR;    }    HTTRACE(PROT_TRACE, "Accepted.... socket %d\n" _ status);    /* Remember the new socket we got and close the old one */    NETCLOSE(HTNet_socket(accepting));    HTNet_setSocket(accepting, status);	    return HT_OK;}/*	HTDoListen**	----------**	Listens on the specified port. **	returns		HT_ERROR	Error has occured or interrupted**			HT_OK		if connected*/PUBLIC int HTDoListen (HTNet * listening, HTNet * accepting, int backlog){    HTHost * host = HTNet_host(listening);    HTRequest * request = HTNet_request(listening);    int preemptive = listening->preemptive;    int status = HT_OK;    char * hostname = HTHost_name(host);    /* Jump into the state machine */    while (1) {	switch (host->tcpstate) {	case TCP_BEGIN:	{	    /*	    ** Add the net object to the host object found above. If the	    ** host is idle then we can start the request right away,	    ** otherwise we must wait until it is free. 	    */	    if ((status = HTHost_addNet(host, accepting)) == HT_PENDING)		HTTRACE(PROT_TRACE, "HTDoListen.. Pending...\n");	    /*	    ** If we are pending then return here, otherwise go to next state	    ** which is setting up a channel	    */	    host->tcpstate = TCP_CHANNEL;	    HTTRACE(PROT_TRACE, "HTHost %p going to state TCP_CHANNEL.\n" _ host);	    if (status == HT_PENDING) return HT_PENDING;	}	break;	case TCP_CHANNEL:	    /*	    **  The next state depends on whether we have a connection or not.	    */	    if (HTHost_channel(host) == NULL) {		host->tcpstate = TCP_NEED_SOCKET;		HTTRACE(PROT_TRACE, "HTHost %p going to state TCP_SOCKET.\n" _ host);	    } else {		/*		**  There is now one more using the channel		*/		HTChannel_upSemaphore(host->channel);		/*		**  We are now all set and can jump to connected mode		*/		host->tcpstate = TCP_CONNECTED;		HTTRACE(PROT_TRACE, "HTHost %p going to state TCP_CONNECTED.\n" _ host);	    }	    hostname = HTHost_name(host);	    break;	case TCP_NEED_SOCKET:	{	    SOCKET sockfd;	    /* Create a new socket */	    if ((sockfd = _makeSocket(host, request, preemptive)) == INVSOC) {		host->tcpstate = TCP_ERROR;		break;	    }	    /* Create channnel and streams */	    createChannelAndTransportStreams (host, sockfd, accepting->transport);	    /* Progress nofitication */	    {		HTAlertCallback *cbf = HTAlert_find(HT_PROG_ACCEPT);		if (cbf) (*cbf)(request, HT_PROG_ACCEPT, HT_MSG_NULL,				NULL, hostname, NULL);	    }	    host->tcpstate = TCP_NEED_BIND;	    HTTRACE(PROT_TRACE, "HTHost %p going to state TCP_NEED_BIND\n" _ host);	    break;	}	case TCP_NEED_BIND:	    HTTRACE(PROT_TRACE, "Socket...... Binding socket %d\n" _ HTNet_socket(listening));	    status = bind(HTNet_socket(listening), (struct sockaddr *) &host->sock_addr,			  sizeof(host->sock_addr));	    if (NETCALL_ERROR(status)) {		HTTRACE(PROT_TRACE, "Socket...... Bind failed %d\n" _ socerrno);		host->tcpstate = TCP_ERROR;			    } else {		HTTRACE(PROT_TRACE, "Socket...... Starting listening on socket %d\n" _ HTNet_socket(listening));		host->tcpstate = TCP_NEED_LISTEN;	    }	    break;	case TCP_NEED_LISTEN:	    status = listen(HTNet_socket(listening), backlog);	    if (NETCALL_ERROR(status))		host->tcpstate = TCP_ERROR;			    else		host->tcpstate = TCP_CONNECTED;	    break;	case TCP_CONNECTED:	    HTHost_unregister(host, listening, HTEvent_ACCEPT);	    HTHost_setRetry(host, 0);	    host->tcpstate = TCP_IN_USE;	    HTTRACE(PROT_TRACE, "HTHost %p listening.\n" _ host);	    return HT_OK;	    break;	    /* once a host is connected, subsequent connections are immediately OK */	case TCP_IN_USE:	    if ((status = HTHost_addNet(host, accepting)) == HT_PENDING) {		HTTRACE(PROT_TRACE, "HTDoListen.. Pending...\n");		return HT_PENDING;	    }	    HTChannel_upSemaphore(host->channel);	    return HT_OK;	case TCP_NEED_CONNECT:	case TCP_DNS:	case TCP_DNS_ERROR:	case TCP_ERROR:	    if (HTChannel_socket(host->channel) != INVSOC) {		NETCLOSE(HTChannel_socket(host->channel));		if (HTHost_isPersistent(host)) {	 /* Inherited socket */		    HTHost_setPersistent(host, NO, HT_TP_SINGLE);		    host->tcpstate = TCP_NEED_SOCKET;		    HTTRACE(PROT_TRACE, "HTHost %p going to state TCP_NEED_SOCKET.\n" _ host);		    break;		}	    }	    HTRequest_addSystemError(request, ERR_FATAL, socerrno, NO, "accept");	    HTHost_setRetry(host, 0);	    host->tcpstate = TCP_BEGIN;	    HTTRACE(PROT_TRACE, "HTHost %p going to state TCP_BEGIN.\n" _ host);	    return HT_ERROR;	    break;	}    }}/*	HTDoClose**	---------**	Closes a file descriptor whatever means are available on the current**	platform. If we have unix file descriptors then use this otherwise use**	the ANSI C file descriptors****	returns		HT_ERROR	Error has occured or interrupted**			HT_OK		if connected**			HT_WOULD_BLOCK  if operation would have blocked*/PUBLIC int HTDoClose (HTNet * net){    int status = -1;    if (net && HTNet_socket(net) != INVSOC) {	HTTRACE(PROT_TRACE, "HTDoClose... Close %d\n" _ HTNet_socket(net));	status = NETCLOSE(HTNet_socket(net));	/*	HTEvent_unregister(HTNet_socket(net), (SockOps) FD_ALL); */	HTNet_decreaseSocket(); 	HTNet_setSocket(net, INVSOC);		/*	**  As we have a socket available we check for whether	**  we can start any pending requests. We do this by asking for	**  pending Host objects. If none then use the current object	*/	HTHost_launchPending(net->host);    } else	HTTRACE(PROT_TRACE, "HTDoClose... No pending requests\n");    return status < 0 ? HT_ERROR : HT_OK;}

⌨️ 快捷键说明

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