📄 socket.c
字号:
if (rawGetProtocol() != protoNone && !local)
/* Hve just switched from local flow control to remote flow
* control, initiate a read to catch any data that has been
* sent by remote end.
*/
readyForRead = TRUE;
localFlowControl = local;
}
/* Stop or restart flow locally
*
* Args:
* stop - should flow be stopped?
*/
void socketSetFlowStop(BOOL stop)
{
if (stop == flowStopped)
/* No change in value
*/
return;
if (rawGetProtocol() != protoNone && localFlowControl && !stop)
/* Have just restarted flow locally. Initiate a read to catch
* any data that we have already received from the remote end
*/
readyForRead = TRUE;
flowStopped = stop;
}
/* Return whether or not flow has been stopped locally
*/
BOOL socketFlowStopped(void)
{
return flowStopped;
}
/* Display the current communications state in the status bar
*/
void socketShowStatus(void)
{
switch (socketState) {
case sockOffline:
statusSetMsg("Offline");
termSetTitle("Dave's Telnet - offline");
break;
case sockGetProxyHostName:
statusSetMsg("Resolving Proxy server host name %s", proxyGetHost());
break;
case sockGetHostName:
statusSetMsg("Resolving host name %s", socketHost);
break;
case sockGetServName:
statusSetMsg("Resolving service name %s", socketService);
break;
case sockConnect:
statusSetMsg("Connecting to %s/%d",
proxyEnabled() ? inet_ntoa(proxyAddr.sin_addr) : inet_ntoa(addr.sin_addr),
proxyEnabled() ? htons(proxyAddr.sin_port) : htons(addr.sin_port));
break;
case sockProxy:
statusSetMsg("Sending Proxy request...");
break;
case sockOnline:
statusSetMsg("Online to %s/%d",
(proxyEnabled() && proxySupportHostname()) ? socketHost : inet_ntoa(addr.sin_addr),
htons(addr.sin_port));
break;
}
}
/* Set and display the socket state
*/
static void socketSetState(SocketState state)
{
socketState = state;
socketShowStatus();
}
/* Window procedure for the socket window
*/
long CALLBACK socketWndProc(HWND wnd,
UINT message, WPARAM wparam, LPARAM lparam)
{
WORD event;
WORD error;
int addrlen;
event = WSAGETSELECTEVENT(lparam);
error = WSAGETASYNCERROR(lparam);
switch (message) {
case WM_SOCK_GETHOSTBYNAME:
/* Have just resolved the address of the remote end. Save the
* data and then request the service port. When the
* getservbyname operation finishes, windows sends the
* WM_SOCK_GETSERVBYNAME message back here.
*/
if (error) {
/* gethostbyname failed for some reason
*/
socketError("WSAAsyncGetHostByName", error);
socketSetState(sockOffline);
break;
}
if (socketState == sockGetProxyHostName) {
/* if the selected proxy protocol don't support hostnames
* as destination, resolve the host locally, otherwise
* we request the service port.
*/
socketSaveProxyHostname();
if (!proxySupportHostname()) {
socketGetHostByName();
}
else {
socketGetServByName();
}
}
else {
socketSaveHostname();
socketGetServByName();
}
break;
case WM_SOCK_GETSERVBYNAME:
/* Have just resolved the service port. Save the data and
* then initiate a connection to the remote host. When the
* connection completes, windows will send WM_SOCK_EVENT with
* FD_CONNECT as the event.
*/
if (error) {
socketError("WSAAsyncGetServByName", error);
socketSetState(sockOffline);
break;
}
socketSaveService();
socketMakeNew();
break;
case WM_SOCK_EVENT:
switch (event) {
case FD_CLOSE:
/* Socket has been closed by the remote end.
*/
remoteHasClosed = TRUE;
break;
case FD_CONNECT:
/* Connect to remote end has completed
*/
if (error) {
closeSocket();
socketError("connect()", error);
break;
}
addrlen = sizeof (localAddr);
getsockname (sock, (struct sockaddr *)&localAddr, &addrlen);
strcpy (socketLocalIp, inet_ntoa (localAddr.sin_addr));
if (proxyEnabled()) {
int ret;
char *dstHost;
socketSetState(sockProxy);
dstHost = proxySupportHostname() ? socketHost : inet_ntoa(addr.sin_addr);
ret = proxyStartRequest(dstHost, ntohs(addr.sin_port));
if (ret != PROXY_OK) {
closeSocket();
break;
}
}
else {
/* The connection was successful, set our state to online,
* update the application window title, kick start a new
* protocol session, and finally update the socket events
* we are interested in.
*/
socketSetState(sockOnline);
telnetSetTitle();
rawStartSession();
}
socketSelect();
break;
case FD_READ:
/* There is some data ready to be read from the remote
* end. Do not read the data now, the message loop will
* service the network IO once all GUI interaction is
* complete.
*/
readyForRead = TRUE;
break;
case FD_WRITE:
/* The socket is ready for us to send some more data to
* the remote end. Handle this as per FD_READ
*/
readyForWrite = TRUE;
break;
case FD_OOB:
/* Received some urgent data from remote end. Probably
* result of pressing ^C.
*/
socketOobReady();
break;
}
break;
case WM_DESTROY:
/* Our window has been destroyed, close up the socket
*/
closeSocket();
return 0;
default:
return DefWindowProc(wnd, message, wparam, lparam);
}
return 0;
}
/* Return the remote host passed into socketConnect()
*/
char* socketGetHost()
{
return socketHost;
}
/* Return the remote service passed into socketConnect()
*/
char* socketGetPort()
{
return socketService;
}
/* Return the handle of the socket
*/
SOCKET socketGetHandle(void)
{
return sock;
}
/* Return local IP-address as a string
*/
char *socketGetLocalIP()
{
return socketLocalIp;
}
/* Initiate a connection to the remote end.
*
* Args:
* host - the hostname or IP address (as string) to connect to
* service - te service name or port number (as string) to connect to
*/
void socketConnect(const char* host, const char* service)
{
/* Store the session details for later reference
*/
strcpy(socketHost, host);
strcpy(socketService, service);
if (proxyEnabled()) {
/* if proxy is enabled, we resolve first the proxy server host name
*/
socketGetProxyHostByName();
}
else {
/* We start the ball rolling by finding the address of the remote
* end. When the gethostbyname operation finishes, windows sends
* the WM_SOCK_GETHOSTBYNAME message back here.
*/
socketGetHostByName();
}
}
/* Queue some data to be written to the remote end.
*
* Args:
* text - the data to be sent to the remote end
* len - the amount of data to be sent
*/
void socketWrite(const char* text, int len)
{
Data* data; /* queue entry for data */
BOOL wasEmpty = dataQueue == NULL; /* was the queue empty when function called */
ASSERT(text != NULL);
ASSERT(len > 0);
ASSERT(len < INT_MAX);
if (socketState != sockOnline)
/* Do not queue data if we are not connected
*/
return;
/* Allocate a queue entry and get a local copy of the data to be
* queued
*/
data = (Data *)xmalloc(sizeof(*data));
ASSERT(data != NULL);
memset(data, 0, sizeof(*data));
data->text = (unsigned char *)xmalloc(len);
ASSERT(data->text != NULL);
data->len = len;
memcpy(data->text, text, len);
/* Add the data to the end of the queue
*/
if (dataEnd != NULL)
dataEnd->next = data;
else
dataQueue = data;
dataEnd = data;
/* If there is already data in the queue, just queue the data. If
* this is the only data, and the socket is ready for writing then
* try to write this data.
*/
if (wasEmpty)
socketWriteReady();
}
/* Check for a local X-server */
BOOL socketHaveXServer ()
{
SOCKET s;
struct sockaddr_in sa;
int rc;
DWORD err;
static BOOL fTested= FALSE, fHave= FALSE;
/* if (fTested) return fHave; *//* optimization? */
s = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s==(SOCKET)-1) {
fHave = FALSE;
fTested = TRUE;
return fHave;
}
memset (&sa, 0, sizeof (sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = INADDR_ANY;
sa.sin_port = htons (6000); /* X-server' port */
rc = bind (s, (struct sockaddr *)&sa, sizeof (sa));
if (rc==-1) {
err = WSAGetLastError ();
if (err == WSAEADDRINUSE) fHave = TRUE;
}
closesocket (s);
fTested = TRUE;
return fHave;
}
/* Register the window class that will receive the socket messages
*/
BOOL socketInitClass(HINSTANCE instance)
{
WNDCLASS wc;
wc.style = 0;
wc.lpfnWndProc = socketWndProc;
wc.cbClsExtra = wc.cbWndExtra = 0;
wc.hInstance = instance;
wc.hIcon = NULL;
wc.hCursor = 0;
wc.hbrBackground = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = socketWinClass;
return RegisterClass(&wc);
}
/* Initialise WINSOCK
*/
BOOL socketInit(HINSTANCE instance)
{
int ret;
if ((ret = WSAStartup(SOCKLIB_VERSION, &WSAData))!=0) {
socketError("WSAStartup()", ret);
return FALSE;
}
sockWnd = CreateWindow(socketWinClass, "", 0,
0, 0, 0, 0,
NULL, NULL, instance, NULL);
if (!sockWnd) {
if (WSACleanup())
socketError("WSACleanup()", WSAGetLastError());
return FALSE;
}
return TRUE;
}
/* Unregister with WINSOCK
*/
void socketCleanup()
{
if (WSAIsBlocking())
if (WSACancelBlockingCall())
;
if (WSACleanup())
;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -