public static int Schedule(ClientConnection conn, int priority) { int id; lock (syncRoot) { if (priority > 2 || priority < 0) { // bypass queue id = AssignSlotOrQueue(conn, 3); } else { id = AssignSlotOrQueue(conn, priority); } } // we send here, so as to prevent a deadlock between our lock // and the connection's sendqueue lock if (id == -1) { var msg = NewNetMessage.PrepareThreadInstance(); msg.SendTileLoading(1, WaitingMessage(conn)); conn.Send(msg.Output); } else if (id >= 0) { var msg = NewNetMessage.PrepareThreadInstance(); msg.ConnectionResponse(id); conn.Send(msg.Output); } return(id); }
public void Send(byte[] data) { if (data == null) { throw new ArgumentException("Data to send cannot be null"); } if (conn == null) { return; } conn.Send(data); }
public override void Process(ClientConnection conn, byte[] readBuffer, int length, int num) { int start = num - 1; //string password = Encoding.ASCII.GetString(readBuffer, num, length - num + start); var password = ReadString(readBuffer); if (conn.State == SlotState.SERVER_AUTH) { var ctx = new HookContext { Connection = conn, }; var args = new HookArgs.ServerPassReceived { Password = password }; HookPoints.ServerPassReceived.Invoke(ref ctx, ref args); if (ctx.CheckForKick()) return; if (ctx.Result == HookResult.ASK_PASS) { var msg = NewNetMessage.PrepareThreadInstance(); msg.PasswordRequest(); conn.Send(msg.Output); } else if (ctx.Result == HookResult.CONTINUE || password == Netplay.password) { conn.State = SlotState.ACCEPTED; var msg = NewNetMessage.PrepareThreadInstance(); msg.ConnectionResponse(253 /* dummy value, real slot assigned later */); conn.Send(msg.Output); return; } conn.Kick("Incorrect server password."); } else if (conn.State == SlotState.PLAYER_AUTH) { var name = conn.Player.Name ?? String.Empty; var ctx = new HookContext { Connection = conn, Player = conn.Player, Sender = conn.Player, }; var args = new HookArgs.PlayerPassReceived { Password = password, }; HookPoints.PlayerPassReceived.Invoke(ref ctx, ref args); if (ctx.CheckForKick()) return; if (ctx.Result == HookResult.ASK_PASS) { var msg = NewNetMessage.PrepareThreadInstance(); msg.PasswordRequest(); conn.Send(msg.Output); } else // HookResult.DEFAULT { var lower = name.ToLower(); bool reserved = false; //conn.Queue = (int)loginEvent.Priority; foreach (var otherPlayer in Main.player) { //var otherSlot = Netplay.slots[otherPlayer.whoAmi]; var otherConn = otherPlayer.Connection; if (otherPlayer.Name != null && lower == otherPlayer.Name.ToLower() && (otherConn as ClientConnection) != null && (otherConn as ClientConnection).HasConnected()) { if (!reserved) { reserved = SlotManager.HandoverSlot(otherConn, conn); } otherConn.Kick("Replaced by new connection."); } } //conn.State = SlotState.SENDING_WORLD; if (!reserved) // reserved slots get assigned immediately during the kick { SlotManager.Schedule(conn, conn.DesiredQueue); } //NewNetMessage.SendData (4, -1, whoAmI, name, whoAmI); // broadcast player data now // replay packets from side buffer //conn.conn.ProcessSideBuffer (); //var buf = NewNetMessage.buffer[whoAmI]; //NewNetMessage.CheckBytes (whoAmI, buf.sideBuffer, ref buf.sideBufferBytes, ref buf.sideBufferMsgLen); //buf.ResetSideBuffer (); //NewNetMessage.SendData (7, whoAmI); // continue with world data } } }
public static void FreeSlot(int id) { ClientConnection assignedTo = null; var slot = Terraria.Netplay.Clients[id] as ServerSlot; slot.Reset(); lock (syncRoot) { if (handovers[id] != null) { assignedTo = handovers[id]; handovers[id] = null; if (!AssignSlot(assignedTo, id)) { assignedTo = null; ProgramLog.Log("Slot {0} handover failed.", id); } else { ProgramLog.Log("Slot {0} handover successful.", id); } } if (assignedTo == null) { assignedTo = FindForSlot(id); } if (assignedTo == null) { PushSlot(id); ProgramLog.Log("Freed slot {0}", id); // this is for when a privileged slot is freed, but no privileged clients are waiting // so we check if we have an unprivileged slot to use if (isPrivileged[id] && (freeSlots.Count > 0 && freeSlots.Count > (privSlotsInUse - overlimitSlots))) { id = freeSlots.Pop(); assignedTo = FindForSlot(id); if (assignedTo == null) { freeSlots.Push(id); return; } } else { return; } } } var msg = NewNetMessage.PrepareThreadInstance(); msg.ConnectionResponse(id); assignedTo.Send(msg.Output); }
public override void Process(ClientConnection conn, byte[] readBuffer, int length, int num) { // ServerSlot slot = Netplay.slots[whoAmI]; // PlayerLoginEvent loginEvent = new PlayerLoginEvent(); // loginEvent.Slot = slot; // loginEvent.Sender = Main.player[whoAmI]; // Server.PluginManager.processHook(Plugin.Hooks.PLAYER_PRELOGIN, loginEvent); // if ((loginEvent.Cancelled || loginEvent.Action == PlayerLoginAction.REJECT) && (slot.state & SlotState.DISCONNECTING) == 0) // { // slot.Kick ("Disconnected by server."); // return; // } string clientName = conn.RemoteAddress.Split(':')[0]; // // if (Server.BanList.containsException(clientName)) // { // slot.Kick ("You are banned from this Server."); // return; // } //if (Program.properties.UseWhiteList && !Server.WhiteList.containsException(clientName)) //{ // conn.Kick ("You are not on the WhiteList."); // return; //} string version = StringCache.FindOrMake(new ArraySegment<byte>(readBuffer, num, length - 1)); Skip(length); var ctx = new HookContext { Connection = conn, }; var args = new HookArgs.ConnectionRequestReceived { Version = version }; HookPoints.ConnectionRequestReceived.Invoke(ref ctx, ref args); if (ctx.CheckForKick()) return; if (ctx.Result == HookResult.DEFAULT && !(version == "Terraria" + Globals.TerrariaRelease)) { if (version.Length > 30) version = version.Substring(0, 30); ProgramLog.Log("Client version string: {0}", version); conn.Kick(string.Concat("This server requires Terraria ", Globals.TerrariaVersion)); return; } var msg = NewNetMessage.PrepareThreadInstance(); if (ctx.Result == HookResult.ASK_PASS || (Netplay.password != null && Netplay.password != String.Empty)) { conn.State = SlotState.SERVER_AUTH; msg.PasswordRequest(); conn.Send(msg.Output); return; } conn.State = SlotState.ACCEPTED; msg.ConnectionResponse(253 /* arbitrary fake value, true slot assigned later */); conn.Send(msg.Output); }
public static int Schedule(ClientConnection conn, int priority) { int id; lock (syncRoot) { if (priority > 2 || priority < 0) { // bypass queue id = AssignSlotOrQueue(conn, 3); } else id = AssignSlotOrQueue(conn, priority); } // we send here, so as to prevent a deadlock between our lock // and the connection's sendqueue lock if (id == -1) { var msg = NewNetMessage.PrepareThreadInstance(); msg.SendTileLoading(1, WaitingMessage(conn)); conn.Send(msg.Output); } else if (id >= 0) { var msg = NewNetMessage.PrepareThreadInstance(); msg.ConnectionResponse(id); conn.Send(msg.Output); } return id; }
public override void Process(ClientConnection conn, byte[] readBuffer, int length, int num) { int start = num - 1; if (conn.State == SlotState.ASSIGNING_SLOT) { // TODO: verify that data didn't change. int who = conn.SlotIndex; NewNetMessage.SendData(4, -1, who, conn.Player.Name, who); return; } //if (conn.Player != null) //{ // conn.Kick("Player data sent twice."); // return; //} //var player = new Player(); var player = conn.Player; var connecting = conn.Player == null; if (connecting) { player = new Player(); conn.Player = player; player.Connection = conn; player.IPAddress = conn.RemoteAddress; player.whoAmi = conn.SlotIndex; } var data = new HookArgs.PlayerDataReceived() { IsConnecting = connecting }; var read = data.Parse(readBuffer, num + 1 /* PlayerId */, length); Skip(read); if (data.Hair >= MAX_HAIR_ID) { data.Hair = 0; } var ctx = new HookContext { Connection = conn, Player = player, Sender = player, }; HookPoints.PlayerDataReceived.Invoke(ref ctx, ref data); if (ctx.CheckForKick()) return; if (!data.NameChecked) { string error; if (!data.CheckName(out error)) { conn.Kick(error); return; } } string address = conn.RemoteAddress.Split(':')[0]; if (!data.BansChecked) { if (Server.Bans.Contains(address) || Server.Bans.Contains(data.Name)) { ProgramLog.Admin.Log("Prevented banned user {0} from accessing the server.", data.Name); conn.Kick("You are banned from this server."); return; } } if (!data.WhitelistChecked && Server.WhitelistEnabled) { if (!Server.Whitelist.Contains(address) && !Server.Whitelist.Contains(data.Name)) { ProgramLog.Admin.Log("Prevented non whitelisted user {0} from accessing the server.", data.Name); conn.Kick("You do not have access to this server."); return; } } data.Apply(player); if (connecting) if (ctx.Result == HookResult.ASK_PASS) { conn.State = SlotState.PLAYER_AUTH; var msg = NewNetMessage.PrepareThreadInstance(); msg.PasswordRequest(); conn.Send(msg.Output); return; } else // HookResult.DEFAULT { // don't allow replacing connections for guests, but do for registered users if (conn.State < SlotState.PLAYING) { var lname = player.Name.ToLower(); foreach (var otherPlayer in Main.player) { var otherSlot = Terraria.Netplay.Clients[otherPlayer.whoAmi]; if (otherPlayer.Name != null && lname == otherPlayer.Name.ToLower() && otherSlot.State() >= SlotState.CONNECTED) { conn.Kick("A \"" + otherPlayer.Name + "\" is already on this server."); return; } } } //conn.Queue = (int)loginEvent.Priority; // actual queueing done on world request message // and now decide whether to queue the connection //SlotManager.Schedule (conn, (int)loginEvent.Priority); //NewNetMessage.SendData (4, -1, -1, player.Name, whoAmI); } //int num3 = (int)ReadByte(readBuffer); //if (Main.netMode == 2) //{ // num3 = this.whoAmI; //} //if (num3 == Main.myPlayer && !Main.ServerSideCharacter) //{ // return; //} //Player player2 = Main.player[num3]; //player2.whoAmi = num3; //if (ReadByte() == 0) //{ // player2.male = true; //} //else //{ // player2.male = false; //} //player2.hair = (int)ReadByte(readBuffer); //if (player2.hair >= 123) //{ // player2.hair = 0; //} //player2.name = ReadString().Trim(); //player2.hairDye = ReadByte(readBuffer); //player2.hideVisual = ReadByte(readBuffer); //player2.hairColor = ReadRGB(); //player2.skinColor = ReadRGB(); //player2.eyeColor = ReadRGB(); //player2.shirtColor = ReadRGB(); //player2.underShirtColor = ReadRGB(); //player2.pantsColor = ReadRGB(); //player2.shoeColor = ReadRGB(); //player2.difficulty = ReadByte(readBuffer); //if (Main.netMode != 2) //{ // return; //} //bool flag = false; //if (tdsm.api.Callbacks.Netplay.slots[this.whoAmI].state < 10) //{ // for (int n = 0; n < 255; n++) // { // if (n != num3 && player2.name == Main.player[n].name && tdsm.api.Callbacks.Netplay.slots[n].active) // { // flag = true; // } // } //} //if (flag) //{ // NewNetMessage.SendData(2, this.whoAmI, -1, player2.name + " " + Lang.mp[5], 0, 0f, 0f, 0f, 0); // return; //} //if (player2.name.Length > Player.nameLen) //{ // NewNetMessage.SendData(2, this.whoAmI, -1, "Name is too long.", 0, 0f, 0f, 0f, 0); // return; //} //if (player2.name == String.Empty) //{ // NewNetMessage.SendData(2, this.whoAmI, -1, "Empty name.", 0, 0f, 0f, 0f, 0); // return; //} //tdsm.api.Callbacks.Netplay.slots[this.whoAmI].oldName = player2.name; //tdsm.api.Callbacks.Netplay.slots[this.whoAmI].name = player2.name; //NewNetMessage.SendData(4, -1, this.whoAmI, player2.name, num3, 0f, 0f, 0f, 0); //return; }