Atrinik Server  4.0
server.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
33 #include <global.h>
34 #include <toolkit/string.h>
35 #include <toolkit/packet.h>
36 #include <toolkit/socket_crypto.h>
37 #include <server.h>
38 #include <player.h>
39 #include <object.h>
40 #include <ban.h>
41 
42 TOOLKIT_API(DEPENDS(socket), IMPORTS(logger));
43 
51 #define SOCKET_COMMAND_PLAYER_ONLY 1
52 
58 #define SOCKET_SERVER_PLAYER_MAX_COMMANDS 15
59 
60 typedef enum socket_server_id {
61  SOCKET_SERVER_ID_CLASSIC_V4,
62  SOCKET_SERVER_ID_SECURE_V4,
63  SOCKET_SERVER_ID_CLASSIC_V6,
64  SOCKET_SERVER_ID_SECURE_V6,
65 
66  SOCKET_SERVER_ID_NUM
67 } socket_server_id_t;
68 
72 typedef struct csocket_entry {
73  struct csocket_entry *next;
74  struct csocket_entry *prev;
77 
81 typedef struct socket_command {
86 
90  int flags;
92 
96 static fd_set fds_read;
100 static fd_set fds_write;
104 static fd_set fds_error;
108 static socket_t *server_sockets[SOCKET_SERVER_ID_NUM];
113 
118  {socket_command_control, 0},
119  {socket_command_ask_face, 0},
120  {socket_command_setup, 0},
121  {socket_command_version, 0},
123  {socket_command_clear, 0},
124  {socket_command_request_update, 0},
125  {socket_command_keepalive, 0},
126  {socket_command_account, 0},
127  {socket_command_item_examine, SOCKET_COMMAND_PLAYER_ONLY},
128  {socket_command_item_apply, SOCKET_COMMAND_PLAYER_ONLY},
129  {socket_command_item_move, SOCKET_COMMAND_PLAYER_ONLY},
131  {socket_command_player_cmd, SOCKET_COMMAND_PLAYER_ONLY},
132  {socket_command_item_lock, SOCKET_COMMAND_PLAYER_ONLY},
133  {socket_command_item_mark, SOCKET_COMMAND_PLAYER_ONLY},
134  {socket_command_fire, SOCKET_COMMAND_PLAYER_ONLY},
135  {socket_command_quickslot, SOCKET_COMMAND_PLAYER_ONLY},
136  {socket_command_quest_list, SOCKET_COMMAND_PLAYER_ONLY},
137  {socket_command_move_path, SOCKET_COMMAND_PLAYER_ONLY},
138  {socket_command_combat, SOCKET_COMMAND_PLAYER_ONLY},
139  {socket_command_talk, SOCKET_COMMAND_PLAYER_ONLY},
140  {socket_command_move, SOCKET_COMMAND_PLAYER_ONLY},
141  {socket_command_target, SOCKET_COMMAND_PLAYER_ONLY},
142 };
143 CASSERT_ARRAY(socket_commands, SERVER_CMD_NROF);
144 
153 static inline bool
154 server_socket_id_is_secure (socket_server_id_t id)
155 {
156  if (id == SOCKET_SERVER_ID_SECURE_V4 || id == SOCKET_SERVER_ID_SECURE_V6) {
157  return true;
158  }
159 
160  return false;
161 }
162 
171 static inline bool
172 server_socket_id_is_v6 (socket_server_id_t id)
173 {
174  if (id == SOCKET_SERVER_ID_CLASSIC_V6 ||
175  id == SOCKET_SERVER_ID_SECURE_V6) {
176  return true;
177  }
178 
179  return false;
180 }
181 
190 static inline bool
191 server_socket_id_is_v4 (socket_server_id_t id)
192 {
193  if (id == SOCKET_SERVER_ID_CLASSIC_V4 ||
194  id == SOCKET_SERVER_ID_SECURE_V4) {
195  return true;
196  }
197 
198  return false;
199 }
200 
204 TOOLKIT_INIT_FUNC(socket_server)
205 {
206  /* Used to store the parsed network stack setting. */
207  struct {
208  /* Type of the network stack; some of these can be combined. */
209  enum {
210  STACK_IPV4,
211  STACK_IPV6,
212  STACK_DUAL,
213  } type;
214 
215  /* IP addresses to bind to in non-dual-stack configurations. */
216  struct sockaddr_storage v4;
217  struct sockaddr_storage v6;
218  } stack_setting;
219  memset(&stack_setting, 0, sizeof(stack_setting));
220 
221  char word[MAX_BUF];
222  size_t pos = 0;
223  while (string_get_word(settings.network_stack, &pos, ',', VS(word), 0)) {
224  string_whitespace_trim(word);
225 
226  char *cps[2];
227  if (string_split(word, cps, arraysize(cps), '=') < 1) {
228  LOG(ERROR, "Failed to split string: %s", word);
229  exit(1);
230  }
231 
232  if (strcasecmp(cps[0], "dual") == 0) {
233  stack_setting.type = 0;
234  BIT_SET(stack_setting.type, STACK_DUAL);
235  break;
236  }
237 
238  BIT_CLEAR(stack_setting.type, STACK_DUAL);
239 
240  struct sockaddr_storage *addr;
241  if (strcasecmp(cps[0], "ipv4") == 0 ||
242  strcasecmp(cps[0], "v4") == 0) {
243  BIT_SET(stack_setting.type, STACK_IPV4);
244  addr = &stack_setting.v4;
245  struct sockaddr_in *saddr = (struct sockaddr_in *) addr;
246  saddr->sin_family = AF_INET;
247  } else if (strcasecmp(cps[0], "ipv6") == 0 ||
248  strcasecmp(cps[0], "v6") == 0) {
249 #ifdef HAVE_IPV6
250  BIT_SET(stack_setting.type, STACK_IPV6);
251  addr = &stack_setting.v6;
252  struct sockaddr_in *saddr = (struct sockaddr_in *) addr;
253  saddr->sin_family = AF_INET6;
254 #endif
255  } else {
256  LOG(ERROR, "Invalid value in network stack setting: %s", cps[0]);
257  exit(1);
258  }
259 
260  if (cps[1] != NULL && !socket_host2addr(cps[1], addr)) {
261  LOG(ERROR,
262  "Invalid IP address in network stack configuration: %s",
263  cps[1]);
264  exit(1);
265  }
266  }
267 
268  if (stack_setting.type == 0) {
269  LOG(ERROR, "No network stack configuration selected");
270  exit(1);
271  }
272 
273  if (settings.port_crypto == 0 || settings.port == 0) {
274  LOG(ERROR, "No port configured");
275  exit(1);
276  }
277 
278  for (socket_server_id_t i = 0; i < SOCKET_SERVER_ID_NUM; i++) {
279  uint16_t port;
280  bool secure = server_socket_id_is_secure(i);
281  if (secure) {
282  port = settings.port_crypto;
283  } else {
284  port = settings.port;
285  }
286 
287  if (port == 0) {
288  continue;
289  }
290 
291  const char *host = NULL;
292  if (BIT_QUERY(stack_setting.type, STACK_DUAL)) {
293  /* Avoid binding more than once. */
294  if (server_socket_id_is_v4(i)) {
295  continue;
296  }
297  } else {
298  struct sockaddr_storage *addr;
299  if (server_socket_id_is_v4(i)) {
300  if (!BIT_QUERY(stack_setting.type, STACK_IPV4)) {
301  continue;
302  }
303 
304  addr = &stack_setting.v4;
305  } else if (server_socket_id_is_v6(i)) {
306  if (!BIT_QUERY(stack_setting.type, STACK_IPV6)) {
307  continue;
308  }
309 
310  addr = &stack_setting.v6;
311  } else {
312  LOG(ERROR, "Reached impossible code branch");
313  exit(1);
314  }
315 
316  char hostname[MAX_BUF];
317  if (socket_addr2host(addr, VS(hostname)) == NULL) {
318  LOG(ERROR, "Failed to convert address to host");
319  exit(1);
320  }
321 
322  host = hostname;
323  }
324 
325  bool dual_stack = BIT_QUERY(stack_setting.type, STACK_DUAL);
326  server_sockets[i] = socket_create(host,
327  port,
328  secure,
329  SOCKET_ROLE_SERVER,
330  dual_stack);
331  if (server_sockets[i] == NULL) {
332  exit(1);
333  }
334 
335  if (!socket_opt_linger(server_sockets[i], false, 0)) {
336  exit(1);
337  }
338 
339  if (!socket_opt_reuse_addr(server_sockets[i], true)) {
340  exit(1);
341  }
342 
343  if (!socket_bind(server_sockets[i])) {
344  exit(1);
345  }
346  }
347 
348  client_sockets = NULL;
349 }
350 TOOLKIT_INIT_FUNC_FINISH
351 
355 TOOLKIT_DEINIT_FUNC(socket_server)
356 {
357  for (int i = 0; i < SOCKET_SERVER_ID_NUM; i++) {
358  if (server_sockets[i] == NULL) {
359  continue;
360  }
361 
362  socket_destroy(server_sockets[i]);
363  }
364 }
365 TOOLKIT_DEINIT_FUNC_FINISH
366 
382 static bool
384  player *pl,
385  uint8_t *data,
386  size_t len)
387 {
388  size_t pos = 0;
389  uint8_t type = packet_to_uint8(data, len, &pos);
390 
391  bool is_secure = socket_is_secure(cs->sc);
392  if (!is_secure && type == SERVER_CMD_CRYPTO) {
393  LOG(PACKET, "Received crypto packet on wrong port from %s",
394  socket_get_str(cs->sc));
395  cs->state = ST_DEAD;
396  return false;
397  }
398 
399  if (socket_is_secure(cs->sc) &&
400  type != SERVER_CMD_CRYPTO &&
401  !socket_crypto_is_done(socket_get_crypto(cs->sc))) {
402  LOG(PACKET,
403  "Received non-crypto packet before crypto exchange from %s",
404  socket_get_str(cs->sc));
405  cs->state = ST_DEAD;
406  return false;
407  }
408 
409 #ifndef DEBUG
410  char *cp;
411 
412  LOG(DUMPRX,
413  "Received packet with command type %d (%" PRIu64 " bytes):",
414  type, (uint64_t) len);
415  cp = emalloc(sizeof(*cp) * (len * 3 + 1));
416  string_tohex(data, len, cp, len * 3 + 1, true);
417  LOG(DUMPRX, " Hexadecimal: %s", cp);
418  efree(cp);
419 #endif
420 
421  if (type >= SERVER_CMD_NROF || socket_commands[type].handle_func == NULL) {
422  LOG(DEVEL, "Unknown command type: %" PRIu8, type);
423  return true;
424  }
425 
426  /* If the command is only for players and the client is not logged in yet,
427  * do not handle the command. */
428  if (socket_commands[type].flags & SOCKET_COMMAND_PLAYER_ONLY &&
429  pl == NULL) {
430  return false;
431  }
432 
433  socket_commands[type].handle_func(cs, pl, data + pos, len - pos, 0);
434 
435  return true;
436 }
437 
438 static void
439 socket_server_csocket_create (socket_t *server_socket)
440 {
441  csocket_entry_t *entry = ecalloc(1, sizeof(*entry));
442  entry->cs = ecalloc(1, sizeof(*entry->cs));
443  entry->cs->sc = socket_accept(server_socket);
444  if (entry->cs->sc == NULL) {
445  efree(entry);
446  return;
447  }
448 
449  if (ban_check(entry->cs, NULL)) {
450  LOG(SYSTEM, "Ban: Banned IP tried to connect: %s",
451  socket_get_addr(entry->cs->sc));
452  socket_destroy(entry->cs->sc);
453  efree(entry);
454  return;
455  }
456 
457  init_connection(entry->cs);
458  DL_APPEND(client_sockets, entry);
459 }
460 
467 static void
469 {
470  HARD_ASSERT(entry != NULL);
471  free_newsocket(entry->cs);
472  DL_DELETE(client_sockets, entry);
473  efree(entry);
474 }
475 
484 static void
486 {
487  HARD_ASSERT(entry != NULL);
488  LOG(SYSTEM, "Connection: dropping connection: %s",
489  socket_get_str(entry->cs->sc));
491 }
492 
502 void
504 {
505  HARD_ASSERT(pl != NULL);
506 
507  for (int num_cmds = 0;
509  num_cmds++) {
510  if (pl->cs->packet_recv_cmd->len == 0) {
511  break;
512  }
513 
514  /* Ensure the player is in a state capable of issue commands, and
515  * has enough speed left to do so. */
516  if (pl->cs->state == ST_ZOMBIE ||
517  pl->cs->state == ST_DEAD ||
518  (pl->cs->state == ST_PLAYING &&
519  pl->ob != NULL &&
520  pl->ob->speed_left < 0)) {
521  break;
522  }
523 
524  size_t len = 2 + (pl->cs->packet_recv_cmd->data[0] << 8) +
525  pl->cs->packet_recv_cmd->data[1];
526 
527  /* Reset idle counter. */
528  if (pl->cs->state == ST_PLAYING) {
529  pl->cs->login_count = 0;
530  pl->cs->keepalive = 0;
531  }
532 
534  pl,
535  pl->cs->packet_recv_cmd->data + 2,
536  len - 2);
537  packet_delete(pl->cs->packet_recv_cmd, 0, len);
538  }
539 }
540 
555 bool
557 {
558  csocket_entry_t *entry, *tmp;
559  DL_FOREACH_SAFE(client_sockets, entry, tmp) {
560  if (entry->cs == cs) {
561  DL_DELETE(client_sockets, entry);
562  efree(entry);
563  return true;
564  }
565  }
566 
567  return false;
568 }
569 
579 static inline bool
581 {
582  HARD_ASSERT(cs != NULL);
583 
584  if (cs->state != ST_ZOMBIE) {
585  return false;
586  }
587 
588  if (cs->login_count++ >= MAX_TICKS_MULTIPLIER) {
589  cs->state = ST_DEAD;
590  }
591 
592  return true;
593 }
594 
601 static inline void
603 {
604  HARD_ASSERT(cs != NULL);
605 
606  if (cs->state == ST_DEAD) {
607  return;
608  }
609 
610  size_t amt;
611  if (!socket_read(cs->sc,
612  (void *) (cs->packet_recv->data + cs->packet_recv->len),
613  cs->packet_recv->size - cs->packet_recv->len,
614  &amt)) {
615  cs->state = ST_DEAD;
616  return;
617  }
618 
619  cs->packet_recv->len += amt;
620 
621  while (cs->packet_recv->len >= 2) {
622  size_t size = 2 + (cs->packet_recv->data[0] << 8) +
623  cs->packet_recv->data[1];
624  if (size > cs->packet_recv->len) {
625  break;
626  }
627 
628  uint8_t *data = cs->packet_recv->data;
629  size_t len = size;
630 
631  uint8_t *decrypted_data;
632  size_t decrypted_len;
633  bool was_decrypted = true;
634  if (socket_is_secure(cs->sc)) {
635  if (!socket_crypto_decrypt(cs->sc,
636  data + 2,
637  len - 2,
638  &decrypted_data,
639  &decrypted_len)) {
640  cs->state = ST_DEAD;
641  break;
642  }
643  } else {
644  decrypted_data = data + 2;
645  decrypted_len = len - 2;
646  was_decrypted = false;
647  }
648 
649  /* Try to handle the command. */
651  NULL,
652  decrypted_data,
653  decrypted_len)) {
654  /* Couldn't handle it immediately, add it to the commands
655  * packet. */
656  packet_append_uint16(cs->packet_recv_cmd, decrypted_len);
657  packet_append_data_len(cs->packet_recv_cmd,
658  decrypted_data,
659  decrypted_len);
660  }
661 
662  if (was_decrypted) {
663  efree(decrypted_data);
664  }
665 
666  packet_delete(cs->packet_recv, 0, size);
667  }
668 }
669 
676 static inline void
678 {
679  HARD_ASSERT(cs != NULL);
680 
681  while (cs->packets != NULL) {
682  packet_struct *packet = cs->packets;
683 
684  if (packet->ndelay) {
685  socket_opt_ndelay(cs->sc, true);
686  }
687 
688  size_t amt;
689  bool success = socket_write(cs->sc,
690  (const void *) (packet->data + packet->pos),
691  packet->len - packet->pos,
692  &amt);
693 
694  if (packet->ndelay) {
695  socket_opt_ndelay(cs->sc, false);
696  }
697 
698  if (!success) {
699  cs->state = ST_DEAD;
700  break;
701  }
702 
703  packet->pos += amt;
704 
705  if (packet->len - packet->pos == 0) {
706  DL_DELETE(cs->packets, packet);
707  packet_free(packet);
708  continue;
709  }
710 
711  /* Failed to send the entire packet; it's unlikely we can retry
712  * immediately, so just stop here. */
713  break;
714  }
715 }
716 
721 void
723 {
724  FD_ZERO(&fds_read);
725  FD_ZERO(&fds_write);
726  FD_ZERO(&fds_error);
727 
728  int nfds = 0;
729 
730  for (socket_server_id_t i = 0; i < SOCKET_SERVER_ID_NUM; i++) {
731  if (server_sockets[i] == NULL) {
732  continue;
733  }
734 
735  int fd = socket_fd(server_sockets[i]);
736  if (nfds < fd) {
737  nfds = fd;
738  }
739 
740  FD_SET(fd, &fds_read);
741  }
742 
743  csocket_entry_t *entry, *entry_tmp;
744  DL_FOREACH_SAFE(client_sockets, entry, entry_tmp) {
745  if (unlikely(!socket_is_fd_valid(entry->cs->sc))) {
746  LOG(ERROR, "Invalid waiting socket: %s",
747  socket_get_str(entry->cs->sc));
748  entry->cs->state = ST_DEAD;
749  }
750 
751  if (entry->cs->state == ST_DEAD) {
753  continue;
754  }
755 
756  if (server_socket_csocket_is_zombie(entry->cs)) {
757  continue;
758  }
759 
760  int fd = socket_fd(entry->cs->sc);
761  if (nfds < fd) {
762  nfds = fd;
763  }
764 
765  FD_SET(fd, &fds_read);
766  FD_SET(fd, &fds_write);
767  FD_SET(fd, &fds_error);
768  }
769 
770  player *pl, *pl_tmp;
771  DL_FOREACH_SAFE(first_player, pl, pl_tmp) {
772  if (pl->cs->state == ST_DEAD) {
773  player_logout(pl);
774  continue;
775  }
776 
777  if (unlikely(!socket_is_fd_valid(pl->cs->sc))) {
778  LOG(ERROR, "Invalid waiting socket: %s",
779  socket_get_str(pl->cs->sc));
780  pl->cs->state = ST_DEAD;
781  }
782 
783  if (pl->cs->keepalive++ >= SOCKET_KEEPALIVE_TIMEOUT) {
784  LOG(SYSTEM, "Keepalive: disconnecting %s [%s]: %d",
785  object_get_str(pl->ob),
786  socket_get_str(pl->cs->sc),
787  socket_fd(pl->cs->sc));
788  pl->cs->state = ST_DEAD;
789  }
790 
791  if (pl->cs->state == ST_DEAD) {
792  player_logout(pl);
793  continue;
794  }
795 
797  continue;
798  }
799 
800  int fd = socket_fd(pl->cs->sc);
801  if (nfds < fd) {
802  nfds = fd;
803  }
804 
805  FD_SET(fd, &fds_read);
806  FD_SET(fd, &fds_write);
807  FD_SET(fd, &fds_error);
808  }
809 
810  int ready;
811 #ifdef HAVE_PSELECT
812  static struct timespec timeout;
813  /* pselect does not change the timeout argument, so we're OK with a
814  * static storage duration one. */
815  ready = pselect(nfds + 1,
816  &fds_read,
817  &fds_write,
818  &fds_error,
819  &timeout,
820  NULL);
821 #else
822  struct timeval timeout;
823  timeout.tv_sec = 0;
824  timeout.tv_usec = 0;
825  ready = select(nfds + 1,
826  &fds_read,
827  &fds_write,
828  &fds_error,
829  &timeout);
830 #endif
831  if (unlikely(ready == -1)) {
832  LOG(ERROR, "pselect/select() returned an error: %s (%d)",
833  strerror(errno), errno);
834  return;
835  }
836 
837  /* No FDs that need processing. */
838  if (ready == 0) {
839  return;
840  }
841 
842  for (socket_server_id_t i = 0; i < SOCKET_SERVER_ID_NUM; i++) {
843  if (server_sockets[i] == NULL) {
844  continue;
845  }
846 
847  if (!FD_ISSET(socket_fd(server_sockets[i]), &fds_read)) {
848  continue;
849  }
850 
851  socket_server_csocket_create(server_sockets[i]);
852  }
853 
854  DL_FOREACH_SAFE(client_sockets, entry, entry_tmp) {
855  int fd = socket_fd(entry->cs->sc);
856 
857  if (FD_ISSET(fd, &fds_error)) {
858  entry->cs->state = ST_DEAD;
859  continue;
860  } else if (FD_ISSET(fd, &fds_read)) {
862  continue;
863  }
864 
865  if (entry->cs->state == ST_DEAD) {
867  continue;
868  }
869 
870  if (FD_ISSET(fd, &fds_write)) {
872  }
873  }
874 
875  DL_FOREACH_SAFE(first_player, pl, pl_tmp) {
876  int fd = socket_fd(pl->cs->sc);
877 
878  if (FD_ISSET(fd, &fds_error)) {
879  pl->cs->state = ST_DEAD;
880  continue;
881  } else if (FD_ISSET(fd, &fds_read)) {
883  continue;
884  }
885 
886  if (pl->cs->state == ST_DEAD) {
887  player_logout(pl);
888  continue;
889  }
890 
891  if (FD_ISSET(fd, &fds_write)) {
893  }
894  }
895 }
896 
901 void
903 {
904  player *pl, *pl_tmp;
905  DL_FOREACH_SAFE(first_player, pl, pl_tmp) {
906  if (pl->cs->state == ST_DEAD) {
907  player_logout(pl);
908  continue;
909  }
910 
911  /* The removal of ext_title_flag is done in two steps because we might
912  * be somewhere in the middle of the loop right now, which would mean
913  * that the previous players in the list would not get the update. */
914  if (pl->cs->ext_title_flag == 1) {
916  pl->cs->ext_title_flag = 2;
917  } else if (pl->cs->ext_title_flag == 2) {
918  pl->cs->ext_title_flag = 0;
919  }
920 
921  esrv_update_stats(pl);
922  party_update_who(pl);
923 
924  if (pl->ob->map != NULL) {
925  draw_client_map(pl->ob);
926 
927  uint32_t update_tile = GET_MAP_UPDATE_COUNTER(pl->ob->map,
928  pl->ob->x,
929  pl->ob->y);
930  if (update_tile != pl->cs->update_tile) {
931  esrv_draw_look(pl->ob);
932  pl->cs->update_tile = update_tile;
933  }
934  }
935 
936  if (FD_ISSET(socket_fd(pl->cs->sc), &fds_write)) {
938  }
939  }
940 }
socket_t * sc
Definition: newserver.h:109
void generate_quick_name(player *pl)
Definition: request.c:2286
void player_logout(player *pl)
Definition: player.c:2895
static fd_set fds_write
Definition: server.c:100
uint32_t update_tile
Definition: newserver.h:134
static TOOLKIT_DEINIT_FUNC_FINISH bool socket_server_handle_command(socket_struct *cs, player *pl, uint8_t *data, size_t len)
Definition: server.c:383
char network_stack[MAX_BUF]
Definition: global.h:464
void socket_server_handle_client(player *pl)
Definition: server.c:503
#define SOCKET_COMMAND_PLAYER_ONLY
Definition: server.c:51
void esrv_draw_look(object *pl)
Definition: item.c:396
uint8_t type
One of operation types.
Definition: sound_ambient.c:45
socket_struct * cs
Client's socket.
Definition: server.c:75
double speed_left
Definition: object.h:472
bool socket_server_remove(socket_struct *cs)
Definition: server.c:556
struct packet_struct * packets
Definition: newserver.h:170
object * ob
Definition: player.h:185
void free_newsocket(socket_struct *ns)
Definition: init.c:113
void socket_server_process(void)
Definition: server.c:722
bool init_connection(socket_struct *ns)
Definition: init.c:51
Definition: server.c:72
static csocket_entry_t * client_sockets
Definition: server.c:112
static void socket_server_csocket_free(csocket_entry_t *entry)
Definition: server.c:468
int16_t y
Definition: object.h:276
static int fd
Definition: statistics.c:43
static void socket_server_csocket_read(socket_struct *cs)
Definition: server.c:602
const char * object_get_str(const object *op)
Definition: object.c:3151
uint32_t keepalive
Definition: newserver.h:177
static bool server_socket_id_is_v6(socket_server_id_t id)
Definition: server.c:172
uint16_t port_crypto
Definition: global.h:333
void draw_client_map(object *pl)
Definition: request.c:426
void(* socket_command_func)(socket_struct *cs, player *pl, uint8_t *data, size_t len, size_t pos)
Definition: server.h:50
uint16_t port
Definition: global.h:328
void socket_command_ask_resource(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
Definition: request.c:3108
struct mapdef * map
Definition: object.h:139
uint8_t ext_title_flag
Definition: newserver.h:161
union @21 data
Data about the rule.
static bool server_socket_csocket_is_zombie(socket_struct *cs)
Definition: server.c:580
void party_update_who(player *pl)
Definition: party.c:530
#define SOCKET_SERVER_PLAYER_MAX_COMMANDS
Definition: server.c:58
TOOLKIT_INIT_FUNC(socket_server)
Definition: server.c:204
void socket_command_crypto(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
Definition: request.c:3046
struct csocket_entry * next
Next entry.
Definition: server.c:73
static fd_set fds_read
Definition: server.c:96
int16_t x
Definition: object.h:273
#define SOCKET_KEEPALIVE_TIMEOUT
Definition: newserver.h:189
socket_command_func handle_func
Definition: server.c:85
struct settings_struct settings
Definition: init.c:55
static void socket_server_csocket_write(socket_struct *cs)
Definition: server.c:677
static void socket_server_csocket_drop(csocket_entry_t *entry)
Definition: server.c:485
bool ban_check(socket_struct *ns, const char *name)
Definition: ban.c:441
struct csocket_entry * prev
Previous entry.
Definition: server.c:74
struct csocket_entry csocket_entry_t
static fd_set fds_error
Definition: server.c:104
static socket_t * server_sockets[SOCKET_SERVER_ID_NUM]
Definition: server.c:108
socket_struct * cs
Definition: player.h:148
static bool server_socket_id_is_secure(socket_server_id_t id)
Definition: server.c:154
struct socket_command socket_command_t
void socket_server_post_process(void)
Definition: server.c:902
void esrv_update_stats(player *pl)
Definition: request.c:187
player * first_player
Definition: main.c:57
static bool server_socket_id_is_v4(socket_server_id_t id)
Definition: server.c:191
TOOLKIT_INIT_FUNC_FINISH TOOLKIT_DEINIT_FUNC(socket_server)
Definition: server.c:355
static const socket_command_t socket_commands[]
Definition: server.c:117