ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/socket/metaserver.C
Revision: 1.3
Committed: Sun Sep 10 13:43:33 2006 UTC (17 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.2: +97 -78 lines
Log Message:
indent

File Contents

# User Rev Content
1 root 1.3
2 elmex 1.1 /*
3     * static char *rcsid_metaserver_c =
4 root 1.3 * "$Id: metaserver.C,v 1.2 2006-08-29 08:01:38 root Exp $";
5 elmex 1.1 */
6    
7     /*
8     CrossFire, A Multiplayer game for X-windows
9    
10     Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11     Copyright (C) 1992 Frank Tore Johansen
12    
13     This program is free software; you can redistribute it and/or modify
14     it under the terms of the GNU General Public License as published by
15     the Free Software Foundation; either version 2 of the License, or
16     (at your option) any later version.
17    
18     This program is distributed in the hope that it will be useful,
19     but WITHOUT ANY WARRANTY; without even the implied warranty of
20     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21     GNU General Public License for more details.
22    
23     You should have received a copy of the GNU General Public License
24     along with this program; if not, write to the Free Software
25     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26    
27     The authors can be reached via e-mail at crossfire-devel@real-time.com
28     */
29    
30     /**
31     * \file
32     * \date 2003-12-02
33     * Meta-server related functions.
34     */
35    
36     #include <global.h>
37    
38 root 1.3 #ifndef WIN32 /* ---win32 exclude unix header files */
39     # include <sys/types.h>
40     # include <sys/socket.h>
41     # include <netinet/in.h>
42     # include <netdb.h>
43     # include <arpa/inet.h>
44 elmex 1.1
45     #endif /* end win32 */
46    
47 root 1.3 static int metafd = -1;
48 elmex 1.1 static struct sockaddr_in sock;
49    
50     /**
51     * Connects to metaserver.
52     *
53     * Its only called once. If we are not
54     * trying to contact the metaserver of the connection attempt fails, metafd will be
55     * set to -1. We use this instead of messing with the settings.meta_on so that
56     * that can be examined to at least see what the user was trying to do.
57     */
58 root 1.3 void
59     metaserver_init (void)
60 elmex 1.1 {
61    
62 root 1.3 #ifdef WIN32 /* ***win32 metaserver_init(): init win32 socket */
63     struct hostent *hostbn;
64     int temp = 1;
65 elmex 1.1 #endif
66    
67 root 1.3 if (!settings.meta_on)
68     {
69     metafd = -1;
70     return;
71     }
72    
73     if (isdigit (settings.meta_server[0]))
74     sock.sin_addr.s_addr = inet_addr (settings.meta_server);
75     else
76     {
77     struct hostent *hostbn = gethostbyname (settings.meta_server);
78    
79     if (hostbn == NULL)
80     {
81     LOG (llevDebug, "metaserver_init: Unable to resolve hostname %s\n", settings.meta_server);
82     return;
83 root 1.2 }
84 root 1.3 memcpy (&sock.sin_addr, hostbn->h_addr, hostbn->h_length);
85 elmex 1.1 }
86 root 1.3 #ifdef WIN32 /* ***win32 metaserver_init(): init win32 socket */
87     ioctlsocket (metafd, FIONBIO, &temp);
88     #else
89     fcntl (metafd, F_SETFL, O_NONBLOCK);
90 elmex 1.1 #endif
91 root 1.3 if ((metafd = socket (AF_INET, SOCK_DGRAM, 0)) == -1)
92     {
93     LOG (llevDebug, "metaserver_init: Unable to create socket, err %d\n", errno);
94     return;
95     }
96     sock.sin_family = AF_INET;
97     sock.sin_port = htons (settings.meta_port);
98    
99     /* No hostname specified, so lets try to figure one out */
100     if (settings.meta_host[0] == 0)
101     {
102     char hostname[MAX_BUF], domain[MAX_BUF];
103    
104     if (gethostname (hostname, MAX_BUF - 1))
105     {
106     LOG (llevDebug, "metaserver_init: gethostname failed - will not report hostname\n");
107     return;
108 root 1.2 }
109 elmex 1.1
110 root 1.3 #ifdef WIN32 /* ***win32 metaserver_init(): gethostbyname! */
111     hostbn = gethostbyname (hostname);
112     if (hostbn != (struct hostent *) NULL) /* quick hack */
113     memcpy (domain, hostbn->h_addr, hostbn->h_length);
114 elmex 1.1
115 root 1.3 if (hostbn == (struct hostent *) NULL)
116     {
117 elmex 1.1 #else
118 root 1.3 if (getdomainname (domain, MAX_BUF - 1))
119     {
120 elmex 1.1 #endif /* win32 */
121 root 1.3 LOG (llevDebug, "metaserver_init: getdomainname failed - will not report hostname\n");
122     return;
123 root 1.2 }
124 root 1.3 /* Potential overrun here but unlikely to occur */
125     sprintf (settings.meta_host, "%s.%s", hostname, domain);
126 elmex 1.1 }
127     }
128    
129     /**
130     * Updates our info in the metaserver
131     */
132 root 1.3 void
133     metaserver_update (void)
134 elmex 1.1 {
135 root 1.3 char data[MAX_BUF], num_players = 0;
136     player *pl;
137 elmex 1.1
138 root 1.3 if (metafd == -1)
139     return; /* No valid connection */
140 elmex 1.1
141 root 1.3 /* We could use socket_info.nconns, but that is not quite as accurate,
142     * as connections in the progress of being established, are listening
143     * but don't have a player, etc. The checks below are basically the
144     * same as for the who commands with the addition that WIZ, AFK, and BOT
145     * players are not counted.
146     */
147     for (pl = first_player; pl != NULL; pl = pl->next)
148     {
149     if (pl->ob->map == NULL)
150     continue;
151     if (pl->hidden)
152     continue;
153     if (QUERY_FLAG (pl->ob, FLAG_WIZ))
154     continue;
155     if (QUERY_FLAG (pl->ob, FLAG_AFK))
156     continue;
157     if (pl->state != ST_PLAYING && pl->state != ST_GET_PARTY_PASSWORD)
158     continue;
159     //if (pl->socket.is_bot) continue;
160     num_players++;
161     }
162    
163     sprintf (data, "%s|%d|%s|%s|%d|%d|%ld", settings.meta_host, num_players, VERSION "+",
164     settings.meta_comment, cst_tot.ibytes, cst_tot.obytes, (long) time (NULL) - cst_tot.time_start);
165     if (sendto (metafd, data, strlen (data), 0, (struct sockaddr *) &sock, sizeof (sock)) < 0)
166     {
167     LOG (llevDebug, "metaserver_update: sendto failed, err = %d\n", errno);
168 elmex 1.1 }
169     }