1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 */ 21 22 #include <assert.h> 23 24 #include "uv.h" 25 #include "internal.h" 26 #include "handle-inl.h" 27 #include "req-inl.h" 28 29 30 int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { 31 int err; 32 if (uv__is_closing(stream)) { 33 return UV_EINVAL; 34 } 35 err = ERROR_INVALID_PARAMETER; 36 switch (stream->type) { 37 case UV_TCP: 38 err = uv__tcp_listen((uv_tcp_t*)stream, backlog, cb); 39 break; 40 case UV_NAMED_PIPE: 41 err = uv__pipe_listen((uv_pipe_t*)stream, backlog, cb); 42 break; 43 default: 44 assert(0); 45 } 46 47 return uv_translate_sys_error(err); 48 } 49 50 51 int uv_accept(uv_stream_t* server, uv_stream_t* client) { 52 int err; 53 54 err = ERROR_INVALID_PARAMETER; 55 switch (server->type) { 56 case UV_TCP: 57 err = uv__tcp_accept((uv_tcp_t*)server, (uv_tcp_t*)client); 58 break; 59 case UV_NAMED_PIPE: 60 err = uv__pipe_accept((uv_pipe_t*)server, client); 61 break; 62 default: 63 assert(0); 64 } 65 66 return uv_translate_sys_error(err); 67 } 68 69 70 int uv__read_start(uv_stream_t* handle, 71 uv_alloc_cb alloc_cb, 72 uv_read_cb read_cb) { 73 int err; 74 75 err = ERROR_INVALID_PARAMETER; 76 switch (handle->type) { 77 case UV_TCP: 78 err = uv__tcp_read_start((uv_tcp_t*)handle, alloc_cb, read_cb); 79 break; 80 case UV_NAMED_PIPE: 81 err = uv__pipe_read_start((uv_pipe_t*)handle, alloc_cb, read_cb); 82 break; 83 case UV_TTY: 84 err = uv__tty_read_start((uv_tty_t*) handle, alloc_cb, read_cb); 85 break; 86 default: 87 assert(0); 88 } 89 90 return uv_translate_sys_error(err); 91 } 92 93 94 int uv_read_stop(uv_stream_t* handle) { 95 int err; 96 97 if (!(handle->flags & UV_HANDLE_READING)) 98 return 0; 99 100 err = 0; 101 if (handle->type == UV_TTY) { 102 err = uv__tty_read_stop((uv_tty_t*) handle); 103 } else if (handle->type == UV_NAMED_PIPE) { 104 uv__pipe_read_stop((uv_pipe_t*) handle); 105 } else { 106 handle->flags &= ~UV_HANDLE_READING; 107 DECREASE_ACTIVE_COUNT(handle->loop, handle); 108 } 109 110 return uv_translate_sys_error(err); 111 } 112 113 114 int uv_write(uv_write_t* req, 115 uv_stream_t* handle, 116 const uv_buf_t bufs[], 117 unsigned int nbufs, 118 uv_write_cb cb) { 119 uv_loop_t* loop = handle->loop; 120 int err; 121 122 if (!(handle->flags & UV_HANDLE_WRITABLE)) { 123 return UV_EPIPE; 124 } 125 126 err = ERROR_INVALID_PARAMETER; 127 switch (handle->type) { 128 case UV_TCP: 129 err = uv__tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb); 130 break; 131 case UV_NAMED_PIPE: 132 err = uv__pipe_write( 133 loop, req, (uv_pipe_t*) handle, bufs, nbufs, NULL, cb); 134 break; 135 case UV_TTY: 136 err = uv__tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb); 137 break; 138 default: 139 assert(0); 140 } 141 142 return uv_translate_sys_error(err); 143 } 144 145 146 int uv_write2(uv_write_t* req, 147 uv_stream_t* handle, 148 const uv_buf_t bufs[], 149 unsigned int nbufs, 150 uv_stream_t* send_handle, 151 uv_write_cb cb) { 152 uv_loop_t* loop = handle->loop; 153 int err; 154 155 if (send_handle == NULL) { 156 return uv_write(req, handle, bufs, nbufs, cb); 157 } 158 159 if (handle->type != UV_NAMED_PIPE || !((uv_pipe_t*) handle)->ipc) { 160 return UV_EINVAL; 161 } else if (!(handle->flags & UV_HANDLE_WRITABLE)) { 162 return UV_EPIPE; 163 } 164 165 err = uv__pipe_write( 166 loop, req, (uv_pipe_t*) handle, bufs, nbufs, send_handle, cb); 167 return uv_translate_sys_error(err); 168 } 169 170 171 int uv_try_write(uv_stream_t* stream, 172 const uv_buf_t bufs[], 173 unsigned int nbufs) { 174 if (stream->flags & UV_HANDLE_CLOSING) 175 return UV_EBADF; 176 if (!(stream->flags & UV_HANDLE_WRITABLE)) 177 return UV_EPIPE; 178 179 switch (stream->type) { 180 case UV_TCP: 181 return uv__tcp_try_write((uv_tcp_t*) stream, bufs, nbufs); 182 case UV_TTY: 183 return uv__tty_try_write((uv_tty_t*) stream, bufs, nbufs); 184 case UV_NAMED_PIPE: 185 return UV_EAGAIN; 186 default: 187 assert(0); 188 return UV_ENOSYS; 189 } 190 } 191 192 193 int uv_try_write2(uv_stream_t* stream, 194 const uv_buf_t bufs[], 195 unsigned int nbufs, 196 uv_stream_t* send_handle) { 197 if (send_handle != NULL) 198 return UV_EAGAIN; 199 return uv_try_write(stream, bufs, nbufs); 200 } 201 202 203 int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { 204 uv_loop_t* loop = handle->loop; 205 206 if (!(handle->flags & UV_HANDLE_WRITABLE) || 207 handle->flags & UV_HANDLE_SHUTTING || 208 uv__is_closing(handle)) { 209 return UV_ENOTCONN; 210 } 211 212 UV_REQ_INIT(req, UV_SHUTDOWN); 213 req->handle = handle; 214 req->cb = cb; 215 216 handle->flags &= ~UV_HANDLE_WRITABLE; 217 handle->flags |= UV_HANDLE_SHUTTING; 218 handle->stream.conn.shutdown_req = req; 219 handle->reqs_pending++; 220 REGISTER_HANDLE_REQ(loop, handle, req); 221 222 if (handle->stream.conn.write_reqs_pending == 0) { 223 if (handle->type == UV_NAMED_PIPE) 224 uv__pipe_shutdown(loop, (uv_pipe_t*) handle, req); 225 else 226 uv__insert_pending_req(loop, (uv_req_t*) req); 227 } 228 229 return 0; 230 } 231 232 233 int uv_is_readable(const uv_stream_t* handle) { 234 return !!(handle->flags & UV_HANDLE_READABLE); 235 } 236 237 238 int uv_is_writable(const uv_stream_t* handle) { 239 return !!(handle->flags & UV_HANDLE_WRITABLE); 240 } 241 242 243 int uv_stream_set_blocking(uv_stream_t* handle, int blocking) { 244 if (handle->type != UV_NAMED_PIPE) 245 return UV_EINVAL; 246 247 if (blocking != 0) 248 handle->flags |= UV_HANDLE_BLOCKING_WRITES; 249 else 250 handle->flags &= ~UV_HANDLE_BLOCKING_WRITES; 251 252 return 0; 253 } 254