Crossfire Server, Trunk
loop.cpp
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 extern uint32_t last_time;
50 
51 /*****************************************************************************
52  * Start of command dispatch area.
53  * The commands here are protocol commands.
54  ****************************************************************************/
55 
56 /* Either keep this near the start or end of the file so it is
57  * at least reasonablye easy to find.
58  * There are really 2 commands - those which are sent/received
59  * before player joins, and those happen after the player has joined.
60  * As such, we have function types that might be called, so
61  * we end up having 2 tables.
62  */
63 
65 typedef void (*func_uint8_int_ns)(char *, int, socket_struct *);
66 
69  const char *cmdname;
71 };
72 
74 typedef void (*func_uint8_int_pl)(char *, int, player *);
77  const char *cmdname;
79  const uint8_t flag;
80 };
81 
97 static const struct player_cmd_mapping player_commands[] = {
98  { "examine", examine_cmd, 1 },
99  { "apply", apply_cmd, 1 },
100  { "move", move_cmd, 1 },
101  { "reply", reply_cmd, 0 },
102  { "ncom", (func_uint8_int_pl)new_player_cmd, 1 },
103  { "lookat", look_at_cmd, 1 },
104  { "lock", (func_uint8_int_pl)lock_item_cmd, 1 },
105  { "mark", (func_uint8_int_pl)mark_item_cmd, 1 },
106  { "inscribe", inscribe_scroll_cmd, 0 },
107  { NULL, NULL, 0 } /* terminator */
108 };
109 
111 static const struct client_cmd_mapping client_commands[] = {
112  { "addme", add_me_cmd },
113  { "askface", send_face_cmd }, /* Added: phil */
114  { "beat", NULL },
115  { "requestinfo", request_info_cmd },
116  { "setup", set_up_cmd },
117  { "version", version_cmd },
118  { "asksmooth", ask_smooth_cmd }, /*Added: tchize (smoothing technologies)*/
119  { "accountlogin", account_login_cmd },
120  { "accountnew", account_new_cmd },
121  { "accountaddplayer", account_add_player_cmd },
122  { "accountplay", account_play_cmd },
123  { "accountpw", account_password },
124  { "createplayer", create_player_cmd },
125  { NULL, NULL } /* terminator (I, II & III)*/
126 };
127 
136 void request_info_cmd(char *buf, int len, socket_struct *ns) {
137  char *params = NULL, *cp;
138  /* No match */
139  SockList sl;
140 
141  if (len <= 0 || !buf) {
142  LOG(llevDebug, "IP '%s' sent bogus request_info_cmd information\n", ns->host);
143  return;
144  }
145 
146  /* Set up replyinfo before we modify any of the buffers - this is used
147  * if we don't find a match.
148  */
149  SockList_Init(&sl);
150  SockList_AddString(&sl, "replyinfo ");
151  SockList_AddString(&sl, buf);
152 
153  /* find the first space, make it null, and update the
154  * params pointer.
155  */
156  for (cp = buf; *cp != '\0'; cp++)
157  if (*cp == ' ') {
158  *cp = '\0';
159  params = cp+1;
160  break;
161  }
162  if (!strcmp(buf, "image_info"))
163  send_image_info(ns);
164  else if (!strcmp(buf, "image_sums"))
165  send_image_sums(ns, params);
166  else if (!strcmp(buf, "skill_info"))
167  send_skill_info(ns, params);
168  else if (!strcmp(buf, "skill_extra"))
170  else if (!strcmp(buf, "spell_paths"))
171  send_spell_paths(ns);
172  else if (!strcmp(buf, "exp_table"))
173  send_exp_table(ns);
174  else if (!strcmp(buf, "race_list"))
175  send_race_list(ns);
176  else if (!strcmp(buf, "race_info"))
177  send_race_info(ns, params);
178  else if (!strcmp(buf, "class_list"))
179  send_class_list(ns);
180  else if (!strcmp(buf, "class_info"))
181  send_class_info(ns, params);
182  else if (!strcmp(buf, "rules"))
183  send_file(ns, "rules");
184  else if (!strcmp(buf, "motd"))
185  send_file(ns, "motd");
186  else if (!strcmp(buf, "news"))
187  send_file(ns, "news");
188  else if (!strcmp(buf,"newcharinfo"))
189  send_new_char_info(ns);
190  else if (!strcmp(buf,"startingmap"))
191  send_map_info(ns);
192  else if (!strcmp(buf, "knowledge_info"))
194  else
195  Send_With_Handling(ns, &sl);
196  SockList_Term(&sl);
197 }
198 
208 static int
209 handle_cmd(socket_struct *ns, player *pl, char *cmd, char *data, int len) {
210  /* Fuzz testing indicated a way to get a null command here
211  * --> make an empty command, but have a length.
212  * So, if we get here with a null command, log it and exit the function.
213  * Neila Hawkins 2020-01-16
214  */
215  if (cmd == NULL) {
216  LOG(llevDebug, "%s: missing command. Sending garbage?\n", ns->host);
217  return 0;
218  }
219  for (int i = 0; client_commands[i].cmdname != NULL; i++) {
220  if (strcmp(cmd, client_commands[i].cmdname) == 0) {
221  if (client_commands[i].cmdproc != NULL) {
222  client_commands[i].cmdproc(data, len, ns);
223  }
224  return 0;
225  }
226  }
227  /* Player must be in the playing state or the flag on the
228  * the command must be zero for the user to use the command -
229  * otherwise, a player cam save, be in the play_again state, and
230  * the map they were on getsswapped out, yet things that try to look
231  * at the map causes a crash. If the command is valid, but
232  * one they can't use, we still swallow it up.
233  */
234  if (pl) {
235  for (int i = 0; player_commands[i].cmdname != NULL; i++) {
236  if (strcmp(cmd, player_commands[i].cmdname) == 0) {
237  if (pl->state == ST_PLAYING || player_commands[i].flag == 0) {
238  player_commands[i].cmdproc(data, len, pl);
239  }
240  return 1;
241  }
242  }
243  }
244  LOG(llevDebug, "%s: invalid command '%s'\n", ns->host, cmd);
245  return 0;
246 }
247 
258  /* Loop through this - maybe we have several complete packets here. */
259  /* Command_count is used to limit the number of requests from
260  * clients that have not logged in - we do not want an unauthenticated
261  * connection to spew us with hundreds of requests. As such,
262  * this counter is only increased in the case of socket level commands.
263  * Note that this also has the effect of throttling down face and other
264  * socket commands from the client. As such, if we have a player attached,
265  * we will process more of these, as getting a fair number when entering
266  * a map may not be uncommon.
267  */
268  int command_count = 0;
269  while (command_count < 5 || (pl && command_count < 25)) {
270  if (pl && pl->state == ST_PLAYING && pl->ob != NULL && pl->ob->speed_left < 0) {
271  // Skip processing players with no turns left.
272  return false;
273  }
274 
275  int status = SockList_ReadPacket(ns->fd, &ns->inbuf, sizeof(ns->inbuf.buf)-1);
276  if (status != 1) {
277  if (status < 0) {
278  ns->status = Ns_Dead;
279  }
280  return false;
281  }
282 
283  /* Since we have a full packet, reset last tick time. */
284  ns->last_tick = 0;
285 
287  assert(ns->inbuf.len >= 2);
288  char *data;
289  char *cmd = strtok_r((char *)ns->inbuf.buf + 2, " ", &data);
290 
291  int got_player_cmd;
292  if (data != NULL) {
293  int rem = ns->inbuf.len - ((unsigned char *)data - ns->inbuf.buf);
294  got_player_cmd = handle_cmd(ns, pl, cmd, data, rem);
295  } else {
296  got_player_cmd = handle_cmd(ns, pl, cmd, NULL, 0);
297  }
298 
300  if (got_player_cmd) {
301  return true;
302  }
303 
304  command_count += 1;
305  /* Evil case, and not a nice workaround, but well...
306  * If we receive eg an accountplay command, the socket is copied
307  * to the player structure, and its faces_sent is set to NULL.
308  * This leads to issues when processing the next commands in the queue,
309  * especially if related to faces...
310  * So get out of here in this case, which we detect because faces_sent is NULL.
311  */
312  if (ns->faces_sent == NULL) {
313  command_count = 6;
314  }
315  }
316  return false;
317 }
318 
319 /*****************************************************************************
320  *
321  * Low level socket looping - select calls and watchdog udp packet
322  * sending.
323  *
324  ******************************************************************************/
325 
326 #ifdef WATCHDOG
327 
333 void watchdog(void) {
334  static int fd = -1;
335  static struct sockaddr_in insock;
336 
337  if (fd == -1) {
338  struct protoent *protoent;
339 
340  if ((protoent = getprotobyname("udp")) == NULL
341  || (fd = socket(PF_INET, SOCK_DGRAM, protoent->p_proto)) == -1) {
342  return;
343  }
344  insock.sin_family = AF_INET;
345  insock.sin_port = htons((unsigned short)13325);
346  insock.sin_addr.s_addr = inet_addr("127.0.0.1");
347  }
348  char buf[MAX_BUF];
349  snprintf(buf, sizeof(buf), "%d\n", pticks);
350  sendto(fd, buf, strlen(buf), 0, (struct sockaddr *)&insock, sizeof(insock));
351 }
352 #endif
353 
362 static int is_fd_valid(int fd) {
363 #ifndef WIN32
364  return fcntl(fd, F_GETFL) != -1 || errno != EBADF;
365 #else
366  return 1;
367 #endif
368 }
369 
374 static void new_connection(int listen_fd) {
375  int newsocknum = -1, j;
376 #ifdef HAVE_GETNAMEINFO
377  struct sockaddr_storage addr;
378 #else
379  struct sockaddr_in addr;
380 #endif
381  socklen_t addrlen = sizeof(addr);
382 
383 #ifdef ESRV_DEBUG
384  LOG(llevDebug, "do_server: New Connection\n");
385 #endif
386 
387  for (j = 0; j < socket_info.allocated_sockets; j++)
388  if (init_sockets[j].status == Ns_Avail) {
389  newsocknum = j;
390  break;
391  }
392 
393  if (newsocknum == -1) {
394  /* If this is the case, all sockets currently in used */
395  init_sockets = static_cast<socket_struct *>(realloc(init_sockets, sizeof(socket_struct)*(socket_info.allocated_sockets+1)));
396  if (!init_sockets)
398  newsocknum = socket_info.allocated_sockets;
400  memset(&init_sockets[newsocknum], 0, sizeof(*init_sockets));
401  init_sockets[newsocknum].listen = NULL;
403  init_sockets[newsocknum].faces_sent = static_cast<uint8_t *>(calloc(get_faces_count(), sizeof(*init_sockets[newsocknum].faces_sent)));
404  if (!init_sockets[newsocknum].faces_sent)
406  init_sockets[newsocknum].status = Ns_Avail;
407  }
408 
409  if (newsocknum < 0) {
410  LOG(llevError, "FATAL: didn't allocate a newsocket?? alloc = %d, newsocknum = %d", socket_info.allocated_sockets, newsocknum);
412  }
413 
414  init_sockets[newsocknum].fd = accept(listen_fd, (struct sockaddr *)&addr, &addrlen);
415  if (init_sockets[newsocknum].fd == -1) {
416  LOG(llevError, "accept failed: %s\n", strerror(errno));
417  } else {
418  char buf[MAX_BUF];
419 #ifndef HAVE_GETNAMEINFO
420  long ip;
421 #endif
422  socket_struct *ns;
423 
424  ns = &init_sockets[newsocknum];
425 
426 #ifdef HAVE_GETNAMEINFO
427  getnameinfo((struct sockaddr *) &addr, addrlen, buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
428 #else
429  ip = ntohl(addr.sin_addr.s_addr);
430  snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld", (ip>>24)&255, (ip>>16)&255, (ip>>8)&255, ip&255);
431 #endif
432 
433  if (checkbanned(NULL, buf)) {
434  LOG(llevInfo, "Banned host tried to connect: [%s]\n", buf);
435  close(init_sockets[newsocknum].fd);
436  init_sockets[newsocknum].fd = -1;
437  } else {
438  init_connection(ns, buf);
439  }
440  }
441 }
442 
448 bool connection_alive(const socket_struct *socket) {
449  // If the client doesn't send heartbeats, assume it's connected.
450  if (!socket->heartbeat) {
451  return true;
452  }
453 
454  // If a client message was received recently, it's connected.
455  if (socket->last_tick < tick_length(BEAT_INTERVAL + 1)) {
456  return true;
457  }
458 
459  return false;
460 }
461 
467  for (uint8_t buf = 0; buf < pl->delayed_buffers_used; buf++) {
468  Send_With_Handling(pl->socket, pl->delayed_buffers[buf]);
469  }
470  pl->delayed_buffers_used = 0;
471 }
472 
476 static void send_updates(player *pl) {
477  /* Update the players stats once per tick. More efficient than
478  * sending them whenever they change, and probably just as useful
479  */
481  if (pl->last_weight != -1 && pl->last_weight != WEIGHT(pl->ob)) {
482  esrv_update_item(UPD_WEIGHT, pl->ob, pl->ob);
483  if (pl->last_weight != WEIGHT(pl->ob))
484  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));
485  }
486  /* draw_client_map does sanity checking that map is
487  * valid, so don't do it here.
488  */
489  draw_client_map(pl->ob);
490  if (pl->socket->update_look)
491  esrv_draw_look(pl->ob);
492  if (pl->socket->update_inventory) {
493  if (pl->ob->container != NULL)
494  esrv_send_inventory(pl->ob, pl->ob->container);
495  pl->socket->update_inventory = 0;
496  }
497 }
498 
513  for (int i = 0; i < socket_info.allocated_sockets; i++) {
514  if (!is_fd_valid(init_sockets[i].fd)) {
516  // prevent a memory leak in pre-player clients with faces sent
517  FREE_AND_CLEAR(init_sockets[i].faces_sent);
518  }
519  }
520 
521  for (player *pl = first_player; pl != NULL; pl = pl->next) {
522  if (!is_fd_valid(pl->socket->fd)) {
523  pl->socket->status = Ns_Dead;
524  }
525  }
526 }
527 
535 void do_server(void) {
536  fd_set tmp_read, tmp_exceptions;
537  FD_ZERO(&tmp_read);
538  FD_ZERO(&tmp_exceptions);
539 
540  for (int i = 0; i < socket_info.allocated_sockets; i++) {
541  if (init_sockets[i].status == Ns_Dead) {
542  LOG(llevInfo, "Disconnected from %s\n", init_sockets[i].host);
543  if (init_sockets[i].listen) {
544  /* try to reopen the listening socket */
546  } else {
549  }
550  } else if (init_sockets[i].status != Ns_Avail) {
551  FD_SET((uint32_t)init_sockets[i].fd, &tmp_read);
552  FD_SET((uint32_t)init_sockets[i].fd, &tmp_exceptions);
553  }
554  }
555 
556  /* Go through the players. Let the loop set the next pl value,
557  * since we may remove some
558  */
559  player *pl, *next;
560  for (pl = first_player; pl != NULL; ) {
561  if (pl->socket->status == Ns_Dead) {
562  player *npl = pl->next;
563  save_player(pl->ob, 0);
564  leave(pl, 1);
566  pl = npl;
567  } else {
568  FD_SET((uint32_t)pl->socket->fd, &tmp_read);
569  FD_SET((uint32_t)pl->socket->fd, &tmp_exceptions);
570  pl = pl->next;
571  }
572  }
573 
574  long sleep_time = get_sleep_remaining();
575  if (sleep_time < 0) {
576  LOG(llevInfo, "skipping time (over by %ld ms)\n", -sleep_time/1000);
577  jump_time();
578 #ifdef CS_LOGSTATS
580 #endif
581  }
582 
583  // Log information about last tick. This can't be in log_time() because
584  // CS_Stat is in socket/, and time is in common/.
585 #ifdef CS_LOGSTATS
588  cst_lst.ticks++;
589 #endif
590 
591  // Since we don't report cumulative tick time information, we don't need to
592  // compute it for cst_tot. Those statistics are available from the
593  // process_*_utime variables anyway.
594 
595  while (sleep_time > 0) {
596  socket_info.timeout.tv_sec = 0;
597  socket_info.timeout.tv_usec = sleep_time;
598  int pollret = select(socket_info.max_filedescriptor, &tmp_read, NULL,
599  &tmp_exceptions, &socket_info.timeout);
600  if (pollret == -1) {
601  if (errno == EINTR) {
602  // ignore
603  return;
604  } else if (errno == EBADF) {
605  check_all_fds();
606  }
607  LOG(llevError, "select failed: %s\n", strerror(errno));
608  return;
609  } else if (!pollret) {
610  return;
611  }
612 
613  /* Check for any exceptions/input on the sockets */
614  for (int i = 0; i < socket_info.allocated_sockets; i++) {
615  /* listen sockets can stay in status Ns_Dead */
616  if (init_sockets[i].status != Ns_Add) {
617  continue;
618  }
619  if (FD_ISSET(init_sockets[i].fd, &tmp_exceptions)) {
622  continue;
623  }
624  if (FD_ISSET(init_sockets[i].fd, &tmp_read)) {
625  if (init_sockets[i].listen)
627  else
628  handle_client(&init_sockets[i], NULL);
629  }
630  }
631 
632  /* This does roughly the same thing, but for the players now */
633  for (pl = first_player; pl != NULL; pl = next) {
634  next = pl->next;
635  if (pl->socket->status == Ns_Dead)
636  continue;
637 
638  if (FD_ISSET(pl->socket->fd, &tmp_exceptions)) {
639  save_player(pl->ob, 0);
640  leave(pl, 1);
642  } else {
643  bool keep_processing = handle_client(pl->socket, pl);
644  if (!keep_processing) {
645  FD_CLR(pl->socket->fd, &tmp_read);
646  }
647 
648  /* There seems to be rare cases where next points to a removed/freed player.
649  * My belief is that this player does something (shout, move, whatever)
650  * that causes data to be sent to the next player on the list, but
651  * that player is defunct, so the socket codes removes that player.
652  * End result is that next now points at the removed player, and
653  * that has garbage data so we crash. So update the next pointer
654  * while pl is still valid. MSW 2007-04-21
655  */
656  next = pl->next;
657 
658 
659  /* If the player has left the game, then the socket status
660  * will be set to this be the leave function. We don't
661  * need to call leave again, as it has already been called
662  * once.
663  */
664  if (pl->socket->status == Ns_Dead) {
665  save_player(pl->ob, 0);
666  leave(pl, 1);
668  } else {
670  send_updates(pl);
671  }
672  }
673  }
674  sleep_time = get_sleep_remaining();
675  }
676 }
677 
682  player *pl, *next;
683  for (pl = first_player; pl != NULL; pl = next) {
684  next = pl->next;
685  send_updates(pl);
686  /* Increment time since last contact only if logged in. */
687  if (pl->state == ST_PLAYING) {
688  pl->socket->last_tick++;
689 
690  if (!connection_alive(pl->socket)) {
691  // TODO: Handle a lost client connection.
692  LOG(llevDebug, "Lost client connection!\n");
693  }
694 
695  if (pl->socket->tick)
696  send_tick(pl);
697  }
698  }
699 }
give.next
def next
Definition: give.py:44
request_info_cmd
void request_info_cmd(char *buf, int len, socket_struct *ns)
Definition: loop.cpp:136
send_image_info
void send_image_info(socket_struct *ns)
Definition: image.cpp:113
global.h
player_cmd_mapping::cmdname
const char * cmdname
Definition: loop.cpp:77
send_image_sums
void send_image_sums(socket_struct *ns, char *params)
Definition: image.cpp:138
first_player
player * first_player
Definition: init.cpp:106
reply_cmd
void reply_cmd(char *buf, int len, player *pl)
Definition: request.cpp:595
socket_struct::heartbeat
bool heartbeat
Definition: newserver.h:112
CS_Stats::total_ticktime
unsigned long total_ticktime
Definition: newclient.h:695
llevError
@ llevError
Definition: logger.h:11
init_connection
void init_connection(socket_struct *ns, const char *from_ip)
Definition: init.cpp:85
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:58
init_sockets
socket_struct * init_sockets
Definition: init.cpp:58
player
Definition: player.h:105
sockproto.h
client_commands
static const struct client_cmd_mapping client_commands[]
Definition: loop.cpp:111
socket_struct
Definition: newserver.h:89
Socket_Info::allocated_sockets
int allocated_sockets
Definition: newserver.h:144
esrv_send_inventory
void esrv_send_inventory(object *pl, object *op)
Definition: item.cpp:316
UPD_WEIGHT
#define UPD_WEIGHT
Definition: newclient.h:305
SockList_AddString
void SockList_AddString(SockList *sl, const char *data)
Definition: lowlevel.cpp:157
socket_info
Socket_Info socket_info
Definition: init.cpp:49
mark_item_cmd
void mark_item_cmd(uint8_t *data, int len, player *pl)
Definition: item.cpp:767
send_updates
static void send_updates(player *pl)
Definition: loop.cpp:476
Socket_Info::max_filedescriptor
int max_filedescriptor
Definition: newserver.h:143
send_new_char_info
void send_new_char_info(socket_struct *ns)
Definition: requestinfo.cpp:520
send_map_info
void send_map_info(socket_struct *ns)
Definition: requestinfo.cpp:441
send_exp_table
void send_exp_table(socket_struct *ns)
Definition: requestinfo.cpp:158
socket_struct::listen
struct listen_info * listen
Definition: newserver.h:92
is_fd_valid
static int is_fd_valid(int fd)
Definition: loop.cpp:362
SEE_LAST_ERROR
@ SEE_LAST_ERROR
Definition: define.h:52
socket_struct::inbuf
SockList inbuf
Definition: newserver.h:99
CS_Stats::ticks
unsigned long ticks
Definition: newclient.h:692
pticks
uint32_t pticks
Definition: time.cpp:47
buf
StringBuffer * buf
Definition: readable.cpp:1565
MAX
#define MAX(x, y)
Definition: compat.h:24
Ns_Dead
@ Ns_Dead
Definition: newserver.h:67
account_password
void account_password(char *buf, int len, socket_struct *ns)
Definition: request.cpp:3044
send_skill_info
void send_skill_info(socket_struct *ns, char *params)
Definition: requestinfo.cpp:71
account_login_cmd
void account_login_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:2177
look_at_cmd
void look_at_cmd(char *buf, int len, player *pl)
Definition: item.cpp:869
knowledge_send_info
void knowledge_send_info(socket_struct *ns)
Definition: knowledge.cpp:1374
Ns_Avail
@ Ns_Avail
Definition: newserver.h:65
final_free_player
void final_free_player(player *pl)
Definition: init.cpp:442
socklen_t
#define socklen_t
Definition: win32.h:17
player_cmd_mapping::flag
const uint8_t flag
Definition: loop.cpp:79
update_players
void update_players()
Definition: loop.cpp:681
func_uint8_int_ns
void(* func_uint8_int_ns)(char *, int, socket_struct *)
Definition: loop.cpp:65
esrv_update_stats
void esrv_update_stats(player *pl)
Definition: request.cpp:873
check_all_fds
void check_all_fds()
Definition: loop.cpp:512
jump_time
void jump_time()
Definition: time.cpp:198
socket_struct::host
char * host
Definition: newserver.h:100
client_cmd_mapping
Definition: loop.cpp:68
send_tick
void send_tick(player *pl)
Definition: request.cpp:1986
navar-midane_time.data
data
Definition: navar-midane_time.py:11
leave
void leave(player *pl, int draw_exit)
Definition: server.cpp:1309
ask_smooth_cmd
void ask_smooth_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:503
account_add_player_cmd
void account_add_player_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:2390
sproto.h
create_player_cmd
void create_player_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:2624
new_player_cmd
void new_player_cmd(uint8_t *buf, int len, player *pl)
Definition: request.cpp:527
get_sleep_remaining
long get_sleep_remaining()
Definition: time.cpp:189
account_play_cmd
void account_play_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:2519
SockList_Init
void SockList_Init(SockList *sl)
Definition: lowlevel.cpp:55
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
do_server
void do_server(void)
Definition: loop.cpp:535
SockList::len
size_t len
Definition: newclient.h:675
send_delayed_buffers
static void send_delayed_buffers(player *pl)
Definition: loop.cpp:466
image.h
client_cmd_mapping::cmdname
const char * cmdname
Definition: loop.cpp:69
move_cmd
void move_cmd(char *buf, int len, player *pl)
Definition: request.cpp:714
fatal
void fatal(enum fatal_error err)
Definition: utils.cpp:590
send_class_info
void send_class_info(socket_struct *ns, char *params)
Definition: requestinfo.cpp:413
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.cpp:32
version_cmd
void version_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:657
tick_length
unsigned int tick_length(float seconds)
Definition: time.cpp:382
new_connection
static void new_connection(int listen_fd)
Definition: loop.cpp:374
SockList_Term
void SockList_Term(SockList *sl)
Definition: lowlevel.cpp:65
send_race_list
void send_race_list(socket_struct *ns)
Definition: requestinfo.cpp:326
handle_client
bool handle_client(socket_struct *ns, player *pl)
Definition: loop.cpp:257
ST_PLAYING
#define ST_PLAYING
Definition: define.h:541
free_newsocket
void free_newsocket(socket_struct *ns)
Definition: init.cpp:407
llevInfo
@ llevInfo
Definition: logger.h:12
inscribe_scroll_cmd
void inscribe_scroll_cmd(char *buf, int len, player *pl)
Definition: item.cpp:964
CS_Stats::max_ticktime
unsigned long max_ticktime
Definition: newclient.h:694
send_class_list
void send_class_list(socket_struct *ns)
Definition: requestinfo.cpp:392
FREE_AND_CLEAR
#define FREE_AND_CLEAR(xyz)
Definition: global.h:193
socket_struct::last_tick
uint32_t last_tick
Definition: newserver.h:130
Socket_Info::timeout
struct timeval timeout
Definition: newserver.h:142
newserver.h
BEAT_INTERVAL
#define BEAT_INTERVAL
Definition: config.h:636
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.cpp:359
esrv_draw_look
void esrv_draw_look(object *pl)
Definition: item.cpp:193
send_file
void send_file(socket_struct *ns, const char *file)
Definition: requestinfo.cpp:479
roll-o-matic.params
params
Definition: roll-o-matic.py:193
examine_cmd
void examine_cmd(char *buf, int len, player *pl)
Definition: item.cpp:646
socket_struct::faces_sent_len
size_t faces_sent_len
Definition: newserver.h:95
WEIGHT
#define WEIGHT(op)
Definition: define.h:651
handle_cmd
static int handle_cmd(socket_struct *ns, player *pl, char *cmd, char *data, int len)
Definition: loop.cpp:209
SockList_ResetRead
void SockList_ResetRead(SockList *sl)
Definition: lowlevel.cpp:83
send_skill_extra
void send_skill_extra(socket_struct *ns, char *params)
Definition: requestinfo.cpp:102
send_spell_paths
void send_spell_paths(socket_struct *ns)
Definition: requestinfo.cpp:132
account_new_cmd
void account_new_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:2276
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:32
lock_item_cmd
void lock_item_cmd(uint8_t *data, int len, player *pl)
Definition: item.cpp:708
save_player
int save_player(object *op, int flag)
Definition: login.cpp:230
last_time
uint32_t last_time
Definition: time.cpp:50
socket_struct::fd
int fd
Definition: newserver.h:91
player_cmd_mapping
Definition: loop.cpp:76
player_commands
static const struct player_cmd_mapping player_commands[]
Definition: loop.cpp:97
get_faces_count
size_t get_faces_count()
Definition: assets.cpp:293
CS_Stats::ticks_overtime
unsigned long ticks_overtime
Definition: newclient.h:693
SockList_ReadPacket
int SockList_ReadPacket(int fd, SockList *sl, int len)
Definition: lowlevel.cpp:275
set_up_cmd
void set_up_cmd(char *buf, int len, socket_struct *ns)
Definition: request.cpp:143
cst_lst
CS_Stats cst_lst
Definition: newclient.h:698
SockList::buf
unsigned char buf[MAXSOCKBUF]
Definition: newclient.h:676
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.cpp:347
client_cmd_mapping::cmdproc
const func_uint8_int_ns cmdproc
Definition: loop.cpp:70
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
player_cmd_mapping::cmdproc
const func_uint8_int_pl cmdproc
Definition: loop.cpp:78
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.cpp:415
draw_client_map
void draw_client_map(object *pl)
Definition: request.cpp:1625
Send_With_Handling
void Send_With_Handling(socket_struct *ns, SockList *sl)
Definition: lowlevel.cpp:447
SockList
Definition: newclient.h:670
apply_cmd
void apply_cmd(char *buf, int len, player *pl)
Definition: item.cpp:668
takeitem.status
status
Definition: takeitem.py:38
func_uint8_int_pl
void(* func_uint8_int_pl)(char *, int, player *)
Definition: loop.cpp:74
SockList_NullTerminate
void SockList_NullTerminate(SockList *sl)
Definition: lowlevel.cpp:237
send_face_cmd
void send_face_cmd(char *buff, int len, socket_struct *ns)
Definition: image.cpp:45
llevDebug
@ llevDebug
Definition: logger.h:13
init_listening_socket
void init_listening_socket(socket_struct *ns)
Definition: init.cpp:181
connection_alive
bool connection_alive(const socket_struct *socket)
Definition: loop.cpp:448