Atrinik Client  4.0
commands.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 
31 #include <global.h>
32 #include <region_map.h>
33 #include <toolkit/packet.h>
34 #include <toolkit/path.h>
35 #include <toolkit/string.h>
36 #include <toolkit/x11.h>
37 #include <toolkit/socket_crypto.h>
38 
40 void socket_command_book(uint8_t *data, size_t len, size_t pos)
41 {
42  sound_play_effect("book.ogg", 100);
43  book_load((char *) data + pos, len);
44 }
45 
47 void socket_command_setup(uint8_t *data, size_t len, size_t pos)
48 {
49  uint8_t type;
50 
51  while (pos < len) {
52  type = packet_to_uint8(data, len, &pos);
53 
54  if (type == CMD_SETUP_SOUND) {
55  packet_to_uint8(data, len, &pos);
56  } else if (type == CMD_SETUP_MAPSIZE) {
57  int x, y;
58 
59  x = packet_to_uint8(data, len, &pos);
60  y = packet_to_uint8(data, len, &pos);
61 
64  } else if (type == CMD_SETUP_DATA_URL) {
65  packet_to_string(data, len, &pos, cpl.http_url,
66  sizeof(cpl.http_url));
67  }
68  }
69 
70  if (cpl.state != ST_PLAY) {
72  }
73 }
74 
76 void socket_command_anim(uint8_t *data, size_t len, size_t pos)
77 {
78  uint16_t anim_id;
79  int i;
80 
81  anim_id = packet_to_uint16(data, len, &pos);
82  animations[anim_id].flags = packet_to_uint8(data, len, &pos);
83  animations[anim_id].facings = packet_to_uint8(data, len, &pos);
84  animations[anim_id].num_animations = (len - pos) / 2;
85 
86  if (animations[anim_id].facings > 1) {
87  animations[anim_id].frame = animations[anim_id].num_animations / animations[anim_id].facings;
88  } else {
89  animations[anim_id].frame = animations[anim_id].num_animations;
90  }
91 
92  animations[anim_id].faces = emalloc(sizeof(uint16_t) * animations[anim_id].num_animations);
93 
94  for (i = 0; pos < len; i++) {
95  animations[anim_id].faces[i] = packet_to_uint16(data, len, &pos);
96  image_request_face(animations[anim_id].faces[i]);
97  }
98 }
99 
101 void socket_command_image(uint8_t *data, size_t len, size_t pos)
102 {
103  uint32_t facenum, filesize;
104  char buf[HUGE_BUF];
105  FILE *fp;
106 
107  facenum = packet_to_uint32(data, len, &pos);
108  filesize = packet_to_uint32(data, len, &pos);
109 
110  /* Save picture to cache and load it to FaceList. */
111  snprintf(buf, sizeof(buf), DIRECTORY_CACHE "/%s", FaceList[facenum].name);
112 
113  fp = path_fopen(buf, "wb+");
114 
115  if (fp) {
116  fwrite(data + pos, 1, filesize, fp);
117  fclose(fp);
118  }
119 
120  FaceList[facenum].sprite = sprite_tryload_file(buf, 0, NULL);
121  map_redraw_flag = minimap_redraw_flag = 1;
122 
123  book_redraw();
125 
126  /* TODO: this could be a bit more intelligent to detect whether any of
127  * these widgets actually contain an object with the updated face. */
128  WIDGET_REDRAW_ALL(PDOLL_ID);
129  WIDGET_REDRAW_ALL(QUICKSLOT_ID);
130  WIDGET_REDRAW_ALL(INVENTORY_ID);
131 }
132 
134 void socket_command_drawinfo(uint8_t *data, size_t len, size_t pos)
135 {
136  uint8_t type;
137  char color[COLOR_BUF], *str;
138  StringBuffer *sb;
139 
140  type = packet_to_uint8(data, len, &pos);
141  packet_to_string(data, len, &pos, color, sizeof(color));
142 
143  sb = stringbuffer_new();
144  packet_to_stringbuffer(data, len, &pos, sb);
145  str = stringbuffer_finish(sb);
146 
147  draw_info_tab(type, color, str);
148 
149  efree(str);
150 }
151 
153 void socket_command_target(uint8_t *data, size_t len, size_t pos)
154 {
155  cpl.target_code = packet_to_uint8(data, len, &pos);
156  packet_to_string(data, len, &pos, cpl.target_color, sizeof(cpl.target_color));
157  packet_to_string(data, len, &pos, cpl.target_name, sizeof(cpl.target_name));
158  cpl.combat = packet_to_uint8(data, len, &pos);
159  cpl.combat_force = packet_to_uint8(data, len, &pos);
160  WIDGET_REDRAW_ALL(TARGET_ID);
161 
162  map_redraw_flag = 1;
163 }
164 
166 void socket_command_stats(uint8_t *data, size_t len, size_t pos)
167 {
168  uint8_t type;
169  int temp;
170 
171  while (pos < len) {
172  type = packet_to_uint8(data, len, &pos);
173 
174  if (type >= CS_STAT_EQUIP_START && type <= CS_STAT_EQUIP_END) {
175  cpl.equipment[type - CS_STAT_EQUIP_START] = packet_to_uint32(data, len, &pos);
176  WIDGET_REDRAW_ALL(PDOLL_ID);
177  } else if (type >= CS_STAT_PROT_START && type <= CS_STAT_PROT_END) {
178  cpl.stats.protection[type - CS_STAT_PROT_START] =
179  packet_to_int8(data, len, &pos);
180  WIDGET_REDRAW_ALL(PROTECTIONS_ID);
181  } else {
182  switch (type) {
183  case CS_STAT_TARGET_HP:
184  cpl.target_hp = packet_to_uint8(data, len, &pos);
185  WIDGET_REDRAW_ALL(TARGET_ID);
186  break;
187 
188  case CS_STAT_REG_HP:
189  cpl.gen_hp = packet_to_uint16(data, len, &pos) / 10.0f;
190  widget_redraw_type_id(STAT_ID, "health");
191  break;
192 
193  case CS_STAT_REG_MANA:
194  cpl.gen_sp = packet_to_uint16(data, len, &pos) / 10.0f;
195  widget_redraw_type_id(STAT_ID, "mana");
196  break;
197 
198  case CS_STAT_HP:
199  temp = packet_to_int32(data, len, &pos);
200 
201  if (temp < cpl.stats.hp && cpl.stats.food) {
202  cpl.warn_hp = 1;
203 
204  if (cpl.stats.maxhp / 12 <= cpl.stats.hp - temp) {
205  cpl.warn_hp = 2;
206  }
207  }
208 
209  cpl.stats.hp = temp;
210  widget_redraw_type_id(STAT_ID, "health");
211  break;
212 
213  case CS_STAT_MAXHP:
214  cpl.stats.maxhp = packet_to_int32(data, len, &pos);
215  widget_redraw_type_id(STAT_ID, "health");
216  break;
217 
218  case CS_STAT_SP:
219  cpl.stats.sp = packet_to_int16(data, len, &pos);
220  widget_redraw_type_id(STAT_ID, "mana");
221  break;
222 
223  case CS_STAT_MAXSP:
224  cpl.stats.maxsp = packet_to_int16(data, len, &pos);
225  widget_redraw_type_id(STAT_ID, "mana");
226  break;
227 
228  case CS_STAT_STR:
229  case CS_STAT_INT:
230  case CS_STAT_POW:
231  case CS_STAT_DEX:
232  case CS_STAT_CON:
233  {
234  int8_t *stat_curr;
235  uint8_t stat_new;
236 
237  stat_curr = &(cpl.stats.Str) + (sizeof(cpl.stats.Str) * (type - CS_STAT_STR));
238  stat_new = packet_to_uint8(data, len, &pos);
239 
240  if (*stat_curr != -1) {
241  if (stat_new > *stat_curr) {
242  cpl.warn_statup = 1;
243  } else if (stat_new < *stat_curr) {
244  cpl.warn_statdown = 1;
245  }
246  }
247 
248  *stat_curr = stat_new;
249  WIDGET_REDRAW_ALL(PDOLL_ID);
250  break;
251  }
252 
253  case CS_STAT_PATH_ATTUNED:
254  cpl.path_attuned = packet_to_uint32(data, len, &pos);
255  WIDGET_REDRAW_ALL(SPELLS_ID);
256  break;
257 
258  case CS_STAT_PATH_REPELLED:
259  cpl.path_repelled = packet_to_uint32(data, len, &pos);
260  WIDGET_REDRAW_ALL(SPELLS_ID);
261  break;
262 
263  case CS_STAT_PATH_DENIED:
264  cpl.path_denied = packet_to_uint32(data, len, &pos);
265  WIDGET_REDRAW_ALL(SPELLS_ID);
266  break;
267 
268  case CS_STAT_EXP:
269  cpl.stats.exp = packet_to_uint64(data, len, &pos);
270  widget_redraw_type_id(STAT_ID, "exp");
271  break;
272 
273  case CS_STAT_LEVEL:
274  cpl.stats.level = packet_to_uint8(data, len, &pos);
275  WIDGET_REDRAW_ALL(PLAYER_INFO_ID);
276  break;
277 
278  case CS_STAT_WC:
279  cpl.stats.wc = packet_to_uint16(data, len, &pos);
280  WIDGET_REDRAW_ALL(PDOLL_ID);
281  break;
282 
283  case CS_STAT_AC:
284  cpl.stats.ac = packet_to_uint16(data, len, &pos);
285  WIDGET_REDRAW_ALL(PDOLL_ID);
286  break;
287 
288  case CS_STAT_DAM:
289  cpl.stats.dam = packet_to_uint16(data, len, &pos);
290  WIDGET_REDRAW_ALL(PDOLL_ID);
291  break;
292 
293  case CS_STAT_SPEED:
294  cpl.stats.speed = packet_to_double(data, len, &pos);
295  WIDGET_REDRAW_ALL(PDOLL_ID);
296  break;
297 
298  case CS_STAT_FOOD:
299  cpl.stats.food = packet_to_uint16(data, len, &pos);
300  widget_redraw_type_id(STAT_ID, "food");
301  break;
302 
303  case CS_STAT_WEAPON_SPEED:
304  cpl.stats.weapon_speed = packet_to_double(data, len, &pos);
305  WIDGET_REDRAW_ALL(PDOLL_ID);
306  break;
307 
308  case CS_STAT_FLAGS:
309  cpl.stats.flags = packet_to_uint16(data, len, &pos);
310  break;
311 
312  case CS_STAT_WEIGHT_LIM:
313  cpl.weight_limit = packet_to_uint32(data, len, &pos) / 1000.0;
314  break;
315 
316  case CS_STAT_ACTION_TIME:
317  cpl.action_timer = packet_to_float(data, len, &pos);
318  WIDGET_REDRAW_ALL(PLAYER_INFO_ID);
319  break;
320 
321  case CS_STAT_GENDER:
322  cpl.gender = packet_to_uint8(data, len, &pos);
323  WIDGET_REDRAW_ALL(PDOLL_ID);
324  break;
325 
326  case CS_STAT_RANGED_DAM:
327  cpl.stats.ranged_dam = packet_to_uint16(data, len, &pos);
328  WIDGET_REDRAW_ALL(PDOLL_ID);
329  break;
330 
331  case CS_STAT_RANGED_WC:
332  cpl.stats.ranged_wc = packet_to_uint16(data, len, &pos);
333  WIDGET_REDRAW_ALL(PDOLL_ID);
334  break;
335 
336  case CS_STAT_RANGED_WS:
337  cpl.stats.ranged_ws = packet_to_float(data, len, &pos);
338  WIDGET_REDRAW_ALL(PDOLL_ID);
339  break;
340  }
341  }
342  }
343 }
344 
346 void socket_command_player(uint8_t *data, size_t len, size_t pos)
347 {
348  int tag, weight, face;
349 
350  tag = packet_to_uint32(data, len, &pos);
351  weight = packet_to_uint32(data, len, &pos);
352  face = packet_to_uint32(data, len, &pos);
353  image_request_face(face);
354  packet_to_string(data, len, &pos, cpl.name, sizeof(cpl.name));
355 
356  new_player(tag, weight, face);
357  map_redraw_flag = 1;
358 
359  cur_widget[INPUT_ID]->show = 0;
360 
361  if (cur_widget[PARTY_ID]->show) {
362  send_command("/party list");
363  }
364 
365  cpl.state = ST_PLAY;
366 }
367 
368 void command_item_update(uint8_t *data, size_t len, size_t *pos, uint32_t flags, object *tmp)
369 {
370  bool force_anim = false;
371 
372  if (flags & UPD_LOCATION) {
373  /* Currently unused. */
374  packet_to_uint32(data, len, pos);
375  }
376 
377  if (flags & UPD_FLAGS) {
378  tmp->flags = packet_to_uint32(data, len, pos);
379  }
380 
381  if (flags & UPD_WEIGHT) {
382  tmp->weight = packet_to_uint32(data, len, pos) / 1000.0;
383  }
384 
385  if (flags & UPD_FACE) {
386  tmp->face = packet_to_uint16(data, len, pos);
387  image_request_face(tmp->face);
388  }
389 
390  if (flags & UPD_DIRECTION) {
391  tmp->direction = packet_to_uint8(data, len, pos);
392  }
393 
394  if (flags & UPD_TYPE) {
395  tmp->itype = packet_to_uint8(data, len, pos);
396  tmp->stype = packet_to_uint8(data, len, pos);
397  tmp->item_qua = packet_to_uint8(data, len, pos);
398 
399  if (tmp->item_qua != 255) {
400  tmp->item_con = packet_to_uint8(data, len, pos);
401  tmp->item_level = packet_to_uint8(data, len, pos);
402  tmp->item_skill_tag = packet_to_uint32(data, len, pos);
403  }
404  }
405 
406  if (flags & UPD_NAME) {
407  packet_to_string(data, len, pos, tmp->s_name, sizeof(tmp->s_name));
408  }
409 
410  if (flags & UPD_ANIM) {
411  uint16_t animation_id;
412 
413  animation_id = packet_to_uint16(data, len, pos);
414 
415  /* Changing animation ID, force animation. */
416  if (tmp->animation_id != animation_id) {
417  force_anim = true;
418  tmp->anim_state = 0;
419  }
420 
421  tmp->animation_id = animation_id;
422  }
423 
424  if (flags & UPD_ANIMSPEED) {
425  uint8_t anim_speed;
426 
427  anim_speed = packet_to_uint8(data, len, pos);
428 
429  /* Animation was disabled and we're enabling it, force animation. */
430  if (tmp->anim_speed == 0 && anim_speed != 0) {
431  force_anim = true;
432  }
433 
434  tmp->anim_speed = anim_speed;
435  }
436 
437  if (flags & UPD_NROF) {
438  tmp->nrof = packet_to_uint32(data, len, pos);
439 
440  if (tmp->nrof == 0) {
441  tmp->nrof = 1;
442  }
443  }
444 
445  if (flags & UPD_EXTRA) {
446  if (tmp->itype == TYPE_SPELL) {
447  uint16_t spell_cost;
448  uint32_t spell_path, spell_flags;
449  char spell_msg[MAX_BUF];
450 
451  spell_cost = packet_to_uint16(data, len, pos);
452  spell_path = packet_to_uint32(data, len, pos);
453  spell_flags = packet_to_uint32(data, len, pos);
454  packet_to_string(data, len, pos, spell_msg, sizeof(spell_msg));
455 
456  spells_update(tmp, spell_cost, spell_path, spell_flags, spell_msg);
457  } else if (tmp->itype == TYPE_SKILL) {
458  uint8_t skill_level = packet_to_uint8(data, len, pos);
459  int64_t skill_exp = packet_to_int64(data, len, pos);
460  char skill_msg[MAX_BUF];
461  packet_to_string(data, len, pos, VS(skill_msg));
462 
463  skills_update(tmp, skill_level, skill_exp, skill_msg);
464  } else if (tmp->itype == TYPE_FORCE || tmp->itype == TYPE_POISONING) {
465  int32_t sec;
466  char msg[HUGE_BUF];
467 
468  sec = packet_to_int32(data, len, pos);
469  packet_to_string(data, len, pos, msg, sizeof(msg));
470 
471  widget_active_effects_update(cur_widget[ACTIVE_EFFECTS_ID], tmp, sec, msg);
472  }
473  }
474 
475  if (flags & UPD_GLOW) {
476  packet_to_string(data, len, pos, VS(tmp->glow));
477  tmp->glow_speed = packet_to_uint8(data, len, pos);
478  }
479 
480  if (tmp->itype == TYPE_REGION_MAP) {
481  region_map_fow_update(MapData.region_map);
482  minimap_redraw_flag = 1;
483  }
484 
485  if (force_anim) {
486  tmp->last_anim = tmp->anim_speed;
487  object_animate(tmp);
488  }
489 
490  object_redraw(tmp);
491 }
492 
494 void socket_command_item(uint8_t *data, size_t len, size_t pos)
495 {
496  bool delete_env = packet_to_uint8(data, len, &pos) == 1;
497  if (delete_env) {
498  tag_t loc_delete = packet_to_uint32(data, len, &pos);
499  object *env = object_find(loc_delete);
500  if (env == NULL) {
501  return;
502  }
503 
505 
506  if (pos == len) {
507  return;
508  }
509  }
510 
511  tag_t loc = packet_to_uint32(data, len, &pos);
512  object *env = object_find(loc);
513  if (env == NULL) {
514  LOG(ERROR, "Server sent invalid location: %" PRIu32, loc);
515  return;
516  }
517 
518  if (env != cpl.below && env != cpl.ob) {
519  cpl.sack = env;
520  }
521 
522  uint8_t bflag = packet_to_uint8(data, len, &pos);
523 
524  while (pos < len) {
525  tag_t tag = packet_to_uint32(data, len, &pos);
526  uint8_t apply_action = CMD_APPLY_ACTION_NORMAL;
527 
528  object *tmp = NULL;
529  if (tag != 0) {
530  tmp = object_find(tag);
531  } else {
532  apply_action = packet_to_uint8(data, len, &pos);
533  }
534 
535  if (tmp != NULL && tmp->env != env) {
536  object_remove(tmp);
537  tmp = NULL;
538  }
539 
540  if (tmp == NULL || delete_env) {
541  object *old_tmp = tmp;
542  tmp = object_create(env, tag, bflag);
543  tmp->apply_action = apply_action;
544 
545  if (old_tmp != NULL) {
546  if (old_tmp == cpl.sack) {
547  cpl.sack = tmp;
548  }
549 
550  object_transfer_inventory(old_tmp, tmp);
551  object_remove(old_tmp);
552  }
553  }
554 
555  uint32_t flags = UPD_FLAGS | UPD_WEIGHT | UPD_FACE | UPD_DIRECTION |
556  UPD_NAME | UPD_ANIM | UPD_ANIMSPEED | UPD_NROF | UPD_GLOW;
557 
558  if (loc > 0) {
559  flags |= UPD_TYPE | UPD_EXTRA;
560  }
561 
562  command_item_update(data, len, &pos, flags, tmp);
563  }
564 }
565 
567 void socket_command_item_update(uint8_t *data, size_t len, size_t pos)
568 {
569  uint32_t flags, tag;
570  object *tmp;
571 
572  flags = packet_to_uint16(data, len, &pos);
573  tag = packet_to_uint32(data, len, &pos);
574 
575  tmp = object_find(tag);
576 
577  if (!tmp) {
578  return;
579  }
580 
581  command_item_update(data, len, &pos, flags, tmp);
582 }
583 
585 void socket_command_item_delete(uint8_t *data, size_t len, size_t pos)
586 {
587  tag_t tag;
588 
589  while (pos < len) {
590  tag = packet_to_uint32(data, len, &pos);
591  delete_object(tag);
592  }
593 }
594 
598 static void map_play_footstep(void)
599 {
600  static int step = 0;
601  static uint32_t tick = 0;
602 
603  if (LastTick - tick > 125) {
604  step++;
605 
606  if (step % 2) {
607  sound_play_effect("step1.ogg", 100);
608  } else {
609  step = 0;
610  sound_play_effect("step2.ogg", 100);
611  }
612 
613  tick = LastTick;
614  }
615 }
616 
618 void socket_command_mapstats(uint8_t *data, size_t len, size_t pos)
619 {
620  uint8_t type;
621  char buf[HUGE_BUF];
622 
623  while (pos < len) {
624  /* Get the type of this command... */
625  type = packet_to_uint8(data, len, &pos);
626 
627  if (type == CMD_MAPSTATS_NAME) {
628  /* Change map name. */
629  packet_to_string(data, len, &pos, buf, sizeof(buf));
630  update_map_name(buf);
631  } else if (type == CMD_MAPSTATS_MUSIC) {
632  /* Change map music. */
633  packet_to_string(data, len, &pos, buf, sizeof(buf));
634  update_map_bg_music(buf);
635  } else if (type == CMD_MAPSTATS_WEATHER) {
636  /* Change map weather. */
637  packet_to_string(data, len, &pos, buf, sizeof(buf));
638  update_map_weather(buf);
639  } else if (type == CMD_MAPSTATS_TEXT_ANIM) {
640  packet_to_string(data, len, &pos, msg_anim.color, sizeof(msg_anim.color));
641  packet_to_string(data, len, &pos, msg_anim.message, sizeof(msg_anim.message));
643  }
644  }
645 }
646 
648 void socket_command_map(uint8_t *data, size_t len, size_t pos)
649 {
650  static int mx = 0, my = 0;
651  int mask, x, y, rx, ry;
652  int mapstat;
653  int xpos, ypos;
654  int layer, ext_flags;
655  uint8_t num_layers, in_building;
656  region_map_def_map_t *def_map;
657  bool region_map_fow_need_update;
658 
659  mapstat = packet_to_uint8(data, len, &pos);
660 
661  if (mapstat != MAP_UPDATE_CMD_SAME) {
662  char mapname[HUGE_BUF], bg_music[HUGE_BUF], weather[MAX_BUF],
663  region_name[MAX_BUF], region_longname[MAX_BUF],
664  mappath[HUGE_BUF];
665  uint8_t height_diff;
666 
667  packet_to_string(data, len, &pos, mapname, sizeof(mapname));
668  packet_to_string(data, len, &pos, bg_music, sizeof(bg_music));
669  packet_to_string(data, len, &pos, weather, sizeof(weather));
670  height_diff = packet_to_uint8(data, len, &pos);
671  MapData.region_has_map = packet_to_uint8(data, len, &pos);
672  packet_to_string(data, len, &pos, VS(region_name));
673  packet_to_string(data, len, &pos, VS(region_longname));
674  packet_to_string(data, len, &pos, VS(mappath));
675 
676  if (mapstat == MAP_UPDATE_CMD_NEW) {
677  int map_w, map_h;
678 
679  map_w = packet_to_uint8(data, len, &pos);
680  map_h = packet_to_uint8(data, len, &pos);
681  xpos = packet_to_uint8(data, len, &pos);
682  ypos = packet_to_uint8(data, len, &pos);
683  mx = xpos;
684  my = ypos;
685  init_map_data(map_w, map_h, xpos, ypos);
686  } else {
687  int xoff, yoff;
688 
689  mapstat = packet_to_uint8(data, len, &pos);
690  xoff = packet_to_int8(data, len, &pos);
691  yoff = packet_to_int8(data, len, &pos);
692  xpos = packet_to_uint8(data, len, &pos);
693  ypos = packet_to_uint8(data, len, &pos);
694  mx = xpos;
695  my = ypos;
696  display_mapscroll(xoff, yoff, 0, 0);
697 
699  }
700 
701  update_map_name(mapname);
702  update_map_bg_music(bg_music);
703  update_map_weather(weather);
704  update_map_height_diff(height_diff);
705  update_map_region_name(region_name);
706  update_map_region_longname(region_longname);
707  update_map_path(mappath);
708  } else {
709  xpos = packet_to_uint8(data, len, &pos);
710  ypos = packet_to_uint8(data, len, &pos);
711 
712  /* Have we moved? */
713  if ((xpos - mx || ypos - my)) {
714  display_mapscroll(xpos - mx, ypos - my, 0, 0);
716  }
717 
718  mx = xpos;
719  my = ypos;
720  }
721 
722  MapData.posx = xpos;
723  MapData.posy = ypos;
724  MapData.player_sub_layer = packet_to_uint8(data, len, &pos);
726 
727  in_building = packet_to_uint8(data, len, &pos);
728 
729  map_get_real_coords(&rx, &ry);
730  region_map_fow_need_update = false;
731 
732  while (pos < len) {
733  mask = packet_to_uint16(data, len, &pos);
734  x = (mask >> 11) & 0x1f;
735  y = (mask >> 6) & 0x1f;
736 
737  /* Clear the whole cell? */
738  if (mask & MAP2_MASK_CLEAR) {
739  map_clear_cell(x, y);
740  continue;
741  }
742 
743  if (MapData.region_name[0] != '\0') {
744  if (region_map_fow_set_visited(MapData.region_map, def_map,
745  MapData.map_path, rx + x, ry + y)) {
746  region_map_fow_need_update = true;
747  }
748  }
749 
750  /* Do we have darkness information? */
751  if (mask & MAP2_MASK_DARKNESS) {
752  map_set_darkness(x, y, 0, packet_to_uint8(data, len, &pos));
753  }
754 
755  if (mask & MAP2_MASK_DARKNESS_MORE) {
756  int sub_layer;
757 
758  for (sub_layer = 1; sub_layer < NUM_SUB_LAYERS; sub_layer++) {
759  map_set_darkness(x, y, sub_layer, packet_to_uint8(data, len,
760  &pos));
761  }
762  }
763 
764  num_layers = packet_to_uint8(data, len, &pos);
765 
766  /* Go through all the layers on this tile. */
767  for (layer = 0; layer < num_layers; layer++) {
768  uint8_t type;
769 
770  type = packet_to_uint8(data, len, &pos);
771 
772  /* Clear this layer. */
773  if (type == MAP2_LAYER_CLEAR) {
774  map_set_data(x, y, packet_to_uint8(data, len, &pos), 0, 0, 0,
775  "", "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
776  0, "", 0);
777  } else { /* We have some data. */
778  int16_t face, height = 0, zoom_x = 0, zoom_y = 0, align = 0, rotate = 0;
779  uint8_t flags, obj_flags, quick_pos = 0, probe = 0, draw_double = 0, alpha = 0, infravision = 0, target_is_friend = 0;
780  uint8_t anim_speed, anim_facing, anim_flags, anim_state, priority, secondpass, glow_speed;
781  char player_name[64], player_color[COLOR_BUF], glow[COLOR_BUF];
782  uint32_t target_object_count = 0;
783 
784  anim_speed = anim_facing = anim_flags = anim_state = 0;
785  priority = secondpass = glow_speed = 0;
786 
787  player_name[0] = '\0';
788  player_color[0] = '\0';
789  glow[0] = '\0';
790 
791  face = packet_to_uint16(data, len, &pos);
792  /* Object flags. */
793  obj_flags = packet_to_uint8(data, len, &pos);
794  /* Flags of this layer. */
795  flags = packet_to_uint8(data, len, &pos);
796 
797  /* Multi-arch? */
798  if (flags & MAP2_FLAG_MULTI) {
799  quick_pos = packet_to_uint8(data, len, &pos);
800  }
801 
802  /* Player name? */
803  if (flags & MAP2_FLAG_NAME) {
804  packet_to_string(data, len, &pos, VS(player_name));
805  packet_to_string(data, len, &pos, VS(player_color));
806  }
807 
808  /* Animation? */
809  if (flags & MAP2_FLAG_ANIMATION) {
810  anim_speed = packet_to_uint8(data, len, &pos);
811  anim_facing = packet_to_uint8(data, len, &pos);
812  anim_flags = packet_to_uint8(data, len, &pos);
813 
814  if (anim_flags & ANIM_FLAG_MOVING) {
815  anim_state = packet_to_uint8(data, len, &pos);
816  }
817  }
818 
819  /* Z position? */
820  if (flags & MAP2_FLAG_HEIGHT) {
821  height = packet_to_int16(data, len, &pos);
822  }
823 
824  /* Align? */
825  if (flags & MAP2_FLAG_ALIGN) {
826  align = packet_to_int16(data, len, &pos);
827  }
828 
829  if (flags & MAP2_FLAG_INFRAVISION) {
830  infravision = 1;
831  }
832 
833  /* Double? */
834  if (flags & MAP2_FLAG_DOUBLE) {
835  draw_double = 1;
836  }
837 
838  if (flags & MAP2_FLAG_MORE) {
839  uint32_t flags2;
840 
841  flags2 = packet_to_uint32(data, len, &pos);
842 
843  if (flags2 & MAP2_FLAG2_ALPHA) {
844  alpha = packet_to_uint8(data, len, &pos);
845  }
846 
847  if (flags2 & MAP2_FLAG2_ROTATE) {
848  rotate = packet_to_int16(data, len, &pos);
849  }
850 
851  /* Zoom? */
852  if (flags2 & MAP2_FLAG2_ZOOM) {
853  zoom_x = packet_to_uint16(data, len, &pos);
854  zoom_y = packet_to_uint16(data, len, &pos);
855  }
856 
857  if (flags2 & MAP2_FLAG2_TARGET) {
858  target_object_count = packet_to_uint32(data, len, &pos);
859  target_is_friend = packet_to_uint8(data, len, &pos);
860  }
861 
862  /* Target's HP? */
863  if (flags2 & MAP2_FLAG2_PROBE) {
864  probe = packet_to_uint8(data, len, &pos);
865  }
866 
867  if (flags2 & MAP2_FLAG2_PRIORITY) {
868  priority = 1;
869  }
870 
871  if (flags2 & MAP2_FLAG2_SECONDPASS) {
872  secondpass = 1;
873  }
874 
875  if (flags2 & MAP2_FLAG2_GLOW) {
876  packet_to_string(data, len, &pos, VS(glow));
877  glow_speed = packet_to_uint8(data, len, &pos);
878  }
879  }
880 
881  /* Set the data we figured out. */
882  map_set_data(x, y, type, face, quick_pos, obj_flags,
883  player_name, player_color, height, probe, zoom_x,
884  zoom_y, align, draw_double, alpha, rotate, infravision,
885  target_object_count, target_is_friend, anim_speed,
886  anim_facing, anim_flags, anim_state, priority,
887  secondpass, glow, glow_speed);
888  }
889  }
890 
891  /* Get tile flags. */
892  ext_flags = packet_to_uint8(data, len, &pos);
893 
894  /* Animation? */
895  if (ext_flags & MAP2_FLAG_EXT_ANIM) {
896  uint8_t anim_num = packet_to_uint8(data, len, &pos);
897 
898  for (uint8_t i = 0; i < anim_num; i++) {
899  uint8_t sub_layer = packet_to_uint8(data, len, &pos);
900  uint8_t anim_type = packet_to_uint8(data, len, &pos);
901  int16_t anim_value = packet_to_int16(data, len, &pos);
902 
903  map_anims_add(anim_type, x, y, sub_layer, anim_value);
904  }
905  }
906  }
907 
909  map_update_in_building(in_building);
910  map_redraw_flag = minimap_redraw_flag = 1;
911 
912  if (region_map_fow_need_update) {
913  region_map_fow_update(MapData.region_map);
914  }
915 }
916 
918 void socket_command_version(uint8_t *data, size_t len, size_t pos)
919 {
920  if (cpl.state != ST_WAITVERSION) {
921  LOG(BUG, "Received version command when not in proper "
922  "state: %d, should be: %d.", cpl.state, ST_WAITVERSION);
923  return;
924  }
925 
926  cpl.server_socket_version = packet_to_uint32(data, len, &pos);
927  cpl.state = ST_VERSION;
928 }
929 
931 void socket_command_compressed(uint8_t *data, size_t len, size_t pos)
932 {
933  unsigned long ucomp_len;
934  uint8_t type, *dest;
935  size_t dest_size;
936 
937  type = packet_to_uint8(data, len, &pos);
938  ucomp_len = packet_to_uint32(data, len, &pos);
939 
940  dest_size = ucomp_len + 1;
941  dest = emalloc(dest_size);
942  dest[0] = type;
943 
944  if (uncompress((Bytef *) dest + 1, (uLongf *) & ucomp_len,
945  (const Bytef *) data + pos, (uLong) len - pos) == Z_OK) {
946  command_buffer *buf;
947 
948  buf = command_buffer_new(ucomp_len + 1, dest);
949  add_input_command(buf);
950  }
951 
952  efree(dest);
953 }
954 
956 void socket_command_control(uint8_t *data, size_t len, size_t pos)
957 {
958  char app_name[MAX_BUF];
959  uint8_t type, sub_type;
960 
961  packet_to_string(data, len, &pos, app_name, sizeof(app_name));
962  type = packet_to_uint8(data, len, &pos);
963  sub_type = packet_to_uint8(data, len, &pos);
964 
965  if (type == CMD_CONTROL_PLAYER && sub_type == CMD_CONTROL_PLAYER_TELEPORT) {
966  x11_window_activate(SDL_display, x11_window_get_parent(SDL_display, SDL_window), 1);
967  }
968 }
969 
973 typedef struct socket_crypto_popup {
974  socket_crypto_cb_ctx_t ctx;
977  uint32_t ticks;
978  int seconds;
980 
984 static const char *const socket_crypto_popup_texts[] = {
985  "The selected server uses a self-signed certificate. This means that it's "
986  "impossible to verify the authenticity of the server, and someone could be "
987  "spying on your connection via a forged certificate.\n\n"
988  "It is strongly recommended NOT to proceed (especially if you've connected "
989  "to this server before and this warning did not appear then).\n\n"
990  "Do you want to proceed (and remember this choice)?",
991  "!!! THE PUBLIC KEY OF THE SERVER HAS CHANGED !!!\n\n"
992  "This is most likely an indication of an MITM (Man In The Middle) attack. "
993  "It is also possible the server's public key has just changed.\n\n"
994  "It is STRONGLY RECOMMENDED [b]NOT[/b] to connect unless you have solid "
995  "evidence that this is correct (eg, an announcement from the server "
996  "officials about the change, ideally if this announcement was at least a "
997  "month in advance).\n\n"
998  "Do you want to proceed (and remember this choice)?",
999 };
1000 CASSERT_ARRAY(socket_crypto_popup_texts, SOCKET_CRYPTO_CB_MAX);
1001 
1006 static const int socket_crypto_popup_delays[] = {
1007  20, /* Self-signed certificate */
1008  60, /* Public key has changed */
1009 };
1010 CASSERT_ARRAY(socket_crypto_popup_delays, SOCKET_CRYPTO_CB_MAX);
1011 
1013 static int
1015 {
1016  socket_crypto_popup_t *data = popup->custom_data;
1017 
1018  int delay = socket_crypto_popup_delays[data->ctx.id];
1019  if (data->seconds != delay) {
1020  uint32_t ticks_diff = SDL_GetTicks() - data->ticks;
1021  int seconds = ticks_diff / 1000;
1022  if (data->seconds != seconds) {
1023  data->seconds = seconds;
1024  popup->redraw = 1;
1025 
1026  if (seconds == delay) {
1027  data->button_ok.disabled = false;
1028  }
1029  }
1030  }
1031 
1032  if (!popup->redraw) {
1033  return 1;
1034  }
1035 
1036  popup->redraw = 0;
1037  surface_show(popup->surface, 0, 0, NULL, texture_surface(popup->texture));
1038 
1039  SDL_Rect box;
1040  box.w = popup->surface->w;
1041  box.h = 38;
1042  text_show(popup->surface,
1043  FONT_SERIF16,
1044  "Suspicious connection!",
1045  0,
1046  0,
1047  COLOR_HGOLD,
1049  &box);
1050 
1051  box.w = popup->surface->w - 10 * 2;
1052  box.h = popup->surface->h - box.h;
1053  text_show(popup->surface,
1054  FONT_ARIAL12,
1055  socket_crypto_popup_texts[data->ctx.id],
1056  10,
1057  50,
1058  COLOR_WHITE,
1060  &box);
1061 
1062  if (data->ctx.fingerprint != NULL) {
1063  text_show(popup->surface,
1064  FONT_ARIAL12,
1065  "Certificate fingerprint:",
1066  0,
1067  90,
1068  COLOR_WHITE,
1070  &box);
1071  text_show(popup->surface,
1072  FONT_ARIAL12,
1073  data->ctx.fingerprint,
1074  0,
1075  110,
1076  COLOR_WHITE,
1078  &box);
1079  }
1080 
1081  char buf[MAX_BUF];
1082  snprintf(VS(buf), "%s", "OK");
1083  if (data->seconds != delay) {
1084  snprintfcat(VS(buf), " (%d)", delay - data->seconds);
1085  }
1086 
1087  data->button_ok.x = popup->surface->w / 4 -
1088  data->button_ok.texture->surface->w;
1089  data->button_ok.y = popup->surface->h -
1090  data->button_ok.texture->surface->h * 2;
1091  data->button_ok.surface = popup->surface;
1092  data->button_ok.px = popup->x;
1093  data->button_ok.py = popup->y;
1094  button_show(&data->button_ok, buf);
1095 
1096  data->button_close.x = popup->surface->w - popup->surface->w / 4;
1097  data->button_close.y = popup->surface->h -
1098  data->button_close.texture->surface->h * 2;
1099  data->button_close.surface = popup->surface;
1100  data->button_close.px = popup->x;
1101  data->button_close.py = popup->y;
1102  button_show(&data->button_close, "Close");
1103 
1104  return 1;
1105 }
1106 
1108 static int
1109 popup_event (popup_struct *popup, SDL_Event *event)
1110 {
1111  socket_crypto_popup_t *data = popup->custom_data;
1112 
1113  if (button_event(&data->button_ok, event) ||
1114  (event->type == SDL_KEYDOWN &&
1115  (event->key.keysym.sym == SDLK_RETURN ||
1116  event->key.keysym.sym == SDLK_KP_ENTER))) {
1117  char *errmsg;
1118  if (!socket_crypto_handle_cb(&data->ctx, &errmsg)) {
1119  draw_info(COLOR_RED, errmsg);
1120  efree(errmsg);
1121  }
1122 
1123  popup_destroy(popup);
1124  login_start();
1125  return 1;
1126  } else if (button_event(&data->button_close, event)) {
1127  popup_destroy(popup);
1128  return 1;
1129  }
1130 
1131  if (data->button_ok.redraw || data->button_close.redraw) {
1132  popup->redraw = true;
1133  }
1134 
1135  return -1;
1136 }
1137 
1139 static int
1141 {
1142  if (cpl.state != ST_WAITLOOP) {
1143  return 0;
1144  }
1145 
1146  socket_crypto_popup_t *data = popup->custom_data;
1147  socket_crypto_free_cb(&data->ctx);
1148  efree(data);
1149  popup->custom_data = NULL;
1150  return 1;
1151 }
1152 
1154 static const char *
1156 {
1157  socket_crypto_popup_t *data = popup->custom_data;
1158  return data->ctx.fingerprint != NULL ? data->ctx.fingerprint : "";
1159 }
1160 
1162 static void
1163 socket_crypto_cb (socket_crypto_t *crypto, const socket_crypto_cb_ctx_t *ctx)
1164 {
1165  socket_crypto_popup_t *data = ecalloc(1, sizeof(*data));
1166  data->ctx = *ctx;
1167  data->ticks = SDL_GetTicks();
1168 
1169  button_create(&data->button_ok);
1170  data->button_ok.disabled = true;
1171  button_create(&data->button_close);
1172 
1173  popup_struct *popup = popup_create(texture_get(TEXTURE_TYPE_CLIENT,
1174  "popup"));
1175  popup->draw_func = popup_draw;
1176  popup->event_func = popup_event;
1179  popup->disable_texture_drawing = 1;
1180  popup->custom_data = data;
1181 }
1182 
1186 static void
1188 {
1189  cpl.state = ST_START;
1191  "Failed to establish a secure connection with %s; see the "
1192  "client log for details.",
1194 }
1195 
1201 static void
1202 socket_command_crypto_hello (uint8_t *data, size_t len, size_t pos)
1203 {
1204  StringBuffer *sb = stringbuffer_new();
1205  packet_to_stringbuffer(data, len, &pos, sb);
1206  char *cert = stringbuffer_finish(sb);
1207  sb = stringbuffer_new();
1208  packet_to_stringbuffer(data, len, &pos, sb);
1209  char *chain = stringbuffer_finish(sb);
1210 
1211  if (*cert == '\0') {
1212  LOG(ERROR, "Received empty certificate from server");
1214  return;
1215  }
1216 
1217  socket_crypto_t *crypto = socket_crypto_create(csocket.sc);
1218  socket_crypto_set_cb(crypto, socket_crypto_cb);
1219 
1220  /* Meta-server servers must have a certificate public key record
1221  * associated with them.*/
1222  if (selected_server->is_meta) {
1223  const char *pubkey = METASERVER_GET_PUBKEY(selected_server);
1224  if (pubkey == NULL) {
1225  LOG(ERROR, " !!! Server has no public key record! !!!");
1227  return;
1228  }
1229 
1230  if (!socket_crypto_load_pubkey(crypto, pubkey)) {
1231  LOG(ERROR, " !!! Failed to load metaserver public key: %s !!!", pubkey);
1233  return;
1234  }
1235  }
1236 
1237  if (!socket_crypto_load_cert(crypto, cert, chain)) {
1238  efree(cert);
1239  efree(chain);
1241  return;
1242  }
1243 
1244  efree(cert);
1245  efree(chain);
1246 
1247  uint8_t key_len;
1248  const unsigned char *key = socket_crypto_create_key(crypto, &key_len);
1249  if (key == NULL) {
1251  return;
1252  }
1253 
1254  /* Send the generated key to the server. */
1255  packet_struct *packet = packet_new(SERVER_CMD_CRYPTO, 128, 128);
1256  packet_append_uint8(packet, CMD_CRYPTO_KEY);
1257  packet_append_uint8(packet, key_len);
1258  packet_append_data_len(packet, key, key_len);
1259 
1260  uint8_t iv_len;
1261  const unsigned char *iv = socket_crypto_get_iv(crypto, &iv_len);
1262  if (iv == NULL) {
1264  return;
1265  }
1266 
1267  packet_append_uint8(packet, iv_len);
1268  packet_append_data_len(packet, iv, iv_len);
1269  socket_send_packet(packet);
1270 
1271  cpl.state = ST_WAITCRYPTO;
1272 }
1273 
1279 static void
1280 socket_command_crypto_key (uint8_t *data, size_t len, size_t pos)
1281 {
1282  socket_crypto_t *crypto = socket_get_crypto(csocket.sc);
1283  SOFT_ASSERT(crypto != NULL, "crypto is NULL");
1284 
1285  if (len == pos) {
1286  LOG(PACKET, "Server sent malformed crypto key command: %s",
1287  socket_get_str(csocket.sc));
1289  return;
1290  }
1291 
1292  uint8_t iv_len;
1293  const unsigned char *iv = socket_crypto_get_iv(crypto, &iv_len);
1294  if (iv == NULL) {
1296  return;
1297  }
1298 
1299  uint8_t recv_iv_len = packet_to_uint8(data, len, &pos);
1300  recv_iv_len = MIN(recv_iv_len, len - pos);
1301  const unsigned char *recv_iv = data + pos;
1302  pos += recv_iv_len;
1303 
1304  if (len != pos) {
1305  LOG(PACKET, "Server sent malformed crypto key command: %s",
1306  socket_get_str(csocket.sc));
1308  return;
1309  }
1310 
1311  if (iv_len != recv_iv_len) {
1312  LOG(PACKET, "Server sent mismatching IV buffer length");
1314  return;
1315  }
1316 
1317  if (memcmp(iv, recv_iv, iv_len) != 0) {
1318  LOG(PACKET, "Server sent mismatching IV buffer");
1320  return;
1321  }
1322 
1323  packet_struct *packet = packet_new(SERVER_CMD_CRYPTO, 128, 128);
1324  packet_append_uint8(packet, CMD_CRYPTO_CURVES);
1325  socket_crypto_packet_append_curves(packet);
1326  socket_send_packet(packet);
1327 }
1328 
1334 static void
1335 socket_command_crypto_curves (uint8_t *data, size_t len, size_t pos)
1336 {
1337  socket_crypto_t *crypto = socket_get_crypto(csocket.sc);
1338  SOFT_ASSERT(crypto != NULL, "crypto is NULL");
1339 
1340  char name[MAX_BUF];
1341  while (packet_to_string(data, len, &pos, VS(name)) != NULL) {
1342  int nid;
1343  if (socket_crypto_curve_supported(name, &nid)) {
1344  socket_crypto_set_nid(crypto, nid);
1345 
1346  uint8_t iv_size;
1347  const unsigned char *iv = socket_crypto_gen_iv(crypto, &iv_size);
1348  if (iv == NULL) {
1349  LOG(SYSTEM, "Failed to generate IV buffer: %s",
1350  socket_get_str(csocket.sc));
1352  return;
1353  }
1354 
1355  size_t pubkey_len;
1356  unsigned char *pubkey = socket_crypto_gen_pubkey(crypto,
1357  &pubkey_len);
1358  if (pubkey == NULL) {
1359  LOG(SYSTEM, "Failed to generate a public key: %s",
1360  socket_get_str(csocket.sc));
1362  return;
1363  }
1364 
1365  if (pubkey_len > INT16_MAX) {
1366  LOG(SYSTEM, "Public key too long: %s",
1367  socket_get_str(csocket.sc));
1369  efree(pubkey);
1370  return;
1371  }
1372 
1373  packet_struct *packet = packet_new(SERVER_CMD_CRYPTO, 512, 0);
1374  packet_append_uint8(packet, CMD_CRYPTO_PUBKEY);
1375  packet_append_uint16(packet, (uint16_t) pubkey_len);
1376  packet_append_data_len(packet, pubkey, pubkey_len);
1377  packet_append_uint8(packet, iv_size);
1378  packet_append_data_len(packet, iv, iv_size);
1379  socket_send_packet(packet);
1380  efree(pubkey);
1381  return;
1382  }
1383  }
1384 
1385  LOG(SYSTEM,
1386  "Server requested crypto but failed to provide a compatible "
1387  "crypto elliptic curve: %s",
1388  socket_get_str(csocket.sc));
1390 }
1391 
1397 static void
1398 socket_command_crypto_pubkey (uint8_t *data, size_t len, size_t pos)
1399 {
1400  socket_crypto_t *crypto = socket_get_crypto(csocket.sc);
1401  SOFT_ASSERT(crypto != NULL, "crypto is NULL");
1402 
1403  if (len == pos) {
1404  LOG(PACKET, "Server sent malformed crypto pubkey command: %s",
1405  socket_get_str(csocket.sc));
1407  return;
1408  }
1409 
1410  uint16_t pubkey_len = packet_to_uint16(data, len, &pos);
1411  unsigned char *pubkey = data + pos;
1412  pubkey_len = MIN(pubkey_len, len - pos);
1413  pos += pubkey_len;
1414  uint8_t iv_len = packet_to_uint8(data, len, &pos);
1415  unsigned char *iv = data + pos;
1416  iv_len = MIN(iv_len, len - pos);
1417  pos += iv_len;
1418 
1419  if (!socket_crypto_derive(crypto, pubkey, pubkey_len, iv, iv_len)) {
1420  LOG(SYSTEM, "Couldn't derive shared secret key: %s",
1421  socket_get_str(csocket.sc));
1423  return;
1424  }
1425 
1426  if (len != pos) {
1427  LOG(PACKET, "Server sent malformed crypto pubkey command: %s",
1428  socket_get_str(csocket.sc));
1430  return;
1431  }
1432 
1433  uint8_t secret_len;
1434  const unsigned char *secret = socket_crypto_create_secret(crypto,
1435  &secret_len);
1436  if (secret == NULL) {
1437  LOG(ERROR, "Failed to generate a secret");
1439  return;
1440  }
1441 
1442  packet_struct *packet = packet_new(SERVER_CMD_CRYPTO, 64, 0);
1443  packet_append_uint8(packet, CMD_CRYPTO_SECRET);
1444  packet_append_uint8(packet, secret_len);
1445  packet_append_data_len(packet, secret, secret_len);
1446  socket_send_packet(packet);
1447 }
1448 
1454 static void
1455 socket_command_crypto_secret (uint8_t *data, size_t len, size_t pos)
1456 {
1457  socket_crypto_t *crypto = socket_get_crypto(csocket.sc);
1458  SOFT_ASSERT(crypto != NULL, "crypto is NULL");
1459 
1460  if (len == pos) {
1461  LOG(PACKET, "Server sent malformed crypto secret command: %s",
1462  socket_get_str(csocket.sc));
1464  return;
1465  }
1466 
1467  uint8_t secret_len = packet_to_uint8(data, len, &pos);
1468  secret_len = MIN(secret_len, len - pos);
1469 
1470  if (!socket_crypto_set_secret(crypto, data + pos, secret_len)) {
1471  LOG(PACKET, "Server sent malformed crypto secret command: %s",
1472  socket_get_str(csocket.sc));
1474  return;
1475  }
1476 
1477  pos += secret_len;
1478 
1479  if (len != pos) {
1480  LOG(PACKET, "Server sent malformed crypto secret command: %s",
1481  socket_get_str(csocket.sc));
1483  return;
1484  }
1485 
1486  packet_struct *packet = packet_new(SERVER_CMD_CRYPTO, 8, 0);
1487  packet_append_uint8(packet, CMD_CRYPTO_DONE);
1488  socket_send_packet(packet);
1489 }
1490 
1496 static void
1497 socket_command_crypto_done (uint8_t *data, size_t len, size_t pos)
1498 {
1499  socket_crypto_t *crypto = socket_get_crypto(csocket.sc);
1500  SOFT_ASSERT(crypto != NULL, "crypto is NULL");
1501 
1502  if (len != pos) {
1503  LOG(PACKET, "Server sent malformed crypto secret command: %s",
1504  socket_get_str(csocket.sc));
1506  return;
1507  }
1508 
1509  if (!socket_crypto_set_done(crypto)) {
1510  /* Logging already done */
1512  return;
1513  }
1514 
1515  /* Begin game data communications */
1516  cpl.state = ST_START_DATA;
1517  LOG(SYSTEM, "Connection: established a secure channel with %s",
1518  socket_get_str(csocket.sc));
1519 }
1520 
1526 void
1527 socket_command_crypto (uint8_t *data, size_t len, size_t pos)
1528 {
1529  uint8_t type = packet_to_uint8(data, len, &pos);
1530  if (!socket_crypto_check_cmd(type, socket_get_crypto(csocket.sc))) {
1531  LOG(PACKET, "Received crypto command in invalid state: %u", type);
1532  return;
1533  }
1534 
1535  switch (type) {
1536  case CMD_CRYPTO_HELLO:
1537  socket_command_crypto_hello(data, len, pos);
1538  break;
1539 
1540  case CMD_CRYPTO_KEY:
1541  socket_command_crypto_key(data, len, pos);
1542  break;
1543 
1544  case CMD_CRYPTO_CURVES:
1545  socket_command_crypto_curves(data, len, pos);
1546  break;
1547 
1548  case CMD_CRYPTO_PUBKEY:
1549  socket_command_crypto_pubkey(data, len, pos);
1550  break;
1551 
1552  case CMD_CRYPTO_SECRET:
1553  socket_command_crypto_secret(data, len, pos);
1554  break;
1555 
1556  case CMD_CRYPTO_DONE:
1557  socket_command_crypto_done(data, len, pos);
1558  break;
1559 
1560  default:
1561  LOG(PACKET, "Received unknown security sub-command: %" PRIu8, type);
1562  break;
1563  }
1564 }
char map_path[HUGE_BUF]
Definition: map.h:134
uint32_t item_skill_tag
Definition: item.h:100
socket_crypto_cb_ctx_t ctx
Context from the socket crypto API.
Definition: commands.c:974
void socket_command_map(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:648
void display_mapscroll(int dx, int dy, int old_w, int old_h)
Definition: map.c:220
object * below
Definition: player.h:114
server_struct * selected_server
Definition: main.c:54
void socket_command_mapstats(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:618
float gen_sp
Definition: player.h:149
static const int socket_crypto_popup_delays[]
Definition: commands.c:1006
#define TEXT_WORD_WRAP
Definition: text.h:226
Definition: main.h:332
char glow[7]
Definition: item.h:109
int(* event_func)(struct popup_struct *popup, SDL_Event *event)
Definition: popup.h:148
float action_timer
Definition: player.h:152
int(* draw_func)(struct popup_struct *popup)
Definition: popup.h:127
void adjust_tile_stretch(void)
Definition: map.c:624
int16_t ac
Definition: player.h:60
char s_name[NAME_LEN]
Definition: item.h:60
Definition: main.h:252
int32_t hp
Definition: player.h:66
void update_map_name(const char *name)
Definition: map.c:271
void draw_info(const char *color, const char *str)
Definition: textwin.c:448
int16_t dam
Definition: player.h:84
uint8_t redraw
Definition: button.h:132
int32_t maxhp
Definition: player.h:69
uint16_t animation_id
Definition: item.h:75
struct map_anim * map_anims_add(int type, int mapx, int mapy, int sub_layer, int value)
Definition: map.c:2501
int64_t exp
Definition: player.h:78
void update_map_height_diff(uint8_t height_diff)
Definition: map.c:289
SDL_Surface * texture_surface(texture_struct *texture)
Definition: texture.c:303
uint8_t item_level
Definition: item.h:103
void sound_play_effect(const char *filename, int volume)
Definition: sound.c:367
uint32_t nrof
Definition: item.h:66
void new_player(tag_t tag, long weight, short face)
Definition: player.c:107
int button_event(button_struct *button, SDL_Event *event)
Definition: button.c:222
struct region_map * region_map
Definition: map.h:169
object * object_create(object *env, tag_t tag, int bflag)
Definition: item.c:327
float speed
Definition: player.h:87
uint8_t item_qua
Definition: item.h:94
static int popup_event(popup_struct *popup, SDL_Event *event)
Definition: commands.c:1109
int16_t face
Definition: item.h:72
int(* destroy_callback_func)(struct popup_struct *popup)
Definition: popup.h:159
static void socket_command_crypto_curves(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:1335
void * custom_data
Definition: popup.h:78
int8_t protection[CS_STAT_PROT_END-CS_STAT_PROT_START+1]
Definition: player.h:96
void socket_command_setup(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:47
void text_show(SDL_Surface *surface, font_struct *font, const char *text, int x, int y, const char *color_notation, uint64_t flags, SDL_Rect *box)
Definition: text.c:1983
void socket_command_item(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:494
static const char * popup_clipboard_copy_func(popup_struct *popup)
Definition: commands.c:1155
int server_socket_version
Definition: player.h:203
void socket_command_crypto(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:1527
static void socket_command_crypto_hello(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:1202
char target_name[MAX_BUF]
Definition: player.h:138
void setting_set_int(int cat, int setting, int64_t val)
Definition: settings.c:592
char target_hp
Definition: player.h:170
Stats stats
Definition: player.h:167
int x
Definition: popup.h:87
#define COLOR_HGOLD
Definition: text.h:319
void map_clear_cell(int x, int y)
Definition: map.c:786
void map_set_data(int x, int y, int layer, int16_t face, uint8_t quick_pos, uint8_t obj_flags, const char *name, const char *name_color, int16_t height, uint8_t probe, int16_t zoom_x, int16_t zoom_y, int16_t align, uint8_t draw_double, uint8_t alpha, int16_t rotate, uint8_t infravision, uint32_t target_object_count, uint8_t target_is_friend, uint8_t anim_speed, uint8_t anim_facing, uint8_t anim_flags, uint8_t anim_state, uint8_t priority, uint8_t secondpass, const char *glow, uint8_t glow_speed)
Definition: map.c:675
texture_struct * texture_get(texture_type_t type, const char *name)
Definition: texture.c:279
static int popup_destroy_callback(popup_struct *popup)
Definition: commands.c:1140
uint16_t flags
Definition: player.h:93
void object_transfer_inventory(object *op, object *to)
Definition: item.c:295
void socket_command_book(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:40
int seconds
Seconds since the popup appeared.
Definition: commands.c:978
uint8_t gender
Definition: player.h:212
char region_name[MAX_BUF]
Definition: map.h:125
#define TEXT_MARKUP
Definition: text.h:224
int object_animate(object *ob)
Definition: item.c:442
uint32_t tick
Definition: main.h:132
int16_t ranged_wc
Definition: player.h:102
void send_command(const char *command)
Definition: player.c:175
void socket_command_compressed(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:931
#define TEXT_ALIGN_CENTER
Definition: text.h:230
object * sack
Definition: player.h:117
const char *(* clipboard_copy_func)(struct popup_struct *popup)
Definition: popup.h:168
void update_map_region_longname(const char *region_longname)
Definition: map.c:314
double weight
Definition: item.h:69
#define COLOR_RED
Definition: text.h:295
uint8_t direction
Definition: item.h:106
static void map_play_footstep(void)
Definition: commands.c:598
void socket_command_item_update(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:567
void socket_command_item_delete(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:585
uint8_t player_sub_layer
Definition: map.h:164
uint8_t glow_speed
Definition: item.h:112
uint32_t ticks
When the popup appeared.
Definition: commands.c:977
_mapdata MapData
Definition: map.c:64
void book_load(const char *data, int len)
Definition: book.c:209
char message[MAX_BUF]
Definition: main.h:129
void socket_command_anim(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:76
client_socket_t csocket
Definition: main.c:51
struct socket_crypto_popup socket_crypto_popup_t
uint8_t apply_action
Definition: item.h:118
float weapon_speed
Definition: player.h:90
uint8_t show
Definition: widget.h:69
static void socket_crypto_cb(socket_crypto_t *crypto, const socket_crypto_cb_ctx_t *ctx)
Definition: commands.c:1163
void socket_command_image(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:101
uint8_t redraw
Definition: popup.h:114
void image_request_face(int pnum)
Definition: image.c:402
static void socket_command_crypto_pubkey(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:1398
void update_map_path(const char *map_path)
Definition: map.c:324
void socket_command_player(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:346
Client_Player cpl
Definition: client.c:50
_face_struct FaceList[MAX_FACE_TILES]
Definition: main.c:77
int posx
Definition: map.h:145
struct obj * env
Definition: item.h:54
button_struct button_ok
OK button.
Definition: commands.c:975
sprite_struct * sprite_tryload_file(char *fname, uint32_t flag, SDL_RWops *rwop)
Definition: sprite.c:110
uint16_t last_anim
Definition: item.h:84
float gen_hp
Definition: player.h:146
button_struct button_close
Close button.
Definition: commands.c:976
int32_t maxsp
Definition: player.h:75
char name[40]
Definition: player.h:173
widgetdata * cur_widget[TOTAL_SUBWIDGETS]
Definition: widget.c:75
void button_create(button_struct *button)
Definition: button.c:65
region_map_def_map_t * region_map_find_map(region_map_t *region_map, const char *map_path)
Definition: region_map.c:295
char http_url[MAX_BUF]
Definition: player.h:252
void socket_command_version(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:918
int target_code
Definition: player.h:132
static void socket_command_crypto_done(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:1497
command_buffer * command_buffer_new(size_t len, uint8_t *data)
Definition: socket.c:68
static const char *const socket_crypto_popup_texts[]
Definition: commands.c:984
void login_start(void)
Definition: login.c:281
uint8_t item_con
Definition: item.h:97
void map_update_in_building(uint8_t in_building)
Definition: map.c:337
x11_display_type SDL_display
Definition: video.c:36
char color[COLOR_BUF]
Definition: main.h:135
#define delete_object(tag)
Definition: item.h:251
#define NUM_SUB_LAYERS
Definition: map.h:80
static void socket_command_crypto_secret(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:1455
char * hostname
Definition: main.h:68
#define METASERVER_GET_PUBKEY(server)
Definition: main.h:119
int16_t wc
Definition: player.h:57
texture_struct * texture
Definition: button.h:61
bool region_has_map
Definition: map.h:128
void map_get_real_coords(int *x, int *y)
Definition: map.c:393
int16_t food
Definition: player.h:81
void socket_command_drawinfo(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:134
int y
Definition: popup.h:90
SDL_Surface * surface
Definition: button.h:46
struct msg_anim_struct msg_anim
Definition: main.c:80
void update_map_weather(const char *weather)
Definition: map.c:281
void update_map_bg_music(const char *bg_music)
Definition: sound.c:523
int disabled
Definition: button.h:111
uint16_t anim_state
Definition: item.h:81
object * object_find(tag_t tag)
Definition: item.c:139
uint32_t level
Definition: player.h:63
int32_t sp
Definition: player.h:72
void map_set_darkness(int x, int y, int sub_layer, uint8_t darkness)
Definition: map.c:813
uint32_t LastTick
Definition: main.c:57
uint16_t anim_speed
Definition: item.h:78
uint8_t itype
Definition: item.h:90
void surface_show(SDL_Surface *surface, int x, int y, SDL_Rect *srcrect, SDL_Surface *src)
Definition: sprite.c:761
x11_window_type SDL_window
Definition: video.c:40
float weight_limit
Definition: player.h:126
int posy
Definition: map.h:148
void object_remove(object *op)
Definition: item.c:174
void socket_command_target(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:153
uint8_t combat_force
Definition: player.h:264
void socket_command_control(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:956
SDL_Surface * surface
Definition: popup.h:65
uint32_t flags
Definition: item.h:87
void draw_info_format(const char *color, const char *format,...)
Definition: textwin.c:429
uint8_t combat
Definition: player.h:258
void interface_redraw(void)
Definition: interface.c:654
static int popup_draw(popup_struct *popup)
Definition: commands.c:1014
void button_show(button_struct *button, const char *text)
Definition: button.c:161
char target_color[COLOR_BUF]
Definition: player.h:135
#define TEXT_VALIGN_CENTER
Definition: text.h:246
void update_map_region_name(const char *region_name)
Definition: map.c:299
texture_struct * texture
Definition: popup.h:70
uint8_t disable_texture_drawing
Definition: popup.h:75
void socket_command_stats(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:166
static void socket_command_crypto_abort(void)
Definition: commands.c:1187
int16_t ranged_dam
Definition: player.h:99
object * ob
Definition: player.h:111
bool is_meta
Definition: main.h:106
float ranged_ws
Definition: player.h:105
void book_redraw(void)
Definition: book.c:286
static void socket_command_crypto_key(uint8_t *data, size_t len, size_t pos)
Definition: commands.c:1280
#define COLOR_WHITE
Definition: text.h:289
void object_remove_inventory(object *op)
Definition: item.c:217
void init_map_data(int xl, int yl, int px, int py)
Definition: map.c:410