AcessNative - TCP emulation working
authorJohn Hodge <[email protected]>
Thu, 28 Nov 2013 05:48:41 +0000 (13:48 +0800)
committerJohn Hodge <[email protected]>
Thu, 28 Nov 2013 05:48:41 +0000 (13:48 +0800)
- Cleanup is lacking, but Rx/Tx works

AcessNative/acesskernel_src/Makefile
AcessNative/acesskernel_src/include/arch.h
AcessNative/acesskernel_src/net.c
AcessNative/acesskernel_src/net_wrap.c
AcessNative/acesskernel_src/net_wrap.h
AcessNative/acesskernel_src/threads_glue.c

index f831a43..00ba775 100644 (file)
@@ -14,6 +14,7 @@ endif
 KERNEL_SRC = ../../KernelLand/Kernel/\r
 LDACESS_SRC = ../../Usermode/Libraries/ld-acess.so_src/\r
 \r
+# - Kernel objects (from KernelLand/Kernel)\r
 KERNEL_OBJ := logging.o adt.o lib.o debug.o messages.o drvutil_disk.o drvutil_video.o\r
 KERNEL_OBJ += mutex.o semaphore.o rwlock.o workqueue.o events.o\r
 #KERNEL_OBJ += libc.o\r
@@ -24,16 +25,16 @@ KERNEL_OBJ += drv/fifo.o drv/proc.o drv/dgram_pipe.o
 KERNEL_OBJ += drv/vterm.o drv/vterm_font.o drv/vterm_output.o drv/vterm_input.o drv/vterm_termbuf.o\r
 KERNEL_OBJ += drv/vterm_vt100.o drv/vterm_2d.o\r
 KERNEL_OBJ += drv/pty.o\r
-\r
-N_OBJ := main.o\r
+# - Native (unsullied) objects\r
+N_OBJ := main.o net_wrap.o\r
+# - Local objects (use the kernel includes)\r
+OBJ := helpers.o threads.o threads_glue.o server.o syscalls.o time.o\r
+OBJ += video.o keyboard.o mouse.o nativefs.o vfs_handle.o ui_sdl.o\r
+OBJ += net.o\r
 \r
 BUILDINFO_OBJ := obj-$(PLATFORM)/buildinfo.o\r
 BUILDINFO_SRC := $(BUILDINFO_OBJ:%.o=%.c)\r
 \r
-OBJ := helpers.o threads.o threads_glue.o server.o syscalls.o time.o\r
-OBJ += video.o keyboard.o mouse.o nativefs.o vfs_handle.o ui_sdl.o\r
-OBJ += net.o net_wrap.o\r
-\r
 OBJ := $(addprefix obj-$(PLATFORM)/,$(OBJ))\r
 N_OBJ := $(addprefix obj-$(PLATFORM)/,$(N_OBJ))\r
 K_OBJ := $(addprefix $(KERNEL_SRC)obj-native-$(PLATFORM)/,$(KERNEL_OBJ))\r
index 1e2be70..ab27de1 100644 (file)
@@ -40,10 +40,11 @@ struct sShortSpinlock
 
 extern void    Threads_int_ShortLock(void **Ptr);
 extern void    Threads_int_ShortRel(void **Ptr);
+extern int     Threads_int_ShortHas(void **Ptr);
 
 #define SHORTLOCK(l)   Threads_int_ShortLock(&(l)->Mutex)
 #define SHORTREL(l)    Threads_int_ShortRel(&(l)->Mutex)
-#define CPU_HAS_LOCK(...)      0
+#define CPU_HAS_LOCK(l)        Threads_int_ShortHas(&(l)->Mutex)
 
 //#define      NUM_CFG_ENTRIES 10
 
