Beispiel #1
0
		internal void Encode(NetConnection connection, NetBuffer intoBuffer)
		{
			if (m_type == NetMessageType.None)
				m_type = NetMessageType.User;
			intoBuffer.Write((byte)m_type, 3);
			switch(m_type)
			{
				case NetMessageType.UserFragmented:
				case NetMessageType.User:
				case NetMessageType.Acknowledge:
				case NetMessageType.AcknowledgeBitField:
					intoBuffer.Write((byte)m_sequenceChannel, 5); // encode channel
					intoBuffer.Write(m_sequenceNumber, 12); // encode sequence number
					break;
			}

			int byteLen = (m_buffer == null ? 0 : m_buffer.LengthBytes);

			if (m_type == NetMessageType.UserFragmented || m_type == NetMessageType.User || m_type == NetMessageType.Discovery || m_type == NetMessageType.Handshake)
				intoBuffer.Write(byteLen, 12); // encode length

			// encode payload
			if (byteLen > 0)
				intoBuffer.Write(m_buffer.Data, 0, byteLen);

			return;
		}
Beispiel #2
0
        internal int ExecuteSend(NetBuffer buffer, NetConnection connection, IPEndPoint remoteEP)
        {
            if (buffer.LengthBytes < 0)
            {
                Log.Warning("ExecuteSend passed 0 bytes to send");
                return 0;
            }

            #if DEBUG
            if (connection != null)
            {
                if (connection.Configuration.SimulateLagLoss && m_lagLoss != null)
                    return m_lagLoss.ExecuteSend(this, buffer, connection, remoteEP);
            }
            #endif
            // encrypt
            if (connection != null && connection.m_encryption.SymmetricEncryptionKeyBytes != null)
            {
                // Log.Debug("SEND: Encrypting packet using key: " + Convert.ToBase64String(connection.SymmetricEncryptionKey));
                connection.m_encryption.EncryptSymmetric(buffer);
            }

            try
            {
                int bytesSent = m_socket.SendTo(buffer.Data, 0, buffer.LengthBytes, SocketFlags.None, remoteEP);

                Debug.Assert(bytesSent == buffer.LengthBytes, "Ouch, sent partial UDP message?!");

                //Log.Verbose(string.Format(CultureInfo.InvariantCulture, "Sent {0} bytes to {1}", bytesSent, remoteEP));
                return bytesSent;
            }
            catch (SocketException sex)
            {
                if (sex.SocketErrorCode == SocketError.WouldBlock)
                {
                    // send buffer overflow?
            #if DEBUG
                    Log.Error("SocketException.WouldBlock thrown during sending; send buffer overflow? Increase buffer using NetAppConfiguration.SendBufferSize");
                    throw new NetException("SocketException.WouldBlock thrown during sending; send buffer overflow? Increase buffer using NetAppConfiguration.SendBufferSize", sex);
            #else
                    // let reliability handle it, but log warning
                    Log.Warning("Network send buffer overflow");
            #endif
                }

                if (sex.SocketErrorCode == SocketError.ConnectionReset ||
                    sex.SocketErrorCode == SocketError.ConnectionRefused ||
                    sex.SocketErrorCode == SocketError.ConnectionAborted)
                {
                    Log.Warning("Remote socket forcefully closed: " + sex.SocketErrorCode);
                    if (connection != null)
                        connection.Disconnect("Socket forcefully closed: " + sex.SocketErrorCode);
                    return 0;
                }

                Log.Warning("Execute SocketException: " + sex.SocketErrorCode);
                return 0;
            }
        }
		public int ExecuteSend(NetBase netBase, NetBuffer buffer, NetConnection connection, IPEndPoint remoteEP)
		{
			int len = buffer.LengthBytes;
#if DEBUG
			if (connection != null)
			{
				NetConnectionConfiguration config = connection.Configuration;

				if (config.LossChance > 0.0f && NetRandom.Default.Chance(config.LossChance))
				{
					//m_log.Debug("(simulating loss of sent packet)");
					return len;
				}
				
				if (config.LagDelayChance > 0.0f && NetRandom.Default.Chance(config.LagDelayChance))
				{
					float delayAmount = config.LagDelayMinimum + (NetRandom.Default.NextFloat() * config.LagDelayVariance);

					DelayedPacket pk = new DelayedPacket();
					pk.Data = new byte[len];
					Array.Copy(buffer.Data, pk.Data, buffer.LengthBytes);
					pk.DelayAmount = delayAmount;
					pk.DelayedUntil = NetTime.Now + delayAmount;
					pk.RemoteEP = remoteEP;
					m_delayed.Add(pk);

					//m_log.Debug("(queueing packet for " + (int)(pk.DelayAmount * 1000.0f) + " ms)");

					return len;
				}
			}
#endif

			try
			{
				int bytesSent = netBase.m_socket.SendTo(buffer.Data, 0, len, SocketFlags.None, remoteEP);
				m_log.Verbose(string.Format(CultureInfo.InvariantCulture, "Sent {0} bytes to {1}", bytesSent, remoteEP));

#if DEBUG
				if (connection != null)
				{
					NetConnectionConfiguration config = connection.Configuration;
					if (NetRandom.Default.Chance(config.DuplicatedPacketChance))
					{
						m_log.Debug("(simulating send packet duplication)");
						netBase.m_socket.SendTo(buffer.Data, 0, buffer.LengthBytes, SocketFlags.None, remoteEP);
					}
				}
#endif

				return bytesSent;
			}
			catch (SocketException sex)
			{
				if (sex.SocketErrorCode == SocketError.ConnectionReset ||
					sex.SocketErrorCode == SocketError.ConnectionRefused ||
					sex.SocketErrorCode == SocketError.ConnectionAborted)
				{
					m_log.Warning("Remote socket forcefully closed: " + sex.SocketErrorCode);
					if (connection != null)
						connection.Disconnect("Socket forcefully closed: " + sex.SocketErrorCode);
					return 0;
				}

				m_log.Warning("Execute SocketException: " + sex.SocketErrorCode);
				return 0;
			}
		}
