Index: libraries/nacl-mounts/base/KernelProxy.cc |
=================================================================== |
--- libraries/nacl-mounts/base/KernelProxy.cc (revision 583) |
+++ libraries/nacl-mounts/base/KernelProxy.cc (working copy) |
@@ -4,12 +4,17 @@ |
* found in the LICENSE file. |
*/ |
#include <assert.h> |
+#include <sys/time.h> |
#include <list> |
#include <utility> |
-#include "../console/ConsoleMount.h" |
+#include "console/ConsoleMount.h" |
Evgeniy Stepanov
2012/05/23 15:35:13
Why this one without ../, and the two below it wit
vissi
2012/05/25 11:08:50
Now without ..
|
#include "../dev/DevMount.h" |
+#include "../net/SocketSubSystem.h" |
#include "KernelProxy.h" |
#include "MountManager.h" |
+#include "net/BaseSocketSubSystem.h" |
+#include <netinet/in.h> |
+#include "util/DebugPrint.h" |
static pthread_once_t kp_once_ = PTHREAD_ONCE_INIT; |
KernelProxy *KernelProxy::kp_instance_; |
@@ -42,6 +47,34 @@ |
assert(fd == 2); |
} |
+void KernelProxy::SetSS(BaseSocketSubSystem* bss) { |
Evgeniy Stepanov
2012/05/23 15:35:13
A more descriptive setter name pls.
vissi
2012/05/25 11:08:50
Done.
|
+ ss = bss; |
+} |
+ |
+void KernelProxy::RemoveFileStream(int fd) { |
+ this->close(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 +210,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 +230,32 @@ |
return fd; |
} |
+ino_t KernelProxy::CreateSocket() { |
+ 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); |
+ handle->mount = NULL; |
+ handle->stream = NULL; |
+ handle->use_count = 1; |
+ 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; |
@@ -235,12 +295,14 @@ |
} |
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(); |
} |
- mount->Unref(); |
return 0; |
} |
@@ -618,7 +680,7 @@ |
return 0; |
} |
-KernelProxy::FileHandle *KernelProxy::GetFileHandle(int fd) { |
+FileHandle* KernelProxy::GetFileHandle(int fd) { |
SimpleAutoLock lock(&kp_lock_); |
FileDescriptor *file = fds_.At(fd); |
if (!file) { |
@@ -676,42 +738,36 @@ |
#ifdef __GLIBC__ |
int KernelProxy::socket(int domain, int type, int protocol) { |
- errno = ENOSYS; |
- fprintf(stderr, "socket has not been implemented!\n"); |
- return -1; |
+ return ss->socket(domain, type, protocol); |
} |
int KernelProxy::accept(int sockfd, struct sockaddr *addr, |
socklen_t* addrlen) { |
- errno = ENOSYS; |
- fprintf(stderr, "accept has not been implemented!\n"); |
- return -1; |
+ return ss->accept(GetFileHandle(sockfd), addr, addrlen); |
} |
int KernelProxy::bind(int sockfd, const struct sockaddr *addr, |
socklen_t addrlen) { |
- errno = ENOSYS; |
- fprintf(stderr, "bind has not been implemented!\n"); |
- return -1; |
+ struct sockaddr_in* in_addr = (struct sockaddr_in*)addr; |
+ return ss->bind(GetFileHandle(sockfd), 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; |
+ return ss->listen(GetFileHandle(sockfd), 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; |
+ struct sockaddr_in* in_addr = (struct sockaddr_in*)addr; |
+ return ss->connect(GetFileHandle(sockfd), 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; |
+ ss->write(GetFileHandle(sockfd), (const char*)buf, len, &nwr); |
+ return nwr; |
} |
int KernelProxy::sendmsg(int sockfd, const struct msghdr *msg, int flags) { |
@@ -728,9 +784,9 @@ |
} |
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; |
+ ss->read(GetFileHandle(sockfd), reinterpret_cast<char*>(buf), len, &nread); |
+ return nread; |
} |
int KernelProxy::recvmsg(int sockfd, struct msghdr *msg, int flags) { |
@@ -748,9 +804,53 @@ |
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; |
+ dbgprintf("int select() before mutex\n"); |
+ Mutex::Lock lock(ss->mutex()); |
+ dbgprintf("int select() after mutex\n"); |
+ |
+ 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 (!(ss->IsReady(nfds, readfds, &FileStream::is_read_ready, false) || |
+ ss->IsReady(nfds, writefds, &FileStream::is_write_ready, false) || |
+ ss->IsReady(nfds, exceptfds, &FileStream::is_exception, false))) { |
+ if (timeout) { |
+ if (!timeout->tv_sec && !timeout->tv_usec) |
+ break; |
+ |
+ if (ss->cond().timedwait(ss->mutex(), &ts_abs)) { |
+ if (errno == ETIMEDOUT) |
+ break; |
+ else |
+ return -1; |
+ } |
+ } else { |
+ ss->cond().wait(ss->mutex()); |
+ } |
+ } |
+ |
+ int nread = ss->IsReady(nfds, readfds, &FileStream::is_read_ready, true); |
+ int nwrite = ss->IsReady(nfds, writefds, &FileStream::is_write_ready, true); |
+ int nexcpt = ss->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 +889,7 @@ |
} |
int KernelProxy::shutdown(int sockfd, int how) { |
- errno = ENOSYS; |
- fprintf(stderr, "shutdown has not been implemented!\n"); |
- return -1; |
+ return close(sockfd); |
} |
int KernelProxy::epoll_create(int size) { |