/// <summary> /// Change default TransportClient behaviour. /// Handle a requestMessage received from local Arbiter and send down the pipe. /// </summary> /// <param name="requestMessage"></param> protected override void OnMessageReceived(TransportMessage message) { TracerHelper.TraceEntry(); if (message.TransportInfo == null) { SystemMonitor.Error("Transport message stack can not be null."); } if (message.TransportInfo == null || message.TransportInfo.TransportInfoCount == 0 || message.TransportInfo.CurrentTransportInfo.Value.ReceiverID == null || message.TransportInfo.CurrentTransportInfo.Value.ReceiverID.HasValue == false || message.TransportInfo.CurrentTransportInfo.Value.ReceiverID.Value.Equals(this.SubscriptionClientID) == false) {// This requestMessage was sent to me, not to one of the clients on the server. SystemMonitor.Error("Error. Send messages to server-client instances."); return; } // We shall now establish the tag defining which will be the client connection receiving the requestMessage (or all). // by default send to all. string tagID = "*"; if (message.IsRequest) {// Request. if (message.TransportInfo.ForwardTransportInfoCount != 0) { if (message.TransportInfo.CurrentForwardTransportInfoAddress.HasValue) {// Has value - take it into account, if no value is present, just use the "*" pop, // and use the rest of the AdditionalForwardTransportSessionStack. tagID = message.TransportInfo.CurrentForwardTransportInfoAddress.Value.SessionTag; } // Pop in both cases - if it is null or it is value. message.TransportInfo.PopForwardTransportInfo(); } } else {// Responce. // Clear the transporting information from the last node to here. message.TransportInfo.PopTransportInfo(); // Now this is the additional marking in the case with the server - the marking of the PipeChannel. SystemMonitor.CheckError(message.TransportInfo.TransportInfoCount > 0 && message.TransportInfo.CurrentTransportInfo.Value.SenderID.Value.Id.Name == "PipeChannelID"); // Responce requestMessage, read and pop out the channel ID entry . tagID = message.TransportInfo.PopTransportInfo().Value.SenderID.Value.SessionTag; } MessageContainer container = new MessageContainer(message); TracerHelper.Trace("[" + message.GetType().Name + "], tag [" + tagID + "] length [" + container.MessageStreamLength + "]"); GeneralHelper.FireAndForget(delegate() { _transportServer.SendMessageContainer(tagID, container); }); }
/// <summary> /// Message received from the "Pipe". /// </summary> void _transport_MessageReceivedEvent(string operationContextSessionID, MessageContainer messageContainer) { TransportMessage message = (TransportMessage)messageContainer.CreateMessageInstance(); TracerHelper.Trace("[" + message.GetType().Name + "], length [" + messageContainer.MessageStreamLength + "]"); if (message.IsRequest) { // Request requestMessage. { // Mark the request requestMessage with additional fragment in the transportation stack. ArbiterClientId senderID = new ArbiterClientId("PipeChannelID", null, null); senderID.SessionTag = operationContextSessionID; message.TransportInfo.AddTransportInfoUnit(new TransportInfoUnit(Guid.NewGuid(), senderID, this.SubscriptionClientID)); } if (MandatoryRequestMessageReceiverID.HasValue) {// There is a default receiver assigned for all messages from this integrator. DoSendCustom(true, Guid.NewGuid(), null, 0, MandatoryRequestMessageReceiverID.Value, this.SubscriptionClientID, message, TimeSpan.Zero); } else {// No explicit mandatory receiver. if (message.TransportInfo.ForwardTransportInfoCount > 0) { // First pop the Session stack, than send the cleared requestMessage. ArbiterClientId?receiverID = message.TransportInfo.PopForwardTransportInfo(); DoSendCustom(true, Guid.NewGuid(), null, 0, receiverID, this.SubscriptionClientID, message, TimeSpan.Zero); } else { DoSendCustom(true, Guid.NewGuid(), null, 0, null, this.SubscriptionClientID, message, TimeSpan.Zero); } } } else {// Responce requestMessage - send back to whoever sent it to us before. // And clear off the initial request information, we are responding now to. Guid sessionID = message.TransportInfo.CurrentTransportInfo.Value.Id; ArbiterClientId?receiverID = message.TransportInfo.CurrentTransportInfo.Value.SenderID; message.TransportInfo.PopTransportInfo(); this.DoSendCustom(false, sessionID, null, 0, receiverID, this.SubscriptionClientID, message, TimeSpan.Zero); } }
/// <summary> /// Change default TransportClient behaviour. /// Handle a requestMessage received from local Arbiter and send down the pipe. /// </summary> /// <param name="requestMessage"></param> protected override void OnMessageReceived(TransportMessage message) { if (message.IsRequest == false) {// Responce requestMessage. // Clear off the transporting information from the last node to here. message.TransportInfo.PopTransportInfo(); } MessageContainer container = new MessageContainer(message); TracerHelper.Trace("[" + message.GetType().Name + "], length [" + container.MessageStreamLength + "]"); if (_transportClient != null) { _transportClient.SendMessageContainer(container); } else { SystemMonitor.OperationError("Message received after Integration Client uninitialized [" + message.GetType().Name + "].", TracerItem.PriorityEnum.Medium); } }
/// <summary> /// Handle a request message. /// </summary> protected virtual void HandleRequestMessage(TransportMessage message) { FastInvokeHelper.FastInvokeHandlerDelegate handler = GetMessageHandler(message); if (handler == null) {// We failed to find a handler for this type or for any of the parent ones. TracerHelper.TraceError("Client instance did not handle a request message received, client [" + this.GetType().Name + "], message [" + message.GetType().Name + "]."); return; } // Before giving the requestMessage to the user class, make a copy of its transport info // so that if the user messes it up, we still can deliver the responce properly. TransportInfo requestMessageTransportInfo = message.TransportInfo.Clone(); TransportMessage responseMessage = (TransportMessage)handler(this, new object[] { message }); if (responseMessage == null) {// No result. return; } if (responseMessage is ResponseMessage) { ((ResponseMessage)responseMessage).RequestMessageTypeName = message.GetType().Name; } Guid sessionGuid = requestMessageTransportInfo.CurrentTransportInfo.Value.Id; ArbiterClientId?senderID = requestMessageTransportInfo.CurrentTransportInfo.Value.SenderID; requestMessageTransportInfo.PopTransportInfo(); // Transfer inherited underlaying transport stack. responseMessage.TransportInfo = requestMessageTransportInfo; // Send the responce requestMessage back. DoSendCustom(false, sessionGuid, null, 0, senderID, this.SubscriptionClientID, responseMessage, TimeSpan.Zero); }
/// <summary> /// /// </summary> protected virtual void HandleResponseMessage(TransportMessage message) { SessionResults respondedSession = null; // First - check if this is a responce to a currently pending session. lock (_communicationSessions) { string requestMessageInfo = string.Empty; if (message is ResponseMessage) { requestMessageInfo = ((ResponseMessage)message).RequestMessageTypeName; } if (_communicationSessions.ContainsKey(message.TransportInfo.CurrentTransportInfo.Value.Id) == false) { TracerHelper.TraceError("Response received to a session that is not pending [from " + message.TransportInfo.OriginalSenderId.Value.Id.Print() + " to " + this.SubscriptionClientID.Id.Print() + "]. Message [" + message.GetType().Name + " responding to " + requestMessageInfo + "] dumped."); return; } respondedSession = _communicationSessions[message.TransportInfo.CurrentTransportInfo.Value.Id]; } // Clear off the sessioning Transport Info that just brough it back as well. message.TransportInfo.PopTransportInfo(); respondedSession.ReceiveResponse(message); }
/// <summary> /// Central sending function. /// </summary> /// <param name="receiverID">The ID of the receiver module. Can be <b>null</b> and this sends to all in the Arbiter.</param> protected TransportMessage[] DoSendCustom(bool isRequest, Guid sessionGuid, Type expectedResponseMessageClassType, int responsesRequired, ArbiterClientId?receiverId, ArbiterClientId?senderId, TransportMessage message, TimeSpan timeOut) { //TracerHelper.TraceEntry(); SessionResults session = null; if (receiverId.HasValue && receiverId.Value.IsEmpty /*receiverId.Value.CompareTo(ArbiterClientId.Empty) == 0*/) { SystemMonitor.Error("Can not send an item to empty receiver. Use null to specify broadcast."); return(null); } // Preliminary verification. if (Arbiter == null) { SystemMonitor.OperationWarning("Using a client [" + this.GetType().Name + ":" + senderId.Value.ClientName + " to " + (receiverId.HasValue ? receiverId.Value.Id.Name : string.Empty) + " , " + message.GetType().Name + "] with no Arbiter assigned."); return(null); } message.IsRequest = isRequest; TransportInfoUnit infoUnit = new TransportInfoUnit(sessionGuid, senderId, receiverId); message.TransportInfo.AddTransportInfoUnit(infoUnit); bool sessionEventResult = false; if (expectedResponseMessageClassType != null) {// Responce waiting session. session = new SessionResults(responsesRequired, expectedResponseMessageClassType); lock (_communicationSessions) {// Register the session. _communicationSessions.Add(sessionGuid, session); } } SystemMonitor.CheckError(message.TransportInfo.CurrentTransportInfo != null); Conversation conversation; if (receiverId == null) { // We shall not use the next level time out mechanism. conversation = Arbiter.CreateConversation(senderId.Value, message, TimeSpan.Zero); } else {// Addressed conversation. // We shall not use the next level time out mechanism. conversation = Arbiter.CreateConversation(senderId.Value, receiverId.Value, message, TimeSpan.Zero); } if (conversation != null && expectedResponseMessageClassType != null) { // Responce waiting session (only if conversation was properly created). if (timeOut == TimeSpan.Zero) { // Wait forever. sessionEventResult = session.SessionEndEvent.WaitOne(); } else {// Wait given period. sessionEventResult = session.SessionEndEvent.WaitOne(timeOut, false); } lock (_communicationSessions) {// Remote the session. _communicationSessions.Remove(sessionGuid); } } message.TransportInfo.PopTransportInfo(); if (expectedResponseMessageClassType == null) {// No responce waiting, just return. //TracerHelper.TraceExit(); return(null); } // Responce waiting session. if (sessionEventResult == false) {// Timed out - only send and receives can time out, as the other ones do not have sessions!! TracerHelper.TraceError("Session has timed out [" + message.GetType().Name + "]."); return(null); } //TracerHelper.TraceExit(); return(session.Responses.ToArray()); }
//public int RequestAllOrders() //{ // //try // //{ // // lock (this) // // { // // for (int i = 0; i < _pendingMessages.Count; i++) // // { // // if (_pendingMessages[i] is GetAllOrdersMessage) // // { // // TracerHelper.Trace(_sessionInformation.Info.Name); // // int result = ((GetAllOrdersMessage)_pendingMessages[i]).OperationID; // // System.Diagnostics.Debug.Assert(result != 0); // // _pendingMessages.RemoveAt(i); // // return result; // // } // // } // // } // //} // //catch (Exception ex) // //{// Make sure we handle any possible unexpected exceptions, as otherwise they bring the // // // entire package (MT4 included) down with a bad error. // // SystemMonitor.Error(ex.Message); // //} // return 0; //} protected void SendToSubscribers(TransportMessage message) { TracerHelper.TraceEntry(message.GetType().Name + " to " + _subscribers.Count + " subscribers"); lock (this) { foreach (KeyValuePair<ArbiterClientId, TransportInfo> pair in _subscribers) { SendResponding(pair.Value, message); } } }
/// <summary> /// /// </summary> /// <param name="message"></param> void SendToSubscriber(TransportMessage message) { TracerHelper.TraceEntry(message.GetType().Name); lock (this) { if (_subscriberTransportMessageInfo != null) { this.SendResponding(_subscriberTransportMessageInfo, message); } } TracerHelper.TraceExit(); }