|
16 | 16 | #include "master.h" |
17 | 17 | #include "proto_oob.h" |
18 | 18 | #include "host.h" |
| 19 | +#include "eiface.h" |
| 20 | +#include "server.h" |
19 | 21 |
|
| 22 | +extern ConVar sv_tags; |
20 | 23 | extern ConVar sv_lan; |
21 | 24 |
|
| 25 | +#define S2A_EXTRA_DATA_HAS_GAMETAG_DATA 0x01 // Next bytes are the game tag string |
| 26 | + |
22 | 27 | //----------------------------------------------------------------------------- |
23 | 28 | // Purpose: List of master servers and some state info about them |
24 | 29 | //----------------------------------------------------------------------------- |
@@ -65,6 +70,8 @@ class CMaster : public IMaster, public IServersInfo |
65 | 70 |
|
66 | 71 | void RunFrame(); |
67 | 72 | void RequestServersInfo(); |
| 73 | + void ReplyInfo( const netadr_t &adr ); |
| 74 | + newgameserver_t &ProcessInfo( bf_read &buf ); |
68 | 75 |
|
69 | 76 | // SeversInfo |
70 | 77 | void RequestInternetServerList( const char *gamedir, IServerListResponse *response ); |
@@ -116,6 +123,79 @@ void CMaster::RunFrame() |
116 | 123 | CheckHeartbeat(); |
117 | 124 | } |
118 | 125 |
|
| 126 | +void CMaster::ReplyInfo( const netadr_t &adr ) |
| 127 | +{ |
| 128 | + static char gamedir[MAX_OSPATH]; |
| 129 | + Q_FileBase( com_gamedir, gamedir, sizeof( gamedir ) ); |
| 130 | + |
| 131 | + CUtlBuffer buf; |
| 132 | + buf.EnsureCapacity( 2048 ); |
| 133 | + |
| 134 | + buf.PutUnsignedInt( LittleDWord( CONNECTIONLESS_HEADER ) ); |
| 135 | + buf.PutUnsignedChar( S2C_INFOREPLY ); |
| 136 | + |
| 137 | + buf.PutUnsignedChar( PROTOCOL_VERSION ); // Hardcoded protocol version number |
| 138 | + buf.PutString( sv.GetName() ); |
| 139 | + buf.PutString( sv.GetMapName() ); |
| 140 | + buf.PutString( gamedir ); |
| 141 | + buf.PutString( serverGameDLL->GetGameDescription() ); |
| 142 | + |
| 143 | + // player info |
| 144 | + buf.PutUnsignedChar( sv.GetNumClients() ); |
| 145 | + buf.PutUnsignedChar( sv.GetMaxClients() ); |
| 146 | + buf.PutUnsignedChar( sv.GetNumFakeClients() ); |
| 147 | + |
| 148 | + // Password? |
| 149 | + buf.PutUnsignedChar( sv.GetPassword() != NULL ? 1 : 0 ); |
| 150 | + |
| 151 | + // Write a byte with some flags that describe what is to follow. |
| 152 | + const char *pchTags = sv_tags.GetString(); |
| 153 | + int nFlags = 0; |
| 154 | + |
| 155 | + if ( pchTags && pchTags[0] != '\0' ) |
| 156 | + nFlags |= S2A_EXTRA_DATA_HAS_GAMETAG_DATA; |
| 157 | + |
| 158 | + buf.PutUnsignedInt( nFlags ); |
| 159 | + |
| 160 | + if ( nFlags & S2A_EXTRA_DATA_HAS_GAMETAG_DATA ) |
| 161 | + { |
| 162 | + buf.PutString( pchTags ); |
| 163 | + } |
| 164 | + |
| 165 | + NET_SendPacket( NULL, NS_SERVER, adr, (unsigned char *)buf.Base(), buf.TellPut() ); |
| 166 | +} |
| 167 | + |
| 168 | +newgameserver_t &CMaster::ProcessInfo(bf_read &buf) |
| 169 | +{ |
| 170 | + static newgameserver_t s; |
| 171 | + memset( &s, 0, sizeof(s) ); |
| 172 | + |
| 173 | + s.m_nProtocolVersion = buf.ReadByte(); |
| 174 | + |
| 175 | + buf.ReadString( s.m_szServerName, sizeof(s.m_szServerName) ); |
| 176 | + buf.ReadString( s.m_szMap, sizeof(s.m_szMap) ); |
| 177 | + buf.ReadString( s.m_szGameDir, sizeof(s.m_szGameDir) ); |
| 178 | + |
| 179 | + buf.ReadString( s.m_szGameDescription, sizeof(s.m_szGameDescription) ); |
| 180 | + |
| 181 | + // player info |
| 182 | + s.m_nPlayers = buf.ReadByte(); |
| 183 | + s.m_nMaxPlayers = buf.ReadByte(); |
| 184 | + s.m_nBotPlayers = buf.ReadByte(); |
| 185 | + |
| 186 | + // Password? |
| 187 | + s.m_bPassword = buf.ReadByte(); |
| 188 | + |
| 189 | + s.m_iFlags = buf.ReadLong(); |
| 190 | + |
| 191 | + if( s.m_iFlags & S2A_EXTRA_DATA_HAS_GAMETAG_DATA ) |
| 192 | + { |
| 193 | + buf.ReadString( s.m_szGameTags, sizeof(s.m_szGameTags) ); |
| 194 | + } |
| 195 | + |
| 196 | + return s; |
| 197 | +} |
| 198 | + |
119 | 199 | void CMaster::ProcessConnectionlessPacket( netpacket_t *packet ) |
120 | 200 | { |
121 | 201 | static ALIGN4 char string[2048] ALIGN4_POST; // Buffer for sending heartbeat |
@@ -158,27 +238,24 @@ void CMaster::ProcessConnectionlessPacket( netpacket_t *packet ) |
158 | 238 | } |
159 | 239 | case C2S_INFOREQUEST: |
160 | 240 | { |
161 | | - bf_write p(string, sizeof(string)); |
162 | | - p.WriteLong(CONNECTIONLESS_HEADER); |
163 | | - p.WriteByte(S2C_INFOREPLY); |
164 | | - p.WriteString(sv.GetName()); |
165 | | - |
166 | | - NET_SendPacket(NULL, NS_SERVER, packet->from, p.GetData(), p.GetNumBytesWritten()); |
167 | | - |
| 241 | + ReplyInfo(packet->from); |
168 | 242 | break; |
169 | 243 | } |
170 | 244 | case S2C_INFOREPLY: |
171 | 245 | { |
172 | | - char hostname[1024]; |
173 | | - msg.ReadString(hostname, sizeof(hostname)); |
| 246 | + newgameserver_t &s = ProcessInfo( msg ); |
| 247 | + Msg("hostname = %s\nplayers: %d/%d\nbots: %d\n", s.m_szServerName, s.m_nPlayers, s.m_nMaxPlayers, s.m_nBotPlayers); |
174 | 248 |
|
175 | | - newgameserver_t s; |
176 | 249 | s.m_NetAdr = packet->from; |
177 | | - s.SetName( hostname ); |
178 | | - |
179 | 250 | m_serverListResponse->ServerResponded( s ); |
180 | 251 | break; |
181 | 252 | } |
| 253 | + case A2A_PING: |
| 254 | + { |
| 255 | + const char p = A2A_ACK; |
| 256 | + NET_SendPacket( NULL, NS_SERVER, packet->from, (unsigned char*)&p, 1); |
| 257 | + break; |
| 258 | + } |
182 | 259 | } |
183 | 260 | } |
184 | 261 |
|
|
0 commit comments