home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / winnt / pop3 / socket.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  7.1 KB  |  276 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples.
  4. *       Copyright (C) 1992-1997 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. //+---------------------------------------------------------------------------
  13. //
  14. //  File:       pop3svr.c
  15. //
  16. //  Contents:
  17. //
  18. //  Classes:
  19. //
  20. //  Functions:
  21. //
  22. //----------------------------------------------------------------------------
  23.  
  24. #include "pop3srvp.h"
  25. #pragma hdrstop
  26.  
  27. extern BOOL bServiceTerminating;
  28. extern SOCKET sListener;
  29.  
  30. #define POP3_PORT 110
  31.  
  32. PCHAR Welcome = "+OK Welcome to the NT Example POP3 Server (POP3SRV)\r\n";
  33.  
  34. BOOL
  35. AcceptClients (
  36.     HANDLE hCompletionPort
  37.     )
  38.  
  39. /*++
  40.  
  41. Routine Description:
  42.  
  43.     This routine sets up a listening socket on the POP3 port, then
  44.     loops accepting incoming connections from clients.  Whenever
  45.     it gets a connection, it sends the greeting message and starts
  46.     a read on the newly connected socket.
  47.  
  48. Arguments:
  49.  
  50.     hCompletionPort - the completion port that the POP3SRV worker 
  51.         threads are waiting on.  
  52.  
  53. Return Value:
  54.  
  55.     BOOL - FALSE if there was an error in starting the listening
  56.         socket.
  57.  
  58. --*/
  59.  
  60. {
  61.     SOCKET s;
  62.     SOCKADDR_IN sin;
  63.     int err;
  64.     BOOL bSuccess;
  65.     PCLIENT_CONTEXT lpClientContext;
  66.     DWORD dwBytesRead;
  67.     int zero;
  68.  
  69.     //
  70.     // Create a listening socket that we'll use to accept incoming
  71.     // conections.
  72.     //
  73.  
  74.     sListener = socket( AF_INET, SOCK_STREAM, 0 );
  75.     if ( sListener == INVALID_SOCKET ) {
  76.         return FALSE;
  77.     }
  78.  
  79.     //
  80.     // Bind the socket to the POP3 well-known port.
  81.     //
  82.  
  83.     sin.sin_family = AF_INET;
  84.     sin.sin_port = htons( POP3_PORT );
  85.     sin.sin_addr.s_addr = INADDR_ANY;
  86.  
  87.     err = bind( sListener, (LPSOCKADDR)&sin, sizeof(sin) );
  88.     if ( err == SOCKET_ERROR ) {
  89.         closesocket( sListener );
  90.         return FALSE;
  91.     }
  92.  
  93.     //
  94.     // Listen for incoming connections on the socket.
  95.     //
  96.  
  97.     err = listen( sListener, 5 );
  98.     if ( err == SOCKET_ERROR ) {
  99.         closesocket( sListener );
  100.         return FALSE;
  101.     }
  102.  
  103.     //
  104.     // Loop forever accepting connections from clients.
  105.     //
  106.  
  107.     while ( TRUE ) {
  108.  
  109.         s = accept( sListener, NULL, NULL );
  110.         if ( s == INVALID_SOCKET ) {
  111.             closesocket( sListener );
  112.             return FALSE;
  113.         }
  114.  
  115.         //
  116.         // If the service if terminating, exit this thread.
  117.         //
  118.  
  119.         if ( bServiceTerminating ) {
  120.             return FALSE;
  121.         }
  122.  
  123.         //
  124.         // Allocate a socket context for the new connection.  We use
  125.         // this context structure to track socket-level information
  126.         // about the client.
  127.         //
  128.  
  129.         lpClientContext = LocalAlloc( 0, sizeof(*lpClientContext) );
  130.         if ( lpClientContext == NULL ) {
  131.             closesocket( s );
  132.             continue;
  133.         }
  134.  
  135.         //
  136.         // Initialize the context structure.
  137.         //
  138.  
  139.         lpClientContext->Socket = s;
  140.         lpClientContext->Context = CreatePop3Context( );
  141.         lpClientContext->Overlapped.Internal = 0;
  142.         lpClientContext->Overlapped.InternalHigh = 0;
  143.         lpClientContext->Overlapped.Offset = 0;
  144.         lpClientContext->Overlapped.OffsetHigh = 0;
  145.         lpClientContext->Overlapped.hEvent = NULL;
  146.  
  147.         //
  148.         // Send the welcome banner.
  149.         //
  150.  
  151.         err = send( s, Welcome, strlen(Welcome), 0 );
  152.         if ( err == SOCKET_ERROR ) {
  153.             LocalFree( lpClientContext );
  154.             closesocket( s );
  155.             continue;
  156.         }
  157.  
  158.         // --- DavidTr: Slide 14(a) ----------------------------------------
  159.         //
  160.         // Associate the new socket with a completion port.
  161.         //
  162.  
  163.         hCompletionPort = CreateIoCompletionPort(
  164.                               (HANDLE)s,
  165.                               hCompletionPort,
  166.                               (DWORD)lpClientContext,
  167.                               0
  168.                               );
  169.         if ( hCompletionPort == NULL ) {
  170.             LocalFree( lpClientContext );
  171.             closesocket( s );
  172.             closesocket( sListener );
  173.             return FALSE;
  174.         }
  175.  
  176.         // --- DavidTr: Slide 16 -------------------------------------------
  177.         //
  178.         // Disable send bufferring on the socket.  Setting SO_SNDBUF
  179.         // to 0 causes winsock to stop bufferring sends and perform
  180.         // sends directly from our buffers, thereby reducing CPU
  181.         // usage.
  182.         //
  183.  
  184.         zero = 0;
  185.         err = setsockopt( s, SOL_SOCKET, SO_SNDBUF, (char *)&zero, sizeof(zero) );
  186.         if ( err == SOCKET_ERROR ) {
  187.             LocalFree( lpClientContext );
  188.             closesocket( s );
  189.             closesocket( sListener );
  190.             return FALSE;
  191.         }
  192.  
  193.         //
  194.         // Start an overlapped read on the socket.  This read will
  195.         // complete in one of the worker threads, which will continue
  196.         // processing of the client.
  197.         //
  198.  
  199.         lpClientContext->LastClientIo = ClientIoRead;
  200.         lpClientContext->BytesReadSoFar = 0;
  201.  
  202.         bSuccess = ReadFile(
  203.                        (HANDLE)s,
  204.                        lpClientContext->Buffer,
  205.                        sizeof(lpClientContext->Buffer),
  206.                        &dwBytesRead,
  207.                        &lpClientContext->Overlapped
  208.                        );
  209.         if ( !bSuccess && GetLastError( ) != ERROR_IO_PENDING ) {
  210.             LocalFree( lpClientContext );
  211.             closesocket( s );
  212.             continue;
  213.         }
  214.     }
  215.  
  216. } // AcceptClients
  217.  
  218.  
  219. VOID
  220. CloseClient (
  221.     PCLIENT_CONTEXT lpClientContext,
  222.     BOOL bGraceful
  223.     )
  224.  
  225. /*++
  226.  
  227. Routine Description:
  228.  
  229.     Terminates a connection with a client and frees up resources.
  230.  
  231. Arguments:
  232.  
  233.     lpClientContext - a pointer to the context structure that contains
  234.         information about this client.
  235.  
  236.     bGraceful - TRUE if the close should be graceful, FALSE otherwise.
  237.  
  238. Return Value:
  239.  
  240.     None.
  241.  
  242. --*/
  243.  
  244. {
  245.     LINGER lingerStruct;
  246.  
  247.     //
  248.     // If we're supposed to abort the connection, set the linger value
  249.     // on the socket to 0.
  250.     //
  251.  
  252.     if ( !bGraceful ) {
  253.         lingerStruct.l_onoff = 1;
  254.         lingerStruct.l_linger = 0;
  255.         setsockopt( lpClientContext->Socket, SOL_SOCKET, SO_LINGER,
  256.                     (char *)&lingerStruct, sizeof(lingerStruct) );
  257.     }
  258.  
  259.     //
  260.     // Now close the socket handle.  This will do an abortive or 
  261.     // graceful close, as requested.  
  262.     //
  263.  
  264.     closesocket( lpClientContext->Socket );
  265.  
  266.     //
  267.     // Free context structuyres.
  268.     //
  269.  
  270.     LocalFree( lpClientContext->Context );
  271.     LocalFree( lpClientContext );
  272.  
  273.     return;
  274.     
  275. } // CloseClient
  276.