Beispiel #4
0
 /// <summary>
 /// Create a net message
 /// </summary>
 public NetMessage()
 {
     m_type = NetMessageType.User;
     System.Diagnostics.Debug.Assert(NetBase.CurrentContext != null, "No network context; create a NetClient or NetServer first");
     m_buffer = new NetBuffer(NetBase.CurrentContext.Configuration.DefaultNetMessageBufferSize);
 }
Beispiel #5
0
        protected void InitBase(NetAppConfiguration config, NetLog log)
        {
            if (config == null)
                throw new ArgumentNullException("config");

            if (log == null)
                throw new ArgumentNullException("log");

            IsLittleEndian = BitConverter.IsLittleEndian;
            //if (BitConverter.IsLittleEndian)
            BitWriter = new LittleEndianBitWriter();
            //else
            //	BitWriter = new BigEndianBitWriter();

            Configuration = config;
            Log = log;

            Configuration.m_isLocked = true; // prevent changes

            // validate config
            if (config.ApplicationIdentifier == NetConstants.DefaultApplicationIdentifier)
                log.Error("Warning! ApplicationIdentifier not set in configuration!");

            if (this is NetServer)
            {
                if (config.MaximumConnections == -1)
                    throw new ArgumentException("MaximumConnections must be set in configuration!");
                if (config.ServerName == NetConstants.DefaultServerName)
                    log.Warning("Warning! Server name not set!");
            }

            // create buffers
            m_sendBuffer = new NetBuffer(config.SendBufferSize);
            m_receiveBuffer = new NetBuffer(config.ReceiveBufferSize);

            // Bind to port
            try
            {
                IPEndPoint iep = new IPEndPoint(IPAddress.Any, config.Port);
                EndPoint ep = (EndPoint)iep;

                m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                m_socket.Blocking = false;
                m_socket.Bind(ep);
                if (iep.Port != 0)
                    Log.Info("Bound to port " + iep.Port);
            }
            catch (SocketException sex)
            {
                if (sex.SocketErrorCode != SocketError.AddressAlreadyInUse)
                    throw new NetException("Failed to bind to port " + config.Port + " - Address already in use!", sex);
            }
            catch (Exception ex)
            {
                throw new NetException("Failed to bind to port " + config.Port, ex);
            }

            m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, config.ReceiveBufferSize);
            m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, config.SendBufferSize);

            m_senderRemote = (EndPoint)new IPEndPoint(IPAddress.Any, 0);
            #if DEBUG
            m_lagLoss = new NetLogLossInducer(log);
            #endif

            return;
        }
