From: brian Date: Mon, 10 May 2004 10:31:36 +0000 (-0700) Subject: socket support X-Git-Url: http://git.megacz.com/?p=nestedvm.git;a=commitdiff_plain;h=7ee9c4231f8e74adfde9679bc60783a715f69c2a socket support darcs-hash:20040510103136-24bed-9bcd12582d26503f78703ca4e0caaac40c7d673f.gz --- diff --git a/src/org/ibex/nestedvm/Runtime.java b/src/org/ibex/nestedvm/Runtime.java index a758a50..c501d0d 100644 --- a/src/org/ibex/nestedvm/Runtime.java +++ b/src/org/ibex/nestedvm/Runtime.java @@ -158,9 +158,9 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { } InputStream stdin = Boolean.valueOf(getSystemProperty("nestedvm.textstdin")).booleanValue() ? new TextInputStream(System.in) : System.in; - addFD(new StdinFD(stdin)); - addFD(new StdoutFD(System.out)); - addFD(new StdoutFD(System.err)); + addFD(new TerminalFD(stdin)); + addFD(new TerminalFD(System.out)); + addFD(new TerminalFD(System.err)); } /** Copy everything from src to addr initializing uninitialized pages if required. @@ -1174,46 +1174,57 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { protected void _close() { try { data.close(); } catch(IOException e) { /*ignore*/ } } } - public static class OutputStreamFD extends FD { - private OutputStream os; - public int flags() { return O_WRONLY; } - public OutputStreamFD(OutputStream os) { this.os = os; } - public int write(byte[] a, int off, int length) throws ErrnoException { - try { - os.write(a,off,length); - return length; - } catch(IOException e) { - throw new ErrnoException(EIO); - } + public static class InputOutputStreamFD extends FD { + private final InputStream is; + private final OutputStream os; + + public InputOutputStreamFD(InputStream is) { this(is,null); } + public InputOutputStreamFD(OutputStream os) { this(null,os); } + public InputOutputStreamFD(InputStream is, OutputStream os) { + this.is = is; + this.os = os; + if(is == null && os == null) throw new IllegalArgumentException("at least one stream must be supplied"); } - public void _close() { try { os.close(); } catch(IOException e) { /*ignore*/ } } - public FStat _fstat() { return new FStat(); } - } - - public static class InputStreamFD extends FD { - private InputStream is; - public int flags() { return O_RDONLY; } - public InputStreamFD(InputStream is) { this.is = is; } + + public int flags() { + if(is != null && os != null) return O_RDWR; + if(is != null) return O_RDONLY; + if(os != null) return O_WRONLY; + throw new Error("should never happen"); + } + + public void _close() { + try {is.close(); } catch(IOException e) { /*ignore*/ } + try {os.close(); } catch(IOException e) { /*ignore*/ } + } + public int read(byte[] a, int off, int length) throws ErrnoException { + if(is == null) return super.read(a,off,length); try { int n = is.read(a,off,length); return n < 0 ? 0 : n; } catch(IOException e) { throw new ErrnoException(EIO); } + } + + public int write(byte[] a, int off, int length) throws ErrnoException { + if(os == null) return super.write(a,off,length); + try { + os.write(a,off,length); + return length; + } catch(IOException e) { + throw new ErrnoException(EIO); + } } - public void _close() { try { is.close(); } catch(IOException e) { /*ignore*/ } } + public FStat _fstat() { return new FStat(); } } - static class StdinFD extends InputStreamFD { - public StdinFD(InputStream is) { super(is); } - public void _close() { /* noop */ } - public FStat _fstat() { return new FStat() { public int type() { return S_IFCHR; } }; } - } - - static class StdoutFD extends OutputStreamFD { - public StdoutFD(OutputStream os) { super(os); } + static class TerminalFD extends InputOutputStreamFD { + public TerminalFD(InputStream is) { this(is,null); } + public TerminalFD(OutputStream os) { this(null,os); } + public TerminalFD(InputStream is, OutputStream os) { super(is,os); } public void _close() { /* noop */ } public FStat _fstat() { return new FStat() { public int type() { return S_IFCHR; } }; } } diff --git a/src/org/ibex/nestedvm/UnixRuntime.java b/src/org/ibex/nestedvm/UnixRuntime.java index 723af47..2b32965 100644 --- a/src/org/ibex/nestedvm/UnixRuntime.java +++ b/src/org/ibex/nestedvm/UnixRuntime.java @@ -3,6 +3,8 @@ package org.ibex.nestedvm; import org.ibex.nestedvm.util.*; import java.io.*; import java.util.*; +import java.net.Socket; +import java.net.ServerSocket; // FEATURE: vfork @@ -124,6 +126,9 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { case SYS_getdents: return sys_getdents(a,b,c,d); case SYS_unlink: return sys_unlink(a); case SYS_getppid: return sys_getppid(); + case SYS_opensocket: return sys_opensocket(a,b); + case SYS_listensocket: return sys_listensocket(a); + case SYS_accept: return sys_accept(a); default: return super._syscall(syscall,a,b,c,d); } @@ -519,6 +524,64 @@ public abstract class UnixRuntime extends Runtime implements Cloneable { return n; } + private static class SocketFD extends InputOutputStreamFD { + private final Socket s; + + public SocketFD(Socket s) throws IOException { + super(s.getInputStream(),s.getOutputStream()); + this.s = s; + } + + public void _close() { try { s.close(); } catch(IOException e) { } } + } + + public int sys_opensocket(int cstring, int port) throws FaultException, ErrnoException { + String hostname = cstring(cstring); + try { + FD fd = new SocketFD(new Socket(hostname,port)); + int n = addFD(fd); + if(n == -1) fd.close(); + return n; + } catch(IOException e) { + return -EIO; + } + } + + private static class ListenSocketFD extends FD { + ServerSocket s; + public ListenSocketFD(ServerSocket s) { this.s = s; } + public int flags() { return 0; } + // FEATURE: What should these be? + public FStat _fstat() { return new FStat(); } + public void _close() { try { s.close(); } catch(IOException e) { } } + } + + public int sys_listensocket(int port) { + try { + ListenSocketFD fd = new ListenSocketFD(new ServerSocket(port)); + int n = addFD(fd); + if(n == -1) fd.close(); + return n; + } catch(IOException e) { + return -EIO; + } + } + + public int sys_accept(int fdn) { + if(fdn < 0 || fdn >= OPEN_MAX) return -EBADFD; + if(fds[fdn] == null) return -EBADFD; + if(!(fds[fdn] instanceof ListenSocketFD)) return -EBADFD; + try { + ServerSocket s = ((ListenSocketFD)fds[fdn]).s; + SocketFD fd = new SocketFD(s.accept()); + int n = addFD(fd); + if(n == -1) fd.close(); + return n; + } catch(IOException e) { + return -EIO; + } + } + // FEATURE: Run through the fork/wait stuff one more time public static class GlobalState { protected static final int OPEN = 1; diff --git a/src/org/ibex/nestedvm/UsermodeConstants.java b/src/org/ibex/nestedvm/UsermodeConstants.java index 75ec440..b2bf093 100644 --- a/src/org/ibex/nestedvm/UsermodeConstants.java +++ b/src/org/ibex/nestedvm/UsermodeConstants.java @@ -50,6 +50,9 @@ public interface UsermodeConstants { public static final int SYS_usleep = 45; public static final int SYS_getppid = 46; public static final int SYS_mkfifo = 47; + public static final int SYS_opensocket = 48; + public static final int SYS_listensocket = 49; + public static final int SYS_accept = 50; public static final int EPERM = 1; /* Not super-user */ public static final int ENOENT = 2; /* No such file or directory */ public static final int ESRCH = 3; /* No such process */ diff --git a/src/org/ibex/nestedvm/support.s b/src/org/ibex/nestedvm/support.s index b436306..c2c4abd 100644 --- a/src/org/ibex/nestedvm/support.s +++ b/src/org/ibex/nestedvm/support.s @@ -136,3 +136,6 @@ SYSCALL_R(ftruncate) SYSCALL_R(usleep) SYSCALL(getppid) SYSCALL_R(mkfifo) +SYSCALL_R2(__open_socket_r,SYS_opensocket) +SYSCALL_R2(__listen_socket_r,SYS_listensocket) +SYSCALL_R2(__accept_r,SYS_accept) diff --git a/src/org/ibex/nestedvm/support_aux.c b/src/org/ibex/nestedvm/support_aux.c index 821769e..513434e 100644 --- a/src/org/ibex/nestedvm/support_aux.c +++ b/src/org/ibex/nestedvm/support_aux.c @@ -90,6 +90,9 @@ REENT_WRAPPER3(mknod,const char *,mode_t,dev_t) REENT_WRAPPER2(ftruncate,int,off_t) REENT_WRAPPER1(usleep,unsigned int) REENT_WRAPPER2(mkfifo,const char *, mode_t) +REENT_WRAPPER2(_open_socket,const char *,int) +REENT_WRAPPER1(_listen_socket,int) +REENT_WRAPPER1(_accept,int) extern int __execve_r(struct _reent *ptr, const char *path, char *const argv[], char *const envp[]); int _execve(const char *path, char *const argv[], char *const envp[]) { diff --git a/src/org/ibex/nestedvm/syscalls.h b/src/org/ibex/nestedvm/syscalls.h index a446886..d62bb2c 100644 --- a/src/org/ibex/nestedvm/syscalls.h +++ b/src/org/ibex/nestedvm/syscalls.h @@ -45,3 +45,6 @@ #define SYS_usleep 45 #define SYS_getppid 46 #define SYS_mkfifo 47 +#define SYS_opensocket 48 +#define SYS_listensocket 49 +#define SYS_accept 50 diff --git a/src/tests/Test.c b/src/tests/Test.c index 2c70026..c223d1c 100644 --- a/src/tests/Test.c +++ b/src/tests/Test.c @@ -101,6 +101,36 @@ int main(int argc, char **argv) { } else if(argc > 2 && strcmp(argv[1],"crashme") == 0) { volatile int *mem = (int*) atoi(argv[2]); *mem = 1; + } else if(argc > 2 && strcmp(argv[1],"get") == 0) { + extern int _open_socket(const char *host, int port); + fd = _open_socket(argv[2],80); + if(fd == -1) { perror("open_socket"); exit(EXIT_FAILURE); } +#define REQ "GET / HTTP/1.0\r\n\r\n" + n = write(fd,REQ,strlen(REQ)); + if(n != strlen(REQ)) { perror("write"); exit(EXIT_FAILURE); } + for(;;) { + n = read(fd,buf,sizeof(buf)); + if(n < 0) { perror("read"); exit(EXIT_FAILURE); } + if(n == 0) break; + write(1,buf,n); + } + } else if(argc > 1 && strcmp(argv[1],"server") == 0) { + extern int _listen_socket(int port); + extern int _accept(int fd); + + int server = _listen_socket(2000); + if(server< 0) { perror("server_socket"); exit(EXIT_FAILURE); } + while((fd = _accept(server)) >= 0) { + char buf2[1024]; + int n = read(fd,buf,sizeof(buf)); + if(n < 0) { perror("read"); continue; } + if(n == 0) continue; + while(n > 0 && (buf[n-1] == '\r' || buf[n-1] == '\n')) n--; + buf[n] = '\0'; + snprintf(buf2,sizeof(buf2),"Hello, %s from nestedvm's socket support\r\n",buf); + write(fd,buf2,strlen(buf2)); + close(fd); + } } else { printf("%d\n", 0xffffff); printf("%u\n", 0xffffffU);