From 79e279ee12a4ed80ab815b6a22a9fe5f893c7eab Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Sun, 27 May 2012 09:48:59 -0700 Subject: std: kludge export of net_ip in std.rc until submodule export is sorted --- src/libstd/std.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/std.rc b/src/libstd/std.rc index 2effb04cd3f..34707271217 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -15,7 +15,7 @@ use core(vers = "0.2"); import core::*; -export net, net_tcp; +export net, net_tcp, net_ip; export uv, uv_ll, uv_iotask, uv_global_loop; export c_vec, util, timer; export bitv, deque, fun_treemap, list, map, smallintmap, sort, treemap; -- cgit 1.4.1-3-g733a5 From 900e4460155c0022c8bbe8d53506d0262929f581 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Sun, 27 May 2012 09:49:33 -0700 Subject: std: import/export cleanup in net_tcp --- src/libstd/net_tcp.rs | 86 +++++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 41 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 8c637f0089e..81171dc51ae 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -7,8 +7,10 @@ import uv::iotask; import uv::iotask::iotask; import comm::methods; import future_spawn = future::spawn; -import future::future; -import result::{result,err,ok,extensions}; +// FIXME: should be able to replace w/ result::{result, extensions}; +import result::*; +import libc::size_t; +import str::extensions; // data export tcp_socket, tcp_conn_port, tcp_err_data; @@ -20,7 +22,7 @@ export new_listener, conn_recv, conn_recv_spawn, conn_peek; // tcp client stuff export connect; // helper methods -export conn_port_methods, sock_methods; +export methods; #[nolink] native mod rustrt { @@ -775,44 +777,46 @@ fn listen_for_conn(host_ip: ip::ip_addr, port: uint, backlog: uint, } } } - -#[doc=" -Convenience methods extending `net::tcp::tcp_conn_port` -"] -impl conn_port_methods for tcp_conn_port { - fn recv() -> result::result { conn_recv(self) } - fn recv_spawn(+cb: fn~(result::result)) - { conn_recv_spawn(self, cb); } - fn peek() -> bool { conn_peek(self) } -} - -#[doc=" -Convenience methods extending `net::tcp::tcp_socket` -"] -impl sock_methods for tcp_socket { - fn read_start() -> result::result>, tcp_err_data> { - read_start(self) - } - fn read_stop() -> - result::result<(), tcp_err_data> { - read_stop(self) - } - fn read(timeout_msecs: uint) -> - result::result<[u8]/~, tcp_err_data> { - read(self, timeout_msecs) +mod methods { + #[doc=" + Convenience methods extending `net::tcp::tcp_conn_port` + "] + impl methods_tcp_conn_port for tcp_conn_port { + fn recv() -> result::result { + conn_recv(self) } + fn recv_spawn(cb: fn~(result::result)) + { conn_recv_spawn(self, cb); } + fn peek() -> bool { conn_peek(self) } } - fn read_future(timeout_msecs: uint) -> - future> { - read_future(self, timeout_msecs) - } - fn write(raw_write_data: [u8]/~) - -> result::result<(), tcp_err_data> { - write(self, raw_write_data) - } - fn write_future(raw_write_data: [u8]/~) - -> future> { - write_future(self, raw_write_data) + + #[doc=" + Convenience methods extending `net::tcp::tcp_socket` + "] + impl methods_tcp_socket for tcp_socket { + fn read_start() -> result::result>, tcp_err_data> { + read_start(self) + } + fn read_stop() -> + result::result<(), tcp_err_data> { + read_stop(self) + } + fn read(timeout_msecs: uint) -> + result::result<[u8]/~, tcp_err_data> { + read(self, timeout_msecs) + } + fn read_future(timeout_msecs: uint) -> + future::future> { + read_future(self, timeout_msecs) + } + fn write(raw_write_data: [u8]/~) + -> result::result<(), tcp_err_data> { + write(self, raw_write_data) + } + fn write_future(raw_write_data: [u8]/~) + -> future::future> { + write_future(self, raw_write_data) + } } } // INTERNAL API @@ -1171,7 +1175,7 @@ crust fn on_tcp_read_cb(stream: *uv::ll::uv_stream_t, } crust fn on_alloc_cb(handle: *libc::c_void, - ++suggested_size: libc::size_t) + ++suggested_size: size_t) -> uv::ll::uv_buf_t unsafe { log(debug, "tcp read on_alloc_cb!"); let char_ptr = uv::ll::malloc_buf_base_of(suggested_size); -- cgit 1.4.1-3-g733a5 From 5d86686e7facd7a5e5acc1c8b682310ad1fe878c Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Sun, 27 May 2012 22:50:11 -0700 Subject: std: mod cleanup, impl/test for conn. refused err + mem leak fix --- src/libstd/net_tcp.rs | 135 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 100 insertions(+), 35 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 81171dc51ae..fde1ef490b5 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -12,8 +12,10 @@ import result::*; import libc::size_t; import str::extensions; -// data -export tcp_socket, tcp_conn_port, tcp_err_data; +// tcp interfaces +export tcp_socket, tcp_conn_port; +// errors +export tcp_err_data, tcp_connect_err_data; // operations on a tcp_socket export write, write_future, read_start, read_stop; // tcp server stuff @@ -22,6 +24,7 @@ export new_listener, conn_recv, conn_recv_spawn, conn_peek; // tcp client stuff export connect; // helper methods +import methods = net_tcp_methods; export methods; #[nolink] @@ -43,25 +46,7 @@ class tcp_socket { new(socket_data: @tcp_socket_data) { self.socket_data = socket_data; } drop { unsafe { - let closed_po = comm::port::<()>(); - let closed_ch = comm::chan(closed_po); - let close_data = { - closed_ch: closed_ch - }; - let close_data_ptr = ptr::addr_of(close_data); - let stream_handle_ptr = (*(self.socket_data)).stream_handle_ptr; - iotask::interact((*(self.socket_data)).iotask) {|loop_ptr| - log(debug, #fmt("interact dtor for tcp_socket stream %? loop %?", - stream_handle_ptr, loop_ptr)); - uv::ll::set_data_for_uv_handle(stream_handle_ptr, - close_data_ptr); - uv::ll::close(stream_handle_ptr, tcp_socket_dtor_close_cb); - }; - comm::recv(closed_po); - log(debug, #fmt("about to free socket_data at %?", self.socket_data)); - rustrt::rust_uv_current_kernel_free(stream_handle_ptr - as *libc::c_void); - log(debug, "exiting dtor for tcp_socket"); + tear_down_socket_data(socket_data) } } } @@ -90,6 +75,17 @@ type tcp_err_data = { err_name: str, err_msg: str }; +enum tcp_connect_err_data { + #[doc=" + Some unplanned-for error. The first and second fields correspond + to libuv's `err_name` and `err_msg` fields, respectively. + "] + generic_connect_err(str, str), + #[doc=" + Invalid IP or invalid port + "] + connection_refused +} #[doc=" Initiate a client connection over TCP/IP @@ -108,7 +104,7 @@ of failure, a `tcp_err_data` will be returned "] fn connect(input_ip: ip::ip_addr, port: uint, iotask: iotask) - -> result::result unsafe { + -> result::result unsafe { let result_po = comm::port::(); let closed_signal_po = comm::port::<()>(); let conn_data = { @@ -198,7 +194,14 @@ fn connect(input_ip: ip::ip_addr, port: uint, conn_failure(err_data) { comm::recv(closed_signal_po); log(debug, "tcp::connect - received failure on result_po"); - result::err(err_data.to_tcp_err()) + // still have to free the malloc'd stream handle.. + rustrt::rust_uv_current_kernel_free(stream_handle_ptr + as *libc::c_void); + let tcp_conn_err = alt err_data.err_name { + "ECONNREFUSED" { connection_refused } + _ { generic_connect_err(err_data.err_name, err_data.err_msg) } + }; + result::err(tcp_conn_err) } } } @@ -777,7 +780,8 @@ fn listen_for_conn(host_ip: ip::ip_addr, port: uint, backlog: uint, } } } -mod methods { + +mod net_tcp_methods { #[doc=" Convenience methods extending `net::tcp::tcp_conn_port` "] @@ -821,6 +825,28 @@ mod methods { } // INTERNAL API +fn tear_down_socket_data(socket_data: @tcp_socket_data) unsafe { + let closed_po = comm::port::<()>(); + let closed_ch = comm::chan(closed_po); + let close_data = { + closed_ch: closed_ch + }; + let close_data_ptr = ptr::addr_of(close_data); + let stream_handle_ptr = (*socket_data).stream_handle_ptr; + iotask::interact((*socket_data).iotask) {|loop_ptr| + log(debug, #fmt("interact dtor for tcp_socket stream %? loop %?", + stream_handle_ptr, loop_ptr)); + uv::ll::set_data_for_uv_handle(stream_handle_ptr, + close_data_ptr); + uv::ll::close(stream_handle_ptr, tcp_socket_dtor_close_cb); + }; + comm::recv(closed_po); + log(debug, #fmt("about to free socket_data at %?", socket_data)); + rustrt::rust_uv_current_kernel_free(stream_handle_ptr + as *libc::c_void); + log(debug, "exiting dtor for tcp_socket"); +} + // shared implementation for tcp::read fn read_common_impl(socket_data: *tcp_socket_data, timeout_msecs: uint) -> result::result<[u8]/~,tcp_err_data> unsafe { @@ -1308,6 +1334,10 @@ mod test { fn test_gl_tcp_server_listener_and_client_ipv4() unsafe { impl_gl_tcp_ipv4_server_listener_and_client(); } + #[test] + fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe { + impl_gl_tcp_ipv4_client_error_connection_refused(); + } } #[cfg(target_arch="x86")] mod impl32 { @@ -1321,6 +1351,11 @@ mod test { fn test_gl_tcp_server_listener_and_client_ipv4() unsafe { impl_gl_tcp_ipv4_server_listener_and_client(); } + #[test] + #[ignore(cfg(target_os = "linux"))] + fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe { + impl_gl_tcp_ipv4_client_error_connection_refused(); + } } } fn impl_gl_tcp_ipv4_server_and_client() { @@ -1351,7 +1386,7 @@ mod test { comm::recv(cont_po); // client log(debug, "server started, firing up client.."); - let actual_resp = comm::listen {|client_ch| + let actual_resp_result = comm::listen {|client_ch| run_tcp_test_client( server_ip, server_port, @@ -1359,6 +1394,8 @@ mod test { client_ch, hl_loop) }; + assert actual_resp_result.is_success(); + let actual_resp = actual_resp_result.get(); let actual_req = comm::recv(server_result_po); log(debug, #fmt("REQ: expected: '%s' actual: '%s'", expected_req, actual_req)); @@ -1395,7 +1432,7 @@ mod test { comm::recv(cont_po); // client log(debug, "server started, firing up client.."); - let actual_resp = comm::listen {|client_ch| + let actual_resp_result = comm::listen {|client_ch| run_tcp_test_client( server_ip, server_port, @@ -1403,6 +1440,8 @@ mod test { client_ch, hl_loop) }; + assert actual_resp_result.is_success(); + let actual_resp = actual_resp_result.get(); let actual_req = comm::recv(server_result_po); log(debug, #fmt("REQ: expected: '%s' actual: '%s'", expected_req, actual_req)); @@ -1411,6 +1450,29 @@ mod test { assert str::contains(actual_req, expected_req); assert str::contains(actual_resp, expected_resp); } + fn impl_gl_tcp_ipv4_client_error_connection_refused() { + let hl_loop = uv::global_loop::get(); + let server_ip = "127.0.0.1"; + let server_port = 8890u; + let expected_req = "ping"; + // client + log(debug, "firing up client.."); + let actual_resp_result = comm::listen {|client_ch| + run_tcp_test_client( + server_ip, + server_port, + expected_req, + client_ch, + hl_loop) + }; + alt actual_resp_result.get_err() { + connection_refused { + } + _ { + fail "unknown error.. expected connection_refused" + } + } + } fn run_tcp_test_server(server_ip: str, server_port: uint, resp: str, server_ch: comm::chan, @@ -1453,7 +1515,7 @@ mod test { let sock = result::unwrap(accept_result); log(debug, "SERVER: successfully accepted"+ "connection!"); - let received_req_bytes = sock.read(0u); + let received_req_bytes = read(sock, 0u); alt received_req_bytes { result::ok(data) { server_ch.send( @@ -1522,7 +1584,7 @@ mod test { log(debug, "SERVER: successfully accepted"+ "connection!"); let received_req_bytes = - sock.read(0u); + read(sock, 0u); alt received_req_bytes { result::ok(data) { server_ch.send( @@ -1543,8 +1605,8 @@ mod test { fn run_tcp_test_client(server_ip: str, server_port: uint, resp: str, client_ch: comm::chan, - iotask: iotask) -> str { - + iotask: iotask) -> result::result { let server_ip_addr = ip::v4::parse_addr(server_ip); log(debug, "CLIENT: starting.."); @@ -1552,9 +1614,7 @@ mod test { if result::is_err(connect_result) { log(debug, "CLIENT: failed to connect"); let err_data = result::get_err(connect_result); - log(debug, #fmt("CLIENT: connect err name: %s msg: %s", - err_data.err_name, err_data.err_msg)); - "" + err(err_data) } else { let sock = result::unwrap(connect_result); @@ -1563,20 +1623,25 @@ mod test { let read_result = sock.read(0u); if read_result.is_err() { log(debug, "CLIENT: failure to read"); - "" + ok("") } else { client_ch.send(str::from_bytes(read_result.get())); let ret_val = client_ch.recv(); log(debug, #fmt("CLIENT: after client_ch recv ret: '%s'", ret_val)); - ret_val + ok(ret_val) } } } +<<<<<<< HEAD fn tcp_write_single(sock: tcp_socket, val: [u8]/~) { let write_result_future = sock.write_future(val); +======= + fn tcp_write_single(sock: tcp_socket, val: [u8]) { + let write_result_future = write_future(sock, val); +>>>>>>> std: mod cleanup, impl/test for conn. refused err + mem leak fix let write_result = write_result_future.get(); if result::is_err(write_result) { log(debug, "tcp_write_single: write failed!"); -- cgit 1.4.1-3-g733a5 From 68e129dc39b29a2a67dda9da2c123c111b271522 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 29 May 2012 05:47:21 -0700 Subject: std: dump the tcp::new_listener server API --- src/libstd/net_tcp.rs | 209 ++------------------------------------------------ 1 file changed, 7 insertions(+), 202 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index fde1ef490b5..1f732978f4b 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -13,14 +13,13 @@ import libc::size_t; import str::extensions; // tcp interfaces -export tcp_socket, tcp_conn_port; +export tcp_socket; // errors export tcp_err_data, tcp_connect_err_data; // operations on a tcp_socket export write, write_future, read_start, read_stop; // tcp server stuff export listen_for_conn, accept; -export new_listener, conn_recv, conn_recv_spawn, conn_peek; // tcp client stuff export connect; // helper methods @@ -51,23 +50,6 @@ class tcp_socket { } } -class tcp_conn_port { - let conn_data: @tcp_conn_port_data; - new(conn_data: @tcp_conn_port_data) { self.conn_data = conn_data; } - drop unsafe { - let conn_data_ptr = ptr::addr_of(*(self.conn_data)); - let server_stream_ptr = ptr::addr_of((*conn_data_ptr).server_stream); - let stream_closed_po = (*(self.conn_data)).stream_closed_po; - let iotask = (*conn_data_ptr).iotask; - iotask::interact(iotask) {|loop_ptr| - log(debug, #fmt("dtor for tcp_conn_port loop: %?", - loop_ptr)); - uv::ll::close(server_stream_ptr, tcp_nl_close_cb); - } - comm::recv(stream_closed_po); - } -} - #[doc=" Contains raw, string-based, error information returned from libuv "] @@ -351,6 +333,7 @@ fn read_future(sock: tcp_socket, timeout_msecs: uint) } #[doc=" +<<<<<<< HEAD Bind to a given IP/port and listen for new connections # Arguments @@ -527,6 +510,8 @@ fn conn_peek(server_port: tcp_conn_port) -> bool { } #[doc=" +======= +>>>>>>> std: dump the tcp::new_listener server API Bind an incoming client connection to a `net::tcp::tcp_socket` # Notes @@ -782,17 +767,6 @@ fn listen_for_conn(host_ip: ip::ip_addr, port: uint, backlog: uint, } mod net_tcp_methods { - #[doc=" - Convenience methods extending `net::tcp::tcp_conn_port` - "] - impl methods_tcp_conn_port for tcp_conn_port { - fn recv() -> result::result { - conn_recv(self) } - fn recv_spawn(cb: fn~(result::result)) - { conn_recv_spawn(self, cb); } - fn peek() -> bool { conn_peek(self) } - } - #[doc=" Convenience methods extending `net::tcp::tcp_socket` "] @@ -993,6 +967,7 @@ fn write_common_impl(socket_data_ptr: *tcp_socket_data, } } +<<<<<<< HEAD // various recv_* can use a tcp_conn_port can re-use this.. fn conn_port_new_tcp_socket( stream_handle_ptr: *uv::ll::uv_tcp_t, @@ -1022,21 +997,12 @@ fn conn_port_new_tcp_socket( result::ok(tcp_socket(client_socket_data)) } +======= +>>>>>>> std: dump the tcp::new_listener server API enum tcp_new_connection { new_tcp_conn(*uv::ll::uv_tcp_t) } -type tcp_conn_port_data = { - server_stream: uv::ll::uv_tcp_t, - stream_closed_po: comm::port<()>, - stream_closed_ch: comm::chan<()>, - iotask: iotask, - new_conn_po: comm::port>, - new_conn_ch: comm::chan> -}; - type tcp_listen_fc_data = { server_stream_ptr: *uv::ll::uv_tcp_t, stream_closed_ch: comm::chan<()>, @@ -1075,66 +1041,11 @@ crust fn tcp_lfc_on_connection_cb(handle: *uv::ll::uv_tcp_t, } } -crust fn tcp_nl_close_cb(handle: *uv::ll::uv_tcp_t) unsafe { - let conn_data_ptr = uv::ll::get_data_for_uv_handle( - handle) as *tcp_conn_port_data; - comm::send((*conn_data_ptr).stream_closed_ch, ()); -} - fn malloc_uv_tcp_t() -> *uv::ll::uv_tcp_t unsafe { rustrt::rust_uv_current_kernel_malloc( rustrt::rust_uv_helper_uv_tcp_t_size()) as *uv::ll::uv_tcp_t } -crust fn tcp_nl_on_connection_cb(server_handle_ptr: *uv::ll::uv_tcp_t, - status: libc::c_int) unsafe { - let server_data_ptr = uv::ll::get_data_for_uv_handle(server_handle_ptr) - as *tcp_conn_port_data; - let new_conn_ch = (*server_data_ptr).new_conn_ch; - let loop_ptr = uv::ll::get_loop_for_uv_handle(server_handle_ptr); - alt status { - 0i32 { - let client_stream_handle_ptr = malloc_uv_tcp_t(); - *(client_stream_handle_ptr as *mut uv::ll::uv_tcp_t) = - uv::ll::tcp_t(); - alt uv::ll::tcp_init(loop_ptr, client_stream_handle_ptr) { - 0i32 { - log(debug, "uv_tcp_init successful for client stream"); - alt uv::ll::accept( - server_handle_ptr as *libc::c_void, - client_stream_handle_ptr as *libc::c_void) { - 0i32 { - log(debug, "successfully accepted client connection"); - comm::send(new_conn_ch, - result::ok(client_stream_handle_ptr)); - } - _ { - log(debug, "failed to accept client conn"); - comm::send( - new_conn_ch, - result::err(uv::ll::get_last_err_data(loop_ptr) - .to_tcp_err())); - } - } - } - _ { - log(debug, "failed to init client stream"); - comm::send( - new_conn_ch, - result::err(uv::ll::get_last_err_data(loop_ptr) - .to_tcp_err())); - } - } - } - _ { - comm::send( - new_conn_ch, - result::err(uv::ll::get_last_err_data(loop_ptr) - .to_tcp_err())); - } - } -} - enum tcp_connect_result { tcp_connected(tcp_socket), tcp_connect_error(tcp_err_data) @@ -1331,10 +1242,6 @@ mod test { impl_gl_tcp_ipv4_server_and_client(); } #[test] - fn test_gl_tcp_server_listener_and_client_ipv4() unsafe { - impl_gl_tcp_ipv4_server_listener_and_client(); - } - #[test] fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe { impl_gl_tcp_ipv4_client_error_connection_refused(); } @@ -1348,11 +1255,6 @@ mod test { } #[test] #[ignore(cfg(target_os = "linux"))] - fn test_gl_tcp_server_listener_and_client_ipv4() unsafe { - impl_gl_tcp_ipv4_server_listener_and_client(); - } - #[test] - #[ignore(cfg(target_os = "linux"))] fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe { impl_gl_tcp_ipv4_client_error_connection_refused(); } @@ -1404,52 +1306,6 @@ mod test { assert str::contains(actual_req, expected_req); assert str::contains(actual_resp, expected_resp); } - fn impl_gl_tcp_ipv4_server_listener_and_client() { - let hl_loop = uv::global_loop::get(); - let server_ip = "127.0.0.1"; - let server_port = 8889u; - let expected_req = "ping"; - let expected_resp = "pong"; - - let server_result_po = comm::port::(); - let server_result_ch = comm::chan(server_result_po); - - let cont_po = comm::port::<()>(); - let cont_ch = comm::chan(cont_po); - // server - task::spawn_sched(task::manual_threads(1u)) {|| - let actual_req = comm::listen {|server_ch| - run_tcp_test_server_listener( - server_ip, - server_port, - expected_resp, - server_ch, - cont_ch, - hl_loop) - }; - server_result_ch.send(actual_req); - }; - comm::recv(cont_po); - // client - log(debug, "server started, firing up client.."); - let actual_resp_result = comm::listen {|client_ch| - run_tcp_test_client( - server_ip, - server_port, - expected_req, - client_ch, - hl_loop) - }; - assert actual_resp_result.is_success(); - let actual_resp = actual_resp_result.get(); - let actual_req = comm::recv(server_result_po); - log(debug, #fmt("REQ: expected: '%s' actual: '%s'", - expected_req, actual_req)); - log(debug, #fmt("RESP: expected: '%s' actual: '%s'", - expected_resp, actual_resp)); - assert str::contains(actual_req, expected_req); - assert str::contains(actual_resp, expected_resp); - } fn impl_gl_tcp_ipv4_client_error_connection_refused() { let hl_loop = uv::global_loop::get(); let server_ip = "127.0.0.1"; @@ -1552,57 +1408,6 @@ mod test { ret_val } - fn run_tcp_test_server_listener(server_ip: str, - server_port: uint, resp: str, - server_ch: comm::chan, - cont_ch: comm::chan<()>, - iotask: iotask) -> str { - - task::spawn_sched(task::manual_threads(1u)) {|| - let server_ip_addr = ip::v4::parse_addr(server_ip); - let new_listener_result = - new_listener(server_ip_addr, server_port, 128u, iotask); - if result::is_err(new_listener_result) { - let err_data = result::get_err(new_listener_result); - log(debug, #fmt("SERVER: exited abnormally name %s msg %s", - err_data.err_name, err_data.err_msg)); - fail "couldn't set up new listener"; - } - let server_port = result::unwrap(new_listener_result); - cont_ch.send(()); - // receive a single new connection.. normally this'd be - // in a loop {}, but we're just going to take a single - // client.. get their req, write a resp and then exit - let new_conn_result = server_port.recv(); - if result::is_err(new_conn_result) { - let err_data = result::get_err(new_conn_result); - log(debug, #fmt("SERVER: exited abnormally name %s msg %s", - err_data.err_name, err_data.err_msg)); - fail "couldn't recv new conn"; - } - let sock = result::unwrap(new_conn_result); - log(debug, "SERVER: successfully accepted"+ - "connection!"); - let received_req_bytes = - read(sock, 0u); - alt received_req_bytes { - result::ok(data) { - server_ch.send( - str::from_bytes(data)); - log(debug, "SERVER: before write"); - tcp_write_single(sock, str::bytes(resp)); - log(debug, "SERVER: after write.. die"); - } - result::err(err_data) { - server_ch.send(""); - } - } - }; - let ret_val = server_ch.recv(); - log(debug, #fmt("SERVER: exited and got ret val: '%s'", ret_val)); - ret_val - } - fn run_tcp_test_client(server_ip: str, server_port: uint, resp: str, client_ch: comm::chan, iotask: iotask) -> result::result Date: Tue, 29 May 2012 15:15:04 -0700 Subject: std: some cleanup in net::tcp rename listen_to_conn->listen --- src/libstd/net_tcp.rs | 59 ++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 1f732978f4b..6f1b1fd5258 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -19,7 +19,7 @@ export tcp_err_data, tcp_connect_err_data; // operations on a tcp_socket export write, write_future, read_start, read_stop; // tcp server stuff -export listen_for_conn, accept; +export listen, accept; // tcp client stuff export connect; // helper methods @@ -676,7 +676,7 @@ a `result` instance containing empty data of type `()` on a successful/normal shutdown, and a `tcp_err_data` record in the event of listen exiting because of an error "] -fn listen_for_conn(host_ip: ip::ip_addr, port: uint, backlog: uint, +fn listen(host_ip: ip::ip_addr, port: uint, backlog: uint, iotask: iotask, on_establish_cb: fn~(comm::chan>), +new_connect_cb: fn~(tcp_new_connection, @@ -697,47 +697,48 @@ fn listen_for_conn(host_ip: ip::ip_addr, port: uint, backlog: uint, }; let server_data_ptr = ptr::addr_of(server_data); - let setup_po = comm::port::>(); - let setup_ch = comm::chan(setup_po); - iotask::interact(iotask) {|loop_ptr| - let tcp_addr = ipv4_ip_addr_to_sockaddr_in(host_ip, - port); - alt uv::ll::tcp_init(loop_ptr, server_stream_ptr) { - 0i32 { - alt uv::ll::tcp_bind(server_stream_ptr, - ptr::addr_of(tcp_addr)) { + let setup_result = comm::listen {|setup_ch| + iotask::interact(iotask) {|loop_ptr| + let tcp_addr = ipv4_ip_addr_to_sockaddr_in(host_ip, + port); + alt uv::ll::tcp_init(loop_ptr, server_stream_ptr) { 0i32 { - alt uv::ll::listen(server_stream_ptr, - backlog as libc::c_int, - tcp_lfc_on_connection_cb) { + alt uv::ll::tcp_bind(server_stream_ptr, + ptr::addr_of(tcp_addr)) { 0i32 { - uv::ll::set_data_for_uv_handle( - server_stream_ptr, - server_data_ptr); - comm::send(setup_ch, none); + alt uv::ll::listen(server_stream_ptr, + backlog as libc::c_int, + tcp_lfc_on_connection_cb) { + 0i32 { + uv::ll::set_data_for_uv_handle( + server_stream_ptr, + server_data_ptr); + comm::send(setup_ch, none); + } + _ { + log(debug, "failure to uv_listen()"); + let err_data = uv::ll::get_last_err_data(loop_ptr); + comm::send(setup_ch, some(err_data)); + } + } } _ { - log(debug, "failure to uv_listen()"); + log(debug, "failure to uv_tcp_bind"); let err_data = uv::ll::get_last_err_data(loop_ptr); comm::send(setup_ch, some(err_data)); } } } _ { - log(debug, "failure to uv_tcp_bind"); + log(debug, "failure to uv_tcp_init"); let err_data = uv::ll::get_last_err_data(loop_ptr); comm::send(setup_ch, some(err_data)); } } - } - _ { - log(debug, "failure to uv_tcp_init"); - let err_data = uv::ll::get_last_err_data(loop_ptr); - comm::send(setup_ch, some(err_data)); - } - } + }; + setup_ch.recv() }; - alt comm::recv(setup_po) { + alt setup_result { some(err_data) { // we failed to bind/list w/ libuv result::err(err_data.to_tcp_err()) @@ -1338,7 +1339,7 @@ mod test { task::spawn_sched(task::manual_threads(1u)) {|| let server_ip_addr = ip::v4::parse_addr(server_ip); let listen_result = - listen_for_conn(server_ip_addr, server_port, 128u, + listen(server_ip_addr, server_port, 128u, iotask, // on_establish_cb -- called when listener is set up {|kill_ch| -- cgit 1.4.1-3-g733a5 From 235f6c7ab75f2f3e0506cca03c38b84f10e003a0 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 29 May 2012 15:50:10 -0700 Subject: std: factor main body of tcp::listen into reusable listen_common --- src/libstd/net_tcp.rs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 6f1b1fd5258..66f287683bb 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -682,6 +682,22 @@ fn listen(host_ip: ip::ip_addr, port: uint, backlog: uint, +new_connect_cb: fn~(tcp_new_connection, comm::chan>)) -> result::result<(), tcp_err_data> unsafe { + listen_common(host_ip, port, backlog, iotask, on_establish_cb) + // on_connect_cb + {|handle| + let server_data_ptr = uv::ll::get_data_for_uv_handle(handle) + as *tcp_listen_fc_data; + let new_conn = new_tcp_conn(handle); + let kill_ch = (*server_data_ptr).kill_ch; + new_connect_cb(new_conn, kill_ch); + } +} + +fn listen_common(host_ip: ip::ip_addr, port: uint, backlog: uint, + iotask: iotask, + on_establish_cb: fn~(comm::chan>), + -on_connect_cb: fn~(*uv::ll::uv_tcp_t)) + -> result::result<(), tcp_err_data> unsafe { let stream_closed_po = comm::port::<()>(); let kill_po = comm::port::>(); let kill_ch = comm::chan(kill_po); @@ -691,7 +707,7 @@ fn listen(host_ip: ip::ip_addr, port: uint, backlog: uint, server_stream_ptr: server_stream_ptr, stream_closed_ch: comm::chan(stream_closed_po), kill_ch: kill_ch, - new_connect_cb: new_connect_cb, + on_connect_cb: on_connect_cb, iotask: iotask, mut active: true }; @@ -1008,8 +1024,7 @@ type tcp_listen_fc_data = { server_stream_ptr: *uv::ll::uv_tcp_t, stream_closed_ch: comm::chan<()>, kill_ch: comm::chan>, - new_connect_cb: fn~(tcp_new_connection, - comm::chan>), + on_connect_cb: fn~(*uv::ll::uv_tcp_t), iotask: iotask, mut active: bool }; @@ -1028,8 +1043,7 @@ crust fn tcp_lfc_on_connection_cb(handle: *uv::ll::uv_tcp_t, if (*server_data_ptr).active { alt status { 0i32 { - let new_conn = new_tcp_conn(handle); - (*server_data_ptr).new_connect_cb(new_conn, kill_ch); + (*server_data_ptr).on_connect_cb(handle); } _ { let loop_ptr = uv::ll::get_loop_for_uv_handle(handle); -- cgit 1.4.1-3-g733a5 From f7e3a4e036cbe84677a924548c2ecbb49b551265 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 5 Jun 2012 06:40:39 -0700 Subject: std: EADDRINUSE and EACCES err tests for tcp server + more cleanup .. confounded resolve! --- src/libstd/net_tcp.rs | 600 +++++++++++++++++++++++--------------------------- 1 file changed, 278 insertions(+), 322 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 66f287683bb..b51058b2499 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -23,8 +23,7 @@ export listen, accept; // tcp client stuff export connect; // helper methods -import methods = net_tcp_methods; -export methods; +export methods_tcp_socket; #[nolink] native mod rustrt { @@ -57,6 +56,38 @@ type tcp_err_data = { err_name: str, err_msg: str }; +#[doc=" +Details returned as part of a `result::err` result from `tcp::listen` +"] +enum tcp_listen_err_data { + #[doc=" + Some unplanned-for error. The first and second fields correspond + to libuv's `err_name` and `err_msg` fields, respectively. + "] + generic_listen_err(str, str), + #[doc=" + Failed to bind to the requested IP/Port, because it is already in use. + + # Possible Causes + + * Attempting to bind to a port already bound to another listener + "] + address_in_use, + #[doc=" + Request to bind to an IP/Port was denied by the system. + + # Possible Causes + + * Attemping to binding to an IP/Port as a non-Administrator + on Windows Vista+ + * Attempting to bind, as a non-priv'd + user, to 'privileged' ports (< 1024) on *nix + "] + access_denied +} +#[doc=" +Details returned as part of a `result::err` result from `tcp::connect` +"] enum tcp_connect_err_data { #[doc=" Some unplanned-for error. The first and second fields correspond @@ -333,185 +364,6 @@ fn read_future(sock: tcp_socket, timeout_msecs: uint) } #[doc=" -<<<<<<< HEAD -Bind to a given IP/port and listen for new connections - -# Arguments - -* `host_ip` - a `net::ip::ip_addr` representing a unique IP -(versions 4 or 6) -* `port` - a uint representing the port to listen on -* `backlog` - a uint representing the number of incoming connections -to cache in memory -* `hl_loop` - a `uv::hl::high_level_loop` that the tcp request will run on - -# Returns - -A `result` instance containing either a `tcp_conn_port` which can used -to listen for, and accept, new connections, or a `tcp_err_data` if -failure to create the tcp listener occurs -"] -fn new_listener(host_ip: ip::ip_addr, port: uint, backlog: uint, - iotask: iotask) - -> result::result unsafe { - let stream_closed_po = comm::port::<()>(); - let stream_closed_ch = comm::chan(stream_closed_po); - let new_conn_po = comm::port::>(); - let new_conn_ch = comm::chan(new_conn_po); - // FIXME (#2656): This shared box should not be captured in the i/o - // task Make it a unique pointer. - let server_data: @tcp_conn_port_data = @{ - server_stream: uv::ll::tcp_t(), - stream_closed_po: stream_closed_po, - stream_closed_ch: stream_closed_ch, - iotask: iotask, - new_conn_po: new_conn_po, - new_conn_ch: new_conn_ch - }; - let server_data_ptr = ptr::addr_of(*server_data); - let server_stream_ptr = ptr::addr_of((*server_data_ptr) - .server_stream); - - let setup_po = comm::port::>(); - let setup_ch = comm::chan(setup_po); - iotask::interact(iotask) {|loop_ptr| - let tcp_addr = ipv4_ip_addr_to_sockaddr_in(host_ip, - port); - alt uv::ll::tcp_init(loop_ptr, server_stream_ptr) { - 0i32 { - alt uv::ll::tcp_bind(server_stream_ptr, - ptr::addr_of(tcp_addr)) { - 0i32 { - alt uv::ll::listen(server_stream_ptr, - backlog as libc::c_int, - tcp_nl_on_connection_cb) { - 0i32 { - uv::ll::set_data_for_uv_handle( - server_stream_ptr, - server_data_ptr); - comm::send(setup_ch, none); - } - _ { - log(debug, "failure to uv_listen()"); - let err_data = uv::ll::get_last_err_data(loop_ptr); - comm::send(setup_ch, some(err_data)); - } - } - } - _ { - log(debug, "failure to uv_tcp_bind"); - let err_data = uv::ll::get_last_err_data(loop_ptr); - comm::send(setup_ch, some(err_data)); - } - } - } - _ { - log(debug, "failure to uv_tcp_init"); - let err_data = uv::ll::get_last_err_data(loop_ptr); - comm::send(setup_ch, some(err_data)); - } - } - }; - alt comm::recv(setup_po) { - some(err_data) { - // we failed to bind/list w/ libuv - result::err(err_data.to_tcp_err()) - } - none { - result::ok(tcp_conn_port(server_data)) - } - } -} - -#[doc=" -Block on a `net::tcp::tcp_conn_port` until a new connection arrives - -This function behaves similarly to `comm::recv()` - -# Arguments - -* server_port -- a `net::tcp::tcp_conn_port` that you wish to listen -on for an incoming connection - -# Returns - -A `result` object containing a `net::tcp::tcp_socket`, ready for immediate -use, as the `ok` varient, or a `net::tcp::tcp_err_data` for the `err` -variant -"] -fn conn_recv(server_port: tcp_conn_port) - -> result::result { - let new_conn_po = (*(server_port.conn_data)).new_conn_po; - let iotask = (*(server_port.conn_data)).iotask; - let new_conn_result = comm::recv(new_conn_po); - alt new_conn_result { - ok(client_stream_ptr) { - conn_port_new_tcp_socket(client_stream_ptr, iotask) - } - err(err_data) { - result::err(err_data) - } - } -} - -#[doc=" -Identical to `net::tcp::conn_recv`, but ran on a new task - -The recv'd tcp_socket is created with a new task on the current scheduler, -and given as a parameter to the provided callback - -# Arguments - -* `server_port` -- a `net::tcp::tcp_conn_port` that you wish to listen -on for an incoming connection -* `cb` -- a callback that will be ran, in a new task on the current scheduler, -once a new connection is recv'd. Its parameter: - * A `result` object containing a `net::tcp::tcp_socket`, ready for immediate - use, as the `ok` varient, or a `net::tcp::tcp_err_data` for the `err` - variant -"] -fn conn_recv_spawn(server_port: tcp_conn_port, - +cb: fn~(result::result)) { - let new_conn_po = (*(server_port.conn_data)).new_conn_po; - let iotask = (*(server_port.conn_data)).iotask; - let new_conn_result = comm::recv(new_conn_po); - task::spawn {|| - let sock_create_result = alt new_conn_result { - ok(client_stream_ptr) { - conn_port_new_tcp_socket(client_stream_ptr, iotask) - } - err(err_data) { - result::err(err_data) - } - }; - cb(sock_create_result); - }; -} - -#[doc=" -Check if a `net::tcp::tcp_conn_port` has one-or-more pending, new connections - -This function behaves similarly to `comm::peek()` - -# Arguments - -* `server_port` -- a `net::tcp::tcp_conn_port` representing a server -connection - -# Returns - -`true` if there are one-or-more pending connections, `false` if there are -none. -"] -fn conn_peek(server_port: tcp_conn_port) -> bool { - let new_conn_po = (*(server_port.conn_data)).new_conn_po; - comm::peek(new_conn_po) -} - -#[doc=" -======= ->>>>>>> std: dump the tcp::new_listener server API Bind an incoming client connection to a `net::tcp::tcp_socket` # Notes @@ -681,7 +533,7 @@ fn listen(host_ip: ip::ip_addr, port: uint, backlog: uint, on_establish_cb: fn~(comm::chan>), +new_connect_cb: fn~(tcp_new_connection, comm::chan>)) - -> result::result<(), tcp_err_data> unsafe { + -> result::result<(), tcp_listen_err_data> unsafe { listen_common(host_ip, port, backlog, iotask, on_establish_cb) // on_connect_cb {|handle| @@ -697,7 +549,7 @@ fn listen_common(host_ip: ip::ip_addr, port: uint, backlog: uint, iotask: iotask, on_establish_cb: fn~(comm::chan>), -on_connect_cb: fn~(*uv::ll::uv_tcp_t)) - -> result::result<(), tcp_err_data> unsafe { + -> result::result<(), tcp_listen_err_data> unsafe { let stream_closed_po = comm::port::<()>(); let kill_po = comm::port::>(); let kill_ch = comm::chan(kill_po); @@ -719,6 +571,9 @@ fn listen_common(host_ip: ip::ip_addr, port: uint, backlog: uint, port); alt uv::ll::tcp_init(loop_ptr, server_stream_ptr) { 0i32 { + uv::ll::set_data_for_uv_handle( + server_stream_ptr, + server_data_ptr); alt uv::ll::tcp_bind(server_stream_ptr, ptr::addr_of(tcp_addr)) { 0i32 { @@ -726,9 +581,6 @@ fn listen_common(host_ip: ip::ip_addr, port: uint, backlog: uint, backlog as libc::c_int, tcp_lfc_on_connection_cb) { 0i32 { - uv::ll::set_data_for_uv_handle( - server_stream_ptr, - server_data_ptr); comm::send(setup_ch, none); } _ { @@ -756,8 +608,29 @@ fn listen_common(host_ip: ip::ip_addr, port: uint, backlog: uint, }; alt setup_result { some(err_data) { - // we failed to bind/list w/ libuv - result::err(err_data.to_tcp_err()) + iotask::interact(iotask) {|loop_ptr| + log(debug, #fmt("tcp::listen post-kill recv hl interact %?", + loop_ptr)); + (*server_data_ptr).active = false; + uv::ll::close(server_stream_ptr, tcp_lfc_close_cb); + }; + stream_closed_po.recv(); + alt err_data.err_name { + "EACCES" { + log(debug, "Got EACCES error"); + result::err(access_denied) + } + "EADDRINUSE" { + log(debug, "Got EADDRINUSE error"); + result::err(address_in_use) + } + _ { + log(debug, #fmt("Got '%s' '%s' libuv error", + err_data.err_name, err_data.err_msg)); + result::err( + generic_listen_err(err_data.err_name, err_data.err_msg)) + } + } } none { on_establish_cb(kill_ch); @@ -768,11 +641,12 @@ fn listen_common(host_ip: ip::ip_addr, port: uint, backlog: uint, (*server_data_ptr).active = false; uv::ll::close(server_stream_ptr, tcp_lfc_close_cb); }; - comm::recv(stream_closed_po); + stream_closed_po.recv(); alt kill_result { // some failure post bind/listen some(err_data) { - result::err(err_data) + result::err(generic_listen_err(err_data.err_name, + err_data.err_msg)) } // clean exit none { @@ -783,35 +657,33 @@ fn listen_common(host_ip: ip::ip_addr, port: uint, backlog: uint, } } -mod net_tcp_methods { - #[doc=" - Convenience methods extending `net::tcp::tcp_socket` - "] - impl methods_tcp_socket for tcp_socket { - fn read_start() -> result::result>, tcp_err_data> { - read_start(self) - } - fn read_stop() -> - result::result<(), tcp_err_data> { - read_stop(self) - } - fn read(timeout_msecs: uint) -> - result::result<[u8]/~, tcp_err_data> { - read(self, timeout_msecs) - } - fn read_future(timeout_msecs: uint) -> - future::future> { - read_future(self, timeout_msecs) - } - fn write(raw_write_data: [u8]/~) - -> result::result<(), tcp_err_data> { - write(self, raw_write_data) - } - fn write_future(raw_write_data: [u8]/~) - -> future::future> { - write_future(self, raw_write_data) - } +#[doc=" +Convenience methods extending `net::tcp::tcp_socket` +"] +impl methods_tcp_socket for tcp_socket { + fn read_start() -> result::result>, tcp_err_data> { + read_start(self) + } + fn read_stop() -> + result::result<(), tcp_err_data> { + read_stop(self) + } + fn read(timeout_msecs: uint) -> + result::result<[u8]/~, tcp_err_data> { + read(self, timeout_msecs) + } + fn read_future(timeout_msecs: uint) -> + future::future> { + read_future(self, timeout_msecs) + } + fn write(raw_write_data: [u8]/~) + -> result::result<(), tcp_err_data> { + write(self, raw_write_data) + } + fn write_future(raw_write_data: [u8]/~) + -> future::future> { + write_future(self, raw_write_data) } } // INTERNAL API @@ -984,38 +856,6 @@ fn write_common_impl(socket_data_ptr: *tcp_socket_data, } } -<<<<<<< HEAD -// various recv_* can use a tcp_conn_port can re-use this.. -fn conn_port_new_tcp_socket( - stream_handle_ptr: *uv::ll::uv_tcp_t, - iotask: iotask) - -> result::result unsafe { - // tcp_nl_on_connection_cb - let reader_po = comm::port::>(); - let client_socket_data = @{ - reader_po : reader_po, - reader_ch : comm::chan(reader_po), - stream_handle_ptr : stream_handle_ptr, - connect_req : uv::ll::connect_t(), - write_req : uv::ll::write_t(), - iotask : iotask - }; - let client_socket_data_ptr = ptr::addr_of(*client_socket_data); - comm::listen {|cont_ch| - iotask::interact(iotask) {|loop_ptr| - log(debug, #fmt("in interact cb 4 conn_port_new_tcp.. loop %?", - loop_ptr)); - uv::ll::set_data_for_uv_handle(stream_handle_ptr, - client_socket_data_ptr); - cont_ch.send(()); - }; - cont_ch.recv() - }; - result::ok(tcp_socket(client_socket_data)) -} - -======= ->>>>>>> std: dump the tcp::new_listener server API enum tcp_new_connection { new_tcp_conn(*uv::ll::uv_tcp_t) } @@ -1260,6 +1100,18 @@ mod test { fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe { impl_gl_tcp_ipv4_client_error_connection_refused(); } + #[test] + fn test_gl_tcp_server_address_in_use() unsafe { + impl_gl_tcp_ipv4_server_address_in_use(); + } + #[test] + // FIXME: this probably needs to be ignored on windows. + // ... need to verify (someday we'll have 64bit windows! :) + //#[ignore(cfg(target_os = "win32"))] + fn test_gl_tcp_server_access_denied() unsafe { + impl_gl_tcp_ipv4_server_access_denied(); + } + } #[cfg(target_arch="x86")] mod impl32 { @@ -1273,6 +1125,19 @@ mod test { fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe { impl_gl_tcp_ipv4_client_error_connection_refused(); } + #[test] + #[ignore(cfg(target_os = "linux"))] + fn test_gl_tcp_server_address_in_use() unsafe { + impl_gl_tcp_ipv4_server_address_in_use(); + } + #[test] + #[ignore(cfg(target_os = "linux"))] + // FIXME: this probably needs to be ignored on windows. + // ... need to verify + //#[ignore(cfg(target_os = "win32"))] + fn test_gl_tcp_server_access_denied() unsafe { + impl_gl_tcp_ipv4_server_access_denied(); + } } } fn impl_gl_tcp_ipv4_server_and_client() { @@ -1324,7 +1189,7 @@ mod test { fn impl_gl_tcp_ipv4_client_error_connection_refused() { let hl_loop = uv::global_loop::get(); let server_ip = "127.0.0.1"; - let server_port = 8890u; + let server_port = 8889u; let expected_req = "ping"; // client log(debug, "firing up client.."); @@ -1344,85 +1209,181 @@ mod test { } } } + fn impl_gl_tcp_ipv4_server_address_in_use() { + let hl_loop = uv::global_loop::get(); + let server_ip = "127.0.0.1"; + let server_port = 8890u; + let expected_req = "ping"; + let expected_resp = "pong"; + + let server_result_po = comm::port::(); + let server_result_ch = comm::chan(server_result_po); + + let cont_po = comm::port::<()>(); + let cont_ch = comm::chan(cont_po); + // server + task::spawn_sched(task::manual_threads(1u)) {|| + let actual_req = comm::listen {|server_ch| + run_tcp_test_server( + server_ip, + server_port, + expected_resp, + server_ch, + cont_ch, + hl_loop) + }; + server_result_ch.send(actual_req); + }; + comm::recv(cont_po); + // this one should fail.. + let listen_err = run_tcp_test_server_fail( + server_ip, + server_port, + hl_loop); + // client.. just doing this so that the first server tears down + log(debug, "server started, firing up client.."); + comm::listen {|client_ch| + run_tcp_test_client( + server_ip, + server_port, + expected_req, + client_ch, + hl_loop) + }; + alt listen_err { + address_in_use { + assert true; + } + _ { + fail "expected address_in_use listen error,"+ + "but got a different error varient. check logs."; + } + } + } + fn impl_gl_tcp_ipv4_server_access_denied() { + let hl_loop = uv::global_loop::get(); + let server_ip = "127.0.0.1"; + let server_port = 80u; + // this one should fail.. + let listen_err = run_tcp_test_server_fail( + server_ip, + server_port, + hl_loop); + alt listen_err { + access_denied { + assert true; + } + _ { + fail "expected address_in_use listen error,"+ + "but got a different error varient. check logs."; + } + } + } fn run_tcp_test_server(server_ip: str, server_port: uint, resp: str, server_ch: comm::chan, cont_ch: comm::chan<()>, iotask: iotask) -> str { - - task::spawn_sched(task::manual_threads(1u)) {|| - let server_ip_addr = ip::v4::parse_addr(server_ip); - let listen_result = - listen(server_ip_addr, server_port, 128u, - iotask, - // on_establish_cb -- called when listener is set up - {|kill_ch| - log(debug, #fmt("establish_cb %?", - kill_ch)); - comm::send(cont_ch, ()); - }, - // risky to run this on the loop, but some users - // will want the POWER - {|new_conn, kill_ch| - log(debug, "SERVER: new connection!"); - comm::listen {|cont_ch| - task::spawn_sched(task::manual_threads(1u)) {|| - log(debug, "SERVER: starting worker for new req"); - - let accept_result = accept(new_conn); - log(debug, "SERVER: after accept()"); - if result::is_err(accept_result) { - log(debug, "SERVER: error accept connection"); - let err_data = result::get_err(accept_result); + let server_ip_addr = ip::v4::parse_addr(server_ip); + let listen_result = listen(server_ip_addr, server_port, 128u, iotask, + // on_establish_cb -- called when listener is set up + {|kill_ch| + log(debug, #fmt("establish_cb %?", + kill_ch)); + comm::send(cont_ch, ()); + }, + // risky to run this on the loop, but some users + // will want the POWER + {|new_conn, kill_ch| + log(debug, "SERVER: new connection!"); + comm::listen {|cont_ch| + task::spawn_sched(task::manual_threads(1u)) {|| + log(debug, "SERVER: starting worker for new req"); + + let accept_result = accept(new_conn); + log(debug, "SERVER: after accept()"); + if result::is_err(accept_result) { + log(debug, "SERVER: error accept connection"); + let err_data = result::get_err(accept_result); + comm::send(kill_ch, some(err_data)); + log(debug, + "SERVER/WORKER: send on err cont ch"); + cont_ch.send(()); + } + else { + log(debug, + "SERVER/WORKER: send on cont ch"); + cont_ch.send(()); + let sock = result::unwrap(accept_result); + log(debug, "SERVER: successfully accepted"+ + "connection!"); + let received_req_bytes = read(sock, 0u); + alt received_req_bytes { + result::ok(data) { + server_ch.send( + str::from_bytes(data)); + log(debug, "SERVER: before write"); + tcp_write_single(sock, str::bytes(resp)); + log(debug, "SERVER: after write.. die"); + comm::send(kill_ch, none); + } + result::err(err_data) { + log(debug, #fmt("SERVER: error recvd: %s %s", + err_data.err_name, err_data.err_msg)); comm::send(kill_ch, some(err_data)); - log(debug, - "SERVER/WORKER: send on err cont ch"); - cont_ch.send(()); - } - else { - log(debug, - "SERVER/WORKER: send on cont ch"); - cont_ch.send(()); - let sock = result::unwrap(accept_result); - log(debug, "SERVER: successfully accepted"+ - "connection!"); - let received_req_bytes = read(sock, 0u); - alt received_req_bytes { - result::ok(data) { - server_ch.send( - str::from_bytes(data)); - log(debug, "SERVER: before write"); - tcp_write_single(sock, str::bytes(resp)); - log(debug, "SERVER: after write.. die"); - comm::send(kill_ch, none); - } - result::err(err_data) { - log(debug, #fmt("SERVER: error recvd: %s %s", - err_data.err_name, err_data.err_msg)); - comm::send(kill_ch, some(err_data)); - server_ch.send(""); - } - } - log(debug, "SERVER: worker spinning down"); + server_ch.send(""); + } } + log(debug, "SERVER: worker spinning down"); } - log(debug, "SERVER: waiting to recv on cont_ch"); - cont_ch.recv() - }; - log(debug, "SERVER: recv'd on cont_ch..leaving listen cb"); - }); - // err check on listen_result - if result::is_err(listen_result) { - let err_data = result::get_err(listen_result); - log(debug, #fmt("SERVER: exited abnormally name %s msg %s", - err_data.err_name, err_data.err_msg)); + } + log(debug, "SERVER: waiting to recv on cont_ch"); + cont_ch.recv() + }; + log(debug, "SERVER: recv'd on cont_ch..leaving listen cb"); + }); + // err check on listen_result + if result::is_err(listen_result) { + alt result::get_err(listen_result) { + generic_listen_err(name, msg) { + fail #fmt("SERVER: exited abnormally name %s msg %s", + name, msg); + } + access_denied { + fail "SERVER: exited abnormally, got access denied.."; + } + address_in_use { + fail "SERVER: exited abnormally, got address in use..."; + } } - }; + } let ret_val = server_ch.recv(); log(debug, #fmt("SERVER: exited and got ret val: '%s'", ret_val)); ret_val } + fn run_tcp_test_server_fail(server_ip: str, server_port: uint, + iotask: iotask) -> tcp_listen_err_data { + let server_ip_addr = ip::v4::parse_addr(server_ip); + let listen_result = listen(server_ip_addr, server_port, 128u, iotask, + // on_establish_cb -- called when listener is set up + {|kill_ch| + log(debug, #fmt("establish_cb %?", + kill_ch)); + }, + {|new_conn, kill_ch| + fail #fmt("SERVER: shouldn't be called.. %? %?", + new_conn, kill_ch); + }); + // err check on listen_result + if result::is_failure(listen_result) { + result::get_err(listen_result) + } + else { + fail "SERVER: did not fail as expected" + } + } + fn run_tcp_test_client(server_ip: str, server_port: uint, resp: str, client_ch: comm::chan, iotask: iotask) -> result::result>>>>>> std: mod cleanup, impl/test for conn. refused err + mem leak fix let write_result = write_result_future.get(); if result::is_err(write_result) { log(debug, "tcp_write_single: write failed!"); -- cgit 1.4.1-3-g733a5 From 31c33ca5ff31e21116885c12ed99ccb27b5e7c8d Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 5 Jun 2012 07:12:12 -0700 Subject: std: doc and misc cleanup in net::tcp * updated rustdoc info for several functions * changed read_stop to take control of the port returned by read_start * made write_future do an explicit data copy with the binary vector it is passed --- src/libstd/net_tcp.rs | 56 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 21 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index b51058b2499..ae9556eec50 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -105,15 +105,16 @@ Initiate a client connection over TCP/IP # Arguments -* `ip` - The IP address (versions 4 or 6) of the remote host +* `input_ip` - The IP address (versions 4 or 6) of the remote host * `port` - the unsigned integer of the desired remote host port * `iotask` - a `uv::iotask` that the tcp request will run on # Returns -A `result` that, if the operation succeeds, contains a `tcp_socket` that -can be used to send and receive data to/from the remote host. In the event -of failure, a `tcp_err_data` will be returned +A `result` that, if the operation succeeds, contains a `net::net::tcp_socket` +that can be used to send and receive data to/from the remote host. In the +event of failure, a `net::tcp::tcp_connect_err_data` instance will be +returned "] fn connect(input_ip: ip::ip_addr, port: uint, iotask: iotask) @@ -244,9 +245,12 @@ Write binary data to tcp stream; Returns a `future::future` value immediately # Safety -This function can produce unsafe results if the call to `write_future` is -made, the `future::future` value returned is never resolved via -`future::get`, and then the `tcp_socket` passed in to `write_future` leaves +This function can produce unsafe results if: + +1. the call to `write_future` is made +2. the `future::future` value returned is never resolved via +`future::get` +3. and then the `tcp_socket` passed in to `write_future` leaves scope and is destructed before the task that runs the libuv write operation completes. @@ -270,7 +274,8 @@ fn write_future(sock: tcp_socket, raw_write_data: [u8]/~) -> future> unsafe { let socket_data_ptr = ptr::addr_of(*(sock.socket_data)); future_spawn {|| - write_common_impl(socket_data_ptr, raw_write_data) + let data_copy = copy(raw_write_data); + write_common_impl(socket_data_ptr, data_copy) } } @@ -301,9 +306,11 @@ Stop reading from an open TCP connection; used with `read_start` * `sock` - a `net::tcp::tcp_socket` that you wish to stop reading on "] -fn read_stop(sock: tcp_socket) -> +fn read_stop(sock: tcp_socket, + -read_port: comm::port>) -> result::result<(), tcp_err_data> unsafe { - let socket_data = ptr::addr_of(*(sock.socket_data)); + log(debug, #fmt("taking the read_port out of commission %?", read_port)); + let socket_data = ptr::addr_of(**sock); read_stop_common_impl(socket_data) } @@ -388,7 +395,15 @@ Here, the `new_conn` is used in conjunction with `accept` from within a task spawned by the `new_connect_cb` passed into `listen` ~~~~~~~~~~~ -net::tcp::listen(remote_ip, remote_port, backlog) {|new_conn, kill_ch| +net::tcp::listen(remote_ip, remote_port, backlog) + // this callback is ran once after the connection is successfully + // set up + {|kill_ch| + // pass the kill_ch to your main loop or wherever you want + // to be able to externally kill the server from + } + // this callback is ran when a new connection arrives + {|new_conn, kill_ch| let cont_po = comm::port::>(); let cont_ch = comm::chan(cont_po); task::spawn {|| @@ -418,13 +433,11 @@ net::tcp::listen(remote_ip, remote_port, backlog) {|new_conn, kill_ch| # Returns -* Success - * On success, this function will return a `net::tcp::tcp_socket` as the - `ok` variant of a `result`. The `net::tcp::tcp_socket` is anchored within - the task that `accept` was called within for its lifetime. -* Failure - * On failure, this function will return a `net::tcp::tcp_err_data` record - as the `err` variant of a `result`. +On success, this function will return a `net::tcp::tcp_socket` as the +`ok` variant of a `result`. The `net::tcp::tcp_socket` is anchored within +the task that `accept` was called within for its lifetime. On failure, +this function will return a `net::tcp::tcp_err_data` record +as the `err` variant of a `result`. "] fn accept(new_conn: tcp_new_connection) -> result::result unsafe { @@ -525,7 +538,7 @@ callback's arguments are: # returns a `result` instance containing empty data of type `()` on a -successful/normal shutdown, and a `tcp_err_data` record in the event +successful/normal shutdown, and a `tcp_listen_err_data` enum in the event of listen exiting because of an error "] fn listen(host_ip: ip::ip_addr, port: uint, backlog: uint, @@ -665,9 +678,10 @@ impl methods_tcp_socket for tcp_socket { result::result<[u8]/~, tcp_err_data>>, tcp_err_data> { read_start(self) } - fn read_stop() -> + fn read_stop(-read_port: + comm::port>) -> result::result<(), tcp_err_data> { - read_stop(self) + read_stop(self, read_port) } fn read(timeout_msecs: uint) -> result::result<[u8]/~, tcp_err_data> { -- cgit 1.4.1-3-g733a5 From 28ab8b841a3551c0493c56a5df163e12a03da680 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Thu, 7 Jun 2012 16:42:39 -0700 Subject: std: add buffered wrapper to tcp_socket + io::reader impl. no tests, yet. need to do some other work, in the subsequent commit, to add io::writer, then tests. --- src/libstd/net_tcp.rs | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index ae9556eec50..692f73467b4 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -18,6 +18,8 @@ export tcp_socket; export tcp_err_data, tcp_connect_err_data; // operations on a tcp_socket export write, write_future, read_start, read_stop; +// buffered socket +export socket_buf; // tcp server stuff export listen, accept; // tcp client stuff @@ -49,6 +51,16 @@ class tcp_socket { } } +#[doc=" +A buffered wrapper for `net::tcp::tcp_socket` + +It is created with a call to `net::tcp::socket_buf()` and has impls that +satisfy both the `io::reader` and `io::writer` ifaces. +"] +resource tcp_socket_buf(data: @tcp_buffered_socket_data) { + log(debug, #fmt("dtor for tcp_socket_buf.. %?", data)); +} + #[doc=" Contains raw, string-based, error information returned from libuv "] @@ -670,6 +682,25 @@ fn listen_common(host_ip: ip::ip_addr, port: uint, backlog: uint, } } +#[doc=" +Convert a `net::tcp::tcp_socket` to a `net::tcp::tcp_socket_buf`. + +This function takes ownership of a `net::tcp::tcp_socket`, returning it +stored within a buffered wrapper, which can be converted to a `io::reader` +or `io::writer` + +# Arguments + +* `sock` -- a `net::tcp::tcp_socket` that you want to buffer + +# Returns + +A buffered wrapper that you can cast as an `io::reader` or `io::writer` +"] +fn socket_buf(-sock: tcp_socket) -> tcp_socket_buf { + tcp_socket_buf(@{ sock: sock, mut buf: [] }) +} + #[doc=" Convenience methods extending `net::tcp::tcp_socket` "] @@ -700,6 +731,74 @@ impl methods_tcp_socket for tcp_socket { write_future(self, raw_write_data) } } + +#[doc=" +Implementation of `io::reader` iface for a buffered `net::tcp::tcp_socket` +"] +impl tcp_socket_buf of io::reader for tcp_socket_buf { + fn read_bytes(amt: uint) -> [u8] { + let has_amt_available = + vec::len((*self).buf) >= amt; + if has_amt_available { + // no arbitrary-length shift in vec::? + let mut ret_buf = []; + while vec::len(ret_buf) < amt { + ret_buf += [vec::shift((*self).buf)]; + } + ret_buf + } + else { + let read_result = read((*self).sock, 0u); + if read_result.is_failure() { + // failure case.. no good answer, yet. + [] + } + else { + let new_chunk = result::unwrap(read_result); + (*self).buf += new_chunk; + self.read_bytes(amt) + } + } + } + fn read_byte() -> int { + self.read_bytes(1u)[0] as int + } + fn unread_byte(amt: int) { + vec::unshift((*self).buf, amt as u8); + } + fn eof() -> bool { + false // noop + } + fn seek(dist: int, seek: io::seek_style) { + log(debug, #fmt("tcp_socket_buf seek stub %? %?", dist, seek)); + // noop + } + fn tell() -> uint { + 0u // noop + } +} + +/* +#[doc=" +Implementation of `io::reader` iface for a buffered `net::tcp::tcp_socket` +"] +impl tcp_socket_buf of io::writer for tcp_socket_buf { + fn write(data: [const u8]/&) { + (*self).sock.write(iter::to_vec(data as [u8]/&)); + } + fn seek(dist: int, seek: io::seek_style) { + log(debug, #fmt("tcp_socket_buf seek stub %? %?", dist, seek)); + // noop + } + fn tell() -> uint { + 0u + } + fn flush() -> int { + 0 + } +} +*/ + // INTERNAL API fn tear_down_socket_data(socket_data: @tcp_socket_data) unsafe { @@ -826,6 +925,8 @@ fn read_start_common_impl(socket_data: *tcp_socket_data) } } +// helper to convert a "class" vector of [u8] to a *[uv::ll::uv_buf_t] + // shared implementation used by write and write_future fn write_common_impl(socket_data_ptr: *tcp_socket_data, raw_write_data: [u8]/~) @@ -1083,6 +1184,11 @@ type tcp_socket_data = { iotask: iotask }; +type tcp_buffered_socket_data = { + sock: tcp_socket, + mut buf: [u8] +}; + // convert rust ip_addr to libuv's native representation fn ipv4_ip_addr_to_sockaddr_in(input_ip: ip::ip_addr, port: uint) -> uv::ll::sockaddr_in unsafe { -- cgit 1.4.1-3-g733a5 From af3fa5306de44250abd9a9fdb5a8747b7fbf405c Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Thu, 7 Jun 2012 21:22:35 -0700 Subject: std: rework signature of tcp::write common impl to make io::writer possible --- src/libstd/net_tcp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 692f73467b4..e8541cb991b 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -287,7 +287,7 @@ fn write_future(sock: tcp_socket, raw_write_data: [u8]/~) let socket_data_ptr = ptr::addr_of(*(sock.socket_data)); future_spawn {|| let data_copy = copy(raw_write_data); - write_common_impl(socket_data_ptr, data_copy) + write_common_impl(socket_data_ptr, data_copy); } } -- cgit 1.4.1-3-g733a5 From 156a4317f6b4c090241d0cbc441a5d34bf4ac1ce Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Thu, 7 Jun 2012 22:06:42 -0700 Subject: std: finish impl of io::writer for tcp_socket_buf --- src/libstd/net_tcp.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index e8541cb991b..cc329513ab2 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -778,13 +778,17 @@ impl tcp_socket_buf of io::reader for tcp_socket_buf { } } -/* #[doc=" Implementation of `io::reader` iface for a buffered `net::tcp::tcp_socket` "] impl tcp_socket_buf of io::writer for tcp_socket_buf { - fn write(data: [const u8]/&) { - (*self).sock.write(iter::to_vec(data as [u8]/&)); + fn write(data: [const u8]/&) unsafe { + let socket_data_ptr = ptr::addr_of(**((*self).sock)); + let write_buf_vec = vec::unpack_const_slice(data) {|ptr, len| + [ uv::ll::buf_init(ptr as *u8, len) ] + }; + let write_buf_vec_ptr = ptr::addr_of(write_buf_vec); + write_common_impl(socket_data_ptr, write_buf_vec_ptr); } fn seek(dist: int, seek: io::seek_style) { log(debug, #fmt("tcp_socket_buf seek stub %? %?", dist, seek)); @@ -797,7 +801,6 @@ impl tcp_socket_buf of io::writer for tcp_socket_buf { 0 } } -*/ // INTERNAL API -- cgit 1.4.1-3-g733a5 From 99d2ec3ad1a3d25f16f3aec6ea125c3acfed0d20 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Thu, 7 Jun 2012 22:10:18 -0700 Subject: std: renaming impl for tcp_socket and reshuffle/cleanup for tcp_socket_buf --- src/libstd/net_tcp.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index cc329513ab2..b6820690171 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -14,18 +14,16 @@ import str::extensions; // tcp interfaces export tcp_socket; +// buffered socket +export tcp_socket_buf, socket_buf; // errors export tcp_err_data, tcp_connect_err_data; // operations on a tcp_socket export write, write_future, read_start, read_stop; -// buffered socket -export socket_buf; // tcp server stuff export listen, accept; // tcp client stuff export connect; -// helper methods -export methods_tcp_socket; #[nolink] native mod rustrt { @@ -704,7 +702,7 @@ fn socket_buf(-sock: tcp_socket) -> tcp_socket_buf { #[doc=" Convenience methods extending `net::tcp::tcp_socket` "] -impl methods_tcp_socket for tcp_socket { +impl tcp_socket for tcp_socket { fn read_start() -> result::result>, tcp_err_data> { read_start(self) -- cgit 1.4.1-3-g733a5 From 942d3b527e1a8d9ed2ee976e82d1242bbe7ff78e Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Sat, 9 Jun 2012 20:46:29 -0700 Subject: std: test impl for using tcp_socket_buf and its reader/writer impls. fails. needs work. probably the slice code and/or the way that the tcp_socket_buf is wrapped in a shared box --- src/libstd/net_tcp.rs | 96 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 5 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index b6820690171..06829312849 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -733,7 +733,7 @@ impl tcp_socket for tcp_socket { #[doc=" Implementation of `io::reader` iface for a buffered `net::tcp::tcp_socket` "] -impl tcp_socket_buf of io::reader for tcp_socket_buf { +impl tcp_socket_buf of io::reader for @tcp_socket_buf { fn read_bytes(amt: uint) -> [u8] { let has_amt_available = vec::len((*self).buf) >= amt; @@ -748,7 +748,9 @@ impl tcp_socket_buf of io::reader for tcp_socket_buf { else { let read_result = read((*self).sock, 0u); if read_result.is_failure() { - // failure case.. no good answer, yet. + let err_data = read_result.get_err(); + log(debug, #fmt("ERROR sock_buf as io::reader.read err %? %?", + err_data.err_name, err_data.err_msg)); [] } else { @@ -779,14 +781,19 @@ impl tcp_socket_buf of io::reader for tcp_socket_buf { #[doc=" Implementation of `io::reader` iface for a buffered `net::tcp::tcp_socket` "] -impl tcp_socket_buf of io::writer for tcp_socket_buf { +impl tcp_socket_buf of io::writer for @tcp_socket_buf { fn write(data: [const u8]/&) unsafe { let socket_data_ptr = ptr::addr_of(**((*self).sock)); let write_buf_vec = vec::unpack_const_slice(data) {|ptr, len| [ uv::ll::buf_init(ptr as *u8, len) ] }; let write_buf_vec_ptr = ptr::addr_of(write_buf_vec); - write_common_impl(socket_data_ptr, write_buf_vec_ptr); + let w_result = write_common_impl(socket_data_ptr, write_buf_vec_ptr); + if w_result.is_failure() { + let err_data = w_result.get_err(); + log(debug, #fmt("ERROR sock_buf as io::writer.writer err: %? %?", + err_data.err_name, err_data.err_msg)); + } } fn seek(dist: int, seek: io::seek_style) { log(debug, #fmt("tcp_socket_buf seek stub %? %?", dist, seek)); @@ -1204,7 +1211,7 @@ fn ipv4_ip_addr_to_sockaddr_in(input_ip: ip::ip_addr, } } -#[cfg(test)] +//#[cfg(test)] mod test { // FIXME don't run on fbsd or linux 32 bit (#2064) #[cfg(target_os="win32")] @@ -1232,6 +1239,10 @@ mod test { fn test_gl_tcp_server_access_denied() unsafe { impl_gl_tcp_ipv4_server_access_denied(); } + #[test] + fn test_gl_tcp_ipv4_server_client_reader_writer() { + impl_gl_tcp_ipv4_server_client_reader_writer(); + } } #[cfg(target_arch="x86")] @@ -1259,6 +1270,11 @@ mod test { fn test_gl_tcp_server_access_denied() unsafe { impl_gl_tcp_ipv4_server_access_denied(); } + #[test] + #[ignore(cfg(target_os = "linux"))] + fn test_gl_tcp_ipv4_server_client_reader_writer() { + impl_gl_tcp_ipv4_server_client_reader_writer(); + } } } fn impl_gl_tcp_ipv4_server_and_client() { @@ -1400,6 +1416,73 @@ mod test { } } } + fn impl_gl_tcp_ipv4_server_client_reader_writer() { + let iotask = uv::global_loop::get(); + let server_ip = "127.0.0.1"; + let server_port = 8891u; + let expected_req = "ping"; + let expected_resp = "pong"; + + let server_result_po = comm::port::(); + let server_result_ch = comm::chan(server_result_po); + + let cont_po = comm::port::<()>(); + let cont_ch = comm::chan(cont_po); + // server + task::spawn_sched(task::manual_threads(1u)) {|| + let actual_req = comm::listen {|server_ch| + run_tcp_test_server( + server_ip, + server_port, + expected_resp, + server_ch, + cont_ch, + iotask) + }; + server_result_ch.send(actual_req); + }; + comm::recv(cont_po); + // client + let server_addr = ip::v4::parse_addr(server_ip); + let conn_result = connect(server_addr, server_port, iotask); + if result::is_failure(conn_result) { + assert false; + } + let sock_buf = @socket_buf(result::unwrap(conn_result)); + buf_write(sock_buf as io::writer, expected_req); + + // so contrived! + let actual_resp = str::as_bytes(expected_resp) {|resp_buf| + buf_read(sock_buf as io::reader, + vec::len(resp_buf)) + }; + + let actual_req = comm::recv(server_result_po); + log(debug, #fmt("REQ: expected: '%s' actual: '%s'", + expected_req, actual_req)); + log(debug, #fmt("RESP: expected: '%s' actual: '%s'", + expected_resp, actual_resp)); + assert str::contains(actual_req, expected_req); + assert str::contains(actual_resp, expected_resp); + } + + fn buf_write(+w: io::writer, val: str) { + log(debug, #fmt("BUF_WRITE: val len %?", str::len(val))); + str::as_slice(val, 0u, str::len(val) -1u) {|val_slice| + str::byte_slice(val_slice) {|b_slice| + log(debug, #fmt("BUF_WRITE: b_slice len %?", + vec::len(b_slice))); + w.write(b_slice) + } + } + } + + fn buf_read(+r: io::reader, len: uint) -> str { + let new_bytes = r.read_bytes(len); + log(debug, #fmt("in buf_read.. new_bytes len: %?", + vec::len(new_bytes))); + str::from_bytes(new_bytes) + } fn run_tcp_test_server(server_ip: str, server_port: uint, resp: str, server_ch: comm::chan, @@ -1441,6 +1524,9 @@ mod test { let received_req_bytes = read(sock, 0u); alt received_req_bytes { result::ok(data) { + log(debug, "SERVER: got REQ str::from_bytes.."); + log(debug, #fmt("SERVER: REQ data len: %?", + vec::len(data))); server_ch.send( str::from_bytes(data)); log(debug, "SERVER: before write"); -- cgit 1.4.1-3-g733a5 From 708b5d986e37eeb61a98b2a7f29ba02f517e7d39 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Sun, 10 Jun 2012 08:30:43 -0700 Subject: core: str::as_slice is unneeded, yay! fixes std::net::tcp socket_buf test i mistook an "unconstrained type" error, due to type-inference messup because i didnt have return vals in some closure wired-up right, for being due to not having a str as a str/& (a str will actually auto-coerce to a str/&, so str::as_slice was erroneously added. my bad). --- src/libcore/str.rs | 11 ----------- src/libstd/net_tcp.rs | 12 +++++------- 2 files changed, 5 insertions(+), 18 deletions(-) (limited to 'src/libstd') diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 2c0f4b4a96b..35d2edd608a 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -23,7 +23,6 @@ export as_buf, as_c_str, unpack_slice, - as_slice, // Adding things to and removing things from a string push_char, @@ -1621,16 +1620,6 @@ pure fn unpack_slice(s: str/&, f: fn(*u8, uint) -> T) -> T { } } -pure fn as_slice(s: str, - start: uint, end: uint, - f: fn(str/&) -> T) -> T unsafe { - assert (start <= end); - assert (end <= len(s)); - let p = ptr::addr_of(s); - f(::unsafe::reinterpret_cast( - (ptr::offset(p, start), (end - start) * sys::size_of::()))) -} - #[doc = " Reserves capacity for exactly `n` bytes in the given string, not including the null terminator. diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 06829312849..6718e3729f7 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -1456,7 +1456,7 @@ mod test { buf_read(sock_buf as io::reader, vec::len(resp_buf)) }; - + let actual_req = comm::recv(server_result_po); log(debug, #fmt("REQ: expected: '%s' actual: '%s'", expected_req, actual_req)); @@ -1468,12 +1468,10 @@ mod test { fn buf_write(+w: io::writer, val: str) { log(debug, #fmt("BUF_WRITE: val len %?", str::len(val))); - str::as_slice(val, 0u, str::len(val) -1u) {|val_slice| - str::byte_slice(val_slice) {|b_slice| - log(debug, #fmt("BUF_WRITE: b_slice len %?", - vec::len(b_slice))); - w.write(b_slice) - } + str::byte_slice(val) {|b_slice| + log(debug, #fmt("BUF_WRITE: b_slice len %?", + vec::len(b_slice))); + w.write(b_slice) } } -- cgit 1.4.1-3-g733a5 From c0272928464c9f3ec8aa2e4a7ed17de6157ad59b Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 12 Jun 2012 08:41:06 -0700 Subject: std: mapping additional libuv ip string helpers.. add test for sockaddr_in6 .. but the test is kind of broken.. it appears that rust pads structs for alignment purposes? I can't get the struct to == 28.. that appears to be the native size of sockaddr_in6.. so we have a size 32 struct, for now. --- src/libstd/uv_ll.rs | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index db0dcf7f4f4..42dd5b93ea9 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -223,10 +223,10 @@ type sockaddr_in = { mut sin_zero: (u8, u8, u8, u8, u8, u8, u8, u8) }; -// unix size: 28 .. make due w/ 32 +// unix size: 28 .. FIXME: stuck with 32 becuse of rust padding structs? type sockaddr_in6 = { a0: *u8, a1: *u8, - a2: *u8, a3: (u8, u8, u8, u8) + a2: *u8, a3: *u8 }; mod uv_ll_struct_stubgen { @@ -500,6 +500,12 @@ native mod rustrt { fn rust_uv_err_name(err: *uv_err_t) -> *libc::c_char; fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int) -> sockaddr_in; + fn rust_uv_ip6_addr(ip: *u8, port: libc::c_int) + -> sockaddr_in6; + fn rust_uv_ip4_name(src: *sockaddr_in, dst: *u8, size: libc::size_t) + -> libc::c_int; + fn rust_uv_ip6_name(src: *sockaddr_in6, dst: *u8, size: libc::size_t) + -> libc::c_int; // FIXME ref #2064 fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t, @@ -558,6 +564,7 @@ native mod rustrt { fn rust_uv_helper_uv_write_t_size() -> libc::c_uint; fn rust_uv_helper_uv_err_t_size() -> libc::c_uint; fn rust_uv_helper_sockaddr_in_size() -> libc::c_uint; + fn rust_uv_helper_sockaddr_in6_size() -> libc::c_uint; fn rust_uv_helper_uv_async_t_size() -> libc::c_uint; fn rust_uv_helper_uv_timer_t_size() -> libc::c_uint; } @@ -686,6 +693,17 @@ unsafe fn ip4_addr(ip: str, port: int) ret rustrt::rust_uv_ip4_addr(addr_vec_ptr, port as libc::c_int); } +unsafe fn ip6_addr(ip: str, port: int) +-> sockaddr_in6 { + let mut addr_vec = str::bytes(ip); + addr_vec += [0u8]; // add null terminator + let addr_vec_ptr = vec::unsafe::to_ptr(addr_vec); + let ip_back = str::from_bytes(addr_vec); + log(debug, #fmt("vec val: '%s' length: %u", + ip_back, vec::len(addr_vec))); + ret rustrt::rust_uv_ip6_addr(addr_vec_ptr, + port as libc::c_int); +} unsafe fn timer_init(loop_ptr: *libc::c_void, timer_ptr: *uv_timer_t) -> libc::c_int { @@ -1366,6 +1384,21 @@ mod test { log(debug, output); assert foreign_handle_size as uint == rust_handle_size; } + #[test] + #[ignore(cfg(target_os = "freebsd"))] + fn test_uv_ll_struct_size_sockaddr_in6() { + let native_handle_size = + rustrt::rust_uv_helper_sockaddr_in6_size(); + let rust_handle_size = sys::size_of::(); + let output = #fmt("sockaddr_in -- native: %u rust: %u", + native_handle_size as uint, rust_handle_size); + log(debug, output); + // FIXME .. rust appears to pack structs to the nearest byte..? + // .. can't get the uv::ll::sockaddr_in6 to == 28 :/ + // .. so the type always appears to be 32 in size.. which is + // good, i guess.. better too big than too little + assert (4u+native_handle_size as uint) == rust_handle_size; + } #[test] #[ignore(cfg(target_os = "freebsd"))] -- cgit 1.4.1-3-g733a5 From 30f26ddbc99e34c42f110625f66fc9399d6f38d1 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Sun, 17 Jun 2012 20:36:36 -0700 Subject: std: adding uv::ll::ip4_name and refactored net::ip to use it replaces net::ip's previously, hand-rolled impl for ipv4 addr parsing.. we're relying on libuv, now --- src/libstd/net_ip.rs | 52 +++++++++++++++++++++++---------------------------- src/libstd/net_tcp.rs | 20 ++++++++++++++------ src/libstd/uv_ll.rs | 18 ++++++++++++++++++ 3 files changed, 55 insertions(+), 35 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 64cded848d1..106f1baa8c5 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -5,6 +5,11 @@ Types/fns concerning Internet Protocol (IP), versions 4 & 6 import vec; import uint; +import sockaddr_in = uv::ll::sockaddr_in; +import sockaddr_in6 = uv::ll::sockaddr_in6; +import uv_ip4_addr = uv::ll::ip4_addr; +import uv_ip4_name = uv::ll::ip4_name; + export ip_addr, parse_addr_err; export format_addr; export v4; @@ -12,7 +17,7 @@ export v4; #[doc = "An IP address"] enum ip_addr { #[doc="An IPv4 address"] - ipv4(u8, u8, u8, u8), + ipv4(sockaddr_in), ipv6(u16,u16,u16,u16,u16,u16,u16,u16) } @@ -32,8 +37,14 @@ Convert a `ip_addr` to a str "] fn format_addr(ip: ip_addr) -> str { alt ip { - ipv4(a, b, c, d) { - #fmt["%u.%u.%u.%u", a as uint, b as uint, c as uint, d as uint] + ipv4(addr) { + unsafe { + let result = uv_ip4_name(&addr); + if result == "" { + fail "failed to convert inner sockaddr_in address to str" + } + result + } } ipv6(_, _, _, _, _, _, _, _) { fail "FIXME (#2651) impl parsing of ipv6 addr"; @@ -59,30 +70,19 @@ j Fails if the string is not a valid IPv4 address "] fn parse_addr(ip: str) -> ip_addr { alt try_parse_addr(ip) { - result::ok(addr) { addr } + // FIXME: more copies brought to light to due the implicit + // copy compiler warning.. what can be done? out pointers, + // ala c#? + result::ok(addr) { copy(addr) } result::err(err_data) { fail err_data.err_msg } } } fn try_parse_addr(ip: str) -> result::result { - let parts = vec::map(str::split_char(ip, '.'), {|s| - alt uint::from_str(s) { - some(n) if n <= 255u { n } - _ { 256u } - } - }); - if vec::len(parts) != 4u { - result::err({err_msg: #fmt("'%s' doesn't have 4 parts", - ip)}) - } - else if vec::contains(parts, 256u) { - result::err({err_msg: #fmt("invalid octal in provided addr '%s'", - ip)}) - } - else { - result::ok(ipv4(parts[0] as u8, parts[1] as u8, - parts[2] as u8, parts[3] as u8)) + unsafe { + // need to figure out how to establish a parse failure.. + result::ok(ipv4(uv_ip4_addr(ip, 22))) } } } @@ -90,14 +90,8 @@ j Fails if the string is not a valid IPv4 address #[cfg(test)] mod test { #[test] - fn test_format_ip() { - assert (format_addr(ipv4(127u8, 0u8, 0u8, 1u8)) + fn test_ipv4_parse_and_format_ip() { + assert (format_addr(v4::parse_addr("127.0.0.1")) == "127.0.0.1") } - - #[test] - fn test_parse_ip() { - assert (v4::parse_addr("127.0.0.1") == - ipv4(127u8, 0u8, 0u8, 1u8)); - } } \ No newline at end of file diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 6718e3729f7..7c3349efae4 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -126,7 +126,7 @@ that can be used to send and receive data to/from the remote host. In the event of failure, a `net::tcp::tcp_connect_err_data` instance will be returned "] -fn connect(input_ip: ip::ip_addr, port: uint, +fn connect(-input_ip: ip::ip_addr, port: uint, iotask: iotask) -> result::result unsafe { let result_po = comm::port::(); @@ -551,7 +551,7 @@ a `result` instance containing empty data of type `()` on a successful/normal shutdown, and a `tcp_listen_err_data` enum in the event of listen exiting because of an error "] -fn listen(host_ip: ip::ip_addr, port: uint, backlog: uint, +fn listen(-host_ip: ip::ip_addr, port: uint, backlog: uint, iotask: iotask, on_establish_cb: fn~(comm::chan>), +new_connect_cb: fn~(tcp_new_connection, @@ -568,7 +568,7 @@ fn listen(host_ip: ip::ip_addr, port: uint, backlog: uint, } } -fn listen_common(host_ip: ip::ip_addr, port: uint, backlog: uint, +fn listen_common(-host_ip: ip::ip_addr, port: uint, backlog: uint, iotask: iotask, on_establish_cb: fn~(comm::chan>), -on_connect_cb: fn~(*uv::ll::uv_tcp_t)) @@ -589,8 +589,15 @@ fn listen_common(host_ip: ip::ip_addr, port: uint, backlog: uint, let server_data_ptr = ptr::addr_of(server_data); let setup_result = comm::listen {|setup_ch| + // FIXME this is to address a compiler warning about + // an implicit copy.. it seems that double nested + // will defeat a move sigil, as is done to the host_ip + // arg above.. this same pattern works w/o complaint in + // tcp::connect (because the iotask::interact cb isn't + // nested within a comm::listen block) + let loc_ip = copy(host_ip); iotask::interact(iotask) {|loop_ptr| - let tcp_addr = ipv4_ip_addr_to_sockaddr_in(host_ip, + let tcp_addr = ipv4_ip_addr_to_sockaddr_in(loc_ip, port); alt uv::ll::tcp_init(loop_ptr, server_stream_ptr) { 0i32 { @@ -1201,9 +1208,10 @@ type tcp_buffered_socket_data = { fn ipv4_ip_addr_to_sockaddr_in(input_ip: ip::ip_addr, port: uint) -> uv::ll::sockaddr_in unsafe { // FIXME (#2656): ipv6 + let addr_str = ip::format_addr(input_ip); alt input_ip { - ip::ipv4(_,_,_,_) { - uv::ll::ip4_addr(ip::format_addr(input_ip), port as int) + ip::ipv4(addr) { + uv::ll::ip4_addr(addr_str, port as int) } ip::ipv6(_,_,_,_,_,_,_,_) { fail "FIXME (#2656) ipv6 not yet supported"; diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 42dd5b93ea9..fb8ba36acd3 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -704,6 +704,24 @@ unsafe fn ip6_addr(ip: str, port: int) ret rustrt::rust_uv_ip6_addr(addr_vec_ptr, port as libc::c_int); } +unsafe fn ip4_name(src: &sockaddr_in) -> str { + // ipv4 addr max size: 15 + 1 trailing null byte + let dst: [u8] = [0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, + 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8]; + let size = 16 as libc::size_t; + vec::as_buf(dst) {|dst_buf| + let result = rustrt::rust_uv_ip4_name(src as *sockaddr_in, + dst_buf, size); + alt result { + 0i32 { + str::unsafe::from_buf(dst_buf) + } + _ { + "" + } + } + } +} unsafe fn timer_init(loop_ptr: *libc::c_void, timer_ptr: *uv_timer_t) -> libc::c_int { -- cgit 1.4.1-3-g733a5 From b6b138630e9b6a9e035be5730c7ef202ba1d4eb2 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Sun, 17 Jun 2012 20:37:24 -0700 Subject: std: getting uv_ip6_* utils working in uv::ll .. stub out some brokeness in net::tcp as a result of ipv6 coming online --- src/libstd/net_tcp.rs | 4 +--- src/libstd/uv_ll.rs | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 7c3349efae4..12ef64bab39 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -1213,9 +1213,7 @@ fn ipv4_ip_addr_to_sockaddr_in(input_ip: ip::ip_addr, ip::ipv4(addr) { uv::ll::ip4_addr(addr_str, port as int) } - ip::ipv6(_,_,_,_,_,_,_,_) { - fail "FIXME (#2656) ipv6 not yet supported"; - } + _ { fail "only works w/ ipv4";} } } diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index fb8ba36acd3..7976bdf6479 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -710,7 +710,27 @@ unsafe fn ip4_name(src: &sockaddr_in) -> str { 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8]; let size = 16 as libc::size_t; vec::as_buf(dst) {|dst_buf| - let result = rustrt::rust_uv_ip4_name(src as *sockaddr_in, + rustrt::rust_uv_ip4_name(src as *sockaddr_in, + dst_buf, size); + // FIXME: seems that checking the result of uv_ip4_name + // doesn't work too well.. + // libuv will actually map a malformed input ip to INADDR_NONE, + // which is going to be 255.255.255.255 on most + // platforms. + str::unsafe::from_buf(dst_buf); + } +} +unsafe fn ip6_name(src: &sockaddr_in6) -> str { + // ipv6 addr max size: 45 + 1 trailing null byte + let dst: [u8] = [0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, + 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, + 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, + 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, + 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, + 0u8,0u8,0u8,0u8,0u8,0u8]; + let size = 46 as libc::size_t; + vec::as_buf(dst) {|dst_buf| + let result = rustrt::rust_uv_ip6_name(src as *sockaddr_in6, dst_buf, size); alt result { 0i32 { -- cgit 1.4.1-3-g733a5 From 334c783d36522a1825ad994056c774e9cad45894 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Sun, 17 Jun 2012 20:42:48 -0700 Subject: std: adding net::ip::v6 utils and rudimentary tests, huzzah! (see caveats) libuv's own ip vetting code appears to in a somewhat woeful state, for both ipv4 and ipv6 (there are some notes in the tests for net_ip, as well as stuff added in uv_ll). They are aware of this and welcome patches. I have rudimentary code in place that can verify whether the provided str ip was, in fact, validly parsed by libuv, making a few assumptions: * for ipv4, we assume that the platform's INADDR_NONE val is 0xffffffff , I should write a helper to return this value from the platform's libc headers instead of hard-coding it in rust. * for ipv6, we assume that the library will always return '::' for malformed inputs.. as is the case in 64bit ubuntu. I need to verify this on other platforms.. but at least the debugging output is in place, so if expectations don't line up, it'll be straightforward to address --- src/libstd/net_ip.rs | 115 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 107 insertions(+), 8 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 106f1baa8c5..655742b2e2c 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -9,6 +9,8 @@ import sockaddr_in = uv::ll::sockaddr_in; import sockaddr_in6 = uv::ll::sockaddr_in6; import uv_ip4_addr = uv::ll::ip4_addr; import uv_ip4_name = uv::ll::ip4_name; +import uv_ip6_addr = uv::ll::ip6_addr; +import uv_ip6_name = uv::ll::ip6_name; export ip_addr, parse_addr_err; export format_addr; @@ -18,7 +20,7 @@ export v4; enum ip_addr { #[doc="An IPv4 address"] ipv4(sockaddr_in), - ipv6(u16,u16,u16,u16,u16,u16,u16,u16) + ipv6(sockaddr_in6) } #[doc=" @@ -46,8 +48,14 @@ fn format_addr(ip: ip_addr) -> str { result } } - ipv6(_, _, _, _, _, _, _, _) { - fail "FIXME (#2651) impl parsing of ipv6 addr"; + ipv6(addr) { + unsafe { + let result = uv_ip6_name(&addr); + if result == "" { + fail "failed to convert inner sockaddr_in address to str" + } + result + } } } } @@ -58,7 +66,7 @@ mod v4 { # Failure -j Fails if the string is not a valid IPv4 address + Fails if the string is not a valid IPv4 address # Arguments @@ -82,16 +90,107 @@ j Fails if the string is not a valid IPv4 address fn try_parse_addr(ip: str) -> result::result { unsafe { // need to figure out how to establish a parse failure.. - result::ok(ipv4(uv_ip4_addr(ip, 22))) + let new_addr = uv_ip4_addr(ip, 22); + let reformatted_name = uv_ip4_name(&new_addr); + log(debug, #fmt("try_parse_addr: input ip: %s reparsed ip: %s", + ip, reformatted_name)); + // here we're going to + let inaddr_none_val = "255.255.255.255"; + if ip != inaddr_none_val && reformatted_name == inaddr_none_val { + result::err({err_msg:#fmt("failed to parse '%s'", + ip)}) + } + else { + result::ok(ipv4(new_addr)) + } } } } +mod v6 { + #[doc = " + Convert a str to `ip_addr` + + # Failure + + Fails if the string is not a valid IPv6 address -#[cfg(test)] + # Arguments + + * ip - an ipv6 string. See RFC2460 for spec. + + # Returns + + * an `ip_addr` of the `ipv6` variant + "] + fn parse_addr(ip: str) -> ip_addr { + alt try_parse_addr(ip) { + // FIXME: more copies brought to light to due the implicit + // copy compiler warning.. what can be done? out pointers, + // ala c#? + result::ok(addr) { copy(addr) } + result::err(err_data) { + fail err_data.err_msg + } + } + } + fn try_parse_addr(ip: str) -> result::result { + unsafe { + // need to figure out how to establish a parse failure.. + let new_addr = uv_ip6_addr(ip, 22); + let reparsed_name = uv_ip6_name(&new_addr); + log(debug, #fmt("v6::try_parse_addr ip: '%s' reparsed '%s'", + ip, reparsed_name)); + // '::' appears to be uv_ip6_name() returns for bogus + // parses.. + if ip != "::" && reparsed_name == "::" { + result::err({err_msg:#fmt("failed to parse '%s'", + ip)}) + } + else { + result::ok(ipv6(new_addr)) + } + } + } +} + +//#[cfg(test)] mod test { #[test] fn test_ipv4_parse_and_format_ip() { - assert (format_addr(v4::parse_addr("127.0.0.1")) - == "127.0.0.1") + let localhost_str = "127.0.0.1"; + assert (format_addr(v4::parse_addr(localhost_str)) + == localhost_str) + } + #[test] + fn test_ipv6_parse_and_format_ip() { + let localhost_str = "::1"; + let format_result = format_addr(v6::parse_addr(localhost_str)); + log(debug, #fmt("results: expected: '%s' actual: '%s'", + localhost_str, format_result)); + assert format_result == localhost_str; + } + #[test] + fn test_ipv4_bad_parse() { + alt v4::try_parse_addr("b4df00d") { + result::err(err_info) { + log(debug, #fmt("got error as expected %?", err_info)); + assert true; + } + result::ok(addr) { + fail #fmt("Expected failure, but got addr %?", addr); + } + } + } + #[test] + fn test_ipv6_bad_parse() { + alt v6::try_parse_addr("::,~2234k;") { + result::err(err_info) { + log(debug, #fmt("got error as expected %?", err_info)); + assert true; + } + result::ok(addr) { + fail #fmt("Expected failure, but got addr %?", addr); + } + } } } \ No newline at end of file -- cgit 1.4.1-3-g733a5 From ccd4bfb6ca35eac096235c8303370c87dce338eb Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Wed, 20 Jun 2012 07:02:16 -0700 Subject: std: mapped addrinfo, addr_in and uv_getaddrinfo_t as rust records --- src/libstd/uv_ll.rs | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 2 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 7976bdf6479..1050d587336 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -229,6 +229,25 @@ type sockaddr_in6 = { a2: *u8, a3: *u8 }; +// unix size: 28 +// unix size: 28 .. FIXME: stuck with 32 becuse of rust padding structs? +type addr_in = { + a0: *u8, a1: *u8, + a2: *u8, a3: *u8 +}; + +// unix size: 48 +type addrinfo = { + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8 +}; + +// unix size: 72 +type uv_getaddrinfo_t = { + a00: *u8, a01: *u8, a02: *u8, a03: *u8, a04: *u8, a05: *u8, + a06: *u8, a07: *u8, a08: *u8 +}; + mod uv_ll_struct_stubgen { fn gen_stub_uv_tcp_t() -> uv_tcp_t { ret gen_stub_os(); @@ -474,10 +493,18 @@ mod uv_ll_struct_stubgen { a12: 0 as *u8 }; } + fn gen_stub_uv_getaddrinfo_t() -> uv_getaddrinfo_t { + { + a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8, a03: 0 as *u8, + a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8, a07: 0 as *u8, + a08: 0 as *u8 + } + } } #[nolink] native mod rustrt { + // libuv public API fn rust_uv_loop_new() -> *libc::c_void; fn rust_uv_loop_delete(lp: *libc::c_void); fn rust_uv_loop_refcount(loop_ptr: *libc::c_void) -> libc::c_int; @@ -533,6 +560,14 @@ native mod rustrt { repeat: libc::c_uint) -> libc::c_int; fn rust_uv_timer_stop(handle: *uv_timer_t) -> libc::c_int; + fn rust_uv_getaddrinfo(loop_ptr: *libc::c_void, + handle: *uv_getaddrinfo_t, cb: *u8, + node_name_ptr: *u8, + service_name_ptr: *u8, + // should probably only pass ptr::null() + hints: *addrinfo) + -> libc::c_int; + // data accessors/helpers for rust-mapped uv structs fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8; fn rust_uv_free_base_of_buf(++buf: uv_buf_t); @@ -567,6 +602,9 @@ native mod rustrt { fn rust_uv_helper_sockaddr_in6_size() -> libc::c_uint; fn rust_uv_helper_uv_async_t_size() -> libc::c_uint; fn rust_uv_helper_uv_timer_t_size() -> libc::c_uint; + fn rust_uv_helper_uv_getaddrinfo_t_size() -> libc::c_uint; + fn rust_uv_helper_addrinfo_size() -> libc::c_uint; + fn rust_uv_helper_addr_in_size() -> libc::c_uint; } unsafe fn loop_new() -> *libc::c_void { @@ -717,7 +755,7 @@ unsafe fn ip4_name(src: &sockaddr_in) -> str { // libuv will actually map a malformed input ip to INADDR_NONE, // which is going to be 255.255.255.255 on most // platforms. - str::unsafe::from_buf(dst_buf); + str::unsafe::from_buf(dst_buf) } } unsafe fn ip6_name(src: &sockaddr_in6) -> str { @@ -772,6 +810,9 @@ unsafe fn async_t() -> uv_async_t { unsafe fn timer_t() -> uv_timer_t { ret uv_ll_struct_stubgen::gen_stub_uv_timer_t(); } +unsafe fn getaddrinfo_t() -> uv_getaddrinfo_t { + ret uv_ll_struct_stubgen::gen_stub_uv_getaddrinfo_t(); +} // data access helpers unsafe fn get_loop_for_uv_handle(handle: *T) @@ -1431,12 +1472,24 @@ mod test { let output = #fmt("sockaddr_in -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); log(debug, output); - // FIXME .. rust appears to pack structs to the nearest byte..? + // FIXME .. rust appears to pad structs to the nearest byte..? // .. can't get the uv::ll::sockaddr_in6 to == 28 :/ // .. so the type always appears to be 32 in size.. which is // good, i guess.. better too big than too little assert (4u+native_handle_size as uint) == rust_handle_size; } + #[test] + #[ignore(cfg(target_os = "freebsd"))] + fn test_uv_ll_struct_size_addr_in() { + let native_handle_size = + rustrt::rust_uv_helper_addr_in_size(); + let rust_handle_size = sys::size_of::(); + let output = #fmt("addr_in -- native: %u rust: %u", + native_handle_size as uint, rust_handle_size); + log(debug, output); + // FIXME .. see note above about struct padding + assert (4u+native_handle_size as uint) == rust_handle_size; + } #[test] #[ignore(cfg(target_os = "freebsd"))] @@ -1461,4 +1514,27 @@ mod test { log(debug, output); assert foreign_handle_size as uint == rust_handle_size; } + + #[test] + #[ignore(cfg(target_os = "freebsd"))] + fn test_uv_ll_struct_size_uv_getaddrinfo_t() { + let native_handle_size = + rustrt::rust_uv_helper_uv_getaddrinfo_t_size(); + let rust_handle_size = sys::size_of::(); + let output = #fmt("uv_getaddrinfo_t -- native: %u rust: %u", + native_handle_size as uint, rust_handle_size); + log(debug, output); + assert native_handle_size as uint == rust_handle_size; + } + #[test] + #[ignore(cfg(target_os = "freebsd"))] + fn test_uv_ll_struct_size_addrinfo() { + let native_handle_size = + rustrt::rust_uv_helper_addrinfo_size(); + let rust_handle_size = sys::size_of::(); + let output = #fmt("addrinfo -- native: %u rust: %u", + native_handle_size as uint, rust_handle_size); + log(debug, output); + assert native_handle_size as uint == rust_handle_size; + } } -- cgit 1.4.1-3-g733a5 From 8afc113b61a7f12e310b56b1760fba9f03ea9306 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Fri, 22 Jun 2012 14:00:16 -0700 Subject: std: wire-up low-level bindings to libuv's uv_getaddrinfo API and friends --- src/libstd/uv_ll.rs | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 1050d587336..e645050828b 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -561,14 +561,18 @@ native mod rustrt { fn rust_uv_timer_stop(handle: *uv_timer_t) -> libc::c_int; fn rust_uv_getaddrinfo(loop_ptr: *libc::c_void, - handle: *uv_getaddrinfo_t, cb: *u8, + handle: *uv_getaddrinfo_t, + cb: *u8, node_name_ptr: *u8, service_name_ptr: *u8, // should probably only pass ptr::null() - hints: *addrinfo) - -> libc::c_int; + hints: *addrinfo) -> libc::c_int; // data accessors/helpers for rust-mapped uv structs + fn rust_uv_is_ipv4_addrinfo(input: *addrinfo) -> bool; + fn rust_uv_get_next_addrinfo(input: *addrinfo) -> *addrinfo; + fn rust_uv_addrinfo_as_sockaddr_in(input: *addrinfo) -> *sockaddr_in; + fn rust_uv_addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6; fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8; fn rust_uv_free_base_of_buf(++buf: uv_buf_t); fn rust_uv_get_stream_handle_from_connect_req( @@ -793,6 +797,19 @@ unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: uint, unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> libc::c_int { ret rustrt::rust_uv_timer_stop(timer_ptr); } +unsafe fn getaddrinfo(loop_ptr: *libc::c_void, + handle: *uv_getaddrinfo_t, + cb: *u8, + node_name_ptr: *u8, + service_name_ptr: *u8, + hints: *addrinfo) -> libc::c_int { + rustrt::rust_uv_getaddrinfo(loop_ptr, + handle, + cb, + node_name_ptr, + service_name_ptr, + hints) +} // libuv struct initializers unsafe fn tcp_t() -> uv_tcp_t { @@ -888,6 +905,19 @@ type uv_err_data = { err_msg: str }; +unsafe fn is_ipv4_addrinfo(input: *addrinfo) -> bool { + rustrt::rust_uv_is_ipv4_addrinfo(input) +} +unsafe fn get_next_addrinfo(input: *addrinfo) -> *addrinfo { + rustrt::rust_uv_get_next_addrinfo(input) +} +unsafe fn addrinfo_as_sockaddr_in(input: *addrinfo) -> *sockaddr_in { + rustrt::rust_uv_addrinfo_as_sockaddr_in(input) +} +unsafe fn addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6 { + rustrt::rust_uv_addrinfo_as_sockaddr_in6(input) +} + #[cfg(test)] mod test { enum tcp_read_data { -- cgit 1.4.1-3-g733a5 From b2894752e4bfcc5cae3a120ba3fc7a964594ed68 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Fri, 22 Jun 2012 15:31:56 -0700 Subject: std: roughcut impl of net::ip::get_addr() still needs tests --- src/libstd/net_ip.rs | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 655742b2e2c..d0eda904e83 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -4,17 +4,28 @@ Types/fns concerning Internet Protocol (IP), versions 4 & 6 import vec; import uint; +import iotask = uv::iotask::iotask; +import interact = uv::iotask::interact; +import comm::methods; import sockaddr_in = uv::ll::sockaddr_in; import sockaddr_in6 = uv::ll::sockaddr_in6; +import addrinfo = uv::ll::addrinfo; +import uv_getaddrinfo_t = uv::ll::uv_getaddrinfo_t; import uv_ip4_addr = uv::ll::ip4_addr; import uv_ip4_name = uv::ll::ip4_name; import uv_ip6_addr = uv::ll::ip6_addr; import uv_ip6_name = uv::ll::ip6_name; +import uv_getaddrinfo = uv::ll::getaddrinfo; +import create_uv_getaddrinfo_t = uv::ll::getaddrinfo_t; +import set_data_for_uv_handle = uv::ll::set_data_for_uv_handle; +import get_data_for_uv_handle = uv::ll::get_data_for_uv_handle; +import ll = uv::ll; export ip_addr, parse_addr_err; export format_addr; -export v4; +export v4, v6; +export get_addr; #[doc = "An IP address"] enum ip_addr { @@ -60,6 +71,92 @@ fn format_addr(ip: ip_addr) -> str { } } +type get_addr_data = { + output_ch: comm::chan> +}; + +crust fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int, + res: *addrinfo) unsafe { + let handle_data = get_data_for_uv_handle(handle) as + *get_addr_data; + if status == 0i32 { + if res != (ptr::null::()) { + let mut out_vec = []; + let mut curr_addr = res; + loop { + if ll::is_ipv4_addrinfo(curr_addr) { + out_vec += + [ipv4(copy(( + *ll::addrinfo_as_sockaddr_in(curr_addr))))]; + } + else { + out_vec += + [ipv6(copy(( + *ll::addrinfo_as_sockaddr_in6(curr_addr))))]; + } + + let next_addr = ll::get_next_addrinfo(curr_addr); + if next_addr == ptr::null::() as *addrinfo { + break; + } + else { + curr_addr = next_addr + } + } + (*handle_data).output_ch.send(result::ok(out_vec)); + } + else { + (*handle_data).output_ch.send( + result::err(get_addr_unknown_error)); + } + } + else { + (*handle_data).output_ch.send( + result::err(get_addr_unknown_error)); + } +} + +#[doc=" +"] +enum ip_get_addr_err { + get_addr_unknown_error +} + +#[doc=" +"] +fn get_addr(++node: str, iotask: iotask) + -> result::result<[ip_addr], ip_get_addr_err> unsafe { + comm::listen {|output_ch| + str::unpack_slice(node) {|node_ptr, len| + log(debug, #fmt("sliace len %?", len)); + let handle = create_uv_getaddrinfo_t(); + let handle_ptr = ptr::addr_of(handle); + let handle_data: get_addr_data = { + output_ch: output_ch + }; + let handle_data_ptr = ptr::addr_of(handle_data); + interact(iotask) {|loop_ptr| + let result = uv_getaddrinfo( + loop_ptr, + handle_ptr, + get_addr_cb, + node_ptr, + ptr::null(), + ptr::null()); + alt result { + 0i32 { + set_data_for_uv_handle(handle_ptr, handle_data_ptr); + } + _ { + output_ch.send(result::err(get_addr_unknown_error)); + } + } + }; + output_ch.recv() + } + } +} + mod v4 { #[doc = " Convert a str to `ip_addr` -- cgit 1.4.1-3-g733a5 From 467e4fba33e10a3a3435b271a116cf7a2eba1637 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Fri, 22 Jun 2012 21:33:11 -0700 Subject: WIP set aside unshift --- src/libstd/net_tcp.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 12ef64bab39..f1436e7c83e 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -771,7 +771,9 @@ impl tcp_socket_buf of io::reader for @tcp_socket_buf { self.read_bytes(1u)[0] as int } fn unread_byte(amt: int) { - vec::unshift((*self).buf, amt as u8); + // FIXME: stubbing this out pending the + // return of vec::unshift + //vec::unshift((*self).buf, amt as u8); } fn eof() -> bool { false // noop -- cgit 1.4.1-3-g733a5 From 5304698621bf73a060e7cc8055beb6f6ae08e410 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Mon, 25 Jun 2012 08:02:34 -0700 Subject: std: net::ip::get_addr is working w/ happy path test. needs more. --- src/libstd/net_ip.rs | 85 ++++++++++++++++++++++++++++++++++++++------------- src/libstd/net_tcp.rs | 16 +++++----- src/libstd/uv_ll.rs | 8 +++-- 3 files changed, 77 insertions(+), 32 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index d0eda904e83..9f19a3dcba8 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -17,9 +17,10 @@ import uv_ip4_name = uv::ll::ip4_name; import uv_ip6_addr = uv::ll::ip6_addr; import uv_ip6_name = uv::ll::ip6_name; import uv_getaddrinfo = uv::ll::getaddrinfo; +import uv_freeaddrinfo = uv::ll::freeaddrinfo; import create_uv_getaddrinfo_t = uv::ll::getaddrinfo_t; -import set_data_for_uv_handle = uv::ll::set_data_for_uv_handle; -import get_data_for_uv_handle = uv::ll::get_data_for_uv_handle; +import set_data_for_req = uv::ll::set_data_for_req; +import get_data_for_req = uv::ll::get_data_for_req; import ll = uv::ll; export ip_addr, parse_addr_err; @@ -77,43 +78,65 @@ type get_addr_data = { crust fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int, res: *addrinfo) unsafe { - let handle_data = get_data_for_uv_handle(handle) as + log(debug, "in get_addr_cb"); + let handle_data = get_data_for_req(handle) as *get_addr_data; if status == 0i32 { if res != (ptr::null::()) { let mut out_vec = []; + let mut addr_strings = []; + log(debug, #fmt("initial addrinfo: %?", res)); let mut curr_addr = res; loop { - if ll::is_ipv4_addrinfo(curr_addr) { - out_vec += - [ipv4(copy(( - *ll::addrinfo_as_sockaddr_in(curr_addr))))]; + let new_ip_addr = if ll::is_ipv4_addrinfo(curr_addr) { + ipv4(copy(( + *ll::addrinfo_as_sockaddr_in(curr_addr)))) } else { - out_vec += - [ipv6(copy(( - *ll::addrinfo_as_sockaddr_in6(curr_addr))))]; + ipv6(copy(( + *ll::addrinfo_as_sockaddr_in6(curr_addr)))) + }; + // we're doing this check to avoid adding multiple + // ip_addrs to the out_vec that are duplicates.. on + // 64bit unbuntu a call to uv_getaddrinfo against + // localhost seems to return three addrinfos, all + // distinct (by ptr addr), that are all ipv4 + // addresses and all point to 127.0.0.1 + let addr_str = format_addr(new_ip_addr); + if !vec::contains(addr_strings, addr_str) { + addr_strings += [addr_str]; + out_vec += [new_ip_addr]; } let next_addr = ll::get_next_addrinfo(curr_addr); if next_addr == ptr::null::() as *addrinfo { + log(debug, "null next_addr encountered. no mas"); break; } else { - curr_addr = next_addr + curr_addr = next_addr; + log(debug, #fmt("next_addr addrinfo: %?", curr_addr)); } } + log(debug, #fmt("successful process addrinfo result, len: %?", + vec::len(out_vec))); (*handle_data).output_ch.send(result::ok(out_vec)); } else { + log(debug, "addrinfo pointer is NULL"); (*handle_data).output_ch.send( result::err(get_addr_unknown_error)); } } else { + log(debug, "status != 0 error in get_addr_cb"); (*handle_data).output_ch.send( result::err(get_addr_unknown_error)); } + if res != (ptr::null::()) { + uv_freeaddrinfo(res); + } + log(debug, "leaving get_addr_cb"); } #[doc=" @@ -128,7 +151,7 @@ fn get_addr(++node: str, iotask: iotask) -> result::result<[ip_addr], ip_get_addr_err> unsafe { comm::listen {|output_ch| str::unpack_slice(node) {|node_ptr, len| - log(debug, #fmt("sliace len %?", len)); + log(debug, #fmt("slice len %?", len)); let handle = create_uv_getaddrinfo_t(); let handle_ptr = ptr::addr_of(handle); let handle_data: get_addr_data = { @@ -145,7 +168,7 @@ fn get_addr(++node: str, iotask: iotask) ptr::null()); alt result { 0i32 { - set_data_for_uv_handle(handle_ptr, handle_data_ptr); + set_data_for_req(handle_ptr, handle_data_ptr); } _ { output_ch.send(result::err(get_addr_unknown_error)); @@ -175,9 +198,6 @@ mod v4 { "] fn parse_addr(ip: str) -> ip_addr { alt try_parse_addr(ip) { - // FIXME: more copies brought to light to due the implicit - // copy compiler warning.. what can be done? out pointers, - // ala c#? result::ok(addr) { copy(addr) } result::err(err_data) { fail err_data.err_msg @@ -198,7 +218,7 @@ mod v4 { ip)}) } else { - result::ok(ipv4(new_addr)) + result::ok(ipv4(copy(new_addr))) } } } @@ -221,9 +241,6 @@ mod v6 { "] fn parse_addr(ip: str) -> ip_addr { alt try_parse_addr(ip) { - // FIXME: more copies brought to light to due the implicit - // copy compiler warning.. what can be done? out pointers, - // ala c#? result::ok(addr) { copy(addr) } result::err(err_data) { fail err_data.err_msg @@ -250,7 +267,7 @@ mod v6 { } } -//#[cfg(test)] +#[cfg(test)] mod test { #[test] fn test_ipv4_parse_and_format_ip() { @@ -290,4 +307,30 @@ mod test { } } } + #[test] + fn test_get_addr() { + let localhost_name = "localhost"; + let iotask = uv::global_loop::get(); + let ga_result = get_addr(localhost_name, iotask); + if result::is_err(ga_result) { + fail "got err result from net::ip::get_addr();" + } + // note really sure how to realiably test/assert + // this.. mostly just wanting to see it work, atm. + let results = result::unwrap(ga_result); + log(debug, #fmt("test_get_addr: Number of results for %s: %?", + localhost_name, vec::len(results))); + for vec::each(results) {|r| + let ipv_prefix = alt r { + ipv4(_) { + "IPv4" + } + ipv6(_) { + "IPv6" + } + }; + log(debug, #fmt("test_get_addr: result %s: '%s'", + ipv_prefix, format_addr(r))); + } + } } \ No newline at end of file diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index f1436e7c83e..d4fd6509339 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -418,7 +418,7 @@ net::tcp::listen(remote_ip, remote_port, backlog) let cont_ch = comm::chan(cont_po); task::spawn {|| let accept_result = net::tcp::accept(new_conn); - if accept_result.is_failure() { + if accept_result.is_err() { comm::send(cont_ch, result::get_err(accept_result)); // fail? } @@ -754,7 +754,7 @@ impl tcp_socket_buf of io::reader for @tcp_socket_buf { } else { let read_result = read((*self).sock, 0u); - if read_result.is_failure() { + if read_result.is_err() { let err_data = read_result.get_err(); log(debug, #fmt("ERROR sock_buf as io::reader.read err %? %?", err_data.err_name, err_data.err_msg)); @@ -771,9 +771,7 @@ impl tcp_socket_buf of io::reader for @tcp_socket_buf { self.read_bytes(1u)[0] as int } fn unread_byte(amt: int) { - // FIXME: stubbing this out pending the - // return of vec::unshift - //vec::unshift((*self).buf, amt as u8); + vec::unshift((*self).buf, amt as u8); } fn eof() -> bool { false // noop @@ -798,7 +796,7 @@ impl tcp_socket_buf of io::writer for @tcp_socket_buf { }; let write_buf_vec_ptr = ptr::addr_of(write_buf_vec); let w_result = write_common_impl(socket_data_ptr, write_buf_vec_ptr); - if w_result.is_failure() { + if w_result.is_err() { let err_data = w_result.get_err(); log(debug, #fmt("ERROR sock_buf as io::writer.writer err: %? %?", err_data.err_name, err_data.err_msg)); @@ -1321,7 +1319,7 @@ mod test { client_ch, hl_loop) }; - assert actual_resp_result.is_success(); + assert actual_resp_result.is_ok(); let actual_resp = actual_resp_result.get(); let actual_req = comm::recv(server_result_po); log(debug, #fmt("REQ: expected: '%s' actual: '%s'", @@ -1453,7 +1451,7 @@ mod test { // client let server_addr = ip::v4::parse_addr(server_ip); let conn_result = connect(server_addr, server_port, iotask); - if result::is_failure(conn_result) { + if result::is_err(conn_result) { assert false; } let sock_buf = @socket_buf(result::unwrap(conn_result)); @@ -1589,7 +1587,7 @@ mod test { new_conn, kill_ch); }); // err check on listen_result - if result::is_failure(listen_result) { + if result::is_err(listen_result) { result::get_err(listen_result) } else { diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index e645050828b..09f8c61d45d 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -567,6 +567,7 @@ native mod rustrt { service_name_ptr: *u8, // should probably only pass ptr::null() hints: *addrinfo) -> libc::c_int; + fn rust_uv_freeaddrinfo(res: *addrinfo); // data accessors/helpers for rust-mapped uv structs fn rust_uv_is_ipv4_addrinfo(input: *addrinfo) -> bool; @@ -755,7 +756,7 @@ unsafe fn ip4_name(src: &sockaddr_in) -> str { rustrt::rust_uv_ip4_name(src as *sockaddr_in, dst_buf, size); // FIXME: seems that checking the result of uv_ip4_name - // doesn't work too well.. + // doesn't work too well.. // libuv will actually map a malformed input ip to INADDR_NONE, // which is going to be 255.255.255.255 on most // platforms. @@ -810,6 +811,9 @@ unsafe fn getaddrinfo(loop_ptr: *libc::c_void, service_name_ptr, hints) } +unsafe fn freeaddrinfo(res: *addrinfo) { + rustrt::rust_uv_freeaddrinfo(res); +} // libuv struct initializers unsafe fn tcp_t() -> uv_tcp_t { @@ -1544,7 +1548,7 @@ mod test { log(debug, output); assert foreign_handle_size as uint == rust_handle_size; } - + #[test] #[ignore(cfg(target_os = "freebsd"))] fn test_uv_ll_struct_size_uv_getaddrinfo_t() { -- cgit 1.4.1-3-g733a5 From 5014a2a4132fca05c39c34a6584e1a172b9008d6 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 26 Jun 2012 06:53:32 -0700 Subject: std: whitespace/comment clean --- src/libstd/net_ip.rs | 12 ------------ src/libstd/net_tcp.rs | 11 +++-------- src/libstd/uv_ll.rs | 20 +++++++++++--------- 3 files changed, 14 insertions(+), 29 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 9f19a3dcba8..0e13a2c590c 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -84,7 +84,6 @@ crust fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int, if status == 0i32 { if res != (ptr::null::()) { let mut out_vec = []; - let mut addr_strings = []; log(debug, #fmt("initial addrinfo: %?", res)); let mut curr_addr = res; loop { @@ -96,17 +95,6 @@ crust fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int, ipv6(copy(( *ll::addrinfo_as_sockaddr_in6(curr_addr)))) }; - // we're doing this check to avoid adding multiple - // ip_addrs to the out_vec that are duplicates.. on - // 64bit unbuntu a call to uv_getaddrinfo against - // localhost seems to return three addrinfos, all - // distinct (by ptr addr), that are all ipv4 - // addresses and all point to 127.0.0.1 - let addr_str = format_addr(new_ip_addr); - if !vec::contains(addr_strings, addr_str) { - addr_strings += [addr_str]; - out_vec += [new_ip_addr]; - } let next_addr = ll::get_next_addrinfo(curr_addr); if next_addr == ptr::null::() as *addrinfo { diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index d4fd6509339..da8c55c3d95 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -7,7 +7,8 @@ import uv::iotask; import uv::iotask::iotask; import comm::methods; import future_spawn = future::spawn; -// FIXME: should be able to replace w/ result::{result, extensions}; +// FIXME #1935 +// should be able to, but can't atm, replace w/ result::{result, extensions}; import result::*; import libc::size_t; import str::extensions; @@ -589,7 +590,7 @@ fn listen_common(-host_ip: ip::ip_addr, port: uint, backlog: uint, let server_data_ptr = ptr::addr_of(server_data); let setup_result = comm::listen {|setup_ch| - // FIXME this is to address a compiler warning about + // this is to address a compiler warning about // an implicit copy.. it seems that double nested // will defeat a move sigil, as is done to the host_ip // arg above.. this same pattern works w/o complaint in @@ -1239,9 +1240,6 @@ mod test { impl_gl_tcp_ipv4_server_address_in_use(); } #[test] - // FIXME: this probably needs to be ignored on windows. - // ... need to verify (someday we'll have 64bit windows! :) - //#[ignore(cfg(target_os = "win32"))] fn test_gl_tcp_server_access_denied() unsafe { impl_gl_tcp_ipv4_server_access_denied(); } @@ -1270,9 +1268,6 @@ mod test { } #[test] #[ignore(cfg(target_os = "linux"))] - // FIXME: this probably needs to be ignored on windows. - // ... need to verify - //#[ignore(cfg(target_os = "win32"))] fn test_gl_tcp_server_access_denied() unsafe { impl_gl_tcp_ipv4_server_access_denied(); } diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 09f8c61d45d..35fa5d4e57e 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -223,14 +223,15 @@ type sockaddr_in = { mut sin_zero: (u8, u8, u8, u8, u8, u8, u8, u8) }; -// unix size: 28 .. FIXME: stuck with 32 becuse of rust padding structs? +// unix size: 28 .. FIXME #1645 +// stuck with 32 becuse of rust padding structs? type sockaddr_in6 = { a0: *u8, a1: *u8, a2: *u8, a3: *u8 }; -// unix size: 28 -// unix size: 28 .. FIXME: stuck with 32 becuse of rust padding structs? +// unix size: 28 .. FIXME #1645 +// stuck with 32 becuse of rust padding structs? type addr_in = { a0: *u8, a1: *u8, a2: *u8, a3: *u8 @@ -755,11 +756,12 @@ unsafe fn ip4_name(src: &sockaddr_in) -> str { vec::as_buf(dst) {|dst_buf| rustrt::rust_uv_ip4_name(src as *sockaddr_in, dst_buf, size); - // FIXME: seems that checking the result of uv_ip4_name + // seems that checking the result of uv_ip4_name // doesn't work too well.. - // libuv will actually map a malformed input ip to INADDR_NONE, - // which is going to be 255.255.255.255 on most - // platforms. + // you're stuck looking at the value of dst_buf + // to see if it is the string representation of + // INADDR_NONE (0xffffffff or 255.255.255.255 on + // many platforms) str::unsafe::from_buf(dst_buf) } } @@ -1506,7 +1508,7 @@ mod test { let output = #fmt("sockaddr_in -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); log(debug, output); - // FIXME .. rust appears to pad structs to the nearest byte..? + // FIXME #1645 .. rust appears to pad structs to the nearest byte..? // .. can't get the uv::ll::sockaddr_in6 to == 28 :/ // .. so the type always appears to be 32 in size.. which is // good, i guess.. better too big than too little @@ -1521,7 +1523,7 @@ mod test { let output = #fmt("addr_in -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); log(debug, output); - // FIXME .. see note above about struct padding + // FIXME #1645 .. see note above about struct padding assert (4u+native_handle_size as uint) == rust_handle_size; } -- cgit 1.4.1-3-g733a5 From 81157ff1d275ed66219f0c41d5695d81454f9e25 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 26 Jun 2012 09:05:33 -0700 Subject: std: add uv::ll::is_ipv6_addrinfo and get_INADDR_NONE --- src/libstd/uv_ll.rs | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/libstd') diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 35fa5d4e57e..e0668ebd44f 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -571,7 +571,9 @@ native mod rustrt { fn rust_uv_freeaddrinfo(res: *addrinfo); // data accessors/helpers for rust-mapped uv structs + fn rust_uv_helper_get_INADDR_NONE() -> u32; fn rust_uv_is_ipv4_addrinfo(input: *addrinfo) -> bool; + fn rust_uv_is_ipv6_addrinfo(input: *addrinfo) -> bool; fn rust_uv_get_next_addrinfo(input: *addrinfo) -> *addrinfo; fn rust_uv_addrinfo_as_sockaddr_in(input: *addrinfo) -> *sockaddr_in; fn rust_uv_addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6; @@ -914,6 +916,12 @@ type uv_err_data = { unsafe fn is_ipv4_addrinfo(input: *addrinfo) -> bool { rustrt::rust_uv_is_ipv4_addrinfo(input) } +unsafe fn is_ipv6_addrinfo(input: *addrinfo) -> bool { + rustrt::rust_uv_is_ipv6_addrinfo(input) +} +unsafe fn get_INADDR_NONE() -> u32 { + rustrt::rust_uv_helper_get_INADDR_NONE() +} unsafe fn get_next_addrinfo(input: *addrinfo) -> *addrinfo { rustrt::rust_uv_get_next_addrinfo(input) } -- cgit 1.4.1-3-g733a5 From e5212de671bbc7a6898d7f45bb08aca2de298dac Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 26 Jun 2012 09:07:24 -0700 Subject: std: beef up ipv4 validation a bit now the best of what we had prior to libuv integration (proper validation of an ipv4 string), along with libuv support (initial ipv6 support) libuv has even weaker facilities for validating an input ipv6 (but still more than what we had), so eventually the "right" answer would be to roll a proper ipv6 address string parser in rust --- src/libstd/net_ip.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 7 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 0e13a2c590c..77940468cfa 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -91,10 +91,18 @@ crust fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int, ipv4(copy(( *ll::addrinfo_as_sockaddr_in(curr_addr)))) } - else { + else if ll::is_ipv6_addrinfo(curr_addr) { ipv6(copy(( *ll::addrinfo_as_sockaddr_in6(curr_addr)))) + } + else { + log(debug, "curr_addr is not of family AF_INET or "+ + "AF_INET6. Error."); + (*handle_data).output_ch.send( + result::err(get_addr_unknown_error)); + break; }; + out_vec += [new_ip_addr]; let next_addr = ll::get_next_addrinfo(curr_addr); if next_addr == ptr::null::() as *addrinfo { @@ -192,18 +200,58 @@ mod v4 { } } } + // the simple, old style numberic representation of + // ipv4 + type ipv4_rep = { a: u8, b: u8, c: u8, d:u8 }; + impl x for ipv4_rep { + // this is pretty dastardly, i know + unsafe fn as_u32() -> u32 { + *((ptr::addr_of(self)) as *u32) + } + } + fn parse_to_ipv4_rep(ip: str) -> result::result { + let parts = vec::map(str::split_char(ip, '.'), {|s| + alt uint::from_str(s) { + some(n) if n <= 255u { n } + _ { 256u } + } + }); + if vec::len(parts) != 4u { + result::err(#fmt("'%s' doesn't have 4 parts", ip)) + } + else if vec::contains(parts, 256u) { + result::err(#fmt("invalid octal in addr '%s'", ip)) + } + else { + result::ok({a: parts[0] as u8, b: parts[1] as u8, + c: parts[2] as u8, d: parts[3] as u8}) + } + } fn try_parse_addr(ip: str) -> result::result { unsafe { - // need to figure out how to establish a parse failure.. + let INADDR_NONE = ll::get_INADDR_NONE(); + let ip_rep_result = parse_to_ipv4_rep(ip); + if result::is_err(ip_rep_result) { + let err_str = result::get_err(ip_rep_result); + ret result::err({err_msg: err_str}) + } + // ipv4_rep.as_u32 is unsafe :/ + let input_is_inaddr_none = + result::get(ip_rep_result).as_u32() == INADDR_NONE; + let new_addr = uv_ip4_addr(ip, 22); let reformatted_name = uv_ip4_name(&new_addr); log(debug, #fmt("try_parse_addr: input ip: %s reparsed ip: %s", ip, reformatted_name)); - // here we're going to - let inaddr_none_val = "255.255.255.255"; - if ip != inaddr_none_val && reformatted_name == inaddr_none_val { - result::err({err_msg:#fmt("failed to parse '%s'", - ip)}) + let ref_ip_rep_result = parse_to_ipv4_rep(reformatted_name); + if result::is_err(ref_ip_rep_result) { + let err_str = result::get_err(ref_ip_rep_result); + ret result::err({err_msg: err_str}) + } + if result::get(ref_ip_rep_result).as_u32() == INADDR_NONE && + !input_is_inaddr_none { + ret result::err( + {err_msg: "uv_ip4_name produced invalid result."}) } else { result::ok(ipv4(copy(new_addr))) -- cgit 1.4.1-3-g733a5 From e097ff6398bdf08a6f5f8d6abe2ad4521ab3d09a Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 26 Jun 2012 11:29:57 -0700 Subject: std: add test for net::ip::get_addr failure --- src/libstd/net_ip.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/libstd') diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 77940468cfa..95a8e953a5e 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -368,5 +368,15 @@ mod test { log(debug, #fmt("test_get_addr: result %s: '%s'", ipv_prefix, format_addr(r))); } + // at least one result.. this is going to vary from system + // to system, based on stuff like the contents of /etc/hosts + assert vec::len(results) > 0; + } + #[test] + fn test_get_addr_bad_input() { + let localhost_name = "sjkl234m,./sdf"; + let iotask = uv::global_loop::get(); + let ga_result = get_addr(localhost_name, iotask); + assert result::is_err(ga_result); } } \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 9edcb104ff2bbedd389ec519aea1de9c88c2beb1 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 26 Jun 2012 12:47:44 -0700 Subject: std: addressing #2656 (ipv6 support in net::tcp) .. there are some additional FIXME nags in net_tcp (L 1012) about blocking because libuv is holding unsafe ptrs to task local data. the proposed fix going is not really feasible w/ the current design, IMO, but i'll leave it there in case someone really wants to make the case without creating more hassle than it's worth. --- src/libstd/net_ip.rs | 4 +-- src/libstd/net_tcp.rs | 68 ++++++++++++++++++++++++++++++++------------------- src/libstd/uv_ll.rs | 23 +++++++++++++++++ src/rt/rust_uv.cpp | 33 +++++++++++++------------ src/rt/rustrt.def.in | 2 ++ 5 files changed, 88 insertions(+), 42 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 95a8e953a5e..6087def6624 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -230,7 +230,7 @@ mod v4 { fn try_parse_addr(ip: str) -> result::result { unsafe { let INADDR_NONE = ll::get_INADDR_NONE(); - let ip_rep_result = parse_to_ipv4_rep(ip); + let ip_rep_result = parse_to_ipv4_rep(ip); if result::is_err(ip_rep_result) { let err_str = result::get_err(ip_rep_result); ret result::err({err_msg: err_str}) @@ -243,7 +243,7 @@ mod v4 { let reformatted_name = uv_ip4_name(&new_addr); log(debug, #fmt("try_parse_addr: input ip: %s reparsed ip: %s", ip, reformatted_name)); - let ref_ip_rep_result = parse_to_ipv4_rep(reformatted_name); + let ref_ip_rep_result = parse_to_ipv4_rep(reformatted_name); if result::is_err(ref_ip_rep_result) { let err_str = result::get_err(ref_ip_rep_result); ret result::err({err_msg: err_str}) diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index da8c55c3d95..585307b8266 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -164,16 +164,35 @@ fn connect(-input_ip: ip::ip_addr, port: uint, alt input_ip { ipv4 { log(debug, "dealing w/ ipv4 connection.."); - let tcp_addr = ipv4_ip_addr_to_sockaddr_in(input_ip, - port); - let tcp_addr_ptr = ptr::addr_of(tcp_addr); let connect_req_ptr = ptr::addr_of((*socket_data_ptr).connect_req); - alt uv::ll::tcp_connect( - connect_req_ptr, - stream_handle_ptr, - tcp_addr_ptr, - tcp_connect_on_connect_cb) { + let addr_str = ip::format_addr(input_ip); + let connect_result = alt input_ip { + ip::ipv4(addr) { + // have to "recreate" the sockaddr_in/6 + // since the ip_addr discards the port + // info.. should probably add an additional + // rust type that actually is closer to + // what the libuv API expects (ip str + port num) + log(debug, #fmt("addr: %?", addr)); + let in_addr = uv::ll::ip4_addr(addr_str, port as int); + uv::ll::tcp_connect( + connect_req_ptr, + stream_handle_ptr, + ptr::addr_of(in_addr), + tcp_connect_on_connect_cb) + } + ip::ipv6(addr) { + log(debug, #fmt("addr: %?", addr)); + let in_addr = uv::ll::ip6_addr(addr_str, port as int); + uv::ll::tcp_connect6( + connect_req_ptr, + stream_handle_ptr, + ptr::addr_of(in_addr), + tcp_connect_on_connect_cb) + } + }; + alt connect_result { 0i32 { log(debug, "tcp_connect successful"); // reusable data that we'll have for the @@ -598,15 +617,27 @@ fn listen_common(-host_ip: ip::ip_addr, port: uint, backlog: uint, // nested within a comm::listen block) let loc_ip = copy(host_ip); iotask::interact(iotask) {|loop_ptr| - let tcp_addr = ipv4_ip_addr_to_sockaddr_in(loc_ip, - port); alt uv::ll::tcp_init(loop_ptr, server_stream_ptr) { 0i32 { uv::ll::set_data_for_uv_handle( server_stream_ptr, server_data_ptr); - alt uv::ll::tcp_bind(server_stream_ptr, - ptr::addr_of(tcp_addr)) { + let addr_str = ip::format_addr(loc_ip); + let bind_result = alt loc_ip { + ip::ipv4(addr) { + log(debug, #fmt("addr: %?", addr)); + let in_addr = uv::ll::ip4_addr(addr_str, port as int); + uv::ll::tcp_bind(server_stream_ptr, + ptr::addr_of(in_addr)) + } + ip::ipv6(addr) { + log(debug, #fmt("addr: %?", addr)); + let in_addr = uv::ll::ip6_addr(addr_str, port as int); + uv::ll::tcp_bind6(server_stream_ptr, + ptr::addr_of(in_addr)) + } + }; + alt bind_result { 0i32 { alt uv::ll::listen(server_stream_ptr, backlog as libc::c_int, @@ -1205,19 +1236,6 @@ type tcp_buffered_socket_data = { mut buf: [u8] }; -// convert rust ip_addr to libuv's native representation -fn ipv4_ip_addr_to_sockaddr_in(input_ip: ip::ip_addr, - port: uint) -> uv::ll::sockaddr_in unsafe { - // FIXME (#2656): ipv6 - let addr_str = ip::format_addr(input_ip); - alt input_ip { - ip::ipv4(addr) { - uv::ll::ip4_addr(addr_str, port as int) - } - _ { fail "only works w/ ipv4";} - } -} - //#[cfg(test)] mod test { // FIXME don't run on fbsd or linux 32 bit (#2064) diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index e0668ebd44f..7921a84175a 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -542,6 +542,14 @@ native mod rustrt { // FIXME ref #2064 fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t, ++addr: *sockaddr_in) -> libc::c_int; + // FIXME ref #2064 + fn rust_uv_tcp_connect6(connect_ptr: *uv_connect_t, + tcp_handle_ptr: *uv_tcp_t, + ++after_cb: *u8, + ++addr: *sockaddr_in6) -> libc::c_int; + // FIXME ref #2064 + fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t, + ++addr: *sockaddr_in6) -> libc::c_int; fn rust_uv_listen(stream: *libc::c_void, backlog: libc::c_int, cb: *u8) -> libc::c_int; fn rust_uv_accept(server: *libc::c_void, client: *libc::c_void) @@ -651,11 +659,26 @@ unsafe fn tcp_connect(connect_ptr: *uv_connect_t, after_connect_cb, addr_ptr); } // FIXME ref #2064 +unsafe fn tcp_connect6(connect_ptr: *uv_connect_t, + tcp_handle_ptr: *uv_tcp_t, + addr_ptr: *sockaddr_in6, + ++after_connect_cb: *u8) +-> libc::c_int { + ret rustrt::rust_uv_tcp_connect6(connect_ptr, tcp_handle_ptr, + after_connect_cb, addr_ptr); +} +// FIXME ref #2064 unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t, addr_ptr: *sockaddr_in) -> libc::c_int { ret rustrt::rust_uv_tcp_bind(tcp_server_ptr, addr_ptr); } +// FIXME ref #2064 +unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t, + addr_ptr: *sockaddr_in6) -> libc::c_int { + ret rustrt::rust_uv_tcp_bind6(tcp_server_ptr, + addr_ptr); +} unsafe fn listen(stream: *T, backlog: libc::c_int, cb: *u8) -> libc::c_int { diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index f681c6bdd99..e47af4e10a3 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -238,32 +238,36 @@ rust_uv_tcp_connect(uv_connect_t* connect_ptr, uv_tcp_t* tcp_ptr, uv_connect_cb cb, sockaddr_in* addr_ptr) { - rust_task* task = rust_get_current_task(); - LOG(task, stdlib, "inside rust_uv_tcp_connect"); // FIXME ref #2064 sockaddr_in addr = *addr_ptr; - LOG(task, stdlib, "before tcp_connect .. port: %d", - addr.sin_port); - LOG(task, stdlib, "before tcp_connect.. tcp stream:" \ - "%lu cb ptr: %lu", - (unsigned long int)tcp_ptr, (unsigned long int)cb); int result = uv_tcp_connect(connect_ptr, tcp_ptr, addr, cb); - LOG(task, stdlib, "leaving rust_uv_tcp_connect.." \ - "and result: %d", - result); return result; } extern "C" int rust_uv_tcp_bind(uv_tcp_t* tcp_server, sockaddr_in* addr_ptr) { // FIXME ref #2064 - rust_task* task = rust_get_current_task(); sockaddr_in addr = *addr_ptr; - LOG(task, stdlib, "before uv_tcp_bind .. tcp_server:" \ - "%lu port: %d", - (unsigned long int)tcp_server, addr.sin_port); return uv_tcp_bind(tcp_server, addr); } +extern "C" int +rust_uv_tcp_connect6(uv_connect_t* connect_ptr, + uv_tcp_t* tcp_ptr, + uv_connect_cb cb, + sockaddr_in6* addr_ptr) { + // FIXME ref #2064 + sockaddr_in6 addr = *addr_ptr; + int result = uv_tcp_connect6(connect_ptr, tcp_ptr, addr, cb); + return result; +} + +extern "C" int +rust_uv_tcp_bind6 +(uv_tcp_t* tcp_server, sockaddr_in6* addr_ptr) { + // FIXME ref #2064 + sockaddr_in6 addr = *addr_ptr; + return uv_tcp_bind6(tcp_server, addr); +} extern "C" int rust_uv_listen(uv_stream_t* stream, int backlog, @@ -328,7 +332,6 @@ extern "C" unsigned int rust_uv_helper_get_INADDR_NONE() { return INADDR_NONE; } - extern "C" uv_stream_t* rust_uv_get_stream_handle_from_connect_req(uv_connect_t* connect) { return connect->handle; diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 2fed7b35685..a218782dcbe 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -116,6 +116,8 @@ rust_uv_ip6_addr rust_uv_ip6_name rust_uv_tcp_connect rust_uv_tcp_bind +rust_uv_tcp_connect6 +rust_uv_tcp_bind6 rust_uv_listen rust_uv_accept rust_uv_write -- cgit 1.4.1-3-g733a5 From b0c4b8ba1860a99f744538aabae4404935fc7555 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 26 Jun 2012 14:39:47 -0700 Subject: std: fix errors from recent rebase and vec expr/type syntax update --- src/libstd/net_ip.rs | 8 ++++---- src/libstd/net_tcp.rs | 44 +++++++++++++++++++++----------------------- src/libstd/uv_ll.rs | 18 +++++++++--------- 3 files changed, 34 insertions(+), 36 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 6087def6624..3efca378bc8 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -73,7 +73,7 @@ fn format_addr(ip: ip_addr) -> str { } type get_addr_data = { - output_ch: comm::chan> + output_ch: comm::chan> }; crust fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int, @@ -83,7 +83,7 @@ crust fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int, *get_addr_data; if status == 0i32 { if res != (ptr::null::()) { - let mut out_vec = []; + let mut out_vec = []/~; log(debug, #fmt("initial addrinfo: %?", res)); let mut curr_addr = res; loop { @@ -102,7 +102,7 @@ crust fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int, result::err(get_addr_unknown_error)); break; }; - out_vec += [new_ip_addr]; + out_vec += [new_ip_addr]/~; let next_addr = ll::get_next_addrinfo(curr_addr); if next_addr == ptr::null::() as *addrinfo { @@ -144,7 +144,7 @@ enum ip_get_addr_err { #[doc=" "] fn get_addr(++node: str, iotask: iotask) - -> result::result<[ip_addr], ip_get_addr_err> unsafe { + -> result::result<[ip_addr]/~, ip_get_addr_err> unsafe { comm::listen {|output_ch| str::unpack_slice(node) {|node_ptr, len| log(debug, #fmt("slice len %?", len)); diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index 585307b8266..c0aa3394e77 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -45,7 +45,7 @@ class tcp_socket { new(socket_data: @tcp_socket_data) { self.socket_data = socket_data; } drop { unsafe { - tear_down_socket_data(socket_data) + tear_down_socket_data(self.socket_data) } } } @@ -56,8 +56,9 @@ A buffered wrapper for `net::tcp::tcp_socket` It is created with a call to `net::tcp::socket_buf()` and has impls that satisfy both the `io::reader` and `io::writer` ifaces. "] -resource tcp_socket_buf(data: @tcp_buffered_socket_data) { - log(debug, #fmt("dtor for tcp_socket_buf.. %?", data)); +class tcp_socket_buf { + let data: @tcp_buffered_socket_data; + new(data: @tcp_buffered_socket_data) { self.data = data; } } #[doc=" @@ -305,7 +306,7 @@ fn write_future(sock: tcp_socket, raw_write_data: [u8]/~) let socket_data_ptr = ptr::addr_of(*(sock.socket_data)); future_spawn {|| let data_copy = copy(raw_write_data); - write_common_impl(socket_data_ptr, data_copy); + write_common_impl(socket_data_ptr, data_copy) } } @@ -337,10 +338,10 @@ Stop reading from an open TCP connection; used with `read_start` * `sock` - a `net::tcp::tcp_socket` that you wish to stop reading on "] fn read_stop(sock: tcp_socket, - -read_port: comm::port>) -> + -read_port: comm::port>) -> result::result<(), tcp_err_data> unsafe { log(debug, #fmt("taking the read_port out of commission %?", read_port)); - let socket_data = ptr::addr_of(**sock); + let socket_data = ptr::addr_of(*sock.socket_data); read_stop_common_impl(socket_data) } @@ -735,7 +736,7 @@ or `io::writer` A buffered wrapper that you can cast as an `io::reader` or `io::writer` "] fn socket_buf(-sock: tcp_socket) -> tcp_socket_buf { - tcp_socket_buf(@{ sock: sock, mut buf: [] }) + tcp_socket_buf(@{ sock: sock, mut buf: []/~ }) } #[doc=" @@ -747,7 +748,7 @@ impl tcp_socket for tcp_socket { read_start(self) } fn read_stop(-read_port: - comm::port>) -> + comm::port>) -> result::result<(), tcp_err_data> { read_stop(self, read_port) } @@ -773,28 +774,28 @@ impl tcp_socket for tcp_socket { Implementation of `io::reader` iface for a buffered `net::tcp::tcp_socket` "] impl tcp_socket_buf of io::reader for @tcp_socket_buf { - fn read_bytes(amt: uint) -> [u8] { + fn read_bytes(amt: uint) -> [u8]/~ { let has_amt_available = - vec::len((*self).buf) >= amt; + vec::len((*(self.data)).buf) >= amt; if has_amt_available { // no arbitrary-length shift in vec::? - let mut ret_buf = []; + let mut ret_buf = []/~; while vec::len(ret_buf) < amt { - ret_buf += [vec::shift((*self).buf)]; + ret_buf += [vec::shift((*(self.data)).buf)]/~; } ret_buf } else { - let read_result = read((*self).sock, 0u); + let read_result = read((*(self.data)).sock, 0u); if read_result.is_err() { let err_data = read_result.get_err(); log(debug, #fmt("ERROR sock_buf as io::reader.read err %? %?", err_data.err_name, err_data.err_msg)); - [] + []/~ } else { let new_chunk = result::unwrap(read_result); - (*self).buf += new_chunk; + (*(self.data)).buf += new_chunk; self.read_bytes(amt) } } @@ -803,7 +804,7 @@ impl tcp_socket_buf of io::reader for @tcp_socket_buf { self.read_bytes(1u)[0] as int } fn unread_byte(amt: int) { - vec::unshift((*self).buf, amt as u8); + vec::unshift((*(self.data)).buf, amt as u8); } fn eof() -> bool { false // noop @@ -822,12 +823,9 @@ Implementation of `io::reader` iface for a buffered `net::tcp::tcp_socket` "] impl tcp_socket_buf of io::writer for @tcp_socket_buf { fn write(data: [const u8]/&) unsafe { - let socket_data_ptr = ptr::addr_of(**((*self).sock)); - let write_buf_vec = vec::unpack_const_slice(data) {|ptr, len| - [ uv::ll::buf_init(ptr as *u8, len) ] - }; - let write_buf_vec_ptr = ptr::addr_of(write_buf_vec); - let w_result = write_common_impl(socket_data_ptr, write_buf_vec_ptr); + let socket_data_ptr = ptr::addr_of(*((*(self.data)).sock).socket_data); + let w_result = write_common_impl(socket_data_ptr, + vec::slice(data, 0, vec::len(data))); if w_result.is_err() { let err_data = w_result.get_err(); log(debug, #fmt("ERROR sock_buf as io::writer.writer err: %? %?", @@ -1233,7 +1231,7 @@ type tcp_socket_data = { type tcp_buffered_socket_data = { sock: tcp_socket, - mut buf: [u8] + mut buf: [u8]/~ }; //#[cfg(test)] diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 7921a84175a..5f75523e2b6 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -765,7 +765,7 @@ unsafe fn ip4_addr(ip: str, port: int) unsafe fn ip6_addr(ip: str, port: int) -> sockaddr_in6 { let mut addr_vec = str::bytes(ip); - addr_vec += [0u8]; // add null terminator + addr_vec += [0u8]/~; // add null terminator let addr_vec_ptr = vec::unsafe::to_ptr(addr_vec); let ip_back = str::from_bytes(addr_vec); log(debug, #fmt("vec val: '%s' length: %u", @@ -775,8 +775,8 @@ unsafe fn ip6_addr(ip: str, port: int) } unsafe fn ip4_name(src: &sockaddr_in) -> str { // ipv4 addr max size: 15 + 1 trailing null byte - let dst: [u8] = [0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, - 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8]; + let dst: [u8]/~ = [0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, + 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8]/~; let size = 16 as libc::size_t; vec::as_buf(dst) {|dst_buf| rustrt::rust_uv_ip4_name(src as *sockaddr_in, @@ -792,12 +792,12 @@ unsafe fn ip4_name(src: &sockaddr_in) -> str { } unsafe fn ip6_name(src: &sockaddr_in6) -> str { // ipv6 addr max size: 45 + 1 trailing null byte - let dst: [u8] = [0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, - 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, - 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, - 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, - 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, - 0u8,0u8,0u8,0u8,0u8,0u8]; + let dst: [u8]/~ = [0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, + 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, + 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, + 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, + 0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8, + 0u8,0u8,0u8,0u8,0u8,0u8]/~; let size = 46 as libc::size_t; vec::as_buf(dst) {|dst_buf| let result = rustrt::rust_uv_ip6_name(src as *sockaddr_in6, -- cgit 1.4.1-3-g733a5 From b0747742324e38d3cb8405a844c2711b76c00e2f Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Tue, 26 Jun 2012 16:13:50 -0700 Subject: rename net::ip tests en masse --- src/libstd/net_ip.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 3efca378bc8..ca0c69cb724 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -306,13 +306,13 @@ mod v6 { #[cfg(test)] mod test { #[test] - fn test_ipv4_parse_and_format_ip() { + fn test_ip_ipv4_parse_and_format_ip() { let localhost_str = "127.0.0.1"; assert (format_addr(v4::parse_addr(localhost_str)) == localhost_str) } #[test] - fn test_ipv6_parse_and_format_ip() { + fn test_ip_ipv6_parse_and_format_ip() { let localhost_str = "::1"; let format_result = format_addr(v6::parse_addr(localhost_str)); log(debug, #fmt("results: expected: '%s' actual: '%s'", @@ -320,7 +320,7 @@ mod test { assert format_result == localhost_str; } #[test] - fn test_ipv4_bad_parse() { + fn test_ip_ipv4_bad_parse() { alt v4::try_parse_addr("b4df00d") { result::err(err_info) { log(debug, #fmt("got error as expected %?", err_info)); @@ -332,7 +332,7 @@ mod test { } } #[test] - fn test_ipv6_bad_parse() { + fn test_ip_ipv6_bad_parse() { alt v6::try_parse_addr("::,~2234k;") { result::err(err_info) { log(debug, #fmt("got error as expected %?", err_info)); @@ -344,7 +344,7 @@ mod test { } } #[test] - fn test_get_addr() { + fn test_ip_get_addr() { let localhost_name = "localhost"; let iotask = uv::global_loop::get(); let ga_result = get_addr(localhost_name, iotask); @@ -373,7 +373,7 @@ mod test { assert vec::len(results) > 0; } #[test] - fn test_get_addr_bad_input() { + fn test_ip_get_addr_bad_input() { let localhost_name = "sjkl234m,./sdf"; let iotask = uv::global_loop::get(); let ga_result = get_addr(localhost_name, iotask); -- cgit 1.4.1-3-g733a5 From cfcd3e683bd5ce1259231be7f43085832cd9e3b9 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Wed, 27 Jun 2012 15:28:03 -0700 Subject: std/rt: cleanup and adding sockaddr_in6 mapping for win32 --- src/libstd/net_ip.rs | 1 + src/libstd/net_tcp.rs | 3 ++- src/libstd/uv_ll.rs | 37 ++++++++++++++++++++----------------- src/rt/rust_uv.cpp | 12 +++++++----- 4 files changed, 30 insertions(+), 23 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index ca0c69cb724..3bd95a718a4 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -332,6 +332,7 @@ mod test { } } #[test] + #[ignore(target_os="win32")] fn test_ip_ipv6_bad_parse() { alt v6::try_parse_addr("::,~2234k;") { result::err(err_info) { diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index c0aa3394e77..feec985b236 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -823,7 +823,8 @@ Implementation of `io::reader` iface for a buffered `net::tcp::tcp_socket` "] impl tcp_socket_buf of io::writer for @tcp_socket_buf { fn write(data: [const u8]/&) unsafe { - let socket_data_ptr = ptr::addr_of(*((*(self.data)).sock).socket_data); + let socket_data_ptr = + ptr::addr_of(*((*(self.data)).sock).socket_data); let w_result = write_common_impl(socket_data_ptr, vec::slice(data, 0, vec::len(data))); if w_result.is_err() { diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 5f75523e2b6..0d6043be36b 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -225,10 +225,18 @@ type sockaddr_in = { // unix size: 28 .. FIXME #1645 // stuck with 32 becuse of rust padding structs? +#[cfg(unix)] type sockaddr_in6 = { a0: *u8, a1: *u8, a2: *u8, a3: *u8 }; +#[cfg(windows)] +type sockaddr_in6 = { + a0: *u8, a1: *u8, + a2: *u8, a3: *u8, + a4: *u8, a5: *u8, + a6: *u8, a7: *u8 +}; // unix size: 28 .. FIXME #1645 // stuck with 32 becuse of rust padding structs? @@ -753,25 +761,17 @@ unsafe fn buf_init(++input: *u8, len: uint) -> uv_buf_t { } unsafe fn ip4_addr(ip: str, port: int) -> sockaddr_in { - let mut addr_vec = str::bytes(ip); - vec::push(addr_vec, 0u8); // add null terminator - let addr_vec_ptr = vec::unsafe::to_ptr(addr_vec); - let ip_back = str::from_bytes(addr_vec); - log(debug, #fmt("vec val: '%s' length: %u", - ip_back, vec::len(addr_vec))); - ret rustrt::rust_uv_ip4_addr(addr_vec_ptr, - port as libc::c_int); + str::as_c_str(ip) {|ip_buf| + rustrt::rust_uv_ip4_addr(ip_buf as *u8, + port as libc::c_int) + } } unsafe fn ip6_addr(ip: str, port: int) -> sockaddr_in6 { - let mut addr_vec = str::bytes(ip); - addr_vec += [0u8]/~; // add null terminator - let addr_vec_ptr = vec::unsafe::to_ptr(addr_vec); - let ip_back = str::from_bytes(addr_vec); - log(debug, #fmt("vec val: '%s' length: %u", - ip_back, vec::len(addr_vec))); - ret rustrt::rust_uv_ip6_addr(addr_vec_ptr, + str::as_c_str(ip) {|ip_buf| + rustrt::rust_uv_ip6_addr(ip_buf as *u8, port as libc::c_int); + } } unsafe fn ip4_name(src: &sockaddr_in) -> str { // ipv4 addr max size: 15 + 1 trailing null byte @@ -800,7 +800,10 @@ unsafe fn ip6_name(src: &sockaddr_in6) -> str { 0u8,0u8,0u8,0u8,0u8,0u8]/~; let size = 46 as libc::size_t; vec::as_buf(dst) {|dst_buf| - let result = rustrt::rust_uv_ip6_name(src as *sockaddr_in6, + let src_unsafe_ptr = src as *sockaddr_in6; + log(debug, #fmt("val of src *sockaddr_in6: %? sockaddr_in6: %?", + src_unsafe_ptr, src)); + let result = rustrt::rust_uv_ip6_name(src_unsafe_ptr, dst_buf, size); alt result { 0i32 { @@ -1536,7 +1539,7 @@ mod test { let native_handle_size = rustrt::rust_uv_helper_sockaddr_in6_size(); let rust_handle_size = sys::size_of::(); - let output = #fmt("sockaddr_in -- native: %u rust: %u", + let output = #fmt("sockaddr_in6 -- native: %u rust: %u", native_handle_size as uint, rust_handle_size); log(debug, output); // FIXME #1645 .. rust appears to pad structs to the nearest byte..? diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index e47af4e10a3..9124172af1a 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -459,7 +459,7 @@ extern "C" struct sockaddr_in rust_uv_ip4_addr(const char* ip, int port) { rust_task* task = rust_get_current_task(); LOG(task, stdlib, "before creating addr_ptr.. ip %s" \ - "port %d", ip, port); + " port %d\n", ip, port); struct sockaddr_in addr = uv_ip4_addr(ip, port); LOG(task, stdlib, "after creating .. port: %d", addr.sin_port); return addr; @@ -468,9 +468,8 @@ extern "C" struct sockaddr_in6 rust_uv_ip6_addr(const char* ip, int port) { rust_task* task = rust_get_current_task(); LOG(task, stdlib, "before creating addr_ptr.. ip %s" \ - "port %d", ip, port); - struct sockaddr_in6 addr = uv_ip6_addr(ip, port); - return addr; + " port %d\n", ip, port); + return uv_ip6_addr(ip, port); } extern "C" int rust_uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size) { @@ -478,7 +477,10 @@ rust_uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size) { } extern "C" int rust_uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size) { - return uv_ip6_name(src, dst, size); + int result = uv_ip6_name(src, dst, size); + printf("rust_uv_ip6_name: src ptr: %lu dst result: '%s'\n", + (unsigned long int)src, dst); + return result; } extern "C" uintptr_t* -- cgit 1.4.1-3-g733a5 From a696193bab3f09e7c95173e10d1e98d18b8f1bb8 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Wed, 27 Jun 2012 15:45:46 -0700 Subject: std: cleanups, post-rebase --- src/libstd/net_tcp.rs | 1 + src/libstd/uv_ll.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index feec985b236..76d5ccd3fcc 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -6,6 +6,7 @@ import ip = net_ip; import uv::iotask; import uv::iotask::iotask; import comm::methods; +import future::future; import future_spawn = future::spawn; // FIXME #1935 // should be able to, but can't atm, replace w/ result::{result, extensions}; diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 0d6043be36b..a58ffca1dd1 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -770,7 +770,7 @@ unsafe fn ip6_addr(ip: str, port: int) -> sockaddr_in6 { str::as_c_str(ip) {|ip_buf| rustrt::rust_uv_ip6_addr(ip_buf as *u8, - port as libc::c_int); + port as libc::c_int) } } unsafe fn ip4_name(src: &sockaddr_in) -> str { -- cgit 1.4.1-3-g733a5 From 087c4244b11f9aeb829640caa661b2dc2d976f0a Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Wed, 27 Jun 2012 15:59:04 -0700 Subject: std: adding some basic docs for net::ip::get_addr --- src/libstd/net_ip.rs | 139 ++++++++++++++++++++++++++++----------------------- 1 file changed, 76 insertions(+), 63 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 3bd95a718a4..70003a22482 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -72,76 +72,26 @@ fn format_addr(ip: ip_addr) -> str { } } -type get_addr_data = { - output_ch: comm::chan> -}; - -crust fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int, - res: *addrinfo) unsafe { - log(debug, "in get_addr_cb"); - let handle_data = get_data_for_req(handle) as - *get_addr_data; - if status == 0i32 { - if res != (ptr::null::()) { - let mut out_vec = []/~; - log(debug, #fmt("initial addrinfo: %?", res)); - let mut curr_addr = res; - loop { - let new_ip_addr = if ll::is_ipv4_addrinfo(curr_addr) { - ipv4(copy(( - *ll::addrinfo_as_sockaddr_in(curr_addr)))) - } - else if ll::is_ipv6_addrinfo(curr_addr) { - ipv6(copy(( - *ll::addrinfo_as_sockaddr_in6(curr_addr)))) - } - else { - log(debug, "curr_addr is not of family AF_INET or "+ - "AF_INET6. Error."); - (*handle_data).output_ch.send( - result::err(get_addr_unknown_error)); - break; - }; - out_vec += [new_ip_addr]/~; - - let next_addr = ll::get_next_addrinfo(curr_addr); - if next_addr == ptr::null::() as *addrinfo { - log(debug, "null next_addr encountered. no mas"); - break; - } - else { - curr_addr = next_addr; - log(debug, #fmt("next_addr addrinfo: %?", curr_addr)); - } - } - log(debug, #fmt("successful process addrinfo result, len: %?", - vec::len(out_vec))); - (*handle_data).output_ch.send(result::ok(out_vec)); - } - else { - log(debug, "addrinfo pointer is NULL"); - (*handle_data).output_ch.send( - result::err(get_addr_unknown_error)); - } - } - else { - log(debug, "status != 0 error in get_addr_cb"); - (*handle_data).output_ch.send( - result::err(get_addr_unknown_error)); - } - if res != (ptr::null::()) { - uv_freeaddrinfo(res); - } - log(debug, "leaving get_addr_cb"); -} - #[doc=" +Represents errors returned from `net::ip::get_addr()` "] enum ip_get_addr_err { get_addr_unknown_error } #[doc=" +Attempts name resolution on the provided `node` string + +# Arguments + +* `node` - a string representing some host address +* `iotask` - a `uv::iotask` used to interact with the underlying event loop + +# Returns + +A `result<[ip_addr]/~, ip_get_addr_err>` instance that will contain +a vector of `ip_addr` results, in the case of success, or an error +object in the case of failure "] fn get_addr(++node: str, iotask: iotask) -> result::result<[ip_addr]/~, ip_get_addr_err> unsafe { @@ -303,6 +253,69 @@ mod v6 { } } +type get_addr_data = { + output_ch: comm::chan> +}; + +crust fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int, + res: *addrinfo) unsafe { + log(debug, "in get_addr_cb"); + let handle_data = get_data_for_req(handle) as + *get_addr_data; + if status == 0i32 { + if res != (ptr::null::()) { + let mut out_vec = []/~; + log(debug, #fmt("initial addrinfo: %?", res)); + let mut curr_addr = res; + loop { + let new_ip_addr = if ll::is_ipv4_addrinfo(curr_addr) { + ipv4(copy(( + *ll::addrinfo_as_sockaddr_in(curr_addr)))) + } + else if ll::is_ipv6_addrinfo(curr_addr) { + ipv6(copy(( + *ll::addrinfo_as_sockaddr_in6(curr_addr)))) + } + else { + log(debug, "curr_addr is not of family AF_INET or "+ + "AF_INET6. Error."); + (*handle_data).output_ch.send( + result::err(get_addr_unknown_error)); + break; + }; + out_vec += [new_ip_addr]/~; + + let next_addr = ll::get_next_addrinfo(curr_addr); + if next_addr == ptr::null::() as *addrinfo { + log(debug, "null next_addr encountered. no mas"); + break; + } + else { + curr_addr = next_addr; + log(debug, #fmt("next_addr addrinfo: %?", curr_addr)); + } + } + log(debug, #fmt("successful process addrinfo result, len: %?", + vec::len(out_vec))); + (*handle_data).output_ch.send(result::ok(out_vec)); + } + else { + log(debug, "addrinfo pointer is NULL"); + (*handle_data).output_ch.send( + result::err(get_addr_unknown_error)); + } + } + else { + log(debug, "status != 0 error in get_addr_cb"); + (*handle_data).output_ch.send( + result::err(get_addr_unknown_error)); + } + if res != (ptr::null::()) { + uv_freeaddrinfo(res); + } + log(debug, "leaving get_addr_cb"); +} + #[cfg(test)] mod test { #[test] -- cgit 1.4.1-3-g733a5 From a3c933e0a0201c9f70ed961f1a8f8f7f9d08e50e Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Fri, 29 Jun 2012 07:06:32 -0700 Subject: std: uv::ll fixes for 32bit linux --- src/libstd/uv_ll.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++--------- src/rt/rust_uv.cpp | 2 -- 2 files changed, 54 insertions(+), 13 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index a58ffca1dd1..4c0f3835f32 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -225,12 +225,12 @@ type sockaddr_in = { // unix size: 28 .. FIXME #1645 // stuck with 32 becuse of rust padding structs? -#[cfg(unix)] +#[cfg(target_arch="x86_64")] type sockaddr_in6 = { a0: *u8, a1: *u8, a2: *u8, a3: *u8 }; -#[cfg(windows)] +#[cfg(target_arch="x86")] type sockaddr_in6 = { a0: *u8, a1: *u8, a2: *u8, a3: *u8, @@ -240,16 +240,59 @@ type sockaddr_in6 = { // unix size: 28 .. FIXME #1645 // stuck with 32 becuse of rust padding structs? -type addr_in = { - a0: *u8, a1: *u8, - a2: *u8, a3: *u8 -}; +type addr_in = addr_in_impl::addr_in; +#[cfg(unix)] +mod addr_in_impl { + #[cfg(target_arch="x86_64")] + type addr_in = { + a0: *u8, a1: *u8, + a2: *u8, a3: *u8 + }; + #[cfg(target_arch="x86")] + type addr_in = { + a0: *u8, a1: *u8, + a2: *u8, a3: *u8, + a4: *u8, a5: *u8, + a6: *u8, a7: *u8, + }; +} +#[cfg(windows)] +mod addr_in_impl { + type addr_in = { + a0: *u8, a1: *u8, + a2: *u8, a3: *u8 + }; +} -// unix size: 48 -type addrinfo = { - a00: *u8, a01: *u8, a02: *u8, a03: *u8, - a04: *u8, a05: *u8 -}; +// unix size: 48, 32bit: 32 +type addrinfo = addrinfo_impl::addrinfo; +#[cfg(target_os="linux")] +mod addrinfo_impl { + #[cfg(target_arch="x86_64")] + type addrinfo = { + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8 + }; + #[cfg(target_arch="x86")] + type addrinfo = { + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8, a06: *u8, a07: *u8 + }; +} +#[cfg(target_os="macos")] +mod addrinfo_impl { + type addrinfo = { + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8 + }; +} +#[cfg(windows)] +mod addrinfo_impl { + type addrinfo = { + a00: *u8, a01: *u8, a02: *u8, a03: *u8, + a04: *u8, a05: *u8 + }; +} // unix size: 72 type uv_getaddrinfo_t = { diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 9124172af1a..706e8ff4380 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -478,8 +478,6 @@ rust_uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size) { extern "C" int rust_uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size) { int result = uv_ip6_name(src, dst, size); - printf("rust_uv_ip6_name: src ptr: %lu dst result: '%s'\n", - (unsigned long int)src, dst); return result; } -- cgit 1.4.1-3-g733a5 From 483aee8dc4a2d83fd97be0d3dfe866c45e59d521 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Fri, 29 Jun 2012 15:35:47 -0700 Subject: Ignore various uv tests that fail --- src/libstd/net_ip.rs | 2 ++ src/libstd/uv_ll.rs | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 70003a22482..f63354d2ea6 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -358,6 +358,7 @@ mod test { } } #[test] + #[ignore(reason = "valgrind says it's leaky")] fn test_ip_get_addr() { let localhost_name = "localhost"; let iotask = uv::global_loop::get(); @@ -387,6 +388,7 @@ mod test { assert vec::len(results) > 0; } #[test] + #[ignore(reason = "valgrind says it's leaky")] fn test_ip_get_addr_bad_input() { let localhost_name = "sjkl234m,./sdf"; let iotask = uv::global_loop::get(); diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 4c0f3835f32..1e4fe0f75b3 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -1592,7 +1592,7 @@ mod test { assert (4u+native_handle_size as uint) == rust_handle_size; } #[test] - #[ignore(cfg(target_os = "freebsd"))] + #[ignore(reason = "questionable size calculations")] fn test_uv_ll_struct_size_addr_in() { let native_handle_size = rustrt::rust_uv_helper_addr_in_size(); @@ -1630,6 +1630,7 @@ mod test { #[test] #[ignore(cfg(target_os = "freebsd"))] + #[ignore(cfg(target_os = "win32"))] fn test_uv_ll_struct_size_uv_getaddrinfo_t() { let native_handle_size = rustrt::rust_uv_helper_uv_getaddrinfo_t_size(); @@ -1641,6 +1642,8 @@ mod test { } #[test] #[ignore(cfg(target_os = "freebsd"))] + #[ignore(cfg(target_os = "macos"))] + #[ignore(cfg(target_os = "win32"))] fn test_uv_ll_struct_size_addrinfo() { let native_handle_size = rustrt::rust_uv_helper_addrinfo_size(); -- cgit 1.4.1-3-g733a5