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