static void connect_cb(uv_connect_t* req, int status) { int r; uv_buf_t buf; ASSERT(req == &ctx.connect_req); ASSERT(status == 0); buf = uv_buf_init(".", 1); r = uv_write2(&ctx.write_req, (uv_stream_t*)&ctx.channel, &buf, 1, &ctx.send.stream, NULL); ASSERT(r == 0); /* Perform two writes to the same pipe to make sure that on Windows we are * not running into issue 505: * https://github.com/libuv/libuv/issues/505 */ buf = uv_buf_init(".", 1); r = uv_write2(&ctx.write_req2, (uv_stream_t*)&ctx.channel, &buf, 1, &ctx.send2.stream, NULL); ASSERT(r == 0); r = uv_read_start((uv_stream_t*)&ctx.channel, alloc_cb, recv_cb); ASSERT(r == 0); }
static int luv_write2(lua_State* L) { uv_stream_t* handle = luv_check_stream(L, 1); uv_write_t* req; int ret, ref; uv_stream_t* send_handle; send_handle = luv_check_stream(L, 3); ref = luv_check_continuation(L, 4); req = lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ref); if (lua_istable(L, 2)) { size_t count; uv_buf_t *bufs = luv_prep_bufs(L, 2, &count); ret = uv_write2(req, handle, bufs, count, send_handle, luv_write_cb); free(bufs); } else if (lua_isstring(L, 2)) { uv_buf_t buf; luv_check_buf(L, 2, &buf); ret = uv_write2(req, handle, &buf, 1, send_handle, luv_write_cb); } else { return luaL_argerror(L, 2, "data must be string or table of strings"); } if (ret < 0) { lua_pop(L, 1); return luv_error(L, ret); } lua_pushvalue(L, 2); ((luv_req_t*)req->data)->data_ref = luaL_ref(L, LUA_REGISTRYINDEX); return 1; }
int ipc_helper_bind_twice(void) { /* * This is launched from test-ipc.c. stdin is a duplex channel * over which two handles will be transmitted. */ struct sockaddr_in addr; uv_write_t write_req; uv_write_t write_req2; int r; uv_buf_t buf; uv_os_fd_t stdin_handle = uv_convert_fd_to_handle(0); ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_pipe_init(uv_default_loop(), &channel, 1); ASSERT(r == 0); uv_pipe_open(&channel, stdin_handle); ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); buf = uv_buf_init("hello\n", 6); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); r = uv_tcp_init(uv_default_loop(), &tcp_server2); ASSERT(r == 0); r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); ASSERT(r == 0); r = uv_tcp_bind(&tcp_server2, (const struct sockaddr*) &addr, 0); ASSERT(r == 0); r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server, NULL); ASSERT(r == 0); r = uv_write2(&write_req2, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server2, NULL); ASSERT(r == 0); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); MAKE_VALGRIND_HAPPY(); return 0; }
static int run_test(void) { uv_process_t process; uv_buf_t buf; int r; spawn_helper(&ctx.channel, &process, "ipc_send_recv_helper"); buf = uv_buf_init(".", 1); r = uv_write2(&ctx.write_req, (uv_stream_t*)&ctx.channel, &buf, 1, &ctx.send.stream, NULL); ASSERT(r == 0); r = uv_read2_start((uv_stream_t*)&ctx.channel, alloc_cb, recv_cb); ASSERT(r == 0); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); ASSERT(num_recv_handles == 1); return 0; }
static void ipc_on_connection(uv_stream_t* server, int status) { int r; uv_buf_t buf; uv_tcp_t* conn; if (!connection_accepted) { /* * Accept the connection and close it. Also let the other * side know. */ ASSERT(status == 0); ASSERT((uv_stream_t*)&tcp_server == server); conn = malloc(sizeof(*conn)); ASSERT(conn); r = uv_tcp_init(server->loop, conn); ASSERT(r == 0); r = uv_accept(server, (uv_stream_t*)conn); ASSERT(r == 0); uv_close((uv_handle_t*)conn, close_conn_cb); buf = uv_buf_init("accepted_connection\n", 20); r = uv_write2(&conn_notify_req, (uv_stream_t*)&channel, &buf, 1, NULL, conn_notify_write_cb); ASSERT(r == 0); connection_accepted = 1; } }
void ipc_connection_cb(uv_stream_t* ipc_pipe, int status) { int rc; struct ipc_server_ctx* sc; struct ipc_peer_ctx* pc; uv_loop_t* loop; uv_buf_t buf; loop = ipc_pipe->loop; buf = uv_buf_init("PING", 4); sc = container_of(ipc_pipe, struct ipc_server_ctx, ipc_pipe); pc = calloc(1, sizeof(*pc)); //ASSERT(pc != NULL); if (ipc_pipe->type == UV_TCP) rc = uv_tcp_init(loop, (uv_tcp_t*) &pc->peer_handle); else if (ipc_pipe->type == UV_NAMED_PIPE) rc = uv_pipe_init(loop, (uv_pipe_t*) &pc->peer_handle, 1); rc = uv_accept(ipc_pipe, (uv_stream_t*) &pc->peer_handle); rc = uv_write2(&pc->write_req, (uv_stream_t*) &pc->peer_handle, &buf, 1, (uv_stream_t*) &sc->server_handle, ipc_write_cb); if (--sc->num_connects == 0) uv_close((uv_handle_t*) ipc_pipe, NULL); }
void connection_cb(uv_stream_t *server, int status) { int r; if (status) { fprintf(stderr, "connection error %d", status); return; } // main diff between uv_tcp_t and uv_pipe_t is the ipc flag and the pipe_fname pointing to local sock file uv_pipe_t *client = (uv_pipe_t*) malloc(sizeof(uv_pipe_t)); uv_pipe_init(loop, client, NOIPC); r = uv_accept(server, (uv_stream_t*) client); if (r == 0) { uv_write_t *write_req = (uv_write_t*) malloc(sizeof(uv_write_t)); dummy_buf = uv_buf_init(".", 1); struct child_worker *worker = &workers[round_robin_counter]; // Extended write function for sending handles over a pipe // https://github.com/thlorenz/libuv-dox/blob/master/methods.md#uv_write2 uv_write2(write_req, (uv_stream_t*) &worker->pipe, &dummy_buf, 1 /*nbufs*/, (uv_stream_t*) client, NULL); round_robin_counter = (round_robin_counter + 1) % child_worker_count; } else { uv_close((uv_handle_t*) client, NULL); } }
static void read2_cb(uv_pipe_t* handle, ssize_t nread, const uv_buf_t* rdbuf, uv_handle_type pending) { uv_buf_t wrbuf; int r; ASSERT(pending == UV_NAMED_PIPE || pending == UV_TCP); ASSERT(handle == &ctx.channel); ASSERT(nread >= 0); wrbuf = uv_buf_init(".", 1); if (pending == UV_NAMED_PIPE) r = uv_pipe_init(ctx.channel.loop, &ctx.recv.pipe, 0); else if (pending == UV_TCP) r = uv_tcp_init(ctx.channel.loop, &ctx.recv.tcp); else abort(); ASSERT(r == 0); r = uv_accept((uv_stream_t*)handle, &ctx.recv.stream); ASSERT(r == 0); r = uv_write2(&ctx.write_req, (uv_stream_t*)&ctx.channel, &wrbuf, 1, &ctx.recv.stream, write2_cb); ASSERT(r == 0); }
static void ipc_on_connection_tcp_conn(uv_stream_t* server, int status) { int r; uv_buf_t buf; uv_tcp_t* conn; ASSERT(status == 0); ASSERT((uv_stream_t*)&tcp_server == server); conn = malloc(sizeof(*conn)); ASSERT(conn); r = uv_tcp_init(server->loop, conn); ASSERT(r == 0); r = uv_accept(server, (uv_stream_t*)conn); ASSERT(r == 0); /* Send the accepted connection to the other process */ buf = uv_buf_init("hello\n", 6); r = uv_write2(&conn_notify_req, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)conn, NULL); ASSERT(r == 0); r = uv_read_start((uv_stream_t*) conn, on_read_alloc, on_tcp_child_process_read); ASSERT(r == 0); uv_close((uv_handle_t*)conn, close_cb); }
/* The buffers to be written must remain valid until the callback is called. * This is not required for the uv_buf_t array. */ int uv_write(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb) { return uv_write2(req, handle, bufs, nbufs, NULL, cb); }
static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* rdbuf) { uv_buf_t wrbuf; uv_pipe_t* pipe; uv_handle_type pending; int r; union handles* recv; uv_write_t* write_req; if (nread == UV_EOF || nread == UV_ECONNABORTED) { return; } pipe = (uv_pipe_t*) handle; do { if (++read_cb_count == 2) { recv = &ctx2.recv; write_req = &ctx2.write_req; } else { recv = &ctx2.recv2; write_req = &ctx2.write_req2; } ASSERT(pipe == &ctx2.channel); ASSERT(nread >= 0); ASSERT(uv_pipe_pending_count(pipe) > 0); pending = uv_pipe_pending_type(pipe); ASSERT(pending == UV_NAMED_PIPE || pending == UV_TCP); if (pending == UV_NAMED_PIPE) r = uv_pipe_init(ctx2.channel.loop, &recv->pipe, 0); else if (pending == UV_TCP) r = uv_tcp_init(ctx2.channel.loop, &recv->tcp); else abort(); ASSERT(r == 0); r = uv_accept(handle, &recv->stream); ASSERT(r == 0); wrbuf = uv_buf_init(".", 1); r = uv_write2(write_req, (uv_stream_t*)&ctx2.channel, &wrbuf, 1, &recv->stream, write2_cb); ASSERT(r == 0); ASSERT(write_req->send_handle == &recv->stream); } while (uv_pipe_pending_count(pipe) > 0); }
static PyObject * pyuv__stream_write_bytes(Stream *self, PyObject *data, PyObject *callback, PyObject *send_handle) { int err; uv_buf_t buf; stream_write_ctx *ctx; Py_buffer *view; ctx = PyMem_Malloc(sizeof *ctx); if (!ctx) { PyErr_NoMemory(); return NULL; } ctx->views = ctx->viewsml; view = &ctx->views[0]; if (PyObject_GetBuffer(data, view, PyBUF_SIMPLE) != 0) { PyMem_Free(ctx); return NULL; } ctx->view_count = 1; ctx->obj = self; ctx->callback = callback; ctx->send_handle = send_handle; Py_INCREF(callback); Py_XINCREF(send_handle); buf = uv_buf_init(view->buf, view->len); if (send_handle != NULL) { ASSERT(UV_HANDLE(self)->type == UV_NAMED_PIPE); err = uv_write2(&ctx->req, (uv_stream_t *)UV_HANDLE(self), &buf, 1, (uv_stream_t *)UV_HANDLE(send_handle), pyuv__stream_write_cb); } else { err = uv_write(&ctx->req, (uv_stream_t *)UV_HANDLE(self), &buf, 1, pyuv__stream_write_cb); } if (err < 0) { RAISE_STREAM_EXCEPTION(err, UV_HANDLE(self)); Py_DECREF(callback); Py_XDECREF(send_handle); PyBuffer_Release(view); PyMem_Free(ctx); return NULL; } /* Increase refcount so that object is not removed before the callback is called */ Py_INCREF(self); Py_RETURN_NONE; }
int ipc_helper(int listen_after_write) { /* * This is launched from test-ipc.c. stdin is a duplex channel that we * over which a handle will be transmitted. */ struct sockaddr_in addr; uv_write_t write_req; int r; uv_buf_t buf; uv_os_fd_t stdin_handle = uv_convert_fd_to_handle(0); ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_pipe_init(uv_default_loop(), &channel, 1); ASSERT(r == 0); uv_pipe_open(&channel, stdin_handle); ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); ASSERT(r == 0); if (!listen_after_write) { r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection); ASSERT(r == 0); } buf = uv_buf_init("hello\n", 6); r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server, NULL); ASSERT(r == 0); if (listen_after_write) { r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection); ASSERT(r == 0); } r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); ASSERT(connection_accepted == 1); ASSERT(close_cb_called == 3); MAKE_VALGRIND_HAPPY(); return 0; }
int ipc_helper_closed_handle(void) { int r; struct sockaddr_in addr; uv_write_t write_req; uv_write_t write_req2; uv_buf_t buf; char buffer[LARGE_SIZE]; r = uv_pipe_init(uv_default_loop(), &channel, 1); ASSERT(r == 0); uv_pipe_open(&channel, 0); ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); memset(buffer, '.', LARGE_SIZE); buf = uv_buf_init(buffer, LARGE_SIZE); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); ASSERT(r == 0); r = uv_write(&write_req, (uv_stream_t*)&channel, &buf, 1, closed_handle_large_write_cb); ASSERT(r == 0); r = uv_write2(&write_req2, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server, closed_handle_write_cb); ASSERT(r == 0); uv_close((uv_handle_t*)&tcp_server, NULL); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); MAKE_VALGRIND_HAPPY(); return 0; }
static int ipc_helper(int listen_after_write) { /* * This is launched from test-ipc.c. stdin is a duplex channel that we * over which a handle will be transmitted. In this initial version only * data is transfered over the channel. XXX edit this comment after handle * transfer is added. */ uv_write_t write_req; int r; uv_buf_t buf; r = uv_pipe_init(uv_default_loop(), &channel, 1); ASSERT(r == 0); uv_pipe_open(&channel, 0); ASSERT(uv_is_readable(&channel)); ASSERT(uv_is_writable(&channel)); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); r = uv_tcp_bind(&tcp_server, uv_ip4_addr("0.0.0.0", TEST_PORT)); ASSERT(r == 0); if (!listen_after_write) { r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection); ASSERT(r == 0); } buf = uv_buf_init("hello\n", 6); r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server, NULL); ASSERT(r == 0); if (listen_after_write) { r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection); ASSERT(r == 0); } r = uv_run(uv_default_loop()); ASSERT(r == 0); ASSERT(connection_accepted == 1); ASSERT(close_cb_called == 3); return 0; }
int ipc_helper(int listen_after_write) { /* * This is launched from test-ipc.c. stdin is a duplex channel that we * over which a handle will be transmitted. */ uv_write_t write_req; int r; uv_buf_t buf; r = uv_pipe_init(uv_default_loop(), &channel, 1); ASSERT(r == 0); uv_pipe_open(&channel, 0); ASSERT(uv_is_readable((uv_stream_t*) &channel)); ASSERT(uv_is_writable((uv_stream_t*) &channel)); ASSERT(!uv_is_closing((uv_handle_t*) &channel)); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); r = uv_tcp_bind(&tcp_server, uv_ip4_addr("0.0.0.0", TEST_PORT)); ASSERT(r == 0); if (!listen_after_write) { r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection); ASSERT(r == 0); } buf = uv_buf_init("hello\n", 6); r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server, NULL); ASSERT(r == 0); if (listen_after_write) { r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection); ASSERT(r == 0); } r = uv_run(uv_default_loop()); ASSERT(r == 0); ASSERT(connection_accepted == 1); ASSERT(close_cb_called == 3); MAKE_VALGRIND_HAPPY(); return 0; }
void on_new_connection(uv_stream_t *server, int status) { if (status == -1) { // error! return; } uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t)); uv_tcp_init(loop, client); if (uv_accept(server, (uv_stream_t*) client) == 0) { uv_write_t *write_req = (uv_write_t*) malloc(sizeof(uv_write_t)); dummy_buf = uv_buf_init(".", 1); struct child_worker *worker = &workers[round_robin_counter]; uv_write2(write_req, (uv_stream_t*) &worker->pipe, &dummy_buf, 1, (uv_stream_t*) client, NULL); round_robin_counter = (round_robin_counter + 1) % child_worker_count; } else { uv_close((uv_handle_t*) client, NULL); } }
static INLINE PyObject * pyuv_stream_write(Stream *self, stream_write_ctx *ctx, Py_buffer *views, uv_buf_t *bufs, int buf_count, PyObject *callback, PyObject *send_handle) { int i, err; Py_INCREF(callback); Py_XINCREF(send_handle); ctx->obj = self; ctx->callback = callback; ctx->send_handle = send_handle; ctx->views = views; ctx->view_count = buf_count; if (send_handle) { err = uv_write2(&ctx->req, (uv_stream_t *)UV_HANDLE(self), bufs, buf_count, (uv_stream_t *)UV_HANDLE(send_handle), on_stream_write); } else { err = uv_write(&ctx->req, (uv_stream_t *)UV_HANDLE(self), bufs, buf_count, on_stream_write); } if (err < 0) { RAISE_STREAM_EXCEPTION(err, UV_HANDLE(self)); goto error; } /* Increase refcount so that object is not removed before the callback is called */ Py_INCREF(self); Py_RETURN_NONE; error: Py_DECREF(callback); Py_XDECREF(send_handle); for (i = 0; i < buf_count; i++) { PyBuffer_Release(&views[i]); } if (ctx->views != ctx->view) { PyMem_Free(views); } PyMem_Free(ctx); return NULL; }
static int couv_write2(lua_State *L) { uv_write_t *req; uv_stream_t *handle; uv_buf_t *bufs; size_t bufcnt; uv_stream_t *send_handle; int r; handle = couvL_checkudataclass(L, 1, COUV_STREAM_MTBL_NAME); bufs = couv_checkbuforstrtable(L, 2, &bufcnt); send_handle = couvL_checkudataclass(L, 3, COUV_STREAM_MTBL_NAME); req = couv_alloc(L, sizeof(uv_write_t)); req->data = bufs; r = uv_write2(req, handle, bufs, (int)bufcnt, send_handle, write_cb); if (r < 0) { luaL_error(L, couvL_uv_lasterrname(couv_loop(L))); } return lua_yield(L, 0); }
static PyObject * pyuv__stream_write_sequence(Stream *self, PyObject *data, PyObject *callback, PyObject *send_handle) { int err; stream_write_ctx *ctx; PyObject *data_fast, *item; Py_ssize_t i, j, buf_count; data_fast = PySequence_Fast(data, "data must be an iterable"); if (data_fast == NULL) return NULL; buf_count = PySequence_Fast_GET_SIZE(data_fast); if (buf_count > INT_MAX) { PyErr_SetString(PyExc_ValueError, "iterable is too long"); Py_DECREF(data_fast); return NULL; } if (buf_count == 0) { PyErr_SetString(PyExc_ValueError, "iterable is empty"); Py_DECREF(data_fast); return NULL; } ctx = PyMem_Malloc(sizeof *ctx); if (!ctx) { PyErr_NoMemory(); Py_DECREF(data_fast); return NULL; } ctx->views = ctx->viewsml; if (buf_count > ARRAY_SIZE(ctx->viewsml)) ctx->views = PyMem_Malloc(sizeof(Py_buffer) * buf_count); if (!ctx->views) { PyErr_NoMemory(); PyMem_Free(ctx); Py_DECREF(data_fast); return NULL; } ctx->view_count = buf_count; { STACK_ARRAY(uv_buf_t, bufs, buf_count); for (i = 0; i < buf_count; i++) { item = PySequence_Fast_GET_ITEM(data_fast, i); if (PyObject_GetBuffer(item, &ctx->views[i], PyBUF_SIMPLE) != 0) goto error; bufs[i].base = ctx->views[i].buf; bufs[i].len = ctx->views[i].len; } ctx->obj = self; ctx->callback = callback; ctx->send_handle = send_handle; Py_INCREF(callback); Py_XINCREF(send_handle); if (send_handle != NULL) { ASSERT(UV_HANDLE(self)->type == UV_NAMED_PIPE); err = uv_write2(&ctx->req, (uv_stream_t *)UV_HANDLE(self), bufs, buf_count, (uv_stream_t *)UV_HANDLE(send_handle), pyuv__stream_write_cb); } else { err = uv_write(&ctx->req, (uv_stream_t *)UV_HANDLE(self), bufs, buf_count, pyuv__stream_write_cb); } } if (err < 0) { RAISE_STREAM_EXCEPTION(err, UV_HANDLE(self)); Py_DECREF(callback); Py_XDECREF(send_handle); goto error; } /* Increase refcount so that object is not removed before the callback is called */ Py_INCREF(self); Py_RETURN_NONE; error: for (j = 0; j < i; j++) PyBuffer_Release(&ctx->views[j]); if (ctx->views != ctx->viewsml) PyMem_Free(ctx->views); PyMem_Free(ctx); Py_XDECREF(data_fast); return NULL; }
/* The buffers to be written must remain valid until the callback is called. * This is not required for the uv_buf_t array. */ int uv_write(uv_write_t* req, uv_stream_t* stream, uv_buf_t bufs[], int bufcnt, uv_write_cb cb) { return uv_write2(req, stream, bufs, bufcnt, NULL, cb); }