/** * Wait for the socket threads to finish. * * Closes the socket first, if it hasn't already been done. */ void socket_thread_stop(void) { client_socket_close(&csocket); SDL_WaitThread(output_thread, NULL); SDL_WaitThread(input_thread, NULL); input_thread = output_thread = NULL; }
/** * Deinitialize the client sockets. */ void client_socket_deinitialize(void) { if (csocket.sc != NULL) { client_socket_close(&csocket); } #ifdef WIN32 WSACleanup(); #endif }
void wid_game_map_go_back_to_editor (void) { client_socket_close(0, 0); wid_game_map_client_hide(); wid_game_map_client_wid_destroy(); level_pos_t level_pos; level_pos.x = 66; level_pos.y = 66; wid_editor(level_pos); }
/** * Worker for the writer thread. It waits for enqueued outgoing packets * and sends them to the server as fast as it can. * * If any error is detected, the socket is closed and the thread exits. It is * up to them main thread to detect this and join() the worker threads. */ static int writer_thread_loop(void *dummy) { command_buffer *buf = NULL; while (!abort_thread) { SDL_LockMutex(output_buffer_mutex); while (output_queue_start == NULL && !abort_thread) { SDL_CondWait(output_buffer_cond, output_buffer_mutex); } buf = command_buffer_dequeue(&output_queue_start, &output_queue_end); SDL_UnlockMutex(output_buffer_mutex); size_t written = 0; while (buf != NULL && written < buf->len && !abort_thread) { size_t amt; bool success = socket_write(csocket.sc, (const void *) (buf->data + written), buf->len - written, &amt); if (!success) { break; } written += amt; network_graph_update(NETWORK_GRAPH_TYPE_GAME, NETWORK_GRAPH_TRAFFIC_TX, amt); } if (buf != NULL) { command_buffer_free(buf); buf = NULL; } } client_socket_close(&csocket); return 0; }
static int reader_thread_loop(void *dummy) { static uint8_t *readbuf = NULL; static int readbuf_size = 256; int readbuf_len = 0; int header_len = 0; int cmd_len = -1; if (!readbuf) { readbuf = emalloc(readbuf_size); } while (!abort_thread) { int toread; /* First, try to read a command length sequence */ if (readbuf_len < 2) { /* Three-byte length? */ if (readbuf_len > 0 && (readbuf[0] & 0x80)) { toread = 3 - readbuf_len; } else { toread = 2 - readbuf_len; } } else if (readbuf_len == 2 && (readbuf[0] & 0x80)) { toread = 1; } else { /* If we have a finished header, get the packet size from it. */ if (readbuf_len <= 3) { uint8_t *p = readbuf; header_len = (*p & 0x80) ? 3 : 2; cmd_len = 0; if (header_len == 3) { cmd_len += ((int) (*p++) & 0x7f) << 16; } cmd_len += ((int) (*p++)) << 8; cmd_len += ((int) (*p++)); } toread = cmd_len + header_len - readbuf_len; if (readbuf_len + toread > readbuf_size) { uint8_t *tmp = readbuf; readbuf_size = readbuf_len + toread; readbuf = emalloc(readbuf_size); memcpy(readbuf, tmp, readbuf_len); efree(tmp); } } size_t amt; bool success = socket_read(csocket.sc, (void *) (readbuf + readbuf_len), toread, &amt); if (!success) { break; } readbuf_len += amt; network_graph_update(NETWORK_GRAPH_TYPE_GAME, NETWORK_GRAPH_TRAFFIC_RX, amt); /* Finished with a command? */ if (readbuf_len == cmd_len + header_len && !abort_thread) { command_buffer *buf = command_buffer_new(readbuf_len - header_len, readbuf + header_len); SDL_LockMutex(input_buffer_mutex); command_buffer_enqueue(buf, &input_queue_start, &input_queue_end); SDL_CondSignal(input_buffer_cond); SDL_UnlockMutex(input_buffer_mutex); cmd_len = -1; header_len = 0; readbuf_len = 0; } } client_socket_close(&csocket); if (readbuf != NULL) { efree(readbuf); readbuf = NULL; } return -1; }