home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / software / pelne / optionp / iis4_07.cab / KeepAliveP.c < prev    next >
C/C++ Source or Header  |  1997-10-25  |  7KB  |  323 lines

  1. /*++
  2.  
  3. Copyright (c) 1997  Microsoft Corporation
  4.  
  5. Module Name: KeepAliveP.c
  6.  
  7. Abstract:
  8.  
  9.       Sample ISAPI Extension demonstrating Keep-Alive with a thread pool.
  10.  
  11. --*/
  12.  
  13. #define WIN32_LEAN_AND_MEAN
  14. #include <windows.h>
  15. #include <httpext.h>
  16. #include <stdio.h>
  17. #include "threadpool.h"
  18.  
  19. BOOL WINAPI 
  20. DllMain( 
  21.     IN HINSTANCE hinstDll, 
  22.     IN DWORD fdwReason, 
  23.     IN LPVOID lpvContext
  24. /*++
  25.  
  26. Purpose:
  27.     
  28.     Initialize the thread pool when the DLL is loaded by IIS.
  29.  
  30. Arguments:
  31.  
  32.     hinstDLL - DLL instance handle
  33.     fdwReason - notification code
  34.     lpdvContext - reserved
  35.  
  36. Returns:
  37.  
  38.     TRUE if notification was successfully processed by the DLL
  39.     FALSE to indicate a failure
  40.  
  41. --*/
  42. {
  43.     BOOL fReturn = TRUE;
  44.  
  45.     switch ( fdwReason ) {
  46.  
  47.     case DLL_PROCESS_ATTACH:
  48.         fReturn = InitThreadPool( );
  49.         break;
  50.     }
  51.  
  52.     return fReturn;
  53. }
  54.  
  55.  
  56. BOOL WINAPI 
  57. GetExtensionVersion( 
  58.     OUT HSE_VERSION_INFO * pVer
  59. )
  60. /*++
  61.  
  62. Purpose:
  63.  
  64.     This is required ISAPI Extension DLL entry point.
  65.  
  66. Arguments:
  67.  
  68.     pVer - poins to extension version info structure 
  69.  
  70. Returns:
  71.  
  72.     always returns TRUE
  73.  
  74. --*/
  75. {
  76.     pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR );
  77.     lstrcpyn( 
  78.         pVer->lpszExtensionDesc, 
  79.         "ISAPI Keep-Alive with Thread Pool Extension Sample",
  80.         HSE_MAX_EXT_DLL_NAME_LEN );
  81.  
  82.     return TRUE;
  83. }
  84.  
  85.  
  86. DWORD WINAPI 
  87. HttpExtensionProc( 
  88.     IN EXTENSION_CONTROL_BLOCK * pECB
  89. )
  90. /*++
  91.  
  92. Purpose:
  93.     Demonstrate usage of persistent connections serviced by a thread pool.
  94.  
  95. Arguments:
  96.  
  97.     pECB - points to the extension control block
  98.  
  99. Returns:
  100.     
  101.     HSE_STATUS_PENDING if request was successfully queued 
  102.     HSE_SUCCESS_AND_KEEP_CONN if request was served immediately
  103.         (presumably because the queue was full)
  104.  
  105. --*/
  106. {
  107.     DWORD dwSize;
  108.     HSE_SEND_HEADER_EX_INFO HeaderExInfo;
  109.  
  110.     char szHeader[] = 
  111.         "Connection: Keep-Alive\r\n"
  112.         "Content-Length: %lu\r\n"
  113.         "Content-type: text/html\r\n\r\n";
  114.  
  115.     char szBusyMessage[] = 
  116.         "<html> <form method=get action=KeepAliveP.dll> <input type=submit> "
  117.         "<br>pECB->ConnID=%lu  <br>Server was too busy. </form></html>";
  118.  
  119.     char szBuffer[4096];
  120.     char szBuffer2[4096];
  121.  
  122.     EnterCriticalSection( &csQueueLock );
  123.  
  124.     if ( !AddWorkQueueEntry( pECB ) ) {
  125.  
  126.         //
  127.         // if ECB could not be assigned
  128.         //
  129.  
  130.         LeaveCriticalSection( &csQueueLock );
  131.  
  132.         sprintf( szBuffer2, szBusyMessage, pECB->ConnID );
  133.  
  134.         //
  135.         // Send outgoing header
  136.         //
  137.  
  138.         sprintf( szBuffer, szHeader, strlen( szBuffer2 ) );
  139.  
  140.         HeaderExInfo.pszHeader = szBuffer;
  141.         HeaderExInfo.cchHeader = strlen( szBuffer );
  142.         HeaderExInfo.pszStatus = "200 OK";
  143.         HeaderExInfo.cchStatus = strlen( HeaderExInfo.pszStatus );
  144.         HeaderExInfo.fKeepConn = TRUE;
  145.  
  146.  
  147.         pECB->ServerSupportFunction( 
  148.             pECB->ConnID, 
  149.             HSE_REQ_SEND_RESPONSE_HEADER_EX,
  150.             &HeaderExInfo,
  151.             NULL,
  152.             NULL
  153.             );
  154.  
  155.         //
  156.         // Send content
  157.         //
  158.  
  159.         dwSize = strlen( szBuffer2 );
  160.         pECB->WriteClient( pECB->ConnID, szBuffer2, &dwSize, 0 );
  161.  
  162.         return HSE_STATUS_SUCCESS_AND_KEEP_CONN;
  163.  
  164.     } else {
  165.  
  166.         //
  167.         // release 1 thread from the pool
  168.         //
  169.  
  170.         ReleaseSemaphore( hWorkSem, 1, NULL );
  171.  
  172.         LeaveCriticalSection( &csQueueLock );
  173.     }
  174.  
  175.     return HSE_STATUS_PENDING;
  176. }
  177.  
  178.  
  179. BOOL WINAPI
  180. TerminateExtension( 
  181.     IN DWORD dwFlags 
  182. )
  183. /*++
  184.  
  185. Routine Description:
  186.  
  187.     This function is called when the WWW service is shutdown
  188.  
  189. Arguments:
  190.  
  191.     dwFlags - HSE_TERM_ADVISORY_UNLOAD or HSE_TERM_MUST_UNLOAD
  192.  
  193. Return Value:
  194.  
  195.     TRUE if extension is ready to be unloaded,
  196.     FALSE otherwise
  197.  
  198. --*/
  199. {
  200.     return TRUE;
  201. }
  202.  
  203.  
  204.  
  205. DWORD WINAPI 
  206. WorkerFunction( 
  207.     IN LPVOID pvThreadNum
  208. )
  209. /*++
  210.  
  211. Purpose:
  212.     
  213.     Worker thread function - simulates extended processing
  214.     of the HTTP request
  215.  
  216. Arguments:
  217.  
  218.     pvThreadNum - thread number
  219.  
  220. Returns:
  221.     
  222.     alsways returns 0
  223.  
  224. --*/
  225. {
  226.     EXTENSION_CONTROL_BLOCK *pECB;
  227.     DWORD dwRet, dwState, dwSize, dwThreadNum;
  228.     HSE_SEND_HEADER_EX_INFO HeaderExInfo;
  229.  
  230.     //This header will be filled in with the content length
  231.     char szHeader[] = 
  232.         "Connection: Keep-Alive\r\nContent-Length: %lu\r\n"
  233.         "Content-type: text/html\r\n\r\n";
  234.  
  235.     char szContent[] = 
  236.         "<html> <form method=get action=KeepAliveP.dll><input type=submit> " 
  237.         "<br>pECB->ConnID=%lu  <br>dwThreadNum=%lu</form></html>";
  238.  
  239.     char szBuffer[4096];
  240.     char szBuffer2[4096];
  241.  
  242.     dwThreadNum = ( DWORD ) pvThreadNum;
  243.  
  244.     while ( TRUE ) {
  245.  
  246.         dwRet = WaitForSingleObject( hWorkSem, INFINITE );
  247.         if ( dwRet == WAIT_OBJECT_0 ) {
  248.  
  249.             EnterCriticalSection( &csQueueLock );
  250.  
  251.             if ( GetWorkQueueEntry( &pECB ) ) {    
  252.                 
  253.                 //
  254.                 // Found work to do
  255.                 //
  256.  
  257.                 LeaveCriticalSection( &csQueueLock );
  258.  
  259.                 sprintf( szBuffer2, szContent, pECB->ConnID, dwThreadNum );
  260.  
  261.                 // Send outgoing header
  262.                 sprintf( szBuffer, szHeader, strlen( szBuffer2 ) );
  263.  
  264.                 HeaderExInfo.pszHeader = szBuffer;
  265.                 HeaderExInfo.cchHeader = strlen( szBuffer );
  266.                 HeaderExInfo.pszStatus = "200 OK";
  267.                 HeaderExInfo.cchStatus = strlen( HeaderExInfo.pszStatus );
  268.                 HeaderExInfo.fKeepConn = TRUE;
  269.  
  270.                 pECB->ServerSupportFunction( 
  271.                     pECB->ConnID, 
  272.                     HSE_REQ_SEND_RESPONSE_HEADER_EX,
  273.                     &HeaderExInfo, 
  274.                     NULL,
  275.                     NULL
  276.                     );
  277.  
  278.                 //
  279.                 // Simulate extended processing
  280.                 //
  281.  
  282.                 Sleep( 3000 );
  283.  
  284.                 //
  285.                 // Send content
  286.                 //
  287.  
  288.                 dwSize = strlen( szBuffer2 );
  289.                 pECB->WriteClient( pECB->ConnID, szBuffer2, &dwSize, 0 );
  290.  
  291.                 //
  292.                 // Tell IIS to keep the connection open
  293.                 //
  294.  
  295.                 dwState = HSE_STATUS_SUCCESS_AND_KEEP_CONN;
  296.  
  297.                 pECB->ServerSupportFunction( 
  298.                     pECB->ConnID, 
  299.                     HSE_REQ_DONE_WITH_SESSION, 
  300.                     &dwState, 
  301.                     NULL, 
  302.                     0 
  303.                     );
  304.  
  305.             } else {            
  306.  
  307.                 //
  308.                 // No item found is unexpected condition - exit thread
  309.                 //
  310.  
  311.                 LeaveCriticalSection( &csQueueLock );
  312.                 ExitThread( 0 );
  313.             }
  314.  
  315.         } else {
  316.             break;
  317.         }
  318.     }
  319.  
  320.     return 0;
  321. }
  322.