Inheritance: BasicTcpPacket, ITcpDataPacket
Example #1
0
 public BasicTcpPacket getPacket(byte[] bytes)
 {
     BasicTcpPacket packet;
     switch (bytes[BasicTcpPacket.PKT_POS_TYPE])
     {
         case BasicTcpPacket.PKT_TYPE_DISCONNECT:
             packet = new StandardDisconnectPacket();
             break;
         case BasicTcpPacket.PKT_TYPE_DISCONNECT_ACK:
             packet = new StandardDisconnectAckPacket();
             break;
         case BasicTcpPacket.PKT_TYPE_DISCONNECT_RS:
             packet = new StandardDisconnectRsPacket();
             break;
         case BasicTcpPacket.PKT_TYPE_CONNECT_RS_ACK:
             packet = new StandardConnectRsAckPacket();
             break;
         case BasicTcpPacket.PKT_TYPE_CONNECT_NAME_RS:
             packet = new StandardNamedConnectRsPacket();
             break;
         case BasicTcpPacket.PKT_TYPE_CONNECT_NAME_RQ:
             packet = new StandardNamedConnectRqPacket();
             break;
         case BasicTcpPacket.PKT_TYPE_DATA:
             packet = new StandardTcpDataPacket();
             break;
         case BasicTcpPacket.PKT_TYPE_ACK:
             packet = new StandardAckPacket();
             break;
         case BasicTcpPacket.PKT_TYPE_NOP:
             packet = new StandardTcpNopPacket();
             break;
         default:
             throw new UnknownPacketException("Failed to determine packet type");
     }
     packet.ProcessPacket(bytes);
     return packet;
 }
Example #2
0
        public override void SendData(byte[] data, int length, int timeout)
        {
            BlockIfNotEstablished(timeout);
            long waitTime = timeout * 10000;
            lock (_sendingLock)
            {
                _sequenceOut++;
                StandardTcpDataPacket packet = new StandardTcpDataPacket(_sequenceOut);
                byte[] packetData = new byte[length];
                Array.Copy(data,packetData,length);
                packet.Data = packetData;
                packet.ConnectionId = ConnectionId;
            #if(DEBUG)
                Logger.Debug("Sending packet " + packet.ToString());
            #endif
                long startTime = DateTime.Now.Ticks;
                _ackEvent.Reset();
                do
                {
                    if (!Established)
                    {
            #if(DEBUG)
                        Logger.Debug("Connection is down, aborting data send");
            #endif
                        throw new ConnectionException("Cannot send data, connection is down");
                    }
                    Transport.SendData(packet);
                    if (packet.ResendCount > 0) { PacketCountTransmitDataResend++; }
                    else { PacketCountTransmitDataFirst++; }
                    if (DateTime.Now.Ticks - startTime > waitTime)
                    {
            #if(DEBUG)
                        Logger.Debug("Data timeout : " + (DateTime.Now.Ticks - startTime));
            #endif
                        _sequenceOut--;
                        throw new TimeoutException("Timeout occured while sending data to " + Transport.TransportManager.RemoteIp);
                    }
            #if(DEBUG)
                    Logger.Debug("Waiting for ack from " + Transport.TransportManager.RemoteIp + " for packet " + _sequenceOut);
            #endif
                    packet.ResendCount++;

                } while (!_ackEvent.WaitOne(AckWaitInterval + (AckWaitInterval * packet.ResendCount)));
                long stopTime = DateTime.Now.Ticks;
                int ackTrip = (int)((stopTime - startTime) / 10000);
                if (ackTrip > AckWaitInterval && (ackTrip - AckWaitInterval) > 20)
                {
                    // ackTrip was more than 50ms longer than our interval, we need to adjust up
                    AckWaitInterval = ((ackTrip - AckWaitInterval) / 2) + AckWaitInterval;
            #if(DEBUG)
                    Logger.Debug("Adjusted ack wait interval UP to " + AckWaitInterval + ", trip was " + ackTrip);
            #endif
                }
                else if (ackTrip < AckWaitInterval && (AckWaitInterval - ackTrip) > 20)
                {
                    // ackTrip was more than 50ms shorter than our internal, we need to adjust down
                    AckWaitInterval = AckWaitInterval - ((AckWaitInterval - ackTrip) / 2);
            #if(DEBUG)
                    Logger.Debug("Adjusted ack wait interval DOWN to " + AckWaitInterval + ", trip was " + ackTrip);
            #endif
                }
            }
        }
