ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/socket/loop.C
(Generate patch)

Comparing deliantra/server/socket/loop.C (file contents):
Revision 1.6 by root, Sun Sep 10 13:43:33 2006 UTC vs.
Revision 1.10 by root, Wed Dec 13 02:55:51 2006 UTC

1
2/*
3 * static char *rcsid_loop_c =
4 * "$Id: loop.C,v 1.6 2006/09/10 13:43:33 root Exp $";
5 */
6
7/* 1/*
8 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
9 3
10 Copyright (C) 2002-2003 Mark Wedel & The Crossfire Development Team 4 Copyright (C) 2002-2003 Mark Wedel & The Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
22 16
23 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 20
27 The author can be reached via e-mail to crossfire-devel@real-time.com 21 The author can be reached via e-mail to <crossfire@schmorp.de>
28*/ 22*/
29 23
30/** 24/**
31 * \file 25 * \file
32 * Main client/server loops. 26 * Main client/server loops.
38 * The reading of data is handled in ericserver.c 32 * The reading of data is handled in ericserver.c
39 */ 33 */
40 34
41 35
42#include <global.h> 36#include <global.h>
43#ifndef __CEXTRACT__
44# include <sproto.h> 37#include <sproto.h>
45# include <sockproto.h> 38#include <sockproto.h>
46#endif
47 39
48#ifndef WIN32 /* ---win32 exclude unix headers */
49# include <sys/types.h> 40#include <sys/types.h>
50# include <sys/time.h> 41#include <sys/time.h>
51# include <sys/socket.h> 42#include <sys/socket.h>
52# include <netinet/in.h> 43#include <netinet/in.h>
53# include <netdb.h> 44#include <netdb.h>
54#endif /* end win32 */
55 45
56#ifdef HAVE_UNISTD_H 46#ifdef HAVE_UNISTD_H
57# include <unistd.h> 47# include <unistd.h>
58#endif 48#endif
59 49
166 { 156 {
167 *cp = '\0'; 157 *cp = '\0';
168 params = cp + 1; 158 params = cp + 1;
169 break; 159 break;
170 } 160 }
161
171 if (!strcmp (buf, "image_info")) 162 if (!strcmp (buf, "image_info"))
172 send_image_info (ns, params); 163 send_image_info (ns, params);
173 else if (!strcmp (buf, "image_sums")) 164 else if (!strcmp (buf, "image_sums"))
174 send_image_sums (ns, params); 165 send_image_sums (ns, params);
175 else if (!strcmp (buf, "skill_info")) 166 else if (!strcmp (buf, "skill_info"))
332 if (pl->socket.status != Ns_Dead) 323 if (pl->socket.status != Ns_Dead)
333 Socket_Flush (&pl->socket); 324 Socket_Flush (&pl->socket);
334} 325}
335 326
336/** 327/**
337 * This checks the sockets for input and exceptions, does the right thing. 328 * This checks the sockets for input, does the right thing.
338 * 329 *
339 * A bit of this code is grabbed out of socket.c 330 * A bit of this code is grabbed out of socket.c
340 * There are 2 lists we need to look through - init_sockets is a list 331 * There are 2 lists we need to look through - init_sockets is a list
341 * 332 *
342 */ 333 */
343void 334void
344doeric_server (void) 335doeric_server (void)
345{ 336{
346 int i, pollret; 337 int i, pollret;
347 fd_set tmp_read, tmp_exceptions, tmp_write; 338 fd_set tmp_read, tmp_write;
348 struct sockaddr_in addr; 339 struct sockaddr_in addr;
349 socklen_t addrlen = sizeof (struct sockaddr); 340 socklen_t addrlen = sizeof (struct sockaddr);
350 player *pl, *next; 341 player *pl, *next;
351 342
352#ifdef CS_LOGSTATS 343#ifdef CS_LOGSTATS
354 write_cs_stats (); 345 write_cs_stats ();
355#endif 346#endif
356 347
357 FD_ZERO (&tmp_read); 348 FD_ZERO (&tmp_read);
358 FD_ZERO (&tmp_write); 349 FD_ZERO (&tmp_write);
359 FD_ZERO (&tmp_exceptions);
360 350
361 for (i = 0; i < socket_info.allocated_sockets; i++) 351 for (i = 0; i < socket_info.allocated_sockets; i++)
362 { 352 {
363 if (init_sockets[i].status == Ns_Dead) 353 if (init_sockets[i].status == Ns_Dead)
364 { 354 {
366 init_sockets[i].status = Ns_Avail; 356 init_sockets[i].status = Ns_Avail;
367 socket_info.nconns--; 357 socket_info.nconns--;
368 } 358 }
369 else if (init_sockets[i].status != Ns_Avail) 359 else if (init_sockets[i].status != Ns_Avail)
370 { 360 {
371 FD_SET ((uint32) init_sockets[i].fd, &tmp_read); 361 FD_SET (init_sockets[i].fd, &tmp_read);
372 FD_SET ((uint32) init_sockets[i].fd, &tmp_write); 362 FD_SET (init_sockets[i].fd, &tmp_write);
373 FD_SET ((uint32) init_sockets[i].fd, &tmp_exceptions);
374 } 363 }
375 } 364 }
376 365
377 /* Go through the players. Let the loop set the next pl value, 366 /* Go through the players. Let the loop set the next pl value,
378 * since we may remove some 367 * since we may remove some
382 if (pl->socket.status == Ns_Dead) 371 if (pl->socket.status == Ns_Dead)
383 { 372 {
384 player *npl = pl->next; 373 player *npl = pl->next;
385 374
386 save_player (pl->ob, 0); 375 save_player (pl->ob, 0);
376
387 if (!QUERY_FLAG (pl->ob, FLAG_REMOVED)) 377 if (!QUERY_FLAG (pl->ob, FLAG_REMOVED))
388 { 378 {
389 terminate_all_pets (pl->ob); 379 terminate_all_pets (pl->ob);
390 remove_ob (pl->ob); 380 pl->ob->remove ();
391 } 381 }
382
392 leave (pl, 1); 383 leave (pl, 1);
393 final_free_player (pl); 384 final_free_player (pl);
394 pl = npl; 385 pl = npl;
395 } 386 }
396 else 387 else
397 { 388 {
398 FD_SET ((uint32) pl->socket.fd, &tmp_read); 389 FD_SET ((uint32) pl->socket.fd, &tmp_read);
399 FD_SET ((uint32) pl->socket.fd, &tmp_write); 390 FD_SET ((uint32) pl->socket.fd, &tmp_write);
400 FD_SET ((uint32) pl->socket.fd, &tmp_exceptions);
401 pl = pl->next; 391 pl = pl->next;
402 } 392 }
403 } 393 }
404 394
405 /* Reset timeout each time, since some OS's will change the values on 395 /* Reset timeout each time, since some OS's will change the values on
406 * the return from select. 396 * the return from select.
407 */ 397 */
408 socket_info.timeout.tv_sec = 0; 398 socket_info.timeout.tv_sec = 0;
409 socket_info.timeout.tv_usec = 0; 399 socket_info.timeout.tv_usec = 0;
410 400
411 pollret = select (socket_info.max_filedescriptor, &tmp_read, &tmp_write, &tmp_exceptions, &socket_info.timeout); 401 pollret = select (socket_info.max_filedescriptor,
402 &tmp_read, &tmp_write, 0,
403 &socket_info.timeout);
412 404
413 if (pollret == -1) 405 if (pollret == -1)
414 { 406 {
415 LOG (llevError, "select failed: %s\n", strerror (errno)); 407 LOG (llevError, "select failed: %s\n", strerror (errno));
416 return; 408 return;
451 { 443 {
452 newsocknum = j; 444 newsocknum = j;
453 break; 445 break;
454 } 446 }
455 } 447 }
448
456 init_sockets[newsocknum].fd = accept (init_sockets[0].fd, (struct sockaddr *) &addr, &addrlen); 449 init_sockets[newsocknum].fd = accept (init_sockets[0].fd, (struct sockaddr *) &addr, &addrlen);
450
457 if (init_sockets[newsocknum].fd == -1) 451 if (init_sockets[newsocknum].fd == -1)
458 {
459 LOG (llevError, "accept failed: %s\n", strerror (errno)); 452 LOG (llevError, "accept failed: %s\n", strerror (errno));
460 }
461 else 453 else
462 { 454 {
463 char buf[MAX_BUF]; 455 char buf[MAX_BUF];
464 long ip; 456 long ip;
465 NewSocket *ns; 457 NewSocket *ns;
481 socket_info.nconns++; 473 socket_info.nconns++;
482 } 474 }
483 } 475 }
484 } 476 }
485 477
486 /* Check for any exceptions/input on the sockets */ 478 /* Check for any input on the sockets */
487 if (pollret) 479 if (pollret)
488 for (i = 1; i < socket_info.allocated_sockets; i++) 480 for (i = 1; i < socket_info.allocated_sockets; i++)
489 { 481 {
490 if (init_sockets[i].status == Ns_Avail) 482 if (init_sockets[i].status == Ns_Avail)
491 continue; 483 continue;
492 if (FD_ISSET (init_sockets[i].fd, &tmp_exceptions)) 484
493 {
494 free_newsocket (&init_sockets[i]);
495 init_sockets[i].status = Ns_Avail;
496 socket_info.nconns--;
497 continue;
498 }
499 if (FD_ISSET (init_sockets[i].fd, &tmp_read)) 485 if (FD_ISSET (init_sockets[i].fd, &tmp_read))
500 {
501 HandleClient (&init_sockets[i], NULL); 486 HandleClient (&init_sockets[i], NULL);
502 } 487
503 if (FD_ISSET (init_sockets[i].fd, &tmp_write)) 488 if (FD_ISSET (init_sockets[i].fd, &tmp_write))
504 {
505 init_sockets[i].can_write = 1; 489 init_sockets[i].can_write = 1;
506 }
507 } 490 }
508 491
509 /* This does roughly the same thing, but for the players now */ 492 /* This does roughly the same thing, but for the players now */
510 for (pl = first_player; pl != NULL; pl = next) 493 for (pl = first_player; pl != NULL; pl = next)
511 { 494 {
522 LOG (llevDebug, "Player %s socket now write enabled\n", pl->ob->name); 505 LOG (llevDebug, "Player %s socket now write enabled\n", pl->ob->name);
523#endif 506#endif
524 pl->socket.can_write = 1; 507 pl->socket.can_write = 1;
525 write_socket_buffer (&pl->socket); 508 write_socket_buffer (&pl->socket);
526 } 509 }
510
527 /* if we get an error on the write_socket buffer, no reason to 511 /* if we get an error on the write_socket buffer, no reason to
528 * continue on this socket. 512 * continue on this socket.
529 */ 513 */
530 if (pl->socket.status == Ns_Dead) 514 if (pl->socket.status == Ns_Dead)
531 continue; 515 continue;
532 } 516 }
533 else 517 else
534 pl->socket.can_write = 0; 518 pl->socket.can_write = 0;
535 519
536 if (FD_ISSET (pl->socket.fd, &tmp_exceptions)) 520 HandleClient (&pl->socket, pl);
521 /* If the player has left the game, then the socket status
522 * will be set to this be the leave function. We don't
523 * need to call leave again, as it has already been called
524 * once.
525 */
526 if (pl->socket.status == Ns_Dead)
537 { 527 {
538 save_player (pl->ob, 0); 528 save_player (pl->ob, 0);
529
539 if (!QUERY_FLAG (pl->ob, FLAG_REMOVED)) 530 if (!QUERY_FLAG (pl->ob, FLAG_REMOVED))
540 { 531 {
541 terminate_all_pets (pl->ob); 532 terminate_all_pets (pl->ob);
542 remove_ob (pl->ob); 533 pl->ob->remove ();
543 } 534 }
535
544 leave (pl, 1); 536 leave (pl, 1);
545 final_free_player (pl); 537 final_free_player (pl);
546 } 538 }
547 else 539 else
548 { 540 {
549 HandleClient (&pl->socket, pl); 541 /* Update the players stats once per tick. More efficient than
550 /* If the player has left the game, then the socket status 542 * sending them whenever they change, and probably just as useful
551 * will be set to this be the leave function. We don't
552 * need to call leave again, as it has already been called
553 * once.
554 */ 543 */
555 if (pl->socket.status == Ns_Dead)
556 {
557 save_player (pl->ob, 0);
558 if (!QUERY_FLAG (pl->ob, FLAG_REMOVED))
559 {
560 terminate_all_pets (pl->ob);
561 remove_ob (pl->ob);
562 }
563 leave (pl, 1);
564 final_free_player (pl);
565 }
566 else
567 {
568
569 /* Update the players stats once per tick. More efficient than
570 * sending them whenever they change, and probably just as useful
571 */
572 esrv_update_stats (pl); 544 esrv_update_stats (pl);
573 if (pl->last_weight != -1 && pl->last_weight != WEIGHT (pl->ob)) 545 if (pl->last_weight != -1 && pl->last_weight != WEIGHT (pl->ob))
574 { 546 {
575 esrv_update_item (UPD_WEIGHT, pl->ob, pl->ob); 547 esrv_update_item (UPD_WEIGHT, pl->ob, pl->ob);
576 if (pl->last_weight != WEIGHT (pl->ob)) 548 if (pl->last_weight != WEIGHT (pl->ob))
577 LOG (llevError, "esrv_update_item(UPD_WEIGHT) did not set player weight: is %lu, should be %lu\n", 549 LOG (llevError, "esrv_update_item(UPD_WEIGHT) did not set player weight: is %lu, should be %lu\n",
578 (unsigned long) pl->last_weight, WEIGHT (pl->ob)); 550 (unsigned long) pl->last_weight, WEIGHT (pl->ob));
579 } 551 }
552
580 /* draw_client_map does sanity checking that map is 553 /* draw_client_map does sanity checking that map is
581 * valid, so don't do it here. 554 * valid, so don't do it here.
582 */ 555 */
583 draw_client_map (pl->ob); 556 draw_client_map (pl->ob);
584 if (pl->socket.update_look) 557 if (pl->socket.update_look)
585 esrv_draw_look (pl->ob); 558 esrv_draw_look (pl->ob);
586 }
587 } 559 }
588 } 560 }
589} 561}
562

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines