socket support
authorbrian <brian@brianweb.net>
Mon, 10 May 2004 10:31:36 +0000 (03:31 -0700)
committerbrian <brian@brianweb.net>
Mon, 10 May 2004 10:31:36 +0000 (03:31 -0700)
darcs-hash:20040510103136-24bed-9bcd12582d26503f78703ca4e0caaac40c7d673f.gz

src/org/ibex/nestedvm/Runtime.java
src/org/ibex/nestedvm/UnixRuntime.java
src/org/ibex/nestedvm/UsermodeConstants.java
src/org/ibex/nestedvm/support.s
src/org/ibex/nestedvm/support_aux.c
src/org/ibex/nestedvm/syscalls.h
src/tests/Test.c

index a758a50..c501d0d 100644 (file)
@@ -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 <i>src</i> to <i>addr</i> 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; } }; }
     }
index 723af47..2b32965 100644 (file)
@@ -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;
index 75ec440..b2bf093 100644 (file)
@@ -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 */
index b436306..c2c4abd 100644 (file)
@@ -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)
index 821769e..513434e 100644 (file)
@@ -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[]) {
index a446886..d62bb2c 100644 (file)
@@ -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
index 2c70026..c223d1c 100644 (file)
@@ -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);