home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / remote / srvhshak.c < prev    next >
C/C++ Source or Header  |  1997-10-12  |  10KB  |  416 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright 1995 - 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. Copyright (c) 1997  Microsoft Corporation
  15.  
  16. Module Name:
  17.  
  18.     SrvHShak.c
  19.  
  20. Abstract:
  21.  
  22.     The server component of Remote.  Handshake with
  23.     client at start of session.
  24.  
  25.  
  26. Author:
  27.  
  28.     Dave Hart  30 May 1997
  29.  
  30. Environment:
  31.  
  32.     Console App. User mode.
  33.  
  34. Revision History:
  35.  
  36. --*/
  37.  
  38. #include <windows.h>
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <io.h>
  42. #include <string.h>
  43. #include "Remote.h"
  44. #include "Server.h"
  45.  
  46.  
  47.  
  48.  
  49. VOID
  50. FASTCALL
  51. HandshakeWithRemoteClient(
  52.     PREMOTE_CLIENT pClient
  53.     )
  54. {
  55.     pClient->ServerFlags |= SFLG_HANDSHAKING;
  56.  
  57.     AddClientToHandshakingList(pClient);
  58.  
  59.     //
  60.     // Read hostname from client
  61.     //
  62.  
  63.     ZeroMemory(
  64.         &pClient->ReadOverlapped,
  65.         sizeof(pClient->ReadOverlapped)
  66.         );
  67.  
  68.     if ( ! ReadFileEx(
  69.                pClient->PipeReadH,
  70.                pClient->Name,
  71.                HOSTNAMELEN - 1,
  72.                &pClient->ReadOverlapped,
  73.                ReadClientNameCompleted
  74.                )) {
  75.  
  76.         CloseClient(pClient);
  77.     }
  78. }
  79.  
  80. VOID
  81. WINAPI
  82. ReadClientNameCompleted(
  83.     DWORD dwError,
  84.     DWORD cbRead,
  85.     LPOVERLAPPED lpO
  86.     )
  87. {
  88.     PREMOTE_CLIENT pClient;
  89.     SESSION_STARTREPLY ssr;
  90.  
  91.     pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, ReadOverlapped);
  92.  
  93.     if (pClient->ServerFlags & SFLG_CLOSING) {
  94.  
  95.         return;
  96.     }
  97.  
  98.     if (dwError) {
  99.         CloseClient(pClient);
  100.         return;
  101.     }
  102.  
  103.     if ((HOSTNAMELEN - 1) != cbRead) {
  104.         printf("ReadClientNameCompleted read %d s/b %d.\n", cbRead, (HOSTNAMELEN - 1));
  105.         CloseClient(pClient);
  106.         return;
  107.     }
  108.  
  109.     //
  110.     // The client name read is 15 bytes always.  The last four
  111.     // should match MAGICNUMBER, which conveniently has the
  112.     // low byte zeroed to terminate the client name after 11
  113.     // characters.
  114.     //
  115.  
  116.     if (MAGICNUMBER != *(DWORD *)&pClient->Name[11]) {
  117.  
  118.         pClient->Name[11] = 0;
  119.         CloseClient(pClient);
  120.         return;
  121.     }
  122.  
  123.     //
  124.     // Now we can tell if this is a single-pipe or two-pipe
  125.     // client, because single-pipe clients replace the
  126.     // first byte of the computername with the illegal
  127.     // character '?'.
  128.     //
  129.  
  130.     if ('?' == pClient->Name[0]) {
  131.  
  132.         pClient->PipeWriteH = pClient->PipeReadH;
  133.  
  134.         TRACE(CONNECT, ("Client %d pipe %x is single-pipe.\n", pClient->dwID, pClient->PipeWriteH));
  135.  
  136.         //
  137.         // In order for things to work reliably for 2-pipe clients
  138.         // when there are multiple remote servers on the same pipename,
  139.         // we need to tear down the listening OUT pipe and recreate it so
  140.         // that the oldest listening IN pipe will be from the same process
  141.         // as the oldest listening OUT pipe.
  142.         //
  143.  
  144.         if (1 == cConnectIns) {
  145.  
  146.             TRACE(CONNECT, ("Recycling OUT pipe %x as well for round-robin behavior.\n",
  147.                             hPipeOut));
  148.  
  149.             CANCELIO(hPipeOut);
  150.             DisconnectNamedPipe(hPipeOut);
  151.             CloseHandle(hPipeOut);
  152.             hPipeOut = INVALID_HANDLE_VALUE;
  153.             bOutPipeConnected = FALSE;
  154.  
  155.             CreatePipeAndIssueConnect(OUT_PIPE);
  156.         }
  157.  
  158.     } else {
  159.  
  160.         if ( ! bOutPipeConnected ) {
  161.  
  162.             printf("Remote: %x two-pipe client connected to IN pipe but not OUT?\n", pClient);
  163.             CloseClient(pClient);
  164.             return;
  165.         }
  166.  
  167.         bOutPipeConnected = FALSE;
  168.  
  169.         if (INVALID_HANDLE_VALUE != hConnectOutTimer) {
  170.             pfnCancelWaitableTimer(hConnectOutTimer);
  171.         }
  172.  
  173.         pClient->PipeWriteH = hPipeOut;
  174.         hPipeOut = INVALID_HANDLE_VALUE;
  175.  
  176.         TRACE(CONNECT, ("Client %d is dual-pipe IN %x OUT %x.\n", pClient->dwID, pClient->PipeReadH, pClient->PipeWriteH));
  177.  
  178.         CreatePipeAndIssueConnect(OUT_PIPE);
  179.     }
  180.  
  181.     TRACE(SHAKE, ("Read client name %s\n", pClient->Name));
  182.  
  183.     //
  184.     // Send our little pile of goodies to the client
  185.     //
  186.  
  187.     ssr.MagicNumber = MAGICNUMBER;
  188.     ssr.Size = sizeof(ssr);
  189.     ssr.FileSize = dwWriteFilePointer;
  190.  
  191.     //
  192.     // Copy ssr structure to a buffer that will be around
  193.     // for the entire I/O.
  194.     //
  195.  
  196.     CopyMemory(pClient->WriteBuffer, &ssr, sizeof(ssr));
  197.  
  198.     if ( ! WriteFileEx(
  199.                pClient->PipeWriteH,
  200.                pClient->WriteBuffer,
  201.                sizeof(ssr),
  202.                &pClient->WriteOverlapped,
  203.                WriteServerReplyCompleted
  204.                )) {
  205.  
  206.         CloseClient(pClient);
  207.     }
  208. }
  209.  
  210.  
  211. VOID
  212. WINAPI
  213. WriteServerReplyCompleted(
  214.     DWORD dwError,
  215.     DWORD cbWritten,
  216.     LPOVERLAPPED lpO
  217.     )
  218. {
  219.     PREMOTE_CLIENT pClient;
  220.  
  221.     pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, WriteOverlapped);
  222.  
  223.     if (pClient->ServerFlags & SFLG_CLOSING) {
  224.  
  225.         return;
  226.     }
  227.  
  228.     if (HandleSessionError(pClient, dwError)) {
  229.         return;
  230.     }
  231.  
  232.     TRACE(SHAKE, ("Wrote server reply\n"));
  233.  
  234.     //
  235.     // Read the size of the SESSION_STARTUPINFO the client is
  236.     // sending us, to deal gracefully with different versions
  237.     // on client and server.
  238.     //
  239.  
  240.     if ( ! ReadFileEx(
  241.                pClient->PipeReadH,
  242.                pClient->ReadBuffer,
  243.                sizeof(DWORD),
  244.                &pClient->ReadOverlapped,
  245.                ReadClientStartupInfoSizeCompleted
  246.                )) {
  247.  
  248.         CloseClient(pClient);
  249.     }
  250. }
  251.  
  252.  
  253. VOID
  254. WINAPI
  255. ReadClientStartupInfoSizeCompleted(
  256.     DWORD dwError,
  257.     DWORD cbRead,
  258.     LPOVERLAPPED lpO
  259.     )
  260. {
  261.     PREMOTE_CLIENT pClient;
  262.     DWORD dwSize;
  263.  
  264.     pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, ReadOverlapped);
  265.  
  266.     if (HandleSessionError(pClient, dwError)) {
  267.  
  268.         return;
  269.     }
  270.  
  271.     if (cbRead != sizeof(DWORD)) {
  272.  
  273.         CloseClient(pClient);
  274.         return;
  275.     }
  276.  
  277.     //
  278.     // Sanity check the size
  279.     //
  280.  
  281.     dwSize = *(DWORD *)pClient->ReadBuffer;
  282.  
  283.     if (dwSize > 1024) {
  284.         CloseClient(pClient);
  285.         return;
  286.     }
  287.  
  288.     //
  289.     // Squirrel away the size in the write buffer,
  290.     // since during handshaking we never have both a
  291.     // read and write pending this is OK.
  292.     //
  293.  
  294.     *(DWORD *)pClient->WriteBuffer = dwSize;
  295.  
  296.     TRACE(SHAKE, ("Read client reply size %d\n", dwSize));
  297.  
  298.     //
  299.     // Read the rest of the SESSION_STARTUPINFO into the read buffer
  300.     // after the size.
  301.     //
  302.  
  303.     RtlZeroMemory(
  304.         &pClient->ReadOverlapped,
  305.         sizeof(pClient->ReadOverlapped)
  306.         );
  307.  
  308.     if ( ! ReadFileEx(
  309.                pClient->PipeReadH,
  310.                pClient->ReadBuffer + sizeof(DWORD),
  311.                dwSize - sizeof(DWORD),
  312.                &pClient->ReadOverlapped,
  313.                ReadClientStartupInfoCompleted
  314.                )) {
  315.  
  316.         CloseClient(pClient);
  317.     }
  318. }
  319.  
  320.  
  321. VOID
  322. WINAPI
  323. ReadClientStartupInfoCompleted(
  324.     DWORD dwError,
  325.     DWORD cbRead,
  326.     LPOVERLAPPED lpO
  327.     )
  328. {
  329.     PREMOTE_CLIENT pClient;
  330.     DWORD dwSize;
  331.     SESSION_STARTUPINFO ssi;
  332.     char  Buf[256];
  333.  
  334.     pClient = CONTAINING_RECORD(lpO, REMOTE_CLIENT, ReadOverlapped);
  335.  
  336.     if (HandleSessionError(pClient, dwError)) {
  337.  
  338.         return;
  339.     }
  340.  
  341.     dwSize = *(DWORD *)pClient->WriteBuffer;
  342.  
  343.     if (cbRead != (dwSize - sizeof(ssi.Size))) {
  344.  
  345.         CloseClient(pClient);
  346.         return;
  347.     }
  348.  
  349.     CopyMemory(&ssi, pClient->ReadBuffer, min(dwSize, sizeof(ssi)));
  350.  
  351.     CopyMemory(pClient->Name, ssi.ClientName, sizeof(pClient->Name));
  352.     pClient->Flag = ssi.Flag;
  353.  
  354.     if (ssi.Version != VERSION) {
  355.  
  356.         printf("Remote Warning: Server Version=%d Client Version=%d for %s\n", VERSION, ssi.Version, pClient->Name);
  357.     }
  358.  
  359.     TRACE(SHAKE, ("Read client info, new name %s, %d lines\n", pClient->Name, ssi.LinesToSend));
  360.  
  361.  
  362.     //
  363.     // Set temp file position according to the client's
  364.     // requested lines to send.  The heuristic of 45 chars
  365.     // per average line is used by the client.  However since old clients
  366.     // hardcode this knowledge and sit and spin trying to read that many
  367.     // bytes before completing initialization, and because we might not send
  368.     // that many due to stripping BEGINMARK and ENDMARK characters, we
  369.     // use 50 chars per line to calculate the temp file position in hopes
  370.     // the extra bytes will overcome the missing MARK characters.
  371.     //
  372.  
  373.     pClient->dwFilePos = dwWriteFilePointer > (ssi.LinesToSend * 50)
  374.                              ? dwWriteFilePointer - (ssi.LinesToSend * 50)
  375.                              : 0;
  376.  
  377.     //
  378.     // This client's ready to roll.
  379.     //
  380.  
  381.     pClient->ServerFlags &= ~SFLG_HANDSHAKING;
  382.  
  383.     MoveClientToNormalList(pClient);
  384.  
  385.     //
  386.     // Start read operation against this client's input.
  387.     //
  388.  
  389.     StartReadClientInput(pClient);
  390.  
  391.     //
  392.     // Announce the connection.
  393.     //
  394.  
  395.     sprintf(Buf,
  396.             "\n**Remote: Connected to %s %s%s [%s]\n",
  397.             pClient->Name,
  398.             pClient->UserName,
  399.             (pClient->PipeReadH != pClient->PipeWriteH)
  400.               ? " (two pipes)"
  401.               : "",
  402.             GetFormattedTime(TRUE));
  403.  
  404.     if (WriteFileSynch(hWriteTempFile,Buf,strlen(Buf),&dwSize,dwWriteFilePointer,&olMainThread)) {
  405.         dwWriteFilePointer += dwSize;
  406.         StartServerToClientFlow();
  407.     }
  408.  
  409.     //
  410.     // Start write cycle for client output from the temp
  411.     // file.
  412.     // not needed because of StartServerToClientFlow() just above
  413.     // StartReadTempFile(pClient);
  414.  
  415. }
  416.