uint8_t* insert_connection_stats_payload(uint8_t* ptr, uint8_t* end, nabto_connect* con) { nabto_stamp_t now; uint32_t connectionAge; UNABTO_ASSERT(ptr <= end); if (end-ptr < NP_PAYLOAD_CONNECTION_STATS_BYTELENGTH) { return NULL; } ptr = insert_payload(ptr, NP_PAYLOAD_TYPE_CONNECTION_STATS, 0, 21); WRITE_FORWARD_U8(ptr, NP_PAYLOAD_CONNECTION_STATS_VERSION); now = nabtoGetStamp(); connectionAge = nabtoStampDiff2ms(nabtoStampDiff(&now, &con->stats.connectionStart)); WRITE_FORWARD_U32(ptr, connectionAge); WRITE_FORWARD_U32(ptr, con->stats.packetsReceived); WRITE_FORWARD_U32(ptr, con->stats.packetsSent); WRITE_FORWARD_U32(ptr, con->stats.bytesReceived); WRITE_FORWARD_U32(ptr, con->stats.bytesSent); return ptr; }
void etimer_set(struct etimer *et, uint32_t interval) { nabto_stamp_t t = nabtoGetStamp(); memcpy(&et->timer.start, &t, sizeof(nabto_stamp_t)); nabtoAddStamp(&et->timer.start, interval); et->timer.interval = interval; }
int main(int argc, char** argv) { int i; nabto_stamp_t initial = nabtoGetStamp(); // test that going forward in time works as expected. for (i = 0; i < 100000; i++) { nabto_stamp_t stamp = nabtoGetStamp(); uint32_t ticks = rand(); ticks = ticks % (INT_MAX); unabto_tick_timer_tick(ticks); if (!nabtoIsStampPassed(&stamp)) { printf("test failed stamp: %i, ticks: %i", stamp, ticks); return 1; } } for (i = 0; i < 100000; i++) { unabto_tick_timer_tick(rand()); nabto_stamp_t realstamp = nabtoGetStamp(); uint32_t ticks = rand(); nabto_stamp_t stamp; ticks = ticks % (INT_MAX); stamp = realstamp + ticks; if (nabtoIsStampPassed(&stamp)) { printf("test failed stamp: %i, ticks: %i\n", realstamp, ticks); return 1; } } { nabto_stamp_t stamp = nabtoGetStamp(); if (nabtoIsStampPassed(&stamp)) { printf("stamp wrongly passed\n"); return 1; } unabto_tick_timer_tick(1); if (!nabtoIsStampPassed(&stamp)) { printf("stamp wrongly not passed\n"); return 1; } } printf("Tick timer test passed\n"); return 0; }
void tunnel_loop_epoll() { struct epoll_event events[MAX_EPOLL_EVENTS]; int timeout; nabto_stamp_t ne; nabto_stamp_t now; int nfds; if (!unabto_init()) { NABTO_LOG_FATAL(("Failed to initialize unabto")); } if (!init_tunnel_module()) { NABTO_LOG_FATAL(("Cannot initialize tunnel module")); return; } unabto_time_auto_update(false); // time is updated here and after the select since that's the only blocking point. unabto_time_update_stamp(); while (true) { int i; unabto_next_event(&ne); now = nabtoGetStamp(); timeout = nabtoStampDiff2ms(nabtoStampDiff(&ne, &now)); if (timeout < 0) { timeout = 0; } nfds = epoll_wait(unabto_epoll_fd, events, MAX_EPOLL_EVENTS, timeout); unabto_time_update_stamp(); for (i = 0; i < nfds; i++) { unabto_epoll_event_handler* handler = (unabto_epoll_event_handler*)events[i].data.ptr; if (handler->epollEventType == UNABTO_EPOLL_TYPE_UDP) { unabto_network_epoll_read(&events[i]); } #if NABTO_ENABLE_TCP_FALLBACK unabto_tcp_fallback_epoll_event(&events[i]); #endif unabto_tunnel_epoll_event(&events[i]); } unabto_time_event(); } deinit_tunnel_module(); unabto_close(); }
/** initialise a connection */ static void nabto_reset_connection(nabto_connect* con) { nabto_stamp_t tmp = nabtoGetStamp(); NABTO_LOG_TRACE((PRInsi " Reset connection", MAKE_NSI_PRINTABLE(0, con->spnsi, 0))); memset(con, 0, offsetof(nabto_connect, cryptoctx)); con->stamp = tmp; con->socket = NABTO_INVALID_SOCKET; con->stats.connectionStart = tmp; #if NABTO_ENABLE_TCP_FALLBACK unabto_tcp_fallback_init(con); #endif nabto_crypto_reset(&con->cryptoctx); }
/** * return next timestamp which should be considered. */ void nabto_stream_update_next_event(nabto_stamp_t* current_min_stamp) { int i; for (i = 0; i < NABTO_MEMORY_STREAM_MAX_STREAMS; i++) { struct nabto_stream_s* stream = &stream__[i]; if (stream->state != STREAM_IDLE) { if (stream->applicationEvents.dataReady || stream->applicationEvents.dataWritten || stream->applicationEvents.readClosed || stream->applicationEvents.writeClosed || stream->applicationEvents.closed) { nabto_stamp_t now = nabtoGetStamp(); nabto_update_min_stamp(current_min_stamp, &now); } // If we have unacked packets then check then use the best timeout we know of nabto_stream_tcb_update_next_event(stream, current_min_stamp); } } }
void wait_event() { int timeout; nabto_stamp_t ne; nabto_stamp_t now; int nfds; int max_read_fd = 0; int max_write_fd = 0; fd_set read_fds; fd_set write_fds; struct timeval timeout_val; unabto_next_event(&ne); now = nabtoGetStamp(); timeout = nabtoStampDiff2ms(nabtoStampDiff(&ne, &now)); if (timeout < 0) timeout = 0; FD_ZERO(&read_fds); FD_ZERO(&write_fds); unabto_network_select_add_to_read_fd_set(&read_fds, &max_read_fd); #if NABTO_ENABLE_TCP_FALLBACK unabto_tcp_fallback_select_add_to_read_fd_set(&read_fds, &max_read_fd); unabto_tcp_fallback_select_add_to_write_fd_set(&write_fds, &max_write_fd); #endif timeout_val.tv_sec = (timeout/1000); timeout_val.tv_usec = ((timeout)%1000)*1000; nfds = select(MAX(max_read_fd+1, max_write_fd+1), &read_fds, &write_fds, NULL, &timeout_val); NABTO_LOG_TRACE(("foobar %i", nfds)); if (nfds < 0) NABTO_LOG_FATAL(("Error in epoll_wait: %d", errno)); unabto_network_select_read_sockets(&read_fds); unabto_time_event(); }
bool nabtoIsStampPassed(nabto_stamp_t* stamp) { return *stamp - nabtoGetStamp() > MAX_STAMP_DIFF; }
intptr_t tick_thread_func(void* args) { nabto_stamp_t ne; nabto_stamp_t shortTime; bool received = false; unabto_mutex_lock(&lock); unabto_next_event(&ne); unabto_mutex_unlock(&lock); nabtoSetFutureStamp(&shortTime, 10); while (running) { //struct epoll_event events[1]; int timeout; nabto_stamp_t now; // updating next event is an expensive operation so only do it if // the earlier update is expired. if (nabtoIsStampPassed(&ne) || (received && nabtoIsStampPassed(&shortTime))) { unabto_mutex_lock(&lock); unabto_time_event(); unabto_next_event(&ne); unabto_mutex_unlock(&lock); nabtoSetFutureStamp(&shortTime, 10); received = false; } // the problem is that the timing is changed when packets is received. now = nabtoGetStamp(); timeout = nabtoStampDiff2ms(nabtoStampDiff(&ne, &now)); if (timeout < 0) { NABTO_LOG_DEBUG(("connection timestamp is in the past. setting timeout to 1ms, timeout=%i, this could be a problem.", timeout)); timeout = 1; } else if (timeout == 0) { timeout = 1; } if (received) { if (timeout > 10) { timeout = 10; } } else { if (timeout > 100) { timeout = 100; } } nabto_socket_t readySockets[16]; uint16_t nReady = nabto_read_events(readySockets, 16, timeout); uint16_t i; for (i = 0; i < nReady; i++) { unabto_mutex_lock(&lock); unabto_read_socket(readySockets[i]); unabto_mutex_unlock(&lock); received = true; } if (nReady == 0) { unabto_mutex_lock(&lock); unabto_time_event(); unabto_mutex_unlock(&lock); } } return 0; }
void tunnel_loop_epoll() { struct epoll_event events[MAX_EPOLL_EVENTS]; int timeout; nabto_stamp_t ne; nabto_stamp_t now; int nfds; int i; if (!unabto_init()) { NABTO_LOG_FATAL(("Failed to initialize unabto")); } if (!init_tunnel_module()) { NABTO_LOG_FATAL(("Cannot initialize tunnel module")); return; } unabto_time_auto_update(false); // time is updated here and after the select since that's the only blocking point. unabto_time_update_stamp(); while (true) { int i; unabto_next_event(&ne); now = nabtoGetStamp(); timeout = nabtoStampDiff2ms(nabtoStampDiff(&ne, &now)); if (timeout < 0) { timeout = 0; } nfds = epoll_wait(unabto_epoll_fd, events, MAX_EPOLL_EVENTS, timeout); unabto_time_update_stamp(); for (i = 0; i < nfds; i++) { unabto_epoll_event_handler* handler = (unabto_epoll_event_handler*)events[i].data.ptr; if (handler->epollEventType == UNABTO_EPOLL_TYPE_UDP) { unabto_epoll_event_handler_udp* udpHandler = (unabto_epoll_event_handler_udp*)handler; bool status; do { status = unabto_read_socket(udpHandler->fd); } while (status); } #if NABTO_ENABLE_TCP_FALLBACK if (handler->epollEventType == UNABTO_EPOLL_TYPE_TCP_FALLBACK) { nabto_connect* con = (nabto_connect*)handler; if (events[i].events & EPOLLIN) { unabto_tcp_fallback_read_ready(con); } if (events[i].events & EPOLLOUT) { unabto_tcp_fallback_write_ready(con); } } #endif if (handler->epollEventType == UNABTO_EPOLL_TYPE_TCP_TUNNEL) { tunnel* tunnelPtr = (tunnel*)handler; if (tunnelPtr->sock != INVALID_SOCKET) { tunnel_event(tunnelPtr, TUNNEL_EVENT_SOURCE_TCP_READ); } if (tunnelPtr->sock != INVALID_SOCKET) { tunnel_event(tunnelPtr, TUNNEL_EVENT_SOURCE_TCP_WRITE); } } } unabto_time_event(); } deinit_tunnel_module(); unabto_close(); }
bool nabtoIsStampPassed(nabto_stamp_t *stamp) { return *(uint32_t*)stamp - (uint32_t)nabtoGetStamp() > MAX_STAMP_DIFF; }