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

# Content
1
2 /*
3 * static char *rcsid_metaserver_c =
4 * "$Id: metaserver.C,v 1.2 2006-08-29 08:01:38 root Exp $";
5 */
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 #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
45 #endif /* end win32 */
46
47 static int metafd = -1;
48 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 void
59 metaserver_init (void)
60 {
61
62 #ifdef WIN32 /* ***win32 metaserver_init(): init win32 socket */
63 struct hostent *hostbn;
64 int temp = 1;
65 #endif
66
67 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 }
84 memcpy (&sock.sin_addr, hostbn->h_addr, hostbn->h_length);
85 }
86 #ifdef WIN32 /* ***win32 metaserver_init(): init win32 socket */
87 ioctlsocket (metafd, FIONBIO, &temp);
88 #else
89 fcntl (metafd, F_SETFL, O_NONBLOCK);
90 #endif
91 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 }
109
110 #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
115 if (hostbn == (struct hostent *) NULL)
116 {
117 #else
118 if (getdomainname (domain, MAX_BUF - 1))
119 {
120 #endif /* win32 */
121 LOG (llevDebug, "metaserver_init: getdomainname failed - will not report hostname\n");
122 return;
123 }
124 /* Potential overrun here but unlikely to occur */
125 sprintf (settings.meta_host, "%s.%s", hostname, domain);
126 }
127 }
128
129 /**
130 * Updates our info in the metaserver
131 */
132 void
133 metaserver_update (void)
134 {
135 char data[MAX_BUF], num_players = 0;
136 player *pl;
137
138 if (metafd == -1)
139 return; /* No valid connection */
140
141 /* 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 }
169 }