Beispiel #6
0
		internal NetMessage(NetMessageType tp, int initialCapacity)
		{
			m_type = tp;
			m_buffer = new NetBuffer(initialCapacity);
		}
Beispiel #7
0
		/// <summary>
		/// Create a message with specified initial capacity in bytes
		/// </summary>
		public NetMessage(int initialCapacity)
		{
			m_type = NetMessageType.User;
			m_buffer = new NetBuffer(initialCapacity);
		}
		/// <summary> 
		/// Decrypt using XTEA algo and verify CRC
		/// </summary>
		/// <returns>true for success, false for failure</returns>
		internal bool DecryptSymmetric(NetBuffer buffer)
		{
			int bufLen = buffer.LengthBytes;

			if (bufLen % 8 != 0)
			{
				if (NetBase.CurrentContext != null && NetBase.CurrentContext.Log != null)
					NetBase.CurrentContext.Log.Info("Bad buffer size in DecryptSymmetricInPlace()");
				return false;
			}

			//NetBase.CurrentContext.Log.Debug.Debug("Decrypting using key: " + Convert.ToBase64String(m_xtea.Key));

			// decrypt
			for (int i = 0; i < bufLen; i += 8)
				m_xtea.DecryptBlock(buffer.Data, i, buffer.Data, i);

			int numPadBits = buffer.Data[bufLen - 1];
			buffer.Data[bufLen - 1] = 0; // zap for correct crc calculation
			int dataBits = (bufLen * 8) - (24 + numPadBits); // include pad and crc

			buffer.ResetReadPointer(dataBits);
			ushort statedCrc = buffer.ReadUInt16();

			// zap crc to be able to compare
			buffer.ResetWritePointer(dataBits);
			buffer.Write((ushort)0);

			ushort dataCrc = Checksum.Adler16(buffer.Data, 0, bufLen);

			//NetBase.CurrentContext.Log.Debug("Plain (len " + bufLen + "): " + Convert.ToBase64String(buffer.Data, 0, bufLen) + " Stated CRC: " + statedCrc + " Calc: " + realCrc);
			if (statedCrc != dataCrc)
			{
				if (NetBase.CurrentContext != null && NetBase.CurrentContext.Log != null)
					NetBase.CurrentContext.Log.Warning("CRC failure; expected " + dataCrc + " found " + statedCrc + " dropping packet!");
				return false;
			}

			// clean up
			buffer.LengthBits = dataBits;
			buffer.ResetReadPointer();

			return true;
		}
		public static bool SimpleUnitTest()
		{
			// encryption test
			NetEncryption enc = new NetEncryption();
			byte[] key = new byte[16];
			NetRandom.Default.NextBytes(key);
			enc.SetSymmetricKey(key);

			byte[] data = Encoding.ASCII.GetBytes("Michael"); // 7 bytes
			byte[] correct = new byte[data.Length];
			data.CopyTo(correct, 0);

			NetBuffer buf = new NetBuffer(data);

			enc.EncryptSymmetric(buf);

			bool ok = enc.DecryptSymmetric(buf);
			if (!ok)
				return false;

			// compare
			if (buf.LengthBytes != correct.Length)
				return false;

			for (int i = 0; i < correct.Length; i++)
				if (buf.Data[i] != correct[i])
					return false;

			return true;
		}
Beispiel #10
0
 internal NetMessage(NetBuffer reuseBuffer)
 {
     m_buffer = reuseBuffer;
 }
		/// <summary>
		/// Append a CRC checksum and encrypt data in place using XTEA
		/// </summary>
		internal void EncryptSymmetric(NetBuffer buffer)
		{
			//string plain = Convert.ToBase64String(buffer.Data, 0, buffer.LengthBytes);
			int bufferLen = buffer.LengthBytes;

			// calculate number of pad bits
			int dataBits = buffer.LengthBits;
			int bitsNeeded = dataBits + 24; // 24 extra for crc and num-pad-bits
			int totalBits = bitsNeeded + (64 - (bitsNeeded % 64));
			int padBits = totalBits - bitsNeeded;

			// write to ensure zeroes in buffer (crc and num-pad-bits space)
			buffer.Write((uint)0, 24);

			if (padBits > 0)
				buffer.Write((ulong)0, padBits);
			int writePadBitsPosition = buffer.LengthBits - 8;

			// write crc
			ushort crc = Checksum.Adler16(buffer.Data, 0, buffer.LengthBytes);
			buffer.ResetWritePointer(dataBits);
			buffer.Write(crc);

			// write num-pad-bits in LAST byte
			buffer.ResetWritePointer(writePadBitsPosition);
			buffer.Write((byte)padBits);

			// encrypt in place
			int ptr = 0;
			bufferLen = buffer.LengthBytes;
			while (ptr < bufferLen)
			{
				m_xtea.EncryptBlock(buffer.Data, ptr, buffer.Data, ptr);
				ptr += 8;
			}

			return;
		}
