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

📄 socket.c

📁 dtelent是开源的开发项目
💻 C
📖 第 1 页 / 共 3 页
字号:
/* socket.c
 * Copyright (c) 1997 David Cole
 *
 * Handle the WINSOCK connection to server
 */
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <winsock.h>

#include "platform.h"
#include "utils.h"
#include "dtelnet.h"
#include "emul.h"
#include "term.h"
#include "connect.h"
#include "raw.h"
#include "socket.h"
#include "status.h"
#include "log.h"
#include "proxy.h"

#define SOCKLIB_VERSION 0x0101

static char hostbuff[MAXGETHOSTSTRUCT];	/* data from host buffer */
static struct WSAData WSAData;	/* SocketLib data buffer */
static HWND sockWnd;		/* window for handling socket messages */
static SOCKET sock = INVALID_SOCKET; /* The socket associated with the class */
static struct sockaddr_in addr;	/* Build address for socket to connect to */
static struct sockaddr_in proxyAddr; /* Build address for proxy server */
static struct sockaddr_in localAddr; /* Local address */

static BOOL remoteHasClosed;	/* Remember if remote end has closed socket */
static BOOL readyForRead;	/* Remember if we have a read pending */
static BOOL readyForWrite;	/* Remember if we have a write pending */
static BOOL localFlowControl;	/* Are we doing local flow control? */
static BOOL flowStopped;	/* Has the user pressed ^S? */

static char socketHost[128];	/* where we connecting to */
static char socketService[64];	/* which service we are connecting to */

static char socketLocalIp[32];  /* Local IP address */

static char readBuffer[512]; /* limit amount we read every
				       * time to 512 so we can have
				       * some ability to interrupt
				       * output via ^S */
static int readIdx;		/* current position in readBuffer */

/* Hold all data to be sent to the remote end in a queue.
 */
typedef struct Data Data;
struct Data {
    Data* next;			/* next data in queue */
    unsigned char* text;	/* text to be sent to remote end */
    int len;			/* length of text being sent */
};

static Data* dataQueue;		/* head of data queue */
static Data* dataEnd;		/* end of data queue */
static int writeIdx;		/* write position in queue head */

/* Define the states that communication to the remote end can be in
 */
typedef enum {
    sockOffline,		/* idle and offline */
    sockGetProxyHostName,	/* offline - resolving proxy host */
    sockGetHostName,		/* offline - resolving host */
    sockGetServName,		/* offline - resolving service */
    sockConnect,		/* offline - connecting */
    sockProxy,			/* offline - proxy request */
    sockOnline			/* online */
} SocketState;

static SocketState socketState = sockOffline; /* current socket state */

static void socketSetState(SocketState state);

static char* socketWinClass = "DTelnetSocketWClass";

/* Report a socket error to the user
 *
 * Args:
 * operation - the operation being performed when error was encountered
 * error -     the error that was encountered
 */
