Skip to content

Commit ecd42e3

Browse files
olsonjefferybrson
authored andcommitted
---
yaml --- r: 12965 b: refs/heads/master c: 550b34b h: refs/heads/master i: 12963: b0cdb7a v: v3
1 parent b856bd8 commit ecd42e3

File tree

3 files changed

+205
-12
lines changed

3 files changed

+205
-12
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: bc846ce7e3a1333411ceeb9092032e6047c0b61e
2+
refs/heads/master: 550b34b7828622d6eb23e6bfbcc026c8b57e19fa
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
55
refs/heads/try: 2898dcc5d97da9427ac367542382b6239d9c0bbf

trunk/src/libstd/net.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Top-level module for network-related functionality
33
"];
44

5+
import tcp = net_tcp;
6+
export tcp;
57

68
import ip = net_ip;
79
export ip;

trunk/src/libstd/net_tcp.rs

Lines changed: 202 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,212 @@
22
High-level interface to libuv's TCP functionality
33
"];
44

5-
#[cfg(ignore)]
5+
import ip = net_ip;
6+
7+
export tcp_connect_result;
8+
export connect;
9+
10+
enum tcp_socket {
11+
valid_tcp_socket(@tcp_socket_data)
12+
}
13+
14+
enum tcp_connect_result {
15+
tcp_connected(tcp_socket),
16+
tcp_connect_error(uv::ll::uv_err_data)
17+
}
18+
19+
#[doc="
20+
Initiate a client connection over TCP/IP
21+
22+
# Arguments
23+
24+
* ip - The IP address (versions 4 or 6) of the remote host
25+
* port - the unsigned integer of the desired remote host port
26+
27+
# Returns
28+
29+
A `tcp_connect_result` that can be used to determine the connection and,
30+
if successful, send and receive data to/from the remote host
31+
"]
32+
fn connect(input_ip: ip::ip_addr, port: uint) -> tcp_connect_result unsafe {
33+
let result_po = comm::port::<conn_attempt>();
34+
let closed_signal_po = comm::port::<()>();
35+
let conn_data = {
36+
result_ch: comm::chan(result_po),
37+
closed_signal_ch: comm::chan(closed_signal_po)
38+
};
39+
let conn_data_ptr = ptr::addr_of(conn_data);
40+
let socket_data = @{
41+
reader_port: comm::port::<[u8]>(),
42+
stream_handle : uv::ll::tcp_t(),
43+
connect_req : uv::ll::connect_t(),
44+
write_req : uv::ll::write_t()
45+
};
46+
log(debug, #fmt("tcp_connect result_ch %?", conn_data.result_ch));
47+
// get an unsafe representation of our stream_handle_ptr that
48+
// we can send into the interact cb to be handled in libuv..
49+
let socket_data_ptr: *tcp_socket_data =
50+
ptr::addr_of(*socket_data);
51+
// in we go!
52+
let hl_loop = uv::global_loop::get();
53+
log(debug, #fmt("stream_handl_ptr outside interact %?",
54+
ptr::addr_of((*socket_data_ptr).stream_handle)));
55+
uv::hl::interact(hl_loop) {|loop_ptr|
56+
log(debug, "in interact cb for tcp client connect..");
57+
let stream_handle_ptr =
58+
ptr::addr_of((*socket_data_ptr).stream_handle);
59+
log(debug, #fmt("stream_handl_ptr in interact %?",
60+
stream_handle_ptr));
61+
alt uv::ll::tcp_init( loop_ptr, stream_handle_ptr) {
62+
0i32 {
63+
log(debug, "tcp_init successful");
64+
alt input_ip {
65+
ipv4 {
66+
log(debug, "dealing w/ ipv4 connection..");
67+
let tcp_addr = ipv4_ip_addr_to_sockaddr_in(input_ip,
68+
port);
69+
let tcp_addr_ptr = ptr::addr_of(tcp_addr);
70+
let connect_req_ptr =
71+
ptr::addr_of((*socket_data_ptr).connect_req);
72+
alt uv::ll::tcp_connect(
73+
connect_req_ptr,
74+
stream_handle_ptr,
75+
tcp_addr_ptr,
76+
tcp_connect_on_connect_cb) {
77+
0i32 {
78+
log(debug, "tcp_connect successful");
79+
// reusable data that we'll have for the
80+
// duration..
81+
uv::ll::set_data_for_uv_handle(stream_handle_ptr,
82+
socket_data_ptr);
83+
// just so the connect_cb can send the
84+
// outcome..
85+
uv::ll::set_data_for_req(connect_req_ptr,
86+
conn_data_ptr);
87+
log(debug, "leaving tcp_connect interact cb...");
88+
// let tcp_connect_on_connect_cb send on
89+
// the result_ch, now..
90+
}
91+
_ {
92+
// immediate connect failure.. probably a garbage
93+
// ip or somesuch
94+
let err_data = uv::ll::get_last_err_data(loop_ptr);
95+
comm::send((*conn_data_ptr).result_ch,
96+
conn_failure(err_data));
97+
uv::ll::set_data_for_uv_handle(stream_handle_ptr,
98+
conn_data_ptr);
99+
uv::ll::close(stream_handle_ptr, stream_error_close_cb);
100+
}
101+
}
102+
}
103+
}
104+
}
105+
_ {
106+
// failure to create a tcp handle
107+
let err_data = uv::ll::get_last_err_data(loop_ptr);
108+
comm::send((*conn_data_ptr).result_ch,
109+
conn_failure(err_data));
110+
}
111+
}
112+
};
113+
alt comm::recv(result_po) {
114+
conn_success {
115+
log(debug, "tcp::connect - received success on result_po");
116+
tcp_connected(valid_tcp_socket(socket_data))
117+
}
118+
conn_failure(err_data) {
119+
comm::recv(closed_signal_po);
120+
log(debug, "tcp::connect - received failure on result_po");
121+
tcp_connect_error(err_data)
122+
}
123+
}
124+
}
125+
// INTERNAL API
126+
type connect_req_data = {
127+
result_ch: comm::chan<conn_attempt>,
128+
closed_signal_ch: comm::chan<()>
129+
};
130+
131+
crust fn stream_error_close_cb(handle: *uv::ll::uv_tcp_t) unsafe {
132+
let data = uv::ll::get_data_for_uv_handle(handle) as
133+
*connect_req_data;
134+
comm::send((*data).closed_signal_ch, ());
135+
log(debug, #fmt("exiting steam_error_close_cb for %?", handle));
136+
}
137+
138+
crust fn tcp_connect_close_cb(handle: *uv::ll::uv_tcp_t) unsafe {
139+
log(debug, #fmt("closed client tcp handle %?", handle));
140+
}
141+
142+
crust fn tcp_connect_on_connect_cb(connect_req_ptr: *uv::ll::uv_connect_t,
143+
status: libc::c_int) unsafe {
144+
let conn_data_ptr = (uv::ll::get_data_for_req(connect_req_ptr)
145+
as *connect_req_data);
146+
let result_ch = (*conn_data_ptr).result_ch;
147+
log(debug, #fmt("tcp_connect result_ch %?", result_ch));
148+
let tcp_stream_ptr =
149+
uv::ll::get_stream_handle_from_connect_req(connect_req_ptr);
150+
alt status {
151+
0i32 {
152+
log(debug, "successful tcp connection!");
153+
comm::send(result_ch, conn_success);
154+
}
155+
_ {
156+
log(debug, "error in tcp_connect_on_connect_cb");
157+
let loop_ptr = uv::ll::get_loop_for_uv_handle(tcp_stream_ptr);
158+
let err_data = uv::ll::get_last_err_data(loop_ptr);
159+
log(debug, #fmt("err_data %? %?", err_data.err_name,
160+
err_data.err_msg));
161+
comm::send(result_ch, conn_failure(err_data));
162+
uv::ll::set_data_for_uv_handle(tcp_stream_ptr,
163+
conn_data_ptr);
164+
uv::ll::close(tcp_stream_ptr, stream_error_close_cb);
165+
}
166+
}
167+
log(debug, "leaving tcp_connect_on_connect_cb");
168+
}
169+
170+
enum conn_attempt {
171+
conn_success,
172+
conn_failure(uv::ll::uv_err_data)
173+
}
174+
175+
176+
type tcp_socket_data = {
177+
reader_port: comm::port<[u8]>,
178+
stream_handle: uv::ll::uv_tcp_t,
179+
connect_req: uv::ll::uv_connect_t,
180+
write_req: uv::ll::uv_write_t
181+
};
182+
183+
// convert rust ip_addr to libuv's native representation
184+
fn ipv4_ip_addr_to_sockaddr_in(input: ip::ip_addr,
185+
port: uint) -> uv::ll::sockaddr_in unsafe {
186+
uv::ll::ip4_addr(ip::format_addr(input), port as int)
187+
}
188+
189+
#[cfg(test)]
6190
mod test {
7191
#[test]
8192
fn test_gl_tcp_ipv4_request() {
9-
let ip = "127.0.0.1";
193+
let ip_str = "127.0.0.1";
10194
let port = 80u;
11195
let expected_read_msg = "foo";
12196
let actual_write_msg = "bar";
13-
let addr = ipv4::address(ip, port);
197+
let host_ip = ip::v4::parse_addr(ip_str);
14198

15199
let data_po = comm::port::<[u8]>();
16200
let data_ch = comm::chan(data_po);
17201

18-
alt connect(addr) {
19-
tcp_connected(tcp_stream) {
202+
alt connect(host_ip, port) {
203+
tcp_connected(sock) {
204+
log(debug, "successful tcp connect");
205+
/*
20206
let write_data = str::as_buf(actual_write_msg);
21-
alt write(tcp_stream, [write_data]) {
207+
alt write(sock, [write_data]) {
22208
tcp_write_success {
23-
let mut total_read_data: [u8] = []
24-
let reader_po = read_start(tcp_stream);
209+
let mut total_read_data: [u8] = [];
210+
let reader_po = read_start(sock);nyw
25211
loop {
26212
alt comm::recv(reader_po) {
27213
new_read_data(data) {
@@ -36,7 +222,8 @@ mod test {
36222
break;
37223
}
38224
error {
39-
fail "erroring occured during read attempt.. FIXME need info";
225+
fail "erroring occured during read attempt.."
226+
+ "FIXME need info";
40227
}
41228
}
42229
}
@@ -46,9 +233,13 @@ mod test {
46233
fail "error during write attempt.. FIXME need err info";
47234
}
48235
}
236+
*/
49237
}
50-
tcp_connect_error {
51-
fail "error during connection attempt.. FIXME need err info..";
238+
tcp_connect_error(err_data) {
239+
log(debug, "tcp_connect_error received..");
240+
log(debug, #fmt("tcp connect error: %? %?", err_data.err_name,
241+
err_data.err_msg));
242+
assert false;
52243
}
53244
}
54245

0 commit comments

Comments
 (0)