/// <summary>
        /// Creates and initializes http web request.
        /// </summary>
        /// <param name="sender">True to create a sender request.</param>
        /// <param name="keepAlive">False to force connection closing.</param>
        /// <returns>Initialized HttpWebRequest instance.</returns>
        public HttpWebRequest InitializeRequest(bool sender, bool keepAlive)
        {
            string postfix = sender ? "SENDER" : "LISTENER";

            // setup connection
            int prefixPos = this.Remote.Url.IndexOf(':');

            if (prefixPos <= 0)
            {
                throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(this.Remote.Url, "Incorrect URI.");
            }

            HttpWebRequest webRequest = null;

            if (this.Remote.Url[prefixPos - 1] == 's')
            {
                webRequest = (HttpWebRequest)HttpWebRequest.Create("https" + this.Remote.Url.Substring(prefixPos) + '?' + Guid.NewGuid().ToString("N"));
            }
            else
            {
                webRequest = (HttpWebRequest)HttpWebRequest.Create("http" + this.Remote.Url.Substring(prefixPos) + '?' + Guid.NewGuid().ToString("N"));
            }

            webRequest.AllowAutoRedirect         = false;
            webRequest.AllowWriteStreamBuffering = this._useWebAuthentication || this._allowWriteStreamBuffering || this._iWebProxy != null;
            webRequest.ContentType         = "application/octet-stream";
            webRequest.ConnectionGroupName = this.HostIdAsString + postfix;

            webRequest.PreAuthenticate = this._useWebAuthentication;

#if FRM11 || FRM20
            webRequest.UnsafeAuthenticatedConnectionSharing = this._useUnsafeConnectionSharing;
#endif

            webRequest.KeepAlive   = keepAlive;
            webRequest.Method      = "POST";
            webRequest.Pipelined   = false;
            webRequest.SendChunked = false;

            webRequest.Proxy     = this._iWebProxy;
            webRequest.UserAgent = this._userAgent;
            webRequest.MediaType = this._mimeMediaType;

            webRequest.Accept = @"*/*";
            webRequest.Headers.Set("Cache-Control", "no-cache");
            webRequest.Headers.Set("Pragma", "no-cache");

            webRequest.Expect = null;

            if (this._credentials != null)
            {
                webRequest.Credentials = this._credentials;
                webRequest.AllowWriteStreamBuffering = true;
            }

            return(webRequest);
        }
        /// <summary>
        /// Constructs an instance of the SharedMemoryConnection class.
        /// </summary>
        /// <param name="iTransportContext">The transport context.</param>
        /// <param name="name">The name of the shared chunk.</param>
        /// <param name="isServer">The role.</param>
        /// <param name="setCloseStatusOnExit">Indicates whether it is necessary to set the "closed" status on exit.</param>
        internal SharedMemoryConnection(ITransportContext iTransportContext, string name, bool isServer, bool setCloseStatusOnExit)
        {
            this.ITransportContext     = iTransportContext;
            this.ShareName             = "GenuineChannels_GShMem_" + name;
            this.IsServer              = isServer;
            this._setCloseStatusOnExit = setCloseStatusOnExit;

            this._shareSize            = (int)iTransportContext.IParameterProvider[GenuineParameter.SMShareSize];
            this._pingTimeOut          = GenuineUtility.ConvertToMilliseconds(iTransportContext.IParameterProvider[GenuineParameter.PersistentConnectionSendPingAfterInactivity]);
            this._closeAfterInactivity = GenuineUtility.ConvertToMilliseconds(iTransportContext.IParameterProvider[GenuineParameter.ClosePersistentConnectionAfterInactivity]);

            string localSideName  = (isServer ? "Server" : "Client");
            string remoteSideName = (isServer ? "Client" : "Server");

            IParameterProvider parameters = this.ITransportContext.IParameterProvider;

            // construct shared object names for the local side
            string readCompletedEventName = GenuineSharedMemoryChannel.ConstructSharedObjectName(
                this.ShareName + localSideName + "ReadCompleted", parameters);
            string writeCompletedEventName = GenuineSharedMemoryChannel.ConstructSharedObjectName(
                this.ShareName + localSideName + "WriteCompleted", parameters);

            // construct shared object names for the remote side
            string remoteReadCompletedEventName = GenuineSharedMemoryChannel.ConstructSharedObjectName(
                this.ShareName + remoteSideName + "ReadCompleted", parameters);
            string remoteWriteCompletedEventName = GenuineSharedMemoryChannel.ConstructSharedObjectName(
                this.ShareName + remoteSideName + "WriteCompleted", parameters);

            if (isServer)
            {
                if (this._shareSize < MIN_SHARE_SIZE || this._shareSize > MAX_SHARE_SIZE)
                {
                    throw GenuineExceptions.Get_Channel_InvalidParameter("SMShareSize");
                }

                this.LowLevel_CreateSharedMemory();
                this._closed           = 0;
                this._writtenShareSize = this._shareSize;

                this._receiveOffset    = 5;
                this._sendOffset       = (this._shareSize - 5) / 2;
                this._receiveSpaceSize = this._sendOffset - 5 - 8;
                this._sendSpaceSize    = this._shareSize - this._sendOffset - 8;

                this._namedEventReadCompleted        = NamedEvent.CreateNamedEvent(readCompletedEventName, false, true);
                this._namedEventWriteCompleted       = NamedEvent.CreateNamedEvent(writeCompletedEventName, false, true);
                this._namedEventRemoteReadCompleted  = NamedEvent.CreateNamedEvent(remoteReadCompletedEventName, false, true);
                this._namedEventRemoteWriteCompleted = NamedEvent.CreateNamedEvent(remoteWriteCompletedEventName, false, true);
            }
            else
            {
                this.OpenSharedMemory();

                if (this._closed != 0)
                {
                    throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(name, "Remote host has already closed the connection.");
                }

                this._shareSize = this._writtenShareSize;
                if (this._shareSize < MIN_SHARE_SIZE || this._shareSize > MAX_SHARE_SIZE)
                {
                    throw GenuineExceptions.Get_Channel_InvalidParameter("SMShareSize");
                }

                this._receiveOffset    = (this._shareSize - 5) / 2;
                this._sendOffset       = 5;
                this._receiveSpaceSize = this._shareSize - this._receiveOffset - 8;
                this._sendSpaceSize    = this._receiveOffset - 5 - 8;

                this._namedEventReadCompleted        = NamedEvent.OpenNamedEvent(readCompletedEventName);
                this._namedEventWriteCompleted       = NamedEvent.OpenNamedEvent(writeCompletedEventName);
                this._namedEventRemoteReadCompleted  = NamedEvent.OpenNamedEvent(remoteReadCompletedEventName);
                this._namedEventRemoteWriteCompleted = NamedEvent.OpenNamedEvent(remoteWriteCompletedEventName);
            }

            this._sendBuffer = new byte[this._sendSpaceSize];
        }
