|
Atrinik Client 2.5
|
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 00120 #include <global.h> 00121 00123 static CURLSH *handle_share = NULL; 00125 static SDL_mutex *handle_share_mutex = NULL; 00126 00135 static size_t curl_callback(void *ptr, size_t size, size_t nmemb, void *data) 00136 { 00137 size_t realsize = size * nmemb; 00138 curl_data *mem = (curl_data *) data; 00139 00140 SDL_LockMutex(mem->mutex); 00141 mem->memory = realloc(mem->memory, mem->size + realsize + 1); 00142 00143 if (mem->memory) 00144 { 00145 memcpy(&(mem->memory[mem->size]), ptr, realsize); 00146 mem->size += realsize; 00147 mem->memory[mem->size] = '\0'; 00148 } 00149 00150 SDL_UnlockMutex(mem->mutex); 00151 00152 return realsize; 00153 } 00154 00161 int curl_connect(void *c_data) 00162 { 00163 curl_data *data = (curl_data *) c_data; 00164 char user_agent[MAX_BUF], version[MAX_BUF]; 00165 CURL *handle; 00166 CURLcode res; 00167 long http_code; 00168 00169 package_get_version_full(version, sizeof(version)); 00170 00171 /* Store user agent for cURL, including if this is GNU/Linux build of client 00172 * or Windows one. */ 00173 #if defined(LINUX) 00174 snprintf(user_agent, sizeof(user_agent), "Atrinik Client (GNU/Linux)/%s (%d)", version, SOCKET_VERSION); 00175 #elif defined(WIN32) 00176 snprintf(user_agent, sizeof(user_agent), "Atrinik Client (Win32)/%s (%d)", version, SOCKET_VERSION); 00177 #else 00178 snprintf(user_agent, sizeof(user_agent), "Atrinik Client (Unknown)/%s (%d)", version, SOCKET_VERSION); 00179 #endif 00180 00181 /* Init "easy" cURL */ 00182 handle = curl_easy_init(); 00183 00184 if (!handle) 00185 { 00186 SDL_LockMutex(data->mutex); 00187 data->status = -1; 00188 SDL_UnlockMutex(data->mutex); 00189 return -1; 00190 } 00191 00192 /* Set connection timeout. */ 00193 curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT, CURL_TIMEOUT); 00194 /* Disable signals since we are in a thread. See 00195 * http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTNOSIGNAL 00196 * for details. */ 00197 curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1); 00198 00199 SDL_LockMutex(data->mutex); 00200 curl_easy_setopt(handle, CURLOPT_URL, data->url); 00201 curl_easy_setopt(handle, CURLOPT_REFERER, data->url); 00202 curl_easy_setopt(handle, CURLOPT_SHARE, handle_share); 00203 SDL_UnlockMutex(data->mutex); 00204 00205 /* The callback function. */ 00206 curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, curl_callback); 00207 curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void *) data); 00208 00209 /* Set user agent. */ 00210 curl_easy_setopt(handle, CURLOPT_USERAGENT, user_agent); 00211 00212 /* Get the data. */ 00213 res = curl_easy_perform(handle); 00214 00215 if (res) 00216 { 00217 LOG(llevBug, "curl_thread(): curl_easy_perform() got error %d (%s).\n", res, curl_easy_strerror(res)); 00218 curl_easy_cleanup(handle); 00219 SDL_LockMutex(data->mutex); 00220 data->status = -1; 00221 SDL_UnlockMutex(data->mutex); 00222 return -1; 00223 } 00224 00225 curl_easy_getinfo(handle, CURLINFO_HTTP_CODE, &http_code); 00226 00227 if (http_code != 200) 00228 { 00229 SDL_LockMutex(data->mutex); 00230 data->status = -1; 00231 SDL_UnlockMutex(data->mutex); 00232 return -1; 00233 } 00234 00235 curl_easy_cleanup(handle); 00236 00237 SDL_LockMutex(data->mutex); 00238 data->status = 1; 00239 SDL_UnlockMutex(data->mutex); 00240 00241 return 1; 00242 } 00243 00248 curl_data *curl_data_new(const char *url) 00249 { 00250 curl_data *data = malloc(sizeof(curl_data)); 00251 00252 /* Store the url. */ 00253 data->url = strdup(url); 00254 data->memory = NULL; 00255 data->size = 0; 00256 data->status = 0; 00257 /* Create a mutex to protect the structure. */ 00258 data->mutex = SDL_CreateMutex(); 00259 00260 return data; 00261 } 00262 00271 curl_data *curl_download_start(const char *url) 00272 { 00273 curl_data *data = curl_data_new(url); 00274 00275 /* Create a new thread. */ 00276 data->thread = SDL_CreateThread(curl_connect, data); 00277 00278 if (!data->thread) 00279 { 00280 LOG(llevError, "curl_download_start(): Thread creation failed.\n"); 00281 } 00282 00283 return data; 00284 } 00285 00291 sint8 curl_download_finished(curl_data *data) 00292 { 00293 sint8 status; 00294 00295 SDL_LockMutex(data->mutex); 00296 status = data->status; 00297 SDL_UnlockMutex(data->mutex); 00298 00299 return status; 00300 } 00301 00305 void curl_data_free(curl_data *data) 00306 { 00307 /* Still downloading? Kill the thread. */ 00308 if (curl_download_finished(data) == 0) 00309 { 00310 SDL_KillThread(data->thread); 00311 } 00312 00313 if (data->memory) 00314 { 00315 free(data->memory); 00316 } 00317 00318 SDL_DestroyMutex(data->mutex); 00319 free(data->url); 00320 free(data); 00321 } 00322 00325 static void curl_share_lock(CURL *handle, curl_lock_data data, curl_lock_access lock_access, void *userptr) 00326 { 00327 (void) handle; 00328 (void) data; 00329 (void) lock_access; 00330 SDL_LockMutex(userptr); 00331 } 00332 00335 static void curl_share_unlock(CURL *handle, curl_lock_data data, void *userptr) 00336 { 00337 (void) handle; 00338 (void) data; 00339 SDL_UnlockMutex(userptr); 00340 } 00341 00344 void curl_init() 00345 { 00346 curl_global_init(CURL_GLOBAL_ALL); 00347 handle_share_mutex = SDL_CreateMutex(); 00348 00349 handle_share = curl_share_init(); 00350 curl_share_setopt(handle_share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); 00351 curl_share_setopt(handle_share, CURLSHOPT_USERDATA, handle_share_mutex); 00352 curl_share_setopt(handle_share, CURLSHOPT_LOCKFUNC, curl_share_lock); 00353 curl_share_setopt(handle_share, CURLSHOPT_UNLOCKFUNC, curl_share_unlock); 00354 } 00355 00358 void curl_deinit() 00359 { 00360 curl_share_cleanup(handle_share); 00361 SDL_DestroyMutex(handle_share_mutex); 00362 curl_global_cleanup(); 00363 }
1.7.4