Skip to content

uv: implement a way to get client's ip/port. #3815

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions src/libstd/net_ip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ use addrinfo = uv::ll::addrinfo;
use uv_getaddrinfo_t = uv::ll::uv_getaddrinfo_t;
use uv_ip4_addr = uv::ll::ip4_addr;
use uv_ip4_name = uv::ll::ip4_name;
use uv_ip4_port = uv::ll::ip4_port;
use uv_ip6_addr = uv::ll::ip6_addr;
use uv_ip6_name = uv::ll::ip6_name;
use uv_ip6_port = uv::ll::ip6_port;
use uv_getaddrinfo = uv::ll::getaddrinfo;
use uv_freeaddrinfo = uv::ll::freeaddrinfo;
use create_uv_getaddrinfo_t = uv::ll::getaddrinfo_t;
Expand All @@ -33,11 +35,11 @@ type ParseAddrErr = {
};

/**
* Convert a `ip_addr` to a str
* Convert a `IpAddr` to a str
*
* # Arguments
*
* * ip - a `std::net::ip::ip_addr`
* * ip - a `std::net::ip::IpAddr`
*/
pub fn format_addr(ip: &IpAddr) -> ~str {
match *ip {
Expand All @@ -58,6 +60,23 @@ pub fn format_addr(ip: &IpAddr) -> ~str {
}
}

/**
* Get the associated port
*
* # Arguments
* * ip - a `std::net::ip::IpAddr`
*/
pub fn get_port(ip: &IpAddr) -> uint {
match *ip {
Ipv4(ref addr) => unsafe {
uv_ip4_port(addr)
},
Ipv6(ref addr) => unsafe {
uv_ip6_port(addr)
}
}
}

/// Represents errors returned from `net::ip::get_addr()`
enum IpGetAddrErr {
GetAddrUnknownError
Expand Down
86 changes: 85 additions & 1 deletion src/libstd/net_tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ pub fn connect(input_ip: ip::IpAddr, port: uint,
stream_handle_ptr: stream_handle_ptr,
connect_req: uv::ll::connect_t(),
write_req: uv::ll::write_t(),
ipv6: match input_ip {
ip::Ipv4(_) => { false }
ip::Ipv6(_) => { true }
},
iotask: iotask
};
let socket_data_ptr = ptr::addr_of(&(*socket_data));
Expand Down Expand Up @@ -475,6 +479,7 @@ pub fn accept(new_conn: TcpNewConnection)
stream_handle_ptr : stream_handle_ptr,
connect_req : uv::ll::connect_t(),
write_req : uv::ll::write_t(),
ipv6: (*server_data_ptr).ipv6,
iotask : iotask
};
let client_socket_data_ptr = ptr::addr_of(&(*client_socket_data));
Expand Down Expand Up @@ -590,6 +595,10 @@ fn listen_common(host_ip: ip::IpAddr, port: uint, backlog: uint,
kill_ch: kill_ch,
on_connect_cb: move on_connect_cb,
iotask: iotask,
ipv6: match host_ip {
ip::Ipv4(_) => { false }
ip::Ipv6(_) => { true }
},
mut active: true
};
let server_data_ptr = ptr::addr_of(&server_data);
Expand Down Expand Up @@ -746,6 +755,21 @@ impl TcpSocket {
-> future::Future<result::Result<(), TcpErrData>> {
write_future(&self, raw_write_data)
}
pub fn get_peer_addr() -> ip::IpAddr {
unsafe {
if self.socket_data.ipv6 {
let addr = uv::ll::ip6_addr("", 0);
uv::ll::tcp_getpeername6(self.socket_data.stream_handle_ptr,
ptr::addr_of(&addr));
ip::Ipv6(move addr)
} else {
let addr = uv::ll::ip4_addr("", 0);
uv::ll::tcp_getpeername(self.socket_data.stream_handle_ptr,
ptr::addr_of(&addr));
ip::Ipv4(move addr)
}
}
}
}

/// Implementation of `io::reader` trait for a buffered `net::tcp::tcp_socket`
Expand Down Expand Up @@ -1003,6 +1027,7 @@ type TcpListenFcData = {
kill_ch: comm::Chan<Option<TcpErrData>>,
on_connect_cb: fn~(*uv::ll::uv_tcp_t),
iotask: IoTask,
ipv6: bool,
mut active: bool
};

Expand Down Expand Up @@ -1201,6 +1226,7 @@ type TcpSocketData = {
stream_handle_ptr: *uv::ll::uv_tcp_t,
connect_req: uv::ll::uv_connect_t,
write_req: uv::ll::uv_write_t,
ipv6: bool,
iotask: IoTask
};

Expand All @@ -1223,6 +1249,10 @@ mod test {
impl_gl_tcp_ipv4_server_and_client();
}
#[test]
fn test_gl_tcp_get_peer_addr() unsafe {
impl_gl_tcp_ipv4_get_peer_addr();
}
#[test]
fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe {
impl_gl_tcp_ipv4_client_error_connection_refused();
}
Expand All @@ -1249,6 +1279,11 @@ mod test {
}
#[test]
#[ignore(cfg(target_os = "linux"))]
fn test_gl_tcp_get_peer_addr() unsafe {
impl_gl_tcp_ipv4_get_peer_addr();
}
#[test]
#[ignore(cfg(target_os = "linux"))]
fn test_gl_tcp_ipv4_client_error_connection_refused() unsafe {
impl_gl_tcp_ipv4_client_error_connection_refused();
}
Expand Down Expand Up @@ -1316,6 +1351,52 @@ mod test {
assert str::contains(actual_req, expected_req);
assert str::contains(actual_resp, expected_resp);
}
fn impl_gl_tcp_ipv4_get_peer_addr() {
let hl_loop = uv::global_loop::get();
let server_ip = ~"127.0.0.1";
let server_port = 8889u;
let expected_resp = ~"pong";

let server_result_po = core::comm::Port::<~str>();
let server_result_ch = core::comm::Chan(&server_result_po);

let cont_po = core::comm::Port::<()>();
let cont_ch = core::comm::Chan(&cont_po);
// server
do task::spawn_sched(task::ManualThreads(1u)) {
let actual_req = do 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);
};
core::comm::recv(cont_po);
// client
log(debug, ~"server started, firing up client..");
do core::comm::listen |client_ch| {
let server_ip_addr = ip::v4::parse_addr(server_ip);
let iotask = uv::global_loop::get();
let connect_result = connect(move server_ip_addr, server_port,
iotask);

let sock = result::unwrap(move connect_result);

// This is what we are actually testing!
assert net::ip::format_addr(&sock.get_peer_addr()) == ~"127.0.0.1";
assert net::ip::get_port(&sock.get_peer_addr()) == 8889;

// Fulfill the protocol the test server expects
let resp_bytes = str::to_bytes(~"ping");
tcp_write_single(&sock, resp_bytes);
let read_result = sock.read(0u);
client_ch.send(str::from_bytes(read_result.get()));
};
}
fn impl_gl_tcp_ipv4_client_error_connection_refused() {
let hl_loop = uv::global_loop::get();
let server_ip = ~"127.0.0.1";
Expand Down Expand Up @@ -1511,8 +1592,11 @@ mod test {
~"SERVER/WORKER: send on cont ch");
cont_ch.send(());
let sock = result::unwrap(move accept_result);
let peer_addr = sock.get_peer_addr();
log(debug, ~"SERVER: successfully accepted"+
~"connection!");
fmt!(" connection from %s:%u",
ip::format_addr(&peer_addr),
ip::get_port(&peer_addr)));
let received_req_bytes = read(&sock, 0u);
match move received_req_bytes {
result::Ok(move data) => {
Expand Down
22 changes: 22 additions & 0 deletions src/libstd/uv_ll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,8 @@ extern mod rustrt {
-> libc::c_int;
fn rust_uv_ip6_name(src: *sockaddr_in6, dst: *u8, size: libc::size_t)
-> libc::c_int;
fn rust_uv_ip4_port(src: *sockaddr_in) -> libc::c_uint;
fn rust_uv_ip6_port(src: *sockaddr_in6) -> libc::c_uint;
// FIXME ref #2064
fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t,
tcp_handle_ptr: *uv_tcp_t,
Expand All @@ -606,6 +608,10 @@ extern mod rustrt {
// FIXME ref #2064
fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t,
++addr: *sockaddr_in6) -> libc::c_int;
fn rust_uv_tcp_getpeername(tcp_handle_ptr: *uv_tcp_t,
++name: *sockaddr_in) -> libc::c_int;
fn rust_uv_tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t,
++name: *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)
Expand Down Expand Up @@ -736,6 +742,16 @@ pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t,
addr_ptr);
}

pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t,
name: *sockaddr_in) -> libc::c_int {
return rustrt::rust_uv_tcp_getpeername(tcp_handle_ptr, name);
}

pub unsafe fn tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t,
name: *sockaddr_in6) ->libc::c_int {
return rustrt::rust_uv_tcp_getpeername6(tcp_handle_ptr, name);
}

pub unsafe fn listen<T>(stream: *T, backlog: libc::c_int,
cb: *u8) -> libc::c_int {
return rustrt::rust_uv_listen(stream as *libc::c_void, backlog, cb);
Expand Down Expand Up @@ -857,6 +873,12 @@ pub unsafe fn ip6_name(src: &sockaddr_in6) -> ~str {
}
}
}
pub unsafe fn ip4_port(src: &sockaddr_in) -> uint {
rustrt::rust_uv_ip4_port(to_unsafe_ptr(src)) as uint
}
pub unsafe fn ip6_port(src: &sockaddr_in6) -> uint {
rustrt::rust_uv_ip6_port(to_unsafe_ptr(src)) as uint
}

pub unsafe fn timer_init(loop_ptr: *libc::c_void,
timer_ptr: *uv_timer_t) -> libc::c_int {
Expand Down
22 changes: 22 additions & 0 deletions src/rt/rust_uv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,20 @@ rust_uv_tcp_bind6
return uv_tcp_bind6(tcp_server, addr);
}

extern "C" int
rust_uv_tcp_getpeername
(uv_tcp_t* handle, sockaddr_in* name) {
int namelen = sizeof(sockaddr_in);
return uv_tcp_getpeername(handle, (sockaddr*)name, &namelen);
}

extern "C" int
rust_uv_tcp_getpeername6
(uv_tcp_t* handle, sockaddr_in6* name) {
int namelen = sizeof(sockaddr_in6);
return uv_tcp_getpeername(handle, (sockaddr*)name, &namelen);
}

extern "C" int
rust_uv_listen(uv_stream_t* stream, int backlog,
uv_connection_cb cb) {
Expand Down Expand Up @@ -480,6 +494,14 @@ rust_uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size) {
int result = uv_ip6_name(src, dst, size);
return result;
}
extern "C" unsigned int
rust_uv_ip4_port(struct sockaddr_in* src) {
return ntohs(src->sin_port);
}
extern "C" unsigned int
rust_uv_ip6_port(struct sockaddr_in6* src) {
return ntohs(src->sin6_port);
}

extern "C" uintptr_t*
rust_uv_get_kernel_global_chan_ptr() {
Expand Down