socket.rs 5.6 KB

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