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

MySQL数据库

开发平台:

Visual C++

  1. /*
  2.  * Copyright (C) 2001 sousou (liupeng.cs@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. #ifdef HAVE_STDDEF_H
  21. # include <stddef.h>
  22. #else
  23. # ifndef NULL
  24. #  define NULL ((void *)0)
  25. # endif
  26. #endif
  27. #include <stdio.h>
  28. #ifdef STDC_HEADERS
  29. # include <stdlib.h>
  30. #else
  31. # ifdef HAVE_MALLOC_H
  32. #  include <malloc.h>
  33. # endif
  34. #endif
  35. #ifdef HAVE_UNISTD_H
  36. # include <unistd.h>
  37. #endif
  38. #ifdef HAVE_FCNTL_H
  39. # include <fcntl.h>
  40. #else
  41. # ifdef HAVE_SYS_FILE_H
  42. #  include <sys/file.h>
  43. # endif
  44. #endif
  45. #ifdef HAVE_STRING_H
  46. # include <string.h>
  47. #else
  48. # ifdef HAVE_STRINGS_H
  49. #  include <strings.h>
  50. # endif
  51. # ifdef HAVE_MEMORY_H
  52. #  include <memory.h>
  53. # endif
  54. #endif
  55. #include "compat/memset.h"
  56. #include <errno.h>
  57. #include "compat/strerror.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. #ifdef HAVE_SYS_TYPES_H
  69. # include <sys/types.h>
  70. #endif
  71. #ifdef HAVE_SYS_SOCKET_H
  72. # include <sys/socket.h>
  73. #endif
  74. #include "compat/socket.h"
  75. #ifdef HAVE_SYS_PARAM_H
  76. # include <sys/param.h>
  77. #endif
  78. #ifdef HAVE_NETINET_IN_H
  79. # include <netinet/in.h>
  80. #endif
  81. #include "compat/netinet_in.h"
  82. #ifdef HAVE_ARPA_INET_H
  83. # include <arpa/inet.h>
  84. #endif
  85. #include "compat/inet_ntoa.h"
  86. #include "compat/psock.h"
  87. #include "dbserver.h"
  88. #include "charlock.h"
  89. #include "d2ladder.h"
  90. #include "dbspacket.h"
  91. #include "prefs.h"
  92. #include "handle_signal.h"
  93. #include "common/list.h"
  94. #include "common/eventlog.h"
  95. #ifdef WIN32
  96. # include <conio.h> /* for kbhit() and getch() */
  97. #endif
  98. #include "common/addr.h"
  99. #include "common/setup_after.h"
  100. static int dbs_packet_gs_id = 0;
  101. static t_preset_d2gsid *preset_d2gsid_head = NULL;
  102. t_list * dbs_server_connection_list = NULL;
  103. int dbs_server_listen_socket=-1;
  104. extern int g_ServiceStatus;
  105. /* dbs_server_main
  106.  * The module's driver function -- we just call other functions and
  107.  * interpret their results.
  108.  */
  109. static int dbs_handle_timed_events(void);
  110. static void dbs_on_exit(void);
  111. int dbs_server_init(void);
  112. void dbs_server_loop(int ListeningSocket);
  113. int dbs_server_setup_fdsets(fd_set * pReadFDs, fd_set * pWriteFDs,
  114.         fd_set * pExceptFDs, int ListeningSocket ) ;
  115. BOOL dbs_server_read_data(t_d2dbs_connection* conn) ;
  116. BOOL dbs_server_write_data(t_d2dbs_connection* conn) ;
  117. int dbs_server_list_add_socket(int sd, unsigned int ipaddr);
  118. static int setsockopt_keepalive(int sock);
  119. static unsigned int get_preset_d2gsid(unsigned int ipaddr);
  120. int dbs_server_main(void)
  121. {
  122. eventlog(eventlog_level_info,__FUNCTION__,"establishing the listener...");
  123. dbs_server_listen_socket = dbs_server_init();
  124. if (dbs_server_listen_socket<0) {
  125. eventlog(eventlog_level_error,__FUNCTION__,"dbs_server_init error ");
  126. return 3;
  127. }
  128. eventlog(eventlog_level_info,__FUNCTION__,"waiting for connections...");
  129. dbs_server_loop(dbs_server_listen_socket);
  130. dbs_on_exit();
  131. return 0;
  132. }
  133. /* dbs_server_init
  134.  * Sets up a listener on the given interface and port, returning the
  135.  * listening socket if successful; if not, returns -1.
  136.  */
  137. /* FIXME: No it doesn't!  pcAddress is not ever referenced in this
  138.  * function.
  139.  * CreepLord: Fixed much better way (will accept dns hostnames)
  140.  */
  141. int dbs_server_init(void)
  142. {
  143. int sd;
  144. struct sockaddr_in sinInterface;
  145. int val;
  146. t_addr * servaddr;
  147. if (! (dbs_server_connection_list=list_create()))
  148. {
  149. eventlog(eventlog_level_error,__FUNCTION__,"list_create() failed");
  150. return -1;
  151. }
  152. if (d2dbs_d2ladder_init()==-1)
  153. {
  154. eventlog(eventlog_level_error,__FUNCTION__,"d2ladder_init() failed");
  155. return -1;
  156. }
  157. if (cl_init(DEFAULT_HASHTBL_LEN, DEFAULT_GS_MAX)==-1)
  158. {
  159. eventlog(eventlog_level_error,__FUNCTION__,"cl_init() failed");
  160. return -1;
  161. }
  162. if (psock_init()<0)
  163. {
  164. eventlog(eventlog_level_error,__FUNCTION__,"psock_init() failed");
  165. return -1;
  166. }
  167. sd = psock_socket(PSOCK_PF_INET, PSOCK_SOCK_STREAM, PSOCK_IPPROTO_TCP);
  168. if (sd==-1)
  169. {
  170. eventlog(eventlog_level_error,__FUNCTION__,"psock_socket() failed : %s",strerror(psock_errno()));
  171. return -1;
  172. }
  173. val = 1;
  174. if (psock_setsockopt(sd, PSOCK_SOL_SOCKET, PSOCK_SO_REUSEADDR, &val, sizeof(val)) < 0)
  175. {
  176. eventlog(eventlog_level_error,__FUNCTION__,"psock_setsockopt() failed : %s",strerror(psock_errno()));
  177. }
  178.         if (!(servaddr=addr_create_str(d2dbs_prefs_get_servaddrs(),INADDR_ANY,DEFAULT_LISTEN_PORT)))
  179. {
  180. eventlog(eventlog_level_error,__FUNCTION__,"could not get servaddr");
  181. return -1;
  182. }
  183. sinInterface.sin_family = PSOCK_AF_INET;
  184. sinInterface.sin_addr.s_addr = htonl(addr_get_ip(servaddr));
  185. sinInterface.sin_port = htons(addr_get_port(servaddr));
  186. if (psock_bind(sd, (struct sockaddr*)&sinInterface, (psock_t_socklen)sizeof(struct sockaddr_in)) < 0)
  187. {
  188. eventlog(eventlog_level_error,__FUNCTION__,"psock_bind() failed : %s",strerror(psock_errno()));
  189. return -1;
  190. }
  191. if (psock_listen(sd, LISTEN_QUEUE) < 0)
  192. {
  193. eventlog(eventlog_level_error,__FUNCTION__,"psock_listen() failed : %s",strerror(psock_errno()));
  194. return -1;
  195. }
  196. addr_destroy(servaddr);
  197. return sd;
  198. }
  199. /* dbs_server_setup_fdsets
  200.  * Set up the three FD sets used with select() with the sockets in the
  201.  * connection list.  Also add one for the listener socket, if we have
  202.  * one.
  203.  */
  204. int dbs_server_setup_fdsets(t_psock_fd_set * pReadFDs, t_psock_fd_set * pWriteFDs, t_psock_fd_set * pExceptFDs, int lsocket)
  205. {
  206. t_elem const * elem;
  207. t_d2dbs_connection* it;
  208. int highest_fd;
  209. PSOCK_FD_ZERO(pReadFDs);
  210. PSOCK_FD_ZERO(pWriteFDs);
  211. PSOCK_FD_ZERO(pExceptFDs); /* FIXME: don't check these... remove this code */
  212. /* Add the listener socket to the read and except FD sets, if there is one. */
  213. if (lsocket >= 0) {
  214. PSOCK_FD_SET(lsocket, pReadFDs);
  215. PSOCK_FD_SET(lsocket, pExceptFDs);
  216. }
  217. highest_fd=lsocket;
  218. LIST_TRAVERSE_CONST(dbs_server_connection_list,elem)
  219. {
  220. if (!(it=elem_get_data(elem))) continue;
  221. if (it->nCharsInReadBuffer < (kBufferSize-kMaxPacketLength)) {
  222. /* There's space in the read buffer, so pay attention to incoming data. */
  223. PSOCK_FD_SET(it->sd, pReadFDs);
  224. }
  225. if (it->nCharsInWriteBuffer > 0) {
  226. PSOCK_FD_SET(it->sd, pWriteFDs);
  227. }
  228. PSOCK_FD_SET(it->sd, pExceptFDs);
  229. if (highest_fd < it->sd) highest_fd=it->sd;
  230. }
  231. return highest_fd;
  232. }
  233. /* dbs_server_read_data
  234.  * Data came in on a client socket, so read it into the buffer.  Returns
  235.  * false on failure, or when the client closes its half of the
  236.  * connection.  (EAGAIN doesn't count as a failure.)
  237.  */
  238. BOOL dbs_server_read_data(t_d2dbs_connection* conn)
  239. {
  240. int nBytes;
  241. nBytes = psock_recv(conn->sd,
  242.         conn->ReadBuf + conn->nCharsInReadBuffer,
  243. kBufferSize - conn->nCharsInReadBuffer, 0);
  244. if (nBytes == 0) {
  245. eventlog(eventlog_level_info,__FUNCTION__,"Socket %d was closed by the client. Shutting down.",conn->sd);
  246. return FALSE;
  247. } else if (nBytes < 0) {
  248. int  err;
  249. psock_t_socklen errlen;
  250. err = 0;
  251. errlen = sizeof(err);
  252. if (psock_getsockopt(conn->sd, PSOCK_SOL_SOCKET, PSOCK_SO_ERROR, &err, &errlen)<0)
  253. return TRUE;
  254. if (errlen==0 || err==PSOCK_EAGAIN) {
  255. return TRUE;
  256. } else {
  257. eventlog(eventlog_level_error,__FUNCTION__,"psock_recv() failed : %s",strerror(err));
  258. return FALSE;
  259. }
  260. }
  261. conn->nCharsInReadBuffer += nBytes;
  262. return TRUE;
  263. }
  264. /* dbs_server_write_data
  265.  * The connection is writable, so send any pending data.  Returns
  266.  * false on failure.  (EAGAIN doesn't count as a failure.)
  267.  */
  268. BOOL dbs_server_write_data(t_d2dbs_connection* conn)
  269. {
  270. unsigned int sendlen;
  271. int nBytes ;
  272. if (conn->nCharsInWriteBuffer>kMaxPacketLength) sendlen=kMaxPacketLength;
  273. else sendlen=conn->nCharsInWriteBuffer;
  274. nBytes = psock_send(conn->sd, conn->WriteBuf, sendlen, 0);
  275. if (nBytes < 0) {
  276.         int  err;
  277. psock_t_socklen errlen;
  278. err = 0;
  279. errlen = sizeof(err);
  280. if (psock_getsockopt(conn->sd, PSOCK_SOL_SOCKET, PSOCK_SO_ERROR, &err, &errlen)<0)
  281. return TRUE;
  282. if (errlen==0 || err==PSOCK_EAGAIN) {
  283. return TRUE;
  284. } else {
  285. eventlog(eventlog_level_error,__FUNCTION__,"psock_send() failed : %s",strerror(err));
  286. return FALSE;
  287. }
  288. }
  289. if (nBytes == conn->nCharsInWriteBuffer) {
  290. conn->nCharsInWriteBuffer = 0;
  291. } else {
  292. conn->nCharsInWriteBuffer -= nBytes;
  293. memmove(conn->WriteBuf, conn->WriteBuf + nBytes, conn->nCharsInWriteBuffer);
  294. }
  295. return TRUE;
  296. }
  297. int dbs_server_list_add_socket(int sd, unsigned int ipaddr)
  298. {
  299. t_d2dbs_connection *it;
  300. struct in_addr in;
  301. if (!(it=malloc(sizeof(t_d2dbs_connection)))) {
  302. eventlog(eventlog_level_error,__FUNCTION__,"malloc() failed");
  303. return 0;
  304. }
  305. memset(it, 0, sizeof(t_d2dbs_connection));
  306. it->sd=sd;
  307. it->ipaddr=ipaddr;
  308. it->major=0;
  309. it->minor=0;
  310. it->type=0;
  311. it->stats=0;
  312. it->verified=0;
  313. it->serverid=get_preset_d2gsid(ipaddr);
  314. it->last_active=time(NULL);
  315. it->nCharsInReadBuffer=0;
  316. it->nCharsInWriteBuffer=0;
  317. list_append_data(dbs_server_connection_list,it);
  318. in.s_addr = htonl(ipaddr);
  319. strncpy(it->serverip, inet_ntoa(in), sizeof(it->serverip)-1);
  320. return 1;
  321. }
  322. static int dbs_handle_timed_events(void)
  323. {
  324. static time_t prev_ladder_save_time=0;
  325. static time_t prev_keepalive_save_time=0;
  326. static  time_t prev_timeout_checktime=0;
  327. time_t now;
  328. now=time(NULL);
  329. if (now-prev_ladder_save_time>(signed)prefs_get_laddersave_interval()) {
  330. d2ladder_saveladder();
  331. prev_ladder_save_time=now;
  332. }
  333. if (now-prev_keepalive_save_time>(signed)prefs_get_keepalive_interval()) {
  334. dbs_keepalive();
  335. prev_keepalive_save_time=now;
  336. }
  337. if (now-prev_timeout_checktime>(signed)d2dbs_prefs_get_timeout_checkinterval()) {
  338. dbs_check_timeout();
  339. prev_timeout_checktime=now;
  340. }
  341. return 0;
  342. }
  343. void dbs_server_loop(int lsocket)
  344. {
  345. struct sockaddr_in sinRemote;
  346. int sd ;
  347. fd_set ReadFDs, WriteFDs, ExceptFDs;
  348. t_elem * elem;
  349. t_d2dbs_connection* it;
  350. BOOL bOK ;
  351. const char* pcErrorType ;
  352. struct timeval         tv;
  353. int highest_fd;
  354. int listpurgecount;
  355. psock_t_socklen nAddrSize = sizeof(sinRemote);
  356. listpurgecount=0;
  357. while (1) {
  358. #ifdef WIN32
  359. if (kbhit() && getch()=='q')
  360.     d2dbs_signal_quit_wrapper();
  361. if (g_ServiceStatus == 0) d2dbs_signal_quit_wrapper();
  362. while (g_ServiceStatus == 2) Sleep(1000);
  363. #endif
  364. if (d2dbs_handle_signal()<0) break;
  365. dbs_handle_timed_events();
  366. highest_fd=dbs_server_setup_fdsets(&ReadFDs, &WriteFDs, &ExceptFDs, lsocket);
  367. tv.tv_sec  = 0;
  368. tv.tv_usec = SELECT_TIME_OUT;
  369. switch (psock_select(highest_fd+1, &ReadFDs, &WriteFDs, &ExceptFDs, &tv) ) {
  370. case -1:
  371. eventlog(eventlog_level_error,__FUNCTION__,"psock_select() failed : %s",strerror(psock_errno()));
  372. continue;
  373. case 0:
  374. continue;
  375. default:
  376. break;
  377. }
  378. if (PSOCK_FD_ISSET(lsocket, &ReadFDs)) {
  379. sd = psock_accept(lsocket, (struct sockaddr*)&sinRemote, &nAddrSize);
  380. if (sd == -1) {
  381. eventlog(eventlog_level_error,__FUNCTION__,"psock_accept() failed : %s",strerror(psock_errno()));
  382. return;
  383. }
  384. eventlog(eventlog_level_info,__FUNCTION__,"accepted connection from %s:%d , socket %d .",
  385. inet_ntoa(sinRemote.sin_addr) , ntohs(sinRemote.sin_port), sd);
  386. eventlog_step(prefs_get_logfile_gs(),eventlog_level_info,__FUNCTION__,"accepted connection from %s:%d , socket %d .",
  387. inet_ntoa(sinRemote.sin_addr) , ntohs(sinRemote.sin_port), sd);
  388. setsockopt_keepalive(sd);
  389. dbs_server_list_add_socket(sd, ntohl(sinRemote.sin_addr.s_addr));
  390. if (psock_ctl(sd,PSOCK_NONBLOCK)<0) {
  391. eventlog(eventlog_level_error,__FUNCTION__,"could not set TCP socket [%d] to non-blocking mode (closing connection) (psock_ctl: %s)", sd,strerror(psock_errno()));
  392. psock_close(sd);
  393. }
  394. } else if (PSOCK_FD_ISSET(lsocket, &ExceptFDs)) {
  395. eventlog(eventlog_level_error,__FUNCTION__,"exception on listening socket");
  396. /* FIXME: exceptions are not errors with TCP, they are out-of-band data */
  397. return;
  398. }
  399. LIST_TRAVERSE(dbs_server_connection_list,elem)
  400. {
  401. bOK = TRUE;
  402. pcErrorType = 0;
  403. if (!(it=elem_get_data(elem))) continue;
  404. if (PSOCK_FD_ISSET(it->sd, &ExceptFDs)) {
  405. bOK = FALSE;
  406. pcErrorType = "General socket error"; /* FIXME: no no no no no */
  407. PSOCK_FD_CLR(it->sd, &ExceptFDs);
  408. } else {
  409. if (PSOCK_FD_ISSET(it->sd, &ReadFDs)) {
  410. bOK = dbs_server_read_data(it);
  411. pcErrorType = "Read error";
  412. PSOCK_FD_CLR(it->sd, &ReadFDs);
  413. }
  414. if (PSOCK_FD_ISSET(it->sd, &WriteFDs)) {
  415. bOK = dbs_server_write_data(it);
  416. pcErrorType = "Write error";
  417. PSOCK_FD_CLR(it->sd, &WriteFDs);
  418. }
  419. }
  420. if (!bOK) {
  421. int err;
  422. psock_t_socklen errlen;
  423. err = 0;
  424. errlen = sizeof(err);
  425. if (psock_getsockopt(it->sd, PSOCK_SOL_SOCKET, PSOCK_SO_ERROR, &err, &errlen)==0) {
  426. if (errlen && err!=0) {
  427. eventlog(eventlog_level_error,__FUNCTION__,"data socket error : %s",strerror(err));
  428. }
  429. }
  430. dbs_server_shutdown_connection(it);
  431. list_remove_elem(dbs_server_connection_list,elem);
  432. listpurgecount++;
  433. } else {
  434. if (dbs_packet_handle(it)==-1) {
  435. eventlog(eventlog_level_error,__FUNCTION__,"dbs_packet_handle() failed");
  436. dbs_server_shutdown_connection(it);
  437. list_remove_elem(dbs_server_connection_list,elem);
  438. listpurgecount++;
  439. }
  440. }
  441. }
  442. if (listpurgecount>100) {
  443. list_purge(dbs_server_connection_list);
  444. listpurgecount=0;
  445. }
  446. }
  447. }
  448. static void dbs_on_exit(void)
  449. {
  450. t_elem * elem;
  451. t_d2dbs_connection * it;
  452. if (dbs_server_listen_socket>=0)
  453. psock_close(dbs_server_listen_socket);
  454. dbs_server_listen_socket=-1;
  455. LIST_TRAVERSE(dbs_server_connection_list,elem)
  456. {
  457. if (!(it=elem_get_data(elem))) continue;
  458. dbs_server_shutdown_connection(it);
  459. list_remove_elem(dbs_server_connection_list,elem);
  460. }
  461. cl_destroy();
  462. d2dbs_d2ladder_destroy();
  463. list_destroy(dbs_server_connection_list);
  464. if (preset_d2gsid_head)
  465. {
  466. t_preset_d2gsid * curr;
  467. t_preset_d2gsid * next;
  468. for (curr=preset_d2gsid_head; curr; curr=next)
  469. {
  470. next = curr->next;
  471. free(curr);
  472. }
  473. }
  474. eventlog(eventlog_level_info,__FUNCTION__,"dbserver stopped");
  475. }
  476. int dbs_server_shutdown_connection(t_d2dbs_connection* conn)
  477. {
  478. psock_shutdown(conn->sd, PSOCK_SHUT_RDWR) ;
  479. psock_close(conn->sd);
  480. if (conn->verified && conn->type==CONNECT_CLASS_D2GS_TO_D2DBS) {
  481. eventlog(eventlog_level_info,__FUNCTION__,"unlock all characters on gs %s(%d)",conn->serverip,conn->serverid);
  482. eventlog_step(prefs_get_logfile_gs(),eventlog_level_info,__FUNCTION__,"unlock all characters on gs %s(%d)",conn->serverip,conn->serverid);
  483. eventlog_step(prefs_get_logfile_gs(),eventlog_level_info,__FUNCTION__,"close connection to gs on socket %d", conn->sd);
  484. cl_unlock_all_char_by_gsid(conn->serverid);
  485. }
  486. free(conn);
  487. return 1;
  488. }
  489. static int setsockopt_keepalive(int sock)
  490. {
  491. int optval;
  492. psock_t_socklen optlen;
  493. optval = 1;
  494. optlen = sizeof(optval);
  495. if (psock_setsockopt(sock, PSOCK_SOL_SOCKET, PSOCK_SO_KEEPALIVE, &optval, optlen)) {
  496. eventlog(eventlog_level_info,__FUNCTION__,"failed set KEEPALIVE for socket %d, errno=%d", sock, psock_errno());
  497. return -1;
  498. } else {
  499. eventlog(eventlog_level_info,__FUNCTION__,"set KEEPALIVE option for socket %d", sock);
  500. return 0;
  501. }
  502. }
  503. static unsigned int get_preset_d2gsid(unsigned int ipaddr)
  504. {
  505. t_preset_d2gsid *pgsid;
  506. pgsid = preset_d2gsid_head;
  507. while (pgsid)
  508. {
  509. if (pgsid->ipaddr == ipaddr)
  510. return pgsid->d2gsid;
  511. pgsid = pgsid->next;
  512. }
  513. /* not found, build a new item */
  514. pgsid = malloc(sizeof(t_preset_d2gsid));
  515. if (!pgsid) {
  516. eventlog(eventlog_level_warn,__FUNCTION__,"failed malloc memory for t_preset_d2gsid");
  517. return ++dbs_packet_gs_id;
  518. }
  519. pgsid->ipaddr = ipaddr;
  520. pgsid->d2gsid = ++dbs_packet_gs_id;
  521. /* add to list */
  522. pgsid->next = preset_d2gsid_head;
  523. preset_d2gsid_head = pgsid;
  524. return preset_d2gsid_head->d2gsid;
  525. }