Beispiel #3
0
        /// <summary>
        /// Resolves the remote host IP address and establishes the connection.
        /// </summary>
        /// <param name="ignored">This parameter is ignored.</param>
        private void StartConnecting(object ignored)
        {
            try
            {
                lock (this._syncRoot)
                {
                    if (!this._continue)
                    {
                        return;
                    }
                }

                // resolve host name to IP address
                IPAddress ipAddress = GenuineUtility.ResolveIPAddress(hostName);

                if (ipAddress == null)
                {
                    throw GenuineExceptions.Get_Connect_CanNotResolveHostName(hostName);
                }

                // get the address of the remote host
                IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, this._portNumber);
                if (ipEndPoint == null)
                {
                    throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(this.hostName, "The IPEndPoint instance cannot be created.");
                }

                // create and setup a socket
                socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                LingerOption lingerOption = new LingerOption(true, 3);
                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lingerOption);

                if ((bool)this._parameterProvider[GenuineParameter.TcpDisableNagling])
                {
                    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 1);
                }

                int tcpReceiveBufferSize = (int)this._parameterProvider[GenuineParameter.TcpReceiveBufferSize];
                int tcpSendBufferSize    = (int)this._parameterProvider[GenuineParameter.TcpSendBufferSize];
                if (tcpReceiveBufferSize >= 0)
                {
                    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, tcpReceiveBufferSize);
                }
                if (tcpSendBufferSize >= 0)
                {
                    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, tcpSendBufferSize);
                }

                lock (this._syncRoot)
                {
                    if (!this._continue)
                    {
                        return;
                    }
                }

                // connect to the remote host
                socket.Connect(ipEndPoint);

                this.Completed.Set();
            }
            catch (Exception ex)
            {
                this.CancelConnecting(ex);
            }
        }
        /// <summary>
        /// Opens the socket if it is not opened or not connected.
        /// </summary>
        public void CheckConnectionStatus()
        {
            if (this.IsDisposed)
            {
                throw new ObjectDisposedException("XHttpPhysicalConnection");
            }

            using (new ReaderAutoLocker(this.DisposeLock))
            {
                lock (this.PhysicalConnectionStateLock)
                {
                    if (this.EntryUri == null)
                    {
                        GenuineUtility.ParseUrl(this.Remote.Url, out this.EntryUri);
                    }

                    if (this.Socket != null && !this.Socket.Connected)
                    {
                        this.CloseSocket();
                    }

                    if (this.Socket == null && !this.XHttpConnection.IsClient)
                    {
                        throw GenuineExceptions.Get_Processing_TransportConnectionFailed();
                    }

                    if (this.Socket != null && this.LocalEndPoint == null)
                    {
                        this.LocalEndPoint = this.Socket.LocalEndPoint.ToString();
                    }

                    if (this.Socket != null)
                    {
                        return;
                    }
                }

                string objectUri;
                string url = GenuineUtility.Parse(this.Remote.Url, out objectUri);

                // parse provided url and fetch a port and IP address
                int    portNumber;
                string hostName = GenuineUtility.SplitHttpLinkToHostAndPort(url, out portNumber);

                // resolve host name to IP address
                IPAddress ipAddress = GenuineUtility.ResolveIPAddress(hostName);

                // get the address of the remote host
                IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, portNumber);
                if (ipEndPoint == null)
                {
                    return;
                }

                // create and setup a socket
                Socket       socket       = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                LingerOption lingerOption = new LingerOption(true, 3);
                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lingerOption);