Beispiel #12
0
 /// <summary>
 /// Create a message with specified initial capacity in bytes
 /// </summary>
 public NetMessage(int initialCapacity)
 {
     m_type   = NetMessageType.User;
     m_buffer = new NetBuffer(initialCapacity);
 }
Beispiel #13
0
 internal NetMessage(NetMessageType tp, byte[] payload)
 {
     m_type   = tp;
     m_buffer = new NetBuffer(payload);
 }
Beispiel #14
0
 internal NetMessage(NetMessageType tp, int initialCapacity)
 {
     m_type   = tp;
     m_buffer = new NetBuffer(initialCapacity);
 }
Beispiel #15
0
		internal static NetMessage Decode(NetBuffer buffer)
		{
			try
			{
				NetMessage retval = new NetMessage(true);

				NetMessageType type = (NetMessageType)buffer.ReadByte(3);
				retval.m_type = type;

				switch (type)
				{
					case NetMessageType.None:
						// packet padding (due to encryption); we've reached the end
						return null;
					case NetMessageType.User:
					case NetMessageType.UserFragmented:
					case NetMessageType.Acknowledge:
					case NetMessageType.AcknowledgeBitField:
						retval.m_sequenceChannel = (NetChannel)buffer.ReadByte(5);
						retval.m_sequenceNumber = (ushort)buffer.ReadUInt32(12);
						break;
				}

				int msgLen = 0;
				switch (type)
				{
					case NetMessageType.User:
					case NetMessageType.UserFragmented:
						msgLen = (int)buffer.ReadUInt32(12);
						break;
					case NetMessageType.Acknowledge:
						msgLen = 0;
						break;
					case NetMessageType.AcknowledgeBitField:
						msgLen = 4;
						break;
					case NetMessageType.Discovery:
						msgLen = (int)buffer.ReadUInt32(12);
						break;
					case NetMessageType.Handshake:
						msgLen = (int)buffer.ReadUInt32(12);
						break;
					case NetMessageType.PingPong:
						msgLen = 3;
						break;
				}

				byte[] payload = null;
				if (msgLen > 0)
					payload = buffer.ReadBytes(msgLen);
				retval.m_buffer = new NetBuffer(payload);

				return retval;
			}
			catch
			{
				NetBase.CurrentContext.Log.Warning("Failed to decode NetMessage from buffer!");
				return null;
			}
		}
