static void _close_active(struct mread_pool * self) { int id = self->active; struct socket * s = &self->sockets[id]; ringbuffer_free(self->rb, s->temp); ringbuffer_free(self->rb, s->node); _close_client(self, id); }
void EditorFileServer::_subthread_start(void *s) { ClientData *cd = (ClientData *)s; cd->connection->set_nodelay(true); uint8_t buf4[8]; Error err = cd->connection->get_data(buf4, 4); if (err != OK) { _close_client(cd); ERR_FAIL_COND(err != OK); } int passlen = decode_uint32(buf4); if (passlen > 512) { _close_client(cd); ERR_FAIL_COND(passlen > 512); } else if (passlen > 0) { Vector<char> passutf8; passutf8.resize(passlen + 1); err = cd->connection->get_data((uint8_t *)passutf8.ptr(), passlen); if (err != OK) { _close_client(cd); ERR_FAIL_COND(err != OK); } passutf8[passlen] = 0; String s; s.parse_utf8(passutf8.ptr()); if (s != cd->efs->password) { encode_uint32(ERR_INVALID_DATA, buf4); cd->connection->put_data(buf4, 4); OS::get_singleton()->delay_usec(1000000); _close_client(cd); ERR_PRINT("CLIENT PASSWORD MISMATCH"); ERR_FAIL(); } } else { if (cd->efs->password != "") { encode_uint32(ERR_INVALID_DATA, buf4); cd->connection->put_data(buf4, 4); OS::get_singleton()->delay_usec(1000000); _close_client(cd); ERR_PRINT("CLIENT PASSWORD MISMATCH (should be empty!)"); ERR_FAIL(); } } encode_uint32(OK, buf4); cd->connection->put_data(buf4, 4); while (!cd->quit) { //wait for ID err = cd->connection->get_data(buf4, 4); //#define DEBUG_PRINT(m_p) print_line(m_p) DEBUG_TIME("get_data") if (err != OK) { _close_client(cd); ERR_FAIL_COND(err != OK); } int id = decode_uint32(buf4); //wait for command err = cd->connection->get_data(buf4, 4); if (err != OK) { _close_client(cd); ERR_FAIL_COND(err != OK); } int cmd = decode_uint32(buf4); switch (cmd) { case FileAccessNetwork::COMMAND_FILE_EXISTS: case FileAccessNetwork::COMMAND_GET_MODTIME: case FileAccessNetwork::COMMAND_OPEN_FILE: { DEBUG_TIME("open_file") err = cd->connection->get_data(buf4, 4); if (err != OK) { _close_client(cd); ERR_FAIL_COND(err != OK); } int namelen = decode_uint32(buf4); Vector<char> fileutf8; fileutf8.resize(namelen + 1); err = cd->connection->get_data((uint8_t *)fileutf8.ptr(), namelen); if (err != OK) { _close_client(cd); ERR_FAIL_COND(err != OK); } fileutf8[namelen] = 0; String s; s.parse_utf8(fileutf8.ptr()); if (cmd == FileAccessNetwork::COMMAND_FILE_EXISTS) { print_line("FILE EXISTS: " + s); } if (cmd == FileAccessNetwork::COMMAND_GET_MODTIME) { print_line("MOD TIME: " + s); } if (cmd == FileAccessNetwork::COMMAND_OPEN_FILE) { print_line("OPEN: " + s); } if (!s.begins_with("res://")) { _close_client(cd); ERR_FAIL_COND(!s.begins_with("res://")); } ERR_CONTINUE(cd->files.has(id)); if (cmd == FileAccessNetwork::COMMAND_FILE_EXISTS) { encode_uint32(id, buf4); cd->connection->put_data(buf4, 4); encode_uint32(FileAccessNetwork::RESPONSE_FILE_EXISTS, buf4); cd->connection->put_data(buf4, 4); encode_uint32(FileAccess::exists(s), buf4); cd->connection->put_data(buf4, 4); DEBUG_TIME("open_file_end") break; } if (cmd == FileAccessNetwork::COMMAND_GET_MODTIME) { encode_uint32(id, buf4); cd->connection->put_data(buf4, 4); encode_uint32(FileAccessNetwork::RESPONSE_GET_MODTIME, buf4); cd->connection->put_data(buf4, 4); encode_uint64(FileAccess::get_modified_time(s), buf4); cd->connection->put_data(buf4, 8); DEBUG_TIME("open_file_end") break; } FileAccess *fa = FileAccess::open(s, FileAccess::READ); if (!fa) { //not found, continue encode_uint32(id, buf4); cd->connection->put_data(buf4, 4); encode_uint32(FileAccessNetwork::RESPONSE_OPEN, buf4); cd->connection->put_data(buf4, 4); encode_uint32(ERR_FILE_NOT_FOUND, buf4); cd->connection->put_data(buf4, 4); DEBUG_TIME("open_file_end") break; } encode_uint32(id, buf4); cd->connection->put_data(buf4, 4); encode_uint32(FileAccessNetwork::RESPONSE_OPEN, buf4); cd->connection->put_data(buf4, 4); encode_uint32(OK, buf4); cd->connection->put_data(buf4, 4); encode_uint64(fa->get_len(), buf4); cd->connection->put_data(buf4, 8); cd->files[id] = fa; DEBUG_TIME("open_file_end") } break;
void * mread_pull(struct mread_pool * self , int size) { if (self->active == -1) { return NULL; } struct socket *s = &self->sockets[self->active]; int rd_size = size; char * buffer = _ringbuffer_read(self, &rd_size); if (buffer) { self->skip += size; return buffer; } if (s->status == SOCKET_CLOSED) { ringbuffer_free(self->rb , s->node); s->node = NULL; return NULL; } if (s->status == SOCKET_READ) { s->status = SOCKET_SUSPEND; return NULL; } assert(s->status == SOCKET_POLLIN); int sz = size - rd_size; int rd = READBLOCKSIZE; if (rd < sz) { rd = sz; } int id = self->active; struct ringbuffer * rb = self->rb; struct ringbuffer_block * blk = ringbuffer_alloc(rb , rd); while (blk == NULL) { int collect_id = ringbuffer_collect(rb); _close_client(self , collect_id); if (id == collect_id) { return NULL; } blk = ringbuffer_alloc(rb , rd); } buffer = (char *)(blk + 1); for (;;) { int bytes = recv(s->fd, buffer, rd, MSG_DONTWAIT); if (bytes > 0) { ringbuffer_resize(rb, blk , bytes); if (bytes < sz) { _link_node(rb, self->active, s , blk); s->status = SOCKET_SUSPEND; return NULL; } s->status = SOCKET_READ; break; } if (bytes == 0) { _close_active(self); return NULL; } if (bytes == -1) { switch(errno) { case EWOULDBLOCK: return NULL; default: if (errno == EAGAIN) { continue; } _close_active(self); return NULL; } } } _link_node(rb, self->active , s , blk); void * ret; int real_rd = ringbuffer_data(rb, s->node , size , self->skip, &ret); if (ret) { self->skip += size; return ret; } assert(real_rd == size); struct ringbuffer_block * temp = ringbuffer_alloc(rb, size); while (temp == NULL) { int collect_id = ringbuffer_collect(rb); if (id == collect_id) { return NULL; } temp = ringbuffer_alloc(rb , size); } temp->id = id; if (s->temp) { ringbuffer_link(rb, temp, s->temp); } s->temp = temp; ret = ringbuffer_copy(rb, s->node, self->skip, temp); assert(ret); self->skip += size; return ret; }