//				socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 1);

                // connect to the remote host
                socket.Connect(ipEndPoint);
                if (!socket.Connected)
                {
                    throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(url, "The value of the Socket.Connected property is false after connecting.");
                }

                this.Remote.PhysicalAddress      = socket.RemoteEndPoint;
                this.Remote.LocalPhysicalAddress = socket.LocalEndPoint;

                if (this.LocalEndPoint == null)
                {
                    this.LocalEndPoint = socket.LocalEndPoint.ToString();
                }

                lock (this._accessToLocalMembers)
                {
                    this.Socket = socket;
                }

#if DEBUG
                lock (this.PhysicalConnectionStateLock)
                {
                    this.TypeOfSocket = "Opened";
                }
#endif
            }
        }
        /// <summary>
        /// Opens a connection to the host specified by the url.
        /// </summary>
        /// <param name="remote">The HostInformation of the Remote Host.</param>
        /// <param name="localUri">The uri of the local host.</param>
        /// <param name="remoteUri">The uri of the remote host.</param>
        /// <param name="remoteHostUniqueIdentifier">The unique identifier of the HostInformation used by the remote host.</param>
        /// <returns>The established connection.</returns>
        private SharedMemoryConnection LowLevel_OpenConnection(HostInformation remote, string localUri, out string remoteUri, out int remoteHostUniqueIdentifier)
        {
            using (new ReaderAutoLocker(this._disposeLock))
            {
                if (this._disposed)
                {
                    throw OperationException.WrapException(this._disposeReason);
                }
            }

            remoteUri = null;
            Stream inputStream  = null;
            Stream outputStream = null;
            string url          = remote.Url;

            // the maximum time during which the connection must be established
            int timeout = GenuineUtility.GetTimeout((TimeSpan)this.ITransportContext.IParameterProvider[GenuineParameter.ConnectTimeout]);

            IParameterProvider parameters = this.ITransportContext.IParameterProvider;

            string mutexName = GenuineSharedMemoryChannel.ConstructSharedObjectName(
                "MUTEX" + url, parameters);
            string clientConnected = GenuineSharedMemoryChannel.ConstructSharedObjectName(
                "CC" + url, parameters);
            string clientAccepted = GenuineSharedMemoryChannel.ConstructSharedObjectName(
                "CA" + url, parameters);

            // open the server share
            SharedMemoryConnection serverSharedMemoryConnection = new SharedMemoryConnection(this.ITransportContext, url, false, false);

            // LOG:
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0)
            {
                binaryLogWriter.WriteConnectionParameterEvent(LogCategory.Connection, "SharedMemoryConnectionManager.LowLevel_OpenConnection",
                                                              LogMessageType.ConnectionParameters, null, remote, this.ITransportContext.IParameterProvider,
                                                              GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, serverSharedMemoryConnection.DbgConnectionId,
                                                              "A Shared Memory connection is being established.");
            }

            // and create the local share
            string shareName = "gshmem://" + Guid.NewGuid().ToString("N");
            SharedMemoryConnection sharedMemoryConnection = new SharedMemoryConnection(this.ITransportContext, shareName, true, true);

            BinaryWriter connectionInformation = MessageCoder.SerializeConnectionHeader(MessageCoder.PROTOCOL_VERSION, GenuineConnectionType.Persistent, "Default");

            connectionInformation.Write(shareName);

            // let the server know that a client's share is ready
            Mutex mutex = null;

            try
            {
                mutex = WindowsAPI.OpenMutex(mutexName);

                NamedEvent _clientConnected = NamedEvent.OpenNamedEvent(clientConnected);
                NamedEvent _clientAccepted  = NamedEvent.OpenNamedEvent(clientAccepted);

                if (!GenuineUtility.WaitOne(mutex, GenuineUtility.GetMillisecondsLeft(timeout)))
                {
                    throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(url, "Can not acquire the lock for the global mutex.");
                }

                // wait until server accepts this client
                _clientAccepted.ManualResetEvent.Reset();
                _clientConnected.ManualResetEvent.Set();

                // copy client's name
                serverSharedMemoryConnection.LowLevel_SendSync(connectionInformation.BaseStream, timeout);

                if (!GenuineUtility.WaitOne(_clientAccepted.ManualResetEvent, GenuineUtility.GetMillisecondsLeft(timeout)))
                {
                    throw GenuineExceptions.Get_Connect_CanNotConnectToRemoteHost(url, "Remote server did not accept a request within the specified time span.");
                }
            }
            finally
            {
                if (mutex != null)
                {
                    try
                    {
                        mutex.ReleaseMutex();
                    }
                    catch
                    {
                    }

                    try
                    {
                        mutex.Close();
                    }
                    catch
                    {
                    }
                }
            }

            // get the connection-level Security Session
            string          connectionLevelSSName = this.ITransportContext.IParameterProvider[GenuineParameter.SecuritySessionForPersistentConnections] as string;
            SecuritySession securitySession       = null;

            if (connectionLevelSSName != null)
            {
                securitySession = this.ITransportContext.IKeyStore.GetKey(connectionLevelSSName).CreateSecuritySession(connectionLevelSSName, null);
            }

            // establish it
            if (securitySession != null && !securitySession.IsEstablished)
            {
                bool firstPass = true;
                for ( ; ;)
                {
                    inputStream = Stream.Null;

                    try
                    {
                        // prepare streams
                        if (!firstPass)
                        {
                            inputStream = sharedMemoryConnection.LowLevel_ReadSync(timeout);
                        }
                        else
                        {
                            firstPass = false;
                        }

                        outputStream = securitySession.EstablishSession(inputStream, true);

                        if (outputStream == null)
                        {
                            break;
                        }

                        // send a packet to the remote host
                        sharedMemoryConnection.LowLevel_SendSync(outputStream, timeout);
                        if (securitySession.IsEstablished)
                        {
                            break;
                        }
                    }
                    finally
                    {
                        if (inputStream != null)
                        {
                            inputStream.Close();
                        }
                        if (outputStream != null)
                        {
                            outputStream.Close();
                        }
                    }
                }
            }

            sharedMemoryConnection.ConnectionLevelSecurity = securitySession;

            // now send connection info through the established connection
            using (GenuineChunkedStream serializedLocalInfo = new GenuineChunkedStream(false))
            {
                // serialize local info
                BinaryWriter binaryWriter = new BinaryWriter(serializedLocalInfo);
                binaryWriter.Write((string)localUri);
                binaryWriter.Write((int)remote.LocalHostUniqueIdentifier);

                // and send it
                sharedMemoryConnection.LowLevel_SendSync(serializedLocalInfo, timeout);

                // read remote info
                using (Stream remoteUriStream = sharedMemoryConnection.LowLevel_ReadSync(timeout))
                {
                    BinaryReader binaryReader = new BinaryReader(remoteUriStream);
                    remoteUri = binaryReader.ReadString();
                    remoteHostUniqueIdentifier = binaryReader.ReadInt32();
                }
            }

            sharedMemoryConnection.Remote = remote;
            sharedMemoryConnection.Remote.UpdateUri(remoteUri, remoteHostUniqueIdentifier);
            sharedMemoryConnection.Remote.GenuinePersistentConnectionState = GenuinePersistentConnectionState.Opened;

            // LOG:
            if (binaryLogWriter != null && binaryLogWriter[LogCategory.HostInformation] > 0)
            {
                binaryLogWriter.WriteHostInformationEvent("SharedMemoryConnectionManager.LowLevel_OpenConnection",
                                                          LogMessageType.HostInformationCreated, null, remote,
                                                          GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null,
                                                          sharedMemoryConnection.DbgConnectionId,
                                                          "HostInformation is ready for actions.");
            }

            // LOG:
            if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0)
            {
                binaryLogWriter.WriteEvent(LogCategory.Connection, "SharedMemoryConnectionManager.LowLevel_OpenConnection",
                                           LogMessageType.ConnectionEstablished, null, null, remote, null,
                                           GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                           securitySession, connectionLevelSSName,
                                           sharedMemoryConnection.DbgConnectionId, (int)GenuineConnectionType.Persistent, 0, 0, this.GetType().Name, null, null, null,
                                           "The connection to the remote host is established.");
            }

            return(sharedMemoryConnection);
        }