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

📄 socket.c

📁 dtelent是开源的开发项目
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Write queued data to the remote end
 */
static void socketWriteReady(void)
{
    while (dataQueue != NULL) {
	int numWritten;

	/* Get the data at the head of the queue and send as
	 * much as possible to the remote end.
	 */
	ASSERT(dataQueue->text != NULL);
	ASSERT(dataQueue->len > writeIdx);
	numWritten = send(sock, (char *)dataQueue->text + writeIdx,
			  dataQueue->len - writeIdx, 0);

	if (numWritten != SOCKET_ERROR) {
	    /* Managed to send data
	     */
	    writeIdx += numWritten;
	    if (writeIdx == dataQueue->len) {
		Data* tmp = dataQueue;

		/* Completed sending the data - remove it from the queue
		 * and delete it.
		 */
		dataQueue = dataQueue->next;
		if (dataQueue == NULL)
		    dataEnd = NULL;
		free(tmp->text);
		free(tmp);
		writeIdx = 0;
	    }
	} else {  
	    int error;		/* query the error encountered */

	    /* Some sort of error sending to remote end.
	     */
	    error = WSAGetLastError();
	    if (error == WSAEWOULDBLOCK)
		/* No problems, remote end can not accept any more
		 * data just now
		 */
		return;
	    else {
		/* Error: close socket
		 */
		socketError("send()", error);
		closeSocket();
		return;
	    }
	}
    }   
}

/* Receive some out-of-band data from the other end of the socket
 */
static void socketOobReady(void)
{
    int numRead;		/* Number of bytes read this time around */
    char oobBuffer[256]; /* Buffer for OOB data */

    /* Try to read as much as possible from the remote end.
     */
    numRead = recv(sock, oobBuffer, sizeof(oobBuffer), MSG_OOB);

    if (numRead == 0)
	/* No more data ready
	 */
	return;
    if (numRead == SOCKET_ERROR) {
	int error = WSAGetLastError();
	if (error == WSAEWOULDBLOCK)
	    /* No more data ready
	     */
	    return;
	/* Error: close socket
	 */
	socketError("recv()", error);
	closeSocket();
	return;
    }

    /* Got some OOB data from remote end
     */
    rawProcessOob((unsigned char*)oobBuffer, numRead);

    /* Assume that the OOB data was in response to ^C, eventually we
     * will get the prompt back - we must allow it to be shown be
     * restoring character flow.
     */
    if (rawGetProtocol() != protoNone && localFlowControl)
	socketSetFlowStop(FALSE);
}

/* Perform a select on the socket.  When an event occurs the WINSOCK
 * library will sent a WM_SOCK_EVENT message to the socket window
 * message proc.
 *
 * Return TRUE if the operation was successful.
 */
static BOOL socketSelect(void)
{                      
    LONG events;		/* socket events we are interested in */

    if ((socketState == sockOnline) || (socketState == sockProxy))
	/* We are online - listen for close, read, write, and out-of-band
	 */
	events = FD_CLOSE|FD_READ|FD_WRITE|FD_OOB;
    else
	/* We are not connected yet, just listen for connect
	 */
	events = FD_CONNECT;

    if (WSAAsyncSelect(sock, sockWnd, WM_SOCK_EVENT, events) != SOCKET_ERROR)
	return TRUE;
    socketError("WSAAsyncSelect()", WSAGetLastError());
    return FALSE;
}

/* Build a new socket and try to connect to the remote end
 *
 * Return TRUE if the operation was successful
 */
