connection.c
上传用户:tany51
上传日期:2013-06-12
资源大小:1397k
文件大小:21k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*
  2.  * Copyright (C) 2000,2001 Onlyer (onlyer@263.net)
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  */
  18. #include "common/setup_before.h"
  19. #include "setup.h"
  20. #include <ctype.h>
  21. #ifdef HAVE_STRING_H
  22. # include <string.h>
  23. #else
  24. # ifdef HAVE_STRINGS_H
  25. #  include <strings.h>
  26. # endif
  27. # ifdef HAVE_MEMORY_H
  28. #  include <memory.h>
  29. # endif
  30. #endif
  31. #ifdef STDC_HEADERS
  32. # include <stdlib.h>
  33. #else
  34. # ifdef HAVE_MALLOC_H
  35. #  include <malloc.h>
  36. # endif
  37. #endif
  38. #include "compat/memcpy.h"
  39. #include "compat/strdup.h"
  40. #ifdef HAVE_UNISTD_H
  41. # include <unistd.h>
  42. #endif
  43. #ifdef HAVE_SYS_TYPES_H
  44. # include <sys/types.h>
  45. #endif
  46. #ifdef HAVE_SYS_SOCKET_H
  47. # include <sys/socket.h>
  48. #endif
  49. #include "compat/psock.h"
  50. #ifdef HAVE_NETINET_IN_H
  51. # include <netinet/in.h>
  52. #endif
  53. #include "compat/netinet_in.h"
  54. #ifdef HAVE_LIMITS_H
  55. # include <limits.h>
  56. #endif
  57. #include "compat/char_bit.h"
  58. #ifdef TIME_WITH_SYS_TIME
  59. # include <time.h>
  60. # include <sys/time.h>
  61. #else
  62. # ifdef HAVE_SYS_TIME_H
  63. #  include <sys/time.h>
  64. # else
  65. #  include <time.h>
  66. # endif
  67. #endif
  68. #include "compat/psock.h"
  69. #include "compat/strcasecmp.h"
  70. #include "connection.h"
  71. #include "game.h"
  72. #include "gamequeue.h"
  73. #include "prefs.h"
  74. #include "d2gs.h"
  75. #include "net.h"
  76. #include "s2s.h"
  77. #include "handle_d2gs.h"
  78. #include "handle_d2cs.h"
  79. #include "handle_init.h"
  80. #include "handle_bnetd.h"
  81. #include "d2charfile.h"
  82. #include "common/fdwatch.h"
  83. #include "common/addr.h"
  84. #include "common/introtate.h"
  85. #include "common/network.h"
  86. #include "common/packet.h"
  87. #include "common/hashtable.h"
  88. #include "common/queue.h"
  89. #include "common/eventlog.h"
  90. #include "common/setup_after.h"
  91. static t_hashtable  * connlist_head=NULL;
  92. static t_hashtable * conn_charname_list_head=NULL;
  93. static t_list * connlist_dead=NULL;
  94. static unsigned int total_connection=0;
  95. static int conn_handle_connecting(t_connection * c);
  96. static int conn_create_packet(t_connection * c);
  97. static int conn_handle_packet(t_connection * c, t_packet * packet);
  98. static int conn_handle_read(t_connection * c);
  99. static int conn_handle_write(t_connection * c);
  100. static unsigned int conn_charname_hash(char const * charname);
  101. static unsigned int conn_sessionnum_hash(unsigned int sessionnum);
  102. static unsigned int conn_sessionnum_hash(unsigned int sessionnum)
  103. {
  104. return sessionnum;
  105. }
  106. static unsigned int conn_charname_hash(char const * charname)
  107. {
  108. unsigned int hash;
  109. unsigned int i, len, pos;
  110. unsigned int ch;
  111. ASSERT(charname,0);
  112. len=strlen(charname);
  113. for (hash=0, i=0, pos=0; i<len; i++) {
  114. if (isascii((int)charname[i])) {
  115. ch=(unsigned int)(unsigned char)tolower((int)charname[i]);
  116. } else {
  117. ch=(unsigned int)(unsigned char)charname[i];
  118. }
  119. hash ^= ROTL(ch,pos,sizeof(unsigned int) * CHAR_BIT);
  120. pos += CHAR_BIT-1;
  121. }
  122. return hash;
  123. }
  124. extern t_hashtable * d2cs_connlist(void)
  125. {
  126. return connlist_head;
  127. }
  128. extern int d2cs_connlist_create(void)
  129. {
  130. if (!(connlist_head=hashtable_create(200))) return -1;
  131. if (!(conn_charname_list_head=hashtable_create(200))) return -1;
  132. return 0;
  133. }
  134. extern int d2cs_connlist_destroy(void)
  135. {
  136. t_connection  * c;
  137. d2cs_connlist_reap();
  138. if (list_destroy(connlist_dead))
  139. eventlog(eventlog_level_error,__FUNCTION__,"error destroy conndead list");
  140. connlist_dead = NULL;
  141. BEGIN_HASHTABLE_TRAVERSE_DATA(connlist_head, c)
  142. {
  143. d2cs_conn_destroy(c);
  144. }
  145. END_HASHTABLE_TRAVERSE_DATA()
  146. if (hashtable_destroy(connlist_head)<0) {
  147. eventlog(eventlog_level_error,__FUNCTION__,"error destroy connection list");
  148. return -1;
  149. }
  150. connlist_head=NULL;
  151. if (hashtable_destroy(conn_charname_list_head)<0) {
  152. eventlog(eventlog_level_error,__FUNCTION__,"error destroy connection charname list");
  153. return -1;
  154. }
  155. conn_charname_list_head=NULL;
  156. return 0;
  157. }
  158. extern int d2cs_connlist_reap(void)
  159. {
  160. t_connection  * c;
  161. if (!connlist_dead) return 0;
  162. BEGIN_LIST_TRAVERSE_DATA(connlist_dead, c)
  163. {
  164. d2cs_conn_destroy(c);
  165. }
  166. END_LIST_TRAVERSE_DATA()
  167. return 0;
  168. }
  169. extern int conn_check_multilogin(t_connection const * c,char const * charname)
  170. {
  171. t_connection * conn;
  172. ASSERT(charname,-1);
  173. if (!prefs_check_multilogin()) return 0;
  174. if (gamelist_find_character(charname)) {
  175. return -1;
  176. }
  177. conn=d2cs_connlist_find_connection_by_charname(charname);
  178. if (conn && conn!=c) {
  179. return -1;
  180. }
  181. return 0;
  182. }
  183. extern t_connection * d2cs_connlist_find_connection_by_sessionnum(unsigned int sessionnum)
  184. {
  185. t_connection  * c;
  186. t_entry * curr;
  187. unsigned int hash;
  188. hash=conn_sessionnum_hash(sessionnum);
  189. HASHTABLE_TRAVERSE_MATCHING(connlist_head,curr,hash)
  190. {
  191. if (!(c=entry_get_data(curr))) {
  192. eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection in list");
  193. } else if (c->sessionnum==sessionnum) {
  194. hashtable_entry_release(curr);
  195. return c;
  196. }
  197. }
  198. return NULL;
  199. }
  200. extern t_connection * d2cs_connlist_find_connection_by_charname(char const * charname)
  201. {
  202. t_entry * curr;
  203. t_connection  * c;
  204. unsigned int hash;
  205. hash=conn_charname_hash(charname);
  206. HASHTABLE_TRAVERSE_MATCHING(connlist_head,curr,hash)
  207. {
  208. if (!(c=entry_get_data(curr))) {
  209. eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection in list");
  210. } else {
  211. if (!c->charname) continue;
  212. if (!strcmp_charname(c->charname,charname)) {
  213. hashtable_entry_release(curr);
  214. return c;
  215. }
  216. }
  217. }
  218. return NULL;
  219. }
  220. static int conn_create_packet(t_connection * c)
  221. {
  222. t_packet * packet;
  223. switch (c->class) {
  224. CASE(conn_class_init, packet=packet_create(packet_class_init));
  225. CASE(conn_class_d2cs, packet=packet_create(packet_class_d2cs));
  226. CASE(conn_class_d2gs, packet=packet_create(packet_class_d2gs));
  227. CASE(conn_class_bnetd, packet=packet_create(packet_class_d2cs_bnetd));
  228. default:
  229. eventlog(eventlog_level_error,__FUNCTION__,"got bad connection class %d",c->class);
  230. return -1;
  231. }
  232. if (!packet) {
  233. eventlog(eventlog_level_error,__FUNCTION__,"error create packet");
  234. return 0;
  235. }
  236. conn_push_inqueue(c,packet);
  237. packet_del_ref(packet);
  238. return 0;
  239. }
  240. static int conn_handle_connecting(t_connection * c)
  241. {
  242. int retval;
  243. if (net_check_connected(c->sock)<0) {
  244. eventlog(eventlog_level_warn,__FUNCTION__,"can not connect to %s",addr_num_to_addr_str(c->addr, c->port));
  245. return -1;
  246. }
  247. eventlog(eventlog_level_info,__FUNCTION__,"connected to %s",addr_num_to_addr_str(c->addr, c->port));
  248. c->state=conn_state_init;
  249.         /* this is a kind of hack to not update fd but updating breaks kqueue
  250.          * and the clean fix would require a cache a userland copy of the kernel
  251.  * kqueue fds, considering that it also doesnt brake anything else should do
  252.  * for the moment 
  253. fdwatch_update_fd(c->sock, fdwatch_type_read); */
  254. switch (c->class) {
  255. case conn_class_bnetd:
  256. retval=handle_bnetd_init(c);
  257. break;
  258. default:
  259. eventlog(eventlog_level_error,__FUNCTION__,"got bad connection class %d",c->class);
  260. return -1;
  261. }
  262. return retval;
  263. }
  264. static int conn_handle_packet(t_connection * c, t_packet * packet)
  265. {
  266. int retval;
  267. switch (c->class) {
  268. CASE (conn_class_init, retval=d2cs_handle_init_packet(c,packet));
  269. CASE (conn_class_d2cs, retval=d2cs_handle_d2cs_packet(c,packet));
  270. CASE (conn_class_d2gs, retval=handle_d2gs_packet(c,packet));
  271. CASE (conn_class_bnetd, retval=handle_bnetd_packet(c,packet));
  272. default:
  273. eventlog(eventlog_level_error,__FUNCTION__,"got bad connection class %d (close connection)",c->class);
  274. retval=-1;
  275. break;
  276. }
  277. return retval;
  278. }
  279. static int conn_handle_read(t_connection * c)
  280. {
  281. t_packet * packet;
  282. int retval;
  283. if (!queue_get_length((t_queue const * const *)&c->inqueue)) {
  284. if (conn_create_packet(c)<0) return -1;
  285. c->insize=0;
  286. }
  287. if (!(packet=conn_peek_inqueue(c))) return 0;
  288. switch (net_recv_packet(c->sock,packet,&c->insize)) {
  289. case -1:
  290. retval=-1;
  291. break;
  292. case 0:
  293. retval=0;
  294. break;
  295. case 1:
  296. c->insize=0;
  297. packet=conn_pull_inqueue(c);
  298. retval=conn_handle_packet(c,packet);
  299. packet_del_ref(packet);
  300. break;
  301. default:
  302. retval=0;
  303. break;
  304. }
  305. return retval;
  306. }
  307. static int conn_handle_write(t_connection * c)
  308. {
  309. t_packet * packet;
  310. int retval;
  311. if (c->state==conn_state_connecting) {
  312. return conn_handle_connecting(c);
  313. }
  314. if (!(packet=conn_peek_outqueue(c))) return 0;
  315. switch (net_send_packet(c->sock, packet, &c->outsize)) {
  316. case -1:
  317. retval=-1;
  318. break;
  319. case 0:
  320. retval=0;
  321. break;
  322. case 1:
  323. c->outsize=0;
  324. packet=conn_pull_outqueue(c);
  325. packet_del_ref(packet);
  326. retval=0;
  327. break;
  328. default:
  329. retval = -1;
  330. }
  331. return retval;
  332. }
  333. extern int conn_handle_socket(t_connection * c)
  334. {
  335. time_t now;
  336. ASSERT(c,-1);
  337. now=time(NULL);
  338. if (c->socket_flag & SOCKET_FLAG_READ) {
  339. if (conn_handle_read(c)<0) return -1;
  340. c->last_active=now;
  341. }
  342. if (c->socket_flag & SOCKET_FLAG_WRITE) {
  343. if (conn_handle_write(c)<0) return -1;
  344. c->last_active=now;
  345. }
  346. c->socket_flag=0;
  347. return 0;
  348. }
  349. extern int connlist_check_timeout(void)
  350. {
  351. t_connection * c;
  352. time_t now;
  353. now=time(NULL);
  354. BEGIN_HASHTABLE_TRAVERSE_DATA(connlist_head, c)
  355. {
  356. switch (c->class) {
  357. case conn_class_d2cs:
  358. if (prefs_get_idletime() && (now - c->last_active > prefs_get_idletime())) {
  359. eventlog(eventlog_level_info,__FUNCTION__,"client %d idled too long time, destroy it",c->sessionnum);
  360. d2cs_conn_set_state(c,conn_state_destroy);
  361. }
  362. break;
  363. case conn_class_d2gs:
  364. if (prefs_get_s2s_idletime() && now - c->last_active > prefs_get_s2s_idletime()) {
  365. eventlog(eventlog_level_info,__FUNCTION__,"server %d timed out",c->sessionnum);
  366. d2cs_conn_set_state(c,conn_state_destroy);
  367. }
  368. break;
  369. case conn_class_bnetd:
  370. break;
  371. default:
  372. break;
  373. }
  374. }
  375. END_HASHTABLE_TRAVERSE_DATA()
  376. return 0;
  377. }
  378. extern t_connection * d2cs_conn_create(int sock, unsigned int local_addr, unsigned short local_port, 
  379. unsigned int addr, unsigned short port)
  380. {
  381. static unsigned int sessionnum=1;
  382. t_connection * c;
  383. if (sock<0) {
  384. eventlog(eventlog_level_error,__FUNCTION__,"got bad socket");
  385. return NULL;
  386. }
  387. if (!(c=malloc(sizeof(t_connection)))) {
  388. eventlog(eventlog_level_error,__FUNCTION__,"error allocate connection");
  389. return NULL;
  390. }
  391. c->charname=NULL;
  392. c->account=NULL;
  393. c->sock=sock;
  394. c->socket_flag=0;
  395. c->local_addr=local_addr;
  396. c->local_port=local_port;
  397. c->addr=addr;
  398. c->port=port;
  399. c->class=conn_class_init;
  400. c->state=conn_state_init;
  401. c->sessionnum=sessionnum++;
  402. c->outqueue=NULL;
  403. c->inqueue=NULL;
  404. c->outsize=0;
  405. c->outsizep=0;
  406. c->insize=0;
  407. c->charinfo=NULL;
  408. c->d2gs_id=0;
  409. c->gamequeue=NULL;
  410. c->last_active=time(NULL);
  411. c->sessionnum_hash=conn_sessionnum_hash(c->sessionnum);
  412. c->bnetd_sessionnum=0;
  413. c->charname_hash=0;
  414. if (hashtable_insert_data(connlist_head, c, c->sessionnum_hash)<0) {
  415. free(c);
  416. eventlog(eventlog_level_error,__FUNCTION__,"error add connection to list");
  417. return NULL;
  418. }
  419. total_connection++;
  420. eventlog(eventlog_level_info,__FUNCTION__,"created session=%d socket=%d (%d current connections)", c->sessionnum, sock, total_connection);
  421. return c;
  422. }
  423. extern int d2cs_conn_destroy(t_connection * c)
  424. {
  425. ASSERT(c,-1);
  426. if (c->state==conn_state_destroying) return 0;
  427. if (hashtable_remove_data(connlist_head,c,c->sessionnum_hash)<0) {
  428. eventlog(eventlog_level_error,__FUNCTION__,"error remove connection from list");
  429. return -1;
  430. }
  431. c->state=conn_state_destroying;
  432. if (c->d2gs_id && c->class==conn_class_d2gs) {
  433. d2gs_deactive(d2gslist_find_gs(c->d2gs_id),c);
  434. }
  435. if (c->class==conn_class_bnetd) {
  436. s2s_destroy(c);
  437. }
  438. if (c->gamequeue) {
  439. gq_destroy(c->gamequeue);
  440. }
  441. if (c->account) free((void *)c->account);
  442. if (c->charinfo) free((void *)c->charinfo);
  443. if (c->charname) d2cs_conn_set_charname(c,NULL);
  444. queue_clear(&c->inqueue);
  445. queue_clear(&c->outqueue);
  446. if (connlist_dead) list_remove_data(connlist_dead, c);
  447. fdwatch_del_fd(c->sock);
  448. psock_shutdown(c->sock,PSOCK_SHUT_RDWR);
  449. psock_close(c->sock);
  450. total_connection--;
  451. eventlog(eventlog_level_info,__FUNCTION__,"[%d] closed connection %d (%d left)",c->sock,c->sessionnum,total_connection);
  452. free(c);
  453. return 0;
  454. }
  455. extern int d2cs_conn_get_socket(t_connection const * c)
  456. {
  457. ASSERT(c,-1);
  458. return c->sock;
  459. }
  460. extern t_conn_state d2cs_conn_get_state(t_connection const * c)
  461. {
  462. ASSERT(c,conn_state_none);
  463. return c->state;
  464. }
  465. extern int d2cs_conn_set_state(t_connection * c, t_conn_state state)
  466. {
  467. ASSERT(c,-1);
  468. /* special case for destroying connections, add them to connlist_dead list */
  469. if (state == conn_state_destroy && c->state != conn_state_destroy) {
  470.     if (!connlist_dead && !(connlist_dead = list_create())) {
  471. eventlog(eventlog_level_error, __FUNCTION__, "could not initilize connlist_dead list");
  472. return -1;
  473.     }
  474.     list_append_data(connlist_dead, c);
  475. } else if (state != conn_state_destroy && c->state == conn_state_destroy) {
  476.     if (list_remove_data(connlist_dead, c)) {
  477. eventlog(eventlog_level_error, __FUNCTION__, "could not remove dead connection");
  478. return -1;
  479.     }
  480. }
  481. c->state=state;
  482. return 0;
  483. }
  484. extern t_conn_class d2cs_conn_get_class(t_connection const * c)
  485. {
  486. ASSERT(c,conn_class_none);
  487. return c->class;
  488. }
  489. extern int d2cs_conn_set_class(t_connection * c, t_conn_class class)
  490. {
  491. ASSERT(c,-1);
  492. c->class=class;
  493. return 0;
  494. }
  495. extern t_queue * * d2cs_conn_get_in_queue(t_connection const * c)
  496. {
  497. ASSERT(c,NULL);
  498. return (t_queue * *)&c->inqueue;
  499. }
  500. extern unsigned int d2cs_conn_get_out_size(t_connection const * c)
  501. {
  502. ASSERT(c,0);
  503. return c->outsize;
  504. }
  505. extern t_queue * * d2cs_conn_get_out_queue(t_connection const * c)
  506. {
  507. ASSERT(c,NULL);
  508. return (t_queue * *)&c->outqueue;
  509. }
  510. extern unsigned int d2cs_conn_get_in_size(t_connection const * c)
  511. {
  512. ASSERT(c,0);
  513. return c->insize;
  514. }
  515. extern int conn_push_outqueue(t_connection * c, t_packet * packet)
  516. {
  517.     if (!c)
  518.     {
  519.         eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection");
  520.         return -1;
  521.     }
  522.     if (!packet)
  523.     {
  524.         eventlog(eventlog_level_error, __FUNCTION__, "got NULL packet");
  525.         return -1;
  526.     }
  527.     queue_push_packet((t_queue * *)&c->outqueue, packet);
  528.     if (!c->outsizep++) fdwatch_update_fd(c->sock, fdwatch_type_read | fdwatch_type_write);
  529.     return 0;
  530. }
  531. extern t_packet * conn_peek_outqueue(t_connection * c)
  532. {
  533.     if (!c)
  534.     {
  535.         eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection");
  536.         return NULL;
  537.     }
  538.     return queue_peek_packet((t_queue const * const *)&c->outqueue);
  539. }
  540. extern t_packet * conn_pull_outqueue(t_connection * c)
  541. {
  542.     if (!c)
  543.     {
  544.         eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection");
  545.         return NULL;
  546.     }
  547.     if (c->outsizep) {
  548.         if (!(--c->outsizep)) fdwatch_update_fd(c->sock, fdwatch_type_read);
  549.         return queue_pull_packet((t_queue * *)&c->outqueue);
  550.     }
  551.     return NULL;
  552. }
  553. extern int conn_push_inqueue(t_connection * c, t_packet * packet)
  554. {
  555.     if (!c)
  556.     {
  557.         eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection");
  558.         return -1;
  559.     }
  560.     if (!packet)
  561.     {
  562.         eventlog(eventlog_level_error, __FUNCTION__, "got NULL packet");
  563.         return -1;
  564.     }
  565.     queue_push_packet((t_queue * *)&c->inqueue, packet);
  566.     return 0;
  567. }
  568. extern t_packet * conn_peek_inqueue(t_connection * c)
  569. {
  570.     if (!c)
  571.     {
  572.         eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection");
  573.         return NULL;
  574.     }
  575.     return queue_peek_packet((t_queue const * const *)&c->inqueue);
  576. }
  577. extern t_packet * conn_pull_inqueue(t_connection * c)
  578. {
  579.     if (!c)
  580.     {
  581.         eventlog(eventlog_level_error, __FUNCTION__, "got NULL connection");
  582.         return NULL;
  583.     }
  584.     return queue_pull_packet((t_queue * *)&c->inqueue);
  585. }
  586. extern int conn_add_socket_flag(t_connection * c, unsigned int flag)
  587. {
  588. ASSERT(c,-1);
  589. c->socket_flag |= flag;
  590. return 0;
  591. }
  592. extern int conn_process_packet(t_connection * c, t_packet * packet, t_packet_handle_table * table,
  593. unsigned int table_size)
  594. {
  595.         unsigned int     type;
  596.         unsigned int     size;
  597. ASSERT(c,-1);
  598.         ASSERT(packet,-1);
  599. ASSERT(table,-1);
  600.         type=packet_get_type(packet);
  601.         size=packet_get_size(packet);
  602.         if (type >= table_size || !table[type].size) {
  603. eventlog(eventlog_level_error,__FUNCTION__,"got bad packet type %d (class %d)",type,packet_get_class(packet));
  604. return -1;
  605. }
  606. if (size < table[type].size) {
  607. eventlog(eventlog_level_error,__FUNCTION__,"got bad packet size %d (type %d class %d)",size,type,packet_get_class(packet));
  608. return -1;
  609. }
  610. if (!(c->state & table[type].state)) {
  611. eventlog(eventlog_level_error,__FUNCTION__,"connection %d state mismatch for packet type %d (class %d)",c->sessionnum,
  612. type,packet_get_class(packet));
  613. return -1;
  614. }
  615. if (!table[type].handler) {
  616. eventlog(eventlog_level_error,__FUNCTION__,"missing handler for packet type %d (class %d)",type,packet_get_class(packet));
  617. return -1;
  618. }
  619. return table[type].handler(c,packet);
  620. }
  621. extern int d2cs_conn_set_account(t_connection * c, char const * account)
  622. {
  623. char const * temp;
  624. ASSERT(c,-1);
  625. if (!account) {
  626. if (c->account) free((void *)c->account);
  627. c->account=NULL;
  628. }
  629. if (!(temp=strdup(account))) {
  630. eventlog(eventlog_level_error,__FUNCTION__,"error allocate temp for account");
  631. return -1;
  632. }
  633. if (c->account) free((void *)c->account);
  634. c->account=temp;
  635. return 0;
  636. }
  637. extern char const * d2cs_conn_get_account(t_connection const * c)
  638. {
  639. ASSERT(c,NULL);
  640. return c->account;
  641. }
  642. extern int d2cs_conn_set_charname(t_connection * c, char const * charname)
  643. {
  644. char const * temp;
  645. ASSERT(c,-1);
  646. temp=NULL;
  647. if (charname && !(temp=strdup(charname))) {
  648. eventlog(eventlog_level_error,__FUNCTION__,"error allocate temp for charname");
  649. return -1;
  650. }
  651. if (c->charname) {
  652. if (hashtable_remove_data(conn_charname_list_head,c,c->charname_hash) <0) {
  653. eventlog(eventlog_level_error,__FUNCTION__,"error remove charname %s from list",charname);
  654. if (temp) free((void *)temp);
  655. return -1;
  656. }
  657. hashtable_purge(conn_charname_list_head);
  658. free((void *)c->charname);
  659. }
  660. if (charname) {
  661. c->charname=temp;
  662. c->charname_hash=conn_charname_hash(charname);
  663. if (hashtable_insert_data(conn_charname_list_head,c,c->charname_hash) <0) {
  664. eventlog(eventlog_level_error,__FUNCTION__,"error insert charname %s to list",charname);
  665. free((void *)c->charname);
  666. c->charname=NULL;
  667. return -1;
  668. }
  669. } else {
  670. c->charname=NULL;
  671. c->charname_hash=0;
  672. }
  673. return 0;
  674. }
  675. extern char const * d2cs_conn_get_charname(t_connection const * c)
  676. {
  677. ASSERT(c,NULL);
  678. return c->charname;
  679. }
  680. extern unsigned int d2cs_conn_get_sessionnum(t_connection const * c)
  681. {
  682. ASSERT(c,0);
  683. return c->sessionnum;
  684. }
  685. extern unsigned int conn_get_charinfo_ladder(t_connection const * c)
  686. {
  687. ASSERT(c,0);
  688. return d2charinfo_get_ladder(c->charinfo);
  689. }
  690. extern unsigned int conn_get_charinfo_expansion(t_connection const * c)
  691. {
  692. ASSERT(c,0);
  693. return d2charinfo_get_expansion(c->charinfo);
  694. }
  695. extern unsigned int conn_get_charinfo_hardcore(t_connection const * c)
  696. {
  697. ASSERT(c,0);
  698. return d2charinfo_get_hardcore(c->charinfo);
  699. }
  700. extern unsigned int conn_get_charinfo_dead(t_connection const * c)
  701. {
  702. ASSERT(c,0);
  703. return d2charinfo_get_dead(c->charinfo);
  704. }
  705. extern unsigned int conn_get_charinfo_difficulty(t_connection const * c)
  706. {
  707. ASSERT(c,0);
  708. return d2charinfo_get_difficulty(c->charinfo);
  709. }
  710. extern unsigned int conn_get_charinfo_level(t_connection const * c)
  711. {
  712. ASSERT(c,0);
  713. return d2charinfo_get_level(c->charinfo);
  714. }
  715. extern unsigned int conn_get_charinfo_class(t_connection const * c)
  716. {
  717. ASSERT(c,0);
  718. return d2charinfo_get_class(c->charinfo);
  719. }
  720. extern int conn_set_charinfo(t_connection * c, t_d2charinfo_summary const * charinfo)
  721. {
  722. t_d2charinfo_summary * temp;
  723. ASSERT(c,-1);
  724. if (!charinfo) {
  725. if (c->charinfo) free((void *)c->charinfo);
  726. c->charinfo=NULL;
  727. return 0;
  728. }
  729. if (!(temp=malloc(sizeof(t_d2charinfo_summary)))) {
  730. eventlog(eventlog_level_error,__FUNCTION__,"error allocate temp for charinfo");
  731. return -1;
  732. }
  733. if (c->charinfo) free((void *)c->charinfo);
  734. memcpy(temp,charinfo,sizeof(t_d2charinfo_summary));
  735. c->charinfo=temp;
  736. return 0;
  737. }
  738. extern int conn_set_d2gs_id(t_connection * c, unsigned int d2gs_id)
  739. {
  740. ASSERT(c,-1)
  741. c->d2gs_id=d2gs_id;
  742. return 0;
  743. }
  744. extern unsigned int conn_get_d2gs_id(t_connection const * c)
  745. {
  746. ASSERT(c,0)
  747. return c->d2gs_id;
  748. }
  749. extern unsigned int d2cs_conn_get_addr(t_connection const * c)
  750. {
  751. ASSERT(c,0);
  752. return c->addr;
  753. }
  754. extern unsigned short d2cs_conn_get_port(t_connection const * c)
  755. {
  756. ASSERT(c,0);
  757. return c->port;
  758. }
  759. extern t_gq * conn_get_gamequeue(t_connection const * c)
  760. {
  761. ASSERT(c,NULL);
  762. return c->gamequeue;
  763. }
  764. extern int conn_set_gamequeue(t_connection * c, t_gq * gq)
  765. {
  766. ASSERT(c,-1);
  767. c->gamequeue=gq;
  768. return 0;
  769. }
  770. extern int conn_set_bnetd_sessionnum(t_connection * c, unsigned int sessionnum)
  771. {
  772. ASSERT(c,-1);
  773. c->bnetd_sessionnum=sessionnum;
  774. return 0;
  775. }
  776. extern unsigned int conn_get_bnetd_sessionnum(t_connection const * c)
  777. {
  778. ASSERT(c,-1);
  779. return c->bnetd_sessionnum;
  780. }