void socketError(const char* operation, int error)
{
    char msg[512];		/* format error message */
    char *dstHost;              /* pointer to destination host */
    char *dstService;           /* pointer to destination service */

    /* set destination host/service
     */
    if (proxyEnabled()) {
        dstHost = proxyGetHost();
        dstService = proxyGetPort();
    }
    else {
        dstHost = socketHost;
        dstService = socketService;
    }
    switch (error) {
    case WSAEINTR:
	sprintf(msg, "%s was interrupted", operation);
	break;
    case WSAEBADF:
	sprintf(msg, "%s used a bad file descriptor", operation);
	break;
    case WSAEACCES:
	sprintf(msg, "Permission denied for %s", operation);
	break;
    case WSAEFAULT:
	sprintf(msg, "%s used a bad address", operation);
	break;
    case WSAEINVAL:
	sprintf(msg, "Invalid argument in %s", operation);
	break;
    case WSAEMFILE:
	sprintf(msg, "Too many open files during %s", operation);
	break;
    case WSAEWOULDBLOCK:
	sprintf(msg, "Operation %s would block", operation);
	break;
    case WSAEINPROGRESS:
	sprintf(msg, "Called %s while blocking operation in progress",
		operation);
	break;
    case WSAEALREADY:
	sprintf(msg, "%s already in progress", operation);
	break;
    case WSAENOTSOCK:
	sprintf(msg, "Called %s on a non-socket", operation);
	break;
    case WSAEDESTADDRREQ:
	sprintf(msg, "Destination address missing during %s", operation);
	break;
    case WSAEMSGSIZE:
	sprintf(msg, "Message too long during %s", operation);
	break;
    case WSAEPROTOTYPE:
	sprintf(msg, "Protocol wrong type for socket during %s", operation);
	break;
    case WSAENOPROTOOPT:
	sprintf(msg, "Protocol not available during %s", operation);
	break;
    case WSAEPROTONOSUPPORT:
	sprintf(msg, "Protocol not supported during %s", operation);
	break;
    case WSAESOCKTNOSUPPORT:
	sprintf(msg, "Socket type not supported during %s", operation);
	break;
    case WSAEOPNOTSUPP:
	sprintf(msg, "Option not supported during %s", operation);
	break;
    case WSAEPFNOSUPPORT:
	sprintf(msg, "Protocol family not supported during %s", operation);
	break;
    case WSAEAFNOSUPPORT:
	sprintf(msg, "Address family not supported during %s", operation);
	break;
    case WSAEADDRINUSE:
	sprintf(msg, "Address already in use during %s", operation);
	break;
    case WSAEADDRNOTAVAIL:
	sprintf(msg, "Cannot assign requested address during %s", operation);
	break;
    case WSAENETDOWN:
	sprintf(msg, "Network is down");
	break;
    case WSAENETUNREACH:
	sprintf(msg, "Network is unreachable");
	break;
    case WSAENETRESET:
	sprintf(msg, "Network dropped connection because of reset");
	break;
    case WSAECONNABORTED:
	sprintf(msg, "Software caused connect abort during %s", operation);
	break;
    case WSAECONNRESET:
	sprintf(msg, "Connect has been reset by server");
	break;
    case WSAENOBUFS:
	sprintf(msg, "No buffer space available during %s", operation);
	break;
    case WSAEISCONN:
	sprintf(msg, "Already connected during %s", operation);
	break;
    case WSAENOTCONN:
	sprintf(msg, "Not connected during %s", operation);
	break;
    case WSAESHUTDOWN:
	sprintf(msg, "Cannot send after shutdown during %s", operation);
	break;
    case WSAETOOMANYREFS:
	sprintf(msg, "Too many references during %s", operation);
	break;
    case WSAETIMEDOUT:
	sprintf(msg, "Connection to %s/%s timed out", dstHost, dstService);
	break;
    case WSAECONNREFUSED:
	sprintf(msg, "Connection to %s/%s refused", dstHost, dstService);
	break;
    case WSAELOOP:
	sprintf(msg, "Too many symbolic links during %s", operation);
	break;
    case WSAENAMETOOLONG:
	sprintf(msg, "File name too long during %s", operation);
	break;
    case WSAEHOSTDOWN:
	sprintf(msg, "Host %s is down", dstHost);
	break;
    case WSAEHOSTUNREACH:
	sprintf(msg, "No route to host %s", dstHost);
	break;
    case WSAENOTEMPTY:
	sprintf(msg, "Directory not empty during %s", operation);
	break;
    case WSAEUSERS:
	sprintf(msg, "Too many users during %s", operation);
	break;
    case WSAEDQUOT:
	sprintf(msg, "Quota exceeded during %s", operation);
	break;
    case WSAESTALE:
	sprintf(msg, "Stale NFS handle during %s", operation);
	break;
    case WSAEREMOTE:
	sprintf(msg, "Object is remote during %s", operation);
	break;
    case WSASYSNOTREADY:
	sprintf(msg, "Network subsystem is not usable");
	break;
    case WSAVERNOTSUPPORTED:
	sprintf(msg, "WINSOCK DLL cannot support this application");
	break;
    case WSANOTINITIALISED:
	sprintf(msg, "WSAStartup has not been called during %s", operation);
	break;
    case WSAHOST_NOT_FOUND:
	sprintf(msg, "Authoritative host not found");
	break;
    case WSATRY_AGAIN:
	sprintf(msg, "Try again");
	break;
    case WSANO_RECOVERY:
	sprintf(msg, "No recovery during %s", operation);
	break;
    case WSANO_DATA:
	switch (socketState) {
	case sockGetProxyHostName:
	    sprintf(msg, "No such host %s", proxyGetHost());
	    break;
	case sockGetHostName:
	    sprintf(msg, "No such host %s", socketHost);
	    break;
	case sockGetServName:
	    sprintf(msg, "No such service %s", socketService);
	    break;
	default:
	    sprintf(msg, "No data during %s", operation);
	    break;
	}
	break;
    }
    MessageBox(termGetWnd(), msg, telnetAppName(),
	       MB_APPLMODAL | MB_ICONHAND | MB_OK);
}

