Beispiel #1
0
        /// <summary>
        /// The Shutdown method is invoked to instruct the module
        /// to terminate the connection to the peer system. If the
        /// graceful flag is set to true, then the module will wait
        /// until all pending I/O operations are completed before
        /// </summary>
        /// <param name="graceful"></param>
        public void Shutdown(bool graceful)
        {
            if (_moduleState == ModuleStates.Module_State_Active)
            {
                _moduleState = ModuleStates.Module_State_Closing;

                if (graceful == false)
                {
                    // REC: Remove all pending send operations
                    // from the queue and return their buffers
                    // to the buffer pool:
                    lock (_synchTxContextQueue)
                    {
                        while (_txContextQueue.Count > 0)
                        {
                            IoContext txContext = _txContextQueue.Dequeue();
                            txContext._ipcBuffer.RdIndex = 0;
                            txContext._ipcBuffer.WrIndex = 0;

                            lock (_synchIoContextQueue)
                            {
                                _ioContextQueue.Enqueue(txContext);
                            }
                        }
                    }

                    // REC: Close the socket that is being
                    // used to send data to the client:
                    _socket.Close();
                }
                else
                {
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// The Activate method is invoked to instruct the IPC module
        /// to start asynchronously processing IO.
        /// </summary>
        public void Activate()
        {
            if (_moduleState == ModuleStates.Module_State_Shutdown)
            {
                _moduleState = ModuleStates.Module_State_Active;

                // REC: Disable the Nagle algorithm:
                _socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);

                // REC: Dispatch the Event_Opened event to the
                // module's owner:
                EventHandler <VfxIpcEventArgs> tmp = EventDispatch;
                if (tmp != null)
                {
                    tmp(this, new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Opened));
                }

                // REC: Initiate the first receive operation against the
                // socket associated with the module. As receive operations
                // complete, the completion handler will take care of all the
                // subsequent IO context generation / management:
                IoContext rxContext = new IoContext(_socket, new VfxMsgBlock(8192));
                InitiateRecv(rxContext);
            }
        }
Beispiel #3
0
 /// <summary>
 /// The InitiateSend method starts an asynchronous send
 /// operation using the supplied IO context. If there is
 /// already a send operation in progress, the IO context
 /// will be enqueued to the pending IO queue and will be
 /// sent when the current operation completes.
 /// </summary>
 /// <param name="ctx">
 /// The IO context that contains the buffer to be sent.
 /// </param>
 /// <param name="internalSend">
 /// Flag that indicates whether or not the send operation
 /// is being initiated from internal or external code.
 /// </param>
 private void InitiateSend(IoContext ctx, bool internalSend)
 {
     if (internalSend == true)
     {
         ctx._ipcSocket.BeginSend(ctx._ipcBuffer.Buffer, ctx._ipcBuffer.RdIndex,
                                  ctx._ipcBuffer.Length(), 0, CompleteSend, ctx);
     }
     else
     {
         //lock (_txContextQueue)
         lock (_synchTxContextQueue)
         {
             if (_txPending == false)
             {
                 // REC: The pending flag gets set so that the
                 // next call to InitiateSend can determine if
                 // it can send or needs to queue the request:
                 _txPending = true;
                 ctx._ipcSocket.BeginSend(ctx._ipcBuffer.Buffer, ctx._ipcBuffer.RdIndex,
                                          ctx._ipcBuffer.Length(), 0, CompleteSend, ctx);
             }
             else
             {
                 // REC: If a send is already pending, then the
                 // request is queued for the completion handler
                 // to pick up when the current send is done:
                 _txContextQueue.Enqueue(ctx);
             }
         }
     }
 }
Beispiel #4
0
        /// <summary>
        /// The acceptor's activate method is called to start
        /// accepting incoming connections. The acceptor initiates
        /// an asynchronous accept operation, which is then handled
        /// in the OnAccept method when a connection is established.
        /// </summary>
        /// <param name="ipcEndPoint">
        /// The IP endpoint that the acceptor is to accept incoming
        /// connections on.
        /// </param>
        /// <param name="factory">
        /// The session factory that the acceptor is to use when
        /// creating new sessions to handle the incoming connections.
        /// </param>
        public void Activate(IPEndPoint ipcEndPoint, IVfxIpcSessionFactory factory)
        {
            Socket    ipcSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
            IoContext context   = new IoContext(ipcSocket, ipcEndPoint);

            _mapEndpoints.Add(ipcEndPoint, context);
            _mapFactories.Add(ipcEndPoint, factory);

            context.IpcSocket.Bind(context.IpcEndPoint);
            context.IpcSocket.Listen(100);
            context.IpcSocket.BeginAccept(CompleteAccept, context);
        }
Beispiel #5
0
        /// <summary>
        /// The HandleTx method is invoked to request that an instance
        /// of the VfxTcpModule send the data in the specified message
        /// block out to the peer system it is connected to.
        /// </summary>
        /// <param name="mb">
        /// The message block that contains the data that is to be sent
        /// to the peer system the module is connected to.
        /// </param>
        public void HandleTx(VfxMsgBlock mb)
        {
            if (_moduleState == ModuleStates.Module_State_Active)
            {
                // REC: Send all of the data in the buffer:
                while (mb.Length() > 0)
                {
                    IoContext ctx = null;
                    lock (_synchIoContextQueue)
                    {
                        if (_ioContextQueue.Count > 0)
                        {
                            ctx = _ioContextQueue.Dequeue();
                        }
                    }

                    if (ctx != null)
                    {
                        if (ctx._ipcBuffer.Remaining() >= mb.Length())
                        {
                            // REC: Append the contents of the buffer
                            // to the IO context's buffer and push it
                            // onto the outgoing queue:
                            ctx._ipcBuffer.UnsafeAppend(mb);
                            mb.RdIndex = mb.WrIndex;

                            InitiateSend(ctx, false);
                        }
                        else
                        {
                            // REC: Copy as much data as possible into
                            // the context and attempt to send that:
                            int txLength = ctx._ipcBuffer.Remaining();
                            ctx._ipcBuffer.UnsafeAppend(mb, txLength);

                            // REC: Adjust the source buffer's index:
                            mb.RdIndex += txLength;

                            InitiateSend(ctx, false);
                        }
                    }
                    else
                    {
                        // REC: Wait for a buffer to become available:
                        _eventTxBuffer.WaitOne();
                    }
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// The Shutdown method is invoked to request that the
        /// acceptor shutdown a specific endpoint. The acceptor
        /// will respond to this method being invoked by shutting
        /// down the specified endpoint so that connections are no
        /// longer accepted on it.
        /// </summary>
        /// <param name="ipcEndPoint">
        /// The endpoint that is to be shutdown.
        /// </param>
        public void Shutdown(IPEndPoint ipcEndPoint)
        {
            if (_mapEndpoints.ContainsKey(ipcEndPoint))
            {
                IoContext context = _mapEndpoints[ipcEndPoint];
                context.IpcSocket.Close();

                _mapEndpoints.Remove(ipcEndPoint);
            }

            if (_mapFactories.ContainsKey(ipcEndPoint))
            {
                _mapFactories.Remove(ipcEndPoint);
            }
        }
Beispiel #7
0
        private void CompleteAccept(IAsyncResult ar)
        {
            IoContext context = ar.AsyncState as IoContext;

            if (context != null)
            {
                try
                {
                    Socket peer = context.IpcSocket.EndAccept(ar);

                    // REC: Locate the factory associated with this endpoint
                    // and create the appropriate type of session instance:
                    if (_mapFactories.ContainsKey(context.IpcEndPoint))
                    {
                        IPEndPoint peerEP = peer.RemoteEndPoint as IPEndPoint;
                        if (ValidatePeer(peerEP))
                        {
                            VfxTcpModule tcpModule = new VfxTcpModule();
                            tcpModule.Init(peer, this.RxBuffering);

                            // REC: Create a new instance of the session handler that
                            // is configured for the endpoint and associated the
                            // client IO stream with it:
                            IVfxIpcSession session = _mapFactories[context.IpcEndPoint].CreateSession();
                            session.Init(tcpModule);
                        }
                        else
                        {
                            peer.Close();
                        }
                    }

                    // REC: Initiate another asynchronous connection:
                    context.IpcSocket.BeginAccept(CompleteAccept, context);
                }
                catch (System.ObjectDisposedException)
                {
                    // REC: This exception gets thrown when an asynchronous
                    // accept fails due to the socket it was initiated from
                    // being closed. This is part of the shutdown procedure
                    // and should just be caught and ignored.
                }
            }
        }
Beispiel #8
0
        /// <summary>
        /// The Init method is called to initialize the IPC module
        /// with an instance of a .NET socket that will be used to
        /// communicate with a peer system.
        /// </summary>
        /// <param name="socket">
        /// The socket that the module will use for communicating
        /// with the peer system.
        /// </param>
        /// <param name="buffered">
        /// The flag that indicates whether or not the module will
        /// offload incoming data onto a separate thread before it
        /// routes those messages up to the module's owner.
        /// </param>
        public void Init(Socket socket, bool buffered = false)
        {
            // REC: Retain a reference to the socket for use
            // with the send and receive operations:
            this._socket = socket;

            // REC: Configure the receive buffering flag:
            this._rxBuffering = buffered;

            // REC: Pre-allocate the transmit contexts that will
            // be used for sending data to the peer system:
            for (int i = 0; i != _maxTxContexts; i++)
            {
                IoContext txContext = new IoContext(socket, new VfxMsgBlock(8192));
                _ioContextQueue.Enqueue(txContext);
            }

            // REC: If the buffered flag is set, then the module will
            // push incoming data onto a separate thread for subsequent
            // processing by the owner of the module.
            if (buffered == true)
            {
                // REC: Allocate an initial bunch of IO contexts that
                // will be used for buffering incoming data. These are
                // going to be reused, so they are allocated up front:
                for (int i = 0; i != _maxRxContexts; i++)
                {
                    IoContext rxContext = new IoContext(socket, new VfxMsgBlock(8192));
                    _rxContextQueue.Enqueue(rxContext);
                }

                // REC: The module starts a secondary thread which will
                // be used to buffer incoming data as it is received from
                // the peer system that the module is communicating with:
                this._rxThread = new Thread(HandleReceive_Entrypoint);
                this._rxThread.Start();
            }
        }
Beispiel #9
0
        /// <summary>
        /// The Activate method is invoked to instruct the IPC module
        /// to start asynchronously processing IO.
        /// </summary>
        public void Activate()
        {
            if (_moduleState == ModuleStates.Module_State_Shutdown)
            {
                _moduleState = ModuleStates.Module_State_Active;

                // REC: Disable the Nagle algorithm:
                _socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);

                // REC: Dispatch the Event_Opened event to the
                // module's owner:
                EventHandler<VfxIpcEventArgs> tmp = EventDispatch;
                if (tmp != null)
                {
                    tmp(this, new VfxIpcEventArgs(VfxIpcEventTypes.Event_Session_Opened));
                }

                // REC: Initiate the first receive operation against the
                // socket associated with the module. As receive operations
                // complete, the completion handler will take care of all the
                // subsequent IO context generation / management:
                IoContext rxContext = new IoContext(_socket, new VfxMsgBlock(8192));
                InitiateRecv(rxContext);
            }
        }
Beispiel #10
0
        /// <summary>
        /// The HandleReceive_Entrypoint method is the entrypoint for
        /// the buffering thread that is started by the module if the
        /// module's owner has enabled incoming IO buffering.
        /// </summary>
        /// <param name="context"></param>
        private void HandleReceive_Entrypoint(object context)
        {
            // REC: The fragment buffer is used when there is residual
            // data remaining from a previously processed buffer. This
            // is allocated at 2x the receive block size, in order for
            // reducing the need to "expand" the fragment buffer when
            // data is left over from a receive operation:
            VfxMsgBlock rxFragment = new VfxMsgBlock(16384);

            while (true)
            {
                // REC: Lock the pending receive queue and check whether or not
                // there are any receive blocks waiting to be processed:
                IoContext rxPending = null;
                lock (this._synchRxPendingQueue)
                {
                    if (this._rxPendingQueue.Count > 0)
                    {
                        rxPending = this._rxPendingQueue.Dequeue();
                    }
                }

                if (rxPending != null)
                {
                    // REC: If there is data in the fragment buffer
                    // then we need to append the data from the incoming
                    // receive context to it:
                    if (rxFragment.Length() > 0)
                    {
                        rxFragment.Append(rxPending._ipcBuffer);

                        // REC: Dispatch from the fragment buffer instead
                        // of from the receive context:
                        EventHandler <VfxIpcEventArgs> tmp = EventDispatch;
                        if (tmp != null)
                        {
                            tmp(this, new VfxIpcEventArgs(rxFragment));
                            rxFragment.Crunch();
                        }

                        // REC: Reset the pointers in the receive context
                        // since its data has been copied to the fragment
                        // buffer for subsequent processing:
                        rxPending._ipcBuffer.RdIndex = rxPending._ipcBuffer.WrIndex = 0;
                    }
                    else
                    {
                        // REC: There is no fragment remaining from the previous
                        // receive operation, so we can just dispatch directly from
                        // the received context:
                        EventHandler <VfxIpcEventArgs> tmp = EventDispatch;
                        if (tmp != null)
                        {
                            tmp(this, new VfxIpcEventArgs(rxPending._ipcBuffer));
                            rxPending._ipcBuffer.Crunch();
                        }

                        // REC: Determine if there is a fragment in the buffer
                        // so that we can chain it to subsequent blocks:
                        if (rxPending._ipcBuffer.Length() > 0)
                        {
                            // REC: There is a fragment of a message remaining
                            // in the current buffer, so it has to be copied into
                            // the fragment buffer for further processing:
                            rxFragment.Append(rxPending._ipcBuffer);

                            // REC: Reset the points in the pending receive context
                            // since it has been copied into the fragment buffer:
                            rxPending._ipcBuffer.RdIndex = 0;
                            rxPending._ipcBuffer.WrIndex = 0;
                        }
                    }

                    // REC: Put the receive context back into the queue so
                    // that it can be used by subsequent receive operations:
                    lock (this._rxContextQueue)
                    {
                        this._rxContextQueue.Enqueue(rxPending);
                    }
                }
                else
                {
                    // REC: A message block wasn't available for us on this
                    // iteration, so just wait until one is added to the queue:
                    this._eventRxBuffer.WaitOne();
                }
            }
        }
Beispiel #11
0
        /// <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);
                    }
                }
            }
        }
