Пример #1
0
        /// <summary>
        /// Handles the deserialization of the <see cref="Query" /> and <see cref="Response" />
        /// messages from the blob data.
        /// </summary>
        /// <param name="es">The enhanced stream holding the payload data.</param>
        protected override void ReadFrom(EnhancedStream es)
        {
            // Let the base message class load the properties and the data blob.

            base.ReadFrom(es);

            // Now parse the query and (optional) response messages from the blob

            es = new EnhancedBlockStream(base._Data);

            try
            {
                query = Msg.Load(es);

                if (es.Eof)
                {
                    response = null;
                }
                else
                {
                    response = Msg.Load(es);
                }
            }
            finally
            {
                es.Close();
            }
        }
Пример #2
0
        /// <summary>
        /// Handles message packets received on the socket.
        /// </summary>
        /// <param name="ar">The async result.</param>
        private void OnSocketReceive(IAsyncResult ar)
        {
            int cb;
            Msg msg = null;

            byte[]     msgBuf;
            int        cbMsg;
            IPEndPoint fromEP = NetworkBinding.Any;

            using (TimedLock.Lock(router.SyncRoot))
            {
                if (!isOpen)
                {
                    return;
                }

                try
                {
                    cb = sock.EndReceiveFrom(ar, ref recvEP);
                    if (cb > 0)
                    {
                        msgBuf = router.DecryptFrame(recvBuf, cb, out cbMsg);
                        msg    = Msg.Load(new EnhancedMemoryStream(msgBuf));

                        fromEP = (IPEndPoint)recvEP;
                        msg._SetFromChannel(new ChannelEP(transport, fromEP));
                    }
                }
                catch (MsgException)
                {
                    // Ignore messages that can't be parsed
                }
                catch (Exception e)
                {
                    SysLog.LogException(e);
                }

                // Initiate the receive of the next message

                if (sock.IsOpen)
                {
                    try
                    {
                        sock.BeginReceiveFrom(recvBuf, 0, recvBuf.Length, SocketFlags.None, ref recvEP, onSocketReceive, null);
                    }
                    catch (Exception e)
                    {
                        SysLog.LogException(e, "LillTek UDP message channel is no longer able to receive messages.");
                    }
                }
            }

            if (msg != null)
            {
                msg._Trace(router, 2, "UDP: Recv", string.Format("From: {0}", fromEP));
                msg._Trace(router, 0, "Receive", string.Empty);
                router.OnReceive(this, msg);
            }
        }
Пример #3
0
        /// <summary>
        /// Generates a clone of this message instance, generating a new
        /// <see cref="_MsgID" /> property if the original ID is
        /// not empty.
        /// </summary>
        /// <returns>Returns a clone of the message.</returns>
        /// <remarks>
        /// <para>
        /// This base method works by serializing and then deseralizing a new copy of
        /// the message to a buffer and then generating a new <see cref="_MsgID" /> GUID.  This
        /// implementation will be relatively costly in terms of processor and
        /// memory resources.
        /// </para>
        /// <para>
        /// Derived messages can choose to override this and implement a shallow
        /// clone instead, using the <see cref="CopyBaseFields" /> method.  Note that
        /// the <see cref="CopyBaseFields" /> method ensures that a new <see cref="_MsgID" />
        /// property is regenerated if the original ID field is not empty.
        /// </para>
        /// </remarks>
        public virtual Msg Clone()
        {
            var es = new EnhancedBlockStream(1024, 1024);
            Msg clone;

            Msg.Save(es, this);
            es.Position = 0;
            clone       = Msg.Load(es);

            if (this.msgID != Guid.Empty)
            {
                clone.msgID = Helper.NewGuid();
            }

            return(clone);
        }
Пример #4
0
        /// <summary>
        /// Handles messages received from the UdpBroadcast client.
        /// </summary>
        /// <param name="sender">The UDP broadcast client.</param>
        /// <param name="args">Event arguments.</param>
        private void OnBroadcastReceive(object sender, UdpBroadcastEventArgs args)
        {
            Msg msg = null;

            byte[] msgBuf;
            int    cbMsg;
            int    cb;

            using (TimedLock.Lock(router.SyncRoot))
            {
                if (!isOpen)
                {
                    return;
                }

                try
                {
                    cb = args.Payload.Length;
                    if (cb > 0)
                    {
                        msgBuf = router.DecryptFrame(args.Payload, cb, out cbMsg);
                        msg    = Msg.Load(new EnhancedMemoryStream(msgBuf));

                        msg._SetFromChannel(new ChannelEP(transport, new IPEndPoint(args.SourceAddress, 0)));
                    }
                }
                catch (MsgException)
                {
                    // Ignore messages that can't be parsed
                }
                catch (Exception e)
                {
                    SysLog.LogException(e);
                }
            }

            if (msg != null)
            {
                msg._Trace(router, 2, "UDP: Broadcast Recv", string.Format("From: {0}", args.SourceAddress));
                msg._Trace(router, 0, "Receive", string.Empty);
                router.OnReceive(this, msg);
            }
        }