Example #3
0
 private void ProcessDataPacket(StandardTcpDataPacket packet)
 {
     try
     {
         TcpConnectionHolder conn = _tcpConnections.GetRemoteConnection(packet.ConnectionId);
         // If the connect response ack packet was lost, its possible that this connection is not open, we need to open it now
         if (!conn.Connection.Established)
         {
             Logger.Debug("Outgoing Connection [" + conn.Connection.ConnectionId + "] received data, means our connect rs ack was lost, auto opening");
             conn.Connection.Open();
         }
         // Lock receiving while we process this packet (we will still be able to send)
         // Now TcpConnection doesn't have to be threadsafe, but each connection
         // can process data independently at full speed.
         lock (conn.ReceiveLock)
         {
             // now process the dataPacket;
             conn.Connection.ProcessDataPacket(packet);
         }
     }
     catch (ConnectionException e)
     {
         Logger.Error("Dropping data packet [" + packet + "], failed to get a connection : " + e.Message);
     }
 }
        public void DataSender()
        {
            try
            {
                // if we still have stuff to send or we are still open
                while (
                    (_sendBuffer.Count > 0 || (!Closing && !Closed)) // we are closing and flushing, or not closing
                    && (!_isDisconnecting && !Disconnected)
                    )
                {
                    long waitStart = Environment.TickCount;
                    lock (_ackWaitingLock)
                    {
                        // wait until there is space in the window. ( we can't send stuff to far into the future )
                        while (!SpaceInWindow() && !Disconnected && !_isDisconnecting)
                        {
                            Stats.NoSpaceInWindow++;
            #if DEBUG
                            Logger.Debug("Pausing send, no space left in window");
            #endif
                            // timeout waiting for space in the window
                            if (!Monitor.Wait(_ackWaitingLock, _currentTimeout))
                            {
                                throw new TimeoutException("Timeout occured while waiting for space in the window to " + Transport.TransportManager.RemoteIp);
                            }
            #if DEBUG
                            Logger.Debug("AckWaitLock release, probably space in window now");
            #endif
                        }

                    }
                    byte[] payload = null;
                    if (!Disconnected && !_isDisconnecting)
                    {

                        // ok now there is space in the window, we will need to send some data and add it to the window.
                        payload = _sendBuffer.Get(TcpChunkSize);
                    }
                    if (!Disconnected && !_isDisconnecting)
                    {
                        if (payload != null && payload.Length > 0)
                        {
            #if DEBUG
                            Logger.Debug("Got " + payload.Length + " bytes from the sendBuffer, " + _sendBuffer.Count +
                                         " left in buffer");
            #endif
                            StandardTcpDataPacket packet = new StandardTcpDataPacket { Data = payload, ConnectionId = ConnectionId, Sequence = _nextDataSeqOut };
                            // make sure there is nothing in the next window space
                            if (_sendWindow[_sendWindowNextFree] != null)
                                throw new ConnectionException(
                                    "Cannot insert packet into window, there is something already there! [" +
                                    _sendWindow[_sendWindowNextFree].Sequence + "]");
                            // actually send the packet
                            Transport.SendData(packet);
                            // calculate some stats
                            Stats.AvgSendWaitTime = (Stats.AvgSendWaitTime * Stats.DataPacketSendCount +
                                                     (Environment.TickCount - waitStart)) /
                                                    (Stats.DataPacketSendCount + 1);
                            Stats.DataPacketSendCount++;
                            // timestamp the packet so we know when it was sent, this will help us when it comes to retrying packets
                            packet.Timestamp = Environment.TickCount;
                            // put it in the next free space in the window and update the free space, expected next data seq etc.
                            _sendWindow[_sendWindowNextFree] = packet;
                            _sendWindowNextFree = (byte)((_sendWindowNextFree + 1) % WindowSize);
                            _nextDataSeqOut++;
                            lock (_retryTimer)
                            {
                                // if we are not currently pending for a retry of an earlier packet, start the timer now.
                                if (!_retryTimer.Enabled)
                                {
                                    _retryTimer.Interval = _retryInterval;
                                    _retryTimer.Start();
            #if DEBUG
                                    Logger.Debug("Setup retry time for " + packet.Sequence + " to " + _retryInterval +
                                                 "ms");
            #endif
                                }
                            }
            #if DEBUG
                            Logger.Debug("Sent packet " + packet.Sequence + ", nextDataSeqOut=" + _nextDataSeqOut +
                                         ", sendWindowNextFree=" + _sendWindowNextFree + ", oldestUnackedPacket=" +
                                         _oldestUnackedPacket);
            #endif
                        }
                    }
                    else
                    {
                        Logger.Debug("Not sending packet, remote side is disconnecting or disconnected.");
                    }
                }
                Logger.Debug("Data sender has completed, buffer=" + _sendBuffer.Count + ", Closing=" + Closing + ", Closed=" + Closed + ", Disconnecting=" + _isDisconnecting + ", Disconnected=" + Disconnected);
            }
            catch (Exception e)
            {
                Logger.Error("DataSender caught Exception while running buffer : " + e.Message, e);
                Close();
            }
            OnDataSenderComplete(EventArgs.Empty);
        }