public ConnectingBroker(UdpSocket udpSocket, UdpPeer peer) { SeningTime = (int)EnvironmentTimer.GetTickCount(); _peer = peer; _udpSocket = udpSocket; SentCount = 0; }
public void FlushSendQueues() { if (_udpSocket.State == SocketState.Disconnected) { return; } int remainingCommands; do { remainingCommands = 0; lock (_udpBuffer) { Array.Clear(_udpBuffer, 0, _udpBuffer.Length); _udpBufferIndex = MtuHeaderLength; uint currentTime = EnvironmentTimer.GetTickCount(); // Sends ack for received reliable commands (1st priority) int commandCountToSend = SerializeAck(currentTime); if (!EnqueueResendingCommands(currentTime)) { return; } #if PERF // Needs to send a ping command because a ack thread is not running in test client. if (currentTime - _timestampOfLastReliableSend > PingInterval) { EnqueueOutgoingCommand(new OutgoingCommand(CommandType.Ping, 0)); } #endif // Send commands int totalReliableCommand = 0; int totalunReliableCommand = 0; for (int i = 0; i < _channels.Count; i++) { totalReliableCommand += SerializeQueue(_channels[i].ReliableSendQueue, currentTime); totalunReliableCommand += SerializeQueue(_channels[i].UnreliableSendQueue, currentTime); remainingCommands += _channels[i].RemainingOutgoingCommands(); } commandCountToSend += (totalReliableCommand + totalunReliableCommand); //if udpCommandCount is more than zero, there is commands to send. SendBuffer(commandCountToSend, currentTime); if (totalReliableCommand > 0) { _timestampOfLastReliableSend = currentTime; } } } while (remainingCommands > 0); }
private void TryToConnect() { if (_connectionBroker.SentCount >= SentCountAllowance) { Disconnect(DisconnectReason.ConnectionFailed, false); return; } if (_connectionBroker.SeningTime + DisconnectTimeout < EnvironmentTimer.GetTickCount()) { _connectionBroker.SeningTime = (int)EnvironmentTimer.GetTickCount(); _udpSocket.Send(_connectionBroker.CreateConnectCommand( ChannelCount, MTU, DataSerializer.Version, DisconnectTimeout, IsCrcEnabled, _cipher.PublicKey, _connectionBroker.SeningTime)); } }
private void SendAck() { do { lock (_udpBuffer) { Array.Clear(_udpBuffer, 0, _udpBuffer.Length); _udpBufferIndex = MtuHeaderLength; uint currentTime = EnvironmentTimer.GetTickCount(); int commandCountToSend = SerializeAck(currentTime); if (!EnqueueResendingCommands(currentTime)) return; //Ping 전송이 필요한지 판단하여 송신 if (_udpSocket.State == SocketState.Connected && currentTime - _timestampOfLastReliableSend > PingInterval) { OutgoingCommand command = new OutgoingCommand(CommandType.Ping, 0); EnqueueOutgoingCommand(command); // Ping이 Reliable command이기 때문에, Reliable command들을 Serialize 한다. for (int i = 0; i < _channels.Count; i++) { commandCountToSend += SerializeQueue(_channels[i].ReliableSendQueue, currentTime); } _timestampOfLastReliableSend = currentTime; } SendBuffer(commandCountToSend, currentTime); } } while (RemainingAckCommands() > 0); }
internal void Init(int peerID, int port, BigInteger serverKey, long sendingTime, long responseTime) { _peerId = peerID; _cipher.EstablishKeyExchange(serverKey); RemoteEndPoint.Port = port; long currentTime = EnvironmentTimer.GetTickCount(); uint rtt = (uint)(currentTime - sendingTime); uint currentServerTime = (uint)(responseTime + (rtt >> 1)); Interlocked.Exchange(ref _serverTimeOffset, (int)(currentServerTime - currentTime)); _roundTripTime.MeanOfRoundTripTime = (int)rtt; if (Logger.IsDebugEnabled) { Log(LogLevel.Debug, "Initial PeerID[{0}] RTT[{1}] Servertime[{2}]", _peerId, _roundTripTime.MeanOfRoundTripTime, currentServerTime); } byte[] bytes = new InitialRequest(SdkVersion, ClientVersion, CustomData).GetBytes(); EnqueueOutgoingCommand(new OutgoingCommand(CommandType.Reliable, 0, bytes)); _udpSocket.SetBroker(this, SocketState.Connected); }
/// <summary> /// Called by a receive thread. /// </summary> void INetworkBroker.OnReceive(IByteBuffer buffer) { uint currentTime = EnvironmentTimer.GetTickCount(); int bufferCount = buffer.Count; CommandType ct = (CommandType)buffer.ReadByte(); if (ct != CommandType.None) { return; } //peerID (4 bytes) int peerID = buffer.ReadInt(); if (_peerId > 0 && peerID != _peerId) { Log(LogLevel.Error, "A assigned peerID [{0}] is different from recevied peerID [{1}] from server", peerID, _peerId); Disconnect(DisconnectReason.InvalidConnection, false); } //timestamp of sent time (8 byte) uint serverSentTime = (uint)buffer.ReadLong(); //the number of commands in a incoming buffer (2 byte) short commandCount = buffer.ReadShort(); //crc value (8 byte) long crc = buffer.ReadLong(); if (IsCrcEnabled) { int writeIndex = buffer.WriteIndex; buffer.WriteIndex = buffer.ReadIndex - (int)Lengths.Crc; buffer.WriteLong(0); buffer.WriteIndex = writeIndex; long calc = buffer.CalculateCrc(); if (crc != calc) { if (_allowStatistics) { _statistics.ErrorCrc(); } return; } } for (int i = 0; i < commandCount; i++) { IncomingCommand command = new IncomingCommand(buffer, currentTime, serverSentTime); if (command.IsReliable) { SendAckFromCommand(command); } if (command.Type == CommandType.Acknowledge) { AckHandler(command); } else { EnqueueRenderingQueue(() => ExecuteReceiveCommand(command)); } } if (_allowStatistics) { _statistics.ReceiveBytes(bufferCount, currentTime); _statistics.ReceiveMtu(serverSentTime); _statistics.ReceiveIncomingCommand(commandCount); } }
/// <summary> /// Connect to a remote server /// </summary> /// <param name="remoteEndPoint">Address information of a remote server</param> /// <returns></returns> public bool Connect(IPEndPoint remoteEndPoint) { if (_udpSocket != null && _udpSocket.State != SocketState.Disconnected) { _udpSocket.Dispose(); } _udpSocket = new UdpSocket(_connectionConfig.MtuSize, DisconnectTimeout); if (_connectionConfig.BindPortRange != null) { _udpSocket.SetBindPort(_connectionConfig.BindPortRange.StartPort, _connectionConfig.BindPortRange.EndPort); } _connectionBroker = new ConnectingBroker(_udpSocket, this); _udpSocket.SetBroker(_connectionBroker, SocketState.Connecting); _peerId = 0; _roundTripTime = new RoundTripTime(); ResetQueues(); RemoteEndPoint = remoteEndPoint; AvailableSpace = (uint)(MTU - (uint)Lengths.FragmentHeader - (uint)Lengths.MtuHeader); _udpBuffer = new byte[MTU]; _cipher.GenerateLocalKeys(); if (_udpSocket.Prepare(RemoteEndPoint)) { _isAckThreadRunning = true; if (_sendAckBackgroundThread != null) { _sendAckBackgroundThread.Abort(); } #if PERF TryToConnectAsync(); #else _sendAckBackgroundThread = new Thread(SendAckBackground); _sendAckBackgroundThread.Name = "SendAckThread"; _sendAckBackgroundThread.IsBackground = true; _sendAckBackgroundThread.Start(); #endif _udpSocket.Send(_connectionBroker.CreateConnectCommand( ChannelCount, MTU, DataSerializer.Version, DisconnectTimeout, IsCrcEnabled, _cipher.PublicKey, EnvironmentTimer.GetTickCount())); } else { if (_listener != null) { string message = string.Format("Fail to connect to [{0}]{1}:{2} - SocketState: {3}", remoteEndPoint.AddressFamily, remoteEndPoint.Address, remoteEndPoint.Port, _udpSocket.State); _listener.OnStatusChanged(StatusCode.FailedToConnect, message); } return(false); } return(true); }