The Labs \ Source Viewer \ SSCLI \ System.Runtime.Remoting.Channels.Tcp \ TcpClientSocketHandler

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. //==========================================================================
  16. // File: TcpClientSocketManager.cs
  17. //
  18. // Summary: Class for managing a socket connection.
  19. //
  20. //==========================================================================
  21. using System;
  22. using System.Collections;
  23. using System.IO;
  24. using System.Net;
  25. using System.Net.Sockets;
  26. using System.Runtime.Remoting.Messaging;
  27. using System.Text;
  28. using System.Threading;
  29. using System.Globalization;
  30. namespace System.Runtime.Remoting.Channels.Tcp
  31. {
  32.    
  33.     // A client socket manager instance should encapsulate the socket
  34.     // for the purpose of reading a response
  35.     internal class TcpClientSocketHandler : TcpSocketHandler
  36.     {
  37.         // prebaked bytes
  38.         private static byte[] s_endOfLineBytes = Encoding.ASCII.GetBytes("\r\n");
  39.        
  40.        
  41.         private string _machinePortAndSid;
  42.         // "machineName:port:Sid"
  43.         // connection state information
  44.         private bool _bOneWayRequest = false;
  45.         // was the request made OneWay?
  46.         private bool _bChunked;
  47.         private int _contentLength;
  48.        
  49.         private Stream _requestStream;
  50.         // the request stream that we return from GetRequestStream()
  51.         private TcpReadingStream _responseStream;
  52.         // the stream that we returned from GetResponseStream()
  53.         private TcpClientTransportSink _sink = null;
  54.        
  55.         public TcpClientSocketHandler(Socket socket, string machinePortAndSid, Stream stream, TcpClientTransportSink sink) : base(socket, stream)
  56.         {
  57.             _machinePortAndSid = machinePortAndSid;
  58.             _sink = sink;
  59.         }
  60.         // TcpClientSocketHandler
  61.        
  62.        
  63.         // Prepare for reading a new request off of the same socket
  64.         protected override void PrepareForNewMessage()
  65.         {
  66.             _requestStream = null;
  67.             _responseStream = null;
  68.         }
  69.         // PrepareForNewRequest
  70.        
  71.         public override void OnInputStreamClosed()
  72.         {
  73.             // make sure we read to the end of the response stream
  74.             if (_responseStream != null) {
  75.                 _responseStream.ReadToEnd();
  76.                 _responseStream = null;
  77.             }
  78.            
  79.             // return socket to the cache
  80.             ReturnToCache();
  81.         }
  82.         // OnInputStreamClosed
  83.        
  84.        
  85.         public BaseTransportHeaders ReadHeaders()
  86.         {
  87.             BaseTransportHeaders headers = new BaseTransportHeaders();
  88.            
  89.             UInt16 operation;
  90.             ReadVersionAndOperation(out operation);
  91.            
  92.             // At this point, we're always expecting a Reply, so check for that.
  93.             if (operation != TcpOperations.Reply) {
  94.                 throw new RemotingException(String.Format(CultureInfo.CurrentCulture, CoreChannel.GetResourceString("Remoting_Tcp_ExpectingReplyOp"), operation.ToString(CultureInfo.CurrentCulture)));
  95.             }
  96.            
  97.             // content length must come next (may be chunked or a specific length)
  98.             ReadContentLength(out _bChunked, out _contentLength);
  99.            
  100.             // read to end of headers
  101.             ReadToEndOfHeaders(headers);
  102.            
  103.             return headers;
  104.         }
  105.         // ReadHeaders
  106.        
  107.         public Stream GetRequestStream(IMessage msg, int contentLength, ITransportHeaders headers)
  108.         {
  109.             IMethodCallMessage mcm = (IMethodCallMessage)msg;
  110.             string uri = mcm.Uri;
  111.             _bOneWayRequest = RemotingServices.IsOneWay(mcm.MethodBase);
  112.            
  113.             ChunkedMemoryStream headerStream = new ChunkedMemoryStream(CoreChannel.BufferPool);
  114.            
  115.             // output preamble and version
  116.             WritePreambleAndVersion(headerStream);
  117.             // output opcode
  118.             if (!_bOneWayRequest)
  119.                 WriteUInt16(TcpOperations.Request, headerStream);
  120.             else
  121.                 WriteUInt16(TcpOperations.OneWayRequest, headerStream);
  122.             // output content delimiter style
  123.             WriteUInt16(TcpContentDelimiter.ContentLength, headerStream);
  124.             WriteInt32(contentLength, headerStream);
  125.            
  126.             // output request uri
  127.             WriteUInt16(TcpHeaders.RequestUri, headerStream);
  128.             WriteByte(TcpHeaderFormat.CountedString, headerStream);
  129.             WriteCountedString(uri, headerStream);
  130.            
  131.             // output rest of headers
  132.             WriteHeaders(headers, headerStream);
  133.            
  134.             headerStream.WriteTo(NetStream);
  135.             headerStream.Close();
  136.            
  137.             _requestStream = NetStream;
  138.            
  139.             return _requestStream;
  140.         }
  141.         // GetRequestStream
  142.         public void SendRequest(IMessage msg, ITransportHeaders headers, Stream contentStream)
  143.         {
  144.             int requestLength = (int)contentStream.Length;
  145.             GetRequestStream(msg, requestLength, headers);
  146.            
  147.             StreamHelper.CopyStream(contentStream, NetStream);
  148.            
  149.             contentStream.Close();
  150.         }
  151.         // SendRequest
  152.        
  153.         public Stream GetResponseStream()
  154.         {
  155.             if (!_bChunked)
  156.                 _responseStream = new TcpFixedLengthReadingStream(this, _contentLength);
  157.             else
  158.                 _responseStream = new TcpChunkedReadingStream(this);
  159.            
  160.             return _responseStream;
  161.         }
  162.         // GetResponseStream
  163.        
  164.         public bool OneWayRequest {
  165.             get { return _bOneWayRequest; }
  166.         }
  167.        
  168.         public void ReturnToCache()
  169.         {
  170.             _sink.ClientSocketCache.ReleaseSocket(_machinePortAndSid, this);
  171.         }
  172.        
  173.     }
  174.     // TcpClientSocketHandler
  175. }
  176. // namespace System.Runtime.Remoting.Channels

Developer Fusion