/// <summary> /// Constructs an instance of the XHttpPhysicalConnection class. /// </summary> /// <param name="xHttpConnection">The physical connection.</param> /// <param name="sender">The sender.</param> public XHttpPhysicalConnection(XHttpConnection xHttpConnection, bool sender) { this.XHttpConnection = xHttpConnection; this.IsSender = sender; this.AsyncSendBuffer = new byte[35000]; this.AsyncReceiveBuffer = new byte[35000]; #if DEBUG this._connectionNumber = Interlocked.Increment(ref _TotalConnections); #endif }
/// <summary> /// Operates with failed sockets. /// </summary> /// <param name="exception">The source exception.</param> /// <param name="xHttpConnection">The failed logical connection.</param> /// <param name="xHttpPhysicalConnection">The failed physical connection.</param> private void ConnectionFailed(Exception exception, XHttpConnection xHttpConnection, XHttpPhysicalConnection xHttpPhysicalConnection) { BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; try { if (xHttpPhysicalConnection == null && xHttpConnection == null) { // LOG: if ( binaryLogWriter != null ) { binaryLogWriter.WriteImplementationWarningEvent("XHttpConnectionManager.ConnectionFailed", LogMessageType.ConnectionFailed, exception, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, "The connection has not been specified while invoking XHttpConnectionManager.ConnectionFailed."); } return ; } OperationException operationException = exception as OperationException; bool conflict409Received = false; if (operationException != null) conflict409Received = operationException.OperationErrorMessage.ErrorIdentifier.IndexOf("ConflictOfConnections") >= 0; // if it's a server, just close the connection // if it's a client sender, re-send it again // if it's a client listener, re-send the request again with the same seq no bool tryToReestablish = ! ConnectionManager.IsExceptionCritical(exception as OperationException); HostInformation remote = null; if (xHttpConnection != null) remote = xHttpConnection.Remote; // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { binaryLogWriter.WriteEvent(LogCategory.Connection, "XHttpConnectionManager.ConnectionFailed", LogMessageType.ConnectionFailed, exception, null, remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, xHttpConnection == null ? -1 : xHttpConnection.DbgConnectionId, 0, 0, 0, null, null, null, null, "XHTTP connection has failed."); } using (new ReaderAutoLocker(this._disposeLock)) { if (this._disposed) tryToReestablish = false; } // close the socket if (xHttpPhysicalConnection != null) GenuineThreadPool.QueueUserWorkItem(new WaitCallback(SocketUtility.CloseSocket), xHttpPhysicalConnection.Socket, true); switch (xHttpConnection.GenuineConnectionType) { case GenuineConnectionType.Persistent: // ignore connections causing conflict if (conflict409Received) break; lock (remote.PersistentConnectionEstablishingLock) { using (new ReaderAutoLocker(this._disposeLock)) { if (! tryToReestablish || xHttpConnection.IsDisposed) { this._persistent.Remove(remote.PrimaryUri, xHttpConnection.ConnectionName); // release all resources this.ITransportContext.KnownHosts.ReleaseHostResources(xHttpConnection.Remote, exception); xHttpConnection.Dispose(exception); xHttpConnection.SignalState(GenuineEventType.GeneralConnectionClosed, exception, null); if (exception is OperationException && ((OperationException) exception).OperationErrorMessage.ErrorIdentifier == "GenuineChannels.Exception.Receive.ServerHasBeenRestarted") xHttpConnection.SignalState(GenuineEventType.GeneralServerRestartDetected, exception, null); break; } xHttpConnection.SignalState(GenuineEventType.GeneralConnectionReestablishing, exception, null); // start reestablishing if (remote.GenuinePersistentConnectionState == GenuinePersistentConnectionState.Opened) { // start the reestablishing, if possible if (xHttpPhysicalConnection != null && xHttpPhysicalConnection.Reestablish_ObtainStatus()) GenuineThreadPool.QueueUserWorkItem(new WaitCallback(this.ReestablishConnection), xHttpPhysicalConnection, true); } } // using (new ReaderAutoLocker(this._disposeLock)) } // lock (remote.PersistentConnectionEstablishingLock) break; case GenuineConnectionType.Invocation: break; } } catch(Exception ex) { // LOG: if ( binaryLogWriter != null ) binaryLogWriter.WriteImplementationWarningEvent("XHttpConnectionManager.ConnectionFailed", LogMessageType.Warning, ex, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, "An unexpected exception is raised inside XHttpConnectionManager.ConnectionFailed method. Most likely, something must be fixed."); } }
/// <summary> /// Processes the sending request on the server side. /// </summary> /// <param name="xHttpConnection">The connection.</param> /// <param name="xHttpPhysicalConnection">The physical connection.</param> /// <param name="inputStream">The connection.</param> private void Pool_Server_ProcessSenderRequest(XHttpConnection xHttpConnection, XHttpPhysicalConnection xHttpPhysicalConnection, Stream inputStream) { Exception gotException = null; try { this.LowLevel_ParseLabelledStream(inputStream, xHttpPhysicalConnection); inputStream.Close(); } catch(Exception ex) { gotException = ex; // LOG: BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { binaryLogWriter.WriteEvent(LogCategory.Connection, "XHttpConnectionManager.Pool_Server_ProcessSenderRequest", LogMessageType.ReceivingFinished, ex, null, xHttpConnection.Remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, xHttpConnection.DbgConnectionId, 0, 0, 0, null, null, null, null, "Error occurred while parsing HTTP Sender Request. Sequence No: {0}.", xHttpPhysicalConnection.SequenceNo); } } if (gotException != null) { gotException = OperationException.WrapException(gotException); GenuineChunkedStream outputStream = new GenuineChunkedStream(false); BinaryFormatter binaryFormatter = new BinaryFormatter(new RemotingSurrogateSelector(), new StreamingContext(StreamingContextStates.Other)); binaryFormatter.Serialize(outputStream, gotException); this.LowLevel_SendHttpContent(GenuineUtility.GetTimeout(xHttpConnection.CloseConnectionAfterInactivity), null, null, gotException, null, xHttpPhysicalConnection, GenuineConnectionType.Persistent, HttpPacketType.SenderError, false, true, true, false); } else { // serialize and send the OK response this.LowLevel_SendHttpContent(GenuineUtility.GetTimeout(xHttpConnection.CloseConnectionAfterInactivity), null, null, null, null, xHttpPhysicalConnection, GenuineConnectionType.Persistent, HttpPacketType.SenderResponse, false, true, true, false); } }
/// <summary> /// Processes the listening request on the server side. /// </summary> /// <param name="xHttpConnection">The connection.</param> /// <param name="xHttpPhysicalConnection">The physical connection.</param> private void Pool_Server_ProcessListenerRequest(XHttpConnection xHttpConnection, XHttpPhysicalConnection xHttpPhysicalConnection) { lock (xHttpConnection.Listener.PhysicalConnectionStateLock) { try { Message message = xHttpConnection.MessageContainer.GetMessage(); if (message == null) { // no data is available, postpone the request // xHttpPhysicalConnection.Listener_Opened = GenuineUtility.TickCount; xHttpPhysicalConnection.MarkAsAvailable(); return; } // some data is available, gather the stream and send it this.LowLevel_SendHttpContent(GenuineUtility.GetTimeout(xHttpConnection.CloseConnectionAfterInactivity), message, null, null, xHttpConnection.MessageContainer, xHttpPhysicalConnection, xHttpConnection.GenuineConnectionType, HttpPacketType.Usual, false, true, true, true); } catch(Exception ex) { // LOG: BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { binaryLogWriter.WriteEvent(LogCategory.Connection, "XHttpConnectionManager.Pool_Server_ProcessListenerRequest", LogMessageType.AsynchronousSendingStarted, ex, null, xHttpPhysicalConnection.Remote, null, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, null, null, xHttpConnection.DbgConnectionId, 0, 0, 0, null, null, null, null, "Error occurred while sending HTTP Listener Request. Sequence No: {0}.", xHttpPhysicalConnection.SequenceNo); } } } }
/// <summary> /// Creates and registers a logical connection to the specified host. /// </summary> /// <param name="remote">The remote host.</param> /// <param name="primaryUri">The primary uri of the remote host.</param> /// <param name="isClient">The type of the behavior applying to the connection.</param> /// <param name="connectionName">Connection name.</param> /// <returns>The created connection.</returns> private XHttpConnection Pool_CreateConnection(HostInformation remote, string primaryUri, bool isClient, string connectionName) { BinaryLogWriter binaryLogWriter = this.ITransportContext.BinaryLogWriter; if (connectionName == null) connectionName = this.GetUniqueConnectionName(); using (new ReaderAutoLocker(this._disposeLock)) { XHttpConnection xHttpConnection = new XHttpConnection(this, isClient, connectionName); xHttpConnection.Remote = remote; xHttpConnection.CloseConnectionAfterInactivity = GenuineUtility.ConvertToMilliseconds(this.ITransportContext.IParameterProvider[GenuineParameter.ClosePersistentConnectionAfterInactivity]); xHttpConnection.GenuineConnectionType = GenuineConnectionType.Persistent; xHttpConnection.Sender = new XHttpPhysicalConnection(xHttpConnection, true); xHttpConnection.Listener = new XHttpPhysicalConnection(xHttpConnection, false); xHttpConnection.MessageContainer = new MessageContainer(this.ITransportContext); this._persistent.Set(primaryUri, connectionName, xHttpConnection); // and CLSS string securitySessionName = this.ITransportContext.IParameterProvider[GenuineParameter.SecuritySessionForPersistentConnections] as string; if (securitySessionName != null) { xHttpConnection.Sender.ConnectionLevelSecurity = this.ITransportContext.IKeyStore.GetKey(securitySessionName).CreateSecuritySession(securitySessionName, null); xHttpConnection.Listener.ConnectionLevelSecurity = this.ITransportContext.IKeyStore.GetKey(securitySessionName).CreateSecuritySession(securitySessionName, null); } // LOG: if ( binaryLogWriter != null && binaryLogWriter[LogCategory.Connection] > 0 ) { binaryLogWriter.WriteConnectionParameterEvent(LogCategory.Connection, "XHttpConnectionManager.Pool_CreateConnection", LogMessageType.ConnectionParameters, null, remote, this.ITransportContext.IParameterProvider, GenuineUtility.CurrentThreadId, Thread.CurrentThread.Name, xHttpConnection.DbgConnectionId, "An XHTTP connection is being established."); } return xHttpConnection; } }