コード例 #1
0
        /// <summary>
        /// Receives the content synchronously.
        /// </summary>
        private void ReceiveSynchronously()
        {
            BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter;

            byte[] receiveBuffer = null;
            this._receivingThreadClosed.Reset();

            try
            {
                int mtu = (int)this.ITransportContext.IParameterProvider[GenuineParameter.UdpMtu];
                for ( ; ;)
                {
                    if (this._closing)
                    {
                        return;
                    }

                    if (BufferPool.GENERAL_BUFFER_SIZE >= mtu)
                    {
                        receiveBuffer = BufferPool.ObtainBuffer();
                    }
                    else
                    {
                        receiveBuffer = new byte[mtu];
                    }

                    try
                    {
                        IPEndPoint ipEndPoint        = new IPEndPoint(IPAddress.Any, 0);
                        EndPoint   endPointReference = ipEndPoint;
                        int        bytesReceived     = this._socket.ReceiveFrom(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, ref endPointReference);
                        ipEndPoint = (IPEndPoint)endPointReference;

                        // LOG:
                        if (binaryLogWriter != null && binaryLogWriter[LogCategory.Transport] > 0)
                        {
                            binaryLogWriter.WriteTransportContentEvent(LogCategory.Transport, "UdpConnectionManager.ReceiveSynchronously",
                                                                       LogMessageType.ReceivingFinished, null, null, null,
                                                                       binaryLogWriter[LogCategory.Transport] > 1 ? new MemoryStream(GenuineUtility.CutOutBuffer(receiveBuffer, 0, bytesReceived)) : null,
                                                                       GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                                       this.DbgConnectionId, bytesReceived, ipEndPoint.ToString(),
                                                                       null, null,
                                                                       "Content is received from {0}.", ipEndPoint.ToString());
                        }

                        // parse the header
                        if (bytesReceived < HEADER_SIZE)
                        {
                            throw GenuineExceptions.Get_Receive_IncorrectData();
                        }
                        if (receiveBuffer[0] != MessageCoder.COMMAND_MAGIC_CODE)
                        {
                            throw GenuineExceptions.Get_Receive_IncorrectData();
                        }

                        // get the packet identifier
                        byte[] guidBuffer = new byte[16];
                        Buffer.BlockCopy(receiveBuffer, 1, guidBuffer, 0, 16);
                        Guid packetGuid = new Guid(guidBuffer);

                        // and chunk number
                        int  chunkNumber = MessageCoder.ReadInt32(receiveBuffer, 17);
                        bool isLast      = chunkNumber < 0;
                        if (chunkNumber < 0)
                        {
                            chunkNumber = -chunkNumber;
                        }
                        chunkNumber--;

                        // process the chunk
                        StreamAssembled streamAssembled;
                        lock (this._streams.SyncRoot)
                        {
                            streamAssembled = this._streams[packetGuid] as StreamAssembled;
                            if (streamAssembled == null)
                            {
                                this._streams[packetGuid] = streamAssembled = new StreamAssembled(ipEndPoint, HEADER_SIZE);
                            }
                            if (streamAssembled.IsProcessed)
                            {
                                continue;
                            }
                        }

                        string          uri    = "gudp://" + ipEndPoint.ToString();
                        HostInformation remote = this.ITransportContext.KnownHosts[uri];
                        remote.Renew(this._closeInvocationConnectionAfterInactivity, false);

                        if ((int)this.ITransportContext.IParameterProvider[GenuineParameter.CompatibilityLevel] <= 0)
                        {
                            remote.UpdateUri(uri, 0, false);
                        }

                        if (streamAssembled.BufferReceived(chunkNumber, receiveBuffer, bytesReceived, isLast))
                        {
                            // prepare it for processing
                            this._streams.Remove(packetGuid);
                            streamAssembled.IsProcessed = true;

                            // read the remote host URI
                            if ((int)this.ITransportContext.IParameterProvider[GenuineParameter.CompatibilityLevel] > 0)
                            {
                                BinaryReader binaryReader = new BinaryReader(streamAssembled);

                                // read the URI
                                byte[] uriBuffer = new byte[16];
                                GenuineUtility.ReadDataFromStream(streamAssembled, uriBuffer, 0, uriBuffer.Length);
                                Guid   remoteHostUriGuid = new Guid(uriBuffer);
                                string receivedUri       = "_gudp://" + remoteHostUriGuid.ToString("N");

                                // read the remote host unique identifier
                                int remoteHostUniqueIdentifier = binaryReader.ReadInt32();

                                // update the host information
                                remote.UpdateUri(receivedUri, remoteHostUniqueIdentifier, false);

                                // and skip the skip space
                                GenuineUtility.CopyStreamToStream(streamAssembled, Stream.Null, binaryReader.ReadInt16());
                            }

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

                            remote.PhysicalAddress = endPointReference;
                            this.ITransportContext.IIncomingStreamHandler.HandleMessage(streamAssembled, remote, GenuineConnectionType.Persistent, string.Empty, -1, false, this._iMessageRegistrator, null, null);
                        }
                    }
                    catch (Exception ex)
                    {
                        // LOG:
                        if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0)
                        {
                            binaryLogWriter.WriteEvent(LogCategory.Connection, "UdpConnectionManager.ReceiveSynchronously",
                                                       LogMessageType.ReceivingFinished, ex, null, null, null,
                                                       GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name,
                                                       null, null,
                                                       this.DbgConnectionId, 0, 0, 0, null, null, null, null,
                                                       "UDP socket failure.");
                        }

                        if (this._closing)
                        {
                            return;
                        }

                        this.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.GUdpSocketException, ex, this.Local, null));
                    }
                }
            }
            finally
            {
                this._receivingThreadClosed.Set();
            }
        }
コード例 #2
0
        /// <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);
        }