Atrinik Client  4.0
server_files.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 
32 #include <global.h>
33 #include <toolkit/string.h>
34 #include <toolkit/path.h>
35 #include <toolkit/curl.h>
36 
39 
41 static curl_request_t *listing_request = NULL;
42 
46 void
48 {
50 
51  server_files = NULL;
52 
53  tmp = server_files_create(SERVER_FILE_BMAPS);
55 
56  tmp = server_files_create(SERVER_FILE_UPDATES);
58 
59  tmp = server_files_create(SERVER_FILE_SETTINGS);
61 
62  tmp = server_files_create(SERVER_FILE_ANIMS);
63  tmp->parse_func = read_anims;
64  tmp->reload_func = anims_reset;
65 
66  tmp = server_files_create(SERVER_FILE_EFFECTS);
67  tmp->parse_func = effects_init;
69 
70  tmp = server_files_create(SERVER_FILE_HFILES);
71  tmp->parse_func = hfiles_init;
72  tmp->init_func = hfiles_init;
73 
75 }
76 
80 void
82 {
83  server_files_struct *curr, *tmp;
84  HASH_ITER(hh, server_files, curr, tmp) {
85  HASH_DEL(server_files, curr);
86  efree(curr->name);
87  efree(curr);
88  }
89 }
90 
94 void
96 {
97  server_files_struct *curr, *tmp;
98  HASH_ITER(hh, server_files, curr, tmp) {
99  if (curr->init_func) {
100  curr->init_func();
101  }
102  }
103 }
104 
116 server_files_create (const char *name)
117 {
118  server_files_struct *tmp;
119 
120  tmp = ecalloc(1, sizeof(*tmp));
121  tmp->name = estrdup(name);
122  HASH_ADD_KEYPTR(hh, server_files, tmp->name, strlen(tmp->name), tmp);
123 
124  return tmp;
125 }
126 
136 server_files_find (const char *name)
137 {
138  server_files_struct *tmp;
139  HASH_FIND(hh, server_files, name, strlen(name), tmp);
140  return tmp;
141 }
142 
150 void
151 server_files_load (int post_load)
152 {
153  server_files_struct *curr, *tmp;
154  FILE *fp;
155  struct stat sb;
156  size_t st_size, numread;
157  char *contents;
158 
159  HASH_ITER(hh, server_files, curr, tmp) {
160  curr->update = 0;
161 
162  if (post_load && curr->loaded) {
163  if (curr->reload_func) {
164  curr->reload_func();
165  }
166 
167  continue;
168  }
169 
170  /* Open the file. */
171  fp = server_file_open(curr);
172 
173  if (fp == NULL) {
174  continue;
175  }
176 
177  /* Get and store the size. */
178  fstat(fileno(fp), &sb);
179  st_size = sb.st_size;
180  curr->size = st_size;
181 
182  /* Allocate temporary buffer and read into it the file. */
183  contents = emalloc(st_size);
184  numread = fread(contents, 1, st_size, fp);
185 
186  /* Calculate and store the checksum, free the temporary buffer
187  * and close the file pointer. */
188  curr->crc32 = crc32(1L, (const unsigned char FAR *) contents, numread);
189  efree(contents);
190  fclose(fp);
191 
192  if (post_load) {
193  /* Mark that we have loaded this file. */
194  curr->loaded = 1;
195 
196  if (curr->parse_func) {
197  curr->parse_func();
198  }
199  }
200  }
201 }
202 
206 void
208 {
209  if (listing_request != NULL) {
210  curl_request_free(listing_request);
211  }
212 
213  char url[HUGE_BUF];
214  snprintf(VS(url), "%s/%s/%s",
215  cpl.http_url,
216  SERVER_FILES_HTTP_DIR,
217  SERVER_FILES_HTTP_LISTING);
218  listing_request = curl_request_create(url, CURL_PKEY_TRUST_APPLICATION);
219  curl_request_start_get(listing_request);
220 }
221 
227 int
229 {
230  if (listing_request == NULL) {
231  return 0;
232  }
233 
234  curl_state_t state = curl_request_get_state(listing_request);
235  if (state == CURL_STATE_ERROR) {
236  cpl.state = ST_INIT;
237  return 0;
238  }
239 
240  if (state == CURL_STATE_INPROGRESS) {
241  return 0;
242  }
243 
244  char *body = curl_request_get_body(listing_request, NULL);
245  if (body == NULL) {
246  cpl.state = ST_INIT;
247  return 0;
248  }
249 
250  char word[HUGE_BUF];
251  size_t pos = 0;
252  while (string_get_word(body, &pos, '\n', VS(word), 0)) {
253  char *cps[3];
254  if (string_split(word, cps, arraysize(cps), ':') != arraysize(cps)) {
255  continue;
256  }
257 
258  server_files_struct *tmp = server_files_find(cps[0]);
259  if (tmp == NULL) {
260  continue;
261  }
262 
263  unsigned long crc = strtoul(cps[1], NULL, 16);
264  size_t fsize = strtoul(cps[2], NULL, 16);
265 
266  if (tmp->crc32 != crc || tmp->size != fsize) {
267  tmp->update = 1;
268  }
269 
270  LOG(DEVEL,
271  "%-10s CRC32: %lu (local: %lu) Size: %" PRIu64 " (local: %" PRIu64
272  ") Update: %d",
273  tmp->name,
274  crc,
275  tmp->crc32,
276  (uint64_t) fsize,
277  (uint64_t) tmp->size,
278  tmp->update);
279 
280  tmp->crc32 = crc;
281  tmp->size = fsize;
282  }
283 
284  curl_request_free(listing_request);
285  listing_request = NULL;
286 
287  return 1;
288 }
289 
298 static int
300 {
301  if (tmp->update == 0) {
302  return 0;
303  }
304 
305  if (tmp->update == 1) {
306  char url[MAX_BUF];
307  snprintf(VS(url), "%s/%s/%s.zz",
308  cpl.http_url,
309  SERVER_FILES_HTTP_DIR,
310  tmp->name);
311 
312  if (tmp->request != NULL) {
313  curl_request_free(tmp->request);
314  }
315 
316  LOG(DEVEL, "Beginning download: %s, URL: %s", tmp->name, url);
317 
318  tmp->request = curl_request_create(url, CURL_PKEY_TRUST_APPLICATION);
319  curl_request_start_get(tmp->request);
320  tmp->update = -1;
321  return 1;
322  }
323 
324  curl_state_t state = curl_request_get_state(tmp->request);
325  if (state == CURL_STATE_INPROGRESS) {
326  return 1;
327  }
328 
329  size_t body_size;
330  char *body = curl_request_get_body(tmp->request, &body_size);
331 
332  int http_code = curl_request_get_http_code(tmp->request);
333  LOG(DEVEL,
334  "Download finished: %s, state: %d, http_code: %d, size: %" PRIu64,
335  tmp->name,
336  state,
337  http_code,
338  (uint64_t) body_size);
339 
340  /* Done. */
341  if (state == CURL_STATE_OK) {
342  if (body != NULL) {
343  unsigned long len_ucomp = tmp->size;
344  unsigned char *dest = emalloc(len_ucomp);
345  uncompress((Bytef *) dest,
346  (uLongf *) &len_ucomp,
347  (const Bytef *) body,
348  (uLong) body_size);
349 
350  LOG(DEVEL, "Saving: %s, uncompressed: %lu", tmp->name, len_ucomp);
351 
352  if (server_file_save(tmp, dest, len_ucomp)) {
353  tmp->loaded = 0;
354  }
355 
356  efree(dest);
357  }
358  } else if (state == CURL_STATE_ERROR) {
359  /* Error occurred. */
360  LOG(ERROR, "Could not download %s: %d", tmp->name, http_code);
361  }
362 
363  tmp->update = 0;
364  curl_request_free(tmp->request);
365  tmp->request = NULL;
366 
367  return 0;
368 }
369 
376 int
378 {
379  server_files_struct *curr, *tmp;
380  /* Check all files. */
381  HASH_ITER(hh, server_files, curr, tmp) {
382  if (server_file_process(curr)) {
383  return 0;
384  }
385  }
386 
387  return 1;
388 }
389 
401 static char
402 *server_file_path (server_files_struct *tmp, char *buf, size_t buf_size)
403 {
404  snprintf(buf, buf_size, "srv_files/%s", tmp->name);
405  return buf;
406 }
407 
416 FILE *
418 {
419  if (tmp == NULL) {
420  return NULL;
421  }
422 
423  char buf[MAX_BUF];
424  server_file_path(tmp, VS(buf));
425  return path_fopen(buf, "rb");
426 }
427 
436 FILE *
437 server_file_open_name (const char *name)
438 {
439  return server_file_open(server_files_find(name));
440 }
441 
454 bool
455 server_file_save (server_files_struct *tmp, unsigned char *data, size_t len)
456 {
457  char path[MAX_BUF];
458  server_file_path(tmp, VS(path));
459 
460  FILE *fp = path_fopen(path, "wb");
461  if (fp == NULL) {
462  LOG(ERROR, "Could not open %s for writing.", path);
463  return false;
464  }
465 
466  bool ret = true;
467 
468  if (fwrite(data, 1, len, fp) != len) {
469  LOG(ERROR, "Failed to write to %s.", path);
470  ret = false;
471  }
472 
473  if (fclose(fp) != 0) {
474  LOG(ERROR, "Could not close %s.", path);
475  ret = false;
476  }
477 
478  return ret;
479 }
void hfiles_init(void)
Definition: help.c:89
static char * server_file_path(server_files_struct *tmp, char *buf, size_t buf_size)
Definition: server_files.c:402
void read_anims(void)
Definition: animations.c:35
FILE * server_file_open(server_files_struct *tmp)
Definition: server_files.c:417
void effects_init(void)
Definition: effects.c:46
bool server_file_save(server_files_struct *tmp, unsigned char *data, size_t len)
Definition: server_files.c:455
void(* init_func)(void)
Definition: server_files.h:73
server_files_struct * server_files_create(const char *name)
Definition: server_files.c:116
static int server_file_process(server_files_struct *tmp)
Definition: server_files.c:299
void(* parse_func)(void)
Definition: server_files.h:79
static server_files_struct * server_files
Definition: server_files.c:38
void server_files_listing_retrieve(void)
Definition: server_files.c:207
FILE * server_file_open_name(const char *name)
Definition: server_files.c:437
void server_files_init_all(void)
Definition: server_files.c:95
void(* reload_func)(void)
Definition: server_files.h:76
Client_Player cpl
Definition: client.c:50
char http_url[MAX_BUF]
Definition: player.h:252
void server_settings_init(void)
unsigned long crc32
Definition: server_files.h:67
void server_files_deinit(void)
Definition: server_files.c:81
void image_bmaps_init(void)
Definition: image.c:143
void anims_reset(void)
Definition: animations.c:138
int server_files_listing_processed(void)
Definition: server_files.c:228
void effects_reinit(void)
Definition: effects.c:294
int server_files_processed(void)
Definition: server_files.c:377
Definition: main.h:242
void file_updates_parse(void)
Definition: updates.c:109
void server_files_load(int post_load)
Definition: server_files.c:151
server_files_struct * server_files_find(const char *name)
Definition: server_files.c:136
static curl_request_t * listing_request
Definition: server_files.c:41
void server_files_init(void)
Definition: server_files.c:47
curl_request_t * request
Definition: server_files.h:70