/// <summary> /// Raises the RemoteErrorOccurred event /// </summary> /// <param name="err"></param> protected virtual void onRemoteErrorOccurred(RemoteError err) { if (this.RemoteErrorOccurred != null) { this.RemoteErrorOccurred(this, err); } }
public void TestRemoteErrorSerialization_MissingErrorCodeElement() { var error = new RemoteError(); error.ComponentName = "component"; var xml = error.Serialize(); xml.Element(XName.Get("ErrorCode", xml.Name.NamespaceName)).Remove(); var roundtrip = new RemoteError(); Assert.IsFalse(roundtrip.Validate(xml)); }
public void TestRemoteErrorSerialization_NoCallId() { var error = new RemoteError(); error.ComponentName = "component"; var xml = error.Serialize(); var roundtrip = new RemoteError(); Assert.IsTrue(roundtrip.Validate(xml)); roundtrip.Deserialize(xml); Assert.IsNotNull(roundtrip); Assert.AreEqual<Guid>(error.CallId, roundtrip.CallId); Assert.AreEqual<string>(error.ComponentName, roundtrip.ComponentName); Assert.AreEqual<RemoteErrorCode>(error.ErrorCode, roundtrip.ErrorCode); }
/// <summary> /// Processes an RemoteError /// </summary> /// <param name="error">The RemoteError that is to be processed</param> protected virtual void processRemoteError(RemoteError error) { //if error was caused by synchronous method call, treat it as method response (thread will be blocked indefinitely otherwise) if (error.CallId != null && error.CallId != Guid.Empty && synchronousCalls_WaitHandles.ContainsKey(error.CallId)) { synchonousCalls_ValueCache.Add(error.CallId, error); synchronousCalls_WaitHandles[error.CallId].Set(); //remove original call from unreplied calls, if it exists if (unrepliedCalls.ContainsKey(error.CallId)) { //if response for the call was expected, decrease the number of expected responses to prevent the connection from timing out if (unrepliedCalls[error.CallId].ResponseExpected) { expectedResponseCount--; } unrepliedCalls.Remove(error.CallId); } } //raise the RemoteErrorOccurred event onRemoteErrorOccurred(error); }
/// <summary> /// Initializes a new instance of RemoteErrorException with the specified RemoteError /// </summary> /// <param name="error">The RemoteError that has occured</param> public RemoteErrorException(RemoteError error) { this.Error = error; }
/// <summary> /// Processes an incoming message (using the MessageProcessor for deserialization) /// </summary> /// <param name="message">The message to be processed</param> private void processMessage(ParsingResult message) { //parse the message XElement xmlMessage; RpcMessage msg = null; var body = message.Payload.ToStringUTF8(); try { //try to parse it as XML xmlMessage = XElement.Parse(body); switch (xmlMessage.Name.LocalName.ToLower()) { case "remotemethodcall": msg = new RemoteMethodCall(); break; case "remotemethodresponse": msg = new RemoteMethodResponse(); break; case "remoteerror": msg = new RemoteError(); break; } if (!msg.Validate(xmlMessage)) { logger.Error("Message from {0} could not be validated", this.Target); var error = new RemoteError(RemoteErrorCode.InvalidXmlError); sendMessage(error); return; } msg.Deserialize(xmlMessage); } //Catch XmlException and wrap it into a format exception (makes catching errors in the caller easier) catch (XmlException) { logger.Error("Could not parse message received from {0}", this.Target); RemoteError error = new RemoteError(RemoteErrorCode.InvalidXmlError); sendMessage(error); return; } //encryption is mandatory if TrustLevel is 2 or higher //if message was not encrypted it will result in a RemoteError and the connection will be reset if (this.TrustLevel >= 2 && !message.WasEncrypted && !(msg is RemoteMethodCall && (msg as RemoteMethodCall).MethodName == CoreMethods.SendResetNotice)) { RemoteError error = new RemoteError(RemoteErrorCode.EncryptionError); if (msg.CallId != Guid.Empty) { error.CallId = msg.CallId; } error.ComponentName = "Authentication"; //The RemoteError will not be encrypted WtlpClient.EncryptMessages = false; sendMessage(error); ResetConnection(); return; } if (msg is RemoteMethodCall) { //get the component responsible for handling the message string componentName = (msg as RpcMessage).ComponentName; var component = GetServerComponent(componentName); if (component == null) { //no component to handle the request was found => send a RemoteError as response and return RemoteError error = new RemoteError(RemoteErrorCode.ComponentNotFoundError); error.CallId = (msg as RemoteMethodCall).CallId; sendMessage(error); return; } var processingTask = new Task(delegate { processRemoteMethodCall(msg as RemoteMethodCall, component); }); processingTask.Start(); var heartBeatTask = new Task(delegate { var coreComponent = new CoreClientComponent(); coreComponent.ClientConnection = this; while (!processingTask.IsCompleted) { Thread.Sleep(25000); if (!processingTask.IsCompleted) { coreComponent.HeartbeatAsync(); } } }); heartBeatTask.Start(); } else if (msg is RemoteMethodResponse) { processRemoteMethodResponse(msg as RemoteMethodResponse); } else if (msg is RemoteError) { processRemoteError(msg as RemoteError); } else { logger.Error("ProcessMessage() encoutered an unknown type of Message"); sendMessage(new RemoteError(RemoteErrorCode.UnknownMessage)); } }
/// <summary> /// Processes an incoming message (using the MessageProcessor for deserialization) /// </summary> /// <param name="message">The message to be processed</param> private void processMessage(ParsingResult message) { //parse the message XElement xmlMessage; RpcMessage msg = null; var body = message.Payload.ToStringUTF8(); try { //try to parse it as XML xmlMessage = XElement.Parse(body); switch (xmlMessage.Name.LocalName.ToLower()) { case "remotemethodcall": msg = new RemoteMethodCall(); break; case "remotemethodresponse": msg = new RemoteMethodResponse(); break; case "remoteerror": msg = new RemoteError(); break; } if (!msg.Validate(xmlMessage)) { logger.Error("Message from {0} could not be validated", this.Target); var error = new RemoteError(RemoteErrorCode.InvalidXmlError); sendMessage(error); return; } msg.Deserialize(xmlMessage); } //Catch XmlException and wrap it into a format exception (makes catching errors in the caller easier) catch (XmlException) { logger.Error("Could not parse message received from {0}", this.Target); RemoteError error = new RemoteError(RemoteErrorCode.InvalidXmlError); sendMessage(error); return; } //encryption is mandatory if TrustLevel is 2 or higher //if message was not encrypted it will result in a RemoteError and the connection will be reset if (this.TrustLevel >= 2 && !message.WasEncrypted && !(msg is RemoteMethodCall && (msg as RemoteMethodCall).MethodName == CoreMethods.SendResetNotice)) { RemoteError error = new RemoteError(RemoteErrorCode.EncryptionError); if (msg.CallId != Guid.Empty) error.CallId = msg.CallId; error.ComponentName = "Authentication"; //The RemoteError will not be encrypted WtlpClient.EncryptMessages = false; sendMessage(error); ResetConnection(); return; } if (msg is RemoteMethodCall) { //get the component responsible for handling the message string componentName = (msg as RpcMessage).ComponentName; var component = GetServerComponent(componentName); if (component == null) { //no component to handle the request was found => send a RemoteError as response and return RemoteError error = new RemoteError(RemoteErrorCode.ComponentNotFoundError); error.CallId = (msg as RemoteMethodCall).CallId; sendMessage(error); return; } var processingTask = new Task(delegate { processRemoteMethodCall(msg as RemoteMethodCall, component); }); processingTask.Start(); var heartBeatTask = new Task(delegate { var coreComponent = new CoreClientComponent(); coreComponent.ClientConnection = this; while (!processingTask.IsCompleted) { Thread.Sleep(25000); if (!processingTask.IsCompleted) coreComponent.HeartbeatAsync(); } }); heartBeatTask.Start(); } else if (msg is RemoteMethodResponse) { processRemoteMethodResponse(msg as RemoteMethodResponse); } else if (msg is RemoteError) { processRemoteError(msg as RemoteError); } else { logger.Error("ProcessMessage() encoutered an unknown type of Message"); sendMessage(new RemoteError(RemoteErrorCode.UnknownMessage)); } }
/// <summary> /// Processes an RemoteError /// </summary> /// <param name="error">The RemoteError that is to be processed</param> protected virtual void processRemoteError(RemoteError error) { //if error was caused by synchronous method call, treat it as method response (thread will be blocked indefinitely otherwise) if (error.CallId != null && error.CallId != Guid.Empty && synchronousCalls_WaitHandles.ContainsKey(error.CallId)) { synchonousCalls_ValueCache.Add(error.CallId, error); synchronousCalls_WaitHandles[error.CallId].Set(); //remove original call from unreplied calls, if it exists if (unrepliedCalls.ContainsKey(error.CallId)) { //if response for the call was expected, decrease the number of expected responses to prevent the connection from timing out if(unrepliedCalls[error.CallId].ResponseExpected) expectedResponseCount--; unrepliedCalls.Remove(error.CallId); } } //raise the RemoteErrorOccurred event onRemoteErrorOccurred(error); }
/// <summary> /// Raises the RemoteErrorOccurred event /// </summary> /// <param name="err"></param> protected virtual void onRemoteErrorOccurred(RemoteError err) { if (this.RemoteErrorOccurred != null) this.RemoteErrorOccurred(this, err); }
/// <summary> /// Initializes a new instance of RemoteErrorException /// </summary> public RemoteErrorException() { Error = null; }