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

Unified Diff: libraries/nacl-mounts/base/KernelProxy.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/base/KernelProxy.cc
===================================================================
--- libraries/nacl-mounts/base/KernelProxy.cc (revision 594)
+++ libraries/nacl-mounts/base/KernelProxy.cc (working copy)
@@ -3,13 +3,18 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
+#include "base/KernelProxy.h"
#include <assert.h>
+#include <netinet/in.h>
+#include <sys/time.h>
#include <list>
#include <utility>
-#include "../console/ConsoleMount.h"
-#include "../dev/DevMount.h"
-#include "KernelProxy.h"
+#include "console/ConsoleMount.h"
+#include "dev/DevMount.h"
#include "MountManager.h"
+#include "net/BaseSocketSubSystem.h"
+#include "net/SocketSubSystem.h"
+#include "util/DebugPrint.h"
static pthread_once_t kp_once_ = PTHREAD_ONCE_INIT;
KernelProxy *KernelProxy::kp_instance_;
@@ -42,6 +47,54 @@
assert(fd == 2);
}
+void KernelProxy::SetSocketSubSystem(BaseSocketSubSystem* bss) {
+ ss = bss;
+}
+
+void KernelProxy::RemoveFileStream(int fd) {
+ this->close(fd);
+}
+
+int KernelProxy::AddFileStream(FileStream* stream, int fd) {
+ SimpleAutoLock lock(&kp_lock_);
+
+ // Setup file handle.
+ int handle_slot = open_files_.AllocAt(fd);
+ if (fds_.AllocAt(fd) != fd) return -1;
+ FileDescriptor* file = fds_.At(fd);
+ file->handle = handle_slot;
+ FileHandle* handle = open_files_.At(handle_slot);
+
+ // init should be safe because we have the kernel proxy lock
+ if (pthread_mutex_init(&handle->lock, NULL)) assert(0);
+
+ handle->mount = (Mount*) NULL;
+ handle->stream = (FileStream*) NULL;
+ handle->use_count = 1;
+
+ return fd;
+}
+
+int KernelProxy::AddFileStream(FileStream* stream) {
+ SimpleAutoLock lock(&kp_lock_);
+
+ // Setup file handle.
+ int handle_slot = open_files_.Alloc();
+ int fd = fds_.Alloc();
+ FileDescriptor* file = fds_.At(fd);
+ file->handle = handle_slot;
+ FileHandle* handle = open_files_.At(handle_slot);
+
+ // init should be safe because we have the kernel proxy lock
+ if (pthread_mutex_init(&handle->lock, NULL)) assert(0);
+
+ handle->mount = (Mount*) NULL;
+ handle->stream = (FileStream*) NULL;
+ handle->use_count = 1;
+
+ return fd;
+}
+
KernelProxy *KernelProxy::KPInstance() {
pthread_once(&kp_once_, Instantiate);
return kp_instance_;
@@ -177,12 +230,13 @@
int fd = fds_.Alloc();
FileDescriptor* file = fds_.At(fd);
file->handle = handle_slot;
- FileHandle *handle = open_files_.At(handle_slot);
+ FileHandle* handle = open_files_.At(handle_slot);
// init should be safe because we have the kernel proxy lock
if (pthread_mutex_init(&handle->lock, NULL)) assert(0);
handle->mount = mount;
+ handle->stream = NULL;
handle->node = st.st_ino;
handle->flags = flags;
handle->use_count = 1;
@@ -196,6 +250,19 @@
return fd;
}
+struct hostent* KernelProxy::gethostbyname(const char* name) {
+ struct hostent *res = (struct hostent*) malloc(sizeof(struct hostent));
+ if (!res) return NULL;
+ res->h_addr_list = (char**) malloc(sizeof(char*) * 2);
+ if (!res->h_addr_list) return NULL;
+ res->h_addr_list[0] = (char*) malloc(sizeof(long int));
+ if (!res->h_addr_list[0]) return NULL;
+ *((long int*)res->h_addr_list[0]) = ss->gethostbyname(name);
+ res->h_addr_list[1] = NULL;
+ res->h_length = sizeof(long int);
+ return res;
+}
+
int KernelProxy::open(const std::string& path, int flags, mode_t mode) {
if (path.empty()) {
errno = EINVAL;
@@ -228,24 +295,28 @@
}
int h = file->handle;
fds_.Free(fd);
- FileHandle *handle = open_files_.At(h);
+ FileHandle* handle = open_files_.At(h);
if (handle == NULL) {
errno = EBADF;
return -1;
}
handle->use_count--;
ino_t node = handle->node;
- Mount *mount = handle->mount;
- if (handle->use_count <= 0) {
- open_files_.Free(h);
- mount->Unref(node);
+ if (handle->mount) {
+ Mount* mount = handle->mount;
+ if (handle->use_count <= 0) {
+ open_files_.Free(h);
+ mount->Unref(node);
+ }
+ mount->Unref();
+ } else {
+ ss->close(handle->stream);
}
- mount->Unref();
return 0;
}
ssize_t KernelProxy::read(int fd, void *buf, size_t count) {
- FileHandle *handle;
+ FileHandle* handle;
// check if fd is valid and handle exists
if (!(handle = GetFileHandle(fd))) {
errno = EBADF;
@@ -254,22 +325,30 @@
SimpleAutoLock(&handle->lock);
- // Check that this file handle can be read from.
- if ((handle->flags & O_ACCMODE) == O_WRONLY ||
- is_dir(handle->mount, handle->node)) {
+ if (handle->mount) {
+ // Check that this file handle can be read from.
+ if ((handle->flags & O_ACCMODE) == O_WRONLY ||
+ is_dir(handle->mount, handle->node)) {
+ errno = EBADF;
+ return -1;
+ }
+
+ ssize_t n = handle->mount->Read(handle->node, handle->offset, buf, count);
+ if (n > 0) {
+ handle->offset += n;
+ }
+ return n;
+ } else if (handle->stream) {
+ // TODO(vissi): more elaborate implementation
+ return recv(fd, buf, count, 0);
+ } else {
errno = EBADF;
return -1;
}
-
- ssize_t n = handle->mount->Read(handle->node, handle->offset, buf, count);
- if (n > 0) {
- handle->offset += n;
- }
- return n;
}
ssize_t KernelProxy::write(int fd, const void *buf, size_t count) {
- FileHandle *handle;
+ FileHandle* handle;
// check if fd is valid and handle exists
if (!(handle = GetFileHandle(fd))) {
@@ -279,23 +358,31 @@
SimpleAutoLock(&handle->lock);
- // Check that this file handle can be written to.
- if ((handle->flags & O_ACCMODE) == O_RDONLY ||
- is_dir(handle->mount, handle->node)) {
+ if (handle->mount) {
+ // Check that this file handle can be written to.
+ if ((handle->flags & O_ACCMODE) == O_RDONLY ||
+ is_dir(handle->mount, handle->node)) {
+ errno = EBADF;
+ return -1;
+ }
+
+ ssize_t n = handle->mount->Write(handle->node, handle->offset, buf, count);
+
+ if (n > 0) {
+ handle->offset += n;
+ }
+ return n;
+ } else if (handle->stream) {
+ // TODO(vissi): more elaborate implementation
+ return send(fd, buf, count, 0);
+ } else {
errno = EBADF;
return -1;
}
-
- ssize_t n = handle->mount->Write(handle->node, handle->offset, buf, count);
-
- if (n > 0) {
- handle->offset += n;
- }
- return n;
}
int KernelProxy::fstat(int fd, struct stat *buf) {
- FileHandle *handle;
+ FileHandle* handle;
// check if fd is valid and handle exists
if (!(handle = GetFileHandle(fd))) {
@@ -321,7 +408,7 @@
}
int KernelProxy::getdents(int fd, void *buf, unsigned int count) {
- FileHandle *handle;
+ FileHandle* handle;
// check if fd is valid and handle exists
if (!(handle = GetFileHandle(fd))) {
@@ -343,7 +430,7 @@
}
int KernelProxy::fsync(int fd) {
- FileHandle *handle;
+ FileHandle* handle;
if (!(handle = GetFileHandle(fd))) {
errno = EBADF;
@@ -354,19 +441,67 @@
}
int KernelProxy::isatty(int fd) {
- FileHandle *handle;
+ FileHandle* handle;
if (!(handle = GetFileHandle(fd))) {
errno = EBADF;
return 0;
}
- SimpleAutoLock(&handle->lock);
return handle->mount->Isatty(handle->node);
}
+int KernelProxy::dup2(int fd, int newfd) {
+ FileStream* stream = GetFileHandle(fd) > 0
+ ? GetFileHandle(fd)->stream : NULL;
+ if (!stream)
+ return EBADF;
+
+ AddFileStream(stream, newfd);
+ return 0;
+}
+
+int KernelProxy::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 = GetFileHandle(i) > 0 ?
+ GetFileHandle(i)->stream : NULL;
+ if (!stream)
+ return -1;
+ if ((stream->*is_ready)()) {
+ if (!apply)
+ return 1;
+ else
+ nset++;
+ } else {
+ if (apply)
+ FD_CLR(i, fds);
+ }
+ }
+ }
+ return nset;
+}
+
int KernelProxy::dup(int oldfd) {
SimpleAutoLock lock(&kp_lock_);
+ FileHandle* fh = GetFileHandle(oldfd);
+ if (!fh) {
+ errno = EBADF;
+ return -1;
+ }
+ if (fh->mount == NULL) {
+ FileStream* stream = GetFileHandle(oldfd) > 0
+ ? GetFileHandle(oldfd)->stream : NULL;
+ if (!stream)
+ return EBADF;
+ int new_fd = AddFileStream(stream);
+ return new_fd;
+ }
FileDescriptor* oldfile = fds_.At(oldfd);
if (oldfile == NULL) {
errno = EBADF;
@@ -376,7 +511,7 @@
FileDescriptor *newfile = fds_.At(newfd);
int h = oldfile->handle;
newfile->handle = h;
- FileHandle *handle = open_files_.At(h);
+ FileHandle* handle = open_files_.At(h);
// init should be safe because we have the kernel proxy lock
if (pthread_mutex_init(&handle->lock, NULL)) assert(0);
@@ -391,7 +526,7 @@
}
off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
- FileHandle *handle;
+ FileHandle* handle;
// check if fd is valid and handle exists
if (!(handle = GetFileHandle(fd))) {
errno = EBADF;
@@ -618,7 +753,7 @@
return 0;
}
-KernelProxy::FileHandle *KernelProxy::GetFileHandle(int fd) {
+KernelProxy::FileHandle* KernelProxy::GetFileHandle(int fd) {
SimpleAutoLock lock(&kp_lock_);
FileDescriptor *file = fds_.At(fd);
if (!file) {
@@ -676,42 +811,56 @@
#ifdef __GLIBC__
int KernelProxy::socket(int domain, int type, int protocol) {
- errno = ENOSYS;
- fprintf(stderr, "socket has not been implemented!\n");
- return -1;
+ SimpleAutoLock lock(&kp_lock_);
+ int handle_slot = open_files_.Alloc();
+ int fd = fds_.Alloc();
+ FileDescriptor* file = fds_.At(fd);
+ file->handle = handle_slot;
+ FileHandle* handle = open_files_.At(handle_slot);
+ // this means it is a socket (not a mount handle) and it's implementation
+ // determined by handle->stream type is defined later
+ handle->mount = NULL;
+ handle->stream = NULL;
+ handle->use_count = 1;
+ return fd;
}
int KernelProxy::accept(int sockfd, struct sockaddr *addr,
socklen_t* addrlen) {
- errno = ENOSYS;
- fprintf(stderr, "accept has not been implemented!\n");
- return -1;
+ if (GetFileHandle(sockfd) == 0) return EBADF;
+ FileStream* ret = ss->accept(GetFileHandle(sockfd)->stream, addr, addrlen);
+ if (!ret)
+ return AddFileStream(ret);
+ else
+ return -1;
}
int KernelProxy::bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen) {
- errno = ENOSYS;
- fprintf(stderr, "bind has not been implemented!\n");
- return -1;
+ if (GetFileHandle(sockfd) == 0) return EBADF;
+ struct sockaddr_in* in_addr = (struct sockaddr_in*)addr;
+ return ss->bind(&(GetFileHandle(sockfd)->stream), in_addr->sin_addr.s_addr,
+ (unsigned short) ntohs(in_addr->sin_port));
}
int KernelProxy::listen(int sockfd, int backlog) {
- errno = ENOSYS;
- fprintf(stderr, "listen has not been implemented!\n");
- return -1;
+ if (GetFileHandle(sockfd) == 0) return EBADF;
+ return ss->listen(GetFileHandle(sockfd)->stream, backlog);
}
int KernelProxy::connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen) {
- errno = ENOSYS;
- fprintf(stderr, "connect has not been implemented!\n");
- return -1;
+ if (GetFileHandle(sockfd) == 0) return EBADF;
+ struct sockaddr_in* in_addr = (struct sockaddr_in*)addr;
+ return ss->connect(&(GetFileHandle(sockfd)->stream), in_addr->sin_addr.s_addr,
+ (unsigned short) ntohs(in_addr->sin_port));
}
int KernelProxy::send(int sockfd, const void *buf, size_t len, int flags) {
- errno = ENOSYS;
- fprintf(stderr, "send has not been implemented!\n");
- return -1;
+ size_t nwr;
+ if (GetFileHandle(sockfd) == 0) return EBADF;
+ ss->write(GetFileHandle(sockfd)->stream, (const char*)buf, len, &nwr);
+ return nwr;
}
int KernelProxy::sendmsg(int sockfd, const struct msghdr *msg, int flags) {
@@ -728,9 +877,11 @@
}
int KernelProxy::recv(int sockfd, void *buf, size_t len, int flags) {
- errno = ENOSYS;
- fprintf(stderr, "recv has not been implemented!\n");
- return -1;
+ size_t nread;
+ if (GetFileHandle(sockfd) == 0) return EBADF;
+ ss->read(GetFileHandle(sockfd)->stream,
+ reinterpret_cast<char*>(buf), len, &nread);
+ return nread;
}
int KernelProxy::recvmsg(int sockfd, struct msghdr *msg, int flags) {
@@ -748,9 +899,51 @@
int KernelProxy::select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set* exceptfds, const struct timeval *timeout) {
- errno = ENOSYS;
- fprintf(stderr, "select has not been implemented!\n");
- return -1;
+ Mutex::Lock lock(mutex());
+
+ timespec ts_abs;
+ if (timeout) {
+ timespec ts;
+ TIMEVAL_TO_TIMESPEC(timeout, &ts);
+ timeval tv_now;
+ gettimeofday(&tv_now, NULL);
+ int64_t current_time_us =
+ tv_now.tv_sec * kMicrosecondsPerSecond + tv_now.tv_usec;
+ int64_t wakeup_time_us =
+ current_time_us +
+ timeout->tv_sec * kMicrosecondsPerSecond + timeout->tv_usec;
+ ts_abs.tv_sec = wakeup_time_us / kMicrosecondsPerSecond;
+ ts_abs.tv_nsec =
+ (wakeup_time_us - ts_abs.tv_sec * kMicrosecondsPerSecond) *
+ kNanosecondsPerMicrosecond;
+ }
+
+ while (!(IsReady(nfds, readfds, &FileStream::is_read_ready, false) ||
+ IsReady(nfds, writefds, &FileStream::is_write_ready, false) ||
+ IsReady(nfds, exceptfds, &FileStream::is_exception, false))) {
+ if (timeout) {
+ if (!timeout->tv_sec && !timeout->tv_usec)
+ break;
+
+ if (cond().timedwait(mutex(), &ts_abs)) {
+ if (errno == ETIMEDOUT)
+ break;
+ else
+ return -1;
+ }
+ } else {
+ cond().wait(mutex());
+ }
+ }
+
+ int nread = IsReady(nfds, readfds, &FileStream::is_read_ready, true);
+ int nwrite = IsReady(nfds, writefds, &FileStream::is_write_ready, true);
+ int nexcpt = IsReady(nfds, exceptfds, &FileStream::is_exception, true);
+ if (nread < 0 || nwrite < 0 || nexcpt < 0) {
+ errno = EBADF;
+ return -1;
+ }
+ return nread + nwrite + nexcpt;
}
int KernelProxy::pselect(int nfds, fd_set *readfds, fd_set *writefds,
@@ -789,9 +982,8 @@
}
int KernelProxy::shutdown(int sockfd, int how) {
- errno = ENOSYS;
- fprintf(stderr, "shutdown has not been implemented!\n");
- return -1;
+ if (GetFileHandle(sockfd) == 0) return EBADF;
+ return ss->shutdown(GetFileHandle(sockfd)->stream, how);
}
int KernelProxy::epoll_create(int size) {

Powered by Google App Engine
This is Rietveld 408576698