/* Close our connection to the remote end and discard any data that
 * was queued to be sent
 */
static void closeSocket(void)
{
    remoteHasClosed = FALSE;
    readIdx = writeIdx = 0;
    if (sock != INVALID_SOCKET) {
        if (WSAAsyncSelect(sock, sockWnd, 0, 0) == SOCKET_ERROR)
            socketError("WSAAsyncSelect()", WSAGetLastError());
        if (closesocket(sock) == SOCKET_ERROR)
            socketError("closesocket()", WSAGetLastError());
        sock = INVALID_SOCKET;
    }

    /* Reset the application window title
     */
    telnetSetTitle();
    socketSetState(sockOffline);

    /* Discard all data that was queued to be sent to remote end
     */
    while (dataQueue != NULL) {
	Data* tmp = dataQueue->next;
	ASSERT(dataQueue->text != NULL);
	free(dataQueue->text);
	free(dataQueue);
	dataQueue = tmp;
    }
    dataEnd = NULL;
}

/* Return whether or not we have a connection to the remote end */
BOOL socketConnected()
{
    return socketState == sockOnline;
}

/* Return whether or not we are offline and idle
 */
BOOL socketOffline(void)
{
    return socketState == sockOffline;
}

/* Close the connection to the server
 */
void socketDisconnect(void)
{
    closeSocket();
}

/* Read some data from the remote end and send it through the raw
 * protocol processing code.
 */
static void socketReadReady(void)
{
    int error;   		/* Error returned from socket read */
    int numRead;		/* Number of bytes read this time around */
    int numUsed;		/* Number of bytes used by processing */

    if (sock == INVALID_SOCKET) return;

    /* we give the control to proxy.c to handle the
     * proxy protocol while socketState == sockProxy
     */
    if (socketState == sockProxy)
    {
	int ret;
	ret = proxyProtocolHandler();
	if (ret == PROXY_ERROR) {
	    closeSocket();
	}
	else if (ret == PROXY_CONNECTED) {
            socketSetState(sockOnline);
            telnetSetTitle();
            rawStartSession();
	}
	return;
    }
    /* Try to read as much as possible from the server.
     */
    ASSERT(readIdx < sizeof(readBuffer));

    numRead = recv(sock, ((char*)readBuffer) + readIdx,
		   sizeof(readBuffer) - readIdx, 0);

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

    /* Got some data from the remote end, send it through protocol
     * processing
     */
    ASSERT(numRead > 0);
    readIdx += numRead;

    numUsed = rawProcessData((unsigned char *)readBuffer, readIdx);
    ASSERT(numUsed >= 0);
    ASSERT(numUsed <= readIdx);

    /* Skip over data that was consumed by protocol code
     */
    if (numUsed == readIdx)
	readIdx = 0;
    else {
	memmove(readBuffer, readBuffer + numUsed, readIdx - numUsed);
	readIdx -= numUsed;
    }
    if (readIdx == sizeof(readBuffer)) {
	/* Buffer is full.
	 */
	readIdx = 0;
    }
}

⌨️ 快捷键说明

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