Beispiel #12
0
 private void InitiateRecv(IoContext rxContext)
 {
     rxContext._ipcSocket.BeginReceive(rxContext._ipcBuffer.Buffer, rxContext._ipcBuffer.WrIndex,
                                       rxContext._ipcBuffer.Remaining(), 0, CompleteRecv, rxContext);
 }
Beispiel #13
0
        /// <summary>
        /// The CompleteSend event handler is invoked in response to an
        /// asynchronous send operation being completed. The system reacts
        /// to the completion by finalizing the asynchronous operation and
        /// then starting a new one.
        /// </summary>
        /// <param name="ar"></param>
        private void CompleteSend(IAsyncResult ar)
        {
            IoContext ctx = ar.AsyncState as IoContext;

            if (ctx != null)
            {
                int txBytes = ctx._ipcSocket.EndSend(ar);
                if (txBytes > 0)
                {
                    // REC: If the system did not transmit all of the data
                    // that was in the IO context buffer then it initiates
                    // a new send operation against the residual content:
                    if (txBytes < ctx._ipcBuffer.Length())
                    {
                        // REC: Adjust the read index...
                        ctx._ipcBuffer.RdIndex += txBytes;
                        ctx._ipcBuffer.Crunch();

                        // REC: and try to send it again...
                        InitiateSend(ctx, true);
                    }
                    else
                    {
                        lock (_synchIoContextQueue)
                        {
                            // REC: Reset the message block's
                            // read and write indices:
                            ctx._ipcBuffer.RdIndex = 0;
                            ctx._ipcBuffer.WrIndex = 0;

                            // REC: Return the buffer to the
                            // pool so it can be used again:
                            _ioContextQueue.Enqueue(ctx);

                            // REC: If there were no contexts remaining
                            // in the transmit queue when this one was
                            // returned to it, trigger the buffer event
                            // so that HandleTx can acquire one:
                            if (_ioContextQueue.Count == 1)
                            {
                                _eventTxBuffer.Set();
                            }
                        }

                        lock (_synchTxContextQueue)
                        {
                            if (_txContextQueue.Count > 0)
                            {
                                IoContext next = _txContextQueue.Dequeue();
                                InitiateSend(next, true);
                            }
                            else
                            {
                                _txPending = false;

                                // REC: If the module is being shutdown
                                // and there are no further pending sends
                                // left to process, generate the shutdown
                                // event to notify the module's owner:
                                if (_moduleState == ModuleStates.Module_State_Closing)
                                {
                                    _moduleState = ModuleStates.Module_State_Shutdown;
                                    // REC: Close the socket to ensure that the
                                    // disconnect event is triggered:
                                    _socket.Close();
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #14
0
        /// <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);
                    }
                }
            }
        }
Beispiel #15
0
        /// <summary>
        /// The Init method is called to initialize the IPC module
        /// with an instance of a .NET socket that will be used to
        /// communicate with a peer system.
        /// </summary>
        /// <param name="socket">
        /// The socket that the module will use for communicating
        /// with the peer system.
        /// </param>
        /// <param name="buffered">
        /// The flag that indicates whether or not the module will
        /// offload incoming data onto a separate thread before it
        /// routes those messages up to the module's owner.
        /// </param>
        public void Init(Socket socket, bool buffered=false)
        {
            // REC: Retain a reference to the socket for use
            // with the send and receive operations:
            this._socket = socket;

            // REC: Configure the receive buffering flag:
            this._rxBuffering = buffered;

            // REC: Pre-allocate the transmit contexts that will
            // be used for sending data to the peer system:
            for (int i = 0; i != _maxTxContexts; i++)
            {
                IoContext txContext = new IoContext(socket, new VfxMsgBlock(8192));
                _ioContextQueue.Enqueue(txContext);
            }

            // REC: If the buffered flag is set, then the module will
            // push incoming data onto a separate thread for subsequent
            // processing by the owner of the module.
            if (buffered == true)
            {
                // REC: Allocate an initial bunch of IO contexts that
                // will be used for buffering incoming data. These are
                // going to be reused, so they are allocated up front:
                for (int i = 0; i != _maxRxContexts; i++)
                {
                    IoContext rxContext = new IoContext(socket, new VfxMsgBlock(8192));
                    _rxContextQueue.Enqueue(rxContext);
                }

                // REC: The module starts a secondary thread which will
                // be used to buffer incoming data as it is received from
                // the peer system that the module is communicating with:
                this._rxThread = new Thread(HandleReceive_Entrypoint);
                this._rxThread.Start();
            }
        }
Beispiel #16
0
 private void InitiateRecv(IoContext rxContext)
 {
     rxContext._ipcSocket.BeginReceive(rxContext._ipcBuffer.Buffer, rxContext._ipcBuffer.WrIndex,
         rxContext._ipcBuffer.Remaining(), 0, CompleteRecv, rxContext);
 }
Beispiel #17
0
        /// <summary>
        /// The InitiateSend method starts an asynchronous send
        /// operation using the supplied IO context. If there is
        /// already a send operation in progress, the IO context
        /// will be enqueued to the pending IO queue and will be
        /// sent when the current operation completes.
        /// </summary>
        /// <param name="ctx">
        /// The IO context that contains the buffer to be sent.
        /// </param>
        /// <param name="internalSend">
        /// Flag that indicates whether or not the send operation
        /// is being initiated from internal or external code.
        /// </param>
        private void InitiateSend(IoContext ctx, bool internalSend)
        {
            if (internalSend == true)
            {
                ctx._ipcSocket.BeginSend(ctx._ipcBuffer.Buffer, ctx._ipcBuffer.RdIndex,
                            ctx._ipcBuffer.Length(), 0, CompleteSend, ctx);
            }
            else
            {
                //lock (_txContextQueue)
                lock(_synchTxContextQueue)
                {
                    if (_txPending == false)
                    {
                        // REC: The pending flag gets set so that the
                        // next call to InitiateSend can determine if
                        // it can send or needs to queue the request:
                        _txPending = true;
                        ctx._ipcSocket.BeginSend(ctx._ipcBuffer.Buffer, ctx._ipcBuffer.RdIndex,
                            ctx._ipcBuffer.Length(), 0, CompleteSend, ctx);

                    }
                    else
                    {
                        // REC: If a send is already pending, then the
                        // request is queued for the completion handler
                        // to pick up when the current send is done:
                        _txContextQueue.Enqueue(ctx);
                    }
                }
            }
        }