Beispiel #16
0
		internal override void HandlePacket(NetBuffer buffer, int bytesReceived, IPEndPoint senderEndpoint)
		{
			double now = NetTime.Now;
			NetConnection sender = FindConnection(senderEndpoint);
			if (sender != null)
			{
				sender.m_lastHeardFromRemote = now;

				if (sender.m_encryption.SymmetricEncryptionKeyBytes != null)
				{
					bool ok = sender.m_encryption.DecryptSymmetric(buffer);
					if (!ok)
					{
						Log.Warning("Failed to decrypt packet from client " + sender);
						return;
					}
				}
			}

			try
			{
				NetMessage response;
				int messagesReceived = 0;
				int usrMessagesReceived = 0;
				int ackMessagesReceived = 0;
				while (buffer.ReadBitsLeft > 7)
				{
					NetMessage msg = NetMessage.Decode(buffer);
					if (msg == null)
						break; // done
				
					messagesReceived++;
					msg.Sender = sender;
					switch (msg.m_type)
					{
						case NetMessageType.Acknowledge:
						case NetMessageType.AcknowledgeBitField:
							if (sender == null)
							{
								Log.Warning("Received Ack from not-connected source!");
							}
							else
							{
								//Log.Debug("Received ack " + msg.SequenceChannel + "|" + msg.SequenceNumber);
								sender.ReceiveAcknowledge(msg);
								ackMessagesReceived++;
							}
							break;
						case NetMessageType.Handshake:
							NetHandshakeType tp = (NetHandshakeType)msg.ReadByte();
							if (tp == NetHandshakeType.ConnectResponse)
							{
								Log.Warning("Received ConnectResponse?!");
							}
							else if (tp == NetHandshakeType.Connect)
							{
								if (sender == null)
								{
									NetHandshake.HandleConnect(msg, this, senderEndpoint);
								}
								else
								{
									// resend response
									NetHandshake.SendConnectResponse(this, sender, senderEndpoint);
									Log.Verbose("Redundant Connect received; resending response");
								}
							}
							else if (tp == NetHandshakeType.ConnectionEstablished)
							{
								if (sender == null)
								{
									Log.Warning("Received ConnectionEstablished, but no sender connection?!");
								}
								else
								{
									float rt = (float)(now - sender.m_firstSentHandshake);
									sender.m_ping.Initialize(rt);

									ushort remoteValue = msg.ReadUInt16();
									sender.RemoteClockOffset = NetTime.CalculateOffset(now, remoteValue, rt);
									Log.Verbose("Reinitializing remote clock offset to " + sender.RemoteClockOffset + " ms (roundtrip " + NetUtil.SecToMil(rt) + " ms)");

									if (sender.Status == NetConnectionStatus.Connected)
									{
										Log.Verbose("Redundant ConnectionEstablished received");
									}
									else
									{
										Log.Debug("Connection established");
										sender.SetStatus(NetConnectionStatus.Connected, "Connected by established");
									}
								}
							}
							else
							{
								// disconnected
								if (sender == null)
								{
									Log.Warning("Disconnected received from unconnected source: " + senderEndpoint);
									return;
								}
								string reason = msg.ReadString();
								sender.Disconnected(reason);
							}
							break;
						case NetMessageType.Discovery:
							Log.Debug("Answering discovery response from " + senderEndpoint);
							response = NetDiscovery.EncodeResponse(this);
							SendSingleMessageAtOnce(response, null, senderEndpoint);
							break;
						case NetMessageType.PingPong:
							
							if (sender == null)
								return;

							bool isPong = msg.ReadBoolean();
							bool isOptimizeInfo = msg.ReadBoolean();
							if (isOptimizeInfo)
							{
								// DON'T handle optimizeinfo... only clients should adapt to server ping info
							} else if (isPong)
							{
								if (sender.Status == NetConnectionStatus.Connected)
									sender.m_ping.HandlePong(now, msg);
							}
							else
							{
								NetPing.ReplyPong(msg, sender); // send pong
							}
							break;
						case NetMessageType.User:
						case NetMessageType.UserFragmented:
							usrMessagesReceived++;
							if (sender == null)
							{
								Log.Warning("User message received from unconnected source: " + senderEndpoint);
								return; // don't handle user messages from unconnected sources
							}
							if (sender.Status == NetConnectionStatus.Connecting)
								sender.SetStatus(NetConnectionStatus.Connected, "Connected by user message");
							sender.ReceiveMessage(now, msg);
							break;
						default:
							Log.Warning("Bad message type: " + msg);
							break;
					}
				}

				if (sender != null)
				{
					NetStatistics stats = sender.Statistics;
					stats.PacketsReceived++;
					stats.MessagesReceived += messagesReceived;
					stats.UserMessagesReceived += usrMessagesReceived;
					stats.AckMessagesReceived += ackMessagesReceived;
					stats.BytesReceived += bytesReceived;
				}
			}
			catch (Exception ex)
			{
				Log.Error("Failed to parse packet correctly; read/write mismatch? " + ex);
			}
		}
Beispiel #17
0
		/// <summary>
		/// Create a net message
		/// </summary>
		public NetMessage()
		{
			m_type = NetMessageType.User;
			System.Diagnostics.Debug.Assert(NetBase.CurrentContext != null, "No network context; create a NetClient or NetServer first");
			m_buffer = new NetBuffer(NetBase.CurrentContext.Configuration.DefaultNetMessageBufferSize);
		}
