Пример #1
0
        // Aborts all related endpoint threads and data
        public void stop()
        {
            fullyStopped = true;

            Thread.Sleep(50); // clear any last messages

            state   = RemoteEndpointState.Closed;
            running = false;

            Thread.Sleep(50); // wait for threads to stop

            lock (sendQueueMessagesHighPriority)
            {
                sendQueueMessagesHighPriority.Clear();
            }

            lock (sendQueueMessagesNormalPriority)
            {
                sendQueueMessagesNormalPriority.Clear();
            }

            lock (sendQueueMessagesLowPriority)
            {
                sendQueueMessagesLowPriority.Clear();
            }

            lock (recvRawQueueMessages)
            {
                recvRawQueueMessages.Clear();
            }

            lock (subscribedAddresses)
            {
                subscribedAddresses.Clear();
            }

            // Abort all related threads
            if (recvThread != null)
            {
                //recvThread.Abort();
                recvThread = null;
            }
            if (sendThread != null)
            {
                //sendThread.Abort();
                sendThread = null;
            }
            if (parseThread != null)
            {
                //parseThread.Abort();
                parseThread = null;
            }

            disconnect();
        }
Пример #2
0
        // Internal function that sends data through the socket
        protected void sendDataInternal(ProtocolMessageCode code, byte[] data, byte[] checksum)
        {
            byte[] ba = CoreProtocolMessage.prepareProtocolMessage(code, data, checksum);
            NetDump.Instance.appendSent(clientSocket, ba, ba.Length);
            try
            {
                for (int sentBytes = 0; sentBytes < ba.Length && running;)
                {
                    int bytesToSendCount = ba.Length - sentBytes;
                    if (bytesToSendCount > 8000)
                    {
                        bytesToSendCount = 8000;
                    }


                    int curSentBytes = clientSocket.Send(ba, sentBytes, bytesToSendCount, SocketFlags.None);

                    lastDataSentTime = Clock.getTimestamp();


                    // Sleep a bit to allow other threads to do their thing
                    Thread.Yield();

                    sentBytes += curSentBytes;
                    // TODO TODO TODO timeout
                }
                if (clientSocket.Connected == false)
                {
                    if (running)
                    {
                        Logging.warn(String.Format("sendRE: Failed senddata to remote endpoint {0}, Closing.", getFullAddress()));
                    }
                    state = RemoteEndpointState.Closed;
                }
            }
            catch (Exception e)
            {
                if (running)
                {
                    Logging.warn(String.Format("sendRE: Socket exception for {0}, closing. {1}", getFullAddress(), e));
                }
                state = RemoteEndpointState.Closed;
            }
        }
Пример #3
0
        public void start(Socket socket = null)
        {
            if (fullyStopped)
            {
                Logging.error("Can't start a fully stopped RemoteEndpoint");
                return;
            }

            if (running)
            {
                return;
            }

            if (socket != null)
            {
                clientSocket = socket;
            }
            if (clientSocket == null)
            {
                Logging.error("Could not start NetworkRemoteEndpoint, socket is null");
                return;
            }

            prepareSocket(clientSocket);

            remoteIP        = (IPEndPoint)clientSocket.RemoteEndPoint;
            address         = remoteIP.Address.ToString();
            fullAddress     = address + ":" + remoteIP.Port;
            presence        = null;
            presenceAddress = null;

            connectionStartTime = Clock.getTimestamp();

            lock (subscribedAddresses)
            {
                subscribedAddresses.Clear();
            }

            lastDataReceivedTime = Clock.getTimestamp();
            lastDataSentTime     = Clock.getTimestamp();

            state = RemoteEndpointState.Established;

            timeDifference   = 0;
            timeSyncComplete = false;
            timeSyncs.Clear();

            running = true;

            // Abort all related threads
            if (recvThread != null)
            {
                recvThread.Abort();
                recvThread = null;
            }
            if (sendThread != null)
            {
                sendThread.Abort();
                sendThread = null;
            }
            if (parseThread != null)
            {
                parseThread.Abort();
                parseThread = null;
            }

            try
            {
                TLC = new ThreadLiveCheck();
                // Start receive thread
                recvThread      = new Thread(new ThreadStart(recvLoop));
                recvThread.Name = "Network_Remote_Endpoint_Receive_Thread";
                recvThread.Start();

                // Start send thread
                sendThread      = new Thread(new ThreadStart(sendLoop));
                sendThread.Name = "Network_Remote_Endpoint_Send_Thread";
                sendThread.Start();

                // Start parse thread
                parseThread      = new Thread(new ThreadStart(parseLoop));
                parseThread.Name = "Network_Remote_Endpoint_Parse_Thread";
                parseThread.Start();
            }
            catch (Exception e)
            {
                Logging.error("Exception start remote endpoint: {0}", e.Message);
            }
        }
