/// <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(); } }
/// <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); }