static BOOL socketMakeNew(void)
{
    int error;			/* detect errors encountered */
    DWORD yes = 1;		/* ioctl parameter */
    struct sockaddr_in *dst;    /* pointer to address for connect (direct/proxy) */

    remoteHasClosed = FALSE;
    /* Log that we are trying to connect
     */
    logProtocol("Connecting to %d.%d.%d.%d/%d\n",
		addr.sin_addr.s_net, addr.sin_addr.s_host,
		addr.sin_addr.s_lh, addr.sin_addr.s_impno,
		htons(addr.sin_port));
    socketSetState(sockConnect);

    /* Set up socket address family
     */
    addr.sin_family = PF_INET;
    proxyAddr.sin_family = PF_INET;

    /* Create a socket
     */
    if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
	socketError("socket()", WSAGetLastError());
	return FALSE;
    }
    /* Set the socket non-blocking
     */
    if (ioctlsocket(sock, FIONBIO, &yes) == SOCKET_ERROR) {
	socketError("ioctlsocket()", WSAGetLastError());
	return FALSE;
    }

    /* Set the events that we are interested in knowing about
     */
    if (!socketSelect())
	return FALSE;

    if (rawGetProtocol() == protoTelnet)
	/* If we are connecting to the Telnet port, disable local flow
	 * control.
	 */
	localFlowControl = FALSE;
    else if (rawGetProtocol() == protoRlogin) {
	SOCKADDR_IN localAddr; /* address of the local end */
	u_short localPort = IPPORT_RESERVED; /* first port to try for
					      * local end of rlogin
					      * connection */

	/* Rlogin servers will only accept connections from ports in
	 * the reserved range (below 1024).  Start at 1023 and keep
	 * trying until we either get a valid local endpoint, or we
	 * run out of ports.
	 */
	localAddr.sin_family = PF_INET;
	localAddr.sin_addr.s_addr = INADDR_ANY;
	for (;;) {
	    localPort--;
	    if (localPort == IPPORT_RESERVED / 2) {
		MessageBox(termGetWnd(), "All reserved ports in use",
			   telnetAppName(),
			   MB_APPLMODAL | MB_ICONHAND | MB_RETRYCANCEL);
		return FALSE;
	    }

	    localAddr.sin_port = htons(localPort);
	    if (bind(sock, (LPSOCKADDR)&localAddr, sizeof(localAddr)) == 0)
		break;
	    if ((error = WSAGetLastError()) != WSAEADDRINUSE) {
		socketError("bind()", error);
		return FALSE;
	    }
	}

	/* Enable local flow control
	 */
	localFlowControl = TRUE;
    } else
	/* Enable local flow control
	 */
	localFlowControl = TRUE;

    /* We start connection with flow enabled.  Flow can not be
     * restarted with any character unless we negotiate that option.
     */
    flowStopped = FALSE;
    emulLocalFlowAny(FALSE);

    /* set the destination address (direct/proxy)
     */
    dst = (proxyEnabled() ? &proxyAddr : &addr);
    /* Initiate the connection
     */
    if (connect(sock, (struct sockaddr*)dst, sizeof(addr)) == SOCKET_ERROR) {
	if ((error = WSAGetLastError()) != WSAEWOULDBLOCK) {
	    socketError("connect()", error);
	    return FALSE;
	}
    }
    return TRUE;
}

/* Asynchronous get service by name has completed, save the results
 * (service port)
 */
static void socketSaveService(void)
{
    struct servent servent;	/* Service to connect */

    memcpy((void*)&servent, hostbuff, sizeof(servent));
    addr.sin_port = servent.s_port;
}

/* Initiate an asynchronous get service by name
 *
 * Return TRUE if successful.
 */
static BOOL socketGetServByName(void)
{
    socketSetState(sockGetServName);

    if (strlen(socketService) > 0 && isdigit(socketService[0])) {
	/* If service name starts with a digit, assume that the port
	 * was directly specified and proceed directly to establish a
	 * connection.
	 */
	addr.sin_port = htons((short)atoi(socketService));
	return socketMakeNew();
    }

    /* Query service port from name
     */
    if (WSAAsyncGetServByName(sockWnd, WM_SOCK_GETSERVBYNAME,
			      socketService, "tcp", hostbuff,
			      MAXGETHOSTSTRUCT))
	return TRUE;
    socketError("WSAAsyncGetServByName()", WSAGetLastError());
    return FALSE;
}

/* Asynchronous get host by name has completed, save the results
 * (host address)
 */
static void socketSaveHostname(void)
{
    struct hostent hostent;	/* Address of host to connect */

    memcpy((void*)&hostent, hostbuff, sizeof(hostent));
    memcpy((char*)&addr.sin_addr, (char*)&hostent.h_addr[0], hostent.h_length);
}

