Atrinik Client 2.5
client/metaserver.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 
00033 static const char *const metaservers[] = {"http://meta.atrinik.org/", "http://atokar.is-a-geek.net/", "http://www.wordowl.com/misc/atrinik/"};
00035 #define NUM_METASERVERS (sizeof(metaservers) / sizeof(metaservers[0]))
00036 
00038 static int metaserver_connecting;
00040 static SDL_mutex *metaserver_connecting_mutex;
00042 static server_struct *start_server;
00044 static size_t server_count;
00046 static SDL_mutex *start_server_mutex;
00048 static uint8 enabled;
00049 
00052 void metaserver_init()
00053 {
00054     /* Initialize the data. */
00055     start_server = NULL;
00056     server_count = 0;
00057     metaserver_connecting = 1;
00058     enabled = 1;
00059 
00060     /* Initialize mutexes. */
00061     metaserver_connecting_mutex = SDL_CreateMutex();
00062     start_server_mutex = SDL_CreateMutex();
00063 }
00064 
00067 void metaserver_disable()
00068 {
00069     enabled = 0;
00070     metaserver_connecting = 0;
00071 }
00072 
00076 static void parse_metaserver_data(char *info)
00077 {
00078     char *tmp[6];
00079 
00080     if (!info || split_string(info, tmp, sizeof(tmp) / sizeof(*tmp), ':') != 6)
00081     {
00082         return;
00083     }
00084 
00085     metaserver_add(tmp[0], atoi(tmp[1]), tmp[2], atoi(tmp[3]), tmp[4], tmp[5]);
00086 }
00087 
00092 server_struct *server_get_id(size_t num)
00093 {
00094     server_struct *node;
00095     size_t i = 0;
00096 
00097     SDL_LockMutex(start_server_mutex);
00098     node = start_server;
00099 
00100     for (i = 0; node; i++, node = node->next)
00101     {
00102         if (i == num)
00103         {
00104             break;
00105         }
00106     }
00107 
00108     SDL_UnlockMutex(start_server_mutex);
00109     return node;
00110 }
00111 
00115 size_t server_get_count()
00116 {
00117     size_t count;
00118 
00119     SDL_LockMutex(start_server_mutex);
00120     count = server_count;
00121     SDL_UnlockMutex(start_server_mutex);
00122     return count;
00123 }
00124 
00129 int ms_connecting(int val)
00130 {
00131     int connecting;
00132 
00133     SDL_LockMutex(metaserver_connecting_mutex);
00134     connecting = metaserver_connecting;
00135 
00136     /* More useful to return the old value than the one we're setting. */
00137     if (val != -1)
00138     {
00139         metaserver_connecting = val;
00140     }
00141 
00142     SDL_UnlockMutex(metaserver_connecting_mutex);
00143     return connecting;
00144 }
00145 
00148 void metaserver_clear_data()
00149 {
00150     server_struct *node, *tmp;
00151 
00152     SDL_LockMutex(start_server_mutex);
00153     node = start_server;
00154 
00155     while (node)
00156     {
00157         tmp = node->next;
00158 
00159         free(node->ip);
00160         free(node->name);
00161         free(node->version);
00162         free(node->desc);
00163         free(node);
00164 
00165         node = tmp;
00166     }
00167 
00168     start_server = NULL;
00169     server_count = 0;
00170     SDL_UnlockMutex(start_server_mutex);
00171 }
00172 
00182 void metaserver_add(const char *ip, int port, const char *name, int player, const char *version, const char *desc)
00183 {
00184     server_struct *node = (server_struct *) malloc(sizeof(server_struct));
00185 
00186     memset(node, 0, sizeof(server_struct));
00187     node->player = player;
00188     node->port = port;
00189     node->ip = strdup(ip);
00190     node->name = strdup(name);
00191     node->version = strdup(version);
00192     node->desc = strdup(desc);
00193 
00194     SDL_LockMutex(start_server_mutex);
00195     node->next = start_server;
00196     start_server = node;
00197     server_count++;
00198     SDL_UnlockMutex(start_server_mutex);
00199 }
00200 
00209 int metaserver_thread(void *dummy)
00210 {
00211     size_t metaserver_id;
00212     curl_data *data;
00213 
00214     (void) dummy;
00215 
00216     /* Go through all the metaservers in the list */
00217     for (metaserver_id = 0; metaserver_id < NUM_METASERVERS; metaserver_id++)
00218     {
00219         data = curl_data_new(metaservers[metaserver_id]);
00220 
00221         /* If the connection succeeded, break out */
00222         if (curl_connect(data) == 1 && data->memory)
00223         {
00224             char *buf = strdup(data->memory), *cp, *saveptr = NULL;
00225 
00226             cp = strtok_r(buf, "\n", &saveptr);
00227 
00228             /* Loop through all the lines returned */
00229             while (cp)
00230             {
00231                 parse_metaserver_data(cp);
00232                 cp = strtok_r(NULL, "\n", &saveptr);
00233             }
00234 
00235             free(buf);
00236             curl_data_free(data);
00237             break;
00238         }
00239 
00240         curl_data_free(data);
00241     }
00242 
00243     SDL_LockMutex(metaserver_connecting_mutex);
00244     /* We're not connecting anymore. */
00245     metaserver_connecting = 0;
00246     SDL_UnlockMutex(metaserver_connecting_mutex);
00247     return 0;
00248 }
00249 
00254 void metaserver_get_servers()
00255 {
00256     SDL_Thread *thread;
00257 
00258     if (!enabled)
00259     {
00260         return;
00261     }
00262 
00263     SDL_LockMutex(metaserver_connecting_mutex);
00264     metaserver_connecting = 1;
00265     SDL_UnlockMutex(metaserver_connecting_mutex);
00266 
00267     thread = SDL_CreateThread(metaserver_thread, NULL);
00268 
00269     if (!thread)
00270     {
00271         LOG(llevError, "metaserver_get_servers(): Thread creation failed.\n");
00272     }
00273 }