1 | |
1 | |
2 | /* |
2 | /* |
3 | * static char *rcsid_loop_c = |
3 | * static char *rcsid_loop_c = |
4 | * "$Id: loop.c,v 1.1.1.1 2006/02/03 07:14:44 root Exp $"; |
4 | * "$Id: loop.c,v 1.11 2006/07/24 23:25:27 root Exp $"; |
5 | */ |
5 | */ |
6 | |
6 | |
7 | /* |
7 | /* |
8 | CrossFire, A Multiplayer game for X-windows |
8 | CrossFire, A Multiplayer game for X-windows |
9 | |
9 | |
… | |
… | |
78 | */ |
78 | */ |
79 | |
79 | |
80 | typedef void (*func_uint8_int_ns) (char*, int, NewSocket *); |
80 | typedef void (*func_uint8_int_ns) (char*, int, NewSocket *); |
81 | |
81 | |
82 | struct NsCmdMapping { |
82 | struct NsCmdMapping { |
83 | char *cmdname; |
83 | const char *cmdname; |
84 | func_uint8_int_ns cmdproc; |
84 | func_uint8_int_ns cmdproc; |
85 | }; |
85 | }; |
86 | |
86 | |
87 | typedef void (*func_uint8_int_pl)(char*, int, player *); |
87 | typedef void (*func_uint8_int_pl)(char*, int, player *); |
88 | struct PlCmdMapping { |
88 | struct PlCmdMapping { |
89 | char *cmdname; |
89 | const char *cmdname; |
90 | func_uint8_int_pl cmdproc; |
90 | func_uint8_int_pl cmdproc; |
91 | uint8 flag; |
91 | uint8 flag; |
92 | }; |
92 | }; |
93 | |
93 | |
94 | /** |
94 | /** |
… | |
… | |
113 | { "ncom", (func_uint8_int_pl)NewPlayerCmd, 1}, |
113 | { "ncom", (func_uint8_int_pl)NewPlayerCmd, 1}, |
114 | { "lookat", LookAt, 1}, |
114 | { "lookat", LookAt, 1}, |
115 | { "lock", (func_uint8_int_pl)LockItem, 1}, |
115 | { "lock", (func_uint8_int_pl)LockItem, 1}, |
116 | { "mark", (func_uint8_int_pl)MarkItem, 1}, |
116 | { "mark", (func_uint8_int_pl)MarkItem, 1}, |
117 | { "mapredraw", MapRedrawCmd, 0}, /* Added: phil */ |
117 | { "mapredraw", MapRedrawCmd, 0}, /* Added: phil */ |
|
|
118 | { "mapinfo", MapInfoCmd, 2}, /* CF+ */ |
|
|
119 | { "ext", ExtCmd, 2}, /* CF+ */ |
118 | { NULL, NULL, 0} /* terminator */ |
120 | { NULL, NULL, 0} /* terminator */ |
119 | }; |
121 | }; |
120 | |
122 | |
121 | /** Face-related commands */ |
123 | /** Face-related commands */ |
122 | static struct NsCmdMapping nscommands[] = { |
124 | static struct NsCmdMapping nscommands[] = { |
… | |
… | |
182 | /* This is not the most efficient block, but keeps the code simpler - |
184 | /* This is not the most efficient block, but keeps the code simpler - |
183 | * we basically read a byte at a time until we get a newline, error, |
185 | * we basically read a byte at a time until we get a newline, error, |
184 | * or no more characters to read. |
186 | * or no more characters to read. |
185 | */ |
187 | */ |
186 | do { |
188 | do { |
|
|
189 | /* hack to disable old socket mode without creating too many conflicts */ |
187 | if (ns->inbuf.len >= MAXSOCKBUF-1) { |
190 | if (1 || ns->inbuf.len >= MAXSOCKBUF-1) { |
188 | ns->status = Ns_Dead; |
191 | ns->status = Ns_Dead; |
189 | LOG(llevDebug, "Old input socket sent too much data without newline\n"); |
192 | LOG(llevDebug, "Old input socket sent too much data without newline\n"); |
190 | return; |
193 | return; |
191 | } |
194 | } |
192 | #ifdef WIN32 /* ***win32: change oldsocket read() to recv() */ |
195 | #ifdef WIN32 /* ***win32: change oldsocket read() to recv() */ |
… | |
… | |
322 | * starting a connection) |
325 | * starting a connection) |
323 | */ |
326 | */ |
324 | |
327 | |
325 | void HandleClient(NewSocket *ns, player *pl) |
328 | void HandleClient(NewSocket *ns, player *pl) |
326 | { |
329 | { |
327 | int len=0,i; |
330 | int len=0,i,cnt; |
328 | unsigned char *data; |
331 | unsigned char *data; |
329 | |
332 | |
330 | /* Loop through this - maybe we have several complete packets here. */ |
333 | /* Loop through this - maybe we have several complete packets here. */ |
331 | while (1) { |
334 | // limit to a few commands only, though, as to not monopolise the server |
|
|
335 | for (cnt = 16; cnt--; ) { |
332 | /* If it is a player, and they don't have any speed left, we |
336 | /* If it is a player, and they don't have any speed left, we |
333 | * return, and will read in the data when they do have time. |
337 | * return, and will read in the data when they do have time. |
334 | */ |
338 | */ |
335 | if (pl && pl->state==ST_PLAYING && pl->ob != NULL && pl->ob->speed_left < 0) { |
339 | if (pl && pl->state==ST_PLAYING && pl->ob != NULL && pl->ob->speed_left < 0) { |
336 | return; |
340 | return; |
… | |
… | |
363 | return; |
367 | return; |
364 | } |
368 | } |
365 | /* Still dont have a full packet */ |
369 | /* Still dont have a full packet */ |
366 | if (i==0) return; |
370 | if (i==0) return; |
367 | |
371 | |
|
|
372 | // //D//TODO//temporarily log long commands |
|
|
373 | // if (ns->inbuf.len >= 40 && pl && pl->ob) |
|
|
374 | // LOG (llevDebug, "HandleClient: long comamnd from <%s,%s> %d<%s>\n", pl->ob->name, ns->host, ns->inbuf.len, ns->inbuf.buf + 2); |
|
|
375 | |
368 | /* First, break out beginning word. There are at least |
376 | /* First, break out beginning word. There are at least |
369 | * a few commands that do not have any paremeters. If |
377 | * a few commands that do not have any paremeters. If |
370 | * we get such a command, don't worry about trying |
378 | * we get such a command, don't worry about trying |
371 | * to break it up. |
379 | * to break it up. |
372 | */ |
380 | */ |
… | |
… | |
381 | ns->inbuf.buf[ns->inbuf.len]='\0'; /* Terminate buffer - useful for string data */ |
389 | ns->inbuf.buf[ns->inbuf.len]='\0'; /* Terminate buffer - useful for string data */ |
382 | for (i=0; nscommands[i].cmdname !=NULL; i++) { |
390 | for (i=0; nscommands[i].cmdname !=NULL; i++) { |
383 | if (strcmp((char*)ns->inbuf.buf+2,nscommands[i].cmdname)==0) { |
391 | if (strcmp((char*)ns->inbuf.buf+2,nscommands[i].cmdname)==0) { |
384 | nscommands[i].cmdproc((char*)data,len,ns); |
392 | nscommands[i].cmdproc((char*)data,len,ns); |
385 | ns->inbuf.len=0; |
393 | ns->inbuf.len=0; |
386 | return; |
394 | return;//D// not doing this causes random memory corruption |
|
|
395 | goto next_packet; |
387 | } |
396 | } |
388 | } |
397 | } |
389 | /* Player must be in the playing state or the flag on the |
398 | /* Player must be in the playing state or the flag on the |
390 | * the command must be zero for the user to use the command - |
399 | * the command must be zero for the user to use the command - |
391 | * otherwise, a player cam save, be in the play_again state, and |
400 | * otherwise, a player cam save, be in the play_again state, and |
392 | * the map they were on getsswapped out, yet things that try to look |
401 | * the map they were on gets swapped out, yet things that try to look |
393 | * at the map causes a crash. If the command is valid, but |
402 | * at the map causes a crash. If the command is valid, but |
394 | * one they can't use, we still swallow it up. |
403 | * one they can't use, we still swallow it up. |
395 | */ |
404 | */ |
396 | if (pl) for (i=0; plcommands[i].cmdname !=NULL; i++) { |
405 | if (pl) for (i=0; plcommands[i].cmdname !=NULL; i++) { |
397 | if (strcmp((char*)ns->inbuf.buf+2,plcommands[i].cmdname)==0) { |
406 | if (strcmp((char*)ns->inbuf.buf+2,plcommands[i].cmdname)==0) { |
398 | if (pl->state == ST_PLAYING || plcommands[i].flag == 0) |
407 | if (pl->state == ST_PLAYING || !(plcommands[i].flag & 1)) |
399 | plcommands[i].cmdproc((char*)data,len,pl); |
408 | plcommands[i].cmdproc((char*)data,len,pl); |
400 | ns->inbuf.len=0; |
409 | ns->inbuf.len=0; |
401 | return; |
410 | //D// not doing this causes random memory corruption |
|
|
411 | if (plcommands[i].flag & 2) |
|
|
412 | goto next_packet; |
|
|
413 | return; |
402 | } |
414 | } |
403 | } |
415 | } |
404 | /* If we get here, we didn't find a valid command. Logging |
416 | /* If we get here, we didn't find a valid command. Logging |
405 | * this might be questionable, because a broken client/malicious |
417 | * this might be questionable, because a broken client/malicious |
406 | * user could certainly send a whole bunch of invalid commands. |
418 | * user could certainly send a whole bunch of invalid commands. |
407 | */ |
419 | */ |
408 | LOG(llevDebug,"Bad command from client (%s)\n",ns->inbuf.buf+2); |
420 | LOG(llevDebug,"Bad command from client (%s)\n",ns->inbuf.buf+2); |
|
|
421 | next_packet: |
|
|
422 | ; |
409 | } |
423 | } |
410 | } |
424 | } |
411 | |
425 | |
412 | |
426 | |
413 | /***************************************************************************** |
427 | /***************************************************************************** |
… | |
… | |
502 | while (select(socket_info.max_filedescriptor, &readfs, NULL, NULL, &Timeout)==0); |
516 | while (select(socket_info.max_filedescriptor, &readfs, NULL, NULL, &Timeout)==0); |
503 | |
517 | |
504 | reset_sleep(); /* Or the game would go too fast */ |
518 | reset_sleep(); /* Or the game would go too fast */ |
505 | } |
519 | } |
506 | |
520 | |
|
|
521 | void flush_sockets(void) |
|
|
522 | { |
|
|
523 | player *pl; |
|
|
524 | |
|
|
525 | for (pl = first_player; pl != NULL; pl = pl->next) |
|
|
526 | if (pl->socket.status != Ns_Dead) |
|
|
527 | Socket_Flush (&pl->socket); |
|
|
528 | } |
507 | |
529 | |
508 | /** |
530 | /** |
509 | * This checks the sockets for input and exceptions, does the right thing. |
531 | * This checks the sockets for input and exceptions, does the right thing. |
510 | * |
532 | * |
511 | * A bit of this code is grabbed out of socket.c |
533 | * A bit of this code is grabbed out of socket.c |
… | |
… | |
563 | FD_SET((uint32)pl->socket.fd, &tmp_exceptions); |
585 | FD_SET((uint32)pl->socket.fd, &tmp_exceptions); |
564 | pl=pl->next; |
586 | pl=pl->next; |
565 | } |
587 | } |
566 | } |
588 | } |
567 | |
589 | |
|
|
590 | #if 0 |
|
|
591 | // the event system and plugins require the server ti run at all times. |
|
|
592 | // since its primarily cf.schmorp.de we are interested in, and |
|
|
593 | // that is supposed to run all the time anyway, its globally disabled |
|
|
594 | // until we can use Event. |
568 | if (socket_info.nconns==1 && first_player==NULL) |
595 | if (socket_info.nconns==1 && first_player==NULL) |
569 | block_until_new_connection(); |
596 | block_until_new_connection(); |
|
|
597 | #endif |
570 | |
598 | |
571 | /* Reset timeout each time, since some OS's will change the values on |
599 | /* Reset timeout each time, since some OS's will change the values on |
572 | * the return from select. |
600 | * the return from select. |
573 | */ |
601 | */ |
574 | socket_info.timeout.tv_sec = 0; |
602 | socket_info.timeout.tv_sec = 0; |
… | |
… | |
709 | if (pl->last_weight != -1 && pl->last_weight != WEIGHT(pl->ob)) { |
737 | if (pl->last_weight != -1 && pl->last_weight != WEIGHT(pl->ob)) { |
710 | esrv_update_item(UPD_WEIGHT, pl->ob, pl->ob); |
738 | esrv_update_item(UPD_WEIGHT, pl->ob, pl->ob); |
711 | if(pl->last_weight != WEIGHT(pl->ob)) |
739 | if(pl->last_weight != WEIGHT(pl->ob)) |
712 | LOG(llevError, "esrv_update_item(UPD_WEIGHT) did not set player weight: is %lu, should be %lu\n", (unsigned long)pl->last_weight, WEIGHT(pl->ob)); |
740 | LOG(llevError, "esrv_update_item(UPD_WEIGHT) did not set player weight: is %lu, should be %lu\n", (unsigned long)pl->last_weight, WEIGHT(pl->ob)); |
713 | } |
741 | } |
714 | if (pl->ob->map && pl->ob->map->in_memory==MAP_IN_MEMORY) |
742 | /* draw_client_map does sanity checking that map is |
|
|
743 | * valid, so don't do it here. |
|
|
744 | */ |
715 | draw_client_map(pl->ob); |
745 | draw_client_map(pl->ob); |
716 | if (pl->socket.update_look) esrv_draw_look(pl->ob); |
746 | if (pl->socket.update_look) esrv_draw_look(pl->ob); |
717 | } |
747 | } |
718 | } |
748 | } |
719 | } |
749 | } |
720 | } |
750 | } |