/* Initiate an asynchronous get host by name
 *
 * Return TRUE if successful.
 */
static BOOL socketGetHostByName(void)
{
    unsigned long inaddr = inet_addr(socketHost); /* check if IP
						   * address specified
						   * directly */

    socketSetState(sockGetHostName);
    if (inaddr != INADDR_NONE) {
	/* Looks like a numeric address was provided.  Copy it into
	 * the address structure, and proceed to service lookup
	 */
	memcpy((char*)&addr.sin_addr, (char*)&inaddr, 4);

	return socketGetServByName();
    }

    /* Query host address from name
     */
    if (WSAAsyncGetHostByName(sockWnd, WM_SOCK_GETHOSTBYNAME,
			      socketHost, hostbuff, MAXGETHOSTSTRUCT))
	return TRUE;
    socketError("WSAAsyncGetGetHostByName()", WSAGetLastError());
    return FALSE;
}

/* Asynchronous get host by name for Proxy server has completed, save the results
 * (host address)
 */
static void socketSaveProxyHostname(void)
{
    struct hostent hostent;     /* Address of host to connect */

    memcpy((void*)&hostent, hostbuff, sizeof(hostent));
    memcpy((char*)&proxyAddr.sin_addr, (char*)&hostent.h_addr[0], hostent.h_length);
}

/* Initiate an asynchronous get host by name for Proxy server
 *
 * Return TRUE if successful.
 */
static BOOL socketGetProxyHostByName(void)
{
    unsigned long inaddr;

    proxyAddr.sin_port = htons((u_short) atoi(proxyGetPort()));
    inaddr = inet_addr(proxyGetHost());
    socketSetState(sockGetProxyHostName);
    if (inaddr != INADDR_NONE) {
        memcpy((char*)&proxyAddr.sin_addr, (char*)&inaddr, 4);
        if (!proxySupportHostname()) {
           return socketGetHostByName();
        }
        return socketGetServByName();
    }
    if (WSAAsyncGetHostByName(sockWnd, WM_SOCK_GETHOSTBYNAME,
                              proxyGetHost(), hostbuff, MAXGETHOSTSTRUCT))
        return TRUE;
    socketError("WSAAsyncGetGetHostByName()", WSAGetLastError());
    return FALSE;
}

/* We delay our read / write on the socket until a convenient
 * processing time.  This prevents the situation where a telnet to
 * CHARGEN totally locks up Windows.  In our case, we wait until the
 * message queue is empty.
 */
void socketProcessPending()
{
    if (readyForRead) {
	/* When we receive an FD_READ event on the socket, the code
	 * processing the event sets readyForRead TRUE.  When we are
	 * performing local flow control, and we have blocked flow, we
	 * do not want to read from the socket.  If we are not running
	 * telnet or rlogin, then there is no local flow control.
	 */
	if (rawGetProtocol() == protoNone
	    || !(localFlowControl && flowStopped)) {
            /* the following two statements are reversed in they */
            /* execution order (Khader Al-Atrash)                */
	    readyForRead = FALSE;
	    socketReadReady();
	}
    }
    if (remoteHasClosed) {
        /* if we have a proxy request in progress, proxyHasClosed() display a error */
        if (socketState == sockProxy) {
            proxyRemoteHasClosed();
        }
	closeSocket();
	/* If the user has set exit-on-disconnect, exit the application
	 */
	if (connectGetExitOnDisconnect())
	    telnetExit();
    } else if (readyForWrite) {
	/* When we receive an FD_WRITE event on the socket, the
	 * processing code sets readyForWrite TRUE.  We perform the
	 * write here, once the event queue is empty.
	 */
        /* the following two statements are reversed in they */
        /* execution order (Khader Al-Atrash)                */
	readyForWrite = FALSE;
	socketWriteReady();
    }
}

/* Return whether or not we are performing local flow control
 */
BOOL socketLocalFlowControl(void)
{
    return localFlowControl;
}

/* Set local flow control on or off
 *
 * Args:
 * local - do we wish to switch to local flow control?
 */
void socketSetLocalFlowControl(BOOL local)
{
    if (local == localFlowControl)
	/* No change in value
	 */
	return;

⌨️ 快捷键说明

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