00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "server.h"
00030
00035 void SV_SetClientState (client_t* client, int state)
00036 {
00037 assert(client);
00038 Com_DPrintf(DEBUG_SERVER, "Set state for client '%s' to %i\n", client->name, state);
00039 client->state = state;
00040 }
00041
00042
00043
00044
00045
00046
00047
00055 static void SV_New_f (client_t *cl)
00056 {
00057 Com_DPrintf(DEBUG_SERVER, "New() from %s\n", cl->name);
00058
00059 if (cl->state != cs_connected) {
00060 if (cl->state == cs_spawning) {
00061
00062 Com_Printf("SV_New_f: client typed 'reconnect/new' while connecting\n");
00063 SV_ClientCommand(cl, "\ndisconnect\nreconnect\n");
00064 SV_DropClient(cl, "");
00065 } else
00066 Com_DPrintf(DEBUG_SERVER, "WARNING: Illegal 'new' from %s, client state %d. This shouldn't happen...\n", cl->name, cl->state);
00067 return;
00068 }
00069
00070
00071 SV_SetClientState(cl, cs_spawning);
00072
00073
00074
00075
00076
00077 {
00078 const int playernum = cl - SV_GetClient(0);
00079 struct dbuffer *msg = new_dbuffer();
00080 NET_WriteByte(msg, svc_serverdata);
00081 NET_WriteLong(msg, PROTOCOL_VERSION);
00082
00083 NET_WriteShort(msg, playernum);
00084
00085
00086 NET_WriteString(msg, SV_GetConfigString(CS_NAME));
00087
00088 NET_WriteMsg(cl->stream, msg);
00089 }
00090
00091
00092 if (Com_ServerState() == ss_game) {
00093 int i;
00094 for (i = 0; i < MAX_CONFIGSTRINGS; i++) {
00095 const char *configString = SV_GetConfigString(i);
00096 if (configString[0] != '\0') {
00097 struct dbuffer *msg = new_dbuffer();
00098 Com_DPrintf(DEBUG_SERVER, "sending configstring %d: %s\n", i, configString);
00099 NET_WriteByte(msg, svc_configstring);
00100 NET_WriteShort(msg, i);
00101 NET_WriteString(msg, configString);
00102
00103 NET_WriteMsg(cl->stream, msg);
00104 }
00105 }
00106 }
00107
00108 SV_ClientCommand(cl, "precache\n");
00109 }
00110
00114 static void SV_Begin_f (client_t *cl)
00115 {
00116 qboolean began;
00117
00118 Com_DPrintf(DEBUG_SERVER, "Begin() from %s\n", cl->name);
00119
00120
00121 if (cl->state != cs_spawning) {
00122 Com_Printf("EXPLOIT: Illegal 'begin' from %s (already spawned), client dropped.\n", cl->name);
00123 SV_DropClient(cl, "Illegal begin\n");
00124 return;
00125 }
00126
00127
00128 SDL_mutexP(svs.serverMutex);
00129 began = svs.ge->ClientBegin(cl->player);
00130 SDL_mutexV(svs.serverMutex);
00131
00132 if (!began) {
00133 SV_DropClient(cl, "'begin' failed\n");
00134 return;
00135 }
00136 SV_SetClientState(cl, cs_began);
00137
00138 Cbuf_InsertFromDefer();
00139 }
00140
00144 static void SV_Spawn_f (client_t *cl)
00145 {
00146 Com_DPrintf(DEBUG_SERVER, "Spawn() from %s\n", cl->name);
00147
00148 if (cl->state != cs_began) {
00149 SV_DropClient(cl, "Invalid state\n");
00150 return;
00151 }
00152
00153 SDL_mutexP(svs.serverMutex);
00154 svs.ge->ClientSpawn(cl->player);
00155 SDL_mutexV(svs.serverMutex);
00156 SV_SetClientState(cl, cs_spawned);
00157
00158 Cbuf_InsertFromDefer();
00159 }
00160
00161
00162
00166 static void SV_Disconnect_f (client_t *cl)
00167 {
00168 SV_DropClient(cl, "Disconnect\n");
00169 }
00170
00171
00175 static void SV_ShowServerinfo_f (client_t *cl)
00176 {
00177 Info_Print(Cvar_Serverinfo());
00178 }
00179
00180
00181 typedef struct {
00182 const char *name;
00183 void (*func) (client_t *client);
00184 } ucmd_t;
00185
00186 static const ucmd_t ucmds[] = {
00187
00188 {"new", SV_New_f},
00189 {"begin", SV_Begin_f},
00190 {"spawn", SV_Spawn_f},
00191
00192 {"disconnect", SV_Disconnect_f},
00193
00194
00195 {"info", SV_ShowServerinfo_f},
00196
00197 {NULL, NULL}
00198 };
00199
00203 static void SV_ExecuteUserCommand (client_t * cl, const char *s)
00204 {
00205 const ucmd_t *u;
00206
00207 Cmd_TokenizeString(s, qfalse);
00208
00209 for (u = ucmds; u->name; u++)
00210 if (!strcmp(Cmd_Argv(0), u->name)) {
00211 Com_DPrintf(DEBUG_SERVER, "SV_ExecuteUserCommand: %s\n", s);
00212 u->func(cl);
00213 return;
00214 }
00215
00216 if (Com_ServerState() == ss_game) {
00217 Com_DPrintf(DEBUG_SERVER, "SV_ExecuteUserCommand: client command: %s\n", s);
00218 SDL_mutexP(svs.serverMutex);
00219 svs.ge->ClientCommand(cl->player);
00220 SDL_mutexV(svs.serverMutex);
00221 }
00222 }
00223
00227 void SV_ExecuteClientMessage (client_t * cl, int cmd, struct dbuffer *msg)
00228 {
00229 if (cmd == -1)
00230 return;
00231
00232 switch (cmd) {
00233 default:
00234 Com_Printf("SV_ExecuteClientMessage: unknown command char '%d'\n", cmd);
00235 SV_DropClient(cl, "Unknown command\n");
00236 return;
00237
00238 case clc_nop:
00239 break;
00240
00241 case clc_userinfo:
00242 NET_ReadString(msg, cl->userinfo, sizeof(cl->userinfo));
00243 Com_DPrintf(DEBUG_SERVER, "userinfo from client: %s\n", cl->userinfo);
00244 SV_UserinfoChanged(cl);
00245 break;
00246
00247 case clc_stringcmd:
00248 {
00249 char str[1024];
00250 NET_ReadString(msg, str, sizeof(str));
00251
00252 Com_DPrintf(DEBUG_SERVER, "stringcmd from client: %s\n", str);
00253 SV_ExecuteUserCommand(cl, str);
00254
00255 if (cl->state == cs_free)
00256 return;
00257 break;
00258 }
00259
00260 case clc_action:
00261
00262 sv.messageBuffer = msg;
00263 SDL_mutexP(svs.serverMutex);
00264 svs.ge->ClientAction(cl->player);
00265 SDL_mutexV(svs.serverMutex);
00266 sv.messageBuffer = NULL;
00267 break;
00268
00269 case clc_endround:
00270
00271 sv.messageBuffer = msg;
00272 SDL_mutexP(svs.serverMutex);
00273 svs.ge->ClientEndRound(cl->player);
00274 SDL_mutexV(svs.serverMutex);
00275 sv.messageBuffer = NULL;
00276 break;
00277
00278 case clc_teaminfo:
00279
00280
00281 sv.messageBuffer = msg;
00282 SDL_mutexP(svs.serverMutex);
00283 svs.ge->ClientTeamInfo(cl->player);
00284 SDL_mutexV(svs.serverMutex);
00285 sv.messageBuffer = NULL;
00286 break;
00287
00288 case clc_initactorstates:
00289
00290
00291 sv.messageBuffer = msg;
00292 SDL_mutexP(svs.serverMutex);
00293 svs.ge->ClientInitActorStates(cl->player);
00294 SDL_mutexV(svs.serverMutex);
00295 sv.messageBuffer = NULL;
00296 break;
00297 }
00298 }