00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00040 #include <global.h>
00041 #ifndef __CEXTRACT__
00042 #include <sproto.h>
00043 #endif
00044 #ifndef WIN32
00045 #include <sys/types.h>
00046 #include <sys/time.h>
00047 #include <sys/socket.h>
00048 #include <netinet/in.h>
00049 #include <netdb.h>
00050 #endif
00051
00052 #ifdef HAVE_UNISTD_H
00053 #include <unistd.h>
00054 #endif
00055
00056 #ifdef HAVE_ARPA_INET_H
00057 #include <arpa/inet.h>
00058 #endif
00059 #include <newserver.h>
00060 #include <loader.h>
00061
00063 Socket_Info socket_info;
00068 socket_struct *init_sockets;
00069
00075 void init_connection(socket_struct *ns, const char *from_ip) {
00076 SockList sl;
00077 int bufsize = 65535;
00078 int oldbufsize;
00079 socklen_t buflen = sizeof(int);
00080
00081 #ifdef WIN32
00082 int temp = 1;
00083
00084 if (ioctlsocket(ns->fd, FIONBIO , &temp) == -1)
00085 LOG(llevError, "init_connection: Error on ioctlsocket.\n");
00086 #else
00087 if (fcntl(ns->fd, F_SETFL, O_NONBLOCK) == -1) {
00088 LOG(llevError, "init_connection: Error on fcntl.\n");
00089 }
00090 #endif
00091
00092 if (getsockopt(ns->fd, SOL_SOCKET, SO_SNDBUF, (char *)&oldbufsize, &buflen) == -1)
00093 oldbufsize = 0;
00094 if (oldbufsize < bufsize) {
00095 #ifdef ESRV_DEBUG
00096 LOG(llevDebug, "Default buffer size was %d bytes, will reset it to %d\n", oldbufsize, bufsize);
00097 #endif
00098 if (setsockopt(ns->fd, SOL_SOCKET, SO_SNDBUF, (char *)&bufsize, sizeof(bufsize))) {
00099 LOG(llevError, "init_connection: setsockopt unable to set output buf size to %d\n", bufsize);
00100 }
00101 }
00102 buflen = sizeof(oldbufsize);
00103 getsockopt(ns->fd, SOL_SOCKET, SO_SNDBUF, (char *)&oldbufsize, &buflen);
00104 #ifdef ESRV_DEBUG
00105 LOG(llevDebug, "Socket buffer size now %d bytes\n", oldbufsize);
00106 #endif
00107
00108 ns->faceset = 0;
00109 ns->facecache = 0;
00110 ns->sound = 0;
00111 ns->monitor_spells = 0;
00112 ns->darkness = 1;
00113 ns->status = Ns_Add;
00114 ns->mapx = 11;
00115 ns->mapy = 11;
00116 ns->newmapcmd = 0;
00117 ns->look_position = 0;
00118 ns->update_look = 0;
00119 ns->has_readable_type = 0;
00120 ns->supported_readables = 0;
00121 ns->monitor_spells = 0;
00122 ns->tick = 0;
00123 ns->is_bot = 0;
00124 ns->num_look_objects = DEFAULT_NUM_LOOK_OBJECTS;
00125 ns->want_pickup = 0;
00126
00127
00128
00129
00130
00131
00132 SockList_Init(&ns->inbuf);
00133 SockList_ResetRead(&ns->inbuf);
00134
00135
00136
00137
00138 memset(ns->inbuf.buf, 0, sizeof(ns->inbuf.buf));
00139 memset(&ns->lastmap, 0, sizeof(struct Map));
00140 if (!ns->faces_sent)
00141 ns->faces_sent = calloc(sizeof(*ns->faces_sent), nrofpixmaps);
00142 ns->faces_sent_len = nrofpixmaps;
00143
00144 memset(&ns->anims_sent, 0, sizeof(ns->anims_sent));
00145 memset(&ns->stats, 0, sizeof(struct statsinfo));
00146 ns->map_scroll_x = 0;
00147 ns->map_scroll_y = 0;
00148
00149
00150
00151
00152 ns->faces_sent[0] = NS_FACESENT_FACE;
00153
00154 ns->outputbuffer.start = 0;
00155 ns->outputbuffer.len = 0;
00156 ns->can_write = 1;
00157 ns->password_fails = 0;
00158
00159 ns->host = strdup_local(from_ip);
00160 SockList_Init(&sl);
00161 SockList_AddPrintf(&sl, "version %d %d %s\n", VERSION_CS, VERSION_SC, VERSION_INFO);
00162 Send_With_Handling(ns, &sl);
00163 SockList_Term(&sl);
00164 #ifdef CS_LOGSTATS
00165 if (socket_info.nconns > cst_tot.max_conn)
00166 cst_tot.max_conn = socket_info.nconns;
00167 if (socket_info.nconns > cst_lst.max_conn)
00168 cst_lst.max_conn = socket_info.nconns;
00169 #endif
00170 }
00171
00173 void init_server(void) {
00174 struct sockaddr_in insock;
00175 struct protoent *protox;
00176 struct linger linger_opt;
00177 char err[MAX_BUF];
00178
00179 #ifdef WIN32
00180 WSADATA w;
00181
00182 socket_info.max_filedescriptor = 1;
00183 WSAStartup(0x0101, &w);
00184
00185
00186 #else
00187
00188 #ifdef HAVE_SYSCONF
00189 socket_info.max_filedescriptor = sysconf(_SC_OPEN_MAX);
00190 #else
00191 # ifdef HAVE_GETDTABLESIZE
00192 socket_info.max_filedescriptor = getdtablesize();
00193 # else
00194 "Unable to find usable function to get max filedescriptors";
00195 # endif
00196 #endif
00197 #endif
00198
00199 socket_info.timeout.tv_sec = 0;
00200 socket_info.timeout.tv_usec = 0;
00201 socket_info.nconns = 0;
00202
00203 #ifdef CS_LOGSTATS
00204 memset(&cst_tot, 0, sizeof(CS_Stats));
00205 memset(&cst_lst, 0, sizeof(CS_Stats));
00206 cst_tot.time_start = time(NULL);
00207 cst_lst.time_start = time(NULL);
00208 #endif
00209
00210 LOG(llevDebug, "Initialize new client/server data\n");
00211 socket_info.nconns = 1;
00212 init_sockets = malloc(sizeof(socket_struct));
00213 init_sockets[0].faces_sent = NULL;
00214 socket_info.allocated_sockets = 1;
00215
00216 protox = getprotobyname("tcp");
00217 if (protox == NULL) {
00218 LOG(llevError, "init_server: Error getting protox\n");
00219 return;
00220 }
00221 init_sockets[0].fd = socket(PF_INET, SOCK_STREAM, protox->p_proto);
00222 if (init_sockets[0].fd == -1) {
00223 LOG(llevError, "Cannot create socket: %s\n", strerror_local(errno, err, sizeof(err)));
00224 exit(-1);
00225 }
00226 insock.sin_family = AF_INET;
00227 insock.sin_port = htons(settings.csport);
00228 insock.sin_addr.s_addr = htonl(INADDR_ANY);
00229
00230 linger_opt.l_onoff = 0;
00231 linger_opt.l_linger = 0;
00232 if (setsockopt(init_sockets[0].fd, SOL_SOCKET, SO_LINGER, (char *)&linger_opt, sizeof(struct linger))) {
00233 LOG(llevError, "Cannot setsockopt(SO_LINGER): %s\n", strerror_local(errno, err, sizeof(err)));
00234 }
00235
00236
00237
00238
00239 #if defined(__osf__) || defined(hpux) || defined(sgi) || defined(NeXT) || \
00240 defined(__sun__) || defined(__linux__) || defined(SVR4) || \
00241 defined(__FreeBSD__) || defined(__OpenBSD__) || \
00242 defined(WIN32) || \
00243 defined(__GNU__)
00244 {
00245 #ifdef WIN32
00246 char tmp = 1;
00247 #else
00248 int tmp = 1;
00249 #endif
00250
00251 if (setsockopt(init_sockets[0].fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp))) {
00252 LOG(llevError, "Cannot setsockopt(SO_REUSEADDR): %s\n", strerror_local(errno, err, sizeof(err)));
00253 }
00254 }
00255 #else
00256 if (setsockopt(init_sockets[0].fd, SOL_SOCKET, SO_REUSEADDR, (char *)NULL, 0)) {
00257 LOG(llevError, "Cannot setsockopt(SO_REUSEADDR): %s\n", strerror_local(errno, err, sizeof(err)));
00258 }
00259 #endif
00260
00261 if (bind(init_sockets[0].fd, (struct sockaddr *)&insock, sizeof(insock)) == (-1)) {
00262 LOG(llevError, "Cannot bind socket to port %d: %s\n", ntohs(insock.sin_port), strerror_local(errno, err, sizeof(err)));
00263 #ifdef WIN32
00264 shutdown(init_sockets[0].fd, SD_BOTH);
00265 closesocket(init_sockets[0].fd);
00266 #else
00267 close(init_sockets[0].fd);
00268 #endif
00269 exit(-1);
00270 }
00271 if (listen(init_sockets[0].fd, 5) == (-1)) {
00272 LOG(llevError, "Cannot listen on socket: %s\n", strerror_local(errno, err, sizeof(err)));
00273 #ifdef WIN32
00274 shutdown(init_sockets[0].fd, SD_BOTH);
00275 closesocket(init_sockets[0].fd);
00276 #else
00277 close(init_sockets[0].fd);
00278 #endif
00279 exit(-1);
00280 }
00281 init_sockets[0].status = Ns_Add;
00282 read_client_images();
00283 }
00284
00285
00286
00287
00288
00289
00290
00292 void free_all_newserver(void) {
00293 LOG(llevDebug, "Freeing all new client/server information.\n");
00294 free_socket_images();
00295 free(init_sockets);
00296 }
00297
00305 void free_newsocket(socket_struct *ns) {
00306 #ifdef WIN32
00307 shutdown(ns->fd, SD_BOTH);
00308 if (closesocket(ns->fd)) {
00309 #else
00310 if (close(ns->fd)) {
00311 #endif
00312
00313 #ifdef ESRV_DEBUG
00314 LOG(llevDebug, "Error closing socket %d\n", ns->fd);
00315 #endif
00316 }
00317 ns->fd = -1;
00318 if (ns->stats.range)
00319 FREE_AND_CLEAR(ns->stats.range);
00320 if (ns->stats.title)
00321 FREE_AND_CLEAR(ns->stats.title);
00322 if (ns->host)
00323 FREE_AND_CLEAR(ns->host);
00324 SockList_Term(&ns->inbuf);
00325 }
00326
00328 void final_free_player(player *pl) {
00329 SockList sl;
00330
00331 SockList_Init(&sl);
00332 SockList_AddString(&sl, "goodbye");
00333 Send_With_Handling(&pl->socket, &sl);
00334 SockList_Term(&sl);
00335 free_newsocket(&pl->socket);
00336 free_player(pl);
00337 }