Atrinik Server 2.5
socket/init.c
Go to the documentation of this file.
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 }