PageRenderTime 57ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/native_client_sdk/src/libraries/nacl_io/socket/socket_node.cc

https://gitlab.com/jonnialva90/iridium-browser
C++ | 529 lines | 406 code | 94 blank | 29 comment | 90 complexity | 27718a0bbb19a25a725d8bd525af86ed MD5 | raw file
  1. // Copyright 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "nacl_io/socket/socket_node.h"
  5. #include "nacl_io/ossocket.h"
  6. #ifdef PROVIDES_SOCKET_API
  7. #include <errno.h>
  8. #include <string.h>
  9. #include "nacl_io/filesystem.h"
  10. #include "nacl_io/kernel_handle.h"
  11. #include "nacl_io/pepper_interface.h"
  12. #include "ppapi/c/pp_resource.h"
  13. #include "ppapi/c/ppb_net_address.h"
  14. namespace nacl_io {
  15. SocketNode::SocketNode(Filesystem* filesystem)
  16. : StreamNode(filesystem),
  17. socket_resource_(0),
  18. local_addr_(0),
  19. remote_addr_(0),
  20. socket_flags_(0),
  21. last_errno_(0),
  22. keep_alive_(false) {
  23. memset(&linger_, 0, sizeof(linger_));
  24. SetType(S_IFSOCK);
  25. }
  26. SocketNode::SocketNode(Filesystem* filesystem, PP_Resource socket)
  27. : StreamNode(filesystem),
  28. socket_resource_(socket),
  29. local_addr_(0),
  30. remote_addr_(0),
  31. socket_flags_(0),
  32. last_errno_(0),
  33. keep_alive_(false) {
  34. memset(&linger_, 0, sizeof(linger_));
  35. SetType(S_IFSOCK);
  36. filesystem_->ppapi()->AddRefResource(socket_resource_);
  37. }
  38. void SocketNode::Destroy() {
  39. if (socket_resource_)
  40. filesystem_->ppapi()->ReleaseResource(socket_resource_);
  41. if (local_addr_)
  42. filesystem_->ppapi()->ReleaseResource(local_addr_);
  43. if (remote_addr_)
  44. filesystem_->ppapi()->ReleaseResource(remote_addr_);
  45. socket_resource_ = 0;
  46. local_addr_ = 0;
  47. remote_addr_ = 0;
  48. }
  49. // Assume that |addr| and |out_addr| are non-NULL.
  50. Error SocketNode::MMap(void* addr,
  51. size_t length,
  52. int prot,
  53. int flags,
  54. size_t offset,
  55. void** out_addr) {
  56. return EACCES;
  57. }
  58. // Normal read/write operations on a Socket are equivalent to
  59. // send/recv with a flag value of 0.
  60. Error SocketNode::Read(const HandleAttr& attr,
  61. void* buf,
  62. size_t count,
  63. int* out_bytes) {
  64. return Recv(attr, buf, count, 0, out_bytes);
  65. }
  66. Error SocketNode::Write(const HandleAttr& attr,
  67. const void* buf,
  68. size_t count,
  69. int* out_bytes) {
  70. return Send(attr, buf, count, 0, out_bytes);
  71. }
  72. NetAddressInterface* SocketNode::NetInterface() {
  73. if (filesystem_->ppapi() == NULL)
  74. return NULL;
  75. return filesystem_->ppapi()->GetNetAddressInterface();
  76. }
  77. TCPSocketInterface* SocketNode::TCPInterface() {
  78. if (filesystem_->ppapi() == NULL)
  79. return NULL;
  80. return filesystem_->ppapi()->GetTCPSocketInterface();
  81. }
  82. UDPSocketInterface* SocketNode::UDPInterface() {
  83. if (filesystem_->ppapi() == NULL)
  84. return NULL;
  85. return filesystem_->ppapi()->GetUDPSocketInterface();
  86. }
  87. PP_Resource SocketNode::SockAddrToResource(const struct sockaddr* addr,
  88. socklen_t len) {
  89. if (NULL == addr)
  90. return 0;
  91. if (AF_INET == addr->sa_family) {
  92. const sockaddr_in* sin = reinterpret_cast<const sockaddr_in*>(addr);
  93. return SockAddrInToResource(sin, len);
  94. }
  95. if (AF_INET6 == addr->sa_family) {
  96. const sockaddr_in6* sin = reinterpret_cast<const sockaddr_in6*>(addr);
  97. return SockAddrIn6ToResource(sin, len);
  98. }
  99. return 0;
  100. }
  101. PP_Resource SocketNode::SockAddrInToResource(const sockaddr_in* sin,
  102. socklen_t len) {
  103. if (len != sizeof(sockaddr_in))
  104. return 0;
  105. PP_NetAddress_IPv4 addr4;
  106. memset(&addr4, 0, sizeof(addr4));
  107. addr4.port = sin->sin_port;
  108. memcpy(addr4.addr, &sin->sin_addr, sizeof(addr4.addr));
  109. return filesystem_->ppapi()->GetNetAddressInterface()->CreateFromIPv4Address(
  110. filesystem_->ppapi()->GetInstance(), &addr4);
  111. }
  112. PP_Resource SocketNode::SockAddrIn6ToResource(const sockaddr_in6* sin,
  113. socklen_t len) {
  114. if (len != sizeof(sockaddr_in6))
  115. return 0;
  116. PP_NetAddress_IPv6 addr6;
  117. memset(&addr6, 0, sizeof(addr6));
  118. addr6.port = sin->sin6_port;
  119. memcpy(addr6.addr, &sin->sin6_addr, sizeof(addr6.addr));
  120. return filesystem_->ppapi()->GetNetAddressInterface()->CreateFromIPv6Address(
  121. filesystem_->ppapi()->GetInstance(), &addr6);
  122. }
  123. socklen_t SocketNode::ResourceToSockAddr(PP_Resource addr,
  124. socklen_t len,
  125. struct sockaddr* out_addr) {
  126. if (0 == addr)
  127. return 0;
  128. PP_NetAddress_IPv4 ipv4;
  129. PP_NetAddress_IPv6 ipv6;
  130. if (PP_TRUE == NetInterface()->DescribeAsIPv4Address(addr, &ipv4)) {
  131. sockaddr_in addr4;
  132. addr4.sin_family = AF_INET;
  133. addr4.sin_port = ipv4.port;
  134. memcpy(&addr4.sin_addr, ipv4.addr, sizeof(ipv4.addr));
  135. memcpy(out_addr, &addr4,
  136. std::min(len, static_cast<socklen_t>(sizeof(addr4))));
  137. // Returns required size not copied size like getpeername/getsockname.
  138. return sizeof(addr4);
  139. }
  140. if (PP_TRUE == NetInterface()->DescribeAsIPv6Address(addr, &ipv6)) {
  141. sockaddr_in6 addr6;
  142. addr6.sin6_family = AF_INET6;
  143. addr6.sin6_port = ipv6.port;
  144. memcpy(&addr6.sin6_addr, ipv6.addr, sizeof(ipv6.addr));
  145. memcpy(out_addr, &addr6,
  146. std::min(len, static_cast<socklen_t>(sizeof(addr6))));
  147. // Returns required size not copied size like getpeername/getsockname.
  148. return sizeof(addr6);
  149. }
  150. return 0;
  151. }
  152. bool SocketNode::IsEquivalentAddress(PP_Resource addr1, PP_Resource addr2) {
  153. if (addr1 == addr2)
  154. return true;
  155. char data1[sizeof(sockaddr_in6)];
  156. char data2[sizeof(sockaddr_in6)];
  157. sockaddr* saddr1 = reinterpret_cast<sockaddr*>(data1);
  158. sockaddr* saddr2 = reinterpret_cast<sockaddr*>(data2);
  159. socklen_t len1 = ResourceToSockAddr(addr1, sizeof(data1), saddr1);
  160. socklen_t len2 = ResourceToSockAddr(addr2, sizeof(data2), saddr2);
  161. if (len1 != len2)
  162. return false;
  163. return memcmp(saddr1, saddr2, len1) == 0;
  164. }
  165. Error SocketNode::Accept(const HandleAttr& attr,
  166. PP_Resource* new_sock,
  167. struct sockaddr* addr,
  168. socklen_t* len) {
  169. return ENOSYS;
  170. }
  171. Error SocketNode::Connect(const HandleAttr& attr,
  172. const struct sockaddr* addr,
  173. socklen_t len) {
  174. if (len < 1)
  175. return EINVAL;
  176. if (NULL == addr)
  177. return EFAULT;
  178. return EOPNOTSUPP;
  179. }
  180. Error SocketNode::Listen(int backlog) {
  181. return EOPNOTSUPP;
  182. }
  183. Error SocketNode::GetSockOpt(int lvl,
  184. int optname,
  185. void* optval,
  186. socklen_t* len) {
  187. if (lvl != SOL_SOCKET)
  188. return ENOPROTOOPT;
  189. AUTO_LOCK(node_lock_);
  190. int value = 0;
  191. socklen_t value_len = 0;
  192. void* value_ptr = NULL;
  193. switch (optname) {
  194. case SO_REUSEADDR:
  195. // SO_REUSEADDR is effectively always on since we can't
  196. // disable it with PPAPI sockets.
  197. value = 1;
  198. value_ptr = &value;
  199. value_len = sizeof(value);
  200. break;
  201. case SO_LINGER:
  202. value_ptr = &linger_;
  203. value_len = sizeof(linger_);
  204. break;
  205. case SO_KEEPALIVE:
  206. value = keep_alive_;
  207. value_ptr = &value;
  208. value_len = sizeof(value);
  209. break;
  210. case SO_ERROR:
  211. value_ptr = &last_errno_;
  212. value_len = sizeof(last_errno_);
  213. last_errno_ = 0;
  214. break;
  215. default:
  216. return ENOPROTOOPT;
  217. }
  218. int copy_bytes = std::min(value_len, *len);
  219. memcpy(optval, value_ptr, copy_bytes);
  220. *len = value_len;
  221. return 0;
  222. }
  223. Error SocketNode::SetSockOpt(int lvl,
  224. int optname,
  225. const void* optval,
  226. socklen_t len) {
  227. AUTO_LOCK(node_lock_);
  228. switch (lvl) {
  229. case SOL_SOCKET: {
  230. return SetSockOptSocket(optname, optval, len);
  231. }
  232. case IPPROTO_TCP: {
  233. return SetSockOptTCP(optname, optval, len);
  234. }
  235. case IPPROTO_IP: {
  236. return SetSockOptIP(optname, optval, len);
  237. }
  238. case IPPROTO_IPV6: {
  239. return SetSockOptIPV6(optname, optval, len);
  240. }
  241. default: { break; }
  242. }
  243. return ENOPROTOOPT;
  244. }
  245. Error SocketNode::SetSockOptSocket(int optname,
  246. const void* optval,
  247. socklen_t len) {
  248. size_t buflen = static_cast<size_t>(len);
  249. switch (optname) {
  250. case SO_REUSEADDR: {
  251. // SO_REUSEADDR is effectivly always on since we can't
  252. // disable it with PPAPI sockets. Just return success
  253. // here regardless.
  254. if (buflen < sizeof(int))
  255. return EINVAL;
  256. return 0;
  257. }
  258. case SO_LINGER: {
  259. // Not supported by the PPAPI interface but we preserve
  260. // the settings and pretend to support it.
  261. if (buflen < sizeof(struct linger))
  262. return EINVAL;
  263. struct linger new_linger = *static_cast<const linger*>(optval);
  264. // Don't allow setting linger to be enabled until we
  265. // implement the required synchronous shutdown()/close().
  266. // TODO(sbc): remove this after http://crbug.com/312401
  267. // gets fixed.
  268. if (new_linger.l_onoff != 0)
  269. return EINVAL;
  270. linger_ = new_linger;
  271. return 0;
  272. }
  273. case SO_KEEPALIVE: {
  274. // Not supported by the PPAPI interface but we preserve
  275. // the flag and pretend to support it.
  276. if (buflen < sizeof(int))
  277. return EINVAL;
  278. int value = *static_cast<const int*>(optval);
  279. keep_alive_ = value != 0;
  280. return 0;
  281. }
  282. }
  283. return ENOPROTOOPT;
  284. }
  285. Error SocketNode::SetSockOptTCP(int optname,
  286. const void* optval,
  287. socklen_t len) {
  288. return ENOPROTOOPT;
  289. }
  290. Error SocketNode::SetSockOptIP(int optname, const void* optval, socklen_t len) {
  291. return ENOPROTOOPT;
  292. }
  293. Error SocketNode::SetSockOptIPV6(int optname,
  294. const void* optval,
  295. socklen_t len) {
  296. return ENOPROTOOPT;
  297. }
  298. Error SocketNode::Bind(const struct sockaddr* addr, socklen_t len) {
  299. return EINVAL;
  300. }
  301. Error SocketNode::Recv(const HandleAttr& attr,
  302. void* buf,
  303. size_t len,
  304. int flags,
  305. int* out_len) {
  306. return RecvFrom(attr, buf, len, flags, NULL, 0, out_len);
  307. }
  308. Error SocketNode::RecvFrom(const HandleAttr& attr,
  309. void* buf,
  310. size_t len,
  311. int flags,
  312. struct sockaddr* src_addr,
  313. socklen_t* addrlen,
  314. int* out_len) {
  315. PP_Resource addr = 0;
  316. Error err = RecvHelper(attr, buf, len, flags, &addr, out_len);
  317. if (0 == err && 0 != addr) {
  318. if (src_addr)
  319. *addrlen = ResourceToSockAddr(addr, *addrlen, src_addr);
  320. filesystem_->ppapi()->ReleaseResource(addr);
  321. }
  322. return err;
  323. }
  324. Error SocketNode::RecvHelper(const HandleAttr& attr,
  325. void* buf,
  326. size_t len,
  327. int flags,
  328. PP_Resource* addr,
  329. int* out_len) {
  330. if (0 == socket_resource_)
  331. return EBADF;
  332. if (TestStreamFlags(SSF_RECV_ENDOFSTREAM)) {
  333. *out_len = 0;
  334. return 0;
  335. }
  336. int ms = read_timeout_;
  337. if ((flags & MSG_DONTWAIT) || !attr.IsBlocking())
  338. ms = 0;
  339. // TODO(bradnelson) BUG=295177
  340. // For UDP we should support filtering packets when using connect
  341. EventListenerLock wait(GetEventEmitter());
  342. Error err = wait.WaitOnEvent(POLLIN, ms);
  343. // Timeout is treated as a would block for sockets.
  344. if (ETIMEDOUT == err)
  345. return EWOULDBLOCK;
  346. if (err)
  347. return err;
  348. err = Recv_Locked(buf, len, addr, out_len);
  349. // We must have read from then inputbuffer, so Q up some receive work.
  350. if ((err == 0) && *out_len)
  351. QueueInput();
  352. return err;
  353. }
  354. Error SocketNode::Send(const HandleAttr& attr,
  355. const void* buf,
  356. size_t len,
  357. int flags,
  358. int* out_len) {
  359. return SendHelper(attr, buf, len, flags, remote_addr_, out_len);
  360. }
  361. Error SocketNode::SendTo(const HandleAttr& attr,
  362. const void* buf,
  363. size_t len,
  364. int flags,
  365. const struct sockaddr* dest_addr,
  366. socklen_t addrlen,
  367. int* out_len) {
  368. if ((NULL == dest_addr) && (0 == remote_addr_))
  369. return EDESTADDRREQ;
  370. PP_Resource addr = SockAddrToResource(dest_addr, addrlen);
  371. if (0 == addr)
  372. return EINVAL;
  373. Error err = SendHelper(attr, buf, len, flags, addr, out_len);
  374. filesystem_->ppapi()->ReleaseResource(addr);
  375. return err;
  376. }
  377. Error SocketNode::SendHelper(const HandleAttr& attr,
  378. const void* buf,
  379. size_t len,
  380. int flags,
  381. PP_Resource addr,
  382. int* out_len) {
  383. if (0 == socket_resource_)
  384. return EBADF;
  385. if (0 == addr)
  386. return ENOTCONN;
  387. int ms = write_timeout_;
  388. if ((flags & MSG_DONTWAIT) || !attr.IsBlocking())
  389. ms = 0;
  390. EventListenerLock wait(GetEventEmitter());
  391. Error err = wait.WaitOnEvent(POLLOUT, ms);
  392. // Timeout is treated as a would block for sockets.
  393. if (ETIMEDOUT == err)
  394. return EWOULDBLOCK;
  395. if (err)
  396. return err;
  397. err = Send_Locked(buf, len, addr, out_len);
  398. // We must have added to the output buffer, so Q up some transmit work.
  399. if ((err == 0) && *out_len)
  400. QueueOutput();
  401. return err;
  402. }
  403. void SocketNode::SetError_Locked(int pp_error_num) {
  404. SetStreamFlags(SSF_ERROR | SSF_CLOSED);
  405. ClearStreamFlags(SSF_CAN_SEND | SSF_CAN_RECV);
  406. last_errno_ = PPERROR_TO_ERRNO(pp_error_num);
  407. }
  408. Error SocketNode::Shutdown(int how) {
  409. return EOPNOTSUPP;
  410. }
  411. Error SocketNode::GetPeerName(struct sockaddr* addr, socklen_t* len) {
  412. if (NULL == addr || NULL == len)
  413. return EFAULT;
  414. AUTO_LOCK(node_lock_);
  415. if (remote_addr_ != 0) {
  416. *len = ResourceToSockAddr(remote_addr_, *len, addr);
  417. return 0;
  418. }
  419. return ENOTCONN;
  420. }
  421. Error SocketNode::GetSockName(struct sockaddr* addr, socklen_t* len) {
  422. if (NULL == addr || NULL == len)
  423. return EFAULT;
  424. AUTO_LOCK(node_lock_);
  425. if (local_addr_ == 0) {
  426. // getsockname succeeds even if the socket is not bound. In this case,
  427. // just return address 0, port 0.
  428. memset(addr, 0, *len);
  429. return 0;
  430. }
  431. *len = ResourceToSockAddr(local_addr_, *len, addr);
  432. return 0;
  433. }
  434. } // namespace nacl_io
  435. #endif // PROVIDES_SOCKET_API