1 /* Copyright libuv project 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 "uv.h" 23 #include "task.h" 24 25 static uv_tcp_t server; 26 static uv_tcp_t connection; 27 static int read_cb_called = 0; 28 29 static uv_tcp_t client; 30 static uv_connect_t connect_req; 31 32 33 static void on_read2(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf); 34 35 static void on_write_close_immediately(uv_write_t* req, int status) { 36 ASSERT(0 == status); 37 38 uv_close((uv_handle_t*)req->handle, NULL); /* Close immediately */ 39 free(req); 40 } 41 42 static void on_write(uv_write_t* req, int status) { 43 ASSERT(0 == status); 44 45 free(req); 46 } 47 48 static void do_write(uv_stream_t* stream, uv_write_cb cb) { 49 uv_write_t* req = malloc(sizeof(*req)); 50 uv_buf_t buf; 51 buf.base = "1234578"; 52 buf.len = 8; 53 ASSERT(0 == uv_write(req, stream, &buf, 1, cb)); 54 } 55 56 static void on_alloc(uv_handle_t* handle, 57 size_t suggested_size, 58 uv_buf_t* buf) { 59 static char slab[65536]; 60 buf->base = slab; 61 buf->len = sizeof(slab); 62 } 63 64 static void on_read1(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { 65 ASSERT(nread >= 0); 66 67 /* Do write on a half open connection to force WSAECONNABORTED (on Windows) 68 * in the subsequent uv_read_start() 69 */ 70 do_write(stream, on_write); 71 72 ASSERT(0 == uv_read_stop(stream)); 73 74 ASSERT(0 == uv_read_start(stream, on_alloc, on_read2)); 75 76 read_cb_called++; 77 } 78 79 static void on_read2(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { 80 ASSERT(nread < 0); 81 82 uv_close((uv_handle_t*)stream, NULL); 83 uv_close((uv_handle_t*)&server, NULL); 84 85 read_cb_called++; 86 } 87 88 static void on_connection(uv_stream_t* server, int status) { 89 ASSERT(0 == status); 90 91 ASSERT(0 == uv_tcp_init(server->loop, &connection)); 92 93 ASSERT(0 == uv_accept(server, (uv_stream_t* )&connection)); 94 95 ASSERT(0 == uv_read_start((uv_stream_t*)&connection, on_alloc, on_read1)); 96 } 97 98 static void on_connect(uv_connect_t* req, int status) { 99 ASSERT(0 == status); 100 101 do_write((uv_stream_t*)&client, on_write_close_immediately); 102 } 103 104 TEST_IMPL(tcp_read_stop_start) { 105 uv_loop_t* loop = uv_default_loop(); 106 107 { /* Server */ 108 struct sockaddr_in addr; 109 110 ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); 111 112 ASSERT(0 == uv_tcp_init(loop, &server)); 113 114 ASSERT(0 == uv_tcp_bind(&server, (struct sockaddr*) & addr, 0)); 115 116 ASSERT(0 == uv_listen((uv_stream_t*)&server, 10, on_connection)); 117 } 118 119 { /* Client */ 120 struct sockaddr_in addr; 121 122 ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 123 124 ASSERT(0 == uv_tcp_init(loop, &client)); 125 126 ASSERT(0 == uv_tcp_connect(&connect_req, &client, 127 (const struct sockaddr*) & addr, on_connect)); 128 } 129 130 ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); 131 132 ASSERT(read_cb_called >= 2); 133 134 MAKE_VALGRIND_HAPPY(); 135 return 0; 136 } 137