void start_server_discovery() { if(server_discovery_started) return; selected_server = -1; top_server_visible = 0; num_servers_unqueried = 0; num_servers_queried = 0; num_servers_found = 0; num_servers_new_proto = 0; struct server_t *cserver = rumoured_servers; while(cserver) { num_servers_unqueried++; LL_ADD_TAIL(struct server_t, &unqueried_servers, cserver); LL_NEXT(cserver); } pipe(servers_info_pipe); output_server_query(); servers_first_output = get_wall_time(); servers_next_output = 1.0 / SERVER_QUERY_OUTPUT_RATE + servers_first_output; pipe(servers_kill_pipe); pthread_create(&servers_thread_id, NULL, servers_thread, NULL); server_discovery_started = 1; }
void save_rumoured_servers() { struct string_t *filename = new_string_string(emergence_home_dir); #ifdef EMCLIENT string_cat_text(filename, "/rumoured.client"); #endif #ifdef EMSERVER string_cat_text(filename, "/rumoured.server."); string_cat_int(filename, net_listen_port); #endif FILE *file = fopen(filename->text, "w"); free_string(filename); if(!file) return; struct server_t *server = rumoured_servers; while(server) { char addr[17]; if(inet_ntop(AF_INET, &server->ip, addr, 17)) fprintf(file, "%s:%hu %u\n", addr, ntohs(server->port), (uint32_t)server->time); LL_NEXT(server); } fclose(file); }
void process_server_info(struct sockaddr_in *sockaddr, struct buffer_t *buffer) { struct queried_server_t *cserver = queried_servers; struct found_server_t new_server_info; uint16_t servers; struct sockaddr_in s; time_t t; int proto_ver; while(cserver) { if(cserver->ip == sockaddr->sin_addr.s_addr && cserver->port == sockaddr->sin_port) { proto_ver = buffer_read_uint8(buffer); if(proto_ver != EM_PROTO_VER) { if(proto_ver > EM_PROTO_VER) num_servers_new_proto++; break; } new_server_info.ip = sockaddr->sin_addr.s_addr; new_server_info.port = sockaddr->sin_port; new_server_info.ping = get_wall_time() - cserver->stamp; new_server_info.host_name = buffer_read_string(buffer); new_server_info.map_name = buffer_read_string(buffer); new_server_info.num_players = buffer_read_uint8(buffer); new_server_info.max_players = buffer_read_uint8(buffer); new_server_info.authenticating = buffer_read_uint8(buffer); add_new_found_server(&new_server_info); add_new_server(&rumoured_servers, sockaddr, time(NULL)); servers = buffer_read_uint16(buffer); while(servers--) { s.sin_addr.s_addr = buffer_read_uint32(buffer); s.sin_port = buffer_read_uint16(buffer); t = buffer_read_uint32(buffer); if(!find_queried_server(s.sin_addr.s_addr, s.sin_port)) { if(add_new_server(&unqueried_servers, &s, t)) num_servers_unqueried++; } } break; } LL_NEXT(cserver); } }
void server_enter(int state) { if(!state) return; pthread_mutex_lock(&servers_mutex); struct found_server_t *cserver = found_servers; int i = 0; while(cserver) { if(i == selected_server) { if(!r_DrawConsole) console_toggle(); em_connect(cserver->ip, cserver->port); goto end; } LL_NEXT(cserver); i++; } end: pthread_mutex_unlock(&servers_mutex); }
/* * sync() * Write dirty buffers to disk * * If handle is not NULL, sync all buffers dirtied with this handle. * Otherwise sync all dirty buffers. */ void sync_bufs(void *handle) { struct llist *l; uint x; for (l = LL_NEXT(&allbufs); l != &allbufs; l = LL_NEXT(l)) { struct buf *b = l->l_data; /* * Not dirty--easy */ if (!(b->b_flags & B_DIRTY)) { continue; } /* * Interlock */ get(b); /* * Not dirty after interlock--still easy */ if (!(b->b_flags & B_DIRTY)) { continue; } /* * No handle, just sync dirty buffers */ if (!handle) { qio(b, Q_FLUSHBUF); continue; } /* * Check for match. */ for (x = 0; x < b->b_nhandle; ++x) { if (b->b_handles[x] == handle) { qio(b, Q_FLUSHBUF); break; } } } }
int count_servers() { int c = 0; struct server_t *cserver = rumoured_servers; while(cserver) { c++; LL_NEXT(cserver); } return c; }
struct queried_server_t *find_queried_server(uint32_t ip, uint16_t port) { struct queried_server_t *cserver = queried_servers; while(cserver) { if(cserver->ip == ip && cserver->port == port) return cserver; LL_NEXT(cserver); } return NULL; }
// // get a new event structure from the freelist, // initialize it, and insert it into the timeoutq // void create_timeoutq_event(int timeout, int repeat, pfv_t function, unsigned int data) { struct event *x; struct event *tempptr; x = (struct event*)LL_POP(freelist); x->timeout = timeout; x->repeat_interval = repeat; x->go = function; x->data = data; if(LL_IS_EMPTY(timeoutq)) LL_PUSH(timeoutq, x); //x=timeoutq=head of list //insert it correct place and update timout else LL_EACH(timeoutq,tempptr,struct event) { if(x->timeout <= tempptr->timeout) { tempptr->timeout -= x->timeout; LL_L_INSERT(tempptr,x); break; } else { if(LL_NEXT(timeoutq,tempptr) == NULL) { x->timeout -= tempptr->timeout; LL_R_INSERT(tempptr,x); break; } else { x->timeout -= tempptr->timeout; continue; //go to the next node } } } //update then_usec // then_usec = now_usec() - then_usec; }
void emit_servers(uint32_t conn) { net_emit_uint8(conn, EMMSG_SERVERS); int servers = min(45, count_servers()); net_emit_uint32(conn, servers); struct server_t *cserver = rumoured_servers; while(servers--) { net_emit_uint32(conn, cserver->ip); net_emit_uint16(conn, cserver->port); net_emit_uint32(conn, cserver->time); LL_NEXT(cserver); } net_emit_end_of_stream(conn); }
int add_new_server(struct server_t **server0, struct sockaddr_in *sockaddr, time_t t) { int found = 0; // see if this server is already in the list struct server_t *cserver = *server0, *temp, *next; while(cserver) { if(cserver->ip == sockaddr->sin_addr.s_addr && cserver->port == sockaddr->sin_port) { next = cserver->next; LL_REMOVE(struct server_t, server0, cserver); cserver = next; found = 1; continue; } LL_NEXT(cserver); } struct server_t server = { sockaddr->sin_addr.s_addr, sockaddr->sin_port, t }; // if rumoured_servers is NULL, then create new server here if(!*server0) { *server0 = malloc(sizeof(struct server_t)); memcpy(*server0, &server, sizeof(struct server_t)); (*server0)->next = NULL; goto end; } if((*server0)->time < t) { temp = *server0; *server0 = malloc(sizeof(struct server_t)); memcpy(*server0, &server, sizeof(struct server_t)); (*server0)->next = temp; goto end; } cserver = *server0; while(cserver->next) { if(cserver->next->time < t) { temp = cserver->next; cserver->next = malloc(sizeof(struct server_t)); cserver = cserver->next; memcpy(cserver, &server, sizeof(struct server_t)); cserver->next = temp; goto end; } LL_NEXT(cserver); } cserver->next = malloc(sizeof(struct server_t)); cserver = cserver->next; memcpy(cserver, &server, sizeof(struct server_t)); cserver->next = NULL; end: ; return !found; }
/* * tmpfs_readdir() * Do reads on directory entries */ static void tmpfs_readdir(struct msg *m, struct file *f) { char *buf; uint len, pos, bufcnt; struct llist *l; struct openfile *o; extern struct llist files; /* * Get a buffer of the requested size, but put a sanity * cap on it. */ len = m->m_arg; if (len > 256) { len = 256; } if ((buf = malloc(len+1)) == 0) { msg_err(m->m_sender, strerror()); return; } buf[0] = '\0'; /* * Assemble as many names as will fit, starting at * given byte offset. We assume the caller's position * always advances in units of a whole directory entry. */ bufcnt = pos = 0; for (l = LL_NEXT(&files); l != &files; l = LL_NEXT(l)) { uint slen; /* * Point to next file. Get its length. */ o = l->l_data; slen = strlen(o->o_name)+1; /* * If we've reached an offset the caller hasn't seen * yet, assemble the entry into the buffer. */ if (pos >= f->f_pos) { /* * No more room in buffer--return results */ if (slen >= len) { break; } /* * Put string with newline at end of buffer */ sprintf(buf + bufcnt, "%s\n", o->o_name); /* * Update counters */ len -= slen; bufcnt += slen; } /* * Update position */ pos += slen; } /* * Send back results */ m->m_buf = buf; m->m_arg = m->m_buflen = bufcnt; m->m_nseg = ((bufcnt > 0) ? 1 : 0); m->m_arg1 = 0; msg_reply(m->m_sender, m); free(buf); f->f_pos = pos; }
void render_servers() { if(r_DrawConsole) return; if(server_discovery_started) { pthread_mutex_lock(&servers_mutex); blit_text(0, vid_height * 5 / 6, 0xff, 0xff, 0xff, s_backbuffer, "Servers unqueried:"); blit_text(150, vid_height * 5 / 6, 0xff, 0xff, 0xff, s_backbuffer, "%u", num_servers_unqueried); blit_text(0, vid_height * 5 / 6 + 14, 0xff, 0xff, 0xff, s_backbuffer, "Servers queried:"); blit_text(150, vid_height * 5 / 6 + 14, 0xff, 0xff, 0xff, s_backbuffer, "%u", num_servers_queried); blit_text(0, vid_height * 5 / 6 + 28, 0xff, 0xff, 0xff, s_backbuffer, "Servers found:"); blit_text(150, vid_height * 5 / 6 + 28, 0xff, 0xff, 0xff, s_backbuffer, "%u", num_servers_found); if(num_servers_new_proto) { blit_text(0, vid_height * 5 / 6 + 42, 0xff, 0xff, 0xff, s_backbuffer, "Servers found requiring new version:"); blit_text(275, vid_height * 5 / 6 + 42, 0xff, 0xff, 0xff, s_backbuffer, "%u", num_servers_new_proto); } blit_text(50, vid_height / 6, 0xff, 0xff, 0xff, s_backbuffer, "Server"); blit_text(50 + 264, vid_height / 6, 0xff, 0xff, 0xff, s_backbuffer, "Port"); blit_text(50 + 264 + 64, vid_height / 6, 0xff, 0xff, 0xff, s_backbuffer, "Ping"); blit_text(50 + 264 + 64 + 64, vid_height / 6, 0xff, 0xff, 0xff, s_backbuffer, "Key"); blit_text(50 + 264 + 64 + 64, vid_height / 6 + 16, 0xff, 0xff, 0xff, s_backbuffer, "Required?"); blit_text(50 + 32, vid_height / 6 + 14, 0xff, 0xff, 0xff, s_backbuffer, "Map"); blit_text(50 + 32 + 264, vid_height / 6 + 14, 0xff, 0xff, 0xff, s_backbuffer, "Players"); struct found_server_t *cserver = found_servers; int i = 1; int server = 0; while(cserver && i <= 8) { if(server >= top_server_visible) { blit_text(50, vid_height / 6 + i * 32, 0xef, 0x6f, 0xff, s_backbuffer, "%s", cserver->host_name->text); blit_text(50 + 264, vid_height / 6 + i * 32, 0xef, 0x6f, 0xff, s_backbuffer, "%u", ntohs(cserver->port)); blit_text(50 + 264 + 64, vid_height / 6 + i * 32, 0xef, 0x6f, 0xff, s_backbuffer, "%.2fms", cserver->ping * 1000.0); if(cserver->authenticating) { blit_text_centered(50 + 264 + 64 + 64 + 12, vid_height / 6 + i * 32 + 6, 0xef, 0x6f, 0xff, s_backbuffer, "Y"); } blit_text(50 + 32, vid_height / 6 + i * 32 + 14, 0xef, 0x6f, 0xff, s_backbuffer, "%s", cserver->map_name->text); blit_text(50 + 32 + 264, vid_height / 6 + i * 32 + 14, 0xef, 0x6f, 0xff, s_backbuffer, "%u/%u", cserver->num_players, cserver->max_players); if(server == selected_server) { struct blit_params_t params; params.red = 0x54; params.green = 0xa6; params.blue = 0xf9; params.alpha = 0x7f; params.dest = s_backbuffer; params.dest_x = 48; params.dest_y = vid_height / 6 + i * 32 - 2; params.width = 475; params.height = 32; alpha_draw_rect(¶ms); } i++; } LL_NEXT(cserver); server++; } pthread_mutex_unlock(&servers_mutex); } }
void add_new_found_server(struct found_server_t *found_server) { // see if this server is already in the list struct found_server_t *cserver = found_servers, *next; int i; while(cserver) { if(cserver->ip == found_server->ip && cserver->port == found_server->port) return; LL_NEXT(cserver); } num_servers_found++; // if rumoured_servers is NULL, then create new server here if(!found_servers) { found_servers = malloc(sizeof(struct found_server_t)); memcpy(found_servers, found_server, sizeof(struct found_server_t)); (found_servers)->next = NULL; return; } if((found_servers)->ping > found_server->ping) { next = found_servers; found_servers = malloc(sizeof(struct found_server_t)); memcpy(found_servers, found_server, sizeof(struct found_server_t)); (found_servers)->next = next; if(selected_server != -1) server_down_in_lock(); return; } cserver = found_servers; i = 1; while(cserver->next) { if(cserver->next->ping > found_server->ping) { next = cserver->next; cserver->next = malloc(sizeof(struct found_server_t)); cserver = cserver->next; memcpy(cserver, found_server, sizeof(struct found_server_t)); cserver->next = next; if(selected_server != -1 && i <= selected_server) server_down_in_lock(); return; } LL_NEXT(cserver); i++; } cserver->next = malloc(sizeof(struct found_server_t)); cserver = cserver->next; memcpy(cserver, found_server, sizeof(struct found_server_t)); cserver->next = NULL; }