Пример #1
0
        public void OnMsg(LeafSettingsMsg msg)
        {
            using (TimedLock.Lock(this.SyncRoot))
            {
                if (advertiseTime != msg.AdvertiseTime)
                {
                    advertiseTime = msg.AdvertiseTime;
                    lastAdvertise = SysTime.Now;
                }

                if (msg.HubIPAddress != null && msg.HubTcpPort != 0)
                {
                    if (hubIPAddress != msg.HubIPAddress || hubTcpPort != msg.HubTcpPort)
                    {
                        hubChannelEP = new ChannelEP(Transport.Tcp, new IPEndPoint(msg.HubIPAddress, msg.HubTcpPort));
                    }
                }
                else
                {
                    hubChannelEP = null;
                }

                hubEP        = msg.HubEP;
                hubIPAddress = msg.HubIPAddress;
                hubUdpPort   = msg.HubUdpPort;
                hubTcpPort   = msg.HubTcpPort;

                if (msg.DiscoverLogical)
                {
                    SendLogicalAdvertiseMsgs(msg.HubEP);
                }
            }
        }
Пример #2
0
        private int cbRecv;                         // Bytes to receive

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="router">The associated message router.</param>
        public TcpChannel(MsgRouter router)
        {
            this.router        = router;
            this.sock          = null;
            this.routerEP      = null;
            this.remoteEP      = null;
            this.localEP       = null;
            this.connected     = false;
            this.initProcessed = false;
            this.lastAccess    = SysTime.Now;
            this.isUplink      = false;
            this.isDownlink    = false;
            this.isP2P         = false;

            this.sending   = false;
            this.sendMsg   = null;
            this.sendQueue = new PriorityQueue <Msg>();
            this.onSend    = new AsyncCallback(OnSend);
            this.sendBuf   = null;
            this.sendPos   = 0;
            this.cbSend    = 0;

            this.onReceive  = new AsyncCallback(OnReceive);
            this.recvHeader = false;
            this.recvBuf    = null;
            this.recvPos    = 0;
        }
