socket.rs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. use core::{mem, ptr, slice};
  2. use syscall::flag::*;
  3. use syscall::{self, Result};
  4. use super::super::types::*;
  5. use super::super::{errno, Pal, PalSocket};
  6. use super::{e, Sys};
  7. use header::netinet_in::{in_addr_t, in_port_t, sockaddr_in};
  8. use header::sys_socket::constants::*;
  9. use header::sys_socket::{sockaddr, socklen_t};
  10. macro_rules! bind_or_connect {
  11. (bind $path:expr) => {
  12. concat!("/", $path)
  13. };
  14. (connect $path:expr) => {
  15. $path
  16. };
  17. ($mode:ident into, $socket:expr, $address:expr, $address_len:expr) => {{
  18. let fd = bind_or_connect!($mode copy, $socket, $address, $address_len);
  19. let result = syscall::dup2(fd, $socket as usize, &[]);
  20. let _ = syscall::close(fd);
  21. if (e(result) as c_int) < 0 {
  22. return -1;
  23. }
  24. 0
  25. }};
  26. ($mode:ident copy, $socket:expr, $address:expr, $address_len:expr) => {{
  27. if (*$address).sa_family as c_int != AF_INET {
  28. errno = syscall::EAFNOSUPPORT;
  29. return -1;
  30. }
  31. if ($address_len as usize) < mem::size_of::<sockaddr>() {
  32. errno = syscall::EINVAL;
  33. return -1;
  34. }
  35. let data = &*($address as *const sockaddr_in);
  36. let addr = data.sin_addr.s_addr;
  37. let port = in_port_t::from_be(data.sin_port);
  38. let path = format!(
  39. bind_or_connect!($mode "{}.{}.{}.{}:{}"),
  40. addr >> 8 * 3,
  41. addr >> 8 * 2 & 0xFF,
  42. addr >> 8 & 0xFF,
  43. addr & 0xFF,
  44. port
  45. );
  46. // Duplicate the socket, and then duplicate the copy back to the original fd
  47. let fd = e(syscall::dup($socket as usize, path.as_bytes()));
  48. if (fd as c_int) < 0 {
  49. return -1;
  50. }
  51. fd
  52. }};
  53. }
  54. unsafe fn inner_get_name(
  55. local: bool,
  56. socket: c_int,
  57. address: *mut sockaddr,
  58. address_len: *mut socklen_t,
  59. ) -> Result<usize> {
  60. // 32 should probably be large enough.
  61. // Format: tcp:remote/local
  62. // and since we only yet support IPv4 (I think)...
  63. let mut buf = [0; 32];
  64. let len = syscall::fpath(socket as usize, &mut buf)?;
  65. let buf = &buf[..len];
  66. assert!(&buf[..4] == b"tcp:" || &buf[..4] == b"udp:");
  67. let buf = &buf[4..];
  68. let mut parts = buf.split(|c| *c == b'/');
  69. if local {
  70. // Skip the remote part
  71. parts.next();
  72. }
  73. let part = parts.next().expect("Invalid reply from netstack");
  74. println!("path: {}", ::core::str::from_utf8_unchecked(&part));
  75. let data = slice::from_raw_parts_mut(
  76. &mut (*address).data as *mut _ as *mut u8,
  77. (*address).data.len(),
  78. );
  79. let len = data.len().min(part.len());
  80. data[..len].copy_from_slice(&part[..len]);
  81. *address_len = len as socklen_t;
  82. Ok(0)
  83. }
  84. impl PalSocket for Sys {
  85. unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
  86. let stream = e(syscall::dup(socket as usize, b"listen")) as c_int;
  87. if stream < 0 {
  88. return -1;
  89. }
  90. if address != ptr::null_mut()
  91. && address_len != ptr::null_mut()
  92. && Self::getpeername(stream, address, address_len) < 0
  93. {
  94. return -1;
  95. }
  96. stream
  97. }
  98. unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
  99. bind_or_connect!(bind into, socket, address, address_len)
  100. }
  101. unsafe fn connect(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
  102. bind_or_connect!(connect into, socket, address, address_len)
  103. }
  104. unsafe fn getpeername(
  105. socket: c_int,
  106. address: *mut sockaddr,
  107. address_len: *mut socklen_t,
  108. ) -> c_int {
  109. e(inner_get_name(false, socket, address, address_len)) as c_int
  110. }
  111. unsafe fn getsockname(
  112. socket: c_int,
  113. address: *mut sockaddr,
  114. address_len: *mut socklen_t,
  115. ) -> c_int {
  116. e(inner_get_name(true, socket, address, address_len)) as c_int
  117. }
  118. unsafe fn recvfrom(
  119. socket: c_int,
  120. buf: *mut c_void,
  121. len: size_t,
  122. flags: c_int,
  123. address: *mut sockaddr,
  124. address_len: *mut socklen_t,
  125. ) -> ssize_t {
  126. if flags != 0 {
  127. errno = syscall::EOPNOTSUPP;
  128. return -1;
  129. }
  130. if address == ptr::null_mut() || address_len == ptr::null_mut() {
  131. Self::read(socket, slice::from_raw_parts_mut(buf as *mut u8, len))
  132. } else {
  133. let fd = e(syscall::dup(socket as usize, b"listen"));
  134. if fd == !0 {
  135. return -1;
  136. }
  137. if Self::getpeername(fd as c_int, address, address_len) < 0 {
  138. let _ = syscall::close(fd);
  139. return -1;
  140. }
  141. let ret = Self::read(fd as c_int, slice::from_raw_parts_mut(buf as *mut u8, len));
  142. let _ = syscall::close(fd);
  143. ret
  144. }
  145. }
  146. unsafe fn sendto(
  147. socket: c_int,
  148. buf: *const c_void,
  149. len: size_t,
  150. flags: c_int,
  151. dest_addr: *const sockaddr,
  152. dest_len: socklen_t,
  153. ) -> ssize_t {
  154. if flags != 0 {
  155. errno = syscall::EOPNOTSUPP;
  156. return -1;
  157. }
  158. if dest_addr == ptr::null() || dest_len == 0 {
  159. Self::write(socket, slice::from_raw_parts(buf as *const u8, len))
  160. } else {
  161. let fd = bind_or_connect!(connect copy, socket, dest_addr, dest_len);
  162. let ret = Self::write(fd as c_int, slice::from_raw_parts(buf as *const u8, len));
  163. let _ = syscall::close(fd);
  164. ret
  165. }
  166. }
  167. unsafe fn socket(domain: c_int, mut kind: c_int, protocol: c_int) -> c_int {
  168. if domain != AF_INET {
  169. errno = syscall::EAFNOSUPPORT;
  170. return -1;
  171. }
  172. // if protocol != 0 {
  173. // errno = syscall::EPROTONOSUPPORT;
  174. // return -1;
  175. // }
  176. let mut flags = O_RDWR;
  177. if kind & SOCK_NONBLOCK == SOCK_NONBLOCK {
  178. kind &= !SOCK_NONBLOCK;
  179. flags |= O_NONBLOCK;
  180. }
  181. if kind & SOCK_CLOEXEC == SOCK_CLOEXEC {
  182. kind &= !SOCK_CLOEXEC;
  183. flags |= O_CLOEXEC;
  184. }
  185. // The tcp: and udp: schemes allow using no path,
  186. // and later specifying one using `dup`.
  187. match kind {
  188. SOCK_STREAM => e(syscall::open("tcp:", flags)) as c_int,
  189. SOCK_DGRAM => e(syscall::open("udp:", flags)) as c_int,
  190. _ => {
  191. errno = syscall::EPROTOTYPE;
  192. -1
  193. }
  194. }
  195. }
  196. }