Beispiel #18
0
        internal override void HandlePacket(NetBuffer buffer, int bytesReceived, IPEndPoint sender)
        {
            double now = NetTime.Now;
            try
            {
                NetMessage msg;
                if (m_serverConnection == null || m_serverConnection.Status == NetConnectionStatus.Disconnected)
                {
                    //
                    // unconnected packet
                    //
                    msg = NetMessage.Decode(buffer);
                    if (msg == null)
                    {
                        Log.Warning("Malformed NetMessage?");
                        return; // malformed?
                    }

                    Log.Verbose("Received unconnected message: " + msg);

                    // discovery response?
                    if (msg.m_type == NetMessageType.Discovery)
                    {
                        NetServerInfo info = NetDiscovery.DecodeResponse(msg, sender);
                        if (ServerDiscovered != null)
                            ServerDiscovered(this, new NetServerDiscoveredEventArgs(info));
                        return;
                    }

                    if (m_serverConnection != null && sender.Equals(m_serverConnection.RemoteEndpoint))
                    {
                        // we have m_serverConnection, but status is disconnected
                        Log.Warning("Received " + buffer.LengthBytes + " from server; but we're disconnected!");
                        return;
                    }

                    Log.Warning("Received " + buffer.LengthBytes + " bytes from non-server source: " + sender + "(server is " + m_serverConnection.RemoteEndpoint + ")");
                    return;
                }

                // decrypt in place
                if (m_serverConnection.m_encryption.SymmetricEncryptionKeyBytes != null)
                {
                    byte[] savedBuffer = null;
                    if (m_serverConnection.Status == NetConnectionStatus.Connecting)
                    {
                        // special case; save buffer in case we get unencrypted response
                        savedBuffer = new byte[buffer.LengthBytes];
                        Array.Copy(buffer.Data, 0, savedBuffer, 0, buffer.LengthBytes);
                    }

                    bool ok = m_serverConnection.m_encryption.DecryptSymmetric(buffer);
                    if (!ok)
                    {
                        // failed to decrypt; drop this packet UNLESS we're in a connecting state,
                        // in which case the server may want to tell us something
                        if (m_serverConnection.Status == NetConnectionStatus.Connecting)
                        {
                            // ok let this one thru unencrypted
                            Array.Copy(savedBuffer, buffer.Data, savedBuffer.Length);
                        }
                        else
                        {
                            Log.Warning("Failed to decrypt packet from server!");
                            return;
                        }
                    }
                }

                m_serverConnection.m_lastHeardFromRemote = now;

                int messagesReceived = 0;
                int usrMessagesReceived = 0;
                int ackMessagesReceived = 0;
                while (buffer.ReadBitsLeft > 7)
                {
                    msg = NetMessage.Decode(buffer);

                    if (msg == null)
                        break; // done
                    messagesReceived++;
                    msg.Sender = m_serverConnection;
                    switch (msg.m_type)
                    {
                        case NetMessageType.Handshake:
                            NetHandshakeType tp = (NetHandshakeType)msg.ReadByte();
                            if (tp == NetHandshakeType.Connect || tp == NetHandshakeType.ConnectionEstablished)
                            {
                                Log.Warning("Client received " + tp + "?!");
                            }
                            else if (tp == NetHandshakeType.ConnectResponse)
                            {
                                if (m_serverConnection.Status != NetConnectionStatus.Connecting)
                                {
                                    Log.Verbose("Received redundant ConnectResponse!");
                                    break;
                                }
                                // Log.Debug("ConnectResponse received");
                                m_serverConnection.SetStatus(NetConnectionStatus.Connected, "Connected");
                                Log.Info("Connected to " + m_serverConnection.RemoteEndpoint);

                                // initialize ping to now - m_firstSentConnect
                                float initRoundtrip = (float)(now - m_serverConnection.m_firstSentHandshake);
                                m_serverConnection.m_ping.Initialize(initRoundtrip);

                                ushort remoteValue = msg.ReadUInt16();
                                m_serverConnection.RemoteClockOffset = NetTime.CalculateOffset(now, remoteValue, initRoundtrip);
                                Log.Verbose("Initializing remote clock offset to " + m_serverConnection.RemoteClockOffset + " ms (roundtrip " + NetUtil.SecToMil(initRoundtrip) + " ms)");

                                NetMessage established = new NetMessage(NetMessageType.Handshake, 3);
                                established.Write((byte)NetHandshakeType.ConnectionEstablished);
                                established.WriteSendStamp();
                                SendSingleMessageAtOnce(established, m_serverConnection, m_serverConnection.RemoteEndpoint);
                            }
                            else
                            { // Disconnected
                                string reason = msg.ReadString();
                                m_serverConnection.SetStatus(NetConnectionStatus.Disconnected, reason);
                            }
                            break;
                        case NetMessageType.Acknowledge:
                            //Log.Debug("Received ack " + msg.SequenceChannel + "|" + msg.SequenceNumber);
                            m_serverConnection.ReceiveAcknowledge(msg);
                            ackMessagesReceived++;
                            break;

                        case NetMessageType.PingPong:
                            bool isPong = msg.ReadBoolean();
                            bool isOptimizeInfo = msg.ReadBoolean();
                            if (isOptimizeInfo)
                            {
                                m_serverConnection.m_ping.HandleOptimizeInfo(now, msg);
                            } else if (isPong)
                            {
                                if (m_serverConnection.Status == NetConnectionStatus.Connected)
                                    m_serverConnection.m_ping.HandlePong(now, msg);
                            }
                            else
                            {
                                NetPing.ReplyPong(msg, m_serverConnection);
                            }
                            break;
                        case NetMessageType.User:
                        case NetMessageType.UserFragmented:
                            //Log.Debug("User message received; " + msg.m_buffer.LengthBytes + " bytes");
                            m_serverConnection.ReceiveMessage(now, msg);
                            usrMessagesReceived++;
                            break;
                        case NetMessageType.Discovery:
                            NetServerInfo info = NetDiscovery.DecodeResponse(msg, sender);
                            if (ServerDiscovered != null)
                                ServerDiscovered(this, new NetServerDiscoveredEventArgs(info));
                            break;
                        default:
                            Log.Warning("Client received " + msg.m_type + "?!");
                            break;
                    }
                }

                // add statistics
                NetStatistics stats = m_serverConnection.Statistics;
                stats.PacketsReceived++;
                stats.MessagesReceived += messagesReceived;
                stats.UserMessagesReceived += usrMessagesReceived;
                stats.AckMessagesReceived += ackMessagesReceived;
                stats.BytesReceived += bytesReceived;
            }
            catch (Exception ex)
            {
                Log.Error("Failed to parse packet correctly; read/write mismatch? " + ex);
            }
        }
