/// <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); } }
/// <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 { } } }
/// <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); } }
/// <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(); } } }
/// <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(); } }
/// <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 } } }