socket.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. // original : core.c 2003/02/26 18:03:12 Rev 1.7
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <sys/types.h>
  5. #ifdef _WIN32
  6. #define WIN32_LEAN_AND_MEAN
  7. #include <windows.h>
  8. #include <winsock2.h>
  9. #else
  10. #include <sys/socket.h>
  11. #include <netinet/in.h>
  12. #include <netinet/tcp.h>
  13. #include <net/if.h>
  14. #include <sys/time.h>
  15. #include <unistd.h>
  16. #include <sys/ioctl.h>
  17. #include <errno.h>
  18. #ifndef SIOCGIFCONF
  19. #include <sys/sockio.h> // SIOCGIFCONF on Solaris, maybe others? [Shinomori]
  20. #endif
  21. #endif
  22. #include <fcntl.h>
  23. #include <string.h>
  24. #include "mmo.h" // [Valaris] thanks to fov
  25. #include "socket.h"
  26. #include "utils.h"
  27. #ifdef MEMWATCH
  28. #include "memwatch.h"
  29. #endif
  30. fd_set readfds;
  31. int fd_max;
  32. time_t tick_;
  33. time_t stall_time_ = 60;
  34. int rfifo_size = 65536;
  35. int wfifo_size = 65536;
  36. #ifndef TCP_FRAME_LEN
  37. #define TCP_FRAME_LEN 1053
  38. #endif
  39. struct socket_data *session[FD_SETSIZE];
  40. static int null_parse(int fd);
  41. static int (*default_func_parse)(int) = null_parse;
  42. static int null_console_parse(char *buf);
  43. static int (*default_console_parse)(char*) = null_console_parse;
  44. /*======================================
  45. * CORE : Set function
  46. *--------------------------------------
  47. */
  48. void set_defaultparse(int (*defaultparse)(int))
  49. {
  50. default_func_parse = defaultparse;
  51. }
  52. void set_nonblocking(int fd, int yes) {
  53. setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char *)&yes,sizeof yes);
  54. }
  55. static void setsocketopts(int fd)
  56. {
  57. int yes = 1; // reuse fix
  58. setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof yes);
  59. #ifdef SO_REUSEPORT
  60. setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&yes,sizeof yes);
  61. #endif
  62. set_nonblocking(fd, yes);
  63. setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &wfifo_size , sizeof(rfifo_size ));
  64. setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &rfifo_size , sizeof(rfifo_size ));
  65. }
  66. /*======================================
  67. * CORE : Socket Sub Function
  68. *--------------------------------------
  69. */
  70. static int recv_to_fifo(int fd)
  71. {
  72. int len;
  73. //printf("recv_to_fifo : %d %d\n",fd,session[fd]->eof);
  74. if(session[fd]->eof)
  75. return -1;
  76. #ifdef _WIN32
  77. len=recv(fd,session[fd]->rdata+session[fd]->rdata_size, RFIFOSPACE(fd), 0);
  78. #else
  79. len=read(fd,session[fd]->rdata+session[fd]->rdata_size,RFIFOSPACE(fd));
  80. #endif
  81. // printf (":::RECEIVE:::\n");
  82. // dump(session[fd]->rdata, len); printf ("\n");
  83. //{ int i; printf("recv %d : ",fd); for(i=0;i<len;i++){ printf("%02x ",RFIFOB(fd,session[fd]->rdata_size+i)); } printf("\n");}
  84. if(len>0){
  85. session[fd]->rdata_size+=len;
  86. session[fd]->rdata_tick = tick_;
  87. } else if(len<=0){
  88. // value of connection is not necessary the same
  89. // printf("set eof : connection #%d\n", fd);
  90. session[fd]->eof=1;
  91. }
  92. return 0;
  93. }
  94. static int send_from_fifo(int fd)
  95. {
  96. int len;
  97. //printf("send_from_fifo : %d\n",fd);
  98. if(session[fd]->eof || session[fd]->wdata == 0)
  99. return -1;
  100. if (session[fd]->wdata_size == 0)
  101. return 0;
  102. #ifdef _WIN32
  103. len=send(fd, session[fd]->wdata,session[fd]->wdata_size, 0);
  104. #else
  105. len=write(fd,session[fd]->wdata,session[fd]->wdata_size);
  106. #endif
  107. // printf (":::SEND:::\n");
  108. // dump(session[fd]->wdata, len); printf ("\n");
  109. //{ int i; printf("send %d : ",fd); for(i=0;i<len;i++){ printf("%02x ",session[fd]->wdata[i]); } printf("\n");}
  110. if(len>0){
  111. if(len<session[fd]->wdata_size){
  112. memmove(session[fd]->wdata,session[fd]->wdata+len,session[fd]->wdata_size-len);
  113. session[fd]->wdata_size-=len;
  114. } else {
  115. session[fd]->wdata_size=0;
  116. }
  117. } else if (errno != EAGAIN) {
  118. // printf("set eof :%d\n",fd);
  119. session[fd]->eof=1;
  120. }
  121. return 0;
  122. }
  123. void flush_fifos()
  124. {
  125. int i;
  126. for(i=0;i<fd_max;i++)
  127. if(session[i] != NULL &&
  128. session[i]->func_send == send_from_fifo)
  129. send_from_fifo(i);
  130. }
  131. static int null_parse(int fd)
  132. {
  133. printf("null_parse : %d\n",fd);
  134. RFIFOSKIP(fd,RFIFOREST(fd));
  135. return 0;
  136. }
  137. /*======================================
  138. * CORE : Socket Function
  139. *--------------------------------------
  140. */
  141. static int connect_client(int listen_fd)
  142. {
  143. int fd;
  144. struct sockaddr_in client_address;
  145. int len;
  146. int result;
  147. //printf("connect_client : %d\n",listen_fd);
  148. len=sizeof(client_address);
  149. fd=accept(listen_fd,(struct sockaddr*)&client_address,&len);
  150. if(fd_max<=fd) fd_max=fd+1;
  151. setsocketopts(fd);
  152. if(fd==-1)
  153. perror("accept");
  154. else
  155. FD_SET(fd,&readfds);
  156. #ifdef _WIN32
  157. {
  158. unsigned long val = 1;
  159. ioctlsocket(fd, FIONBIO, &val);
  160. }
  161. #else
  162. result = fcntl(fd, F_SETFL, O_NONBLOCK);
  163. #endif
  164. CREATE(session[fd], struct socket_data, 1);
  165. CREATE(session[fd]->rdata, unsigned char, rfifo_size);
  166. CREATE(session[fd]->wdata, unsigned char, wfifo_size);
  167. session[fd]->max_rdata = rfifo_size;
  168. session[fd]->max_wdata = wfifo_size;
  169. session[fd]->func_recv = recv_to_fifo;
  170. session[fd]->func_send = send_from_fifo;
  171. session[fd]->func_parse = default_func_parse;
  172. session[fd]->client_addr = client_address;
  173. session[fd]->rdata_tick = tick_;
  174. //printf("new_session : %d %d\n",fd,session[fd]->eof);
  175. return fd;
  176. }
  177. int make_listen_port(int port)
  178. {
  179. struct sockaddr_in server_address;
  180. int fd;
  181. int result;
  182. fd = socket( AF_INET, SOCK_STREAM, 0 );
  183. if(fd_max<=fd) fd_max=fd+1;
  184. #ifdef _WIN32
  185. {
  186. unsigned long val = 1;
  187. ioctlsocket(fd, FIONBIO, &val);
  188. }
  189. #else
  190. result = fcntl(fd, F_SETFL, O_NONBLOCK);
  191. #endif
  192. setsocketopts(fd);
  193. server_address.sin_family = AF_INET;
  194. server_address.sin_addr.s_addr = htonl( INADDR_ANY );
  195. server_address.sin_port = htons(port);
  196. result = bind(fd, (struct sockaddr*)&server_address, sizeof(server_address));
  197. if( result == -1 ) {
  198. perror("bind");
  199. exit(1);
  200. }
  201. result = listen( fd, 5 );
  202. if( result == -1 ) { /* error */
  203. perror("listen");
  204. exit(1);
  205. }
  206. FD_SET(fd, &readfds );
  207. CREATE(session[fd], struct socket_data, 1);
  208. if(session[fd]==NULL){
  209. printf("out of memory : make_listen_port\n");
  210. exit(1);
  211. }
  212. memset(session[fd],0,sizeof(*session[fd]));
  213. session[fd]->func_recv = connect_client;
  214. return fd;
  215. }
  216. // Console Reciever [Wizputer]
  217. int console_recieve(int i) {
  218. int n;
  219. char *buf;
  220. CREATE(buf, char , 64);
  221. memset(buf,0,sizeof(64));
  222. n = read(0, buf , 64);
  223. if ( n < 0 )
  224. printf("Console input read error\n");
  225. else
  226. session[0]->func_console(buf);
  227. return 0;
  228. }
  229. void set_defaultconsoleparse(int (*defaultparse)(char*))
  230. {
  231. default_console_parse = defaultparse;
  232. }
  233. static int null_console_parse(char *buf)
  234. {
  235. printf("null_console_parse : %s\n",buf);
  236. return 0;
  237. }
  238. // Console Input [Wizputer]
  239. int start_console(void) {
  240. FD_SET(0,&readfds);
  241. CREATE(session[0], struct socket_data, 1);
  242. if(session[0]==NULL){
  243. printf("out of memory : start_console\n");
  244. exit(1);
  245. }
  246. memset(session[0],0,sizeof(*session[0]));
  247. session[0]->func_recv = console_recieve;
  248. session[0]->func_console = default_console_parse;
  249. return 0;
  250. }
  251. int make_connection(long ip,int port)
  252. {
  253. struct sockaddr_in server_address;
  254. int fd;
  255. int result;
  256. fd = socket( AF_INET, SOCK_STREAM, 0 );
  257. if(fd_max<=fd)
  258. fd_max=fd+1;
  259. setsocketopts(fd);
  260. server_address.sin_family = AF_INET;
  261. server_address.sin_addr.s_addr = ip;
  262. server_address.sin_port = htons(port);
  263. #ifdef _WIN32
  264. {
  265. unsigned long val = 1;
  266. ioctlsocket(fd, FIONBIO, &val);
  267. }
  268. #else
  269. result = fcntl(fd, F_SETFL, O_NONBLOCK);
  270. #endif
  271. result = connect(fd, (struct sockaddr *)(&server_address),sizeof(struct sockaddr_in));
  272. FD_SET(fd,&readfds);
  273. CREATE(session[fd], struct socket_data, 1);
  274. CREATE(session[fd]->rdata, unsigned char, rfifo_size);
  275. CREATE(session[fd]->wdata, unsigned char, wfifo_size);
  276. session[fd]->max_rdata = rfifo_size;
  277. session[fd]->max_wdata = wfifo_size;
  278. session[fd]->func_recv = recv_to_fifo;
  279. session[fd]->func_send = send_from_fifo;
  280. session[fd]->func_parse = default_func_parse;
  281. session[fd]->rdata_tick = tick_;
  282. return fd;
  283. }
  284. int delete_session(int fd)
  285. {
  286. if(fd<0 || fd>=FD_SETSIZE)
  287. return -1;
  288. FD_CLR(fd,&readfds);
  289. if(session[fd]){
  290. if(session[fd]->rdata)
  291. free(session[fd]->rdata);
  292. if(session[fd]->wdata)
  293. free(session[fd]->wdata);
  294. if(session[fd]->session_data)
  295. free(session[fd]->session_data);
  296. free(session[fd]);
  297. }
  298. session[fd]=NULL;
  299. //printf("delete_session:%d\n",fd);
  300. return 0;
  301. }
  302. int realloc_fifo(int fd,int rfifo_size,int wfifo_size)
  303. {
  304. struct socket_data *s=session[fd];
  305. if( s->max_rdata != rfifo_size && s->rdata_size < rfifo_size){
  306. RECREATE(s->rdata, unsigned char, rfifo_size);
  307. s->max_rdata = rfifo_size;
  308. }
  309. if( s->max_wdata != wfifo_size && s->wdata_size < wfifo_size){
  310. RECREATE(s->wdata, unsigned char, wfifo_size);
  311. s->max_wdata = wfifo_size;
  312. }
  313. return 0;
  314. }
  315. int WFIFOSET(int fd,int len)
  316. {
  317. struct socket_data *s=session[fd];
  318. if (s == NULL || s->wdata == NULL)
  319. return 0;
  320. if( s->wdata_size+len+16384 > s->max_wdata ){
  321. unsigned char *sin_addr = (unsigned char *)&s->client_addr.sin_addr;
  322. realloc_fifo(fd,s->max_rdata, s->max_wdata <<1 );
  323. printf("socket: %d (%d.%d.%d.%d) wdata expanded to %d bytes.\n",fd, sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3], s->max_wdata);
  324. }
  325. s->wdata_size=(s->wdata_size+(len)+2048 < s->max_wdata) ?
  326. s->wdata_size+len : (printf("socket: %d wdata lost !!\n",fd),s->wdata_size);
  327. if (s->wdata_size > (TCP_FRAME_LEN))
  328. send_from_fifo(fd);
  329. return 0;
  330. }
  331. int do_sendrecv(int next)
  332. {
  333. fd_set rfd,wfd;
  334. struct timeval timeout;
  335. int ret,i;
  336. tick_ = time(0);
  337. memcpy(&rfd, &readfds, sizeof(rfd));
  338. FD_ZERO(&wfd);
  339. for(i=0;i<fd_max;i++){
  340. if(!session[i] && FD_ISSET(i,&readfds)){
  341. printf("force clr fds %d\n",i);
  342. FD_CLR(i,&readfds);
  343. continue;
  344. }
  345. if(!session[i])
  346. continue;
  347. if(session[i]->wdata_size)
  348. FD_SET(i,&wfd);
  349. }
  350. timeout.tv_sec = next/1000;
  351. timeout.tv_usec = next%1000*1000;
  352. ret = select(fd_max,&rfd,&wfd,NULL,&timeout);
  353. if(ret<=0)
  354. return 0;
  355. for(i=0;i<fd_max;i++){
  356. if(!session[i])
  357. continue;
  358. if(FD_ISSET(i,&wfd)){
  359. //printf("write:%d\n",i);
  360. if(session[i]->func_send)
  361. session[i]->func_send(i);
  362. }
  363. if(FD_ISSET(i,&rfd)){
  364. //printf("read:%d\n",i);
  365. if(session[i]->func_recv)
  366. session[i]->func_recv(i);
  367. }
  368. }
  369. return 0;
  370. }
  371. int do_parsepacket(void)
  372. {
  373. int i;
  374. for(i=0;i<fd_max;i++){
  375. if(!session[i])
  376. continue;
  377. if ((session[i]->rdata_tick != 0) && ((tick_ - session[i]->rdata_tick) > stall_time_))
  378. session[i]->eof = 1;
  379. if(session[i]->rdata_size==0 && session[i]->eof==0)
  380. continue;
  381. if(session[i]->func_parse){
  382. session[i]->func_parse(i);
  383. if(!session[i])
  384. continue;
  385. }
  386. RFIFOFLUSH(i);
  387. }
  388. return 0;
  389. }
  390. void do_socket(void)
  391. {
  392. FD_ZERO(&readfds);
  393. }
  394. int RFIFOSKIP(int fd,int len)
  395. {
  396. struct socket_data *s=session[fd];
  397. if (s->rdata_size-s->rdata_pos-len<0) {
  398. fprintf(stderr,"too many skip\n");
  399. exit(1);
  400. }
  401. s->rdata_pos = s->rdata_pos+len;
  402. return 0;
  403. }
  404. unsigned int addr_[16]; // ip addresses of local host (host byte order)
  405. unsigned int naddr_ = 0; // # of ip addresses
  406. int Net_Init(void)
  407. {
  408. #ifdef _WIN32
  409. char** a;
  410. unsigned int i;
  411. char fullhost[255];
  412. struct hostent* hent;
  413. /* Start up the windows networking */
  414. WSADATA wsaData;
  415. if ( WSAStartup(WINSOCK_VERSION, &wsaData) != 0 ) {
  416. printf("SYSERR: WinSock not available!\n");
  417. exit(1);
  418. }
  419. if(gethostname(fullhost, sizeof(fullhost)) == SOCKET_ERROR) {
  420. printf("Ugg.. no hostname defined!\n");
  421. return 0;
  422. }
  423. // XXX This should look up the local IP addresses in the registry
  424. // instead of calling gethostbyname. However, the way IP addresses
  425. // are stored in the registry is annoyingly complex, so I'll leave
  426. // this as T.B.D.
  427. hent = gethostbyname(fullhost);
  428. if (hent == NULL) {
  429. printf("Cannot resolve our own hostname to a IP address");
  430. return 0;
  431. }
  432. a = hent->h_addr_list;
  433. for(i = 0; a[i] != 0 && i < 16; ++i) {
  434. unsigned long addr1 = ntohl(*(unsigned long*) a[i]);
  435. addr_[i] = addr1;
  436. }
  437. naddr_ = i;
  438. #else
  439. int pos;
  440. int fdes = socket(AF_INET, SOCK_STREAM, 0);
  441. char buf[16 * sizeof(struct ifreq)];
  442. struct ifconf ic;
  443. // The ioctl call will fail with Invalid Argument if there are more
  444. // interfaces than will fit in the buffer
  445. ic.ifc_len = sizeof(buf);
  446. ic.ifc_buf = buf;
  447. if(ioctl(fdes, SIOCGIFCONF, &ic) == -1) {
  448. printf("SIOCGIFCONF failed!\n");
  449. return 0;
  450. }
  451. for(pos = 0; pos < ic.ifc_len;)
  452. {
  453. struct ifreq * ir = (struct ifreq *) (ic.ifc_buf + pos);
  454. struct sockaddr_in * a = (struct sockaddr_in *) &(ir->ifr_addr);
  455. if(a->sin_family == AF_INET) {
  456. u_long ad = ntohl(a->sin_addr.s_addr);
  457. if(ad != INADDR_LOOPBACK) {
  458. addr_[naddr_ ++] = ad;
  459. if(naddr_ == 16)
  460. break;
  461. }
  462. }
  463. #if defined(_AIX) || defined(__APPLE__)
  464. pos += ir->ifr_addr.sa_len; // For when we port athena to run on Mac's :)
  465. pos += sizeof(ir->ifr_name);
  466. #else
  467. pos += sizeof(struct ifreq);
  468. #endif
  469. }
  470. #endif
  471. return(0);
  472. }