Crossfire Server, Trunk  R21120
loop.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
25 #include "global.h"
26 
27 #include <arpa/inet.h>
28 #include <assert.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 
35 #ifndef WIN32 /* ---win32 exclude unix headers */
36 #include <sys/types.h>
37 #include <sys/time.h>
38 #include <netinet/in.h>
39 #include <netdb.h>
40 #endif /* end win32 */
41 
42 #include "image.h"
43 #include "newserver.h"
44 #include "sockproto.h"
45 #include "sproto.h"
46 
47 /*****************************************************************************
48  * Start of command dispatch area.
49  * The commands here are protocol commands.
50  ****************************************************************************/
51 
52 /* Either keep this near the start or end of the file so it is
53  * at least reasonablye easy to find.
54  * There are really 2 commands - those which are sent/received
55  * before player joins, and those happen after the player has joined.
56  * As such, we have function types that might be called, so
57  * we end up having 2 tables.
58  */
59 
61 typedef void (*func_uint8_int_ns)(char *, int, socket_struct *);
62 
65  const char *cmdname;
67 };
68 
70 typedef void (*func_uint8_int_pl)(char *, int, player *);
73  const char *cmdname;
75  const uint8_t flag;
76 };
77 
93 static const struct player_cmd_mapping player_commands[] = {
94  { "examine", examine_cmd, 1 },
95  { "apply", apply_cmd, 1 },
96  { "move", move_cmd, 1 },
97  { "reply", reply_cmd, 0 },
98  { "ncom", (func_uint8_int_pl)new_player_cmd, 1 },
99  { "lookat", look_at_cmd, 1 },
100  { "lock", (func_uint8_int_pl)lock_item_cmd, 1 },
101  { "mark", (func_uint8_int_pl)mark_item_cmd, 1 },
102  { "inscribe", inscribe_scroll_cmd, 0 },
103  { NULL, NULL, 0 } /* terminator */
104 };
105 
107 static const struct client_cmd_mapping client_commands[] = {
108  { "addme", add_me_cmd },
109  { "askface", send_face_cmd }, /* Added: phil */
110  { "beat", NULL },
111  { "requestinfo", request_info_cmd },
112  { "setup", set_up_cmd },
113  { "version", version_cmd },
114  { "asksmooth", ask_smooth_cmd }, /*Added: tchize (smoothing technologies)*/
115  { "accountlogin", account_login_cmd },
116  { "accountnew", account_new_cmd },
117  { "accountaddplayer", account_add_player_cmd },
118  { "accountplay", account_play_cmd },
119  { "accountpw", account_password },
120  { "createplayer", create_player_cmd },
121  { NULL, NULL } /* terminator (I, II & III)*/
122 };
123 
132 void request_info_cmd(char *buf, int len, socket_struct *ns) {
133  char *params = NULL, *cp;
134  /* No match */
135  SockList sl;
136 
137  if (len <= 0 || !buf) {
138  LOG(llevDebug, "IP '%s' sent bogus request_info_cmd information\n", ns->host);
139  return;
140  }
141 
142  /* Set up replyinfo before we modify any of the buffers - this is used
143  * if we don't find a match.
144  */
145  SockList_Init(&sl);
146  SockList_AddString(&sl, "replyinfo ");
147  SockList_AddString(&sl, buf);
148 
149  /* find the first space, make it null, and update the
150  * params pointer.
151  */
152  for (cp = buf; *cp != '\0'; cp++)
153  if (*cp == ' ') {
154  *cp = '\0';
155  params = cp+1;
156  break;
157  }
158  if (!strcmp(buf, "image_info"))
159  send_image_info(ns);
160  else if (!strcmp(buf, "image_sums"))
161  send_image_sums(ns, params);
162  else if (!strcmp(buf, "skill_info"))
163  send_skill_info(ns, params);
164  else if (!strcmp(buf, "spell_paths"))
165  send_spell_paths(ns, params);
166  else if (!strcmp(buf, "exp_table"))
167  send_exp_table(ns, params);
168  else if (!strcmp(buf, "race_list"))
169  send_race_list(ns, params);
170  else if (!strcmp(buf, "race_info"))
171  send_race_info(ns, params);
172  else if (!strcmp(buf, "class_list"))
173  send_class_list(ns, params);
174  else if (!strcmp(buf, "class_info"))
175  send_class_info(ns, params);
176  else if (!strcmp(buf, "rules"))
177  send_file(ns, "rules");
178  else if (!strcmp(buf, "motd"))
179  send_file(ns, "motd");
180  else if (!strcmp(buf, "news"))
181  send_file(ns, "news");
182  else if (!strcmp(buf,"newcharinfo"))
183  send_new_char_info(ns);
184  else if (!strcmp(buf,"startingmap"))
185  send_map_info(ns);
186  else if (!strcmp(buf, "knowledge_info"))
188  else
189  Send_With_Handling(ns, &sl);
190  SockList_Term(&sl);
191 }
192 
193 static int
194 handle_cmd(socket_struct *ns, player *pl, char *cmd, char *data, int len) {
195  /* Fuzz testing indicated a way to get a null command here
196  * --> make an empty command, but have a length.
197  * So, if we get here with a null command, log it and exit the function.
198  * Daniel Hawkins 2020-01-16
199  */
200  if (cmd == NULL) {
201  LOG(llevDebug, "%s: missing command. Sending garbage?\n", ns->host);
202  return 0;
203  }
204  for (int i = 0; client_commands[i].cmdname != NULL; i++) {
205  if (strcmp(cmd, client_commands[i].cmdname) == 0) {
206  if (client_commands[i].cmdproc != NULL) {
207  client_commands[i].cmdproc(data, len, ns);
208  }
209  return 0;
210  }
211  }
212  /* Player must be in the playing state or the flag on the
213  * the command must be zero for the user to use the command -
214  * otherwise, a player cam save, be in the play_again state, and
215  * the map they were on getsswapped out, yet things that try to look
216  * at the map causes a crash. If the command is valid, but
217  * one they can't use, we still swallow it up.
218  */
219  if (pl) {
220  for (int i = 0; player_commands[i].cmdname != NULL; i++) {
221  if (strcmp(cmd, player_commands[i].cmdname) == 0) {
222  if (pl->state == ST_PLAYING || player_commands[i].flag == 0) {
223  player_commands[i].cmdproc(data, len, pl);
224  }
225  return 1;
226  }
227  }
228  }
229  LOG(llevDebug, "%s: invalid command '%s'\n", ns->host, cmd);
230  return 0;
231 }
232 
243  /* Loop through this - maybe we have several complete packets here. */
244  /* Command_count is used to limit the number of requests from
245  * clients that have not logged in - we do not want an unauthenticated
246  * connection to spew us with hundreds of requests. As such,
247  * this counter is only increased in the case of socket level commands.
248  * Note that this also has the effect of throttling down face and other
249  * socket commands from the client. As such, if we have a player attached,
250  * we will process more of these, as getting a fair number when entering
251  * a map may not be uncommon.
252  */
253  int command_count = 0;
254  while (command_count < 5 || (pl && command_count < 25)) {
255  if (pl && pl->state == ST_PLAYING && pl->ob != NULL && pl->ob->speed_left < 0) {
256  // Skip processing players with no turns left.
257  return false;
258  }
259 
260  int status = SockList_ReadPacket(ns->fd, &ns->inbuf, sizeof(ns->inbuf.buf)-1);
261  if (status != 1) {
262  if (status < 0) {
263  ns->status = Ns_Dead;
264  }
265  return false;
266  }
267 
268  /* Since we have a full packet, reset last tick time. */
269  ns->last_tick = 0;
270 
272  assert(ns->inbuf.len >= 2);
273  char *data;
274  char *cmd = strtok_r((char *)ns->inbuf.buf + 2, " ", &data);
275 
276  int got_player_cmd;
277  if (data != NULL) {
278  int rem = ns->inbuf.len - ((unsigned char *)data - ns->inbuf.buf);
279  got_player_cmd = handle_cmd(ns, pl, cmd, data, rem);
280  } else {
281  got_player_cmd = handle_cmd(ns, pl, cmd, NULL, 0);
282  }
283 
285  if (got_player_cmd) {
286  return true;
287  }
288 
289  command_count += 1;
290  /* Evil case, and not a nice workaround, but well...
291  * If we receive eg an accountplay command, the socket is copied
292  * to the player structure, and its faces_sent is set to NULL.
293  * This leads to issues when processing the next commands in the queue,
294  * especially if related to faces...
295  * So get out of here in this case, which we detect because faces_sent is NULL.
296  */
297  if (ns->faces_sent == NULL) {
298  command_count = 6;
299  }
300  }
301  return false;
302 }
303 
304 /*****************************************************************************
305  *
306  * Low level socket looping - select calls and watchdog udp packet
307  * sending.
308  *
309  ******************************************************************************/
310 
311 #ifdef WATCHDOG
312 
318 void watchdog(void) {
319  static int fd = -1;
320  static struct sockaddr_in insock;
321 
322  if (fd == -1) {
323  struct protoent *protoent;
324 
325  if ((protoent = getprotobyname("udp")) == NULL
326  || (fd = socket(PF_INET, SOCK_DGRAM, protoent->p_proto)) == -1) {
327  return;
328  }
329  insock.sin_family = AF_INET;
330  insock.sin_port = htons((unsigned short)13325);
331  insock.sin_addr.s_addr = inet_addr("127.0.0.1");
332  }
333  sendto(fd, (void *)&fd, 1, 0, (struct sockaddr *)&insock, sizeof(insock));
334 }
335 #endif
336 
337 extern unsigned long todtick;
338 
342 static void block_until_new_connection(void) {
343  struct timeval Timeout;
344  fd_set readfs;
345  int cycles;
346  int i;
347 
348  LOG(llevInfo, "Waiting for connections...\n");
349 
350  cycles = 1;
351  do {
352  /* Every minutes is a bit often for updates - especially if nothing is going
353  * on. This slows it down to every 6 minutes.
354  */
355  cycles++;
356  if (cycles%2 == 0)
357  tick_the_clock();
358 
359  FD_ZERO(&readfs);
360  for (i = 0; i < socket_info.allocated_sockets && init_sockets[i].listen; i++)
361  if (init_sockets[i].status == Ns_Add)
362  FD_SET((uint32_t)init_sockets[i].fd, &readfs);
363 
364  /* If fastclock is set, we need to seriously slow down the updates
365  * to the metaserver as well as watchdog. Do same for flush_old_maps() -
366  * that is time sensitive, so there is no good reason to call it 2000 times
367  * a second.
368  */
369  if (settings.fastclock > 0) {
370 #ifdef WATCHDOG
371  if (cycles%120000 == 0) {
372  watchdog();
373  flush_old_maps();
374  }
375 #endif
376  if (cycles == 720000) {
378  cycles = 1;
379  }
380  Timeout.tv_sec = 0;
381  Timeout.tv_usec = 50;
382  } else {
383  Timeout.tv_sec = 60;
384  Timeout.tv_usec = 0;
385  if (cycles == 7) {
387  cycles = 1;
388  }
389  flush_old_maps();
390  }
391  } while (select(socket_info.max_filedescriptor, &readfs, NULL, NULL, &Timeout) == 0);
392 
393  reset_sleep(); /* Or the game would go too fast */
394 }
395 
404 static int is_fd_valid(int fd) {
405 #ifndef WIN32
406  return fcntl(fd, F_GETFL) != -1 || errno != EBADF;
407 #else
408  return 1;
409 #endif
410 }
411 
416 static void new_connection(int listen_fd) {
417  int newsocknum = -1, j;
418 #ifdef HAVE_GETNAMEINFO
419  struct sockaddr_storage addr;
420 #else
421  struct sockaddr_in addr;
422 #endif
423  socklen_t addrlen = sizeof(addr);
424 
425 #ifdef ESRV_DEBUG
426  LOG(llevDebug, "do_server: New Connection\n");
427 #endif
428 
429  for (j = 0; j < socket_info.allocated_sockets; j++)
430  if (init_sockets[j].status == Ns_Avail) {
431  newsocknum = j;
432  break;
433  }
434 
435  if (newsocknum == -1) {
436  /* If this is the case, all sockets currently in used */
438  if (!init_sockets)
440  newsocknum = socket_info.allocated_sockets;
442  init_sockets[newsocknum].listen = NULL;
444  init_sockets[newsocknum].faces_sent = calloc(nrofpixmaps, sizeof(*init_sockets[newsocknum].faces_sent));
445  if (!init_sockets[newsocknum].faces_sent)
447  init_sockets[newsocknum].status = Ns_Avail;
448  }
449 
450  if (newsocknum < 0) {
451  LOG(llevError, "FATAL: didn't allocate a newsocket?? alloc = %d, newsocknum = %d", socket_info.allocated_sockets, newsocknum);
453  }
454 
455  init_sockets[newsocknum].fd = accept(listen_fd, (struct sockaddr *)&addr, &addrlen);
456  if (init_sockets[newsocknum].fd == -1) {
457  LOG(llevError, "accept failed: %s\n", strerror(errno));
458  } else {
459  char buf[MAX_BUF];
460 #ifndef HAVE_GETNAMEINFO
461  long ip;
462 #endif
463  socket_struct *ns;
464 
465  ns = &init_sockets[newsocknum];
466 
467 #ifdef HAVE_GETNAMEINFO
468  getnameinfo((struct sockaddr *) &addr, addrlen, buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
469 #else
470  ip = ntohl(addr.sin_addr.s_addr);
471  snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld", (ip>>24)&255, (ip>>16)&255, (ip>>8)&255, ip&255);
472 #endif
473 
474  if (checkbanned(NULL, buf)) {
475  LOG(llevInfo, "Banned host tried to connect: [%s]\n", buf);
476  close(init_sockets[newsocknum].fd);
477  init_sockets[newsocknum].fd = -1;
478  } else {
479  init_connection(ns, buf);
480  }
481  }
482 }
483 
490  // If the client doesn't send heartbeats, assume it's connected.
491  if (!socket.heartbeat) {
492  return true;
493  }
494 
495  // If a client message was received recently, it's connected.
496  if (socket.last_tick < tick_length(BEAT_INTERVAL + 1)) {
497  return true;
498  }
499 
500  return false;
501 }
502 
506 static void send_updates(player *pl) {
507  /* Update the players stats once per tick. More efficient than
508  * sending them whenever they change, and probably just as useful
509  */
510  esrv_update_stats(pl);
511  if (pl->last_weight != -1 && pl->last_weight != WEIGHT(pl->ob)) {
512  esrv_update_item(UPD_WEIGHT, pl->ob, pl->ob);
513  if (pl->last_weight != WEIGHT(pl->ob))
514  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));
515  }
516  /* draw_client_map does sanity checking that map is
517  * valid, so don't do it here.
518  */
519  draw_client_map(pl->ob);
520  if (pl->socket.update_look)
521  esrv_draw_look(pl->ob);
522  if (pl->socket.update_inventory) {
523  if (pl->ob->container != NULL)
524  esrv_send_inventory(pl->ob, pl->ob->container);
525  pl->socket.update_inventory = 0;
526  }
527 }
528 
536 void do_server(void) {
537  fd_set tmp_read, tmp_exceptions;
538  int active = 0;
539  FD_ZERO(&tmp_read);
540  FD_ZERO(&tmp_exceptions);
541 
542  for (int i = 0; i < socket_info.allocated_sockets; i++) {
543  if (init_sockets[i].status == Ns_Add && !is_fd_valid(init_sockets[i].fd)) {
544  LOG(llevError, "do_server: invalid waiting fd %d\n", i);
546  }
547  if (init_sockets[i].status == Ns_Dead) {
548  LOG(llevInfo, "Disconnected from %s\n", init_sockets[i].host);
549  if (init_sockets[i].listen) {
550  /* try to reopen the listening socket */
552  } else {
555  }
556  } else if (init_sockets[i].status != Ns_Avail) {
557  FD_SET((uint32_t)init_sockets[i].fd, &tmp_read);
558  FD_SET((uint32_t)init_sockets[i].fd, &tmp_exceptions);
559  active++;
560  }
561  }
562 
563  /* Go through the players. Let the loop set the next pl value,
564  * since we may remove some
565  */
566  player *pl, *next;
567  for (pl = first_player; pl != NULL; ) {
568  if (pl->socket.status != Ns_Dead && !is_fd_valid(pl->socket.fd)) {
569  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);
570  pl->socket.status = Ns_Dead;
571  }
572 
573  if (pl->socket.status == Ns_Dead) {
574  player *npl = pl->next;
575 
576  save_player(pl->ob, 0);
577  leave(pl, 1);
578  final_free_player(pl);
579  pl = npl;
580  } else {
581  FD_SET((uint32_t)pl->socket.fd, &tmp_read);
582  FD_SET((uint32_t)pl->socket.fd, &tmp_exceptions);
583  pl = pl->next;
584  }
585  }
586 
587  if (active == 1 && first_player == NULL)
589 
590  long sleep_time = get_sleep_remaining();
591  if (sleep_time < 0) {
592  LOG(llevInfo, "skipping time (over by %ld microseconds)\n", -sleep_time);
593  jump_time();
594  }
595 
596  while (sleep_time > 0) {
597  socket_info.timeout.tv_sec = 0;
598  socket_info.timeout.tv_usec = sleep_time;
599  int pollret = select(socket_info.max_filedescriptor, &tmp_read, NULL,
600  &tmp_exceptions, &socket_info.timeout);
601  if (pollret == -1) {
602  if (errno != EINTR) {
603  LOG(llevError, "select failed: %s\n", strerror(errno));
604  }
605  return;
606  } else if (!pollret) {
607  return;
608  }
609 
610  /* Check for any exceptions/input on the sockets */
611  for (int i = 0; i < socket_info.allocated_sockets; i++) {
612  /* listen sockets can stay in status Ns_Dead */
613  if (init_sockets[i].status != Ns_Add) {
614  continue;
615  }
616  if (FD_ISSET(init_sockets[i].fd, &tmp_exceptions)) {
619  continue;
620  }
621  if (FD_ISSET(init_sockets[i].fd, &tmp_read)) {
622  if (init_sockets[i].listen)
624  else
625  handle_client(&init_sockets[i], NULL);
626  }
627  }
628 
629  /* This does roughly the same thing, but for the players now */
630  for (pl = first_player; pl != NULL; pl = next) {
631  next = pl->next;
632  if (pl->socket.status == Ns_Dead)
633  continue;
634 
635  if (FD_ISSET(pl->socket.fd, &tmp_exceptions)) {
636  save_player(pl->ob, 0);
637  leave(pl, 1);
638  final_free_player(pl);
639  } else {
640  bool keep_processing = handle_client(&pl->socket, pl);
641  if (!keep_processing) {
642  FD_CLR(pl->socket.fd, &tmp_read);
643  }
644 
645  /* There seems to be rare cases where next points to a removed/freed player.
646  * My belief is that this player does something (shout, move, whatever)
647  * that causes data to be sent to the next player on the list, but
648  * that player is defunct, so the socket codes removes that player.
649  * End result is that next now points at the removed player, and
650  * that has garbage data so we crash. So update the next pointer
651  * while pl is still valid. MSW 2007-04-21
652  */
653  next = pl->next;
654 
655 
656  /* If the player has left the game, then the socket status
657  * will be set to this be the leave function. We don't
658  * need to call leave again, as it has already been called
659  * once.
660  */
661  if (pl->socket.status == Ns_Dead) {
662  save_player(pl->ob, 0);
663  leave(pl, 1);
664  final_free_player(pl);
665  } else {
666  send_updates(pl);
667  }
668  }
669  }
670  sleep_time = get_sleep_remaining();
671  }
672 }
673 
678  player *pl, *next;
679  for (pl = first_player; pl != NULL; pl = next) {
680  next = pl->next;
681  send_updates(pl);
682  /* Increment time since last contact only if logged in. */
683  if (pl->state == ST_PLAYING) {
684  pl->socket.last_tick++;
685 
686  if (!connection_alive(pl->socket)) {
687  // TODO: Handle a lost client connection.
688  LOG(llevDebug, "Lost client connection!\n");
689  }
690  }
691 
692  if (pl->socket.tick)
693  send_tick(pl);
694  }
695 }
const char * cmdname
Definition: loop.c:73
Definition: player.h:92
static void send_updates(player *pl)
Definition: loop.c:506
size_t len
Definition: newclient.h:685
uint32_t tick
Definition: newserver.h:106
void leave(player *pl, int draw_exit)
Definition: server.c:1201
const func_uint8_int_ns cmdproc
Definition: loop.c:66
void SockList_Init(SockList *sl)
Definition: lowlevel.c:48
unsigned char buf[MAXSOCKBUF]
Definition: newclient.h:686
void account_login_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:2057
unsigned char uint8_t
Definition: win32.h:161
void SockList_ResetRead(SockList *sl)
Definition: lowlevel.c:75
void mark_item_cmd(uint8_t *data, int len, player *pl)
Definition: item.c:725
void look_at_cmd(char *buf, int len, player *pl)
Definition: item.c:821
void version_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:583
void metaserver_update(void)
Definition: metaserver.c:49
struct obj * container
Definition: object.h:291
const func_uint8_int_pl cmdproc
Definition: loop.c:74
void fatal(enum fatal_error err)
Definition: utils.c:597
uint32_t last_tick
Definition: newserver.h:130
int save_player(object *op, int flag)
Definition: login.c:211
void do_server(void)
Definition: loop.c:536
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.c:342
void send_map_info(socket_struct *ns)
Definition: requestinfo.c:404
void send_image_sums(socket_struct *ns, char *params)
Definition: image.c:139
socket_struct socket
Definition: player.h:94
void esrv_send_inventory(object *pl, object *op)
Definition: item.c:307
bool heartbeat
Definition: newserver.h:112
void new_player_cmd(uint8_t *buf, int len, player *pl)
Definition: request.c:449
int checkbanned(const char *login, const char *host)
Definition: ban.c:32
enum Sock_Status status
Definition: newserver.h:90
#define socklen_t
Definition: win32.h:130
void inscribe_scroll_cmd(char *buf, int len, player *pl)
Definition: item.c:910
int max_filedescriptor
Definition: newserver.h:143
void send_skill_info(socket_struct *ns, char *params)
Definition: requestinfo.c:67
#define ST_PLAYING
Definition: define.h:579
int tick_length(float seconds)
Definition: time.c:378
char * host
Definition: newserver.h:100
unsigned int nrofpixmaps
Definition: image.c:45
socket_struct * init_sockets
Definition: init.c:56
void send_class_list(socket_struct *ns, char *params)
Definition: requestinfo.c:359
void free_newsocket(socket_struct *ns)
Definition: init.c:413
size_t faces_sent_len
Definition: newserver.h:95
uint32_t update_look
Definition: newserver.h:104
static int handle_cmd(socket_struct *ns, player *pl, char *cmd, char *data, int len)
Definition: loop.c:194
const uint8_t flag
Definition: loop.c:75
void flush_old_maps(void)
Definition: swap.c:289
static const struct client_cmd_mapping client_commands[]
Definition: loop.c:107
#define strtok_r(x, y, z)
Definition: win32.h:62
Socket_Info socket_info
Definition: init.c:47
float speed_left
Definition: object.h:329
void send_exp_table(socket_struct *ns, char *params)
Definition: requestinfo.c:121
#define BEAT_INTERVAL
Definition: config.h:680
void SockList_Term(SockList *sl)
Definition: lowlevel.c:58
#define snprintf
Definition: win32.h:46
long get_sleep_remaining()
Definition: time.c:184
void(* func_uint8_int_ns)(char *, int, socket_struct *)
Definition: loop.c:61
void update_players()
Definition: loop.c:677
void account_password(char *buf, int len, socket_struct *ns)
Definition: request.c:2887
bool connection_alive(socket_struct socket)
Definition: loop.c:489
const char * name
Definition: object.h:311
#define WEIGHT(op)
Definition: define.h:688
void jump_time()
Definition: time.c:192
void init_listening_socket(socket_struct *ns)
Definition: init.c:171
uint8_t state
Definition: player.h:118
void SockList_AddString(SockList *sl, const char *data)
Definition: lowlevel.c:149
void account_new_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:2184
uint32_t update_inventory
Definition: newserver.h:105
void send_race_info(socket_struct *ns, char *params)
Definition: requestinfo.c:313
#define UPD_WEIGHT
Definition: newclient.h:291
void tick_the_clock(void)
Definition: weather.c:96
int allocated_sockets
Definition: newserver.h:144
void send_image_info(socket_struct *ns)
Definition: image.c:112
#define MAX_BUF
Definition: define.h:35
static int is_fd_valid(int fd)
Definition: loop.c:404
void reset_sleep(void)
Definition: time.c:130
void send_class_info(socket_struct *ns, char *params)
Definition: requestinfo.c:380
void set_up_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:93
object * ob
Definition: player.h:158
void draw_client_map(object *pl)
Definition: request.c:1456
unsigned int uint32_t
Definition: win32.h:162
void esrv_draw_look(object *pl)
Definition: item.c:187
static const struct player_cmd_mapping player_commands[]
Definition: loop.c:93
unsigned long todtick
Definition: init.c:407
void init_connection(socket_struct *ns, const char *from_ip)
Definition: init.c:83
const char * cmdname
Definition: loop.c:65
void send_tick(player *pl)
Definition: request.c:1817
void send_spell_paths(socket_struct *ns, char *params)
Definition: requestinfo.c:97
void request_info_cmd(char *buf, int len, socket_struct *ns)
Definition: loop.c:132
int32_t last_weight
Definition: player.h:142
void lock_item_cmd(uint8_t *data, int len, player *pl)
Definition: item.c:673
struct timeval timeout
Definition: newserver.h:142
struct Settings settings
Definition: init.c:40
void ask_smooth_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:425
void(* func_uint8_int_pl)(char *, int, player *)
Definition: loop.c:70
void send_file(socket_struct *ns, const char *file)
Definition: requestinfo.c:443
bool handle_client(socket_struct *ns, player *pl)
Definition: loop.c:242
void examine_cmd(char *buf, int len, player *pl)
Definition: item.c:614
uint8_t fastclock
Definition: global.h:294
void apply_cmd(char *buf, int len, player *pl)
Definition: item.c:633
static void block_until_new_connection(void)
Definition: loop.c:342
EXTERN player * first_player
Definition: global.h:117
struct pl * next
Definition: player.h:93
void account_add_player_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:2292
void watchdog(void)
void final_free_player(player *pl)
Definition: init.c:444
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
void add_me_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:347
void send_race_list(socket_struct *ns, char *params)
Definition: requestinfo.c:292
void reply_cmd(char *buf, int len, player *pl)
Definition: request.c:511
void send_new_char_info(socket_struct *ns)
Definition: requestinfo.c:484
static void new_connection(int listen_fd)
Definition: loop.c:416
void knowledge_send_info(socket_struct *ns)
Definition: knowledge.c:1382
void SockList_NullTerminate(SockList *sl)
Definition: lowlevel.c:229
void esrv_update_stats(player *pl)
Definition: request.c:728
int SockList_ReadPacket(int fd, SockList *sl, int len)
Definition: lowlevel.c:267
void send_face_cmd(char *buff, int len, socket_struct *ns)
Definition: image.c:43
struct listen_info * listen
Definition: newserver.h:92
uint8_t * faces_sent
Definition: newserver.h:96
void move_cmd(char *buf, int len, player *pl)
Definition: request.c:639
void create_player_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:2508
SockList inbuf
Definition: newserver.h:99
void Send_With_Handling(socket_struct *ns, SockList *sl)
Definition: lowlevel.c:434
void account_play_cmd(char *buf, int len, socket_struct *ns)
Definition: request.c:2421