/// <summary> /// Verarbeitet eine Anfragenachricht asynchron. /// </summary> /// <param name="sinkStack">Senkenstapel</param> /// <param name="msg">Remoting-Nachricht</param> /// <param name="headers">Anfrage-Header-Auflistung</param> /// <param name="stream">Anfrage-Datenstrom</param> public void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders headers, Stream stream) { // Asynchroner Verarbeitungsstatus AsyncProcessingState state = null; // Verschlüsselter Datenstrom Stream encryptedStream = null; // Eindeutige Kennung der Sicherheitstransaktion Guid _secureTransactionID; lock (_lockObject) { // Sicherheitstransaktion starten _secureTransactionID = StartSecureTransaction(msg, headers); // Asynchronen Verarbeitungsstatus erzeugen state = new AsyncProcessingState(msg, headers, ref stream, _secureTransactionID); // Nachricht verschlüsseln encryptedStream = EncryptMessage(headers, stream); } // Aktuelle Senke auf den Senkenstapel legen (Damit ggf. die Verarbeitung der Antwort später asynchron aufgerufen werden kann) sinkStack.Push(this, state); // Nächste Kanalsenke aufrufen _next.AsyncProcessRequest(sinkStack, msg, headers, encryptedStream); }
/// <summary>Requests asynchronous processing of a method call on the current sink.</summary> /// <param name="sinkStack">A stack of channel sinks.</param> /// <param name="msg">The message to process.</param> /// <param name="headers">The headers to send to the server.</param> /// <param name="stream">The stream headed to the transport sink.</param> public void AsyncProcessRequest( IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders headers, Stream stream) { AsyncProcessingState state = null; Stream encryptedStream = null; Guid id; lock (_transactionLock) // could be a big lock... probably a faster way, but for now suffices { // Establish connection information with the server; the roundtrip will hopefully // only be done once, so we ensure that we have the necessary information. id = EnsureIDAndProvider(msg, headers); // Protect ourselves a bit. If the asynchronous call fails because the server forgot about // us, we'll be in a bit of a fix. We'll need the current arguments as we'll need // to retry the request synchronously. Store them into a state object and use // that as the state when pushing ourself onto the stack. That way, AsyncProcessResponse // have access to it. state = new AsyncProcessingState(msg, headers, ref stream, id); // Send encrypted message by encrypting the stream encryptedStream = SetupEncryptedMessage(headers, stream); } // Push ourselves onto the stack with the necessary state and forward on to the next sink sinkStack.Push(this, state); _next.AsyncProcessRequest(sinkStack, msg, headers, encryptedStream); }
/// <summary> /// Requests asynchronous processing of a response to a method call on the current sink. /// </summary> /// <param name="sinkStack">A stack of sinks that called this sink.</param> /// <param name="state">Information generated on the request side that is associated with this sink.</param> /// <param name="headers">The headers retrieved from the server response stream.</param> /// <param name="stream">The stream coming back from the transport sink.</param> public void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, object state, ITransportHeaders headers, Stream stream) { // Gets the asynchronous processing state AsyncProcessingState asyncState = (AsyncProcessingState)state; try { SecureTransactionStage currentStage = (SecureTransactionStage)Convert.ToInt32((string)headers[CommonHeaderNames.SECURE_TRANSACTION_STATE]); switch (currentStage) { case SecureTransactionStage.SendingEncryptedResult: // Get the encrypted response from the server lock (_lockObject) { if (asyncState.SecureTransactionID.Equals(_secureTransactionID)) { stream = DecryptResponse(stream, headers); } else { throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_KeyChanged); } } break; case SecureTransactionStage.UnknownTransactionID: // Bad transaction identifier throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_InvalidTransactionID); default: case SecureTransactionStage.Uninitialized: // Secure transaction is not yet set up break; } } catch (CryptoRemotingException) { lock (_lockObject) { // If remote transaction identifier matches the local secure transaction identifier, reset the shared key if (_provider == null || asyncState.SecureTransactionID.Equals(_secureTransactionID)) { ClearSharedKey(); } ProcessMessage(asyncState.Message, asyncState.Headers, asyncState.Stream, out headers, out stream); } } finally { // Close the input stream asyncState.Stream.Close(); } // Pass on to the next sink to continue processing sinkStack.AsyncProcessResponse(headers, stream); }
public void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, object state, ITransportHeaders headers, Stream stream) { AsyncProcessingState asyncState = (AsyncProcessingState)state; try { SecureTransaction transactType = (SecureTransaction)Convert.ToInt32((string)headers[CommonHeaders.Transaction]); switch (transactType) { case SecureTransaction.SendingEncryptedResult: { lock (_transactionLock) { if (asyncState.ID.Equals(_transactID)) { stream = DecryptResponse(stream, headers); } else { throw new SecureRemotingException("The key has changed since the message was decrypted."); } } break; } case SecureTransaction.UnknownIdentifier: { throw new SecureRemotingException("The server sink was unable to identify the client, most likely due to the connection information timing out."); } default: case SecureTransaction.Uninitialized: { break; } } } catch (SecureRemotingException) { lock (_transactionLock) { if (_provider == null || asyncState.ID.Equals(_transactID)) { ClearSharedKey(); } ProcessMessage(asyncState.Message, asyncState.Headers, asyncState.Stream, out headers, out stream); } } finally { asyncState.Stream.Close(); } sinkStack.AsyncProcessResponse(headers, stream); }
public void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders headers, Stream stream) { AsyncProcessingState state = null; Stream encryptedStream = null; Guid id; lock (_transactionLock) { id = EnsureIDAndProvider(msg, headers); state = new AsyncProcessingState(msg, headers, ref stream, id); encryptedStream = SetupEncryptedMessage(headers, stream, null); } sinkStack.Push(this, state); _next.AsyncProcessRequest(sinkStack, msg, headers, encryptedStream); }
/// <summary> /// Verarbeitet eine Anfragenachricht asynchron. /// </summary> /// <param name="sinkStack">Senkenstapel</param> /// <param name="msg">Remoting-Nachricht</param> /// <param name="headers">Anfrage-Header-Auflistung</param> /// <param name="stream">Anfrage-Datenstrom</param> public void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders headers, Stream stream) { // Asynchroner Verarbeitungsstatus AsyncProcessingState state = null; lock (_lockObject) { // Asynchronen Verarbeitungsstatus erzeugen state = new AsyncProcessingState(msg, headers, ref stream, new Guid()); //Methode aufrufen die Verarbeitung übernimmt DoProcessMessageBefore(msg, headers, stream); } // Aktuelle Senke auf den Senkenstapel legen (Damit ggf. die Verarbeitung der Antwort später asynchron aufgerufen werden kann) sinkStack.Push(this, state); // Nächste Kanalsenke aufrufen _next.AsyncProcessRequest(sinkStack, msg, headers, stream); }
/// <summary> /// Verarbeitet eine Antwort-Nachricht asynchron. /// </summary> /// <param name="sinkStack">Senkenstapel</param> /// <param name="state">Asynchroner Verarbeitungsstatus</param> /// <param name="headers">Anfrage-Header-Auflistung</param> /// <param name="stream">Anfrage-Datenstrom</param> public void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, object state, ITransportHeaders headers, Stream stream) { // Asychronen Verarbeitungsstatus abrufen AsyncProcessingState asyncState = (AsyncProcessingState)state; try { lock (_lockObject) { //Todo: Was ist hier zu tun? } } finally { } ProcessMessage(asyncState.Message, asyncState.Headers, asyncState.Stream, out headers, out stream); asyncState.Stream.Close(); // Verarbeitung in der nächsten Kanalsenke fortsetzen sinkStack.AsyncProcessResponse(headers, stream); }
/// <summary> /// Requests asynchronous processing of a method call on the current sink. /// </summary> /// <param name="sinkStack">A stack of channel sinks that called this sink.</param> /// <param name="msg">The message to process.</param> /// <param name="headers">The headers to add to the outgoing message heading to the server.</param> /// <param name="stream">The stream headed to the transport sink.</param> public void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders headers, Stream stream) { AsyncProcessingState state = null; Stream encryptedStream = null; Guid _secureTransactionID; lock (_lockObject) { // Start the secure transaction and save its identifier _secureTransactionID = StartSecureTransaction(msg, headers); // Prepare asynchronous state state = new AsyncProcessingState(msg, headers, ref stream, _secureTransactionID); // Encrypt the message encryptedStream = EncryptMessage(headers, stream); } // Push the current sink onto the sink stack so the processing of the response can be invoked asynchronously later sinkStack.Push(this, state); // Pass the message on to the next sink _next.AsyncProcessRequest(sinkStack, msg, headers, encryptedStream); }
/// <summary> /// Verarbeitet eine Antwort-Nachricht asynchron. /// </summary> /// <param name="sinkStack">Senkenstapel</param> /// <param name="state">Asynchroner Verarbeitungsstatus</param> /// <param name="headers">Anfrage-Header-Auflistung</param> /// <param name="stream">Anfrage-Datenstrom</param> public void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, object state, ITransportHeaders headers, Stream stream) { // Asychronen Verarbeitungsstatus abrufen AsyncProcessingState asyncState = (AsyncProcessingState)state; try { // Aktuellen Verarbeitungsschritt der Sicherheitstransaktion ermitteln SecureTransactionStage currentStage = (SecureTransactionStage)Convert.ToInt32((string)headers[CommonHeaderNames.SECURE_TRANSACTION_STATE]); // Verarbeitungsschritt auswerten switch (currentStage) { case SecureTransactionStage.SendingEncryptedResult: // Verschlüsselte Daten vom Server eingtroffen lock (_lockObject) { // Wenn die Antwort auch tatsächlich zur aktuellen Sicherheitstransaktion gehört ... if (asyncState.SecureTransactionID.Equals(_secureTransactionID)) { // Datenstrom entschlüsseln stream = DecryptResponse(stream, headers); } // Andernfalls ... else { // Ausnahme werfen throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_KeyChanged); } } break; case SecureTransactionStage.UnknownTransactionID: // Unbekannte Transaktionskennung // Ausnahme werfen throw new CryptoRemotingException(LanguageResource.CryptoRemotingException_InvalidTransactionID); default: case SecureTransactionStage.Uninitialized: // Keine Sicherheitstransaktion eingerichtet break; } } catch (CryptoRemotingException) { lock (_lockObject) { // Wenn die gesendete Transaktionskennung mit der lokalen übereinstimmt ... if (_provider == null || asyncState.SecureTransactionID.Equals(_secureTransactionID)) { // Gemeinamen Schlüssel löschen ClearSharedKey(); } // Nachricht weiterverarbeiten ProcessMessage(asyncState.Message, asyncState.Headers, asyncState.Stream, out headers, out stream); } } finally { // Datenstrom schließen asyncState.Stream.Close(); } // Verarbeitung in der nächsten Kanalsenke fortsetzen sinkStack.AsyncProcessResponse(headers, stream); }
/// <summary>Requests asynchronous processing of a method call on the current sink.</summary> /// <param name="sinkStack">A stack of channel sinks.</param> /// <param name="msg">The message to process.</param> /// <param name="headers">The headers to send to the server.</param> /// <param name="stream">The stream headed to the transport sink.</param> public void AsyncProcessRequest( IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders headers, Stream stream) { AsyncProcessingState state = null; Stream encryptedStream = null; Guid id; lock(_transactionLock) // could be a big lock... probably a faster way, but for now suffices { // Establish connection information with the server; the roundtrip will hopefully // only be done once, so we ensure that we have the necessary information. id = EnsureIDAndProvider(msg, headers); // Protect ourselves a bit. If the asynchronous call fails because the server forgot about // us, we'll be in a bit of a fix. We'll need the current arguments as we'll need // to retry the request synchronously. Store them into a state object and use // that as the state when pushing ourself onto the stack. That way, AsyncProcessResponse // have access to it. state = new AsyncProcessingState(msg, headers, ref stream, id); // Send encrypted message by encrypting the stream encryptedStream = SetupEncryptedMessage(headers, stream); } // Push ourselves onto the stack with the necessary state and forward on to the next sink sinkStack.Push(this, state); _next.AsyncProcessRequest(sinkStack, msg, headers, encryptedStream); }
/// <summary>Requests asynchronous processing of a response to a method call on the current sink.</summary> /// <param name="sinkStack">A stack of sinks that called this sink.</param> /// <param name="state">Information generated on the request side that is associated with this sink.</param> /// <param name="headers">The headers retrieved from the server response stream.</param> /// <param name="stream">The stream coming back from the transport sink.</param> public void AsyncProcessResponse( IClientResponseChannelSinkStack sinkStack, object state, ITransportHeaders headers, Stream stream) { // Get the async state we put on the stack AsyncProcessingState asyncState = (AsyncProcessingState)state; try { // Decrypt the response if possible SecureTransaction transactType = (SecureTransaction)Convert.ToInt32((string)headers[CommonHeaders.Transaction]); switch (transactType) { // The only valid value; the server is sending results encrypted, // so we need to decrypt them case SecureTransaction.SendingEncryptedResult: lock (_transactionLock) { if (asyncState.ID.Equals(_transactID)) { stream = DecryptResponse(stream, headers); } else { throw new SecureRemotingException("The key has changed since the message was decrypted."); } } break; // The server has no record of the client, so error out. // If this were synchronous, we could try again, first renewing // the connection information. The best we can do here is null // out our current connection information so that the next time // through we'll create a new provider and identifier. case SecureTransaction.UnknownIdentifier: throw new SecureRemotingException( "The server sink was unable to identify the client, " + "most likely due to the connection information timing out."); // Something happened and the response is not encrypted, i.e. there // are no transport headers, or at least no transaction header, or it has // been explicitly set by the server to Uninitialized. // Regardless, do nothing. default: case SecureTransaction.Uninitialized: break; } } catch (SecureRemotingException) { // We got back a secure remoting exceptionIt would be difficult to retry this as an // asynchronous call as we need to have the output ready to go before // we return. Thus, we'll make a synchronous one by calling ProcessMessage() // just as if we were the previous sink. Luckily, we kept all of the // necessary information sitting around. lock (_transactionLock) // This is a big, big lock, as are many locks in this app! Oh well. { if (_provider == null || asyncState.ID.Equals(_transactID)) { ClearSharedKey(); } ProcessMessage( asyncState.Message, asyncState.Headers, asyncState.Stream, out headers, out stream); } } finally { // Close the old stream just in case it hasn't been closed yet. asyncState.Stream.Close(); } // Process through the rest of the sinks. sinkStack.AsyncProcessResponse(headers, stream); }