int api_tcp_accept(api_tcp_listener_t* listener, api_tcp_t* tcp) { api_tcp_listener_accept_t accept; if (listener->loop->terminated) return API__TERMINATE; if (listener->status.closed || listener->status.terminated || listener->status.error != API__OK) return listener->status.error; accept.task = listener->loop->scheduler.current; accept.tcp = tcp; accept.success = 0; tcp->address.address.ss_family = listener->os_linux.af; tcp->address.length = sizeof(tcp->address.address); listener->os_linux.reserved = &accept; api_loop_read_add(listener->loop, listener->fd, &listener->os_linux.e); api_task_sleep(accept.task); api_loop_read_del(listener->loop, listener->fd, &listener->os_linux.e); listener->os_linux.reserved = 0; if (accept.success) return API__OK; return listener->status.error; }
size_t api_stream_on_read(struct api_filter_t* filter, char* buffer, size_t length) { api_stream_t* stream = filter->stream; api_stream_read_t read; api_timer_t timeout; struct timespec start, end, elapsed; uint64_t timeout_value = stream->read_timeout; if (length == 0) return length; if (stream->status.read_timeout || stream->status.eof || stream->status.error != API__OK || stream->status.closed || stream->status.peer_closed || stream->status.terminated) return 0; read.buffer = buffer; read.length = length; read.done = 0; read.task = stream->loop->base.scheduler.current; stream->os_linux.reserved[0] = &read; if (timeout_value > 0) { memset(&timeout, 0, sizeof(timeout)); timeout.task = read.task; api_timeout_exec(&stream->loop->base.timeouts, &timeout, timeout_value); } clock_gettime(CLOCK_MONOTONIC, &start); api_loop_read_add(stream->loop, stream->fd, &stream->os_linux.e); api_task_sleep(read.task); api_loop_read_del(stream->loop, stream->fd, &stream->os_linux.e); clock_gettime(CLOCK_MONOTONIC, &end); if (end.tv_nsec - start.tv_nsec < 0) { elapsed.tv_sec = end.tv_sec - start.tv_sec - 1; elapsed.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec; } else { elapsed.tv_sec = end.tv_sec - start.tv_sec; elapsed.tv_nsec = end.tv_nsec - start.tv_nsec; } if (timeout_value > 0) api_timeout_exec(&stream->loop->base.timeouts, &timeout, 0); stream->os_linux.reserved[0] = 0; stream->read_bandwidth.read += read.done; stream->read_bandwidth.period += elapsed.tv_sec * 1000000 + elapsed.tv_nsec / 1000; if (timeout_value > 0 && timeout.elapsed) { stream->status.read_timeout = 1; stream->filter_head->on_read_timeout(stream->filter_head); return 0; } else { return read.done; } }