DWORD WINAPI AutoupdateProc(void * lpParameter) { double lastupdatetime = -1; while (autoupdate_serverinfo) { double time = Sys_DoubleTime(); if ((sb_liveupdate.integer > 0) && time >= lastupdatetime + sb_liveupdate.integer && key_dest == key_menu /* todo: add "on server list tab" condition here */) { server_data *serv; Sys_SemWait(&serverinfo_semaphore); serv = autoupdate_server; if (serv != NULL) { GetServerInfo(serv); lastupdatetime = time; } Sys_SemPost(&serverinfo_semaphore); } Sys_MSleep(1000); // we don't need nor allow updates faster than 1 second anyway } return 0; }
void Rebuild_Servers_List(void) { int i; int suppressed_servers = 0; int server_limit = sizeof(servers) / sizeof(servers[0]); serversn = 0; rebuild_servers_list = 0; Sys_SemWait(&serverlist_semaphore); for (i=0; i < sourcesn; i++) { if (sources[i]->checked) { int j; for (j=0; j < sources[i]->serversn; j++) { int k; qbool found_duplicate = false; // Try and find a matching address for (k = 0; k < serversn && k < server_limit; k++) { if (!memcmp(&(servers[k]->address), &(sources[i]->servers[j]->address), sizeof(netadr_t))) { found_duplicate = true; break; } } if (! found_duplicate) { // if not on list yet if (serversn < server_limit) { servers[serversn++] = sources[i]->servers[j]; } else { ++suppressed_servers; } } } } } if (suppressed_servers) { Con_Printf("Warning: suppressed %d servers\n", suppressed_servers); } resort_servers = 1; rebuild_all_players = 1; Servers_pos = 0; serversn_passed = serversn; Sys_SemPost(&serverlist_semaphore); }
/// Creates whole graph structure for looking up shortest paths to servers (ping-wise). /// /// Grabs data from the server browser and then from the proxies. void SB_PingTree_Build(void) { if (building_pingtree) { Com_Printf("Ping Tree is still being built...\n"); return; } // no race condition here, as this must always get executed by the main thread building_pingtree = true; Com_Printf("Building the Ping Tree...\n"); // first quick phase is initialization + quick read of data from the server browser SB_PingTree_Phase1(); // second longer phase is querying the proxies for their ping data + dijkstra algo Sys_SemWait(&phase2thread_lock); Sys_CreateThread(SB_PingTree_Phase2, NULL); }
void SB_PingTree_Shutdown(void) { Sys_SemWait(&phase2thread_lock); Sys_SemDestroy(&phase2thread_lock); }
void Update_Source(source_data *s) { int i; qbool should_dump = false; server_data *servers[MAX_SERVERS]; int serversn = 0; if (s->type == type_dummy) return; if (s->type == type_file) { // read servers from file char name[1024]; snprintf(name, sizeof (name), "sb/%s", s->address.filename); should_dump = Update_Source_From_File(s, name, servers, &serversn); GetLocalTime(&(s->last_update)); } if (s->type == type_url) { SB_Update_Source_From_URL(s, servers, &serversn); } if (s->type == type_master) { // get servers from master server char request[] = {'c', '\n', '\0'}; socket_t newsocket; struct sockaddr_storage server; int ret = 0, i; unsigned char answer[10000]; fd_set fd; struct timeval tv; int trynum; int timeout; newsocket = UDP_OpenSocket(PORT_ANY); // so we have a socket // send status request for (trynum=0; trynum < sb_masterretries.value; trynum++) { NetadrToSockadr (&(s->address.address), &server); ret = sendto (newsocket, request, sizeof(request), 0, (struct sockaddr *)&server, sizeof(server) ); } if (ret < 0) return; timeout = Sys_DoubleTime() + (sb_mastertimeout.value / 1000.0); while (Sys_DoubleTime() < timeout) { //fd.fd_count = 1; //fd.fd_array[0] = newsocket; FD_ZERO(&fd); FD_SET(newsocket, &fd); tv.tv_sec = 0; tv.tv_usec = 1000 * 1.5 * sb_mastertimeout.value; // multiply timeout by 1.5 ret = select(newsocket+1, &fd, NULL, NULL, &tv); // get answer if (ret > 0) ret = recvfrom (newsocket, (char *) answer, 10000, 0, NULL, NULL); if (ret > 0 && ret < 10000) { answer[ret] = 0; if (memcmp(answer, "\xff\xff\xff\xff\x64\x0a", 6)) { closesocket(newsocket); return; } // create servers avoiding duplicates for (i=6; i+5 < ret; i+=6) { char buf[32]; server_data* server; qbool exists = false; int j; snprintf(buf, sizeof (buf), "%u.%u.%u.%u:%u", (int)answer[i+0], (int)answer[i+1], (int)answer[i+2], (int)answer[i+3], 256 * (int)answer[i+4] + (int)answer[i+5]); server = Create_Server(buf); for (j=0; j<serversn; j++) { if (NET_CompareAdr(servers[j]->address, server->address)) { exists = true; break; } } if (!exists) servers[serversn++] = server; else Delete_Server(server); } } } closesocket(newsocket); } Sys_SemWait(&serverlist_semaphore); // copy all servers to source list if (serversn > 0) { Reset_Source(s); s->servers = (server_data **) Q_malloc((serversn + (s->type==type_file ? MAX_UNBOUND : 0)) * sizeof(server_data *)); for (i=0; i < serversn; i++) s->servers[i] = servers[i]; s->serversn = serversn; if (s->checked) rebuild_servers_list = 1; if (sb_mastercache.value) { DumpSource(s); should_dump = false; } GetLocalTime(&(s->last_update)); } else if (s->type == type_file) { Reset_Source(s); s->servers = (server_data **) Q_malloc((serversn + (s->type==type_file ? MAX_UNBOUND : 0)) * sizeof(server_data *)); } Sys_SemPost(&serverlist_semaphore); if (should_dump) DumpSource(s); //Com_Printf ("Updating %15.15s: %d servers\n", s->name, serversn); }