Beispiel #19
0
		internal NetMessage(NetMessageType tp, byte[] payload)
		{
			m_type = tp;
			m_buffer = new NetBuffer(payload);
		}
Beispiel #20
0
 internal abstract void HandlePacket(NetBuffer buffer, int bytesReceived, IPEndPoint sender);
Beispiel #21
0
		internal NetMessage(NetBuffer reuseBuffer)
		{
			m_buffer = reuseBuffer;
		}
Beispiel #22
0
        internal static NetMessage Decode(NetBuffer buffer)
        {
            try
            {
                NetMessage retval = new NetMessage(true);

                NetMessageType type = (NetMessageType)buffer.ReadByte(3);
                retval.m_type = type;

                switch (type)
                {
                case NetMessageType.None:
                    // packet padding (due to encryption); we've reached the end
                    return(null);

                case NetMessageType.User:
                case NetMessageType.UserFragmented:
                case NetMessageType.Acknowledge:
                case NetMessageType.AcknowledgeBitField:
                    retval.m_sequenceChannel = (NetChannel)buffer.ReadByte(5);
                    retval.m_sequenceNumber  = (ushort)buffer.ReadUInt32(12);
                    break;
                }

                int msgLen = 0;
                switch (type)
                {
                case NetMessageType.User:
                case NetMessageType.UserFragmented:
                    msgLen = (int)buffer.ReadUInt32(12);
                    break;

                case NetMessageType.Acknowledge:
                    msgLen = 0;
                    break;

                case NetMessageType.AcknowledgeBitField:
                    msgLen = 4;
                    break;

                case NetMessageType.Discovery:
                    msgLen = (int)buffer.ReadUInt32(12);
                    break;

                case NetMessageType.Handshake:
                    msgLen = (int)buffer.ReadUInt32(12);
                    break;

                case NetMessageType.PingPong:
                    msgLen = 3;
                    break;
                }

                byte[] payload = null;
                if (msgLen > 0)
                {
                    payload = buffer.ReadBytes(msgLen);
                }
                retval.m_buffer = new NetBuffer(payload);

                return(retval);
            }
            catch
            {
                NetBase.CurrentContext.Log.Warning("Failed to decode NetMessage from buffer!");
                return(null);
            }
        }