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 "uv.h" 23#include "task.h" 24 25#include <stdio.h> 26#include <stdlib.h> 27#include <string.h> 28 29#define MAX_BYTES 1024 * 1024 30 31static uv_tcp_t server; 32static uv_tcp_t client; 33static uv_tcp_t incoming; 34static int connect_cb_called; 35static int close_cb_called; 36static int connection_cb_called; 37static int bytes_read; 38static int bytes_written; 39 40 41static void close_cb(uv_handle_t* handle) { 42 close_cb_called++; 43} 44 45 46static void connect_cb(uv_connect_t* req, int status) { 47 int r; 48 uv_buf_t buf; 49 ASSERT(status == 0); 50 connect_cb_called++; 51 52 do { 53 buf = uv_buf_init("PING", 4); 54 r = uv_try_write((uv_stream_t*) &client, &buf, 1); 55 ASSERT(r > 0 || r == UV_EAGAIN); 56 if (r > 0) { 57 bytes_written += r; 58 break; 59 } 60 } while (1); 61 62 do { 63 buf = uv_buf_init("", 0); 64 r = uv_try_write((uv_stream_t*) &client, &buf, 1); 65 } while (r != 0); 66 uv_close((uv_handle_t*) &client, close_cb); 67} 68 69 70static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { 71 static char base[1024]; 72 73 buf->base = base; 74 buf->len = sizeof(base); 75} 76 77 78static void read_cb(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) { 79 if (nread < 0) { 80 uv_close((uv_handle_t*) tcp, close_cb); 81 uv_close((uv_handle_t*) &server, close_cb); 82 return; 83 } 84 85 bytes_read += nread; 86} 87 88 89static void connection_cb(uv_stream_t* tcp, int status) { 90 ASSERT(status == 0); 91 92 ASSERT(0 == uv_tcp_init(tcp->loop, &incoming)); 93 ASSERT(0 == uv_accept(tcp, (uv_stream_t*) &incoming)); 94 95 connection_cb_called++; 96 ASSERT(0 == uv_read_start((uv_stream_t*) &incoming, alloc_cb, read_cb)); 97} 98 99 100static void start_server(void) { 101 struct sockaddr_in addr; 102 103 ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); 104 105 ASSERT(0 == uv_tcp_init(uv_default_loop(), &server)); 106 ASSERT(0 == uv_tcp_bind(&server, (struct sockaddr*) &addr, 0)); 107 ASSERT(0 == uv_listen((uv_stream_t*) &server, 128, connection_cb)); 108} 109 110 111TEST_IMPL(tcp_try_write) { 112 uv_connect_t connect_req; 113 struct sockaddr_in addr; 114 115 start_server(); 116 117 ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 118 119 ASSERT(0 == uv_tcp_init(uv_default_loop(), &client)); 120 ASSERT(0 == uv_tcp_connect(&connect_req, 121 &client, 122 (struct sockaddr*) &addr, 123 connect_cb)); 124 125 ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); 126 127 ASSERT(connect_cb_called == 1); 128 ASSERT(close_cb_called == 3); 129 ASSERT(connection_cb_called == 1); 130 ASSERT(bytes_read == bytes_written); 131 ASSERT(bytes_written > 0); 132 133 MAKE_VALGRIND_HAPPY(); 134 return 0; 135} 136