home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / winsock / fingd100 / src / clients.c next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  8.8 KB  |  345 lines

  1.  
  2. // Contents ---------------------------------------------------------------
  3. //
  4. //   clients.c  -- a Windows Socket Finger Daemon
  5. //
  6. //   Version 1.0
  7. //
  8. //   Copyright (C) Frederick W. Bent 1994
  9. //   All rights reserved.
  10. //
  11. //
  12. // Description
  13. //
  14. //      FINGERD is both the user interface and the network interface.
  15. //    FINGERD is a server, its 'users' are FINGER clients, so the user
  16. //    interface requirements of the daemon are rather simple.  FINGERD
  17. //      simply updates its display with outbound buffer traffic.  We also
  18. //      display winsock errors in the server display.
  19. //
  20. //      FINGERD uses WSAAsyncSelect() to receive the SOCKET_MESSAGE window
  21. //      messages that notify FINGERD of pending client requests, causing
  22. //    FINGERD to respond.  When an FD_ACCEPT is received, the socket is
  23. //      added to the linked list of clients.
  24. //
  25. //      FINGERD speaks the finger protocol, and will reply to finger
  26. //    (e.g., the MS-Windows 3.x winsock finger client).
  27. //
  28. // Ends -------------------------------------------------------------------
  29.  
  30. // History ----------------------------------------------------------------
  31. //
  32. // 6/28/94  1.0  Fred Bent    First release
  33. //
  34. // Ends -------------------------------------------------------------------
  35.  
  36. // Legal Stuff ------------------------------------------------------------
  37. //
  38. // Permission to use, modify, and distribute this software and its
  39. // documentation for any purpose and without fee is hereby granted,
  40. // provided that the above copyright notice appears in all copies and
  41. // that both that copyright notice and this permission notice appear in
  42. // supporting documentation.  The author makes no claims as to the
  43. // suitability of this software and documentation for any purpose.
  44. //
  45. // Legal Stuff Ends -------------------------------------------------------
  46.  
  47. // Interface Dependencies -------------------------------------------------
  48.  
  49. #define STRICT
  50.  
  51. #include <windows.h>
  52. #include <windowsx.h>
  53. #include <winsock.h>
  54. #include "fingerd.h"
  55.  
  56. // End Interface Dependencies ---------------------------------------------
  57.  
  58. // External Declarations --------------------------------------------------
  59.  
  60. extern  SOCKET  sListen;          // awaits connection requests
  61. extern    HWND    hwndNetwork;      // our invisible network "window"
  62. extern  char    szNetworkClass[]; // class name of network window
  63.  
  64. // End External Declarations ----------------------------------------------
  65.  
  66.  
  67. // Function
  68.  
  69.     LPCLIENT    fingerAddClient(SOCKET sSocket)
  70.  
  71. // Summary ----------------------------------------------------------------
  72. //
  73. //    Adds a client to the linked list of clients.  The client is
  74. //    also initialized by this function.
  75. //
  76. //
  77. // Parameters
  78. //
  79. //      sSocket
  80. //
  81. //    The client socket to be added to the client list.
  82. //
  83. // Return
  84. //
  85. //    LPCLIENT    Returns a pointer to the new client, or NULL
  86. //
  87. // Ends -------------------------------------------------------------------
  88.  
  89.     {
  90.         int    iRcvSize;
  91.         int    iSndSize;
  92.         int    iSizeofRcvSize;
  93.  
  94.         HGLOBAL    hInput, hOutput;
  95.         LPSTR    lpInput, lpOutput;
  96.  
  97.         HCLIENT    hClient;
  98.         LPCLIENT lpClient, lpWalker;
  99.  
  100.         /* Determine the receive buffer size */
  101.  
  102.         iSizeofRcvSize = sizeof(iRcvSize);
  103.         getsockopt( sSocket
  104.               , SOL_SOCKET, SO_RCVBUF
  105.               , (char FAR*)&iRcvSize, (int FAR*)&iSizeofRcvSize);
  106.  
  107.         getsockopt( sSocket
  108.               , SOL_SOCKET, SO_SNDBUF
  109.               , (char FAR*)&iSndSize, (int FAR*)&iSizeofRcvSize);
  110.  
  111.         /* Make sure it's not too small... */
  112.         if ( iRcvSize < SENDBUFLEN ) iRcvSize = SENDBUFLEN;
  113.         if ( iSndSize > SENDBUFLEN ) iSndSize = SENDBUFLEN;
  114.  
  115.         /* Want receive buffer */
  116.         iRcvSize = iRcvSize * 2;
  117.         hInput = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, iRcvSize);
  118.         if ( hInput == NULL ) return(NULL);
  119.  
  120.         /* Now get a pointer to it */
  121.         lpInput = GlobalLock(hInput);
  122.         if (lpInput == NULL )
  123.         {
  124.             GlobalFree(hInput);
  125.             return(NULL);
  126.         }
  127.  
  128.         /* The send buffer it determined by us, so easier */
  129.         hOutput = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, SENDBUFLEN);
  130.         if ( hOutput == NULL )
  131.         {
  132.             GlobalUnlock(hInput);
  133.             GlobalFree(hInput);
  134.             return(NULL);
  135.         }
  136.         lpOutput = GlobalLock(hOutput);
  137.         if ( lpOutput == NULL )
  138.         {
  139.             GlobalFree(hOutput);
  140.             GlobalUnlock(hInput);
  141.             GlobalFree(hInput);
  142.             return(NULL);
  143.         }
  144.  
  145.         /* Ok, now allocate a LPCLIENT */
  146.         hClient = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(CLIENT));
  147.         if ( hClient == NULL )
  148.         {
  149.             GlobalUnlock(hOutput);
  150.             GlobalFree(hOutput);
  151.             GlobalUnlock(hInput);
  152.             GlobalFree(hInput);
  153.             return(NULL);
  154.         }
  155.         lpClient = (LPCLIENT)GlobalLock(hClient);
  156.         if ( lpClient == NULL )
  157.         {
  158.             GlobalFree(hClient);
  159.             GlobalUnlock(hOutput);
  160.             GlobalFree(hOutput);
  161.             GlobalUnlock(hInput);
  162.             GlobalFree(hInput);
  163.             return(NULL);
  164.         }
  165.  
  166.         lpClient->sSocket = sSocket;
  167.         lpClient->hClient = hClient;
  168.         lpClient->hfFile = HFILE_ERROR;
  169.  
  170.         lpClient->iExtErr = 0;
  171.  
  172.         lpClient->iState = STATE_WAIT_FOR_USER;
  173.  
  174.         lpClient->lpOutputBuffer = lpOutput;
  175.         lpClient->hOutputBuffer = hOutput;
  176.         lpClient->lpInputBuffer = lpInput;
  177.         lpClient->hInputBuffer = hInput;
  178.  
  179.         /* OutputSize is SENDBUFLEN */
  180.  
  181.         lpClient->iInputSize = iRcvSize;
  182.         lpClient->iOutputSize = iSndSize;
  183.  
  184.         lpClient->fifoOutputStart = 0;
  185.         lpClient->fifoOutputStop = 0;
  186.         lpClient->fifoOutputFull = FALSE;
  187.         lpClient->fifoInputStart = 0;
  188.         lpClient->fifoInputStop = 0;
  189.         lpClient->fifoInputFull = FALSE;
  190.  
  191.         lpClient->lpNextClient=NULL;
  192.         lpClient->lpPrevClient=NULL;
  193.  
  194.         if (fingerClientsHead == NULL)
  195.         {
  196.             fingerClientsHead = lpClient;
  197.         } else {
  198.             lpWalker = fingerClientsHead;
  199.             while (lpWalker->lpNextClient != NULL)
  200.                 lpWalker = lpWalker->lpNextClient;
  201.             lpWalker->lpNextClient = lpClient;
  202.             lpClient->lpPrevClient = lpWalker;
  203.         }
  204.  
  205.         return(lpClient);
  206.     }
  207.  
  208.  
  209. // Function
  210.  
  211.     LPCLIENT fingerSocketToClient(SOCKET sSocket)
  212.  
  213. // Summary ----------------------------------------------------------------
  214. //
  215. //    Given a socket, find the client in the list.
  216. //
  217. // Parameters
  218. //
  219. //      sSocket
  220. //
  221. //    The socket that we want to find
  222. //
  223. // Return
  224. //
  225. //    LPCLIENT    Returns NULL if not found.
  226. //
  227. // Ends -------------------------------------------------------------------
  228.  
  229.     {
  230.         LPCLIENT lpClient;
  231.  
  232.         lpClient = fingerClientsHead;
  233.         if (sSocket == INVALID_SOCKET) return(NULL);
  234.  
  235.         while (lpClient != NULL)
  236.         {
  237.             if (lpClient->sSocket == sSocket) return(lpClient);
  238.             lpClient = lpClient->lpNextClient;
  239.         }
  240.         return(lpClient);
  241.     }
  242.  
  243.  
  244. // Function
  245.  
  246.     BOOL fingerDestroyClient(LPCLIENT lpClient)
  247.  
  248. // Summary ----------------------------------------------------------------
  249. //
  250. //    Free the memory used by the client and close the socket. Also
  251. //    will close the file if it is still open.
  252. //
  253. // Parameters
  254. //
  255. //         lpClient
  256. //
  257. //    A far pointer to the CLIENT data structure to be destroyed.
  258. //
  259. // Return
  260. //
  261. //    BOOL    Returns TRUE if error
  262. //
  263. // Ends -------------------------------------------------------------------
  264.  
  265.     {
  266.         LPCLIENT lpNext, lpPrev;
  267.         HCLIENT    hClient;
  268.         int    err;
  269.  
  270.         if (lpClient == NULL) return(TRUE);
  271.  
  272.         lpClient->iState = STATE_CLOSING;
  273.  
  274.         /* Perform a graceful termination */
  275.         err = shutdown(lpClient->sSocket, 1);    // no sending now
  276.  
  277.         if ( err == SOCKET_ERROR ) {
  278.             DisplayWSError("Error during shutdown.");
  279.         }
  280.  
  281.         /* Get all remaining data, if any... */
  282.  
  283.         while( (err = recv(lpClient->sSocket, lpClient->lpInputBuffer, lpClient->iInputSize, 0)) != 0 )
  284.         {
  285.             if (err == SOCKET_ERROR)
  286.                         {
  287.                 err = WSAGetLastError();
  288.                 if ( err != WSAEWOULDBLOCK )
  289.                 {
  290.                     lpClient->iState = STATE_WSERROR;
  291.                                     WSASetLastError(err);
  292.                     DisplayWSError("Error getting last data from socket.");
  293.                 }
  294.         break;
  295.                         }
  296.         }
  297.  
  298.         /* turn off all messages, its now a blocking socket */
  299.         (void) netSelectEvents(lpClient, 0);
  300.  
  301.         /* now close the socket, will also flush send buffers */
  302.  
  303.         closesocket(lpClient->sSocket);
  304.  
  305.         fingerLog(DEBUG_HIGH | LOG_TIME, IDS_DISCONNECT_S, (LPSTR)lpClient->szPeer);
  306.  
  307.         /* If file still open, then close it... */
  308.  
  309.         if (lpClient->hfFile != HFILE_ERROR)
  310.         {
  311.             _lclose(lpClient->hfFile);
  312.         }
  313.  
  314.         /* Patch the client links */
  315.  
  316.         lpNext = lpClient->lpNextClient;
  317.         lpPrev = lpClient->lpPrevClient;
  318.  
  319.         /* Is this the first "head" entry? */
  320.         if ( lpPrev != NULL )
  321.         {
  322.             lpPrev->lpNextClient = lpNext;
  323.         } else {
  324.             fingerClientsHead = lpNext;
  325.         }
  326.  
  327.         if ( lpNext != NULL )
  328.                     lpNext->lpPrevClient = lpPrev;
  329.  
  330.  
  331.         /* Now free the memory */
  332.         GlobalUnlock(lpClient->hInputBuffer);
  333.         GlobalFree(lpClient->hInputBuffer);
  334.         GlobalUnlock(lpClient->hOutputBuffer);
  335.         GlobalFree(lpClient->hOutputBuffer);
  336.  
  337.         /* Once lpClient is unlocked, lpClient is invalid */
  338.         hClient = lpClient->hClient;
  339.         GlobalUnlock(lpClient->hClient);
  340.         GlobalFree(hClient);
  341.  
  342.         return(FALSE);
  343.     }
  344.  
  345.