OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 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 |
| 5 |
| 6 #include "nacl_io/ossocket.h" |
| 7 #ifdef PROVIDES_SOCKET_API |
| 8 |
| 9 #include <errno.h> |
| 10 #include <string.h> |
| 11 #include <algorithm> |
| 12 |
| 13 #include "nacl_io/mount.h" |
| 14 #include "nacl_io/mount_node_socket.h" |
| 15 #include "nacl_io/mount_node_udp.h" |
| 16 #include "nacl_io/pepper_interface.h" |
| 17 |
| 18 namespace nacl_io { |
| 19 |
| 20 MountNodeUDP::MountNodeUDP(Mount* mount) : MountNodeSocket(mount) {} |
| 21 |
| 22 |
| 23 UDPSocketInterface* MountNodeUDP::UDPSocket() { |
| 24 if (mount_->ppapi() == NULL) |
| 25 return NULL; |
| 26 |
| 27 return mount_->ppapi()->GetUDPSocketInterface(); |
| 28 } |
| 29 |
| 30 Error MountNodeUDP::Init(int flags) { |
| 31 if (UDPSocket() == NULL) |
| 32 return EACCES; |
| 33 |
| 34 socket_resource_ = UDPSocket()->Create(mount_->ppapi()->GetInstance()); |
| 35 if (0 == socket_resource_) |
| 36 return EACCES; |
| 37 |
| 38 return 0; |
| 39 } |
| 40 |
| 41 Error MountNodeUDP::Bind(const struct sockaddr* addr, socklen_t len) { |
| 42 if (0 == socket_resource_) |
| 43 return EBADF; |
| 44 |
| 45 /* Only bind once. */ |
| 46 if (local_addr_ != 0) |
| 47 return EINVAL; |
| 48 |
| 49 PP_Resource out_addr = SockAddrToResource(addr, len); |
| 50 if (0 == out_addr) |
| 51 return EINVAL; |
| 52 |
| 53 int err = UDPSocket()->Bind(socket_resource_, |
| 54 out_addr, |
| 55 PP_BlockUntilComplete()); |
| 56 if (err != 0) { |
| 57 mount_->ppapi()->ReleaseResource(out_addr); |
| 58 return PPErrorToErrno(err); |
| 59 } |
| 60 |
| 61 local_addr_ = out_addr; |
| 62 return 0; |
| 63 } |
| 64 |
| 65 Error MountNodeUDP::Connect(const struct sockaddr* addr, socklen_t len) { |
| 66 if (0 == socket_resource_) |
| 67 return EBADF; |
| 68 |
| 69 /* Connect for UDP is the default dest, it's legal to change it. */ |
| 70 if (remote_addr_ != 0) { |
| 71 mount_->ppapi()->ReleaseResource(remote_addr_); |
| 72 remote_addr_ = 0; |
| 73 } |
| 74 |
| 75 remote_addr_ = SockAddrToResource(addr, len); |
| 76 if (0 == remote_addr_) |
| 77 return EINVAL; |
| 78 |
| 79 return 0; |
| 80 } |
| 81 |
| 82 Error MountNodeUDP::RecvFromHelper(void* buf, |
| 83 size_t len, |
| 84 int flags, |
| 85 PP_Resource* out_addr, |
| 86 int* out_len) { |
| 87 if (0 == socket_resource_) |
| 88 return EBADF; |
| 89 |
| 90 int capped_len = static_cast<int32_t>(std::min(len, MAX_SOCK_TRANSFER)); |
| 91 int err = UDPSocket()->RecvFrom(socket_resource_, |
| 92 static_cast<char*>(buf), |
| 93 capped_len, |
| 94 out_addr, |
| 95 PP_BlockUntilComplete()); |
| 96 if (err < 0) |
| 97 return PPErrorToErrno(err); |
| 98 |
| 99 *out_len = err; |
| 100 return 0; |
| 101 } |
| 102 |
| 103 Error MountNodeUDP::Recv(void* buf, size_t len, int flags, int* out_len) { |
| 104 while (1) { |
| 105 int local_len = 0; |
| 106 PP_Resource addr = 0; |
| 107 |
| 108 int err = RecvFromHelper(buf, len, flags, &addr, &local_len); |
| 109 if (err < 0) |
| 110 return PPErrorToErrno(err); |
| 111 |
| 112 /* If "connected" then only receive packets from the given remote. */ |
| 113 bool same = IsEquivalentAddress(addr, remote_addr_); |
| 114 mount_->ppapi()->ReleaseResource(addr); |
| 115 |
| 116 if (remote_addr_ != 0 && same) |
| 117 continue; |
| 118 |
| 119 *out_len = local_len; |
| 120 return 0; |
| 121 } |
| 122 } |
| 123 |
| 124 Error MountNodeUDP::RecvFrom(void* buf, |
| 125 size_t len, |
| 126 int flags, |
| 127 struct sockaddr* src_addr, |
| 128 socklen_t* addrlen, |
| 129 int* out_len) { |
| 130 PP_Resource addr = 0; |
| 131 int err = RecvFromHelper(buf, len, flags, &addr, out_len); |
| 132 if (err < 0) |
| 133 return PPErrorToErrno(err); |
| 134 |
| 135 if (src_addr) |
| 136 *addrlen = ResourceToSockAddr(addr, *addrlen, src_addr); |
| 137 |
| 138 mount_->ppapi()->ReleaseResource(addr); |
| 139 return 0; |
| 140 } |
| 141 |
| 142 |
| 143 Error MountNodeUDP::SendToHelper(const void* buf, |
| 144 size_t len, |
| 145 int flags, |
| 146 PP_Resource addr, |
| 147 int* out_len) { |
| 148 if (0 == socket_resource_) |
| 149 return EBADF; |
| 150 |
| 151 if (0 == addr) |
| 152 return ENOTCONN; |
| 153 |
| 154 int capped_len = static_cast<int32_t>(std::min(len, MAX_SOCK_TRANSFER)); |
| 155 int err = UDPSocket()->SendTo(socket_resource_, |
| 156 static_cast<const char*>(buf), |
| 157 capped_len, |
| 158 addr, |
| 159 PP_BlockUntilComplete()); |
| 160 if (err < 0) |
| 161 return PPErrorToErrno(err); |
| 162 |
| 163 *out_len = err; |
| 164 return 0; |
| 165 } |
| 166 |
| 167 Error MountNodeUDP::Send(const void* buf, size_t len, int flags, int* out_len) { |
| 168 return SendToHelper(buf, len, flags, remote_addr_, out_len); |
| 169 } |
| 170 |
| 171 Error MountNodeUDP::SendTo(const void* buf, |
| 172 size_t len, |
| 173 int flags, |
| 174 const struct sockaddr* dest_addr, |
| 175 socklen_t addrlen, |
| 176 int* out_len) { |
| 177 PP_Resource out_addr = SockAddrToResource(dest_addr, addrlen); |
| 178 if (0 == out_addr) |
| 179 return EINVAL; |
| 180 |
| 181 Error err = SendToHelper(buf, len, flags, out_addr, out_len); |
| 182 mount_->ppapi()->ReleaseResource(out_addr); |
| 183 return err; |
| 184 } |
| 185 |
| 186 } // namespace nacl_io |
| 187 |
| 188 #endif // PROVIDES_SOCKET_API |
OLD | NEW |