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