home *** CD-ROM | disk | FTP | other *** search
-
- // Contents ---------------------------------------------------------------
- //
- // clients.c -- a Windows Socket Finger Daemon
- //
- // Version 1.0
- //
- // Copyright (C) Frederick W. Bent 1994
- // All rights reserved.
- //
- //
- // Description
- //
- // FINGERD is both the user interface and the network interface.
- // FINGERD is a server, its 'users' are FINGER clients, so the user
- // interface requirements of the daemon are rather simple. FINGERD
- // simply updates its display with outbound buffer traffic. We also
- // display winsock errors in the server display.
- //
- // FINGERD uses WSAAsyncSelect() to receive the SOCKET_MESSAGE window
- // messages that notify FINGERD of pending client requests, causing
- // FINGERD to respond. When an FD_ACCEPT is received, the socket is
- // added to the linked list of clients.
- //
- // FINGERD speaks the finger protocol, and will reply to finger
- // (e.g., the MS-Windows 3.x winsock finger client).
- //
- // Ends -------------------------------------------------------------------
-
- // History ----------------------------------------------------------------
- //
- // 6/28/94 1.0 Fred Bent First release
- //
- // Ends -------------------------------------------------------------------
-
- // Legal Stuff ------------------------------------------------------------
- //
- // Permission to use, modify, and distribute this software and its
- // documentation for any purpose and without fee is hereby granted,
- // provided that the above copyright notice appears in all copies and
- // that both that copyright notice and this permission notice appear in
- // supporting documentation. The author makes no claims as to the
- // suitability of this software and documentation for any purpose.
- //
- // Legal Stuff Ends -------------------------------------------------------
-
- // Interface Dependencies -------------------------------------------------
-
- #define STRICT
-
- #include <windows.h>
- #include <windowsx.h>
- #include <winsock.h>
- #include "fingerd.h"
-
- // End Interface Dependencies ---------------------------------------------
-
- // External Declarations --------------------------------------------------
-
- extern SOCKET sListen; // awaits connection requests
- extern HWND hwndNetwork; // our invisible network "window"
- extern char szNetworkClass[]; // class name of network window
-
- // End External Declarations ----------------------------------------------
-
-
- // Function
-
- LPCLIENT fingerAddClient(SOCKET sSocket)
-
- // Summary ----------------------------------------------------------------
- //
- // Adds a client to the linked list of clients. The client is
- // also initialized by this function.
- //
- //
- // Parameters
- //
- // sSocket
- //
- // The client socket to be added to the client list.
- //
- // Return
- //
- // LPCLIENT Returns a pointer to the new client, or NULL
- //
- // Ends -------------------------------------------------------------------
-
- {
- int iRcvSize;
- int iSndSize;
- int iSizeofRcvSize;
-
- HGLOBAL hInput, hOutput;
- LPSTR lpInput, lpOutput;
-
- HCLIENT hClient;
- LPCLIENT lpClient, lpWalker;
-
- /* Determine the receive buffer size */
-
- iSizeofRcvSize = sizeof(iRcvSize);
- getsockopt( sSocket
- , SOL_SOCKET, SO_RCVBUF
- , (char FAR*)&iRcvSize, (int FAR*)&iSizeofRcvSize);
-
- getsockopt( sSocket
- , SOL_SOCKET, SO_SNDBUF
- , (char FAR*)&iSndSize, (int FAR*)&iSizeofRcvSize);
-
- /* Make sure it's not too small... */
- if ( iRcvSize < SENDBUFLEN ) iRcvSize = SENDBUFLEN;
- if ( iSndSize > SENDBUFLEN ) iSndSize = SENDBUFLEN;
-
- /* Want receive buffer */
- iRcvSize = iRcvSize * 2;
- hInput = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, iRcvSize);
- if ( hInput == NULL ) return(NULL);
-
- /* Now get a pointer to it */
- lpInput = GlobalLock(hInput);
- if (lpInput == NULL )
- {
- GlobalFree(hInput);
- return(NULL);
- }
-
- /* The send buffer it determined by us, so easier */
- hOutput = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, SENDBUFLEN);
- if ( hOutput == NULL )
- {
- GlobalUnlock(hInput);
- GlobalFree(hInput);
- return(NULL);
- }
- lpOutput = GlobalLock(hOutput);
- if ( lpOutput == NULL )
- {
- GlobalFree(hOutput);
- GlobalUnlock(hInput);
- GlobalFree(hInput);
- return(NULL);
- }
-
- /* Ok, now allocate a LPCLIENT */
- hClient = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(CLIENT));
- if ( hClient == NULL )
- {
- GlobalUnlock(hOutput);
- GlobalFree(hOutput);
- GlobalUnlock(hInput);
- GlobalFree(hInput);
- return(NULL);
- }
- lpClient = (LPCLIENT)GlobalLock(hClient);
- if ( lpClient == NULL )
- {
- GlobalFree(hClient);
- GlobalUnlock(hOutput);
- GlobalFree(hOutput);
- GlobalUnlock(hInput);
- GlobalFree(hInput);
- return(NULL);
- }
-
- lpClient->sSocket = sSocket;
- lpClient->hClient = hClient;
- lpClient->hfFile = HFILE_ERROR;
-
- lpClient->iExtErr = 0;
-
- lpClient->iState = STATE_WAIT_FOR_USER;
-
- lpClient->lpOutputBuffer = lpOutput;
- lpClient->hOutputBuffer = hOutput;
- lpClient->lpInputBuffer = lpInput;
- lpClient->hInputBuffer = hInput;
-
- /* OutputSize is SENDBUFLEN */
-
- lpClient->iInputSize = iRcvSize;
- lpClient->iOutputSize = iSndSize;
-
- lpClient->fifoOutputStart = 0;
- lpClient->fifoOutputStop = 0;
- lpClient->fifoOutputFull = FALSE;
- lpClient->fifoInputStart = 0;
- lpClient->fifoInputStop = 0;
- lpClient->fifoInputFull = FALSE;
-
- lpClient->lpNextClient=NULL;
- lpClient->lpPrevClient=NULL;
-
- if (fingerClientsHead == NULL)
- {
- fingerClientsHead = lpClient;
- } else {
- lpWalker = fingerClientsHead;
- while (lpWalker->lpNextClient != NULL)
- lpWalker = lpWalker->lpNextClient;
- lpWalker->lpNextClient = lpClient;
- lpClient->lpPrevClient = lpWalker;
- }
-
- return(lpClient);
- }
-
-
- // Function
-
- LPCLIENT fingerSocketToClient(SOCKET sSocket)
-
- // Summary ----------------------------------------------------------------
- //
- // Given a socket, find the client in the list.
- //
- // Parameters
- //
- // sSocket
- //
- // The socket that we want to find
- //
- // Return
- //
- // LPCLIENT Returns NULL if not found.
- //
- // Ends -------------------------------------------------------------------
-
- {
- LPCLIENT lpClient;
-
- lpClient = fingerClientsHead;
- if (sSocket == INVALID_SOCKET) return(NULL);
-
- while (lpClient != NULL)
- {
- if (lpClient->sSocket == sSocket) return(lpClient);
- lpClient = lpClient->lpNextClient;
- }
- return(lpClient);
- }
-
-
- // Function
-
- BOOL fingerDestroyClient(LPCLIENT lpClient)
-
- // Summary ----------------------------------------------------------------
- //
- // Free the memory used by the client and close the socket. Also
- // will close the file if it is still open.
- //
- // Parameters
- //
- // lpClient
- //
- // A far pointer to the CLIENT data structure to be destroyed.
- //
- // Return
- //
- // BOOL Returns TRUE if error
- //
- // Ends -------------------------------------------------------------------
-
- {
- LPCLIENT lpNext, lpPrev;
- HCLIENT hClient;
- int err;
-
- if (lpClient == NULL) return(TRUE);
-
- lpClient->iState = STATE_CLOSING;
-
- /* Perform a graceful termination */
- err = shutdown(lpClient->sSocket, 1); // no sending now
-
- if ( err == SOCKET_ERROR ) {
- DisplayWSError("Error during shutdown.");
- }
-
- /* Get all remaining data, if any... */
-
- while( (err = recv(lpClient->sSocket, lpClient->lpInputBuffer, lpClient->iInputSize, 0)) != 0 )
- {
- if (err == SOCKET_ERROR)
- {
- err = WSAGetLastError();
- if ( err != WSAEWOULDBLOCK )
- {
- lpClient->iState = STATE_WSERROR;
- WSASetLastError(err);
- DisplayWSError("Error getting last data from socket.");
- }
- break;
- }
- }
-
- /* turn off all messages, its now a blocking socket */
- (void) netSelectEvents(lpClient, 0);
-
- /* now close the socket, will also flush send buffers */
-
- closesocket(lpClient->sSocket);
-
- fingerLog(DEBUG_HIGH | LOG_TIME, IDS_DISCONNECT_S, (LPSTR)lpClient->szPeer);
-
- /* If file still open, then close it... */
-
- if (lpClient->hfFile != HFILE_ERROR)
- {
- _lclose(lpClient->hfFile);
- }
-
- /* Patch the client links */
-
- lpNext = lpClient->lpNextClient;
- lpPrev = lpClient->lpPrevClient;
-
- /* Is this the first "head" entry? */
- if ( lpPrev != NULL )
- {
- lpPrev->lpNextClient = lpNext;
- } else {
- fingerClientsHead = lpNext;
- }
-
- if ( lpNext != NULL )
- lpNext->lpPrevClient = lpPrev;
-
-
- /* Now free the memory */
- GlobalUnlock(lpClient->hInputBuffer);
- GlobalFree(lpClient->hInputBuffer);
- GlobalUnlock(lpClient->hOutputBuffer);
- GlobalFree(lpClient->hOutputBuffer);
-
- /* Once lpClient is unlocked, lpClient is invalid */
- hClient = lpClient->hClient;
- GlobalUnlock(lpClient->hClient);
- GlobalFree(hClient);
-
- return(FALSE);
- }
-
-