Atrinik Server  4.0
lowlevel.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 
30 #include <global.h>
31 #include <toolkit/packet.h>
32 #include <toolkit/string.h>
33 #include <toolkit/socket_crypto.h>
34 
35 static void socket_packet_enqueue(socket_struct *ns, packet_struct *packet)
36 {
37 #ifndef DEBUG
38  {
39  char *cp, *cp2;
40 
41  LOG(DUMPTX, "Enqueuing packet with command type %d (%" PRIu64
42  " bytes):", packet->type, (uint64_t) packet->len);
43 
44  cp = packet_get_debug(packet);
45 
46  if (cp[0] != '\0') {
47  LOG(DUMPTX, " Debug info:\n");
48  cp2 = strtok(cp, "\n");
49 
50  while (cp2 != NULL) {
51  LOG(DUMPTX, " %s", cp2);
52  cp2 = strtok(NULL, "\n");
53  }
54  }
55 
56  efree(cp);
57 
58  cp = emalloc(sizeof(*cp) * (packet->len * 3 + 1));
59  string_tohex(packet->data, packet->len, cp, packet->len * 3 + 1, true);
60  LOG(DUMPTX, " Hexadecimal: %s", cp);
61  efree(cp);
62  }
63 #endif
64 
65  DL_APPEND(ns->packets, packet);
66 }
67 
74 {
75  packet_struct *packet, *tmp;
76  DL_FOREACH_SAFE(ns->packets, packet, tmp) {
77  packet_free(packet);
78  }
79 
80  ns->packets = NULL;
81 }
82 
89 {
90  while (ns->packets != NULL) {
91  packet_struct *packet = ns->packets;
92 
93  if (packet->ndelay) {
94  socket_opt_ndelay(ns->sc, true);
95  }
96 
97  size_t amt;
98  bool success = socket_write(ns->sc, (const void *) (packet->data +
99  packet->pos), packet->len - packet->pos, &amt);
100 
101  if (packet->ndelay) {
102  socket_opt_ndelay(ns->sc, false);
103  }
104 
105  if (!success) {
106  ns->state = ST_DEAD;
107  break;
108  }
109 
110  packet->pos += amt;
111 
112  if (packet->len - packet->pos == 0) {
113  DL_DELETE(ns->packets, packet);
114  packet_free(packet);
115  }
116  }
117 }
118 
119 void socket_send_packet(socket_struct *ns, struct packet_struct *packet)
120 {
121  HARD_ASSERT(ns != NULL);
122  HARD_ASSERT(packet != NULL);
123 
124  if (ns->state == ST_DEAD) {
125  packet_free(packet);
126  return;
127  }
128 
129  if (packet->len + 1 > UINT16_MAX) {
130  log_error("Sending packet with size >%u", UINT16_MAX);
131  packet_free(packet);
132  return;
133  }
134 
135  packet_struct *packet_meta = packet_new(0, 4, 0);
136  packet_meta->ndelay = packet->ndelay;
137 
138  if (socket_is_secure(ns->sc)) {
139  bool checksum_only = !socket_crypto_server_should_encrypt(packet->type);
140  packet = socket_crypto_encrypt(ns->sc,
141  packet,
142  packet_meta,
143  checksum_only);
144  if (packet == NULL) {
145  /* Logging already done. */
146  ns->state = ST_DEAD;
147  return;
148  }
149  } else {
150  packet_compress(packet);
151  packet_append_uint16(packet_meta, (uint16_t) packet->len + 1);
152  packet_append_uint8(packet_meta, packet->type);
153  }
154 
155  socket_packet_enqueue(ns, packet_meta);
156 
157  if (packet->len != 0) {
158  socket_packet_enqueue(ns, packet);
159  } else {
160  packet_free(packet);
161  }
162 }
socket_t * sc
Definition: newserver.h:109
struct packet_struct * packets
Definition: newserver.h:170
void socket_buffer_clear(socket_struct *ns)
Definition: lowlevel.c:73
void socket_buffer_write(socket_struct *ns)
Definition: lowlevel.c:88