SRVHSHAK.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:10k
源码类别:

Windows编程

开发平台:

Visual C++

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