Пример #3
0
        /// <summary>
        /// Removes the route to the channel endpoint passed if it exists in
        /// the table.
        /// </summary>
        /// <param name="ep">The channel endpoint of the route to remove.</param>
        public void Remove(ChannelEP ep)
        {
            if (ep.Transport != Transport.Tcp)
            {
                throw new MsgException("Only TCP endpoins supported.");
            }

            using (TimedLock.Lock(router.SyncRoot))
            {
                var delList = new List <string>();

                foreach (PhysicalRoute route in routes.Values)
                {
                    if (route.TcpEP == ep)
                    {
                        delList.Add(route.RouterEP.ToString(-1, false));
                    }
                }

                for (int i = 0; i < delList.Count; i++)
                {
                    routes.Remove(delList[i]);
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Transmits the message via the UDP broadcast client.
        /// </summary>
        /// <param name="toEP">The target endpoint.</param>
        /// <param name="msg">The message.</param>
        private void TransmitViaUdpBroadcast(ChannelEP toEP, Msg msg)
        {
            byte[] sendBuf;
            int    cbSend;
            int    cbMsg;

            msg._SetToChannel(toEP);
            msg._SetFromChannel(localEP);
            msg._Trace(router, 2, "UDP: Send", null);

            using (TimedLock.Lock(router.SyncRoot))
            {
                // Initiate transmission of the message

                cbMsg   = Msg.Save(new EnhancedMemoryStream(msgBuf), msg);
                sendBuf = router.EncryptFrame(msgBuf, cbMsg);
                cbSend  = sendBuf.Length;

                Assertion.Validate(cbSend <= TcpConst.MTU - UdpBroadcastClient.MessageEnvelopeSize, "Message larger than UDP MTU.");

                try
                {
                    broadcastClient.Broadcast(sendBuf);
                }
                catch
                {
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Opens a broadcast channel that uses a  instance to
        /// broadcast messages across a collection of servers.  This is typically used on networks
        /// that do not support multicast.
        /// </summary>
        /// <param name="settings">The settings to use for the <see cref="UdpBroadcastClient" />.</param>
        public void OpenUdpBroadcast(UdpBroadcastClientSettings settings)
        {
            using (TimedLock.Lock(router.SyncRoot))
            {
                this.broadcastClient = new UdpBroadcastClient(settings);
                this.broadcastClient.PacketReceived += new UdpBroadcastDelegate(OnBroadcastReceive);

                this.transport       = Transport.Multicast;
                this.localEP         = router.NormalizeEP(new ChannelEP(Transport.Udp, router.UdpEP));
                this.port            = 0;
                this.sendQueue       = null;
                this.onSend          = null;
                this.sendMsg         = null;
                this.cbSend          = 0;
                this.sendBuf         = null;
                this.msgBuf          = new byte[TcpConst.MTU];
                this.cloudEP         = null;
                this.onSocketReceive = null;
                this.recvBuf         = null;

                router.Trace(1, "UDP: OpenUdpBroadcast", null, null);

                // Mark the channel as open.

                this.isOpen = true;
            }
        }
Пример #6
0
 /// <summary>
 /// Called occasionally by the associated router when the
 /// channel's local endpoint is changed.
 /// </summary>
 /// <param name="localEP">The new (normalized) endpoint.</param>
 /// <remarks>
 /// <para>
 /// The endpoint can change if the channel isn't bound to a
 /// specific IP address (aka IPAddress.Any), and the router
 /// detects an IP address change (due perhaps to a new network
 /// connection or a new IP address during a DHCP lease renewal).
 /// </para>
 /// <note>
 /// The endpoint passed will be normalized: the
 /// IP address will be valid.  If no adapter IP address association
 /// can be found, then the IP address will be set to the loopback
 /// address: 127.0.0.1.
 /// </note>
 /// </remarks>
 public void OnNewEP(ChannelEP localEP)
 {
     using (TimedLock.Lock(router.SyncRoot))
     {
         router.Trace(2, "TCP: NewEP", localEP.ToString(), null);
         this.localEP = localEP;
     }
 }
Пример #7
0
 /// <summary>
 /// Used by unit tests to queue the message passed for sending
 /// rather than sending it immediately.  A subsequent Send() call
 /// should send the message passed and then send the queued message.
 /// </summary>
 /// <param name="toEP">The target endpoint.</param>
 /// <param name="msg">The message to queue.</param>
 internal void QueueTo(ChannelEP toEP, Msg msg)
 {
     using (TimedLock.Lock(router.SyncRoot))
     {
         msg._SetToChannel(toEP);
         Enqueue(msg);
     }
 }
Пример #8
0
        /// <summary>
        /// Initializes the channel endpoints of the message's TO
        /// endpoint, creating the endpoint object if necessary.
        /// </summary>
        /// <param name="toChannelEP">The channel endpoint.</param>
        public void _SetToChannel(ChannelEP toChannelEP)
        {
            if (this.toEP == null)
            {
                this._ToEP = new MsgEP(toChannelEP);
            }

            this.toEP.ChannelEP = toChannelEP;
        }
Пример #9
0
        /// <summary>
        /// Initializes the channel endpoints of the message's FROM
        /// endpoint, creating the endpoint object if necessary.
        /// </summary>
        /// <param name="fromChannelEP">The channel endpoint.</param>
        public void _SetFromChannel(ChannelEP fromChannelEP)
        {
            if (this.fromEP == null)
            {
                this.fromEP = new MsgEP(fromChannelEP);
            }

            this.fromEP.ChannelEP = fromChannelEP;
        }
Пример #10
0
        /// <summary>
        /// Initiates a network connection to the message router at the
        /// specified network endpoint and then initiates the transmission
        /// of the message once the connection is established.
        /// </summary>
        /// <param name="ep">The remote router's endpoint.</param>
        /// <param name="msg">The message to be sent (or <c>null</c>).</param>
        public void Connect(IPEndPoint ep, Msg msg)
        {
            using (TimedLock.Lock(router.SyncRoot))
            {
                Assertion.Test(sock == null);
                sock    = new EnhancedSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                localEP = new ChannelEP(Transport.Tcp, router.NormalizeEP(router.TcpEP));

                sock.NoDelay           = !router.TcpDelay;
                sock.SendBufferSize    = router.TcpSockConfig.SendBufferSize;
                sock.ReceiveBufferSize = router.TcpSockConfig.ReceiveBufferSize;

                if (router.FragmentTcp)
                {
                    sock.SendMax    = 1;
                    sock.ReceiveMax = 1;
                }

                // Queue the channel initialization message and the message passed

                Msg initMsg;

                initMsg      = new TcpInitMsg(router.RouterEP, new MsgRouterInfo(router), isUplink, router.TcpEP.Port);
                initMsg._TTL = 1;

                Serialize(initMsg);
                Enqueue(initMsg);

                try
                {
                    SetLastAccess();
                    remoteEP = new ChannelEP(Transport.Tcp, router.NormalizeEP(ep));

                    if (msg != null)
                    {
                        msg._SetToChannel(remoteEP);
                        msg._SetFromChannel(localEP);
                        msg._Trace(router, 2, "TCP: Queue", null);

                        Serialize(msg);
                        Enqueue(msg);
                    }

                    router.Trace(2, "TCP: Outbound", "LocalEP=" + localEP.NetEP.ToString() + " remoteEP=" + remoteEP.NetEP.ToString(), null);
                    sock.BeginConnect(remoteEP.NetEP, new AsyncCallback(OnConnect), null);
                }
                catch (Exception e)
                {
                    router.Trace(string.Format(null, "TCP: Connect Failed [{0}]", ep), e);
                    router.OnTcpClose(this);
                    Close();
                }
            }
        }
Пример #11
0
 /// <summary>
 /// Transmits the message to the specified channel endpoint.
 /// </summary>
 /// <param name="toEP">The target endpoint.</param>
 /// <param name="msg">The message.</param>
 public void Transmit(ChannelEP toEP, Msg msg)
 {
     if (broadcastClient != null)
     {
         TransmitViaUdpBroadcast(toEP, msg);
     }
     else
     {
         TransmitViaSocket(toEP, msg);
     }
 }
Пример #12
0
        /// <summary>
        /// Private implementation of the Transmit() method that implements an
        /// option that disables queuing for the message passed.
        /// </summary>
        /// <param name="toEP">The target endpoint.</param>
        /// <param name="msg">The message.</param>
        /// <param name="queue">Indicates whether queuing should be enabled for this message.</param>
        private void Transmit(ChannelEP toEP, Msg msg, bool queue)
        {
            msg._SetToChannel(toEP);
            msg._SetFromChannel(localEP);
            msg._Trace(router, 2, "TCP: Send", null);

            // Serialize the message here rather than within the lock
            // below for better multiprocessor performance.

            Serialize(msg);

            // Initiate transmission of the message or queue it if other
            // messages are awaiting transmission (if queuing is enabled).

            try
            {
                using (TimedLock.Lock(router.SyncRoot))
                {
                    if (!connected || sending)
                    {
                        Enqueue(msg);
                        return;
                    }

                    // If there are already messages in the queue then add this
                    // message to the end of the queue and then dequeue a message
                    // from the front of the queue and send it.

                    if (queue && sendQueue.Count > 0)
                    {
                        Enqueue(msg);
                        msg = Dequeue();
                    }

                    // Initiate message transmission

                    sendBuf = msg._MsgFrame;
                    sending = true;
                    sendPos = 0;
                    cbSend  = sendBuf.Length;

                    sock.BeginSend(sendBuf, sendPos, cbSend, SocketFlags.None, onSend, null);
                }
            }
            catch (Exception e)
            {
                TraceException(e);
                router.OnTcpClose(this);
                Close();
            }
        }
Пример #13
0
        /// <summary>
        /// Queues the message passed rather than initiating an
        /// immediate transmission.
        /// </summary>
        /// <param name="toEP">The target endpoint.</param>
        /// <param name="msg">The message to queue.</param>
        internal void QueueTo(ChannelEP toEP, Msg msg)
        {
            msg._SetToChannel(toEP);
            msg._SetFromChannel(localEP);
            msg._Trace(router, 2, "TCP: Queue", null);

            Serialize(msg);

            using (TimedLock.Lock(router.SyncRoot))
            {
                msg._SetToChannel(toEP);
                Enqueue(msg);
            }
        }
Пример #14
0
        private Guid logicalEndpointSetID;              // The current logical endpoint set ID

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="routerEP">The router endpoint.</param>
        /// <param name="appName">The name of the application hosting the router.</param>
        /// <param name="appDescription">A description of the application.</param>
        /// <param name="routerInfo">The router's capability information.</param>
        /// <param name="logicalEndpointSetID">The router's logical endpoint set ID.</param>
        /// <param name="udpEP">The UDP network endpoint (or <c>null</c>).</param>
        /// <param name="tcpEP">The TCP network endpoint (or <c>null</c>).</param>
        /// <param name="ttd">Route time-to-die (SYS).</param>
        /// <remarks>
        /// The router endpoint must be a physical non-channel endpoint.
        /// </remarks>
        internal PhysicalRoute(MsgEP routerEP, string appName, string appDescription, MsgRouterInfo routerInfo,
                               Guid logicalEndpointSetID, IPEndPoint udpEP, IPEndPoint tcpEP, DateTime ttd)
        {
            Assertion.Test(routerEP.IsPhysical);
            Assertion.Test(!routerEP.IsChannel);

            this.routerEP             = routerEP;
            this.appName              = appName;
            this.appDescription       = appDescription;
            this.routerInfo           = routerInfo;
            this.logicalEndpointSetID = logicalEndpointSetID;
            this.udpEP = udpEP == null ? null : new ChannelEP(Transport.Udp, udpEP);
            this.tcpEP = tcpEP == null ? null : new ChannelEP(Transport.Tcp, tcpEP);
            this.ttd   = ttd;
            this.isP2P = routerInfo.IsP2P;
        }
Пример #15
0
        /// <summary>
        /// Handles connection completions.
        /// </summary>
        /// <param name="ar">The async result.</param>
        private void OnConnect(IAsyncResult ar)
        {
            using (TimedLock.Lock(router.SyncRoot))
            {
                try
                {
                    if (sock == null)
                    {
                        return;
                    }

                    sock.EndConnect(ar);

                    connected = true;
                    remoteEP  = new ChannelEP(Transport.Tcp, new IPEndPoint(((IPEndPoint)sock.RemoteEndPoint).Address, 0));

                    router.Trace(2, "TCP: Connected", "LocalEP=" + localEP.NetEP.ToString() + " remoteEP=" + remoteEP.NetEP.ToString(), null);
                    SetLastAccess();

                    // Initiation reception of the first message

                    BeginReceive();

                    // Start sending any queued messages

                    Assertion.Test(!sending);
                    if (sendQueue.Count > 0)
                    {
                        Msg msg;

                        msg = Dequeue();
                        Transmit(msg._ToEP.ChannelEP, msg, false);
                    }
                }
                catch (Exception e)
                {
                    router.Trace(string.Format(null, "TCP: Connect Failed"), e);
                    router.OnTcpClose(this);
                    Close();
                }
            }
        }
Пример #16
0
        /// <summary>
        /// Opens a UDP unicast socket.
        /// </summary>
        /// <param name="ep">The UDP endpoint to open.</param>
        /// <remarks>
        /// <para>
        /// Pass <b>ep.Address=IPAddress.Any</b> if the channel should be opened on all
        /// network adapters.
        /// </para>
        /// <para>
        /// Pass <b>ep.Port=0</b> if Windows should assign the socket's port.  The
        /// port assigned can be determined via the <see cref="Port" /> property.
        /// </para>
        /// </remarks>
        public void OpenUnicast(IPEndPoint ep)
        {
            using (TimedLock.Lock(router.SyncRoot))
            {
                this.sock = new EnhancedSocket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                this.sock.Bind(ep);

                this.transport       = Transport.Udp;
                this.localEP         = router.NormalizeEP(new ChannelEP(Transport.Udp, (IPEndPoint)sock.LocalEndPoint));
                this.port            = localEP.NetEP.Port;
                this.sendQueue       = new PriorityQueue <Msg>();
                this.onSend          = new AsyncCallback(OnSend);
                this.sendMsg         = null;
                this.cbSend          = 0;
                this.sendBuf         = null;
                this.msgBuf          = new byte[TcpConst.MTU];
                this.cloudEP         = null;
                this.multicastInit   = false;
                this.broadcastClient = null;

                sendQueue.CountLimit = router.UdpMsgQueueCountMax;
                sendQueue.SizeLimit  = router.UdpMsgQueueSizeMax;

                this.onSocketReceive = new AsyncCallback(OnSocketReceive);
                this.recvBuf         = new byte[TcpConst.MTU];

                router.Trace(1, "UDP: OpenUnicast", "localEP=" + localEP.NetEP.ToString(), null);

                sock.IgnoreUdpConnectionReset = true;
                sock.SendBufferSize           = router.UdpUnicastSockConfig.SendBufferSize;
                sock.ReceiveBufferSize        = router.UdpUnicastSockConfig.ReceiveBufferSize;

                // Initiate the first async receive operation on this socket

                sock.BeginReceiveFrom(recvBuf, 0, recvBuf.Length, SocketFlags.None, ref recvEP, onSocketReceive, null);

                // Mark the channel as open.

                this.isOpen = true;
            }
        }
Пример #17
0
        /// <summary>
        /// Associates the channel with the open socket passed and begins
        /// listening for messages received on the socket.
        /// </summary>
        /// <param name="sock">The open socket.</param>
        public void Open(EnhancedSocket sock)
        {
            using (TimedLock.Lock(router.SyncRoot))
            {
                Assertion.Test(this.sock == null);

                this.sock      = sock;
                this.connected = true;
                this.localEP   = router.NormalizeEP(new ChannelEP(Transport.Tcp, router.TcpEP));
                this.remoteEP  = new ChannelEP(Transport.Tcp, new IPEndPoint(((IPEndPoint)sock.RemoteEndPoint).Address, 0));
                this.sendQueue.Clear();

                sock.SendBufferSize    = router.TcpSockConfig.SendBufferSize;
                sock.ReceiveBufferSize = router.TcpSockConfig.ReceiveBufferSize;

                // Send the channel initialization message to the other endpoint.

                sock.NoDelay = !router.TcpDelay;

                if (router.FragmentTcp)
                {
                    sock.SendMax    = 1;
                    sock.ReceiveMax = 1;
                }

                router.Trace(2, "TCP: Inbound", "LocalEP=" + localEP.NetEP.ToString() + " remoteEP=" + remoteEP.NetEP.ToString(), null);

                SetLastAccess();
                BeginReceive();

                TcpInitMsg msg;

                msg      = new TcpInitMsg(router.RouterEP, new MsgRouterInfo(router), isUplink, localEP.NetEP.Port);
                msg._TTL = 1;
                Transmit(router.NormalizeEP(remoteEP), msg, false);
            }
        }
Пример #18
0
        /// <summary>
        /// Transmits the message via the socket.
        /// </summary>
        /// <param name="toEP">The target endpoint.</param>
        /// <param name="msg">The message.</param>
        private void TransmitViaSocket(ChannelEP toEP, Msg msg)
        {
            int cbMsg;

            if (cloudEP != null && !multicastInit)
            {
                // Retry adding the socket to the multicast group if this didn't
                // work earlier.

                try
                {
                    this.sock.MulticastGroup = cloudEP.Address;
                    this.multicastInit       = true;
                }
                catch
                {
                    this.multicastInit = false;
                }
            }

            msg._SetToChannel(toEP);
            msg._SetFromChannel(localEP);
            msg._Trace(router, 2, "UDP: Send", null);

            using (TimedLock.Lock(router.SyncRoot))
            {
                if (sendMsg != null)
                {
                    // We're already in the process of transmitting
                    // a message so queue this one.

                    Enqueue(msg);
                    return;
                }

                // If there are already messages in the queue then queue
                // this one and then setup to transmit the first message
                // waiting in the queue.

                if (sendQueue.Count > 0)
                {
                    Enqueue(msg);
                    msg = sendQueue.Dequeue();
                }

                // Initiate transmission of the message

                sendMsg = msg;
                cbMsg   = Msg.Save(new EnhancedMemoryStream(msgBuf), sendMsg);
                sendBuf = router.EncryptFrame(msgBuf, cbMsg);
                cbSend  = sendBuf.Length;

                Assertion.Validate(cbSend <= TcpConst.MTU, "Message larger than UDP MTU.");

                try
                {
                    sock.BeginSendTo(sendBuf, 0, cbSend, SocketFlags.None, router.NormalizeEP(toEP.NetEP), onSend, null);
                }
                catch
                {
                    // Ignoring
                }
            }
        }
Пример #19
0
        public void OnMsg(RouterAdvertiseMsg msg)
        {
            PhysicalRoute physRoute;
            bool          discoverLogical;

            if (this.RouterEP == null)
            {
                return;     // Router is not fully initialized
            }
            if (this.RouterEP.IsPhysicalMatch(msg.RouterEP))
            {
                // I've noticed that on multi-homed machines, we can see source IP addresses for
                // multicast messages from ourself that differ from what we think our IP address
                // is.  I'm going to check the source IP address against all of the local IP
                // addresses to avoid issuing invalid warnings.

                var isLocalIPAddress = NetHelper.IsLocalAddress(msg.IPAddress);

                if (msg.TcpPort != this.TcpEP.Port || !isLocalIPAddress)
                {
                    this.dupLeafDetected = true;
                    SysLog.LogWarning("Duplicate router [{0}] appears to be advertising on TCP[{1}:{2}].  Local endpoint is TCP[{3}:{4}].",
                                      msg.RouterEP.ToString(-1, false),
                                      msg.IPAddress, msg.TcpPort,
                                      this.TcpEP.Address, this.TcpEP.Port);
                }

                if (msg.UdpPort != this.UdpEP.Port || !isLocalIPAddress)
                {
                    this.dupLeafDetected = true;
                    SysLog.LogWarning("Duplicate router [{0}] appears to be advertising on UDP[{1}:{2}].  Local endpoint is UDP[{3}:{4}].",
                                      msg.RouterEP.ToString(-1, false),
                                      msg.IPAddress, msg.UdpPort,
                                      this.UdpEP.Address, this.UdpEP.Port);
                }

                return;     // Don't add routes to self to the routing table
            }

            // If the source router is this router's hub then send it a RouterAdvertiseMsg
            // so the hub can continue the route discovery process.

            if (msg.ReplyAdvertise && this.RouterEP.GetPhysicalParent().Equals(msg.RouterEP))
            {
                // Set up a temporary route to the hub so the RouterAdvertiseMsg can be delivered.
                // These values will be finalized when the LeafSettingsMsg is received.

                this.hubEP        = msg.RouterEP;
                this.hubChannelEP = new ChannelEP(Transport.Tcp, new IPEndPoint(msg.IPAddress, msg.TcpPort));

                // Send the RouterAdvertiseMsg to the hub.

                SendTo(msg.RouterEP, new RouterAdvertiseMsg(this.RouterEP, this.AppName, this.AppDescription, this.RouterInfo,
                                                            this.UdpEP.Port, this.TcpEP.Port, this.Dispatcher.LogicalEndpointSetID, false, false));
                return;
            }

            // Ignore the message if either this router or the advertised router is not
            // peer-to-peer enabled.  In these cases, messages will be forwarded to
            // the hub for delivery.

            if (!base.EnableP2P || !msg.RouterInfo.IsP2P)
            {
                return;
            }

            // Add/update the physical route to the advertised router.

            using (TimedLock.Lock(this.SyncRoot))
            {
                if (!isRunning)
                {
                    return;
                }

                // Handle route table management for peer routers.

                if (!this.RouterEP.IsPhysicalPeer(msg.RouterEP))
                {
                    const string format =
                        @"RouterEP: {0}
Route:    {1}";
                    NetTrace.Write(MsgRouter.TraceSubsystem, 1, "Ignore route", this.GetType().Name + ": " + msg.RouterEP.ToString(), string.Format(null, format, this.RouterEP.ToString(), msg.RouterEP.ToString()));
                    return;
                }

                // If this is the first time we've seen this router or if the router's set
                // of handled logical endpoints has changed then we'll need to set the
                // DiscoverLogical=true on the RouterAdvertiseMsg so the other will send
                // us its logical endpoints.

                physRoute       = base.PhysicalRoutes[msg.RouterEP];
                discoverLogical = physRoute == null || physRoute.LogicalEndpointSetID != msg.LogicalEndpointSetID;

                // Send a RouterAdvertiseMsg for this router back to the source router if that
                // router is P2P enabled and a reply is requested.  This will give that router
                // a chance to learn about this router.

                if (msg.RouterInfo.IsP2P && (msg.ReplyAdvertise || discoverLogical))
                {
                    SendTo(msg.RouterEP, new RouterAdvertiseMsg(this.RouterEP, this.AppName, this.AppDescription, this.RouterInfo,
                                                                this.UdpEP.Port, this.TcpEP.Port, this.Dispatcher.LogicalEndpointSetID, false, discoverLogical));
                }

                AddPhysicalRoute(msg.RouterEP, msg.AppName, msg.AppDescription, msg.RouterInfo, msg.LogicalEndpointSetID,
                                 new IPEndPoint(msg.IPAddress, msg.UdpPort), new IPEndPoint(msg.IPAddress, msg.TcpPort));

                // Send LogicalAdvertiseMsgs back to the sender if requested.

                if (msg.DiscoverLogical)
                {
                    SendLogicalAdvertiseMsgs(msg.RouterEP);
                }
            }
        }
Пример #20
0
        /// <summary>
        /// Opens a UDP multicast socket.
        /// </summary>
        /// <param name="adapter">The network adapter to bind this socket.</param>
        /// <param name="cloudEP">Specifies the multicast group and port.</param>
        /// <remarks>
        /// <para>
        /// Pass <b>adapter=IPAddress.Any</b> to bind the socket to all available network
        /// adapters.
        /// </para>
        /// <note>
        /// A valid port and address must be specified in <b>cloudEP</b>.
        /// </note>
        /// </remarks>
        public void OpenMulticast(IPAddress adapter, IPEndPoint cloudEP)
        {
            if (cloudEP.Address.Equals(IPAddress.Any))
            {
                throw new MsgException("Invalid multicast address.");
            }

            if (cloudEP.Port == 0)
            {
                throw new MsgException("Invalid multicast port.");
            }

            using (TimedLock.Lock(router.SyncRoot))
            {
                this.sock = new EnhancedSocket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                this.sock.ReuseAddress             = true;
                this.sock.EnableBroadcast          = true;
                this.sock.MulticastTTL             = MulticastTTL;
                this.sock.MulticastLoopback        = true;
                this.sock.IgnoreUdpConnectionReset = true;

                this.sock.Bind(new IPEndPoint(adapter, cloudEP.Port));

                // The framework throws an exception if there is no connected network connection
                // when we attempt to add the socket to the multicast group.  I'm going to catch
                // this exception and track that this didn't work and then periodically retry
                // the operation.

                try
                {
                    this.sock.MulticastGroup = cloudEP.Address;
                    this.multicastInit       = true;
                }
                catch
                {
                    this.multicastInit = false;
                }

                this.transport = Transport.Multicast;
                this.localEP   = router.NormalizeEP(new ChannelEP(Transport.Udp, router.UdpEP));
                this.port      = cloudEP.Port;
                this.sendQueue = new PriorityQueue <Msg>();
                this.onSend    = new AsyncCallback(OnSend);
                this.sendMsg   = null;
                this.cbSend    = 0;
                this.sendBuf   = null;
                this.msgBuf    = new byte[TcpConst.MTU];
                this.cloudEP   = cloudEP;

                this.onSocketReceive = new AsyncCallback(OnSocketReceive);
                this.recvBuf         = new byte[TcpConst.MTU];

                sendQueue.CountLimit = router.UdpMsgQueueCountMax;
                sendQueue.SizeLimit  = router.UdpMsgQueueSizeMax;

                router.Trace(1, "UDP: OpenMulticast",
                             string.Format("cloudEP={0} localEP={1} adaptor={2} NIC={3}",
                                           cloudEP, localEP.NetEP, adapter, NetHelper.GetNetworkAdapterIndex(adapter)), null);

                sock.SendBufferSize    = router.UdpMulticastSockConfig.SendBufferSize;
                sock.ReceiveBufferSize = router.UdpMulticastSockConfig.ReceiveBufferSize;

                // Initiate the first async receive operation on this socket

                sock.BeginReceiveFrom(recvBuf, 0, recvBuf.Length, SocketFlags.None, ref recvEP, onSocketReceive, null);

                // Mark the channel as open.

                this.isOpen = true;
            }
        }
Пример #21
0
 /// <summary>
 /// Transmits the message to the specified channel endpoint.
 /// </summary>
 /// <param name="toEP">The target endpoint.</param>
 /// <param name="msg">The message.</param>
 public void Transmit(ChannelEP toEP, Msg msg)
 {
     Transmit(toEP, msg, true);
 }