int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { int domain; /* Use the lower 8 bits for the domain */ domain = flags & 0xFF; if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) return UV_EINVAL; if (flags & ~0xFF) return UV_EINVAL; uv__handle_init(loop, (uv_handle_t*) handle, UV_UDP); handle->socket = INVALID_SOCKET; handle->reqs_pending = 0; handle->activecnt = 0; handle->func_wsarecv = WSARecv; handle->func_wsarecvfrom = WSARecvFrom; handle->send_queue_size = 0; handle->send_queue_count = 0; uv_req_init(loop, (uv_req_t*) &(handle->recv_req)); handle->recv_req.type = UV_UDP_RECV; handle->recv_req.data = handle; /* If anything fails beyond this point we need to remove the handle from * the handle queue, since it was added by uv__handle_init. */ if (domain != AF_UNSPEC) { SOCKET sock; DWORD err; sock = socket(domain, SOCK_DGRAM, 0); if (sock == INVALID_SOCKET) { err = WSAGetLastError(); QUEUE_REMOVE(&handle->handle_queue); return uv_translate_sys_error(err); } err = uv_udp_set_socket(handle->loop, handle, sock, domain); if (err) { closesocket(sock); QUEUE_REMOVE(&handle->handle_queue); return uv_translate_sys_error(err); } } return 0; }
void uv__io_close(uv_loop_t* loop, uv__io_t* w) { uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP); QUEUE_REMOVE(&w->pending_queue); /* Remove stale events for this file descriptor */ uv__platform_invalidate_fd(loop, w->fd); }
static void uv__cf_loop_cb(void* arg) { uv_loop_t* loop; QUEUE* item; QUEUE split_head; uv__cf_loop_signal_t* s; loop = arg; uv_mutex_lock(&loop->cf_mutex); QUEUE_INIT(&split_head); if (!QUEUE_EMPTY(&loop->cf_signals)) { QUEUE* split_pos = QUEUE_HEAD(&loop->cf_signals); QUEUE_SPLIT(&loop->cf_signals, split_pos, &split_head); } uv_mutex_unlock(&loop->cf_mutex); while (!QUEUE_EMPTY(&split_head)) { item = QUEUE_HEAD(&split_head); s = QUEUE_DATA(item, uv__cf_loop_signal_t, member); /* This was a termination signal */ if (s->cb == NULL) CFRunLoopStop(loop->cf_loop); else s->cb(s->arg); QUEUE_REMOVE(item); free(s); } }
void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) { assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP))); assert(0 != events); if (w->fd == -1) return; assert(w->fd >= 0); /* Happens when uv__io_stop() is called on a handle that was never started. */ if ((unsigned) w->fd >= loop->nwatchers) return; w->pevents &= ~events; if (w->pevents == 0) { QUEUE_REMOVE(&w->watcher_queue); QUEUE_INIT(&w->watcher_queue); if (loop->watchers[w->fd] != NULL) { assert(loop->watchers[w->fd] == w); assert(loop->nfds > 0); loop->watchers[w->fd] = NULL; loop->nfds--; w->events = 0; } } else if (QUEUE_EMPTY(&w->watcher_queue)) QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); }
void uv__work_done(uv_async_t* handle) { struct uv__work* w; uv_loop_t* loop; QUEUE* q; QUEUE wq; int err; loop = container_of(handle, uv_loop_t, wq_async); QUEUE_INIT(&wq); uv_mutex_lock(&loop->wq_mutex); if (!QUEUE_EMPTY(&loop->wq)) { q = QUEUE_HEAD(&loop->wq); QUEUE_SPLIT(&loop->wq, q, &wq); } uv_mutex_unlock(&loop->wq_mutex); while (!QUEUE_EMPTY(&wq)) { q = QUEUE_HEAD(&wq); QUEUE_REMOVE(q); w = container_of(q, struct uv__work, wq); err = (w->work == uv__cancelled) ? UV_ECANCELED : 0; w->done(w, err); } }
void uv__udp_finish_close(uv_udp_t* handle) { uv_udp_send_t* req; QUEUE* q; assert(!uv__io_active(&handle->io_watcher, UV__POLLIN | UV__POLLOUT)); assert(handle->io_watcher.fd == -1); while (!QUEUE_EMPTY(&handle->write_queue)) { q = QUEUE_HEAD(&handle->write_queue); QUEUE_REMOVE(q); req = QUEUE_DATA(q, uv_udp_send_t, queue); req->status = -ECANCELED; QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue); } uv__udp_run_completed(handle); assert(handle->send_queue_size == 0); assert(handle->send_queue_count == 0); /* Now tear down the handle. */ handle->recv_cb = NULL; handle->alloc_cb = NULL; /* but _do not_ touch close_cb */ }
static void uv__udp_run_completed(uv_udp_t* handle) { uv_udp_send_t* req; QUEUE* q; while (!QUEUE_EMPTY(&handle->write_completed_queue)) { q = QUEUE_HEAD(&handle->write_completed_queue); QUEUE_REMOVE(q); req = QUEUE_DATA(q, uv_udp_send_t, queue); uv__req_unregister(handle->loop, req); if (req->bufs != req->bufsml) free(req->bufs); req->bufs = NULL; if (req->send_cb == NULL) continue; /* req->status >= 0 == bytes written * req->status < 0 == errno */ if (req->status >= 0) req->send_cb(req, 0); else req->send_cb(req, req->status); } }
void uv__udp_finish_close(uv_udp_t* handle) { uv_udp_send_t* req; QUEUE* q; assert(!uv__io_active(&handle->io_watcher, UV__POLLIN | UV__POLLOUT)); assert(handle->io_watcher.fd == -1); uv__udp_run_completed(handle); while (!QUEUE_EMPTY(&handle->write_queue)) { q = QUEUE_HEAD(&handle->write_queue); QUEUE_REMOVE(q); req = QUEUE_DATA(q, uv_udp_send_t, queue); uv__req_unregister(handle->loop, req); if (req->bufs != req->bufsml) free(req->bufs); req->bufs = NULL; if (req->send_cb != NULL) req->send_cb(req, -ECANCELED); } /* Now tear down the handle. */ handle->recv_cb = NULL; handle->alloc_cb = NULL; /* but _do not_ touch close_cb */ }
int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) { int domain; /* Use the lower 8 bits for the domain */ domain = flags & 0xFF; if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) return -EINVAL; if (flags & ~0xFF) return -EINVAL; uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP); /* If anything fails beyond this point we need to remove the handle from * the handle queue, since it was added by uv__handle_init in uv_stream_init. */ if (domain != AF_UNSPEC) { int err = maybe_new_socket(tcp, domain, 0); if (err) { QUEUE_REMOVE(&tcp->handle_queue); return err; } } return 0; }
void uv__cf_loop_cb(void* arg) { uv_loop_t* loop; QUEUE* item; QUEUE split_head; uv__cf_loop_signal_t* s; loop = arg; uv_mutex_lock(&loop->cf_mutex); QUEUE_INIT(&split_head); if (!QUEUE_EMPTY(&loop->cf_signals)) { QUEUE* split_pos = QUEUE_HEAD(&loop->cf_signals); QUEUE_SPLIT(&loop->cf_signals, split_pos, &split_head); } uv_mutex_unlock(&loop->cf_mutex); while (!QUEUE_EMPTY(&split_head)) { item = QUEUE_HEAD(&split_head); s = QUEUE_DATA(item, uv__cf_loop_signal_t, member); s->cb(s->arg); QUEUE_REMOVE(item); free(s); } }
static void uv__write_callbacks(uv_stream_t* stream) { uv_write_t* req; QUEUE* q; while (!QUEUE_EMPTY(&stream->write_completed_queue)) { /* Pop a req off write_completed_queue. */ q = QUEUE_HEAD(&stream->write_completed_queue); req = QUEUE_DATA(q, uv_write_t, queue); QUEUE_REMOVE(q); uv__req_unregister(stream->loop, req); if (req->bufs != NULL) { stream->write_queue_size -= uv__write_req_size(req); if (req->bufs != req->bufsml) free(req->bufs); req->bufs = NULL; } /* NOTE: call callback AFTER freeing the request data. */ if (req->cb) req->cb(req, req->error); } assert(QUEUE_EMPTY(&stream->write_completed_queue)); }
void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) { assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP))); assert(0 != events); assert(w->fd >= 0); assert(w->fd < INT_MAX); w->pevents |= events; maybe_resize(loop, w->fd + 1); #if !defined(__sun) /* The event ports backend needs to rearm all file descriptors on each and * every tick of the event loop but the other backends allow us to * short-circuit here if the event mask is unchanged. */ if (w->events == w->pevents) { if (w->events == 0 && !QUEUE_EMPTY(&w->watcher_queue)) { QUEUE_REMOVE(&w->watcher_queue); QUEUE_INIT(&w->watcher_queue); } return; } #endif if (QUEUE_EMPTY(&w->watcher_queue)) QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue); if (loop->watchers[w->fd] == NULL) { loop->watchers[w->fd] = w; loop->nfds++; } }
void uv__work_done(uv_async_t* handle) { struct uv__work* w; uv_loop_t* loop; QUEUE* q; QUEUE wq; int err; loop = container_of(handle, uv_loop_t, wq_async); QUEUE_INIT(&wq); // uv_mutex_lock(&loop->wq_mutex); if (!QUEUE_EMPTY(&loop->wq)) { q = QUEUE_HEAD(&loop->wq); QUEUE_SPLIT(&loop->wq, q, &wq); } // uv_mutex_unlock(&loop->wq_mutex); while (!QUEUE_EMPTY(&wq)) { q = QUEUE_HEAD(&wq); QUEUE_REMOVE(q); w = container_of(q, struct uv__work, wq); w->done(w, 0, NULL, 0); } }
int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) { int domain; /* Use the lower 8 bits for the domain */ domain = flags & 0xFF; if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC) return UV_EINVAL; if (flags & ~0xFF) return UV_EINVAL; uv_stream_init(loop, (uv_stream_t*) handle, UV_TCP); handle->tcp.serv.accept_reqs = NULL; handle->tcp.serv.pending_accepts = NULL; handle->socket = INVALID_SOCKET; handle->reqs_pending = 0; handle->tcp.serv.func_acceptex = NULL; handle->tcp.conn.func_connectex = NULL; handle->tcp.serv.processed_accepts = 0; handle->delayed_error = 0; /* If anything fails beyond this point we need to remove the handle from * the handle queue, since it was added by uv__handle_init in uv_stream_init. */ if (domain != AF_UNSPEC) { SOCKET sock; DWORD err; sock = socket(domain, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { err = WSAGetLastError(); QUEUE_REMOVE(&handle->handle_queue); return uv_translate_sys_error(err); } err = uv_tcp_set_socket(handle->loop, handle, sock, domain, 0); if (err) { closesocket(sock); QUEUE_REMOVE(&handle->handle_queue); return uv_translate_sys_error(err); } } return 0; }
static void uv__inotify_read(uv_loop_t* loop, uv__io_t* dummy, unsigned int events) { const struct uv__inotify_event* e; struct watcher_list* w; uv_fs_event_t* h; QUEUE queue; QUEUE* q; const char* path; ssize_t size; const char *p; /* needs to be large enough for sizeof(inotify_event) + strlen(path) */ char buf[4096]; while (1) { do size = read(loop->inotify_fd, buf, sizeof(buf)); while (size == -1 && errno == EINTR); if (size == -1) { assert(errno == EAGAIN || errno == EWOULDBLOCK); break; } assert(size > 0); /* pre-2.6.21 thing, size=0 == read buffer too small */ /* Now we have one or more inotify_event structs. */ for (p = buf; p < buf + size; p += sizeof(*e) + e->len) { e = (const struct uv__inotify_event*)p; events = 0; if (e->mask & (UV__IN_ATTRIB|UV__IN_MODIFY)) events |= UV_CHANGE; if (e->mask & ~(UV__IN_ATTRIB|UV__IN_MODIFY)) events |= UV_RENAME; w = find_watcher(loop, e->wd); if (w == NULL) continue; /* Stale event, no watchers left. */ /* inotify does not return the filename when monitoring a single file * for modifications. Repurpose the filename for API compatibility. * I'm not convinced this is a good thing, maybe it should go. */ path = e->len ? (const char*) (e + 1) : uv__basename_r(w->path); QUEUE_MOVE(&w->watchers, &queue); while (!QUEUE_EMPTY(&queue)) { q = QUEUE_HEAD(&queue); h = QUEUE_DATA(q, uv_fs_event_t, watchers); QUEUE_REMOVE(q); QUEUE_INSERT_TAIL(&w->watchers, q); h->cb(h, path, events, 0); } } } }
int timer_close (evHandle *handle) { handle->flags |= HANDLE_CLOSING; timer_stop(handle); QUEUE_REMOVE(&handle->queue); QUEUE_INSERT_TAIL(&handle->loop->closing_queue, &handle->queue); return 0; }
static Token stack_pop(QUEUE *stack) { QUEUE *h = QUEUE_HEAD(stack); queue_item *item = queue_node_data(h); QUEUE_REMOVE(&item->node); Token token = item->item; free(item); return token; }
static void uv__udp_run_pending(uv_udp_t* handle) { uv_udp_send_t* req; QUEUE* q; struct msghdr h; ssize_t size; while (!QUEUE_EMPTY(&handle->write_queue)) { q = QUEUE_HEAD(&handle->write_queue); assert(q != NULL); req = QUEUE_DATA(q, uv_udp_send_t, queue); assert(req != NULL); memset(&h, 0, sizeof h); h.msg_name = &req->addr; h.msg_namelen = (req->addr.sin6_family == AF_INET6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); h.msg_iov = (struct iovec*)req->bufs; h.msg_iovlen = req->bufcnt; do { size = sendmsg(handle->io_watcher.fd, &h, 0); } while (size == -1 && errno == EINTR); /* TODO try to write once or twice more in the * hope that the socket becomes readable again? */ if (size == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) break; req->status = (size == -1 ? -errno : size); #ifndef NDEBUG /* Sanity check. */ if (size != -1) { ssize_t nbytes; int i; for (nbytes = i = 0; i < req->bufcnt; i++) nbytes += req->bufs[i].len; assert(size == nbytes); } #endif /* Sending a datagram is an atomic operation: either all data * is written or nothing is (and EMSGSIZE is raised). That is * why we don't handle partial writes. Just pop the request * off the write queue and onto the completed queue, done. */ QUEUE_REMOVE(&req->queue); QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue); } }
static void loop_run_immediate(evLoop *loop) { QUEUE *q; evHandle *handle; while ( !QUEUE_EMPTY(&loop->handle_queue) ){ q = QUEUE_HEAD(&(loop)->handle_queue); QUEUE_REMOVE(q); handle = QUEUE_DATA(q, evHandle, queue); assert(handle); handle->cb(handle); } }
static Event queue_pop(Queue *queue) { QUEUE *h = QUEUE_HEAD(&queue->headtail); queue_item *item = queue_node_data(h); QUEUE_REMOVE(&item->node); Event e; e = item->item; free(item); return e; }
void uv_chan_clear(uv_chan_t *chan) { uv_mutex_lock(&chan->mutex); uv__chan_item_t *item = NULL; QUEUE *head = NULL; while (!QUEUE_EMPTY(&chan->q)) { head = QUEUE_HEAD(&chan->q); item = QUEUE_DATA(head, uv__chan_item_t, active_queue); QUEUE_REMOVE(head); free(item); } uv_mutex_unlock(&chan->mutex); }
void tls__write_done_cb(uv_write_t* w, int status) { tr_uv_wi_t* wi = NULL; int i; QUEUE* q; GET_TLS(w); tt->is_writing = 0; if (status) { pc_lib_log(PC_LOG_ERROR, "tcp__write_done_cb - uv_write callback error: %s", uv_strerror(status)); } status = status ? PC_RC_ERROR : PC_RC_OK; pc_mutex_lock(&tt->wq_mutex); while(!QUEUE_EMPTY(&tt->writing_queue)) { q = QUEUE_HEAD(&tt->writing_queue); QUEUE_REMOVE(q); QUEUE_INIT(q); wi = (tr_uv_wi_t* )QUEUE_DATA(q, tr_uv_wi_t, queue); if (!status && TR_UV_WI_IS_RESP(wi->type)) { pc_lib_log(PC_LOG_DEBUG, "tls__write_to_tcp - move wi from writing queue to resp pending queue," " seq_num: %u, req_id: %u", wi->seq_num, wi->req_id); QUEUE_INSERT_TAIL(&tt->resp_pending_queue, q); continue; }; pc_lib_free(wi->buf.base); wi->buf.base = NULL; wi->buf.len = 0; if (TR_UV_WI_IS_NOTIFY(wi->type)) { pc_trans_sent(tt->client, wi->seq_num, status); } if (TR_UV_WI_IS_RESP(wi->type)) { pc_trans_resp(tt->client, wi->req_id, status, NULL); } // if internal, do nothing here. if (PC_IS_PRE_ALLOC(wi->type)) { PC_PRE_ALLOC_SET_IDLE(wi->type); } else { pc_lib_free(wi); } } pc_mutex_unlock(&tt->wq_mutex); tls__write_to_tcp(tls); }
static void uv__run_pending(uv_loop_t* loop) { QUEUE* q; uv__io_t* w; while (!QUEUE_EMPTY(&loop->pending_queue)) { q = QUEUE_HEAD(&loop->pending_queue); QUEUE_REMOVE(q); QUEUE_INIT(q); w = QUEUE_DATA(q, uv__io_t, pending_queue); w->cb(loop, w, UV__POLLOUT); } }
static void uv__stream_flush_write_queue(uv_stream_t* stream, int error) { uv_write_t* req; QUEUE* q; while (!QUEUE_EMPTY(&stream->write_queue)) { q = QUEUE_HEAD(&stream->write_queue); QUEUE_REMOVE(q); req = QUEUE_DATA(q, uv_write_t, queue); req->error = error; QUEUE_INSERT_TAIL(&stream->write_completed_queue, &req->queue); } }
static void ref_pop(QUEUE *refs) { QUEUE *h = QUEUE_HEAD(refs); queue_ref_item *item = QUEUE_DATA(h, queue_ref_item, node); QUEUE_REMOVE(&item->node); void *ref = item->item.ref; if (item->item.v_type == VAR_LIST) { List *l = ref; utarray_free(l->items); } free(item); free(ref); }
static int _worker_dispatch_cb (evHandle *handle){ comoWorker *worker = handle->data; duk_context *ctx = worker->Mainctx; mtx_lock(&worker->mtx); QUEUE *q; while ( !QUEUE_EMPTY(&worker->queueOut) ){ q = QUEUE_HEAD(&(worker)->queueOut); QUEUE_REMOVE(q); comoQueue *queue = QUEUE_DATA(q, comoQueue, queue); if (worker->destroy != 0){ goto FREE; } duk_push_heapptr(ctx, worker->self); if (duk_get_type(ctx, -1) != DUK_TYPE_OBJECT){ dump_stack(ctx, "DUK"); assert(0); } como_push_worker_value(ctx, queue); duk_call(ctx, 1); duk_pop(ctx); FREE : /* free except in case of pointers */ if (queue->data != NULL && queue->type != DUK_TYPE_POINTER){ free(queue->data); } free(queue); } mtx_unlock(&worker->mtx); if (worker->destroy == 2){ duk_push_global_stash(ctx); duk_get_prop_string(ctx, -1, "comoWorkersCallBack"); duk_push_number(ctx, (double) handle->id); duk_del_prop(ctx, -2); handle_close(handle); free(worker); } return 0; }
void loop_run_closing_handles(evLoop *loop){ QUEUE *q; evHandle *handle; while ( !QUEUE_EMPTY(&loop->closing_queue) ){ q = QUEUE_HEAD(&(loop)->closing_queue); QUEUE_REMOVE(q); handle = QUEUE_DATA(q, evHandle, queue); assert(handle); if (handle->close != NULL){ handle->close(handle); } // _free_handle(handle); } }
static void uv__finish_close(uv_handle_t* handle) { /* Note: while the handle is in the UV_HANDLE_CLOSING state now, it's still * possible for it to be active in the sense that uv__is_active() returns * true. * * A good example is when the user calls uv_shutdown(), immediately followed * by uv_close(). The handle is considered active at this point because the * completion of the shutdown req is still pending. */ assert(handle->flags & UV_HANDLE_CLOSING); assert(!(handle->flags & UV_HANDLE_CLOSED)); handle->flags |= UV_HANDLE_CLOSED; switch (handle->type) { case UV_PREPARE: case UV_CHECK: case UV_IDLE: case UV_ASYNC: case UV_TIMER: case UV_PROCESS: case UV_FS_EVENT: case UV_FS_POLL: case UV_POLL: case UV_SIGNAL: break; case UV_NAMED_PIPE: case UV_TCP: case UV_TTY: uv__stream_destroy((uv_stream_t*)handle); break; case UV_UDP: uv__udp_finish_close((uv_udp_t*)handle); break; default: assert(0); break; } uv__handle_unref(handle); QUEUE_REMOVE(&handle->handle_queue); if (handle->close_cb) { handle->close_cb(handle); } }
void tls__reset(tr_uv_tcp_transport_t* tt) { int ret; QUEUE* q; tr_uv_tls_transport_t* tls = (tr_uv_tls_transport_t* )tt; pc_lib_log(PC_LOG_DEBUG, "tls__reset - reset ssl"); if (!SSL_clear(tls->tls)) { pc_lib_log(PC_LOG_WARN, "tls__reset - ssl clear error: %s", ERR_error_string(ERR_get_error(), NULL)); } ret = BIO_reset(tls->in); assert(ret == 1); ret = BIO_reset(tls->out); assert(ret == 1); // write should retry remained, insert it to writing queue // then tcp__reset will recycle it. if (tls->should_retry) { pc_lib_log(PC_LOG_DEBUG, "tls__reset - move should retry wi to writing queue, seq_num: %u, req_id: %u", tls->should_retry->seq_num, tls->should_retry->req_id); QUEUE_INIT(&tls->should_retry->queue); QUEUE_INSERT_TAIL(&tt->writing_queue, &tls->should_retry->queue); tls->should_retry = NULL; } if (tls->retry_wb) { pc_lib_free(tls->retry_wb); tls->retry_wb = NULL; tls->retry_wb_len = 0; } // tcp reset will recycle following write item while(!QUEUE_EMPTY(&tls->when_tcp_is_writing_queue)) { q = QUEUE_HEAD(&tls->when_tcp_is_writing_queue); QUEUE_REMOVE(q); QUEUE_INIT(q); QUEUE_INSERT_TAIL(&tt->writing_queue, q); } tcp__reset(tt); }
void handle_close (evHandle *h){ if ((h->flags & HANDLE_CLOSING) != 0) return; if (h->type == EV_IO){ io_close(h); } else if (h->type == EV_TIMER){ timer_close(h); } else { handle_stop(h); h->flags |= HANDLE_CLOSING; QUEUE_REMOVE(&h->queue); QUEUE_INSERT_TAIL(&h->loop->closing_queue, &h->queue); //closing un initaited handle //assert(0 && "CLOSING UNKNOWN HANDLE\n"); } }