/** * Master_Shutdown, Informs all masters that this server is going down. */ public static void Master_Shutdown() { int i; // pgm post3.19 change, cvar pointer not validated before dereferencing if (null == Globals.dedicated || 0 == Globals.dedicated.value) { return; // only dedicated servers send heartbeats } // pgm post3.19 change, cvar pointer not validated before dereferencing if (null == SV_MAIN.public_server || 0 == SV_MAIN.public_server.value) { return; // a private dedicated game } // send to group master for (i = 0; i < Defines.MAX_MASTERS; i++) { if (SV_MAIN.master_adr[i].port != 0) { if (i > 0) { Com.Printf("Sending heartbeat to " + NET.AdrToString(SV_MAIN.master_adr[i]) + "\n"); } Netchan.OutOfBandPrint(Defines.NS_SERVER, SV_MAIN.master_adr[i], "shutdown"); } } }
public static void Master_Heartbeat( ) { String string_renamed; Int32 i; if (Globals.dedicated == null || 0 == Globals.dedicated.value) { return; } if (null == SV_MAIN.public_server || 0 == SV_MAIN.public_server.value) { return; } if (SV_INIT.svs.last_heartbeat > SV_INIT.svs.realtime) { SV_INIT.svs.last_heartbeat = SV_INIT.svs.realtime; } if (SV_INIT.svs.realtime - SV_INIT.svs.last_heartbeat < SV_MAIN.HEARTBEAT_SECONDS * 1000) { return; } SV_INIT.svs.last_heartbeat = SV_INIT.svs.realtime; string_renamed = SV_StatusString(); for (i = 0; i < Defines.MAX_MASTERS; i++) { if (SV_MAIN.master_adr[i].port != 0) { Com.Printf("Sending heartbeat to " + NET.AdrToString(SV_MAIN.master_adr[i]) + "\\n"); Netchan.OutOfBandPrint(Defines.NS_SERVER, SV_MAIN.master_adr[i], "heartbeat\\n" + string_renamed); } } }
public static bool Process(netchan_t chan, sizebuf_t msg) { MSG.BeginReading(msg); int sequence = MSG.ReadLong(msg); int sequence_ack = MSG.ReadLong(msg); if (chan.sock == Defines.NS_SERVER) { MSG.ReadShort(msg); } int reliable_message = sequence >> 31; int reliable_ack = sequence_ack >> 31; sequence &= ~(1 << 31); sequence_ack &= ~(1 << 31); if (showpackets.value != 0) { if (reliable_message != 0) { Com.Printf("recv " + msg.cursize + " : s=" + sequence + " reliable=" + (chan.incoming_reliable_sequence ^ 1) + " ack=" + sequence_ack + " rack=" + reliable_ack + "\\n"); } else { Com.Printf("recv " + msg.cursize + " : s=" + sequence + " ack=" + sequence_ack + " rack=" + reliable_ack + "\\n"); } } if (sequence <= chan.incoming_sequence) { if (showdrop.value != 0) { Com.Printf(NET.AdrToString(chan.remote_address) + ":Out of order packet " + sequence + " at " + chan.incoming_sequence + "\\n"); } return(false); } chan.dropped = sequence - (chan.incoming_sequence + 1); if (chan.dropped > 0) { if (showdrop.value != 0) { Com.Printf(NET.AdrToString(chan.remote_address) + ":Dropped " + chan.dropped + " packets at " + sequence + "\\n"); } } if (reliable_ack == chan.reliable_sequence) { chan.reliable_length = 0; } chan.incoming_sequence = sequence; chan.incoming_acknowledged = sequence_ack; chan.incoming_reliable_acknowledged = reliable_ack; if (reliable_message != 0) { chan.incoming_reliable_sequence ^= 1; } chan.last_received = (int)Globals.curtime; return(true); }
public static void SVC_RemoteCommand( ) { Int32 i; String remaining; i = Rcon_Validate(); var msg = Lib.CtoJava(Globals.net_message.data, 4, 1024); if (i == 0) { Com.Printf("Bad rcon from " + NET.AdrToString(Globals.net_from) + ":\\n" + msg + "\\n"); } else { Com.Printf("Rcon from " + NET.AdrToString(Globals.net_from) + ":\\n" + msg + "\\n"); } Com.BeginRedirect(Defines.RD_PACKET, SV_SEND.sv_outputbuf, Defines.SV_OUTPUTBUF_LENGTH, new AnonymousRD_Flusher()); if (0 == Rcon_Validate()) { Com.Printf("Bad rcon_password.\\n"); } else { remaining = ""; for (i = 2; i < Cmd.Argc(); i++) { remaining += Cmd.Argv(i); remaining += " "; } Cmd.ExecuteString(remaining); } Com.EndRedirect(); }
public static void Transmit(netchan_t chan, int length, byte[] data) { int send_reliable; int w1, w2; if (chan.message.overflowed) { chan.fatal_error = true; Com.Printf(NET.AdrToString(chan.remote_address) + ":Outgoing message overflow\\n"); return; } send_reliable = Netchan_NeedReliable(chan) ? 1 : 0; if (chan.reliable_length == 0 && chan.message.cursize != 0) { System.Array.Copy(chan.message_buf, 0, chan.reliable_buf, 0, chan.message.cursize); chan.reliable_length = chan.message.cursize; chan.message.cursize = 0; chan.reliable_sequence ^= 1; } SZ.Init(send, send_buf, send_buf.Length); w1 = (chan.outgoing_sequence & ~(1 << 31)) | (send_reliable << 31); w2 = (chan.incoming_sequence & ~(1 << 31)) | (chan.incoming_reliable_sequence << 31); chan.outgoing_sequence++; chan.last_sent = (int)Globals.curtime; MSG.WriteInt(send, w1); MSG.WriteInt(send, w2); if (chan.sock == Defines.NS_CLIENT) { MSG.WriteShort(send, (int)qport.value); } if (send_reliable != 0) { SZ.Write(send, chan.reliable_buf, chan.reliable_length); chan.last_reliable_sequence = chan.outgoing_sequence; } if (send.maxsize - send.cursize >= length) { SZ.Write(send, data, length); } else { Com.Printf("Netchan_Transmit: dumped unreliable\\n"); } NET.SendPacket(chan.sock, send.cursize, send.data, chan.remote_address); if (showpackets.value != 0) { if (send_reliable != 0) { Com.Printf("send " + send.cursize + " : s=" + (chan.outgoing_sequence - 1) + " reliable=" + chan.reliable_sequence + " ack=" + chan.incoming_sequence + " rack=" + chan.incoming_reliable_sequence + "\\n"); } else { Com.Printf("send " + send.cursize + " : s=" + (chan.outgoing_sequence - 1) + " ack=" + chan.incoming_sequence + " rack=" + chan.incoming_reliable_sequence + "\\n"); } } }
public static void SV_Status_f( ) { Int32 i, j, l; client_t cl; String s; Int32 ping; if (SV_INIT.svs.clients == null) { Com.Printf("No server running.\\n"); return; } Com.Printf("map : " + SV_INIT.sv.name + "\\n"); Com.Printf("num score ping name lastmsg address qport \\n"); Com.Printf("--- ----- ---- --------------- ------- --------------------- ------\\n"); for (i = 0; i < SV_MAIN.maxclients.value; i++) { cl = SV_INIT.svs.clients[i]; if (0 == cl.state) { continue; } Com.Printf("%3i ", i); Com.Printf("%5i ", cl.edict.client.ps.stats[Defines.STAT_FRAGS]); if (cl.state == Defines.cs_connected) { Com.Printf("CNCT "); } else if (cl.state == Defines.cs_zombie) { Com.Printf("ZMBI "); } else { ping = cl.ping < 9999 ? cl.ping : 9999; Com.Printf("%4i ", ping); } Com.Printf("%s", cl.name); l = 16 - cl.name.Length; for (j = 0; j < l; j++) { Com.Printf(" "); } Com.Printf("%7i ", SV_INIT.svs.realtime - cl.lastmessage); s = NET.AdrToString(cl.netchan.remote_address); Com.Printf(s); l = 22 - s.Length; for (j = 0; j < l; j++) { Com.Printf(" "); } Com.Printf("%5i", cl.netchan.qport); Com.Printf("\\n"); } Com.Printf("\\n"); }
/** * A connectionless packet has four leading 0xff characters to distinguish * it from a game channel. Clients that are in the game can still send * connectionless packets. It is used also by rcon commands. */ public static void SV_ConnectionlessPacket() { string s; string c; MSG.BeginReading(Globals.net_message); MSG.ReadLong(Globals.net_message); // skip the -1 marker s = MSG.ReadStringLine(Globals.net_message); Cmd.TokenizeString(s.ToCharArray(), false); c = Cmd.Argv(0); //for debugging purposes //Com.Printf("Packet " + NET.AdrToString(Netchan.net_from) + " : " + c + "\n"); //Com.Printf(Lib.hexDump(net_message.data, 64, false) + "\n"); if (0 == Lib.strcmp(c, "ping")) { SV_MAIN.SVC_Ping(); } else if (0 == Lib.strcmp(c, "ack")) { SV_MAIN.SVC_Ack(); } else if (0 == Lib.strcmp(c, "status")) { SV_MAIN.SVC_Status(); } else if (0 == Lib.strcmp(c, "info")) { SV_MAIN.SVC_Info(); } else if (0 == Lib.strcmp(c, "getchallenge")) { SV_MAIN.SVC_GetChallenge(); } else if (0 == Lib.strcmp(c, "connect")) { SV_MAIN.SVC_DirectConnect(); } else if (0 == Lib.strcmp(c, "rcon")) { SV_MAIN.SVC_RemoteCommand(); } else { Com.Printf("bad connectionless packet from " + NET.AdrToString(Globals.net_from) + "\n"); Com.Printf("[" + s + "]\n"); Com.Printf("" + Lib.hexDump(Globals.net_message.data, 128, false)); } }
/* * =============================================================================== * * OPERATOR CONSOLE ONLY COMMANDS * * These commands can only be entered from stdin or by a remote operator datagram * =============================================================================== */ /* * ==================== * SV_SetMaster_f * * Specify a list of master servers * ==================== */ public static void SV_SetMaster_f() { int i, slot; // only dedicated servers send heartbeats if (Globals.dedicated.value == 0) { Com.Printf("Only dedicated servers use masters.\n"); return; } // make sure the server is listed public Cvar.Set("public", "1"); for (i = 1; i < Defines.MAX_MASTERS; i++) { SV_MAIN.master_adr[i] = new(); } slot = 1; // slot 0 will always contain the id master for (i = 1; i < Cmd.Argc(); i++) { if (slot == Defines.MAX_MASTERS) { break; } if (!NET.StringToAdr(Cmd.Argv(i), SV_MAIN.master_adr[i])) { Com.Printf("Bad address: " + Cmd.Argv(i) + "\n"); continue; } if (SV_MAIN.master_adr[slot].port == 0) { SV_MAIN.master_adr[slot].port = Defines.PORT_MASTER; } Com.Printf("Master server at " + NET.AdrToString(SV_MAIN.master_adr[slot]) + "\n"); Com.Printf("Sending a ping.\n"); Netchan.OutOfBandPrint(Defines.NS_SERVER, SV_MAIN.master_adr[slot], "ping"); slot++; } SV_INIT.svs.last_heartbeat = -9999999; }
public static void SV_ConnectionlessPacket( ) { String s; String c; MSG.BeginReading(Globals.net_message); MSG.ReadLong(Globals.net_message); s = MSG.ReadStringLine(Globals.net_message); Cmd.TokenizeString(s.ToCharArray(), false); c = Cmd.Argv(0); if (0 == Lib.Strcmp(c, "ping")) { SVC_Ping(); } else if (0 == Lib.Strcmp(c, "ack")) { SVC_Ack(); } else if (0 == Lib.Strcmp(c, "status")) { SVC_Status(); } else if (0 == Lib.Strcmp(c, "info")) { SVC_Info(); } else if (0 == Lib.Strcmp(c, "getchallenge")) { SVC_GetChallenge(); } else if (0 == Lib.Strcmp(c, "connect")) { SVC_DirectConnect(); } else if (0 == Lib.Strcmp(c, "rcon")) { SVC_RemoteCommand(); } else { Com.Printf("bad connectionless packet from " + NET.AdrToString(Globals.net_from) + "\\n"); Com.Printf("[" + s + "]\\n"); Com.Printf("" + Lib.HexDump(Globals.net_message.data, 128, false)); } }
/** * A client issued an rcon command. Shift down the remaining args Redirect * all printfs fromt hte server to the client. */ public static void SVC_RemoteCommand() { int i; string remaining; i = SV_MAIN.Rcon_Validate(); var msg = Lib.CtoJava(Globals.net_message.data, 4, 1024); if (i == 0) { Com.Printf("Bad rcon from " + NET.AdrToString(Globals.net_from) + ":\n" + msg + "\n"); } else { Com.Printf("Rcon from " + NET.AdrToString(Globals.net_from) + ":\n" + msg + "\n"); } Com.BeginRedirect( Defines.RD_PACKET, SV_SEND.sv_outputbuf, Defines.SV_OUTPUTBUF_LENGTH, (target, buffer) => { SV_SEND.SV_FlushRedirect(target, Lib.stringToBytes(buffer.ToString())); } ); if (0 == SV_MAIN.Rcon_Validate()) { Com.Printf("Bad rcon_password.\n"); } else { remaining = ""; for (i = 2; i < Cmd.Argc(); i++) { remaining += Cmd.Argv(i); remaining += " "; } Cmd.ExecuteString(remaining); } Com.EndRedirect(); }
public static void Master_Heartbeat() { string @string; int i; // pgm post3.19 change, cvar pointer not validated before dereferencing if (Globals.dedicated == null || 0 == Globals.dedicated.value) { return; // only dedicated servers send heartbeats } // pgm post3.19 change, cvar pointer not validated before dereferencing if (null == SV_MAIN.public_server || 0 == SV_MAIN.public_server.value) { return; // a private dedicated game } // check for time wraparound if (SV_INIT.svs.last_heartbeat > SV_INIT.svs.realtime) { SV_INIT.svs.last_heartbeat = SV_INIT.svs.realtime; } if (SV_INIT.svs.realtime - SV_INIT.svs.last_heartbeat < SV_MAIN.HEARTBEAT_SECONDS * 1000) { return; // not time to send yet } SV_INIT.svs.last_heartbeat = SV_INIT.svs.realtime; // send the same string that we would give for a status OOB command @string = SV_MAIN.SV_StatusString(); // send to group master for (i = 0; i < Defines.MAX_MASTERS; i++) { if (SV_MAIN.master_adr[i].port != 0) { Com.Printf("Sending heartbeat to " + NET.AdrToString(SV_MAIN.master_adr[i]) + "\n"); Netchan.OutOfBandPrint(Defines.NS_SERVER, SV_MAIN.master_adr[i], "heartbeat\n" + @string); } } }
public static void Master_Shutdown( ) { Int32 i; if (null == Globals.dedicated || 0 == Globals.dedicated.value) { return; } if (null == SV_MAIN.public_server || 0 == SV_MAIN.public_server.value) { return; } for (i = 0; i < Defines.MAX_MASTERS; i++) { if (SV_MAIN.master_adr[i].port != 0) { if (i > 0) { Com.Printf("Sending heartbeat to " + NET.AdrToString(SV_MAIN.master_adr[i]) + "\\n"); } Netchan.OutOfBandPrint(Defines.NS_SERVER, SV_MAIN.master_adr[i], "shutdown"); } } }
public string toString() { return(this.type == Defines.NA_LOOPBACK ? "loopback" : NET.AdrToString(this)); }
public override String ToString( ) { return((type == Defines.NA_LOOPBACK) ? "loopback" : NET.AdrToString(this)); }
public static void SVC_Ack( ) { Com.Printf("Ping acknowledge from " + NET.AdrToString(Globals.net_from) + "\\n"); }
public static void SVC_DirectConnect( ) { String userinfo; netadr_t adr; Int32 i; client_t cl; Int32 version; Int32 qport; adr = Globals.net_from; Com.DPrintf("SVC_DirectConnect ()\\n"); version = Lib.Atoi(Cmd.Argv(1)); if (version != Defines.PROTOCOL_VERSION) { Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nServer is version " + Globals.VERSION + "\\n"); Com.DPrintf(" rejected connect from version " + version + "\\n"); return; } qport = Lib.Atoi(Cmd.Argv(2)); var challenge = Lib.Atoi(Cmd.Argv(3)); userinfo = Cmd.Argv(4); userinfo = Info.Info_SetValueForKey(userinfo, "ip", NET.AdrToString(Globals.net_from)); if (SV_INIT.sv.attractloop) { if (!NET.IsLocalAddress(adr)) { Com.Printf("Remote connect in attract loop. Ignored.\\n"); Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nConnection refused.\\n"); return; } } if (!NET.IsLocalAddress(adr)) { for (i = 0; i < Defines.MAX_CHALLENGES; i++) { if (NET.CompareBaseAdr(Globals.net_from, SV_INIT.svs.challenges[i].adr)) { if (challenge == SV_INIT.svs.challenges[i].challenge) { break; } Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nBad challenge.\\n"); return; } } if (i == Defines.MAX_CHALLENGES) { Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nNo challenge for address.\\n"); return; } } for (i = 0; i < SV_MAIN.maxclients.value; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state == Defines.cs_free) { continue; } if (NET.CompareBaseAdr(adr, cl.netchan.remote_address) && (cl.netchan.qport == qport || adr.port == cl.netchan.remote_address.port)) { if (!NET.IsLocalAddress(adr) && (SV_INIT.svs.realtime - cl.lastconnect) < (( Int32 )SV_MAIN.sv_reconnect_limit.value * 1000)) { Com.DPrintf(NET.AdrToString(adr) + ":reconnect rejected : too soon\\n"); return; } Com.Printf(NET.AdrToString(adr) + ":reconnect\\n"); Gotnewcl(i, challenge, userinfo, adr, qport); return; } } var index = -1; for (i = 0; i < SV_MAIN.maxclients.value; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state == Defines.cs_free) { index = i; break; } } if (index == -1) { Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nServer is full.\\n"); Com.DPrintf("Rejected a connection.\\n"); return; } Gotnewcl(index, challenge, userinfo, adr, qport); }
/** * A connection request that did not come from the master. */ public static void SVC_DirectConnect() { string userinfo; netadr_t adr; int i; client_t cl; int version; int qport; adr = Globals.net_from; Com.DPrintf("SVC_DirectConnect ()\n"); version = Lib.atoi(Cmd.Argv(1)); if (version != Defines.PROTOCOL_VERSION) { Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nServer is version " + Globals.VERSION + "\n"); Com.DPrintf(" rejected connect from version " + version + "\n"); return; } qport = Lib.atoi(Cmd.Argv(2)); var challenge = Lib.atoi(Cmd.Argv(3)); userinfo = Cmd.Argv(4); // force the IP key/value pair so the game can filter based on ip userinfo = Info.Info_SetValueForKey(userinfo, "ip", NET.AdrToString(Globals.net_from)); // attractloop servers are ONLY for local clients if (SV_INIT.sv.attractloop) { if (!NET.IsLocalAddress(adr)) { Com.Printf("Remote connect in attract loop. Ignored.\n"); Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nConnection refused.\n"); return; } } // see if the challenge is valid if (!NET.IsLocalAddress(adr)) { for (i = 0; i < Defines.MAX_CHALLENGES; i++) { if (NET.CompareBaseAdr(Globals.net_from, SV_INIT.svs.challenges[i].adr)) { if (challenge == SV_INIT.svs.challenges[i].challenge) { break; // good } Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nBad challenge.\n"); return; } } if (i == Defines.MAX_CHALLENGES) { Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nNo challenge for address.\n"); return; } } // if there is already a slot for this ip, reuse it for (i = 0; i < SV_MAIN.maxclients.value; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state == Defines.cs_free) { continue; } if (NET.CompareBaseAdr(adr, cl.netchan.remote_address) && (cl.netchan.qport == qport || adr.port == cl.netchan.remote_address.port)) { if (!NET.IsLocalAddress(adr) && SV_INIT.svs.realtime - cl.lastconnect < (int)SV_MAIN.sv_reconnect_limit.value * 1000) { Com.DPrintf(NET.AdrToString(adr) + ":reconnect rejected : too soon\n"); return; } Com.Printf(NET.AdrToString(adr) + ":reconnect\n"); SV_MAIN.gotnewcl(i, challenge, userinfo, adr, qport); return; } } // find a client slot //newcl = null; var index = -1; for (i = 0; i < SV_MAIN.maxclients.value; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state == Defines.cs_free) { index = i; break; } } if (index == -1) { Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nServer is full.\n"); Com.DPrintf("Rejected a connection.\n"); return; } SV_MAIN.gotnewcl(index, challenge, userinfo, adr, qport); }