Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Unified Diff: libraries/nacl-mounts/net/SocketSubSystem.cc

Issue 10392070: Socket subsystem implementation (Closed) Base URL: http://naclports.googlecode.com/svn/trunk/src/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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,310 @@
+// 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 "base/KernelProxy.h"
+#include "net/SocketSubSystem.h"
+#include "net/TcpServerSocket.h"
+#include "net/TcpSocket.h"
+#include "ppapi/cpp/file_ref.h"
+#include "util/DebugPrint.h"
+
+FileStream* const SocketSubSystem::kBadFileStream =
+ reinterpret_cast<FileStream*>(-1);
+
+SocketSubSystem* SocketSubSystem::instance_ = NULL;
+
+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::socket(int socket_family, int socket_type, int protocol) {
+ Mutex::Lock lock(mutex_);
+ int fd = KernelProxy::KPInstance()->CreateSocket();
+ return fd;
+}
+
+int SocketSubSystem::GetFirstUnusedDescriptor() {
+ return KernelProxy::KPInstance()->CreateSocket();
+}
+
+bool SocketSubSystem::IsKnowDescriptor(int fd) {
+ return KernelProxy::KPInstance()->GetFileHandle(fd) != 0 &&
+ KernelProxy::KPInstance()->GetFileHandle(fd)->stream != kBadFileStream;
+}
+
+FileStream* SocketSubSystem::GetStream(int fd) {
+ return KernelProxy::KPInstance()->GetFileHandle(fd)->stream;
+}
+
+int SocketSubSystem::bind(FileHandle* handle, 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);
+ }
+
+ handle->stream = new TCPServerSocket(0, host.c_str(), port);
+ return 0;
+}
+
+int SocketSubSystem::connect(FileHandle* handle, 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);
+ }
+
+ FileStream* stream = NULL;
+ TCPSocket* socket = new TCPSocket(O_RDWR);
+ if (!socket->connect(host.c_str(), port)) {
+ errno = ECONNREFUSED;
+ socket->release();
+ return -1;
+ }
+ stream = socket;
+
+ handle->stream = stream;
+ return 0;
+}
+
+SocketSubSystem::~SocketSubSystem() {
+}
+
+int SocketSubSystem::shutdown(int fd, int how) {
+ Mutex::Lock lock(mutex_);
+ FileStream* stream = GetStream(fd);
+ 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(int fd) {
+ Mutex::Lock lock(mutex_);
+ if (!IsKnowDescriptor(fd))
+ return EBADF;
+
+ FileStream* stream = GetStream(fd);
+ if (stream && stream != kBadFileStream) {
+ stream->close();
+ stream->release();
+ }
+ KernelProxy::KPInstance()->RemoveFileStream(fd);
+ return 0;
+}
+
+int SocketSubSystem::read(FileHandle* handle, char* buf, size_t count,
+ size_t* nread) {
+ Mutex::Lock lock(mutex_);
+ FileStream* stream = handle->stream;
+ if (stream && stream != kBadFileStream)
+ return stream->read(buf, count, nread);
+ else
+ return EBADF;
+}
+
+int SocketSubSystem::write(FileHandle* handle, const char* buf, size_t count,
+ size_t* nwrote) {
+ Mutex::Lock lock(mutex_);
+ FileStream* stream = handle->stream;
+ if (stream && stream != kBadFileStream)
+ return stream->write(buf, count, nwrote);
+ else
+ return EBADF;
+}
+
+int SocketSubSystem::seek(FileHandle* handle, nacl_abi_off_t offset, int whence,
+ nacl_abi_off_t* new_offset) {
+ Mutex::Lock lock(mutex_);
+ FileStream* stream = handle->stream;
+ if (stream && stream != kBadFileStream)
+ return stream->seek(offset, whence, new_offset);
+ else
+ return EBADF;
+}
+
+/*int SocketSubSystem::dup(int fd, int *newfd) {
+ Mutex::Lock lock(mutex_);
+ FileStream* stream = GetStream(fd);
+ if (!stream || stream == kBadFileStream)
+ return EBADF;
+
+ // Mark as used.
+ *newfd = KernelProxy::KPInstance()->AddFileStream(NULL);
+ FileStream* new_stream = stream->dup(*newfd);
+ if (!new_stream) {
+ KernelProxy::KPInstance()->RemoveFileStream(*newfd);
+ return EACCES;
+ }
+
+ // TODO(vissi): check it
+ KernelProxy::KPInstance()->GetFileHandle(*newfd)->stream = new_stream;
+ return 0;
+}
+
+int SocketSubSystem::dup2(int fd, int newfd) {
+ Mutex::Lock lock(mutex_);
+ FileStream* stream = GetStream(fd);
+ if (!stream || stream == kBadFileStream)
+ return EBADF;
+
+ FileStream* new_stream = GetStream(newfd);
+ if (stream == kBadFileStream) {
+ return EBADF;
+ } else if (!new_stream) {
+ new_stream->close();
+ new_stream->release();
+ KernelProxy::KPInstance()->RemoveFileStream(newfd);
+ }
+
+ KernelProxy::KPInstance()->GetFileHandle(newfd)->stream
+ = stream->dup(newfd);
+ if (!new_stream)
+ return EACCES;
+
+ // TODO(vissi): AddFileStream(newfd, new_stream);
+ return 0;
+}*/
+
+int SocketSubSystem::fstat(FileHandle* handle, nacl_abi_stat* out) {
+ Mutex::Lock lock(mutex_);
+ FileStream* stream = handle->stream;
+ if (stream && stream != kBadFileStream)
+ return stream->fstat(out);
+ else
+ return EBADF;
+}
+
+int SocketSubSystem::fcntl(FileHandle* handle, int cmd, va_list ap) {
+ Mutex::Lock lock(mutex_);
+ FileStream* stream = handle->stream;
+ if (stream && stream != kBadFileStream) {
+ return stream->fcntl(cmd, ap);
+ } else {
+ errno = EBADF;
+ return -1;
+ }
+}
+
+int SocketSubSystem::ioctl(FileHandle* handle, int request, va_list ap) {
+ Mutex::Lock lock(mutex_);
+ FileStream* stream = handle->stream;
+ if (stream && stream != kBadFileStream) {
+ return stream->ioctl(request, ap);
+ } else {
+ errno = EBADF;
+ return -1;
+ }
+}
+
+int SocketSubSystem::IsReady(int nfds, fd_set* fds,
+ bool (FileStream::*is_ready)(), bool apply) {
+ if (!fds)
+ return 0;
+
+ int nset = 0;
+ for (int i = 0; i < nfds; i++) {
+ if (FD_ISSET(i, fds)) {
+ FileStream* stream = GetStream(i);
+ if (!stream)
+ return -1;
+ if ((stream->*is_ready)()) {
+ if (!apply)
+ return 1;
+ else
+ nset++;
+ } else {
+ if (apply)
+ FD_CLR(i, fds);
+ }
+ }
+ }
+ return nset;
+}
+
+int SocketSubSystem::listen(FileHandle *handle, int backlog) {
+ Mutex::Lock lock(mutex_);
+ FileStream *stream = handle->stream;
+ if (stream && stream != kBadFileStream) {
+ if (static_cast<TCPServerSocket*>(stream)->listen(backlog)) {
+ return 0;
+ } else {
+ errno = EACCES;
+ return -1;
+ }
+ } else {
+ errno = EBADF;
+ return -1;
+ }
+}
+
+int SocketSubSystem::accept(FileHandle* handle, struct sockaddr *addr,
+ socklen_t* addrlen) {
+ Mutex::Lock lock(mutex_);
+ FileStream *stream = handle->stream;
+ 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 KernelProxy::KPInstance()->AddFileStream(socket);
+ } else {
+ socket->release();
+ }
+ }
+ errno = EINVAL;
+ return -1;
+ } else {
+ errno = EBADF;
+ return -1;
+ }
+}
+

Powered by Google App Engine
This is Rietveld 408576698