wait_obj() : set_state(false) , signal(BACK_EVENT_NONE) , object_and_time(false) , waked_up_by_time(false) { this->trigger_time = tvtime(); }
// long long is not embind type. Use long or double (safe for 53 bits) long next_timeout() { session_reactor.set_current_time(tvtime()); std::chrono::microseconds us = session_reactor.get_next_timeout(SessionReactor::EnableGraphics{true}, 5s) - session_reactor.get_current_time(); return us.count(); }
// Idle time in millisecond void set(uint64_t idle_usec = 0) { this->set_state = true; struct timeval now = tvtime(); uint64_t sum_usec = (now.tv_usec + idle_usec); this->trigger_time.tv_sec = (sum_usec / 1000000) + now.tv_sec; this->trigger_time.tv_usec = sum_usec % 1000000; }
void resume() { if (this->capture_wrm){ if (this->enable_file_encryption) { this->crypto_wrm_trans->next(); } else { this->wrm_trans->next(); } struct timeval now = tvtime(); this->pnc->recorder.timestamp(now); this->pnc->recorder.send_timestamp_chunk(true); } }
void add_to_fd_set(int fd, fd_set & rfds, unsigned & max, timeval & timeout) const { if (fd > INVALID_SOCKET) { FD_SET(fd, &rfds); max = (static_cast<unsigned>(fd) > max) ? fd : max; } if ((fd <= INVALID_SOCKET || this->object_and_time) && this->set_state) { struct timeval now; now = tvtime(); timeval remain = how_long_to_wait(this->trigger_time, now); if (lessthantimeval(remain, timeout)) { timeout = remain; } } }
// Idle time in microsecond void update(uint64_t idle_usec) { if (!idle_usec) { return; } if (this->set_state) { timeval now = tvtime(); timeval new_trigger = addusectimeval(idle_usec, now); if (lessthantimeval(new_trigger, this->trigger_time)) { this->trigger_time = new_trigger; } } else { this->set(idle_usec); } }
inline void add_to_fd_set(wait_obj & w, SocketTransport * t, fd_set & rfds, unsigned & max, timeval & timeout) { if (t && t->sck > 0){ FD_SET(t->sck, &rfds); max = ((unsigned)t->sck > max)?t->sck:max; } if ((!t || t->sck <= 0 || w.object_and_time) && w.set_state) { struct timeval now; now = tvtime(); timeval remain = how_long_to_wait(w.trigger_time, now); if (lessthantimeval(remain, timeout)){ timeout = remain; } } }
bool is_set(fd_set & rfds) { if (this->obj > 0) { return FD_ISSET(this->obj, &rfds); } else { if (this->set_state) { struct timeval now; now = tvtime(); if ((now.tv_sec > this->trigger_time.tv_sec) || ( (now.tv_sec == this->trigger_time.tv_sec) &&(now.tv_usec > this->trigger_time.tv_usec))) { return true; } } } return false; }
bool is_set(int fd, fd_set & rfds) { this->waked_up_by_time = false; if (fd > INVALID_SOCKET) { bool res = FD_ISSET(fd, &rfds); if (res || !this->object_and_time) { return res; } } if (this->set_state) { if (tvtime() >= this->trigger_time) { this->waked_up_by_time = true; return true; } } return false; }
inline bool is_set(wait_obj & w, SocketTransport * t, fd_set & rfds) { w.waked_up_by_time = false; if (t && t->sck > 0) { bool res = FD_ISSET(t->sck, &rfds); if (res || !w.object_and_time) { return res; } } if (w.set_state) { if (tvtime() >= w.trigger_time) { w.waked_up_by_time = true; return true; } } return false; }
void make_chunk_header(OutStream & stream, uint8_t chunk_type, uint16_t data_size) { stream.out_uint8(chunk_type); stream.out_uint16_le(data_size); stream.out_timeval_to_uint64le_usec(tvtime()); }
void update() { session_reactor.execute_timers_at( SessionReactor::EnableGraphics{true}, tvtime(), [&]() -> gdi::GraphicApi& { return front; }); }
wait_obj(int sck) : obj(sck) , set_state(false) { this->trigger_time = tvtime(); }
void pause() { if (this->capture_png) { struct timeval now = tvtime(); this->psc->pause_snapshot(now); } }
bool interpret_chunk(bool real_time = true) { try { uint8_t array[AUTOSIZE]; static_assert(AUTOSIZE >= TRANSPARENT_CHUNK_HEADER_SIZE, ""); InStream header(array, TRANSPARENT_CHUNK_HEADER_SIZE); uint8_t * end = array; this->t->recv(&end, header.get_capacity()); uint8_t chunk_type = header.in_uint8(); uint16_t data_size = header.in_uint16_le(); timeval last_record_now = this->record_now; header.in_timeval_from_uint64le_usec(this->record_now); //LOG(LOG_INFO, "chunk_type=%u data_size=%u", chunk_type, data_size); end = array; this->t->recv(&end, data_size); InStream payload(array, end - array); switch (chunk_type) { case CHUNK_TYPE_META: { uint8_t trm_format_version = payload.in_uint8(); (void)trm_format_version; this->replay_now = tvtime(); this->meta_ok = true; } break; case CHUNK_TYPE_FASTPATH: { this->consumer->send_fastpath_data(payload); } break; case CHUNK_TYPE_FRONTCHANNEL: { uint8_t mod_channel_name_length = payload.in_uint8(); uint16_t length = payload.in_uint16_le(); uint16_t chunk_size = payload.in_uint16_le(); uint32_t flags = payload.in_uint32_le(); char mod_channel_name[256]; payload.in_copy_bytes(mod_channel_name, mod_channel_name_length); mod_channel_name[mod_channel_name_length] = 0; const CHANNELS::ChannelDef * front_channel = this->consumer->get_channel_list().get_by_name(mod_channel_name); if (front_channel) { this->consumer->send_to_channel(*front_channel, const_cast<uint8_t *>(payload.in_uint8p(length)), length, chunk_size, flags); } } break; case CHUNK_TYPE_SLOWPATH: { uint16_t channelId = payload.in_uint16_le(); HStream data(1024, 65535); size_t length(data_size - sizeof(uint16_t)); data.out_copy_bytes(payload.in_uint8p(length), length); data.mark_end(); this->consumer->send_data_indication_ex(channelId, data); } break; case CHUNK_TYPE_RESIZE: { uint16_t width = payload.in_uint16_le(); uint16_t height = payload.in_uint16_le(); uint8_t bpp = payload.in_uint8(); this->consumer->server_resize(width, height, bpp); } break; default: LOG(LOG_ERR, "Unknown chunt type(%d)", chunk_type); throw Error(ERR_TRM_UNKNOWN_CHUNK_TYPE); } if (real_time && (chunk_type != CHUNK_TYPE_META)) { timeval now = tvtime(); uint64_t elapsed = difftimeval(now, this->replay_now); this->replay_now = now; uint64_t record_elapsed = difftimeval(this->record_now, last_record_now); if (elapsed <= record_elapsed) { struct timespec wtime = { static_cast<time_t>((record_elapsed - elapsed) / 1000000LL) , static_cast<time_t>(((record_elapsed - elapsed) % 1000000LL) * 1000) }; struct timespec wtime_rem = { 0, 0 }; while ((nanosleep(&wtime, nullptr) == -1) && (errno == EINTR)) { wtime = wtime_rem; } } } } catch (Error & e){ LOG(LOG_INFO,"receive error %u : end of transport", e.id); // receive error, end of transport return false; } return true; }