index 1f0f977..940827e 100644 (file)
@@ -63,6 +63,7 @@ tVFS_Node     gNet_Node_Routes = {
 int Net_Install(char **Arguments)
 {
        DevFS_AddDevice(&gNet_DevInfo);
+       Net_Wrap_Init();
        return 0;
 }
 
@@ -154,7 +155,7 @@ int Net_TCPC_IOCtl(tVFS_Node *Node, int IOCtl, void *Data)
        case 7: // Connect
                Node->Data = Net_Wrap_ConnectTcp(Node, tcpc->SrcPort, tcpc->DstPort,
                        tcpc->AddrType, tcpc->DestAddr);
-               return (Node->Data == NULL);
+               return (Node->Data != NULL);
        case 8:
                Debug("TODO: TCPC rx buffer length");
                return -1;
index 0b22e77..730eda0 100644 (file)
  * net.c
  * - Networking
  */
+#define DEBUG  1
+#include <stdlib.h>
 #include <unistd.h>
-#include <logdebug.h>
+#include "../../KernelLand/Kernel/include/logdebug.h"
 #include "net_wrap.h"
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <sys/eventfd.h>
+#include <poll.h>
+
+#include <SDL/SDL.h>   // for worker
 
 typedef struct sNetSocket      tNetSocket;
 
 struct sNetSocket
 {
        tNetSocket      *Next;
+       tNetSocket      *Prev;
+       void    *Node;
         int    FD;
+       char    bSkipRead;
+       char    bSkipWrite;
+       char    bSkipError;
 };
 
+
+ int   Net_Wrap_WatcherThread(void *arg);
+
+ int   gNet_Wrap_EventFD;
 tNetSocket     *gNet_Wrap_FirstSocket;
 tNetSocket     *gNet_Wrap_LastSocket;
+SDL_Thread     *gNet_Wrap_SelectChecker;
 
 // === CODE ===
-void *Net_Wrap_ConnectTcp(void *Node, short SrcPort, short DstPtr, int Type, const void *Addr)
+void Net_Wrap_Init(void)
 {
-       return NULL;
+       gNet_Wrap_EventFD = eventfd(0, 0);
+       gNet_Wrap_SelectChecker = SDL_CreateThread( Net_Wrap_WatcherThread, NULL );
+}
+
+static inline void Net_Wrap_ProdWatcher(void)
+{
+       uint64_t val = 1;
+       write(gNet_Wrap_EventFD, &val, sizeof(val));
+}
+
+int Net_Wrap_WatcherThread(void *arg)
+{
+       for(;;)
+       {
+                int    maxfd = gNet_Wrap_EventFD;
+               fd_set  rfds, wfds, efds;
+               FD_ZERO(&rfds);
+               FD_ZERO(&wfds);
+               FD_ZERO(&efds);
+               // Event FD used to wake this thread when the list changes
+               FD_SET(gNet_Wrap_EventFD, &rfds);
+               // Populate socket FDs
+               for( tNetSocket *s = gNet_Wrap_FirstSocket; s; s = s->Next )
+               {
+                       if( s->FD > maxfd )
+                               maxfd = s->FD;
+                       if( !s->bSkipRead )     FD_SET(s->FD, &rfds);
+                       if( !s->bSkipWrite )    FD_SET(s->FD, &wfds);
+                       if( !s->bSkipError )    FD_SET(s->FD, &efds);
+               }
+       
+               LOG("select(%i+1, ...)", maxfd);
+               int rv = select(maxfd+1, &rfds, &wfds, &efds, NULL);
+               LOG("rv = %i");
+               if( rv <= 0 )
+                       continue ;
+
+               if( FD_ISSET(gNet_Wrap_EventFD, &rfds) )
+               {
+                       uint64_t        val;
+                       read(gNet_Wrap_EventFD, &val, 8);
+               }       
+
+               for( tNetSocket *s = gNet_Wrap_FirstSocket; s; s = s->Next )
+               {
+                       if( FD_ISSET(s->FD, &rfds) ) {
+                               VFS_MarkAvaliable(s->Node, 1);
+                               s->bSkipRead = 1;
+                       }
+                       if( FD_ISSET(s->FD, &wfds) ) {
+                               VFS_MarkFull(s->Node, 0);
+                               s->bSkipWrite = 1;
+                       }
+                       if( FD_ISSET(s->FD, &efds) ) {
+                               VFS_MarkError(s->Node, 1);
+                               s->bSkipError = 1;      // TODO: how will err be acked?
+                       }
+               }
+       }
+}
+
+void *Net_Wrap_ConnectTcp(void *Node, short SrcPort, short DstPort, int Type, const void *Addr)
+{
+       struct sockaddr_in      addr4;
+       struct sockaddr *addr;
+       socklen_t       addr_size;
+       
+        int    af;
+       switch(Type)
+       {
+       case 4:
+               af = AF_INET;
+               addr = (struct sockaddr*)&addr4;
+               addr_size = sizeof(addr4);
+               memset(addr, 0, addr_size);
+               LOG("%02x%02x%02x%02x",
+                       ((uint8_t*)Addr)[0], ((uint8_t*)Addr)[1],
+                       ((uint8_t*)Addr)[2], ((uint8_t*)Addr)[3]);
+               memcpy(&addr4.sin_addr, Addr, 4);
+               //addr4.sin_addr.s_addr = htonl( addr4.sin_addr.s_addr);
+               addr4.sin_port = htons(DstPort);
+               break;
+       //case 6:       af = AF_INET6;  break;
+       default:
+               return NULL;
+       }       
+       
+       addr->sa_family = af;
+
+       int fd = socket(af, SOCK_STREAM, 0);
+       if( SrcPort ) {
+               Log_Warning("NetWrap", "TODO: Support setting TCP source port");
+       }
+       Debug_HexDump("NetWrap: addr=", addr, addr_size);
+       if( connect(fd, addr, addr_size) ) {
+               close(fd);
+               Log_Notice("NetWrap", "connect() failed: %s", strerror(errno));
+               char tmp[64] = {0};
+               inet_ntop(af, addr->sa_data+2, tmp, sizeof(tmp));
+               printf("addr = %p %s\n", tmp, tmp);
+               return NULL;
+       }
+       
+       tNetSocket      *ret = malloc( sizeof(tNetSocket) );
+       if(!ret) {
+               close(fd);
+               return NULL;
+       }
+       
+       ret->Next = NULL;
+       ret->Node = Node;
+       ret->FD = fd;
+       ret->bSkipRead = 0;
+       ret->bSkipWrite = 0;
+       ret->bSkipError = 0;
+
+       if( gNet_Wrap_FirstSocket ) {
+               gNet_Wrap_LastSocket->Next = ret;
+               ret->Prev = gNet_Wrap_LastSocket;
+       }
+       else {
+               gNet_Wrap_FirstSocket = ret;
+               ret->Prev = NULL;
+       }
+       gNet_Wrap_LastSocket = ret;
+
+       Net_Wrap_ProdWatcher(); 
+
+       return ret;
+}
+
+static void Net_Wrap_UpdateFlags(tNetSocket *hdl)
+{
+       struct pollfd fdinfo = {.fd = hdl->FD, .events=POLLIN|POLLOUT, .revents=0};
+       
+       poll(&fdinfo, 1, 0);
+       
+       VFS_MarkAvaliable(hdl->Node, !!(fdinfo.revents & POLLIN));
+       VFS_MarkFull(hdl->Node, !(fdinfo.revents & POLLOUT));
+
+       // If no data can be written, re-enable select  
+       if( !(fdinfo.revents & POLLOUT) )
+               hdl->bSkipWrite = 0;
+       // Same for if no data to read
+       if( !(fdinfo.revents & POLLIN) )
+               hdl->bSkipRead = 0;
+       
+       Net_Wrap_ProdWatcher(); 
 }
 
 size_t Net_Wrap_ReadSocket(void *Handle, size_t Bytes, void *Dest)
 {
        tNetSocket      *hdl = Handle;
        if(!hdl)        return -1;
-       return read(hdl->FD, Dest, Bytes);
+       size_t rv = read(hdl->FD, Dest, Bytes);
+       Net_Wrap_UpdateFlags(hdl);      
+       return rv;
 }
 
 size_t Net_Wrap_WriteSocket(void *Handle, size_t Bytes, const void *Dest)
 {
        tNetSocket      *hdl = Handle;
        if(!hdl)        return -1;
-       return write(hdl->FD, Dest, Bytes);
+       size_t rv = write(hdl->FD, Dest, Bytes);
+       Net_Wrap_UpdateFlags(hdl);      
+       return rv;
 }
 
 void Net_Wrap_CloseSocket(void *Handle)
 {
-       // TODO
+       tNetSocket      *hdl = Handle;
+
+       // TODO: Lock
+       if(hdl->Prev)
+               hdl->Prev->Next = hdl->Next;
+       else 
+               gNet_Wrap_FirstSocket = hdl->Next;
+       if(hdl->Next)
+               hdl->Next->Prev = hdl->Prev;
+       else
+               gNet_Wrap_LastSocket = hdl->Prev;       
+       Net_Wrap_ProdWatcher(); 
+
+       close(hdl->FD);
+       free(hdl);
 }
 
index 8d655d2..73dfc99 100644 (file)
@@ -2,6 +2,7 @@
 #ifndef _NET_WRAP_H_
 #define _NET_WRAP_H_
 
+extern void    Net_Wrap_Init(void);
 extern void    *Net_Wrap_ConnectTcp(void *Node, short SrcPort, short DstPtr, int Type, const void *Addr);
 extern size_t  Net_Wrap_ReadSocket(void *Handle, size_t Bytes, void *Dest);
 extern size_t  Net_Wrap_WriteSocket(void *Handle, size_t Bytes, const void *Dest);
index c2efb71..fa83980 100644 (file)
@@ -21,6 +21,7 @@ typedef void  **tShortSpinlock;
 
 #define NORETURN       __attribute__((noreturn))
 #include <logdebug.h>  // Kernel land, but uses standards
+#include <errno.h>
 
 // === CODE ===
 void Threads_Glue_Yield(void)
@@ -82,9 +83,15 @@ void Threads_int_ShortLock(void **MutexPtr)
 {
        if( !*MutexPtr ) {
                *MutexPtr = malloc( sizeof(pthread_mutex_t) );
+               pthread_mutexattr_t     attr;
+               pthread_mutexattr_init(&attr);
+               pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
                pthread_mutex_init(*MutexPtr, NULL);
        }
-       pthread_mutex_lock(*MutexPtr);
+       if( pthread_mutex_lock(*MutexPtr) ) {
+               fprintf(stderr, "ERROR: Mutex pointer %p double locked\n", MutexPtr);
+               AcessNative_Exit();
+       }
 }
 
 void Threads_int_ShortRel(void **MutexPtr)
@@ -92,4 +99,18 @@ void Threads_int_ShortRel(void **MutexPtr)
        pthread_mutex_unlock(*MutexPtr);
 }
 
+int Threads_int_ShortHas(void **Ptr)
+{
+       if( !*Ptr )
+               return 0;
+       int rv = pthread_mutex_trylock(*Ptr);
+       if( rv == 0 ) {
+               pthread_mutex_unlock(*Ptr);
+               return 0;
+       }
+       if( rv == EBUSY ) {
+               return 0;
+       }
+       return 1;
+}
 

UCC git Repository :: git.ucc.asn.au