/// <summary> /// The thread main of the message reading and processing thread. /// </summary> private void MessageReader() { try { object messageEnvelope = null; while ((messageEnvelope = _messageObjectStream.Read()) != null) { MessageBase message = GetMessageFromEnvelope(messageEnvelope); if (message == null) { this.Error("Received unexpected message envelope of type '{0}' -> ignore it.", messageEnvelope.GetType().Name); continue; } if (message.GetType().Name == "KeepAliveRequest") { var response = new KeepAliveResponseEnvelope() { KeepAliveResponse = new KeepAliveResponse() { Id = message.Id, Source = message.Destination, Destination = message.Source } }; _messageObjectStream.Write(response); continue; } lock (_activeInterceptors) { foreach (var interceptor in _activeInterceptors) { if (interceptor.InterceptMessage(message)) { message = null; break; } } } if ((message != null) && (this.MessageArrived != null)) { this.Trace( "MessageArrived event is raised: a new message arrived that is not handled by any pending message interceptors."); this.MessageArrived(this, new MessageArrivedArgs() { Message = message }); } } } catch (Exception ex) { this.Error("Reading and dispatching messages failed!", ex); } finally { lock (_activeInterceptors) { foreach (var interceptor in _activeInterceptors) { interceptor.Cancel(); } } _threadDownEvent.Set(); } try { if (this.MessageStreamDown != null) { this.MessageStreamDown(this, null); } } catch (Exception ex) { this.Error("Throwing final message stream down event failed!", ex); } }
/// <summary> /// Processes the WWKS 2.0 protocol handshake to initialize the connection to the digital shelf. /// </summary> private bool ProcessHandshake() { HelloRequestEnvelope request = new HelloRequestEnvelope() { HelloRequest = new HelloRequest() { Id = MessageId.Next, //TODO: Don't use static message id generator but create instance. Subscriber = new Subscriber() { Id = SubscriberID, Type = SubscriberType.IMS, Manufacturer = "CareFusion Germany 326 GmbH", ProductInfo = "StorageSystem Library", VersionInfo = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion, Capability = Capabilities } } }; if (_messageObjectStream.Write(request) == false) { this.Error("Sending the initial 'HelloRequest' message failed!"); return(false); } object response = _messageObjectStream.Read(HandshakeTimeout); if (response == null) { this.Error("Waiting for the message 'HelloResponse' failed."); return(false); } if (response.GetType() != typeof(HelloResponseEnvelope)) { this.Error("Received unexpected message of type '{0}'.", response.GetType().Name); return(false); } HelloResponseEnvelope resp = (HelloResponseEnvelope)response; if (resp.HelloResponse.Subscriber == null) { this.Error("Received a 'HelloResponse' message with invalid subscriber information."); return(false); } if (resp.HelloResponse.Id != request.HelloRequest.Id) { this.Error("Received a 'HelloResponse' message with invalid message identifier."); return(false); } _destinationCapabilities = resp.HelloResponse.Subscriber.Capability; this.Info("WWKS 2.0 protocol handshake successfully finished -> ID='{0}' Type='{1}' " + "Manufacturer='{2}' ProductInfo='{3}' VersionInfo='{4}'.", resp.HelloResponse.Subscriber.Id, resp.HelloResponse.Subscriber.Type.ToString(), string.IsNullOrEmpty(resp.HelloResponse.Subscriber.Manufacturer) ? string.Empty : resp.HelloResponse.Subscriber.Manufacturer, string.IsNullOrEmpty(resp.HelloResponse.Subscriber.ProductInfo) ? string.Empty : resp.HelloResponse.Subscriber.ProductInfo, string.IsNullOrEmpty(resp.HelloResponse.Subscriber.VersionInfo) ? string.Empty : resp.HelloResponse.Subscriber.VersionInfo); _destinationId = resp.HelloResponse.Subscriber.Id; return(true); }
/// <summary> /// Reads the next Mosaic message from the underlying connection and returns it. This method will block until a new Mosaic message /// has been read, the converter stream has been cancelled or an error occurred. /// </summary> /// <returns> /// Read Mosaic message if successful; <c>null</c> otherwise. /// </returns> public MosaicMessage Read() { while (true) { IMessageConversion message = null; while (message == null) { object readMessage = _objectStream.Read(); if (readMessage == null) { return(null); } if (readMessage.GetType() == typeof(KeepAliveRequestEnvelope)) { var request = (KeepAliveRequestEnvelope)readMessage; var response = new KeepAliveResponseEnvelope() { KeepAliveResponse = new KeepAliveResponse() { Id = request.KeepAliveRequest.Id, Source = _configuration.SubscriberID, Destination = request.KeepAliveRequest.Source } }; if (_objectStream.Write(response) == false) { this.Error("Sending keep alive response with ID '{0}' failed.", request.KeepAliveRequest.Id); return(null); } continue; } if (readMessage.GetType() == typeof(KeepAliveResponseEnvelope)) { var response = (KeepAliveResponseEnvelope)readMessage; if (TypeConverter.ConvertInt(response.KeepAliveResponse.Id) == _keepAliveID) { System.Threading.Interlocked.Exchange(ref _lastKeepAlive, 0); continue; } this.Error("Received orphan keep alive response with ID '{0}' but expected ID '{1}'.", response.KeepAliveResponse.Id, _keepAliveID); return(null); } message = readMessage as IMessageConversion; if (message == null) { this.Error("Ignored unsupported message of type '{0}'.", readMessage.GetType().FullName); continue; } } var mosaicMessage = message.ToMosaicMessage(this); if (mosaicMessage != null) { mosaicMessage.TenantID = _tenantID; } return(mosaicMessage); } }