|
Atrinik Server 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00030 #include <global.h> 00031 #include "zlib.h" 00032 00034 _srv_client_files SrvClientFiles[SRV_CLIENT_FILES]; 00035 00037 Socket_Info socket_info; 00039 socket_struct *init_sockets; 00040 00050 void init_connection(socket_struct *ns, const char *from_ip) 00051 { 00052 int bufsize = 65535; 00053 int oldbufsize; 00054 socklen_t buflen = sizeof(int); 00055 00056 #ifdef WIN32 00057 u_long temp = 1; 00058 00059 if (ioctlsocket(ns->fd, FIONBIO, &temp) == -1) 00060 { 00061 LOG(llevDebug, "init_connection(): Error on ioctlsocket.\n"); 00062 } 00063 #else 00064 if (fcntl(ns->fd, F_SETFL, O_NDELAY | O_NONBLOCK) == -1) 00065 { 00066 LOG(llevDebug, "init_connection(): Error on fcntl.\n"); 00067 } 00068 #endif 00069 00070 if (getsockopt(ns->fd, SOL_SOCKET, SO_SNDBUF, (char *) &oldbufsize, &buflen) == -1) 00071 { 00072 oldbufsize = 0; 00073 } 00074 00075 if (oldbufsize < bufsize) 00076 { 00077 if (setsockopt(ns->fd, SOL_SOCKET, SO_SNDBUF, (char *) &bufsize, sizeof(bufsize))) 00078 { 00079 LOG(llevDebug, "init_connection(): setsockopt unable to set output buf size to %d\n", bufsize); 00080 } 00081 } 00082 00083 ns->login_count = 0; 00084 ns->keepalive = 0; 00085 ns->addme = 0; 00086 ns->faceset = 0; 00087 ns->sound = 0; 00088 ns->ext_title_flag = 1; 00089 ns->status = Ns_Add; 00090 ns->mapx = 17; 00091 ns->mapy = 17; 00092 ns->mapx_2 = 8; 00093 ns->mapy_2 = 8; 00094 ns->version = 0; 00095 ns->rf_settings = 0; 00096 ns->rf_skills = 0; 00097 ns->rf_spells = 0; 00098 ns->rf_anims = 0; 00099 ns->rf_hfiles = 0; 00100 ns->rf_bmaps = 0; 00101 ns->password_fails = 0; 00102 ns->is_bot = 0; 00103 00104 ns->inbuf.len = 0; 00105 ns->inbuf.buf = malloc(MAXSOCKBUF_IN); 00106 ns->inbuf.buf[0] = '\0'; 00107 00108 ns->readbuf.len = 0; 00109 ns->readbuf.buf = malloc(MAXSOCKBUF_IN); 00110 ns->readbuf.buf[0] = '\0'; 00111 00112 ns->cmdbuf.len = 0; 00113 ns->cmdbuf.buf = malloc(MAXSOCKBUF); 00114 ns->cmdbuf.buf[0] = '\0'; 00115 00116 memset(&ns->lastmap, 0, sizeof(struct Map)); 00117 ns->buffer_front = NULL; 00118 ns->buffer_back = NULL; 00119 00120 ns->host = strdup_local(from_ip); 00121 00122 /* Legacy support for older clients. */ 00123 { 00124 unsigned char buf[256]; 00125 SockList sl; 00126 00127 strncpy((char *) buf, "X991017 991017 Atrinik Server", sizeof(buf) - 1); 00128 buf[0] = BINARY_CMD_VERSION; 00129 00130 sl.buf = buf; 00131 sl.len = strlen((char *) buf); 00132 Send_With_Handling(ns, &sl); 00133 } 00134 00135 #if CS_LOGSTATS 00136 if (socket_info.nconns > cst_tot.max_conn) 00137 { 00138 cst_tot.max_conn = socket_info.nconns; 00139 } 00140 00141 if (socket_info.nconns > cst_lst.max_conn) 00142 { 00143 cst_lst.max_conn = socket_info.nconns; 00144 } 00145 #endif 00146 } 00147 00151 void init_ericserver() 00152 { 00153 struct sockaddr_in insock; 00154 struct linger linger_opt; 00155 #ifndef WIN32 00156 struct protoent *protox; 00157 00158 # ifdef HAVE_SYSCONF 00159 socket_info.max_filedescriptor = sysconf(_SC_OPEN_MAX); 00160 # else 00161 # ifdef HAVE_GETDTABLESIZE 00162 socket_info.max_filedescriptor = getdtablesize(); 00163 # else 00164 "Unable to find usable function to get max filedescriptors"; 00165 # endif 00166 # endif 00167 #else 00168 WSADATA w; 00169 00170 /* Used in select, ignored in winsockets */ 00171 socket_info.max_filedescriptor = 1; 00172 /* This sets up all socket stuff */ 00173 WSAStartup(0x0101, &w); 00174 #endif 00175 00176 socket_info.timeout.tv_sec = 0; 00177 socket_info.timeout.tv_usec = 0; 00178 socket_info.nconns = 0; 00179 00180 #if CS_LOGSTATS 00181 memset(&cst_tot, 0, sizeof(CS_Stats)); 00182 memset(&cst_lst, 0, sizeof(CS_Stats)); 00183 cst_tot.time_start = time(NULL); 00184 cst_lst.time_start = time(NULL); 00185 #endif 00186 00187 LOG(llevDebug, "Initialize new client/server data\n"); 00188 socket_info.nconns = 1; 00189 init_sockets = malloc(sizeof(socket_struct)); 00190 socket_info.allocated_sockets = 1; 00191 00192 #ifndef WIN32 00193 protox = getprotobyname("tcp"); 00194 00195 if (protox == NULL) 00196 { 00197 LOG(llevBug, "init_ericserver: Error getting protox\n"); 00198 return; 00199 } 00200 00201 init_sockets[0].fd = socket(PF_INET, SOCK_STREAM, protox->p_proto); 00202 00203 #else 00204 init_sockets[0].fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 00205 #endif 00206 00207 if (init_sockets[0].fd == -1) 00208 { 00209 LOG(llevError, "Cannot create socket: %s\n", strerror_local(errno)); 00210 } 00211 00212 insock.sin_family = AF_INET; 00213 insock.sin_port = htons(settings.csport); 00214 insock.sin_addr.s_addr = htonl(INADDR_ANY); 00215 00216 linger_opt.l_onoff = 0; 00217 linger_opt.l_linger = 0; 00218 00219 if (setsockopt(init_sockets[0].fd, SOL_SOCKET, SO_LINGER, (char *) &linger_opt, sizeof(struct linger))) 00220 { 00221 LOG(llevError, "init_ericserver(): Cannot setsockopt(SO_LINGER): %s\n", strerror_local(errno)); 00222 } 00223 00224 /* Would be nice to have an autoconf check for this. It appears that 00225 * these functions are both using the same calling syntax, just one 00226 * of them needs extra values passed. */ 00227 #if !defined(_WEIRD_OS_) 00228 { 00229 int tmp = 1; 00230 00231 if (setsockopt(init_sockets[0].fd, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, sizeof(tmp))) 00232 { 00233 LOG(llevDebug, "Cannot setsockopt(SO_REUSEADDR): %s\n", strerror_local(errno)); 00234 } 00235 } 00236 #else 00237 if (setsockopt(init_sockets[0].fd, SOL_SOCKET, SO_REUSEADDR, (char *) NULL, 0)) 00238 { 00239 LOG(llevDebug, "Cannot setsockopt(SO_REUSEADDR): %s\n", strerror_local(errno)); 00240 } 00241 #endif 00242 00243 if (bind(init_sockets[0].fd, (struct sockaddr *) &insock, sizeof(insock)) == -1) 00244 { 00245 #ifndef WIN32 00246 close(init_sockets[0].fd); 00247 #else 00248 shutdown(init_sockets[0].fd, SD_BOTH); 00249 closesocket(init_sockets[0].fd); 00250 #endif 00251 LOG(llevError, "Cannot bind socket to port %d: %s\n", ntohs(insock.sin_port), strerror_local(errno)); 00252 } 00253 00254 if (listen(init_sockets[0].fd, 5) == -1) 00255 { 00256 #ifndef WIN32 00257 close(init_sockets[0].fd); 00258 #else 00259 shutdown(init_sockets[0].fd, SD_BOTH); 00260 closesocket(init_sockets[0].fd); 00261 #endif 00262 LOG(llevError, "Cannot listen on socket: %s\n", strerror_local(errno)); 00263 } 00264 00265 init_sockets[0].status = Ns_Wait; 00266 read_client_images(); 00267 updates_init(); 00268 init_srv_files(); 00269 } 00270 00273 void free_all_newserver() 00274 { 00275 LOG(llevDebug, "Freeing all new client/server information.\n"); 00276 00277 free_socket_images(); 00278 free(init_sockets); 00279 } 00280 00287 void free_newsocket(socket_struct *ns) 00288 { 00289 #ifndef WIN32 00290 if (close(ns->fd)) 00291 #else 00292 shutdown(ns->fd, SD_BOTH); 00293 if (closesocket(ns->fd)) 00294 #endif 00295 { 00296 #ifdef ESRV_DEBUG 00297 LOG(llevDebug, "Error closing socket %d\n", ns->fd); 00298 #endif 00299 } 00300 00301 if (ns->host) 00302 { 00303 free(ns->host); 00304 } 00305 00306 if (ns->inbuf.buf) 00307 { 00308 free(ns->inbuf.buf); 00309 } 00310 00311 if (ns->readbuf.buf) 00312 { 00313 free(ns->readbuf.buf); 00314 } 00315 00316 if (ns->cmdbuf.buf) 00317 { 00318 free(ns->cmdbuf.buf); 00319 } 00320 00321 socket_buffer_clear(ns); 00322 00323 memset(ns, 0, sizeof(ns)); 00324 } 00325 00331 static void load_srv_file(char *fname, int id) 00332 { 00333 FILE *fp; 00334 char *contents, *compressed; 00335 size_t fsize, numread; 00336 struct stat statbuf; 00337 00338 LOG(llevDebug, "Loading %s...", fname); 00339 00340 if ((fp = fopen(fname, "rb")) == NULL) 00341 { 00342 LOG(llevError, "Can't open file %s\n", fname); 00343 } 00344 00345 fstat(fileno(fp), &statbuf); 00346 fsize = statbuf.st_size; 00347 /* Allocate a buffer to hold the whole file. */ 00348 contents = malloc(fsize); 00349 00350 if (!contents) 00351 { 00352 LOG(llevError, "load_srv_file(): Out of memory.\n"); 00353 } 00354 00355 numread = fread(contents, 1, fsize, fp); 00356 fclose(fp); 00357 00358 /* Get a crc from the uncompressed file. */ 00359 SrvClientFiles[id].crc = crc32(1L, (const unsigned char FAR *) contents, numread); 00360 /* Store uncompressed length. */ 00361 SrvClientFiles[id].len_ucomp = numread; 00362 00363 /* Calculate the upper bound of the compressed size. */ 00364 numread = compressBound(fsize); 00365 /* Allocate a buffer to hold the compressed file. */ 00366 compressed = malloc(numread); 00367 00368 if (!compressed) 00369 { 00370 LOG(llevError, "load_srv_file(): Out of memory.\n"); 00371 } 00372 00373 compress2((Bytef *) compressed, (uLong *) &numread, (const unsigned char FAR *) contents, fsize, Z_BEST_COMPRESSION); 00374 SrvClientFiles[id].file = malloc(numread); 00375 00376 if (!SrvClientFiles[id].file) 00377 { 00378 LOG(llevError, "load_srv_file(): Out of memory.\n"); 00379 } 00380 00381 memcpy(SrvClientFiles[id].file, compressed, numread); 00382 SrvClientFiles[id].len = numread; 00383 00384 /* Free temporary buffers. */ 00385 free(contents); 00386 free(compressed); 00387 00388 LOG(llevDebug, " size: %"FMT64U" (%"FMT64U") (crc uncomp.: %lx)\n", (uint64) SrvClientFiles[id].len_ucomp, (uint64) numread, SrvClientFiles[id].crc); 00389 } 00390 00394 static void create_client_settings() 00395 { 00396 char buf[MAX_BUF * 4]; 00397 int i; 00398 FILE *fset_default, *fset_create; 00399 00400 LOG(llevDebug, "Creating %s/client_settings...\n", settings.localdir); 00401 00402 snprintf(buf, sizeof(buf), "%s/client_settings", settings.datadir); 00403 00404 /* Open default */ 00405 if ((fset_default = fopen(buf, "rb")) == NULL) 00406 { 00407 LOG(llevError, "Can not open file %s\n", buf); 00408 } 00409 00410 /* Delete our target - we create it new now */ 00411 snprintf(buf, sizeof(buf), "%s/client_settings", settings.localdir); 00412 unlink(buf); 00413 00414 /* Open target client_settings */ 00415 if ((fset_create = fopen(buf, "wb")) == NULL) 00416 { 00417 fclose(fset_default); 00418 LOG(llevError, "Can not open file %s\n", buf); 00419 } 00420 00421 /* Copy default to target */ 00422 while (fgets(buf, MAX_BUF, fset_default) != NULL) 00423 { 00424 fputs(buf, fset_create); 00425 } 00426 00427 fclose(fset_default); 00428 00429 /* Now add the level information */ 00430 snprintf(buf, sizeof(buf), "level %d\n", MAXLEVEL); 00431 fputs(buf, fset_create); 00432 00433 for (i = 0; i <= MAXLEVEL; i++) 00434 { 00435 snprintf(buf, sizeof(buf), "%"FMT64HEX"\n", new_levels[i]); 00436 fputs(buf, fset_create); 00437 } 00438 00439 fclose(fset_create); 00440 } 00441 00445 static void create_server_settings() 00446 { 00447 char buf[MAX_BUF]; 00448 size_t i; 00449 FILE *fp; 00450 00451 snprintf(buf, sizeof(buf), "%s/server_settings", settings.localdir); 00452 LOG(llevDebug, "Creating %s...\n", buf); 00453 00454 fp = fopen(buf, "wb"); 00455 00456 if (!fp) 00457 { 00458 LOG(llevError, "Couldn't create %s.\n", buf); 00459 } 00460 00461 /* Copy the default. */ 00462 snprintf(buf, sizeof(buf), "%s/server_settings", settings.datadir); 00463 copy_file(buf, fp); 00464 00465 /* Add the level information. */ 00466 snprintf(buf, sizeof(buf), "level %d\n", MAXLEVEL); 00467 fputs(buf, fp); 00468 00469 for (i = 0; i <= MAXLEVEL; i++) 00470 { 00471 snprintf(buf, sizeof(buf), "%"FMT64HEX"\n", new_levels[i]); 00472 fputs(buf, fp); 00473 } 00474 00475 fclose(fp); 00476 } 00477 00480 static void create_server_animations() 00481 { 00482 char buf[MAX_BUF]; 00483 FILE *fp, *fp2; 00484 00485 snprintf(buf, sizeof(buf), "%s/anims", settings.localdir); 00486 LOG(llevDebug, "Creating %s...\n", buf); 00487 00488 fp = fopen(buf, "wb"); 00489 00490 if (!fp) 00491 { 00492 LOG(llevError, "Couldn't create %s.\n", buf); 00493 } 00494 00495 snprintf(buf, sizeof(buf), "%s/animations", settings.datadir); 00496 fp2 = fopen(buf, "rb"); 00497 00498 if (!fp2) 00499 { 00500 LOG(llevError, "Couldn't open %s.\n", buf); 00501 } 00502 00503 while (fgets(buf, sizeof(buf), fp2)) 00504 { 00505 /* Copy anything but face names. */ 00506 if (!strncmp(buf, "anim ", 5) || !strcmp(buf, "mina\n") || !strncmp(buf, "facings ", 8)) 00507 { 00508 fputs(buf, fp); 00509 } 00510 /* Transform face names into IDs. */ 00511 else 00512 { 00513 char *end = strchr(buf, '\n'); 00514 00515 *end = '\0'; 00516 fprintf(fp, "%d\n", find_face(buf, 0)); 00517 } 00518 } 00519 00520 fclose(fp2); 00521 fclose(fp); 00522 } 00523 00529 void init_srv_files() 00530 { 00531 char buf[MAX_BUF]; 00532 00533 memset(&SrvClientFiles, 0, sizeof(SrvClientFiles)); 00534 00535 snprintf(buf, sizeof(buf), "%s/hfiles", settings.datadir); 00536 load_srv_file(buf, SRV_CLIENT_HFILES); 00537 00538 snprintf(buf, sizeof(buf), "%s/animations", settings.datadir); 00539 load_srv_file(buf, SRV_CLIENT_ANIMS); 00540 00541 snprintf(buf, sizeof(buf), "%s/client_bmaps", settings.localdir); 00542 load_srv_file(buf, SRV_CLIENT_BMAPS); 00543 00544 snprintf(buf, sizeof(buf), "%s/client_skills", settings.datadir); 00545 load_srv_file(buf, SRV_CLIENT_SKILLS); 00546 00547 snprintf(buf, sizeof(buf), "%s/client_spells", settings.datadir); 00548 load_srv_file(buf, SRV_CLIENT_SPELLS); 00549 00550 create_client_settings(); 00551 00552 snprintf(buf, sizeof(buf), "%s/client_settings", settings.localdir); 00553 load_srv_file(buf, SRV_CLIENT_SETTINGS); 00554 00555 snprintf(buf, sizeof(buf), "%s/%s", settings.localdir, UPDATES_FILE_NAME); 00556 load_srv_file(buf, SRV_FILE_UPDATES); 00557 00558 snprintf(buf, sizeof(buf), "%s/%s", settings.localdir, SRV_FILE_SPELLS_FILENAME); 00559 load_srv_file(buf, SRV_FILE_SPELLS_V2); 00560 00561 create_server_settings(); 00562 snprintf(buf, sizeof(buf), "%s/server_settings", settings.localdir); 00563 load_srv_file(buf, SRV_SERVER_SETTINGS); 00564 new_chars_init(); 00565 00566 create_server_animations(); 00567 snprintf(buf, sizeof(buf), "%s/anims", settings.localdir); 00568 load_srv_file(buf, SRV_CLIENT_ANIMS_V2); 00569 00570 snprintf(buf, sizeof(buf), "%s/effects", settings.datadir); 00571 load_srv_file(buf, SRV_CLIENT_EFFECTS); 00572 00573 snprintf(buf, sizeof(buf), "%s/%s", settings.localdir, SRV_CLIENT_SKILLS_FILENAME); 00574 load_srv_file(buf, SRV_CLIENT_SKILLS_V2); 00575 } 00576 00579 void free_srv_files() 00580 { 00581 int i; 00582 00583 LOG(llevDebug, "Freeing server/client files.\n"); 00584 00585 for (i = 0; i < SRV_CLIENT_FILES; i++) 00586 { 00587 free(SrvClientFiles[i].file); 00588 } 00589 } 00590 00599 void send_srv_file(socket_struct *ns, int id) 00600 { 00601 SockList sl; 00602 00603 /* 1 byte for the command type, 1 byte for the srv file type, 00604 * 4 bytes for original uncompressed length. */ 00605 sl.buf = malloc(SrvClientFiles[id].len + 6); 00606 00607 SOCKET_SET_BINARY_CMD(&sl, BINARY_CMD_DATA); 00608 SockList_AddChar(&sl, (char) id); 00609 SockList_AddInt(&sl, SrvClientFiles[id].len_ucomp); 00610 00611 memcpy(sl.buf + sl.len, SrvClientFiles[id].file, SrvClientFiles[id].len); 00612 sl.len += SrvClientFiles[id].len; 00613 00614 Send_With_Handling(ns, &sl); 00615 free(sl.buf); 00616 }
1.7.4