10
10
11
11
use libc:: { size_t, ssize_t, c_int, c_void, c_uint} ;
12
12
use libc;
13
- use std:: intrinsics;
14
13
use std:: mem;
15
14
use std:: ptr;
16
15
use std:: rt:: rtio;
@@ -849,18 +848,18 @@ pub struct SocketWatcher {
849
848
handle : * mut uvll:: uv_poll_t ,
850
849
socket : uvll:: uv_os_socket_t ,
851
850
home : HomeHandle ,
852
- close_on_drop : bool ,
853
- }
854
851
855
- #[ cfg( windows) ]
856
- pub fn net_buflen ( buf : & [ u8 ] ) -> i32 {
857
- buf. len ( ) as i32
852
+ // See above for what these are
853
+ refcount : Refcount ,
854
+ read_access : AccessTimeout ,
855
+ write_access : AccessTimeout ,
856
+
858
857
}
859
858
859
+ #[ cfg( windows) ]
860
+ type Buflen = i32 ;
860
861
#[ cfg( not( windows) ) ]
861
- pub fn net_buflen ( buf : & [ u8 ] ) -> u64 {
862
- buf. len ( ) as u64
863
- }
862
+ type Buflen = u64 ;
864
863
865
864
#[ cfg( windows) ]
866
865
fn last_error ( ) -> IoError {
@@ -909,7 +908,9 @@ fn make_nonblocking(socket: c_int) -> Option<IoError> {
909
908
}
910
909
911
910
impl SocketWatcher {
912
- pub fn new ( io : & mut UvIoFactory , socket : uvll:: uv_os_socket_t , close_on_drop : bool )
911
+ // NOTE It is an error to have multiple SocketWatchers for the same socket,
912
+ // see documentation for uv_poll_s in uv.h.
913
+ pub fn new ( io : & mut UvIoFactory , socket : uvll:: uv_os_socket_t )
913
914
-> Result < SocketWatcher , IoError >
914
915
{
915
916
let handle = unsafe { uvll:: malloc_handle ( uvll:: UV_POLL ) } ;
@@ -918,7 +919,9 @@ impl SocketWatcher {
918
919
handle : handle,
919
920
home : io. make_handle ( ) ,
920
921
socket : socket,
921
- close_on_drop : close_on_drop
922
+ refcount : Refcount :: new ( ) ,
923
+ read_access : AccessTimeout :: new ( ) ,
924
+ write_access : AccessTimeout :: new ( ) ,
922
925
} ;
923
926
924
927
// Make socket non-blocking - required for libuv
@@ -941,7 +944,7 @@ impl UvHandle<uvll::uv_poll_t> for SocketWatcher {
941
944
impl Drop for SocketWatcher {
942
945
fn drop ( & mut self ) {
943
946
let _m = self . fire_homing_missile ( ) ;
944
- if self . close_on_drop {
947
+ if self . refcount . decrement ( ) {
945
948
self . close ( ) ;
946
949
}
947
950
}
@@ -959,10 +962,12 @@ impl rtio::RtioCustomSocket for SocketWatcher {
959
962
task : Option < BlockedTask > ,
960
963
buf : & ' b [ u8 ] ,
961
964
result : Option < Result < ssize_t , IoError > > ,
962
- socket : Option < uvll:: uv_os_socket_t > ,
965
+ socket : uvll:: uv_os_socket_t ,
963
966
addr : * mut libc:: sockaddr_storage
964
967
}
965
- let _m = self . fire_homing_missile ( ) ;
968
+ let loop_ = self . uv_loop ( ) ;
969
+ let m = self . fire_homing_missile ( ) ;
970
+ let _guard = try!( self . read_access . grant ( m) ) ;
966
971
let a = match unsafe {
967
972
uvll:: uv_poll_start ( self . handle , uvll:: UV_READABLE as c_int , recv_cb)
968
973
} {
@@ -971,11 +976,12 @@ impl rtio::RtioCustomSocket for SocketWatcher {
971
976
task : None ,
972
977
buf : buf,
973
978
result : None ,
974
- socket : Some ( self . socket ) ,
979
+ socket : self . socket ,
975
980
addr : addr,
976
981
} ;
977
- wait_until_woken_after ( & mut cx. task , & self . uv_loop ( ) , || {
978
- unsafe { uvll:: set_data_for_uv_handle ( self . handle , & mut cx) }
982
+ let handle = self . handle ;
983
+ wait_until_woken_after ( & mut cx. task , & loop_, || {
984
+ unsafe { uvll:: set_data_for_uv_handle ( handle, & mut cx) }
979
985
} ) ;
980
986
cx. result . unwrap ( ) . map ( |n| n as uint )
981
987
}
@@ -985,43 +991,38 @@ impl rtio::RtioCustomSocket for SocketWatcher {
985
991
986
992
extern fn recv_cb ( handle : * mut uvll:: uv_poll_t , status : c_int , events : c_int ) {
987
993
assert ! ( ( events & ( uvll:: UV_READABLE as c_int) ) != 0 ) ;
988
- let cx: & mut Ctx = unsafe {
989
- intrinsics :: transmute ( uvll:: get_data_for_uv_handle ( handle) )
994
+ let cx = unsafe {
995
+ uvll:: get_data_for_uv_handle ( handle) as * mut Ctx
990
996
} ;
991
997
992
998
if status < 0 {
993
- cx. result = Some ( Err ( uv_error_to_io_error ( UvError ( status) ) ) ) ;
994
- wakeup ( & mut cx. task ) ;
999
+ unsafe {
1000
+ ( * cx) . result = Some ( Err ( uv_error_to_io_error ( UvError ( status) ) ) ) ;
1001
+ wakeup ( & mut ( * cx) . task ) ;
1002
+ }
995
1003
return ;
996
1004
}
997
1005
998
1006
unsafe {
999
1007
assert_eq ! ( uvll:: uv_poll_stop( handle) , 0 )
1000
1008
}
1001
1009
1002
- let mut caddrlen = unsafe {
1003
- intrinsics:: size_of :: < libc:: sockaddr_storage > ( )
1004
- } as libc:: socklen_t ;
1005
- let len = match cx. socket {
1006
- Some ( sock) => unsafe {
1007
- libc:: recvfrom ( sock,
1008
- cx. buf . as_ptr ( ) as * mut c_void ,
1009
- net_buflen ( cx. buf ) ,
1010
- 0 ,
1011
- cx. addr as * mut libc:: sockaddr ,
1012
- & mut caddrlen)
1013
- } ,
1014
- _ => -1
1010
+ let mut caddrlen = mem:: size_of :: < libc:: sockaddr_storage > ( ) as libc:: socklen_t ;
1011
+ let len = unsafe {
1012
+ libc:: recvfrom ( ( * cx) . socket , ( * cx) . buf . as_ptr ( ) as * mut c_void ,
1013
+ ( * cx) . buf . len ( ) as Buflen , 0 ,
1014
+ ( * cx) . addr as * mut libc:: sockaddr , & mut caddrlen)
1015
1015
} ;
1016
- if len == -1 {
1017
- cx. result = Some ( Err ( last_error ( ) ) ) ;
1018
- wakeup ( & mut cx. task ) ;
1019
- return ;
1020
- }
1021
1016
1022
- cx. result = Some ( Ok ( len as ssize_t ) ) ;
1017
+ unsafe {
1018
+ ( * cx) . result = if len == -1 {
1019
+ Some ( Err ( last_error ( ) ) )
1020
+ } else {
1021
+ Some ( Ok ( len as ssize_t ) )
1022
+ } ;
1023
1023
1024
- wakeup ( & mut cx. task ) ;
1024
+ wakeup ( & mut ( * cx) . task ) ;
1025
+ }
1025
1026
}
1026
1027
}
1027
1028
@@ -1032,11 +1033,13 @@ impl rtio::RtioCustomSocket for SocketWatcher {
1032
1033
task : Option < BlockedTask > ,
1033
1034
buf : & ' b [ u8 ] ,
1034
1035
result : Option < Result < uint , IoError > > ,
1035
- socket : Option < uvll:: uv_os_socket_t > ,
1036
+ socket : uvll:: uv_os_socket_t ,
1036
1037
addr : * const libc:: sockaddr ,
1037
1038
len : uint
1038
1039
}
1039
- let _m = self . fire_homing_missile ( ) ;
1040
+ let loop_ = self . uv_loop ( ) ;
1041
+ let m = self . fire_homing_missile ( ) ;
1042
+ let _guard = try!( self . write_access . grant ( m) ) ;
1040
1043
1041
1044
let a = match unsafe {
1042
1045
uvll:: uv_poll_start ( self . handle , uvll:: UV_WRITABLE as c_int , send_cb)
@@ -1046,12 +1049,13 @@ impl rtio::RtioCustomSocket for SocketWatcher {
1046
1049
task : None ,
1047
1050
buf : buf,
1048
1051
result : None ,
1049
- socket : Some ( self . socket ) ,
1052
+ socket : self . socket ,
1050
1053
addr : dst,
1051
1054
len : slen
1052
1055
} ;
1053
- wait_until_woken_after ( & mut cx. task , & self . uv_loop ( ) , || {
1054
- unsafe { uvll:: set_data_for_uv_handle ( self . handle , & mut cx) }
1056
+ let handle = self . handle ;
1057
+ wait_until_woken_after ( & mut cx. task , & loop_, || {
1058
+ unsafe { uvll:: set_data_for_uv_handle ( handle, & mut cx) }
1055
1059
} ) ;
1056
1060
cx. result . unwrap ( )
1057
1061
}
@@ -1061,42 +1065,49 @@ impl rtio::RtioCustomSocket for SocketWatcher {
1061
1065
1062
1066
extern fn send_cb ( handle : * mut uvll:: uv_poll_t , status : c_int , events : c_int ) {
1063
1067
assert ! ( ( events & ( uvll:: UV_WRITABLE as c_int) ) != 0 ) ;
1064
- let cx: & mut Ctx = unsafe {
1065
- intrinsics :: transmute ( uvll:: get_data_for_uv_handle ( handle) )
1068
+ let cx = unsafe {
1069
+ uvll:: get_data_for_uv_handle ( handle) as * mut Ctx
1066
1070
} ;
1067
1071
if status < 0 {
1068
- cx. result = Some ( Err ( uv_error_to_io_error ( UvError ( status) ) ) ) ;
1069
- wakeup ( & mut cx. task ) ;
1072
+ unsafe {
1073
+ ( * cx) . result = Some ( Err ( uv_error_to_io_error ( UvError ( status) ) ) ) ;
1074
+ wakeup ( & mut ( * cx) . task ) ;
1075
+ }
1070
1076
return ;
1071
1077
}
1072
1078
1073
1079
unsafe {
1074
1080
assert_eq ! ( uvll:: uv_poll_stop( handle) , 0 )
1075
1081
}
1076
1082
1077
- let len = match cx. socket {
1078
- Some ( sock) => {
1079
- unsafe {
1080
- libc:: sendto ( sock,
1081
- cx. buf . as_ptr ( ) as * const c_void ,
1082
- net_buflen ( cx. buf ) ,
1083
- 0 ,
1084
- cx. addr ,
1085
- cx. len as libc:: socklen_t )
1086
- }
1087
- } ,
1088
- _ => -1
1083
+ let len = unsafe {
1084
+ libc:: sendto ( ( * cx) . socket , ( * cx) . buf . as_ptr ( ) as * const c_void ,
1085
+ ( * cx) . buf . len ( ) as Buflen , 0 ,
1086
+ ( * cx) . addr , ( * cx) . len as libc:: socklen_t )
1089
1087
} ;
1090
1088
1091
- cx. result = if len < 0 {
1092
- Some ( Err ( last_error ( ) ) )
1093
- } else {
1094
- Some ( Ok ( len as uint ) )
1095
- } ;
1089
+ unsafe {
1090
+ ( * cx) . result = if len < 0 {
1091
+ Some ( Err ( last_error ( ) ) )
1092
+ } else {
1093
+ Some ( Ok ( len as uint ) )
1094
+ } ;
1096
1095
1097
- wakeup ( & mut cx. task ) ;
1096
+ wakeup ( & mut ( * cx) . task ) ;
1097
+ }
1098
1098
}
1099
1099
}
1100
+
1101
+ fn clone ( & self ) -> Box < rtio:: RtioCustomSocket + Send > {
1102
+ box SocketWatcher {
1103
+ handle : self . handle ,
1104
+ socket : self . socket ,
1105
+ home : self . home . clone ( ) ,
1106
+ refcount : self . refcount . clone ( ) ,
1107
+ write_access : self . write_access . clone ( ) ,
1108
+ read_access : self . read_access . clone ( ) ,
1109
+ } as Box < rtio:: RtioCustomSocket + Send >
1110
+ }
1100
1111
}
1101
1112
1102
1113
0 commit comments