Пример #4
0
        // Send thread
        protected void sendLoop()
        {
            // Prepare an special message object to use while sending, without locking up the queue messages
            QueueMessage active_message = new QueueMessage();

            if (enableSendTimeSyncMessages)
            {
                sendTimeSyncMessages();
            }

            int messageCount = 0;

            while (running)
            {
                TLC.Report();
                long curTime = Clock.getTimestamp();
                if (helloReceived == false && curTime - connectionStartTime > 10)
                {
                    // haven't received hello message for 10 seconds, stop running
                    Logging.warn(String.Format("Node {0} hasn't received hello data from remote endpoint for over 10 seconds, disconnecting.", getFullAddress()));
                    state   = RemoteEndpointState.Closed;
                    running = false;
                    break;
                }
                if (curTime - lastDataReceivedTime > CoreConfig.pingTimeout)
                {
                    // haven't received any data for 10 seconds, stop running
                    Logging.warn(String.Format("Node {0} hasn't received any data from remote endpoint for over {1} seconds, disconnecting.", getFullAddress(), CoreConfig.pingTimeout));
                    state   = RemoteEndpointState.Closed;
                    running = false;
                    break;
                }
                if (curTime - lastDataSentTime > CoreConfig.pongInterval)
                {
                    try
                    {
                        clientSocket.Send(new byte[1] {
                            1
                        }, SocketFlags.None);
                        lastDataSentTime = curTime;
                        continue;
                    }
                    catch (Exception)
                    {
                        state   = RemoteEndpointState.Closed;
                        running = false;
                        break;
                    }
                }

                bool message_found = false;
                lock (sendQueueMessagesHighPriority)
                {
                    lock (sendQueueMessagesNormalPriority)
                    {
                        if ((messageCount > 0 && messageCount % 5 == 0) || (sendQueueMessagesNormalPriority.Count == 0 && sendQueueMessagesHighPriority.Count == 0))
                        {
                            lock (sendQueueMessagesLowPriority)
                            {
                                if (sendQueueMessagesLowPriority.Count > 0)
                                {
                                    // Pick the oldest message
                                    QueueMessage candidate = sendQueueMessagesLowPriority[0];
                                    active_message.code         = candidate.code;
                                    active_message.data         = candidate.data;
                                    active_message.checksum     = candidate.checksum;
                                    active_message.skipEndpoint = candidate.skipEndpoint;
                                    active_message.helperData   = candidate.helperData;
                                    // Remove it from the queue
                                    sendQueueMessagesLowPriority.Remove(candidate);
                                    message_found = true;
                                }
                            }
                            messageCount = 0;
                        }

                        if (message_found == false && ((messageCount > 0 && messageCount % 3 == 0) || sendQueueMessagesHighPriority.Count == 0))
                        {
                            if (sendQueueMessagesNormalPriority.Count > 0)
                            {
                                // Pick the oldest message
                                QueueMessage candidate = sendQueueMessagesNormalPriority[0];
                                active_message.code         = candidate.code;
                                active_message.data         = candidate.data;
                                active_message.checksum     = candidate.checksum;
                                active_message.skipEndpoint = candidate.skipEndpoint;
                                active_message.helperData   = candidate.helperData;
                                // Remove it from the queue
                                sendQueueMessagesNormalPriority.Remove(candidate);
                                message_found = true;
                            }
                        }

                        if (message_found == false && sendQueueMessagesHighPriority.Count > 0)
                        {
                            // Pick the oldest message
                            QueueMessage candidate = sendQueueMessagesHighPriority[0];
                            active_message.code         = candidate.code;
                            active_message.data         = candidate.data;
                            active_message.checksum     = candidate.checksum;
                            active_message.skipEndpoint = candidate.skipEndpoint;
                            active_message.helperData   = candidate.helperData;
                            // Remove it from the queue
                            sendQueueMessagesHighPriority.Remove(candidate);
                            message_found = true;
                        }
                    }
                }

                if (message_found)
                {
                    messageCount++;
                    // Active message set, attempt to send it
                    sendDataInternal(active_message.code, active_message.data, active_message.checksum);
                    if (active_message.code == ProtocolMessageCode.bye)
                    {
                        Thread.Sleep(500); // grace sleep to get the message through
                        running      = false;
                        fullyStopped = true;
                    }
                    Thread.Sleep(1);
                }
                else
                {
                    // Sleep for 10ms to prevent cpu waste
                    Thread.Sleep(10);
                }
            }
        }
Пример #5
0
        // Receive thread
        protected virtual void recvLoop()
        {
            socketReadBuffer    = new byte[8192];
            lastMessageStatTime = DateTime.UtcNow;
            while (running)
            {
                TLC.Report();
                // Let the protocol handler receive and handle messages
                try
                {
                    byte[] data = readSocketData();
                    if (data != null)
                    {
                        parseDataInternal(data, this);
                        messagesPerSecond++;
                    }
                }
                catch (Exception e)
                {
                    if (running)
                    {
                        Logging.warn(string.Format("recvRE: Disconnected client {0} with exception {1}", getFullAddress(), e.ToString()));
                    }
                    state = RemoteEndpointState.Closed;
                }

                // Check if the client disconnected
                if (state == RemoteEndpointState.Closed)
                {
                    running = false;
                    break;
                }

                TimeSpan timeSinceLastStat = DateTime.UtcNow - lastMessageStatTime;
                if (timeSinceLastStat.TotalSeconds < 0 || timeSinceLastStat.TotalSeconds > 2)
                {
                    lastMessageStatTime   = DateTime.UtcNow;
                    lastMessagesPerSecond = (int)(messagesPerSecond / timeSinceLastStat.TotalSeconds);
                    messagesPerSecond     = 0;
                }

                if (lastMessagesPerSecond < 1)
                {
                    lastMessagesPerSecond = 1;
                }

                // Sleep a while to throttle the client
                // Check if there are too many messages
                // TODO TODO TODO this can be handled way better
                int total_message_count = NetworkQueue.getQueuedMessageCount() + NetworkQueue.getTxQueuedMessageCount();
                if (total_message_count > 500)
                {
                    Thread.Sleep(100 * lastMessagesPerSecond);
                    if (messagesPerSecond == 0)
                    {
                        lastMessageStatTime = DateTime.UtcNow;
                    }
                    lastDataReceivedTime = Clock.getTimestamp();
                }
                else if (total_message_count > 100)
                {
                    Thread.Sleep(total_message_count / 10);
                }
                else
                {
                    Thread.Sleep(1);
                }
            }
        }