ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / native_client_sdk / src / libraries / nacl_io / socket / socket_node.cc
blob4eaf6ac6db83da826254d5565985d157129d4bf8
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.
5 #include "nacl_io/socket/socket_node.h"
7 #include "nacl_io/ossocket.h"
8 #ifdef PROVIDES_SOCKET_API
10 #include <errno.h>
11 #include <string.h>
13 #include "nacl_io/filesystem.h"
14 #include "nacl_io/kernel_handle.h"
15 #include "nacl_io/pepper_interface.h"
17 #include "ppapi/c/pp_resource.h"
18 #include "ppapi/c/ppb_net_address.h"
20 namespace nacl_io {
22 SocketNode::SocketNode(Filesystem* filesystem)
23 : StreamNode(filesystem),
24 socket_resource_(0),
25 local_addr_(0),
26 remote_addr_(0),
27 socket_flags_(0),
28 last_errno_(0),
29 keep_alive_(false) {
30 memset(&linger_, 0, sizeof(linger_));
31 SetType(S_IFSOCK);
34 SocketNode::SocketNode(Filesystem* filesystem, PP_Resource socket)
35 : StreamNode(filesystem),
36 socket_resource_(socket),
37 local_addr_(0),
38 remote_addr_(0),
39 socket_flags_(0),
40 last_errno_(0),
41 keep_alive_(false) {
42 memset(&linger_, 0, sizeof(linger_));
43 SetType(S_IFSOCK);
44 filesystem_->ppapi()->AddRefResource(socket_resource_);
47 void SocketNode::Destroy() {
48 if (socket_resource_)
49 filesystem_->ppapi()->ReleaseResource(socket_resource_);
50 if (local_addr_)
51 filesystem_->ppapi()->ReleaseResource(local_addr_);
52 if (remote_addr_)
53 filesystem_->ppapi()->ReleaseResource(remote_addr_);
55 socket_resource_ = 0;
56 local_addr_ = 0;
57 remote_addr_ = 0;
60 // Assume that |addr| and |out_addr| are non-NULL.
61 Error SocketNode::MMap(void* addr,
62 size_t length,
63 int prot,
64 int flags,
65 size_t offset,
66 void** out_addr) {
67 return EACCES;
70 // Normal read/write operations on a Socket are equivalent to
71 // send/recv with a flag value of 0.
72 Error SocketNode::Read(const HandleAttr& attr,
73 void* buf,
74 size_t count,
75 int* out_bytes) {
76 return Recv(attr, buf, count, 0, out_bytes);
79 Error SocketNode::Write(const HandleAttr& attr,
80 const void* buf,
81 size_t count,
82 int* out_bytes) {
83 return Send(attr, buf, count, 0, out_bytes);
86 NetAddressInterface* SocketNode::NetInterface() {
87 if (filesystem_->ppapi() == NULL)
88 return NULL;
90 return filesystem_->ppapi()->GetNetAddressInterface();
93 TCPSocketInterface* SocketNode::TCPInterface() {
94 if (filesystem_->ppapi() == NULL)
95 return NULL;
97 return filesystem_->ppapi()->GetTCPSocketInterface();
100 UDPSocketInterface* SocketNode::UDPInterface() {
101 if (filesystem_->ppapi() == NULL)
102 return NULL;
104 return filesystem_->ppapi()->GetUDPSocketInterface();
107 PP_Resource SocketNode::SockAddrToResource(const struct sockaddr* addr,
108 socklen_t len) {
109 if (NULL == addr)
110 return 0;
112 if (AF_INET == addr->sa_family) {
113 PP_NetAddress_IPv4 addr4;
114 const sockaddr_in* sin = reinterpret_cast<const sockaddr_in*>(addr);
116 if (len != sizeof(sockaddr_in))
117 return 0;
119 memset(&addr4, 0, sizeof(addr4));
121 addr4.port = sin->sin_port;
122 memcpy(addr4.addr, &sin->sin_addr, sizeof(addr4.addr));
123 return filesystem_->ppapi()
124 ->GetNetAddressInterface()
125 ->CreateFromIPv4Address(filesystem_->ppapi()->GetInstance(), &addr4);
128 if (AF_INET6 == addr->sa_family) {
129 PP_NetAddress_IPv6 addr6;
130 const sockaddr_in6* sin = reinterpret_cast<const sockaddr_in6*>(addr);
132 if (len != sizeof(sockaddr_in6))
133 return 0;
135 memset(&addr6, 0, sizeof(addr6));
137 addr6.port = sin->sin6_port;
138 memcpy(addr6.addr, &sin->sin6_addr, sizeof(addr6.addr));
139 return filesystem_->ppapi()
140 ->GetNetAddressInterface()
141 ->CreateFromIPv6Address(filesystem_->ppapi()->GetInstance(), &addr6);
143 return 0;
146 socklen_t SocketNode::ResourceToSockAddr(PP_Resource addr,
147 socklen_t len,
148 struct sockaddr* out_addr) {
149 if (0 == addr)
150 return 0;
152 PP_NetAddress_IPv4 ipv4;
153 PP_NetAddress_IPv6 ipv6;
155 if (PP_TRUE == NetInterface()->DescribeAsIPv4Address(addr, &ipv4)) {
156 sockaddr_in addr4;
157 addr4.sin_family = AF_INET;
158 addr4.sin_port = ipv4.port;
159 memcpy(&addr4.sin_addr, ipv4.addr, sizeof(ipv4.addr));
160 memcpy(out_addr, &addr4,
161 std::min(len, static_cast<socklen_t>(sizeof(addr4))));
163 // Returns required size not copied size like getpeername/getsockname.
164 return sizeof(addr4);
167 if (PP_TRUE == NetInterface()->DescribeAsIPv6Address(addr, &ipv6)) {
168 sockaddr_in6 addr6;
169 addr6.sin6_family = AF_INET6;
170 addr6.sin6_port = ipv6.port;
171 memcpy(&addr6.sin6_addr, ipv6.addr, sizeof(ipv6.addr));
172 memcpy(out_addr, &addr6,
173 std::min(len, static_cast<socklen_t>(sizeof(addr6))));
175 // Returns required size not copied size like getpeername/getsockname.
176 return sizeof(addr6);
179 return 0;
182 bool SocketNode::IsEquivalentAddress(PP_Resource addr1, PP_Resource addr2) {
183 if (addr1 == addr2)
184 return true;
186 char data1[sizeof(sockaddr_in6)];
187 char data2[sizeof(sockaddr_in6)];
189 sockaddr* saddr1 = reinterpret_cast<sockaddr*>(data1);
190 sockaddr* saddr2 = reinterpret_cast<sockaddr*>(data2);
192 socklen_t len1 = ResourceToSockAddr(addr1, sizeof(data1), saddr1);
193 socklen_t len2 = ResourceToSockAddr(addr2, sizeof(data2), saddr2);
195 if (len1 != len2)
196 return false;
198 return memcmp(saddr1, saddr2, len1) == 0;
201 Error SocketNode::Accept(const HandleAttr& attr,
202 PP_Resource* new_sock,
203 struct sockaddr* addr,
204 socklen_t* len) {
205 return ENOSYS;
208 Error SocketNode::Connect(const HandleAttr& attr,
209 const struct sockaddr* addr,
210 socklen_t len) {
211 if (len < 1)
212 return EINVAL;
214 if (NULL == addr)
215 return EFAULT;
217 return EOPNOTSUPP;
220 Error SocketNode::Listen(int backlog) {
221 return EOPNOTSUPP;
224 Error SocketNode::GetSockOpt(int lvl,
225 int optname,
226 void* optval,
227 socklen_t* len) {
228 if (lvl != SOL_SOCKET)
229 return ENOPROTOOPT;
231 AUTO_LOCK(node_lock_);
233 int value = 0;
234 socklen_t value_len = 0;
235 void* value_ptr = NULL;
237 switch (optname) {
238 case SO_REUSEADDR:
239 // SO_REUSEADDR is effectively always on since we can't
240 // disable it with PPAPI sockets.
241 value = 1;
242 value_ptr = &value;
243 value_len = sizeof(value);
244 break;
245 case SO_LINGER:
246 value_ptr = &linger_;
247 value_len = sizeof(linger_);
248 break;
249 case SO_KEEPALIVE:
250 value = keep_alive_;
251 value_ptr = &value;
252 value_len = sizeof(value);
253 break;
254 case SO_ERROR:
255 value_ptr = &last_errno_;
256 value_len = sizeof(last_errno_);
257 last_errno_ = 0;
258 break;
259 default:
260 return ENOPROTOOPT;
263 int copy_bytes = std::min(value_len, *len);
264 memcpy(optval, value_ptr, copy_bytes);
265 *len = value_len;
266 return 0;
269 Error SocketNode::SetSockOpt(int lvl,
270 int optname,
271 const void* optval,
272 socklen_t len) {
273 size_t buflen = static_cast<size_t>(len);
275 if (lvl != SOL_SOCKET)
276 return ENOPROTOOPT;
278 AUTO_LOCK(node_lock_);
280 switch (optname) {
281 case SO_REUSEADDR: {
282 // SO_REUSEADDR is effectivly always on since we can't
283 // disable it with PPAPI sockets. Just return success
284 // here regardless.
285 if (buflen < sizeof(int))
286 return EINVAL;
287 return 0;
289 case SO_LINGER: {
290 // Not supported by the PPAPI interface but we preserve
291 // the settings and pretend to support it.
292 if (buflen < sizeof(struct linger))
293 return EINVAL;
294 struct linger new_linger = *static_cast<const linger*>(optval);
295 // Don't allow setting linger to be enabled until we
296 // implement the required synchronous shutdown()/close().
297 // TODO(sbc): remove this after http://crbug.com/312401
298 // gets fixed.
299 if (new_linger.l_onoff != 0)
300 return EINVAL;
301 linger_ = new_linger;
302 return 0;
304 case SO_KEEPALIVE: {
305 // Not supported by the PPAPI interface but we preserve
306 // the flag and pretend to support it.
307 if (buflen < sizeof(int))
308 return EINVAL;
309 int value = *static_cast<const int*>(optval);
310 keep_alive_ = value != 0;
311 return 0;
315 return ENOPROTOOPT;
318 Error SocketNode::Bind(const struct sockaddr* addr, socklen_t len) {
319 return EINVAL;
322 Error SocketNode::Recv(const HandleAttr& attr,
323 void* buf,
324 size_t len,
325 int flags,
326 int* out_len) {
327 return RecvFrom(attr, buf, len, flags, NULL, 0, out_len);
330 Error SocketNode::RecvFrom(const HandleAttr& attr,
331 void* buf,
332 size_t len,
333 int flags,
334 struct sockaddr* src_addr,
335 socklen_t* addrlen,
336 int* out_len) {
337 PP_Resource addr = 0;
338 Error err = RecvHelper(attr, buf, len, flags, &addr, out_len);
339 if (0 == err && 0 != addr) {
340 if (src_addr)
341 *addrlen = ResourceToSockAddr(addr, *addrlen, src_addr);
343 filesystem_->ppapi()->ReleaseResource(addr);
346 return err;
349 Error SocketNode::RecvHelper(const HandleAttr& attr,
350 void* buf,
351 size_t len,
352 int flags,
353 PP_Resource* addr,
354 int* out_len) {
355 if (0 == socket_resource_)
356 return EBADF;
358 if (TestStreamFlags(SSF_RECV_ENDOFSTREAM)) {
359 *out_len = 0;
360 return 0;
363 int ms = read_timeout_;
364 if ((flags & MSG_DONTWAIT) || !attr.IsBlocking())
365 ms = 0;
367 // TODO(bradnelson) BUG=295177
368 // For UDP we should support filtering packets when using connect
369 EventListenerLock wait(GetEventEmitter());
370 Error err = wait.WaitOnEvent(POLLIN, ms);
372 // Timeout is treated as a would block for sockets.
373 if (ETIMEDOUT == err)
374 return EWOULDBLOCK;
376 if (err)
377 return err;
379 err = Recv_Locked(buf, len, addr, out_len);
381 // We must have read from then inputbuffer, so Q up some receive work.
382 if ((err == 0) && *out_len)
383 QueueInput();
384 return err;
387 Error SocketNode::Send(const HandleAttr& attr,
388 const void* buf,
389 size_t len,
390 int flags,
391 int* out_len) {
392 return SendHelper(attr, buf, len, flags, remote_addr_, out_len);
395 Error SocketNode::SendTo(const HandleAttr& attr,
396 const void* buf,
397 size_t len,
398 int flags,
399 const struct sockaddr* dest_addr,
400 socklen_t addrlen,
401 int* out_len) {
402 if ((NULL == dest_addr) && (0 == remote_addr_))
403 return EDESTADDRREQ;
405 PP_Resource addr = SockAddrToResource(dest_addr, addrlen);
406 if (0 == addr)
407 return EINVAL;
409 Error err = SendHelper(attr, buf, len, flags, addr, out_len);
410 filesystem_->ppapi()->ReleaseResource(addr);
411 return err;
414 Error SocketNode::SendHelper(const HandleAttr& attr,
415 const void* buf,
416 size_t len,
417 int flags,
418 PP_Resource addr,
419 int* out_len) {
420 if (0 == socket_resource_)
421 return EBADF;
423 if (0 == addr)
424 return ENOTCONN;
426 int ms = write_timeout_;
427 if ((flags & MSG_DONTWAIT) || !attr.IsBlocking())
428 ms = 0;
430 EventListenerLock wait(GetEventEmitter());
431 Error err = wait.WaitOnEvent(POLLOUT, ms);
433 // Timeout is treated as a would block for sockets.
434 if (ETIMEDOUT == err)
435 return EWOULDBLOCK;
437 if (err)
438 return err;
440 err = Send_Locked(buf, len, addr, out_len);
442 // We must have added to the output buffer, so Q up some transmit work.
443 if ((err == 0) && *out_len)
444 QueueOutput();
445 return err;
448 void SocketNode::SetError_Locked(int pp_error_num) {
449 SetStreamFlags(SSF_ERROR | SSF_CLOSED);
450 ClearStreamFlags(SSF_CAN_SEND | SSF_CAN_RECV);
451 last_errno_ = PPErrorToErrno(pp_error_num);
454 Error SocketNode::Shutdown(int how) {
455 return EOPNOTSUPP;
458 Error SocketNode::GetPeerName(struct sockaddr* addr, socklen_t* len) {
459 if (NULL == addr || NULL == len)
460 return EFAULT;
462 AUTO_LOCK(node_lock_);
463 if (remote_addr_ != 0) {
464 *len = ResourceToSockAddr(remote_addr_, *len, addr);
465 return 0;
468 return ENOTCONN;
471 Error SocketNode::GetSockName(struct sockaddr* addr, socklen_t* len) {
472 if (NULL == addr || NULL == len)
473 return EFAULT;
475 AUTO_LOCK(node_lock_);
476 if (local_addr_ == 0) {
477 // getsockname succeeds even if the socket is not bound. In this case,
478 // just return address 0, port 0.
479 memset(addr, 0, *len);
480 return 0;
483 *len = ResourceToSockAddr(local_addr_, *len, addr);
484 return 0;
487 } // namespace nacl_io
489 #endif // PROVIDES_SOCKET_API