Пример #5
0
        /// <summary>
        /// Handles receive completions on the socket.
        /// </summary>
        /// <param name="ar">The async result.</param>
        private void OnReceive(IAsyncResult ar)
        {
            int cbRecv;

            try
            {
                using (TimedLock.Lock(router.SyncRoot))
                {
                    if (sock == null || recvBuf == null)
                    {
                        return;
                    }

                    try
                    {
                        cbRecv = sock.EndReceive(ar);
                    }
                    catch (SocketException e2)
                    {
                        if (e2.SocketErrorCode == SocketError.ConnectionReset)
                        {
                            cbRecv = 0;     // Treat connection resets as connection closure
                        }
                        else
                        {
                            throw;
                        }
                    }

                    if (cbRecv == 0)
                    {
                        sock.ShutdownAndClose();
                        return;
                    }

                    SetLastAccess();

                    recvPos += cbRecv;
                    if (recvPos < recvBuf.Length)
                    {
                        // Continue the reception

                        sock.BeginReceive(recvBuf, recvPos, recvBuf.Length - recvPos, SocketFlags.None, onReceive, null);
                        return;
                    }

                    if (recvHeader)
                    {
                        // Initiate reception of the frame payload

                        int    pos = 0;
                        int    cbFrame;
                        byte[] buf;

                        cbFrame = Helper.ReadInt32(recvBuf, ref pos);
                        buf     = new byte[MsgRouter.FrameHeaderSize + cbFrame];
                        Array.Copy(recvBuf, 0, buf, 0, MsgRouter.FrameHeaderSize);

                        recvHeader = false;
                        recvBuf    = buf;
                        recvPos    = MsgRouter.FrameHeaderSize;
                        cbRecv     = cbFrame;

                        sock.BeginReceive(recvBuf, recvPos, cbFrame, SocketFlags.None, onReceive, null);
                    }
                    else
                    {
                        // We've completed the reception of a message

                        Msg    msg;
                        byte[] msgBuf;
                        int    cbMsg;

                        msgBuf = router.DecryptFrame(recvBuf, recvBuf.Length, out cbMsg);
                        msg    = Msg.Load(new EnhancedMemoryStream(msgBuf));
                        msgBuf = null;

                        // Handle initialization messages locally and queue a
                        // notification for all other messages so that router.OnReceive()
                        // will be called on a worker thread.

                        if (!initProcessed)
                        {
                            TcpInitMsg initMsg;
                            Exception  e;

                            initMsg = msg as TcpInitMsg;
                            if (initMsg == null)
                            {
                                e = new MsgException("Invalid TCP channel protocol: TcpInitMsg expected.");
                                SysLog.LogException(e);
                                Helper.Rethrow(e);
                            }

                            initMsg._Trace(router, 2, "Receive", null);

                            // If the sender indicates that it is an uplink then we're going
                            // to use the actual remote port for the remoteEP rather than
                            // ListenPort (which should be 0).  The reason for this is that
                            // intervening routers and NATs may translate the port number
                            // reported by the child router.

                            routerEP            = initMsg.RouterEP;
                            remoteEP.NetEP.Port = initMsg.IsUplink ? ((IPEndPoint)sock.RemoteEndPoint).Port : initMsg.ListenPort;
                            isDownlink          = initMsg.IsUplink;
                            isP2P         = initMsg.RouterInfo.IsP2P;
                            initProcessed = true;

                            router.OnTcpInit(this);
                        }
                        else
                        {
                            msg._SetFromChannel(remoteEP);
                            msg._Trace(router, 2, "TCP: Recv", null);
                            msg._Trace(router, 0, "Receive", string.Empty);
                            router.OnReceive(this, msg);
                        }

                        // Initiate reception of the next message

                        BeginReceive();
                    }
                }
            }
            catch (SocketException e)
            {
                // Don't log connection resets because we see these all the
                // time when a router stops.  We're not going to consider
                // this to be an error.

                if (e.SocketErrorCode != SocketError.ConnectionReset)
                {
                    TraceException(e);
                    SysLog.LogException(e);
                }

                router.OnTcpClose(this);
                Close();
            }
            catch (Exception e)
            {
                TraceException(e);
                SysLog.LogException(e);
                router.OnTcpClose(this);
                Close();
            }
        }