Crossfire Server, Branches 1.12  R18729
loop.c
Go to the documentation of this file.
1 
2 /*
3  * static char *rcsid_loop_c =
4  * "$Id: loop.c 11578 2009-02-23 22:02:27Z lalo $";
5  */
6 
7 /*
8  CrossFire, A Multiplayer game for X-windows
9 
10  Copyright (C) 2006 Mark Wedel & The Crossfire Development Team
11  Copyright (C) 1992 Frank Tore Johansen
12 
13  This program is free software; you can redistribute it and/or modify
14  it under the terms of the GNU General Public License as published by
15  the Free Software Foundation; either version 2 of the License, or
16  (at your option) any later version.
17 
18  This program is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  GNU General Public License for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with this program; if not, write to the Free Software
25  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 
27  The author can be reached via e-mail to crossfire-devel@real-time.com
28 */
29 
41 #include <global.h>
42 #ifndef __CEXTRACT__
43 #include <sproto.h>
44 #include <sockproto.h>
45 #endif
46 
47 #ifndef WIN32 /* ---win32 exclude unix headers */
48 #include <sys/types.h>
49 #include <sys/time.h>
50 #include <sys/socket.h>
51 #include <netinet/in.h>
52 #include <netdb.h>
53 #endif /* end win32 */
54 
55 #ifdef HAVE_UNISTD_H
56 #include <unistd.h>
57 #endif
58 
59 #ifdef HAVE_ARPA_INET_H
60 #include <arpa/inet.h>
61 #endif
62 
63 #include <loader.h>
64 #include <newserver.h>
65 
66 /*****************************************************************************
67  * Start of command dispatch area.
68  * The commands here are protocol commands.
69  ****************************************************************************/
70 
71 /* Either keep this near the start or end of the file so it is
72  * at least reasonablye easy to find.
73  * There are really 2 commands - those which are sent/received
74  * before player joins, and those happen after the player has joined.
75  * As such, we have function types that might be called, so
76  * we end up having 2 tables.
77  */
78 
80 typedef void (*func_uint8_int_ns)(char *, int, socket_struct *);
81 
84  const char *cmdname;
86 };
87 
89 typedef void (*func_uint8_int_pl)(char *, int, player *);
92  const char *cmdname;
94  const uint8 flag;
95 };
96 
112 static const struct player_cmd_mapping player_commands[] = {
113  { "examine", examine_cmd, 1 },
114  { "apply", apply_cmd, 1 },
115  { "move", move_cmd, 1 },
116  { "reply", reply_cmd, 0 },
117  { "ncom", (func_uint8_int_pl)new_player_cmd, 1 },
118  { "lookat", look_at_cmd, 1 },
119  { "lock", (func_uint8_int_pl)lock_item_cmd, 1 },
120  { "mark", (func_uint8_int_pl)mark_item_cmd, 1 },
121  { "mapredraw", map_redraw_cmd, 0 }, /* Added: phil */
122  { "inscribe", inscribe_scroll_cmd, 0 },
123  { NULL, NULL, 0 } /* terminator */
124 };
125 
127 static const struct client_cmd_mapping client_commands[] = {
128  { "addme", add_me_cmd },
129  { "askface", send_face_cmd }, /* Added: phil */
130  { "requestinfo", request_info_cmd },
131  { "setfacemode", set_face_mode_cmd },
132  { "setsound", set_sound_cmd },
133  { "setup", set_up_cmd },
134  { "version", version_cmd },
135  { "toggleextendedinfos", toggle_extended_infos_cmd }, /*Added: tchize*/
136  { "toggleextendedtext", toggle_extended_text_cmd }, /*Added: tchize*/
137  { "asksmooth", ask_smooth_cmd }, /*Added: tchize (smoothing technologies)*/
138  { NULL, NULL } /* terminator (I, II & III)*/
139 };
140 
146 void request_info_cmd(char *buf, int len, socket_struct *ns) {
147  char *params = NULL, *cp;
148  /* No match */
149  SockList sl;
150 
151  /* Set up replyinfo before we modify any of the buffers - this is used
152  * if we don't find a match.
153  */
154  SockList_Init(&sl);
155  SockList_AddString(&sl, "replyinfo ");
156  SockList_AddString(&sl, buf);
157 
158  /* find the first space, make it null, and update the
159  * params pointer.
160  */
161  for (cp = buf; *cp != '\0'; cp++)
162  if (*cp == ' ') {
163  *cp = '\0';
164  params = cp+1;
165  break;
166  }
167  if (!strcmp(buf, "image_info"))
168  send_image_info(ns, params);
169  else if (!strcmp(buf, "image_sums"))
170  send_image_sums(ns, params);
171  else if (!strcmp(buf, "skill_info"))
172  send_skill_info(ns, params);
173  else if (!strcmp(buf, "spell_paths"))
174  send_spell_paths(ns, params);
175  else if (!strcmp(buf, "exp_table"))
176  send_exp_table(ns, params);
177  else if (!strcmp(buf, "race_list"))
178  send_race_list(ns, params);
179  else if (!strcmp(buf, "race_info"))
180  send_race_info(ns, params);
181  else if (!strcmp(buf, "class_list"))
182  send_class_list(ns, params);
183  else if (!strcmp(buf, "class_info"))
184  send_class_info(ns, params);
185  else
186  Send_With_Handling(ns, &sl);
187  SockList_Term(&sl);
188 }
189 
201  int len, i;
202  unsigned char *data;
203 
204  /* Loop through this - maybe we have several complete packets here. */
205  while (1) {
206  /* If it is a player, and they don't have any speed left, we
207  * return, and will read in the data when they do have time.
208  */
209  if (pl && pl->state == ST_PLAYING && pl->ob != NULL && pl->ob->speed_left < 0) {
210  return;
211  }
212 
213  i = SockList_ReadPacket(ns->fd, &ns->inbuf, sizeof(ns->inbuf.buf)-1);
214  if (i < 0) {
215 #ifdef ESRV_DEBUG
216  LOG(llevDebug, "handle_client: Read error on connection player %s\n", (pl ? pl->ob->name : "None"));
217 #endif
218  /* Caller will take care of cleaning this up */
219  ns->status = Ns_Dead;
220  return;
221  }
222  /* Still dont have a full packet */
223  if (i == 0)
224  return;
225 
226  SockList_NullTerminate(&ns->inbuf); /* Terminate buffer - useful for string data */
227 
228  /* First, break out beginning word. There are at least
229  * a few commands that do not have any paremeters. If
230  * we get such a command, don't worry about trying
231  * to break it up.
232  */
233  data = (unsigned char *)strchr((char *)ns->inbuf.buf+2, ' ');
234  if (data) {
235  *data = '\0';
236  data++;
237  len = ns->inbuf.len-(data-ns->inbuf.buf);
238  } else
239  len = 0;
240 
241  for (i = 0; client_commands[i].cmdname != NULL; i++) {
242  if (strcmp((char *)ns->inbuf.buf+2, client_commands[i].cmdname) == 0) {
243  client_commands[i].cmdproc((char *)data, len, ns);
245  return;
246  }
247  }
248  /* Player must be in the playing state or the flag on the
249  * the command must be zero for the user to use the command -
250  * otherwise, a player cam save, be in the play_again state, and
251  * the map they were on getsswapped out, yet things that try to look
252  * at the map causes a crash. If the command is valid, but
253  * one they can't use, we still swallow it up.
254  */
255  if (pl)
256  for (i = 0; player_commands[i].cmdname != NULL; i++) {
257  if (strcmp((char *)ns->inbuf.buf+2, player_commands[i].cmdname) == 0) {
258  if (pl->state == ST_PLAYING || player_commands[i].flag == 0)
259  player_commands[i].cmdproc((char *)data, len, pl);
261  return;
262  }
263  }
264  /* If we get here, we didn't find a valid command. Logging
265  * this might be questionable, because a broken client/malicious
266  * user could certainly send a whole bunch of invalid commands.
267  */
268  LOG(llevDebug, "Bad command from client (%s)\n", ns->inbuf.buf+2);
270  }
271 }
272 
273 /*****************************************************************************
274  *
275  * Low level socket looping - select calls and watchdog udp packet
276  * sending.
277  *
278  ******************************************************************************/
279 
280 #ifdef WATCHDOG
281 
287 void watchdog(void) {
288  static int fd = -1;
289  static struct sockaddr_in insock;
290 
291  if (fd == -1) {
292  struct protoent *protoent;
293 
294  if ((protoent = getprotobyname("udp")) == NULL
295  || (fd = socket(PF_INET, SOCK_DGRAM, protoent->p_proto)) == -1) {
296  return;
297  }
298  insock.sin_family = AF_INET;
299  insock.sin_port = htons((unsigned short)13325);
300  insock.sin_addr.s_addr = inet_addr("127.0.0.1");
301  }
302  sendto(fd, (void *)&fd, 1, 0, (struct sockaddr *)&insock, sizeof(insock));
303 }
304 #endif
305 
306 extern unsigned long todtick;
307 
309 static void block_until_new_connection(void) {
310  struct timeval Timeout;
311  fd_set readfs;
312  int cycles;
313 
314  LOG(llevInfo, "Waiting for connections...\n");
315 
316  cycles = 1;
317  do {
318  /* Every minutes is a bit often for updates - especially if nothing is going
319  * on. This slows it down to every 6 minutes.
320  */
321  cycles++;
322  if (cycles%2 == 0)
323  tick_the_clock();
324 
325  FD_ZERO(&readfs);
326  FD_SET((uint32)init_sockets[0].fd, &readfs);
327 
328  /* If fastclock is set, we need to seriously slow down the updates
329  * to the metaserver as well as watchdog. Do same for flush_old_maps() -
330  * that is time sensitive, so there is no good reason to call it 2000 times
331  * a second.
332  */
333  if (settings.fastclock > 0) {
334 #ifdef WATCHDOG
335  if (cycles%120000 == 0) {
336  watchdog();
337  flush_old_maps();
338  }
339 #endif
340  if (cycles == 720000) {
342  cycles = 1;
343  }
344  Timeout.tv_sec = 0;
345  Timeout.tv_usec = 50;
346  } else {
347  Timeout.tv_sec = 60;
348  Timeout.tv_usec = 0;
349  if (cycles == 7) {
351  cycles = 1;
352  }
353  flush_old_maps();
354  }
355  } while (select(socket_info.max_filedescriptor, &readfs, NULL, NULL, &Timeout) == 0);
356 
357  reset_sleep(); /* Or the game would go too fast */
358 }
359 
368 static int is_fd_valid(int fd) {
369 #ifndef WIN32
370  return fcntl(fd, F_GETFL) != -1 || errno != EBADF;
371 #else
372  return 1;
373 #endif
374 }
375 
383 void do_server(void) {
384  int i, pollret;
385  fd_set tmp_read, tmp_exceptions, tmp_write;
386  struct sockaddr_in addr;
387  socklen_t addrlen = sizeof(struct sockaddr);
388  player *pl, *next;
389  char err[MAX_BUF];
390 
391 #ifdef CS_LOGSTATS
392  if ((time(NULL)-cst_lst.time_start) >= CS_LOGTIME)
393  write_cs_stats();
394 #endif
395 
396  FD_ZERO(&tmp_read);
397  FD_ZERO(&tmp_write);
398  FD_ZERO(&tmp_exceptions);
399 
400  for (i = 0; i < socket_info.allocated_sockets; i++) {
401  if (init_sockets[i].status == Ns_Add && !is_fd_valid(init_sockets[i].fd)) {
402  LOG(llevError, "do_server: invalid waiting fd %d\n", i);
404  }
405  if (init_sockets[i].status == Ns_Dead) {
409  } else if (init_sockets[i].status != Ns_Avail) {
410  FD_SET((uint32)init_sockets[i].fd, &tmp_read);
411  FD_SET((uint32)init_sockets[i].fd, &tmp_write);
412  FD_SET((uint32)init_sockets[i].fd, &tmp_exceptions);
413  }
414  }
415 
416  /* Go through the players. Let the loop set the next pl value,
417  * since we may remove some
418  */
419  for (pl = first_player; pl != NULL; ) {
420  if (pl->socket.status != Ns_Dead && !is_fd_valid(pl->socket.fd)) {
421  LOG(llevError, "do_server: invalid file descriptor for player %s [%s]: %d\n", (pl->ob && pl->ob->name) ? pl->ob->name : "(unnamed player?)", (pl->socket.host) ? pl->socket.host : "(unknown ip?)", pl->socket.fd);
422  pl->socket.status = Ns_Dead;
423  }
424 
425  if (pl->socket.status == Ns_Dead) {
426  player *npl = pl->next;
427 
428  save_player(pl->ob, 0);
429  if (!QUERY_FLAG(pl->ob, FLAG_REMOVED)) {
430  terminate_all_pets(pl->ob);
431  remove_ob(pl->ob);
432  }
433  leave(pl, 1);
434  final_free_player(pl);
435  pl = npl;
436  } else {
437  FD_SET((uint32)pl->socket.fd, &tmp_read);
438  FD_SET((uint32)pl->socket.fd, &tmp_write);
439  FD_SET((uint32)pl->socket.fd, &tmp_exceptions);
440  pl = pl->next;
441  }
442  }
443 
444  if (socket_info.nconns == 1 && first_player == NULL)
446 
447  /* Reset timeout each time, since some OS's will change the values on
448  * the return from select.
449  */
450  socket_info.timeout.tv_sec = 0;
451  socket_info.timeout.tv_usec = 0;
452 
453  pollret = select(socket_info.max_filedescriptor, &tmp_read, &tmp_write, &tmp_exceptions, &socket_info.timeout);
454 
455  if (pollret == -1) {
456  LOG(llevError, "select failed: %s\n", strerror_local(errno, err, sizeof(err)));
457  return;
458  }
459 
460  /* We need to do some of the processing below regardless */
461  /* if (!pollret) return;*/
462 
463  /* Following adds a new connection */
464  if (pollret && FD_ISSET(init_sockets[0].fd, &tmp_read)) {
465  int newsocknum = 0;
466 
467 #ifdef ESRV_DEBUG
468  LOG(llevDebug, "do_server: New Connection\n");
469 #endif
470  /* If this is the case, all sockets currently in used */
472  init_sockets = realloc(init_sockets, sizeof(socket_struct)*(socket_info.nconns+1));
473  if (!init_sockets)
475  newsocknum = socket_info.allocated_sockets;
478  init_sockets[newsocknum].faces_sent = calloc(1, nrofpixmaps*sizeof(*init_sockets[newsocknum].faces_sent));
479  if (!init_sockets[newsocknum].faces_sent)
481  init_sockets[newsocknum].status = Ns_Avail;
482  } else {
483  int j;
484 
485  for (j = 1; j < socket_info.allocated_sockets; j++)
486  if (init_sockets[j].status == Ns_Avail) {
487  newsocknum = j;
488  break;
489  }
490  }
491  init_sockets[newsocknum].fd = accept(init_sockets[0].fd, (struct sockaddr *)&addr, &addrlen);
492  if (init_sockets[newsocknum].fd == -1) {
493  LOG(llevError, "accept failed: %s\n", strerror_local(errno, err, sizeof(err)));
494  } else {
495  char buf[MAX_BUF];
496  long ip;
497  socket_struct *ns;
498 
499  ns = &init_sockets[newsocknum];
500 
501  ip = ntohl(addr.sin_addr.s_addr);
502  snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld", (ip>>24)&255, (ip>>16)&255, (ip>>8)&255, ip&255);
503 
504  if (checkbanned(NULL, buf)) {
505  LOG(llevInfo, "Banned host tried to connect: [%s]\n", buf);
506  close(init_sockets[newsocknum].fd);
507  init_sockets[newsocknum].fd = -1;
508  } else {
509  init_connection(ns, buf);
511  }
512  }
513  }
514 
515  /* Check for any exceptions/input on the sockets */
516  if (pollret)
517  for (i = 1; i < socket_info.allocated_sockets; i++) {
518  if (init_sockets[i].status == Ns_Avail)
519  continue;
520  if (FD_ISSET(init_sockets[i].fd, &tmp_exceptions)) {
524  continue;
525  }
526  if (FD_ISSET(init_sockets[i].fd, &tmp_read)) {
527  handle_client(&init_sockets[i], NULL);
528  }
529  if (FD_ISSET(init_sockets[i].fd, &tmp_write)) {
530  init_sockets[i].can_write = 1;
531  }
532  }
533 
534  /* This does roughly the same thing, but for the players now */
535  for (pl = first_player; pl != NULL; pl = next) {
536  next = pl->next;
537  if (pl->socket.status == Ns_Dead)
538  continue;
539 
540  if (FD_ISSET(pl->socket.fd, &tmp_write)) {
541  if (!pl->socket.can_write) {
542  pl->socket.can_write = 1;
544  }
545  /* if we get an error on the write_socket buffer, no reason to
546  * continue on this socket.
547  */
548  if (pl->socket.status == Ns_Dead)
549  continue;
550  } else
551  pl->socket.can_write = 0;
552 
553  if (FD_ISSET(pl->socket.fd, &tmp_exceptions)) {
554  save_player(pl->ob, 0);
555  if (!QUERY_FLAG(pl->ob, FLAG_REMOVED)) {
556  terminate_all_pets(pl->ob);
557  remove_ob(pl->ob);
558  }
559  leave(pl, 1);
560  final_free_player(pl);
561  } else {
562  handle_client(&pl->socket, pl);
563 
564  /* There seems to be rare cases where next points to a removed/freed player.
565  * My belief is that this player does something (shout, move, whatever)
566  * that causes data to be sent to the next player on the list, but
567  * that player is defunct, so the socket codes removes that player.
568  * End result is that next now points at the removed player, and
569  * that has garbage data so we crash. So update the next pointer
570  * while pl is still valid. MSW 2007-04-21
571  */
572  next = pl->next;
573 
574 
575  /* If the player has left the game, then the socket status
576  * will be set to this be the leave function. We don't
577  * need to call leave again, as it has already been called
578  * once.
579  */
580  if (pl->socket.status == Ns_Dead) {
581  save_player(pl->ob, 0);
582  if (!QUERY_FLAG(pl->ob, FLAG_REMOVED)) {
583  terminate_all_pets(pl->ob);
584  remove_ob(pl->ob);
585  }
586  leave(pl, 1);
587  final_free_player(pl);
588  } else {
589  /* Update the players stats once per tick. More efficient than
590  * sending them whenever they change, and probably just as useful
591  */
592  esrv_update_stats(pl);
593  if (pl->last_weight != -1 && pl->last_weight != WEIGHT(pl->ob)) {
594  esrv_update_item(UPD_WEIGHT, pl->ob, pl->ob);
595  if (pl->last_weight != WEIGHT(pl->ob))
596  LOG(llevError, "esrv_update_item(UPD_WEIGHT) did not set player weight: is %lu, should be %lu\n", (unsigned long)pl->last_weight, (unsigned long)WEIGHT(pl->ob));
597  }
598  /* draw_client_map does sanity checking that map is
599  * valid, so don't do it here.
600  */
601  draw_client_map(pl->ob);
602  if (pl->socket.update_look)
603  esrv_draw_look(pl->ob);
604  if (pl->socket.tick)
605  send_tick(pl);
606 
607  }
608  }
609  }
610 }
const char * cmdname
Definition: loop.c:92
Definition: player.h:146
size_t len
Definition: newclient.h:575
#define OUT_OF_MEMORY
Definition: define.h:94
void leave(player *pl, int draw_exit)
Definition: server.c:1234
int nrofpixmaps
Definition: image.c:76
uint32 can_write
Definition: newserver.h:132
void map_redraw_cmd(char *buf, int len, player *pl)
Definition: request.c:662
const func_uint8_int_ns cmdproc
Definition: loop.c:85
void SockList_Init(SockList *sl)
Definition: lowlevel.c:67
void(* func_uint8_int_pl)(char *, int, player *)
Definition: loop.c:89
void set_face_mode_cmd(char *buf, int len, socket_struct *ns)
Definition: image.c:53
void SockList_ResetRead(SockList *sl)
Definition: lowlevel.c:94
void look_at_cmd(char *buf, int len, player *pl)
Definition: item.c:754
void version_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:621
void metaserver_update(void)
Definition: metaserver.c:134
uint8 fastclock
Definition: global.h:386
const func_uint8_int_pl cmdproc
Definition: loop.c:93
int save_player(object *op, int flag)
Definition: login.c:223
uint32 tick
Definition: newserver.h:136
void do_server(void)
Definition: loop.c:383
void esrv_update_item(int flags, object *pl, object *op)
Definition: standalone.c:200
void send_image_sums(socket_struct *ns, char *params)
Definition: image.c:165
void send_image_info(socket_struct *ns, char *params)
Definition: image.c:138
socket_struct socket
Definition: player.h:148
int checkbanned(const char *login, const char *host)
Definition: ban.c:38
const uint8 flag
Definition: loop.c:94
enum Sock_Status status
Definition: newserver.h:116
#define socklen_t
Definition: win32.h:148
void inscribe_scroll_cmd(char *buf, int len, player *pl)
Definition: item.c:841
int max_filedescriptor
Definition: newserver.h:173
void terminate_all_pets(object *owner)
Definition: pets.c:250
void send_skill_info(socket_struct *ns, char *params)
Definition: request.c:1505
#define ST_PLAYING
Definition: define.h:886
char * host
Definition: newserver.h:125
#define FLAG_REMOVED
Definition: define.h:528
socket_struct * init_sockets
Definition: init.c:68
void send_class_list(socket_struct *ns, char *params)
Definition: request.c:1642
void free_newsocket(socket_struct *ns)
Definition: init.c:305
size_t faces_sent_len
Definition: newserver.h:120
unsigned char buf[2+65536UL+1]
Definition: newclient.h:576
void remove_ob(object *op)
Definition: object.c:1515
uint8 * faces_sent
Definition: newserver.h:121
void flush_old_maps(void)
Definition: swap.c:305
static const struct client_cmd_mapping client_commands[]
Definition: loop.c:127
Socket_Info socket_info
Definition: init.c:63
void new_player_cmd(uint8 *buf, int len, player *pl)
Definition: request.c:492
CS_Stats cst_lst
float speed_left
Definition: object.h:182
void handle_client(socket_struct *ns, player *pl)
Definition: loop.c:200
void send_exp_table(socket_struct *ns, char *params)
Definition: request.c:1482
void SockList_Term(SockList *sl)
Definition: lowlevel.c:77
void write_socket_buffer(socket_struct *ns)
Definition: lowlevel.c:418
const char * name
Definition: object.h:167
#define WEIGHT(op)
Definition: define.h:1098
uint8 state
Definition: player.h:172
void fatal(int err)
Definition: glue.c:60
void SockList_AddString(SockList *sl, const char *data)
Definition: lowlevel.c:154
sint32 last_weight
Definition: player.h:197
unsigned char uint8
Definition: global.h:75
void mark_item_cmd(uint8 *data, int len, player *pl)
Definition: item.c:655
void send_race_info(socket_struct *ns, char *params)
Definition: request.c:1600
void tick_the_clock(void)
Definition: weather.c:111
int allocated_sockets
Definition: newserver.h:175
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
#define MAX_BUF
Definition: define.h:81
static int is_fd_valid(int fd)
Definition: loop.c:368
#define CS_LOGTIME
Definition: config.h:163
void reset_sleep(void)
Definition: time.c:141
void send_class_info(socket_struct *ns, char *params)
Definition: request.c:1664
void set_sound_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:656
void set_up_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:116
object * ob
Definition: player.h:207
void draw_client_map(object *pl)
Definition: request.c:1371
void toggle_extended_infos_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:359
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
void lock_item_cmd(uint8 *data, int len, player *pl)
Definition: item.c:615
void esrv_draw_look(object *pl)
Definition: item.c:191
static const struct player_cmd_mapping player_commands[]
Definition: loop.c:112
unsigned long todtick
Definition: init.c:418
uint32 update_look
Definition: newserver.h:131
void init_connection(socket_struct *ns, const char *from_ip)
Definition: init.c:75
const char * cmdname
Definition: loop.c:84
void send_tick(player *pl)
Definition: request.c:1863
void send_spell_paths(socket_struct *ns, char *params)
Definition: request.c:1530
void request_info_cmd(char *buf, int len, socket_struct *ns)
Definition: loop.c:146
void write_cs_stats(void)
void(* func_uint8_int_ns)(char *, int, socket_struct *)
Definition: loop.c:80
struct timeval timeout
Definition: newserver.h:172
struct Settings settings
Definition: init.c:48
void ask_smooth_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:473
void toggle_extended_text_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:398
void examine_cmd(char *buf, int len, player *pl)
Definition: item.c:562
void apply_cmd(char *buf, int len, player *pl)
Definition: item.c:581
static void block_until_new_connection(void)
Definition: loop.c:309
EXTERN player * first_player
Definition: global.h:190
time_t time_start
Definition: newclient.h:584
struct pl * next
Definition: player.h:147
#define UPD_WEIGHT
Definition: newclient.h:256
void watchdog(void)
void final_free_player(player *pl)
Definition: init.c:328
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
void add_me_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:320
unsigned int uint32
Definition: global.h:58
void send_race_list(socket_struct *ns, char *params)
Definition: request.c:1578
void reply_cmd(char *buf, int len, player *pl)
Definition: request.c:555
char * strerror_local(int errnum, char *buf, size_t size)
Definition: porting.c:525
void SockList_NullTerminate(SockList *sl)
Definition: lowlevel.c:222
void esrv_update_stats(player *pl)
Definition: request.c:779
int SockList_ReadPacket(int fd, SockList *sl, int len)
Definition: lowlevel.c:260
void send_face_cmd(char *buff, int len, socket_struct *ns)
Definition: image.c:80
void move_cmd(char *buf, int len, player *pl)
Definition: request.c:694
SockList inbuf
Definition: newserver.h:124
void Send_With_Handling(socket_struct *ns, SockList *sl)
Definition: lowlevel.c:541