public NetConnectionConfiguration(NetConnection forConnection) { if (forConnection == null) throw new ArgumentNullException("forConnection"); m_forConnection = forConnection; forConnection.Configuration = this; ConnectionTimeOut = NetConnectionConfiguration.DefaultConnectionTimeOut; AveragePingSamples = 5; PingFrequency = NetConnectionConfiguration.DefaultPingFrequency; m_currentOptimization = NetOptimization.EmphasizeBandwidth; ThrottleBytesPerSecond = NetConnectionConfiguration.DefaultThrottleBytesPerSecond; // default lag/loss/dupe settings SimulateLagLoss = false; LossChance = 0.05f; LagDelayChance = 1.0f; LagDelayMinimum = 0.1f; LagDelayVariance = 0.05f; DuplicatedPacketChance = 0.01f; // reliability OptimizeSettings(m_currentOptimization, 0.1f, true); // assume 100ms roundtrip for starters }
public NetPing(NetConnection forConnection) { m_connection = forConnection; m_samples = new float[6]; Initialize(20.0f); // 50 ms m_lastSentPing = NetTime.Now; }
public void AddPlayer(PlayerCarac carac, ActorRTInfo info, NetConnection co) { // Container creation Player player = new Player(); player.Carac = carac; player.Info = info; if (co != null) { player.Connection = co; co.Tag = carac.ActorID; } player.score = new PlayerScore(); // And finally add it to our list List.Add(player.Carac.ActorID, player); }
// Create a player from a partially constructed PlayerCarac and return its ID public int CreatePlayer(PlayerCarac carac, NetConnection co) { carac.AssignID(); ActorRTInfo info = new ActorRTInfo(); // Set Physical infos info.Health = carac.HealthCap = 100; info.Mana = carac.ManaCap = 100; info.Weapon = 1; // Set position info info.Position = 1.0f; info.Velocity = 0.0f; // And add the player AddPlayer(carac, info, co); return carac.ActorID; }
internal static int SendDisconnected(NetBase netBase, string reason, NetConnection connection) { NetMessage bye = new NetMessage(NetMessageType.Handshake, reason.Length + 3); bye.Write((byte)NetHandshakeType.Disconnected); bye.Write(reason); return netBase.SendSingleMessageAtOnce(bye, connection, connection.RemoteEndpoint); }
internal static int SendConnectResponse(NetBase netBase, NetConnection clientConnection, IPEndPoint remoteEndpoint) { double now = NetTime.Now; ushort nowEnc = NetTime.Encoded(now); NetMessage response = new NetMessage(NetMessageType.Handshake, 3); response.Write((byte)NetHandshakeType.ConnectResponse); response.Write(nowEnc); clientConnection.m_firstSentHandshake = now; clientConnection.m_lastSentHandshake = now; return netBase.SendSingleMessageAtOnce(response, clientConnection, remoteEndpoint); }
public static int GetPlayerID(NetConnection co) { return (int)co.Tag; }
private void SendGameState(NetConnection Conn) { GameState++; NetMessage msg = new NetMessage(); string Message = "P" + Player.Location.X + "," + Player.Location.Y; Message = Message + "P"; foreach (Zombie Zombie in Zombies) { Message = Message + "Z" + Zombie.Location.X + "," + Zombie.Location.Y; } Message = Message + "P"; foreach (Bullet Bullet in Bullets) { Message = Message + "B" + Bullet.Location.X + "," + Bullet.Location.Y; } msg.Write(Message); //Sending the packet in Reliable is okay for this because its //one packet, When sending lots and lots of data you need to //set this to Unreliable. This will garentee it arrives but //not in a sepcific order. server.SendMessage(msg, Conn, NetChannel.Unreliable); }
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; }
protected void HdlMsgReBroadcast(BBMessage msg, NetConnection sender) { int id = PlayerList.GetPlayerID(sender); //if (msg.MsgType == BBMsgType.CHAT) // Log.Info("Chat " + id + " : " + msg.Param1); // Set the id of the message sender msg.ActorInfo = new ActorRTInfo(); msg.ActorInfo.Id = id; // And broadcast this message Server.Broadcast(msg.GetNetMessage(), NetChannel.ReliableUnordered); }
private void HdlMsgShoot(BBMessage msg, NetConnection sender) { int id = PlayerList.GetPlayerID(sender); if (msg.MsgType == BBMsgType.ACTOR_SHOOT) { Log.Info("Shoot from " + id + " to " + msg.Shoot.Cible_ID); ++PList.GetPlayer(id).score.Shots; } else if (msg.MsgType == BBMsgType.ACTOR_SHOOT_RESPONSE) { Log.Info("Shoot response from " + id + " - shooter: " + msg.Resp.SenderID + ". result : " + msg.Resp.ShootResponse.ToString()); if (msg.Resp.ShootResponse == ShootResponseDesc.Response.AVOIDED || msg.Resp.ShootResponse == ShootResponseDesc.Response.COUNTERED) { ++PList.GetPlayer(id).score.Hit; } else if (msg.Resp.ShootResponse == ShootResponseDesc.Response.TAKEN) { ++PList.GetPlayer(id).score.Hit; ++PList.GetPlayer(id).score.Deaths; ++PList.GetPlayer(msg.Resp.SenderID).score.Kills; } } // Set the id of the message sender msg.ActorInfo = new ActorRTInfo(); msg.ActorInfo.Id = id; // And broadcast this message Server.Broadcast(msg.GetNetMessage(), NetChannel.ReliableUnordered); }
/// <summary> /// Remove connection from Connections list(s) /// </summary> internal void RemoveConnection(NetConnection conn) { if (conn == null) return; Log.Debug("Removing connection " + conn); for(int i=0;i<Connections.Length;i++) if (Connections[i] == conn) Connections[i] = null; // also remove lookup entry int hash = conn.RemoteEndpoint.GetHashCode(); if (m_connectionsLookUpTable.ContainsKey(hash)) m_connectionsLookUpTable.Remove(hash); }
/// <summary> /// Broadcasts a message to all connections except specified; should NOT be used for /// messages which uses the string table read/write methods! /// </summary> public int Broadcast(NetMessage msg, NetChannel channel, NetConnection except) { int numSentTo = 0; bool originalSent = false; foreach (NetConnection conn in Connections) { if (conn == null || conn == except || (conn.Status != NetConnectionStatus.Connected && conn.Status != NetConnectionStatus.Reconnecting)) continue; numSentTo++; if (!originalSent) { // send original conn.SendMessage(msg, channel); originalSent = true; } else { // send refcloned message NetMessage clone = NetMessage.CreateReferenceClone(msg); conn.SendMessage(clone, channel); numSentTo++; } } return numSentTo; }
/// <summary> /// Sends a message to a certain connection using the channel specified /// </summary> public bool SendMessage(NetMessage msg, NetConnection connection, NetChannel channel) { if (connection == null) throw new ArgumentNullException("connection"); if (connection.Status == NetConnectionStatus.Disconnected) { Log.Warning("SendMessage failed - Connection is Disconnected!"); return false; } connection.SendMessage(msg, channel); return true; }
internal NetConnection AddConnection(IPEndPoint remoteEndpoint, int remoteClockOffset) { // find empty slot for (int i = 0; i < Connections.Length; i++) { if (Connections[i] == null) { NetConnection conn = new NetConnection(this, remoteEndpoint); conn.RemoteClockOffset = remoteClockOffset; Log.Verbose("Initializing remote clock offset to " + remoteClockOffset + " ms"); conn.m_firstSentHandshake = NetTime.Now; conn.m_lastSentHandshake = conn.m_firstSentHandshake; int hash = remoteEndpoint.GetHashCode(); NetConnection existingConn; if (m_connectionsLookUpTable.TryGetValue(hash, out existingConn)) { if (existingConn.Status != NetConnectionStatus.Disconnected) throw new NetException("Ack thphth; Connections lookup hash value taken!"); // disconnected; just remove it RemoveConnection(existingConn); } Connections[i] = conn; m_connectionsLookUpTable[hash] = conn; conn.SetStatus(NetConnectionStatus.Connecting, "Connecting from " + remoteEndpoint); return conn; } } Log.Warning("Failed to add new connection!"); return null; }
private NetPlayer GetPlayer(NetConnection nc) { for (int i = 0; i < m_players.Count; i++) { NetPlayer tmp = m_players[i]; if (nc == tmp.PlayerConnection) return tmp; } return null; }
/// <summary> /// Sends the given message with the given UDP delivery type to the targetConnection /// </summary> /// <param name="message">The message to be send</param> /// <param name="deliveryType">The UDP delivery type</param> /// <param name="targetConnection">The target connection</param> public void SendMessage(SpiderMessage message, NetChannel deliveryType, NetConnection targetConnection) { NetMessage msg = new NetMessage(); msg.Write(message.ToByteArray()); spiderNet.SendMessage(msg, targetConnection, deliveryType); }
/// <summary> /// Connects to a server /// </summary> public bool Connect(IPAddress address, int port, byte[] customData) { if (m_serverConnection != null && m_serverConnection.Status != NetConnectionStatus.Disconnected) m_serverConnection.Disconnect("Reconnecting"); IPEndPoint remoteIP = new IPEndPoint(address, port); m_serverConnection = new NetConnection(this, remoteIP); string remoteHost = remoteIP.ToString(); Log.Info("Connecting to " + remoteHost); m_serverConnection.m_firstSentHandshake = NetTime.Now; m_serverConnection.m_lastSentHandshake = m_serverConnection.m_firstSentHandshake; m_serverConnection.SetStatus(NetConnectionStatus.Connecting, "Connecting"); // save custom data for repeat connect requests if (customData != null) { m_serverConnection.m_savedConnectCustomData = new byte[customData.Length]; Array.Copy(customData, m_serverConnection.m_savedConnectCustomData, customData.Length); } int bytesSent = NetHandshake.SendConnect(this, remoteIP, customData); // account for connect packet m_serverConnection.Statistics.PacketsSent++; m_serverConnection.Statistics.MessagesSent++; m_serverConnection.Statistics.BytesSent += bytesSent; return true; }
public void HandleMessage(BBMessage msg, NetConnection sender) { switch (msg.MsgType) { case BBMsgType.ASK_LOGIN: HdlLogin(msg, sender); break; case BBMsgType.PRIVATE_MESSAGE: case BBMsgType.PRIVATE_CONVERSATION: case BBMsgType.JOIN_CONVERSATION: case BBMsgType.LEAVE_CONVERSATION: case BBMsgType.CHAT: case BBMsgType.VDM: case BBMsgType.PENDU: case BBMsgType.BASH: case BBMsgType.TYPING_MSG: case BBMsgType.KNOCK: HdlMsgReBroadcast(msg, sender); break; case BBMsgType.COFFEE: HdlMsgReBroadcast(msg, sender); break; case BBMsgType.EAT: HdlMsgReBroadcast(msg, sender); break; case BBMsgType.ACTOR_SHOOT: HdlMsgShoot(msg, sender); break; case BBMsgType.ACTOR_SHOOT_RESPONSE: HdlMsgShoot(msg, sender); break; default: Log.Warning("Received unknown message"); break; } }
internal void NotifyStatusChange(NetConnection conn, NetConnectionStatus previousStatus, string reason) { if (StatusChanged != null) { NetStatusEventArgs e = new NetStatusEventArgs(); e.PreviousStatus = previousStatus; e.Connection = conn; e.Reason = reason; StatusChanged(this, e); } }
protected void HdlLogin(BBMessage msg, NetConnection sender) { // Test if login is possible if (PList.GetPlayer(msg.PlayerCarac.Nick, null) != null) { // No : player already exists BBMessage msg_back = new BBMessage(); msg_back.MsgNoLogin("Player \"" + msg.PlayerCarac.Nick + "\" already exists"); Server.SendMessage(msg_back.GetNetMessage(), sender, NetChannel.ReliableUnordered); // And close the connection sender.Disconnect("Player \"" + msg.PlayerCarac.Nick + "\" already exists, Login refused"); } else { if ((msg.Param1 == null) || (msg.Param1 != BBMessage.Version)) { BBMessage msg_back1 = new BBMessage(); string str = msg.Param1; if (str == null) str = "No version"; msg_back1.MsgNoLogin("Player \"" + msg.PlayerCarac.Nick + "\" , Login refused. Version Serveur = " + BBMessage.Version + " Version Client = " + str); Server.SendMessage(msg_back1.GetNetMessage(), sender, NetChannel.ReliableUnordered); //sender.Disconnect("Player \"" + msg.PlayerCarac.Nick + "\" , Login refused. Version Serveur = " + BBMessage.Version + " Version Client = " + msg.Param1.ToString()); } else { // Yes : Add the player to the list and send OK // Now add the player to our list int id = PList.CreatePlayer(msg.PlayerCarac, sender); Log.Info("Player added : " + msg.PlayerCarac.Nick + ", " + id); // Send OK msg.MsgOkLogin(id); Server.SendMessage(msg.GetNetMessage(), sender, NetChannel.ReliableUnordered); // Send connection of other clients to our new client IDictionaryEnumerator en = PList.GetPlayerEnum(); BBMessage msg_notice; while (en.MoveNext()) { if (((Player)en.Value).Carac.ActorID != id) { msg_notice = new BBMessage(); msg_notice.MsgAddPlayer((Player)en.Value, false); Server.SendMessage(msg_notice.GetNetMessage(), sender, NetChannel.ReliableUnordered); } } // Notify other clients BBMessage msg_back = new BBMessage(); msg_back.MsgAddPlayer(PList.GetPlayer(id), true); BroadcastMsgExcept(msg_back.GetNetMessage(), NetChannel.ReliableUnordered, id); // Notify NotifyClientConnected(id); } } }
// unsequenced packets only, returns number of bytes sent internal int SendSingleMessageAtOnce(NetMessage msg, NetConnection connection, IPEndPoint endpoint) { m_sendBuffer.ResetWritePointer(); msg.Encode(connection, m_sendBuffer); if (connection != null) return ExecuteSend(m_sendBuffer, connection, connection.RemoteEndpoint); else return ExecuteSend(m_sendBuffer, null, endpoint); }
internal void NotifyClientDisconnected(NetConnection co) { if (ClientDisconnected != null) { ClientDisconnected(this, new ClientConnectEventArgs(PList.GetPlayer(PlayerList.GetPlayerID(co)).Carac)); } }
internal static void ReplyPong(NetMessage pingMessage, NetConnection connection) { byte nr = pingMessage.ReadByte(6); NetMessage pong = new NetMessage(NetMessageType.PingPong, 3); pong.Write(true); // means pong pong.Write(false); // means NOT optimize info pong.Write(nr, 6); pong.WriteSendStamp(); connection.Parent.SendSingleMessageAtOnce(pong, connection, connection.RemoteEndpoint); }
public NetPlayer(NetConnection con, String name) : base(name) { m_connection = con; }
/// <summary> /// Creates a network message by decoding a NetMessage /// </summary> /// <param name="msg">The NetMessage to be decoded</param> public SpiderMessage(NetMessage msg) { //This is the exception we throw if something goes wrong Exception e = new Exception("Could not read message"); byte[] contents = msg.ReadBytes(msg.Length); type = (SpiderMessageType)contents[0]; int dataOffset = BitConverter.ToInt32(contents, 1); label = Encoding.UTF8.GetString(contents, 1 + sizeof(int), dataOffset - 1 - sizeof(int)); senderIP = msg.Sender.RemoteEndpoint.Address; connection = msg.Sender; if (type == SpiderMessageType.Bytes) { data = new byte[contents.Length - dataOffset]; for (int i = 0; i < contents.Length - dataOffset; i++) { ((byte[])data)[i] = contents[i + dataOffset]; } } else { String tempData = Encoding.UTF8.GetString(contents, dataOffset, contents.Length - dataOffset); switch (type) { case SpiderMessageType.Double: data = Convert.ToDouble(tempData); break; case SpiderMessageType.Int: data = Convert.ToInt32(tempData); break; default: data = tempData; break; } } }
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 NetStatistics(NetConnection forConnection) { m_forConnection = forConnection; Reset(); }
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; } }
public void WriteStringTable(NetConnection connection, string val) { if (connection == null) throw new ArgumentNullException("connection"); connection.m_stringTable.Write(this, val); }