/// <summary> /// Constructs an instance of the GenuineUdpChannel class. /// </summary> /// <param name="properties">An IDictionary of the channel properties which hold the configuration information for the current channel.</param> /// <param name="iClientChannelSinkProvider">The IClientChannelSinkProvider that creates the client channel sinks for the underlying channel through which remoting messages flow through.</param> /// <param name="iServerChannelSinkProvider">The IServerChannelSinkProvider that creates server channel sinks for the underlying channel through which remoting messages flow through.</param> public GenuineUdpChannel(IDictionary properties, IClientChannelSinkProvider iClientChannelSinkProvider, IServerChannelSinkProvider iServerChannelSinkProvider) : base(iClientChannelSinkProvider, iServerChannelSinkProvider) { this.ITransportContext = TransportContextServices.CreateDefaultUdpContext(properties, this); this.InitializeInstance(properties); if (this._channelName == null) { this._channelName = "gudp"; } if (this._urlPrefix == null) { this._urlPrefix = "gudp"; } this._possibleChannelPrefixes = new string[] { this.UrlPrefix, this.UriPrefix, GetBroadcastUriPrefix(this.UrlPrefix), GetBroadcastUriPrefix(this.UriPrefix) }; // retrieve settings string uriToListen = this["Address"] as string; foreach (DictionaryEntry entry in properties) { if (string.Compare(entry.Key.ToString(), "Address", true) == 0) { uriToListen = entry.Value.ToString(); } } if (uriToListen == null || uriToListen.Length <= 0 || !uriToListen.StartsWith(this.UrlPrefix + ":")) { throw GenuineExceptions.Get_Server_IncorrectAddressToListen(uriToListen); } this.StartListening(uriToListen); }
/// <summary> /// Sends the content to the specified remote host and returns a response sent by the remote /// host in reply. /// </summary> /// <param name="destination">The remote host.</param> /// <param name="serviceName">The name of the service.</param> /// <param name="content">The content.</param> /// <returns>The response.</returns> public Stream SendSync(HostInformation destination, string serviceName, Stream content) { // create the message Message message = new Message(this.ITransportContext, destination, 0, new TransportHeaders(), content); message.IsSynchronous = true; message.GenuineMessageType = GenuineMessageType.ExternalStreamConsumer; message.DestinationMarshalByRef = serviceName; // register the response catcher SyncResponseProcessorWithEvent syncResponseProcessorWithEvent = new SyncResponseProcessorWithEvent(message); this.ITransportContext.IIncomingStreamHandler.RegisterResponseProcessor(message.MessageId, syncResponseProcessorWithEvent); // and send the message this.ITransportContext.ConnectionManager.Send(message); int timeSpanInMilliseconds = GenuineUtility.GetMillisecondsLeft(message.FinishTime); if (timeSpanInMilliseconds <= 0) { throw GenuineExceptions.Get_Send_ServerDidNotReply(); } if (!syncResponseProcessorWithEvent.IsReceivedEvent.WaitOne(timeSpanInMilliseconds, false)) { throw GenuineExceptions.Get_Send_ServerDidNotReply(); } if (syncResponseProcessorWithEvent.DispatchedException != null) { throw OperationException.WrapException(syncResponseProcessorWithEvent.DispatchedException); } return(syncResponseProcessorWithEvent.Response.Stream); }
/// <summary> /// Creates shared memory object. /// </summary> public void LowLevel_CreateSharedMemory() { if (WindowsAPI.FailureReason != null) { throw OperationException.WrapException(WindowsAPI.FailureReason); } IParameterProvider parameters = this.ITransportContext.IParameterProvider; string fileMappingName = GenuineSharedMemoryChannel.ConstructSharedObjectName( this.ShareName, parameters); this._mapHandle = WindowsAPI.CreateFileMapping((IntPtr)(int)-1, WindowsAPI.AttributesWithNullDACL, WindowsAPI.PAGE_READWRITE, 0, (uint)this._shareSize, fileMappingName); if (this._mapHandle == IntPtr.Zero) { throw GenuineExceptions.Get_Windows_CanNotCreateOrOpenSharedMemory(Marshal.GetLastWin32Error()); } this._pointer = WindowsAPI.MapViewOfFile(this._mapHandle, WindowsAPI.SECTION_MAP_READ | WindowsAPI.SECTION_MAP_WRITE, 0, 0, 0); if (this._pointer == IntPtr.Zero) { int lastWinError = Marshal.GetLastWin32Error(); WindowsAPI.CloseHandle(this._mapHandle); throw GenuineExceptions.Get_Windows_SharedMemoryError(lastWinError); } }
/// <summary> /// Reads a sequence of bytes from the current connection. /// </summary> /// <param name="buffer">An array of bytes.</param> /// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream.</param> /// <param name="count">The maximum number of bytes to be read from the current stream.</param> /// <returns>The total number of bytes read into the buffer.</returns> public override int Read(byte[] buffer, int offset, int count) { int size = 0; int resultSize = 0; for ( ; ;) { if (!this.IsValid) { throw GenuineExceptions.Get_Processing_TransportConnectionFailed(); } // check whether we have the next portion if (this._currentPosition < this._validLength) { size = Math.Min(this._validLength - this._currentPosition, count); Marshal.Copy((IntPtr)(this._pointer.ToInt32() + this._receiveOffset + this._currentPosition + SHARE_CONTENT_OFFSET), buffer, offset, size); this._currentPosition += size; count -= size; resultSize += size; offset += size; } if (count <= 0 || this._messageRead) { return(resultSize); } ReadNextPortion(); } }
/// <summary> /// Constructs the response to the specified message. /// </summary> /// <param name="sourceMessage">The source message.</param> /// <param name="iTransportHeaders">The transport headers.</param> /// <param name="stream">The message content.</param> public Message(Message sourceMessage, ITransportHeaders iTransportHeaders, Stream stream) { this.ITransportContext = sourceMessage.ITransportContext; this.ITransportHeaders = iTransportHeaders; // this.Sender = sourceMessage.Recipient; this.Recipient = sourceMessage.Sender; this.ReplyToId = sourceMessage.MessageId; this.GenuineMessageType = sourceMessage.GenuineMessageType; this.Stream = stream; this.ConnectionName = sourceMessage.ConnectionName; this.SecuritySessionParameters = this.ITransportContext.FixSecuritySessionParameters(sourceMessage.SecuritySessionParameters); this.IsSynchronous = (this.SecuritySessionParameters.Attributes & SecuritySessionAttributes.ForceSync) != 0 || ((bool)this.ITransportContext.IParameterProvider[GenuineParameter.SyncResponses] && (this.SecuritySessionParameters.Attributes & SecuritySessionAttributes.ForceAsync) == 0); if (this.ITransportHeaders != null) { this.ITransportHeaders[TransportHeadersSenderEntryName] = this.Sender; } this.MessageId = Interlocked.Increment(ref _currentMessageId); #if TRIAL if (this.MessageId > 3010) { throw GenuineExceptions.Get_Channel_TrialConditionExceeded("The maximum number of messages restriction has been exceeded. You can not send more than 3000 messages using TRIAL version."); } #endif }
/// <summary> /// Gets a Security Session. /// </summary> /// <param name="securitySessionName">The name of the Security Session.</param> /// <param name="keyStore">The store of all keys.</param> /// <returns>An object implementing ISecuritySession interface.</returns> public SecuritySession GetSecuritySession(string securitySessionName, IKeyStore keyStore) { lock (this.DisposeLock) { if (this.IsDisposed) { throw OperationException.WrapException(this.DisposeReason); } lock (_securitySessions) { SecuritySession iSecuritySession = _securitySessions[securitySessionName] as SecuritySession; if (iSecuritySession == null) { IKeyProvider iKeyProvider = keyStore.GetKey(securitySessionName); if (iKeyProvider == null) { throw GenuineExceptions.Get_Security_ContextNotFound(securitySessionName); } iSecuritySession = iKeyProvider.CreateSecuritySession(securitySessionName, this); _securitySessions[securitySessionName] = iSecuritySession; } return(iSecuritySession); } } }
/// <summary> /// Handles the incoming request. /// </summary> /// <param name="message">The response.</param> /// <returns>The response.</returns> public Stream HandleRequest(Message message) { // fetch the name of the server service IServerServiceEntry iServerServiceEntry = null; string entryName = message.DestinationMarshalByRef as string; if (entryName != null) { iServerServiceEntry = this._services[entryName] as IServerServiceEntry; } // there is no service registered in the local collection, try the global collection if (entryName != null && iServerServiceEntry == null) { iServerServiceEntry = _globalServices[entryName] as IServerServiceEntry; } if (iServerServiceEntry == null) { // no services are registered to handle this request // message.ITransportContext.IEventLogger.Log(LogMessageCategory.Error, null, "DirectExchangeManager.HandlerRequest", // null, "There are no services associated with the \"{0}\" name. Incoming request is ignored.", entryName == null ? "<null!>" : entryName); message.ITransportContext.IGenuineEventProvider.Fire(new GenuineEventArgs(GenuineEventType.UnknownServerService, null, message.Sender, entryName)); throw GenuineExceptions.Get_Receive_NoServices(entryName); } return(iServerServiceEntry.HandleMessage(message.Stream, message.Sender)); }
/// <summary> /// Releases all resources. /// </summary> /// <param name="reason">The reason of disposing.</param> public void Dispose(Exception reason) { if (this.IsDisposed) { return; } if (reason == null) { reason = GenuineExceptions.Get_Processing_TransportConnectionFailed(); } // stop the processing using (new WriterAutoLocker(this.DisposeLock)) { if (this.IsDisposed) { return; } this.IsDisposed = true; this._disposeReason = reason; } InternalDispose(reason); }
/// <summary> /// Stops listening to the specified end point. Does not close any connections. /// </summary> /// <param name="endPoint">The end point</param> public override void StopListening(object endPoint) { lock (this) { if (this._socket == null) { return; } // LOG: BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; if (binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0) { binaryLogWriter.WriteEvent(LogCategory.Connection, "UdpConnectionManager.StopListening", LogMessageType.ListeningStopped, null, null, null, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, this.DbgConnectionId, 0, 0, 0, null, null, null, null, "The listening socket is not longer associated with the {0} local end point.", endPoint == null ? string.Empty : endPoint.ToString()); } SocketUtility.CloseSocket(this._socket); this._socket = null; this._closing = true; } if (!this._receivingThreadClosed.WaitOne(TimeSpan.FromMinutes(2), false)) { throw GenuineExceptions.Get_Processing_LogicError("Receiving thread didn't exit within 2 minutes."); } }
/// <summary> /// Sends the message to the remote host. /// Returns a response if the corresponding Security Session is established and the initial message is not one-way. /// </summary> /// <param name="message">Message to be sent or a null reference (if there is a queued message).</param> protected override void InternalSend(Message message) { SharedMemoryConnection sharedMemoryConnection = null; string uri = message.Recipient.Url; bool isServer = false; // get the connection lock (message.Recipient.PersistentConnectionEstablishingLock) { switch (message.Recipient.GenuinePersistentConnectionState) { case GenuinePersistentConnectionState.NotEstablished: if (message.Recipient.Url == null) { throw GenuineExceptions.Get_Send_DestinationIsUnreachable(message.Recipient.Uri); } message.Recipient.GenuinePersistentConnectionState = GenuinePersistentConnectionState.Opened; break; case GenuinePersistentConnectionState.Accepted: isServer = true; uri = message.Recipient.Uri; break; } // if it's possible to establish a connection to the remote host if (!isServer) { sharedMemoryConnection = this._persistent[uri] as SharedMemoryConnection; if (sharedMemoryConnection == null) { // try to establish a persistent connection string remoteUri; int remoteHostUniqueIdentifier; sharedMemoryConnection = this.LowLevel_OpenConnection(message.Recipient, this.Local.Uri, out remoteUri, out remoteHostUniqueIdentifier); // update remote host info message.Recipient.UpdateUri(remoteUri, remoteHostUniqueIdentifier); sharedMemoryConnection.Remote = message.Recipient; sharedMemoryConnection.SignalState(GenuineEventType.GeneralConnectionEstablished, null, null); // OK, connection established this._persistent[uri] = sharedMemoryConnection; this.Connection_InitiateReceiving(sharedMemoryConnection); } } else { // remote host is a client and if there is no connection to it, it's unreachable sharedMemoryConnection = this._persistent[uri] as SharedMemoryConnection; if (sharedMemoryConnection == null) { throw GenuineExceptions.Get_Send_DestinationIsUnreachable(message.Recipient.Uri); } } } this.SendSync(message, sharedMemoryConnection); }
/// <summary> /// Resolves IP address. Throws the CanNotResolveHostName exception if resolving fails. /// </summary> /// <param name="url">Url to resolve.</param> /// <returns>Resolved IPAddress.</returns> public static IPAddress ResolveIPAddress(string url) { IPAddress ipAddress = null; try { if (url.Length > 0 && url[0] >= '0' && url[0] <= '9') { ipAddress = IPAddress.Parse(url); } } catch { } if (ipAddress == null) { IPAddress[] addresses = Dns.GetHostEntry(url).AddressList; if (addresses.Length <= 0) { throw GenuineExceptions.Get_Connect_CanNotResolveHostName(url); } ipAddress = addresses[0]; } if (ipAddress == null) { throw GenuineExceptions.Get_Connect_CanNotResolveHostName(url); } return(ipAddress); }
/// <summary> /// Sends a message synchronously. Does not process exceptions! /// </summary> /// <param name="content">The content being sent to the remote host.</param> /// <param name="timeout">The sending must be completed before this moment.</param> public void LowLevel_SendSync(Stream content, int timeout) { // apply the connection-level security session if (this.ConnectionLevelSecurity != null) { GenuineChunkedStream outputStream = new GenuineChunkedStream(true); this.ConnectionLevelSecurity.Encrypt(content, outputStream); content = outputStream; } for ( ; ;) { if (!this.IsValid) { throw GenuineExceptions.Get_Processing_TransportConnectionFailed(); } if (!GenuineUtility.WaitOne(_namedEventRemoteReadCompleted.ManualResetEvent, GenuineUtility.GetMillisecondsLeft(timeout))) { throw GenuineExceptions.Get_Send_Timeout(); } if (this._closed != 0) { throw GenuineExceptions.Get_Receive_ConnectionClosed(); } this._namedEventRemoteReadCompleted.ManualResetEvent.Reset(); // read the next portion int bytesRead = content.Read(this._sendBuffer, 0, this._sendSpaceSize); // LOG: BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; if (binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0) { binaryLogWriter.WriteTransportContentEvent(LogCategory.LowLevelTransport, "GenuineSaredMemoryConnection.LowLevel_SendSync", LogMessageType.LowLevelTransport_AsyncSendingInitiating, null, null, this.Remote, binaryLogWriter[LogCategory.LowLevelTransport] > 1 ? new MemoryStream(this._sendBuffer, 0, bytesRead) : null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, this.DbgConnectionId, bytesRead, null, null, null, "Content sending."); } Marshal.Copy(this._sendBuffer, 0, (IntPtr)(this._pointer.ToInt32() + this._sendOffset + SHARE_CONTENT_OFFSET), bytesRead); this._MessageToSendTotalSize = bytesRead; this._MessageToSendFinishFlag = bytesRead < this._sendSpaceSize ? 1 : 0; this._namedEventWriteCompleted.ManualResetEvent.Set(); if (bytesRead < this._sendSpaceSize) { this.UpdateLastTimeAMessageWasSent(); return; } } }
/// <summary> /// Constructs a blank instance of the Message class. /// </summary> public Message() { #if TRIAL if (this.MessageId > 3003) { throw GenuineExceptions.Get_Channel_TrialConditionExceeded("The maximum number of messages restriction has been exceeded. You can not send more than 3000 messages using TRIAL version."); } #endif }
/// <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> /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. /// </summary> /// <param name="buffer">An array of bytes.</param> /// <param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream.</param> /// <param name="count">The number of bytes to be written to the current stream.</param> public override void Write(byte[] buffer, int offset, int count) { BinaryLogWriter binaryLogWriter = this._remote.ITransportContext.BinaryLogWriter; try { while (count > 0) { int milliseconds = GenuineUtility.GetMillisecondsLeft(this._writeTimeout); if (milliseconds <= 0) { throw GenuineExceptions.Get_Send_Timeout(); } this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, milliseconds); int bytesSent = this._socket.Send(buffer, offset, count, SocketFlags.None); // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0) { binaryLogWriter.WriteTransportContentEvent(LogCategory.LowLevelTransport, "SyncSocketWritingStream.Write", LogMessageType.LowLevelTransport_SyncSendingCompleted, null, null, this._remote, binaryLogWriter[LogCategory.LowLevelTransport] > 1 ? new MemoryStream(GenuineUtility.CutOutBuffer(buffer, offset, count)) : null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, this._dbgConnectionId, count, this._socket.RemoteEndPoint.ToString(), null, null, "Immediately after Socket.Send(). Size: {0}. Sent: {1}.", count, bytesSent); } if (bytesSent == 0) { throw GenuineExceptions.Get_Send_TransportProblem(); } offset += bytesSent; count -= bytesSent; this._connectionManager.IncreaseBytesSent(bytesSent); } } catch (Exception ex) { // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0) { binaryLogWriter.WriteTransportContentEvent(LogCategory.LowLevelTransport, "SyncSocketWritingStream.Write", LogMessageType.LowLevelTransport_SyncSendingCompleted, ex, null, this._remote, binaryLogWriter[LogCategory.LowLevelTransport] > 1 ? new MemoryStream(GenuineUtility.CutOutBuffer(buffer, offset, count)) : null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, this._dbgConnectionId, count, null, null, null, "Socket.Send(); ERROR."); } throw GenuineExceptions.Get_Send_TransportProblem(); } }
/// <summary> /// Opens an existent event object with the specified name. /// </summary> /// <param name="name">The name of the global Event.</param> /// <returns>The opened event object.</returns> public static NamedEvent OpenNamedEvent(string name) { IntPtr handler = WindowsAPI.OpenEvent(WindowsAPI.EVENT_ALL_ACCESS, 0, name); if (handler == IntPtr.Zero) { throw GenuineExceptions.Get_Windows_CanNotCreateOrOpenNamedEvent(Marshal.GetLastWin32Error()); } return(new NamedEvent(handler)); }
/// <summary> /// Constructs an instance of the Dispatcher class. /// </summary> /// <param name="interfaceToSupport">The interface which is supported by all receivers.</param> public Dispatcher(Type interfaceToSupport) { if (!interfaceToSupport.IsInterface) { throw GenuineExceptions.Get_Broadcast_DestinationTypeMustBeAnInterface(); } this._broadcastProxy = new BroadcastProxy(interfaceToSupport, this); this._transparentProxy = _broadcastProxy.GetTransparentProxy(); this._interfaceToSupport = interfaceToSupport; }
/// <summary> /// Reads the response from the stream. /// </summary> /// <param name="binaryReader">The source.</param> /// <param name="serverUri">The fetched server uri.</param> /// <param name="sequenceNo">The packet number.</param> /// <param name="httpPacketType">The type of the packet.</param> /// <param name="remoteHostUniqueIdentifier">The unique identifier of the HostInformation used by the remote host.</param> public static void ReadResponseHeader(BinaryReader binaryReader, out string serverUri, out int sequenceNo, out HttpPacketType httpPacketType, out int remoteHostUniqueIdentifier) { if (binaryReader.ReadByte() != MessageCoder.COMMAND_MAGIC_CODE) { throw GenuineExceptions.Get_Receive_IncorrectData(); } serverUri = binaryReader.ReadString(); sequenceNo = binaryReader.ReadInt32(); httpPacketType = (HttpPacketType)binaryReader.ReadByte(); remoteHostUniqueIdentifier = binaryReader.ReadInt32(); }
/// <summary> /// Parses the specified HTTP header line. /// </summary> /// <param name="line">The line of the HTTP header.</param> /// <param name="indexOfFirstDigit">The index of the first digit in the line.</param> /// <param name="indexOfLastDigit">The index of the last digit in the line.</param> /// <returns>The type of HTTP header field.</returns> public HeaderFields ParseHeader(string line, int indexOfFirstDigit, int indexOfLastDigit) { this._lineNumber++; if (!this._firstLineIsParsed) { int indexOfHttp = line.IndexOf("TTP/"); if (indexOfHttp < 0) { throw GenuineExceptions.Get_Receive_IncorrectData(); } this._firstLineIsParsed = true; this._isHttp11 = line.Substring(indexOfHttp + 4, 3).CompareTo("1.1") == 0; if (line.IndexOf("409", indexOfHttp + 1) >= 0) { throw GenuineExceptions.Get_Receive_ConflictOfConnections(); } return(HeaderFields.FirstLine); } if (this._client && !_firstLineIsParsed) { throw GenuineExceptions.Get_Receive_IncorrectData(); } if (!this._contentLengthIsParsed && line.IndexOf("CONTENT-LENGTH") >= 0) { this._contentLength = Convert.ToInt64(line.Substring(indexOfFirstDigit, indexOfLastDigit - indexOfFirstDigit + 1)); return(HeaderFields.ContentLength); } if (!this._client) { int indexOfExpect; if (!this._http11_100continueIsParsed && (indexOfExpect = line.IndexOf("EXPECT")) >= 0 && line.IndexOf("100", indexOfExpect + 1) >= 0) { this._http11_100continueIsParsed = true; this._http11_100Continue = true; return(HeaderFields.Expect100Continue); } } if (this._lineNumber > 30) { throw GenuineExceptions.Get_Receive_IncorrectData(); } return(HeaderFields.OtherField); }
/// <summary> /// Reads settings. /// </summary> /// <param name="properties">Settings container to read from.</param> protected virtual void ReadSettings(IDictionary properties) { // retrieve settings foreach (DictionaryEntry entry in properties) { if (string.Compare(entry.Key.ToString(), "name", true) == 0) { this._channelName = entry.Value.ToString(); } if (string.Compare(entry.Key.ToString(), "priority", true) == 0) { this._channelPriority = GenuineUtility.SafeConvertToInt32(entry.Value, this._channelPriority); } if (string.Compare(entry.Key.ToString(), "prefix", true) == 0) { this._urlPrefix = entry.Value.ToString(); if (!this._urlPrefix.StartsWith("g") || this._urlPrefix.Length < 4 || this._urlPrefix.Length > 8) { GenuineExceptions.Get_Channel_InvalidParameter("prefix"); } } } // enable compresion if such an option is specified if ((bool)this.ITransportContext.IParameterProvider[GenuineParameter.Compression]) { this.SecuritySessionParameters = SecuritySessionServices.DefaultContextWithCompression; } #if DEBUG try { // enable logging if (this.ITransportContext.IParameterProvider[GenuineParameter.EnableGlobalLoggingToFile] is string && ((string)this.ITransportContext.IParameterProvider[GenuineParameter.EnableGlobalLoggingToFile]).Length > 0) { GenuineLoggingServices.SetUpLoggingToFile(this.ITransportContext.IParameterProvider[GenuineParameter.EnableGlobalLoggingToFile] as string, this.ITransportContext.IParameterProvider[GenuineParameter.LoggingParameters] as string); } else if (this.ITransportContext.IParameterProvider[GenuineParameter.EnableGlobalLoggingToMemory] is int && ((int)this.ITransportContext.IParameterProvider[GenuineParameter.EnableGlobalLoggingToMemory]) > 0) { GenuineLoggingServices.SetUpLoggingToMemory((int)this.ITransportContext.IParameterProvider[GenuineParameter.EnableGlobalLoggingToMemory], this.ITransportContext.IParameterProvider[GenuineParameter.LoggingParameters] as string); } } catch { } #endif }
/// <summary> /// Creates and returns a stream containing decrypted data. /// </summary> /// <param name="input">A stream containing encrypted data.</param> /// <returns>A stream with decrypted data.</returns> public override Stream Decrypt(Stream input) { // check on view whether it's session's packet if (input.ReadByte() == 0) { // continue the Security Session establishing Stream outputStream = this.EstablishSession(input, false); if (outputStream != null) { GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this.SendMessage), outputStream, false); } return(null); } lock (this) { GenuineChunkedStream output = new GenuineChunkedStream(false); byte[] sign = null; int signSize = 0; if (this.KeyedHashAlgorithm != null) { signSize = this.KeyedHashAlgorithm.HashSize / 8; } // decrypt the content and fetch the sign if (this._decryptor != null) { CryptoStream cryptoStream = new CryptoStream(new FinishReadingStream(output), this._decryptor, CryptoStreamMode.Write); sign = GenuineUtility.CopyStreamToStreamExceptSign(input, cryptoStream, signSize); cryptoStream.FlushFinalBlock(); } else { sign = GenuineUtility.CopyStreamToStreamExceptSign(input, output, signSize); } // check the sign if (this.KeyedHashAlgorithm != null) { if (!ZeroProofAuthorizationUtility.CompareBuffers(sign, this.KeyedHashAlgorithm.ComputeHash(output), sign.Length)) { throw GenuineExceptions.Get_Security_WrongSignature(); } output.Position = 0; } output.ReleaseOnReadMode = true; return(output); } }
// /// <summary> // /// Creates a new mutex with NULL DACL. // /// </summary> // /// <param name="mutex">The mutex.</param> // /// <param name="name">The name of the mutex.</param> // static internal void UpgrageMutexSecurity(Mutex mutex, string name) // { // CloseHandle(mutex.Handle); // mutex.Handle = CreateMutex(AttributesWithNullDACL, false, name); // } /// <summary> /// Opens an existent mutex. /// </summary> /// <param name="name">The name of the mutex.</param> /// <returns>The opened mutex.</returns> static internal Mutex OpenMutex(string name) { IntPtr result = OpenMutex(MUTEX_ALL_ACCESS, false, name); if (result == IntPtr.Zero) { throw GenuineExceptions.Get_Windows_SharedMemoryError(Marshal.GetLastWin32Error()); } Mutex mutex = new Mutex(); mutex.SafeWaitHandle = new SafeWaitHandle(result, true); return(mutex); }
/// <summary> /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. /// </summary> /// <param name="buffer">An array of bytes.</param> /// <param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream.</param> /// <param name="count">The number of bytes to be written to the current stream.</param> public override void Write(byte[] buffer, int offset, int count) { while (count > 0) { int bytesSent = this._socket.Send(buffer, offset, count, SocketFlags.None); if (bytesSent == 0) { throw GenuineExceptions.Get_Send_TransportProblem(); } this._connectionManager.IncreaseBytesSent(bytesSent); count -= bytesSent; offset += bytesSent; } }
/// <summary> /// Creates named event object. /// </summary> /// <param name="name">The name of the event object.</param> /// <param name="initialState">If this parameter is TRUE, the initial state of the event object is signaled; otherwise, it is nonsignaled.</param> /// <param name="manualReset">If this parameter is FALSE, the function creates an auto-reset event object, and system automatically resets the state to nonsignaled after a single waiting thread has been released.</param> /// <returns>Created event object.</returns> public static NamedEvent CreateNamedEvent(string name, bool initialState, bool manualReset) { if (WindowsAPI.FailureReason != null) { throw OperationException.WrapException(WindowsAPI.FailureReason); } IntPtr handler = WindowsAPI.CreateEvent(WindowsAPI.AttributesWithNullDACL, manualReset ? 1 : 0, (initialState ? 1 : 0), name); if (handler == IntPtr.Zero) { throw GenuineExceptions.Get_Windows_CanNotCreateOrOpenNamedEvent(Marshal.GetLastWin32Error()); } return(new NamedEvent(handler)); }
/// <summary> /// Provides a stream reading synchronously from the given connection. /// </summary> /// <param name="finishTime">Read timeout.</param> /// <returns>A stream.</returns> public Stream LowLevel_ReadSync(int finishTime) { if (!this.IsValid) { throw GenuineExceptions.Get_Processing_TransportConnectionFailed(); } this._currentPosition = this._validLength; this._messageRead = false; this._readDeadline = finishTime; if (this.ConnectionLevelSecurity != null) { return(this.ConnectionLevelSecurity.Decrypt(this)); } return(this); }
/// <summary> /// Reads data from the socket. /// </summary> /// <param name="buffer">An array of type Byte that is the storage location for received data.</param> /// <param name="offset">The location in buffer to store the received data.</param> /// <param name="count">The number of bytes to receive.</param> /// <returns>The number of bytes read.</returns> public int ReadFromSocket(byte[] buffer, int offset, int count) { BinaryLogWriter binaryLogWriter = this._tcpConnectionManager.ITransportContext.BinaryLogWriter; try { int millisecondsRemained = GenuineUtility.GetMillisecondsLeft(this._receiveTimeout); if (millisecondsRemained <= 0) { throw GenuineExceptions.Get_Send_ServerDidNotReply(); } this._tcpSocketInfo.Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, millisecondsRemained); int bytesReceived = this._tcpSocketInfo.Socket.Receive(buffer, offset, count, SocketFlags.None); // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0) { binaryLogWriter.WriteTransportContentEvent(LogCategory.LowLevelTransport, "SyncSocketReadingStream.ReadFromSocket", LogMessageType.LowLevelTransport_SyncReceivingCompleted, null, null, this._tcpSocketInfo.Remote, binaryLogWriter[LogCategory.LowLevelTransport] > 1 ? new MemoryStream(buffer, offset, bytesReceived) : null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, this._tcpSocketInfo.DbgConnectionId, bytesReceived, this._tcpSocketInfo.Socket.RemoteEndPoint.ToString(), null, null, "Socket.Receive(). Bytes received: {0}.", bytesReceived); } this._tcpConnectionManager.IncreaseBytesReceived(bytesReceived); return(bytesReceived); } catch (Exception ex) { // LOG: if (binaryLogWriter != null && binaryLogWriter[LogCategory.LowLevelTransport] > 0) { binaryLogWriter.WriteEvent(LogCategory.LowLevelTransport, "SyncSocketReadingStream.ReadFromSocket", LogMessageType.LowLevelTransport_SyncReceivingCompleted, ex, null, this._tcpSocketInfo.Remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, this._tcpSocketInfo.DbgConnectionId, 0, 0, 0, null, null, null, null, "Socket.Receive() failed."); } throw; } }
/// <summary> /// Creates and returns a stream containing decrypted data. /// </summary> /// <param name="input">A stream containing encrypted data.</param> /// <returns>A stream with decrypted data.</returns> public override Stream Decrypt(Stream input) { // check on view whether it's session's packet if (input.ReadByte() == 0) { // continue the Security Session establishing Stream outputStream = this.EstablishSession(input, false); if (outputStream != null) { GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this.SendMessage), outputStream, false); } return(null); } if (this.RijndaelKey == null) { throw GenuineExceptions.Get_Security_ContextWasNotEstablished(this.Name); } lock (this.RijndaelKey) { if (this._decryptor == null) { Rijndael rijndael = Rijndael.Create(); rijndael.Key = this.RijndaelKey; rijndael.Mode = CipherMode.ECB; this._encryptor = rijndael.CreateEncryptor(); this._decryptor = rijndael.CreateDecryptor(); } } lock (this._decryptor) { GenuineChunkedStream output = new GenuineChunkedStream(true); GenuineUtility.CopyStreamToStream(new CryptoStream(new FinishReadingStream(input), this._decryptor, CryptoStreamMode.Read), output); GenuineUtility.CopyStreamToStream(input, Stream.Null); input.Close(); return(output); } }
/// <summary> /// Closes the current stream and releases any resources associated with the current stream. /// </summary> public override void Close() { // read the remaining bytes if (this._assumedLength > 0) { using (BufferKeeper bufferKeeper = new BufferKeeper(0)) { while (this._assumedLength > 0) { int bytesRead = this._underlyingStream.Read(bufferKeeper.Buffer, 0, (int)this._assumedLength); this._assumedLength -= bytesRead; if (bytesRead == 0) { throw GenuineExceptions.Get_Receive_IncorrectData(); } } } } }
/// <summary> /// Releases the element with the specified index. /// </summary> /// <param name="index">The index.</param> private void ReleaseConnectionEntry(int index) { lock (this._availableConnections) { #if DEBUG if (this._availableConnections.Count <= index) { throw GenuineExceptions.Get_Processing_LogicError("HttpInvocationConnection.ReleaseConnectionEntry. The requested element does not exist."); } if ((bool)this._availableConnections[index]) { throw GenuineExceptions.Get_Processing_LogicError("HttpInvocationConnection.ReleaseConnectionEntry. Element is already available!"); } #endif this._availableConnections[index] = true; } }
/// <summary> /// Copies data from the stream to the buffer. /// If the stream does not contain specified number of bytes, an exception will be thrown. /// </summary> /// <param name="inputStream">The source stream to copy data from.</param> /// <param name="buffer">The buffer to copy data from.</param> /// <param name="offset">The zero-based byte offset in a buffer at which to begin storing the data read from the current stream.</param> /// <param name="sizeToRead">The size of the chunk being copied.</param> public static void ReadDataFromStream(Stream inputStream, byte[] buffer, int offset, int sizeToRead) { if (sizeToRead <= 0) { return; } int readPortion = 0; int readSize = inputStream.Read(buffer, offset, sizeToRead); for ( ; readSize < sizeToRead; readSize += readPortion) { readPortion = inputStream.Read(buffer, offset + readSize, sizeToRead - readSize); if (readPortion <= 0) { throw GenuineExceptions.Get_Receive_Portion(); } } }