Index: libraries/nacl-mounts/net/SocketSubSystem.cc |
=================================================================== |
--- libraries/nacl-mounts/net/SocketSubSystem.cc (revision 0) |
+++ libraries/nacl-mounts/net/SocketSubSystem.cc (revision 0) |
@@ -0,0 +1,207 @@ |
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <arpa/inet.h> |
+#include <irt.h> |
+#include <netinet/in.h> |
+#include <signal.h> |
+#include <string.h> |
+#include <sys/socket.h> |
+ |
+#include "net/SocketSubSystem.h" |
+#include "net/TcpServerSocket.h" |
+#include "net/TcpSocket.h" |
+#include "ppapi/cpp/file_ref.h" |
+#include "util/DebugPrint.h" |
+ |
+ |
+SocketSubSystem* SocketSubSystem::instance_ = NULL; |
Evgeniy Stepanov
2012/05/25 12:05:57
unused
vissi
2012/05/25 13:07:09
No, it's used by GetSocketSubSystem() referenced i
Evgeniy Stepanov
2012/05/25 13:19:51
Pass pp::Instance through TCPSocket constructor.
vissi
2012/05/25 14:32:06
They use the same condition variable. Should they?
vissi
2012/05/25 14:54:08
Per offline discussion, we decided that it would b
|
+ |
+SocketSubSystem::SocketSubSystem(pp::Instance* instance) |
+ : pp_instance_(instance) |
+ , first_unused_addr_(kFirstAddr) { |
+ AddHostAddress("localhost", 0x7F000001); |
+ instance_ = this; |
+} |
+ |
+void SocketSubSystem::AddHostAddress(const char* name, unsigned long addr) { |
+ addr = htonl(addr); |
+ hosts_[name] = addr; |
+ addrs_[addr] = name; |
+} |
+ |
+unsigned long SocketSubSystem::gethostbyname(const char* name) { |
+ Mutex::Lock lock(mutex_); |
+ HostMap::iterator it = hosts_.find(name); |
+ if (it != hosts_.end()) |
+ return it->second; |
+ |
+ int addr = htonl(first_unused_addr_++); |
+ hosts_[name] = addr; |
+ addrs_[addr] = name; |
+ return addr; |
+} |
+ |
+int SocketSubSystem::bind(FileStream** stream, unsigned long addr, |
+ unsigned short port) { |
+ Mutex::Lock lock(mutex_); |
+ |
+ std::string host; |
+ AddressMap::iterator it = addrs_.find(addr); |
+ if (it != addrs_.end()) { |
+ host = it->second; |
+ } else { |
+ in_addr iaddr; |
+ iaddr.s_addr = addr; |
+ host = inet_ntoa(iaddr); |
+ } |
+ |
+ *stream = new TCPServerSocket(0, host.c_str(), port); |
+ return 0; |
+} |
+ |
+int SocketSubSystem::connect(FileStream** stream, unsigned long addr, |
+ unsigned short port) { |
+ Mutex::Lock lock(mutex_); |
+ |
+ std::string host; |
+ AddressMap::iterator it = addrs_.find(addr); |
Evgeniy Stepanov
2012/05/25 12:05:57
factor this piece out
vissi
2012/05/25 13:07:09
Why?
Evgeniy Stepanov
2012/05/25 13:19:51
I mean, make it a function. It's repeated twice in
vissi
2012/05/25 14:32:06
Done.
|
+ if (it != addrs_.end()) { |
+ host = it->second; |
+ } else { |
+ in_addr iaddr; |
+ iaddr.s_addr = addr; |
+ host = inet_ntoa(iaddr); |
+ } |
+ |
+ FileStream* new_stream = NULL; |
+ TCPSocket* socket = new TCPSocket(O_RDWR); |
+ if (!socket->connect(host.c_str(), port)) { |
+ errno = ECONNREFUSED; |
+ socket->release(); |
+ return -1; |
+ } |
+ new_stream = socket; |
+ |
+ *stream = new_stream; |
+ return 0; |
+} |
+ |
+SocketSubSystem::~SocketSubSystem() { |
+} |
+ |
+int SocketSubSystem::shutdown(FileStream* stream, int how) { |
+ Mutex::Lock lock(mutex_); |
+ if (stream && stream != kBadFileStream) { |
+ // Actually shutdown should be something more complicated by for now |
+ // it works. Method close can be called multiple time. |
+ stream->close(); |
+ return 0; |
+ } else { |
+ errno = EBADF; |
+ return -1; |
+ } |
+} |
+ |
+int SocketSubSystem::close(FileStream* stream) { |
+ Mutex::Lock lock(mutex_); |
+ |
+ if (stream && stream != kBadFileStream) { |
Evgeniy Stepanov
2012/05/25 12:05:57
could we get rid of this constant?
vissi
2012/05/25 13:07:09
yup.
|
+ stream->close(); |
+ stream->release(); |
+ } |
+ return 0; |
+} |
+ |
+int SocketSubSystem::read(FileStream* stream, char* buf, size_t count, |
+ size_t* nread) { |
+ Mutex::Lock lock(mutex_); |
+ if (stream && stream != kBadFileStream) |
Evgeniy Stepanov
2012/05/25 12:05:57
move this check to KernelProxy, assume that stream
vissi
2012/05/25 13:07:09
Haven't moved this yet. We check if FileHandle is
|
+ return stream->read(buf, count, nread); |
+ else |
+ return EBADF; |
+} |
+ |
+int SocketSubSystem::write(FileStream* stream, const char* buf, size_t count, |
+ size_t* nwrote) { |
+ Mutex::Lock lock(mutex_); |
+ if (stream && stream != kBadFileStream) |
+ return stream->write(buf, count, nwrote); |
+ else |
+ return EBADF; |
+} |
+ |
+int SocketSubSystem::seek(FileStream* stream, nacl_abi_off_t offset, int whence, |
+ nacl_abi_off_t* new_offset) { |
+ Mutex::Lock lock(mutex_); |
+ if (stream && stream != kBadFileStream) |
+ return stream->seek(offset, whence, new_offset); |
+ else |
+ return EBADF; |
+} |
+ |
+int SocketSubSystem::fstat(FileStream* stream, nacl_abi_stat* out) { |
+ Mutex::Lock lock(mutex_); |
+ if (stream && stream != kBadFileStream) |
+ return stream->fstat(out); |
+ else |
+ return EBADF; |
+} |
+ |
+int SocketSubSystem::fcntl(FileStream* stream, int cmd, va_list ap) { |
+ Mutex::Lock lock(mutex_); |
+ if (stream && stream != kBadFileStream) { |
+ return stream->fcntl(cmd, ap); |
+ } else { |
+ errno = EBADF; |
+ return -1; |
+ } |
+} |
+ |
+int SocketSubSystem::ioctl(FileStream* stream, int request, va_list ap) { |
+ Mutex::Lock lock(mutex_); |
+ if (stream && stream != kBadFileStream) { |
+ return stream->ioctl(request, ap); |
+ } else { |
+ errno = EBADF; |
+ return -1; |
+ } |
+} |
+ |
+int SocketSubSystem::listen(FileStream* stream, int backlog) { |
+ Mutex::Lock lock(mutex_); |
+ if (stream && stream != kBadFileStream) { |
+ if (static_cast<TCPServerSocket*>(stream)->listen(backlog)) { |
+ return 0; |
+ } else { |
+ errno = EACCES; |
+ return -1; |
+ } |
+ } else { |
+ errno = EBADF; |
+ return -1; |
+ } |
+} |
+ |
+FileStream* SocketSubSystem::accept(FileStream* stream, struct sockaddr *addr, |
+ socklen_t* addrlen) { |
+ Mutex::Lock lock(mutex_); |
+ if (stream && stream != kBadFileStream) { |
+ PP_Resource resource = static_cast<TCPServerSocket*>(stream)->accept(); |
+ if (resource) { |
+ TCPSocket* socket = new TCPSocket(O_RDWR); |
+ if (socket->accept(resource)) { |
+ return socket; |
+ } else { |
+ socket->release(); |
+ } |
+ } |
+ errno = EINVAL; |
+ return 0; |
+ } else { |
+ errno = EBADF; |
+ return 0; |
+ } |
+} |
+ |