/// <summary> /// The HandleIpcDispatch_EventOpened event handler is invoked in /// response to a new session being established between a peer /// system and the endpoint associated with the service. /// </summary> /// <param name="sender"> /// The IPC endpoint that dispatched the event. /// </param> /// <param name="args"> /// The details of the event being dispatched. /// </param> private void HandleIpcDispatch_EventOpened(object sender, VfxIpcEventArgs args) { // REC: Create a new instance of a FIX session to handle // the communication between the server and the peer: IVfxFixSession fixSession = null; // REC: Retrieve the version definition from the version // definition registry and determine what kind of session // needs to be created in order to handle the connection: IVfxFixVxRegistry vxRegistry = this._localServices.GetService(typeof(IVfxFixVxRegistry)) as IVfxFixVxRegistry; // REC: Check the version definition in order to tell if // this is a FIX 4.x or FIX 5.x service: VfxFixVxRecord vxRecord = vxRegistry.Get(this._sxVersion); if (vxRecord.Layer.ToLower().CompareTo("combined") == 0) { fixSession = new VfxFix4xServerSession(); } else { fixSession = new VfxFix5xServerSession(); } // REC: Initialize the session: fixSession.Init(_localServices, this); // REC: Create an entry for the session in the // local session map: _mapFixSessions.Add(fixSession.InstanceId, fixSession); // REC: Bind the FIX session to the IPC session: _mapFixToIpc.Add(fixSession.InstanceId, args.Token); // REC: Bind the IPC session to the FIX session: _mapIpcToFix.Add(args.Token, fixSession.InstanceId); // REC: Create the application session container // that will be passed to the app implementation // when events are generated on the session: VfxFixServerSession appSession = new VfxFixServerSession(fixSession); // REC: Create a binding between the FIX session // and the application session so that events from // the FIX session can be correlated to the correct // application session when events are dispatched to // the user's FIX application instance: _mapAppSessions.Add(fixSession.InstanceId, appSession); // REC: Inform the session that a peer system // has been connected to it: fixSession.HandleConnect(); }
/// <summary> /// The HandleDispatch event handler is invoked in response /// to an IPC event being dispatched to the session by the /// session's associated IPC module. The session assigns its /// unique identifier to the event and then forwards the event /// up to the server endpoint that owns the session. /// </summary> /// <param name="sender"> /// The IPC module that is dispatching the event. /// </param> /// <param name="args"> /// The details of the event being dispatched. /// </param> private void HandleDispatch(object sender, VfxIpcEventArgs args) { args.Token = _instanceGuid.ToString(); EventHandler<VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { tmp(this, args); } }
/// <summary> /// The HandleIpcDispatch_EventClosed event handler is invoked /// when an IPC session disconnects from a peer system. /// </summary> /// <param name="sender"> /// The IPC session that dispatched the event. /// </param> /// <param name="args"> /// The details of the event being dispatched. /// </param> private void HandleIpcDispatch_EventClosed(object sender, VfxIpcEventArgs args) { // REC: Determine if there is currently an instance of // a FIX session associated with the IPC session: if (_mapIpcToFix.ContainsKey(args.Token)) { // REC: Remove the binding between the FIX session // and the IPC session, since the IPC session has been // disconnected and can not be used by the FIX session // for any other operations: if (_mapFixToIpc.ContainsKey(_mapIpcToFix[args.Token])) { _mapFixToIpc.Remove(_mapIpcToFix[args.Token]); } // REC: Notify the associated FIX session that the // connection has been broken: _mapFixSessions[_mapIpcToFix[args.Token]].HandleDisconnect(); } }
private void HandleIpcDispatch_EventMessage(object sender, VfxIpcEventArgs args) { if (_mapIpcToFix.ContainsKey(args.Token)) { _mapFixSessions[_mapIpcToFix[args.Token]].HandleRxMessage(args.EventData); } }
/// <summary> /// The HandleTcpConnector_Success event handler is invoked /// in response to the tcp connector establishing a connection /// to the peer system. /// </summary> /// <param name="sender"> /// The connector that is dispatching the event. /// </param> /// <param name="args"> /// The event details that are associated with the event. /// </param> private void HandleTcpConnector_Success(object sender, VfxTcpConnectorEventArgs args) { // REC: Translate the connector's success notification // into the corresponding IPC event and dispatch it: EventHandler<VfxIpcEventArgs> tmpDispatch = EventDispatch; if (tmpDispatch != null) { VfxIpcEventArgs tmpArgs = new VfxIpcEventArgs(VfxIpcEventTypes.Event_Connect_Success); tmpDispatch(this, tmpArgs); } }
/// <summary> /// The HandleIpcDispatch event handler is invoked in response to /// an IPC session raising an event. The server service examines /// the token/sessionId that is contained in the event arguments /// and uses that information to demultiplex the details of the /// event to the corresponding FIX session. /// </summary> /// <param name="sender"> /// The endpoint session that generated the event. /// </param> /// <param name="args"> /// The details of the event that was generated. /// </param> private void HandleIpcDispatch(object sender, VfxIpcEventArgs args) { switch (args.EventType) { case VfxIpcEventTypes.Event_Session_Opened: HandleIpcDispatch_EventOpened(sender, args); break; case VfxIpcEventTypes.Event_Session_Closed: HandleIpcDispatch_EventClosed(sender, args); break; case VfxIpcEventTypes.Event_Session_Message: HandleIpcDispatch_EventMessage(sender, args); break; default: break; } }
/// <summary> /// The HandleDispatch event handler is invoked in response to /// one of the IPC sessions dispatching an event to the endpoint. /// </summary> /// <param name="sender"> /// The IPC session that is dispatching the event. /// </param> /// <param name="args"> /// The details of the event being dispatched. The Token property /// of the event args instance will be set to the session id of the /// session that generated the event so that subscribers know which /// of the endpoint's sessions the event originated from. /// </param> private void HandleDispatch(object sender, VfxIpcEventArgs args) { EventHandler<VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { tmp(this, args); } }
/// <summary> /// The HandleIpc_Dispatch method is invoked in response /// to the IPC session handler dispatching an IPC event to /// the endpoint. The event is simply forwarded to the owner /// of the endpoint instance for processing. /// </summary> /// <param name="sender"> /// The IPC session that is dispatching the event. /// </param> /// <param name="args"> /// The details of the IPC event being dispatched. /// </param> private void HandleIpc_Dispatch(object sender, VfxIpcEventArgs args) { // REC: The incoming event from the underlying IPC session // is simply forwarded to the endpoint's owner: EventHandler<VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { tmp(this, args); } }
/// <summary> /// The CompleteRecv method is invoked in response to /// an asynchronous receive operation completing. /// </summary> /// <param name="ar"></param> private void CompleteRecv(IAsyncResult ar) { // REC: Retrieve the IO context that is associated with the // original asynchronous receive operation. IoContext rxContext = ar.AsyncState as IoContext; if (rxContext != null) { try { // REC: Get the total number of bytes that were read // from the peer system by this operation: int rxBytes = rxContext._ipcSocket.EndReceive(ar); if (rxBytes > 0) { // REC: Adjust the write index in the message block: rxContext._ipcBuffer.WrIndex = rxContext._ipcBuffer.WrIndex + rxBytes; // REC: Offload the received data onto a separate thread: if (this._rxBuffering == true) { Socket rxSocket = rxContext._ipcSocket; lock (this._synchRxPendingQueue) { // REC: Push the received data onto the queue so that // it can be picked up by the secondary receive thread // for further processing: this._rxPendingQueue.Enqueue(rxContext); // REC: If the queue was empty prior to this context // being added to it, we need to signal the secondary // receive thread so that it can start processing the // data again: if (this._rxPendingQueue.Count == 1) { this._eventRxBuffer.Set(); } } // REC: Attempt to pull another context from the context // queue so that we can receive more data: IoContext rxNext; if (this._rxContextQueue.Count > 0) { rxNext = this._rxContextQueue.Dequeue(); } else { // REC: Note that this is BAD and will result in the // exhaustion of all the system's memory if there is a // continuous problem with the speed at which messages // are being consumed on the receive thread... rxNext = new IoContext(rxSocket, new VfxMsgBlock(8192)); } // REC: Initiate a new receive operation, using the next // available receive context: InitiateRecv(rxNext); } else { // REC: If receive buffering has not been enabled then the // data is dispatched directly to the module's owner: EventHandler <VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { tmp(this, new VfxIpcEventArgs(rxContext._ipcBuffer)); // REC: Adjust the buffer to take into consideration // any data that was read by the module's owner: rxContext._ipcBuffer.Crunch(); // REC: Initiate another receive operation using the // same receive buffer that was just processed: InitiateRecv(rxContext); } } } else { _moduleState = ModuleStates.Module_State_Shutdown; // REC: This might happen as the result of the // user closing the session down. EventHandler <VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { VfxIpcEventArgs dxArgs = new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Closed); tmp(this, dxArgs); } } } catch (SocketException) { _moduleState = ModuleStates.Module_State_Shutdown; // REC: This might happen as the result of the // user closing the session down. EventHandler <VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { VfxIpcEventArgs dxArgs = new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Closed); tmp(this, dxArgs); } } catch (ObjectDisposedException) { _moduleState = ModuleStates.Module_State_Shutdown; // REC: This happens if the socket gets closed // locally rather than being closed by the peer. EventHandler <VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { VfxIpcEventArgs dxArgs = new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Closed); tmp(this, dxArgs); } } } }
/// <summary> /// The HandleIpc_EventOpened method is invoked in response /// to the IPC endpoint establishing a connection to the peer /// system that the service is interacting with. /// </summary> /// <param name="sender"> /// The VfxIpcEndpoint that dispatched the event. /// </param> /// <param name="args"> /// The details associated with the event. /// </param> private void HandleIpc_EventOpened(object sender, VfxIpcEventArgs args) { lock (_synch) { // REC: The IPC session is now established. _ipcEstablished = true; // REC: Adjust the service's current status: _serviceStatus = VfxFixServiceStatus.Service_Status_Opened; // REC: Dispatch the update to the service's subscribers: EventHandler<VfxFixServiceEventArgs> tmpDispatch_Update = EventDispatch; if (tmpDispatch_Update != null) { VfxFixServiceEventArgs tmpArgs = new VfxFixServiceEventArgs(VfxFixServiceEventTypes.Event_Service_Updated, _serviceStatus); tmpDispatch_Update(this, tmpArgs); } // REC: Retrieve the version definition from the version // definition registry and determine what kind of session // needs to be created in order to handle the connection: IVfxFixVxRegistry vxRegistry = this._localServices.GetService(typeof(IVfxFixVxRegistry)) as IVfxFixVxRegistry; // REC: Create a new instance of a FIX session to handle // the communication between the server and the peer: IVfxFixSession fixSession = null; // REC: Check the version definition in order to tell if // this is a FIX 4.x or FIX 5.x service: VfxFixVxRecord vxRecord = vxRegistry.Get(this._sxVersion); if (vxRecord.Layer.ToLower().CompareTo("combined") == 0) { fixSession = new VfxFix4xClientSession(); } else { fixSession = new VfxFix5xClientSession(); } _fixSession = fixSession; // REC: Initialize the session: _fixSession.Init(this._localServices, this); // REC: Construct an instance of the session wrapper // for the FIX application and bind it to the session // implementation that has been created: _appSession = new VfxFixClientSession(_fixSession); // REC: Notify the FIX session implementation that it // has been connected to a peer system: _fixSession.HandleConnect(); } }
/// <summary> /// The HandleIpc_EventMessage event handler is invoked in /// response to the service being notified that the IPC session /// has received some data from the peer system. /// </summary> /// <param name="sender"> /// The IPC session that is dispatching the event. /// </param> /// <param name="args"> /// The details of the IPC event being dispatched. /// </param> private void HandleIpc_EventMessage(object sender, VfxIpcEventArgs args) { lock (_synch) { _fixSession.HandleRxMessage(args.EventData); } }
/// <summary> /// The HandleIpc_EventClosed event handler is invoked in /// response to the service being notified that the session /// has been disconnected from the peer system. /// </summary> /// <param name="sender"> /// The IPC session that is dispatching the event. /// </param> /// <param name="args"> /// The details of the IPC event being dispatched. /// </param> private void HandleIpc_EventClosed(object sender, VfxIpcEventArgs args) { lock (_synch) { // REC: The IPC session is no longer established: _ipcEstablished = false; // REC: Notify the FIX session that the peer system // is no longer connected: _fixSession.HandleDisconnect(); // REC: Adjust the service's current status: _serviceStatus = VfxFixServiceStatus.Service_Status_Disconnected; EventHandler<VfxFixServiceEventArgs> tmpDispatch_Update = EventDispatch; if (tmpDispatch_Update != null) { VfxFixServiceEventArgs tmpArgs = new VfxFixServiceEventArgs(VfxFixServiceEventTypes.Event_Service_Updated, _serviceStatus); tmpDispatch_Update(this, tmpArgs); } // REC: If the service is closing, then the disconnection // of the IPC endpoint is the last thing that needs to be // completed before dispatching the stopped event back up // to the service's owner/subscribers: if (_serviceState == VfxFixServiceStates.Service_State_Closing) { // REC: Adjust the service's current state: _serviceState = VfxFixServiceStates.Service_State_Closed; // REC: Adjust the service's current status: _serviceStatus = VfxFixServiceStatus.Service_Status_Closed; EventHandler<VfxFixServiceEventArgs> tmpDispatch_Stopped = EventDispatch; if (tmpDispatch_Stopped != null) { VfxFixServiceEventArgs tmpArgs = new VfxFixServiceEventArgs(VfxFixServiceEventTypes.Event_Service_Stopped, _serviceStatus); tmpDispatch_Stopped(this, tmpArgs); } } else { // REC: If the service is not configured to reconnect // to the peer system, then it is now stopped: // NOTE: Add reconnect logic here! // REC: Adjust the service's current state: _serviceState = VfxFixServiceStates.Service_State_Closed; // REC: Adjust the service's current status: _serviceStatus = VfxFixServiceStatus.Service_Status_Closed; EventHandler<VfxFixServiceEventArgs> tmpDispatch_Stopped = EventDispatch; if (tmpDispatch_Stopped != null) { VfxFixServiceEventArgs tmpArgs = new VfxFixServiceEventArgs(VfxFixServiceEventTypes.Event_Service_Stopped, _serviceStatus); tmpDispatch_Stopped(this, tmpArgs); } } } }
/// <summary> /// The CompleteRecv method is invoked in response to /// an asynchronous receive operation completing. /// </summary> /// <param name="ar"></param> private void CompleteRecv(IAsyncResult ar) { // REC: Retrieve the IO context that is associated with the // original asynchronous receive operation. IoContext rxContext = ar.AsyncState as IoContext; if (rxContext != null) { try { // REC: Get the total number of bytes that were read // from the peer system by this operation: int rxBytes = rxContext._ipcSocket.EndReceive(ar); if (rxBytes > 0) { // REC: Adjust the write index in the message block: rxContext._ipcBuffer.WrIndex = rxContext._ipcBuffer.WrIndex + rxBytes; // REC: Offload the received data onto a separate thread: if (this._rxBuffering == true) { Socket rxSocket = rxContext._ipcSocket; lock (this._synchRxPendingQueue) { // REC: Push the received data onto the queue so that // it can be picked up by the secondary receive thread // for further processing: this._rxPendingQueue.Enqueue(rxContext); // REC: If the queue was empty prior to this context // being added to it, we need to signal the secondary // receive thread so that it can start processing the // data again: if (this._rxPendingQueue.Count == 1) { this._eventRxBuffer.Set(); } } // REC: Attempt to pull another context from the context // queue so that we can receive more data: IoContext rxNext; if (this._rxContextQueue.Count > 0) { rxNext = this._rxContextQueue.Dequeue(); } else { // REC: Note that this is BAD and will result in the // exhaustion of all the system's memory if there is a // continuous problem with the speed at which messages // are being consumed on the receive thread... rxNext = new IoContext(rxSocket, new VfxMsgBlock(8192)); } // REC: Initiate a new receive operation, using the next // available receive context: InitiateRecv(rxNext); } else { // REC: If receive buffering has not been enabled then the // data is dispatched directly to the module's owner: EventHandler<VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { tmp(this, new VfxIpcEventArgs(rxContext._ipcBuffer)); // REC: Adjust the buffer to take into consideration // any data that was read by the module's owner: rxContext._ipcBuffer.Crunch(); // REC: Initiate another receive operation using the // same receive buffer that was just processed: InitiateRecv(rxContext); } } } else { _moduleState = ModuleStates.Module_State_Shutdown; // REC: This might happen as the result of the // user closing the session down. EventHandler<VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { VfxIpcEventArgs dxArgs = new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Closed); tmp(this, dxArgs); } } } catch (SocketException) { _moduleState = ModuleStates.Module_State_Shutdown; // REC: This might happen as the result of the // user closing the session down. EventHandler<VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { VfxIpcEventArgs dxArgs = new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Closed); tmp(this, dxArgs); } } catch (ObjectDisposedException) { _moduleState = ModuleStates.Module_State_Shutdown; // REC: This happens if the socket gets closed // locally rather than being closed by the peer. EventHandler<VfxIpcEventArgs> tmp = EventDispatch; if (tmp != null) { VfxIpcEventArgs dxArgs = new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Closed); tmp(this, dxArgs); } } } }