Implementing telnet server, fixes everywhere
authorJohn Hodge <[email protected]>
Mon, 30 Jan 2012 15:41:25 +0000 (23:41 +0800)
committerJohn Hodge <[email protected]>
Mon, 30 Jan 2012 15:41:25 +0000 (23:41 +0800)
- TCP Server wait fixes
- FIFO code was bug ridden

Kernel/binary.c
Kernel/drv/fifo.c
Kernel/syscalls.c
Kernel/vfs/select.c
Modules/IPStack/tcp.c
RunQemu
Usermode/Applications/telnetd_src/main.c
Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h
Usermode/Libraries/ld-acess.so_src/export.c

index b776fed..5213bf2 100644 (file)
@@ -178,7 +178,7 @@ int Proc_SysSpawn(const char *Binary, const char **ArgV, const char **EnvP, int
        
        // --- Save File, ArgV and EnvP
        size = Binary_int_CacheArgs( &Binary, &ArgV, &EnvP, NULL );
-       cachebuf = alloca( size );
+       cachebuf = malloc( size );
        Binary_int_CacheArgs( &Binary, &ArgV, &EnvP, cachebuf );
 
        // Cache the VFS handles        
@@ -190,6 +190,7 @@ int Proc_SysSpawn(const char *Binary, const char **ArgV, const char **EnvP, int
        {
                VFS_RestoreHandles(nFD, handles);
                VFS_FreeSavedHandles(nFD, handles);
+               // Frees cachebuf
                Proc_Execve(Binary, ArgV, EnvP, size);
                for(;;);
        }
index 4d3595b..0779a60 100644 (file)
@@ -1,6 +1,7 @@
 /* AcessOS
  * FIFO Pipe Driver
  */
+#define DEBUG  0
 #include <acess.h>
 #include <modules.h>
 #include <fs_devfs.h>
@@ -28,6 +29,7 @@ typedef struct sPipe {
 char   *FIFO_ReadDir(tVFS_Node *Node, int Id);
 tVFS_Node      *FIFO_FindDir(tVFS_Node *Node, const char *Filename);
  int   FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
+void   FIFO_Reference(tVFS_Node *Node);
 void   FIFO_Close(tVFS_Node *Node);
  int   FIFO_Relink(tVFS_Node *Node, const char *OldName, const char *NewName);
 Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
@@ -48,7 +50,8 @@ tVFS_NodeType gFIFO_PipeNodeType = {
        .TypeName = "FIFO Pipe Node",
        .Read = FIFO_Read,
        .Write = FIFO_Write,
-       .Close = FIFO_Close
+       .Close = FIFO_Close,
+       .Reference = FIFO_Reference
 };
 tDevFS_Driver  gFIFO_DriverInfo = {
        NULL, "fifo",
@@ -144,6 +147,13 @@ int FIFO_MkNod(tVFS_Node *Node, const char *Name, Uint Flags)
        return 0;
 }
 
+void FIFO_Reference(tVFS_Node *Node)
+{
+       if(!Node->ImplPtr)      return ;
+       
+       Node->ReferenceCount ++;
+}
+
 /**
  * \fn void FIFO_Close(tVFS_Node *Node)
  * \brief Close a FIFO end
@@ -159,6 +169,7 @@ void FIFO_Close(tVFS_Node *Node)
        pipe = Node->ImplPtr;
        
        if(strcmp(pipe->Name, "anon") == 0) {
+               Log_Debug("FIFO", "Pipe %p closed", Node->ImplPtr);
                free(Node->ImplPtr);
                return ;
        }
@@ -223,37 +234,44 @@ Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        tPipe   *pipe = Node->ImplPtr;
        Uint    len;
        Uint    remaining = Length;
-       
+
        if(!pipe)       return 0;
        
+       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+       
        while(remaining)
        {
                // Wait for buffer to fill
                if(pipe->Flags & PF_BLOCKING)
                {
-                       #if 0
-                       len = Semaphore_Wait( &pipe->Semaphore, remaining );
-                       #else
-                       VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "FIFO_Read");
-                       // Read buffer
-                       // TODO: Rethink this, it might not work on buffer overflow
-                       if(pipe->WritePos - pipe->ReadPos < remaining)
-                               len = pipe->WritePos - pipe->ReadPos;
-                       else
-                               len = remaining;
-                       #endif
+                       if( pipe->ReadPos == pipe->WritePos )
+                               VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "FIFO_Read");
+                       
                }
                else
                {
                        if(pipe->ReadPos == pipe->WritePos)
+                       {
+                               VFS_MarkAvaliable(Node, 0);
+                               LEAVE('i', 0);
                                return 0;
-                       // Read buffer
-                       if(pipe->WritePos - pipe->ReadPos < remaining)
-                               len = pipe->WritePos - pipe->ReadPos;
-                       else
-                               len = remaining;
+                       }
                }
-               
+       
+               len = remaining;
+               if( pipe->ReadPos < pipe->WritePos )
+               {
+                        int    avail_bytes = pipe->WritePos - pipe->ReadPos;
+                       if( avail_bytes < remaining )   len = avail_bytes;
+               }
+               else
+               {
+                        int    avail_bytes = pipe->WritePos + pipe->BufSize - pipe->ReadPos;
+                       if( avail_bytes < remaining )   len = avail_bytes;
+               }
+
+               LOG("len = %i, remaining = %i", len, remaining);                
+
                // Check if read overflows buffer
                if(len > pipe->BufSize - pipe->ReadPos)
                {
@@ -280,8 +298,13 @@ Uint64 FIFO_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
                remaining -= len;
                // Increment Buffer address
                Buffer = (Uint8*)Buffer + len;
+               
+               // TODO: Option to read differently
+               LEAVE('i', len);
+               return len;
        }
 
+       LEAVE('i', Length);
        return Length;
 
 }
@@ -297,25 +320,35 @@ Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buf
        Uint    remaining = Length;
        
        if(!pipe)       return 0;
+
+       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
        
        while(remaining)
        {
                // Wait for buffer to empty
                if(pipe->Flags & PF_BLOCKING) {
-                       #if 0
-                       len = Semaphore_Signal( &pipe->Semaphore, remaining );
-                       #else
-                       VFS_SelectNode(Node, VFS_SELECT_WRITE, NULL, "FIFO_Write");
-                       if(pipe->ReadPos - pipe->WritePos < remaining)
-                               len = pipe->ReadPos - pipe->WritePos;
+                       if( pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize )
+                               VFS_SelectNode(Node, VFS_SELECT_WRITE, NULL, "FIFO_Write");
+
+                       len = remaining;
+                       if( pipe->ReadPos > pipe->WritePos )
+                       {
+                                int    rem_space = pipe->ReadPos - pipe->WritePos;
+                               if(rem_space < remaining)       len = rem_space;
+                       }
                        else
-                               len = remaining;
-                       #endif
+                       {
+                                int    rem_space = pipe->ReadPos + pipe->BufSize - pipe->WritePos;
+                               if(rem_space < remaining)       len = rem_space;
+                       }
                }
                else
                {
                        if(pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize)
+                       {
+                               LEAVE('i', 0);
                                return 0;
+                       }
                        // Write buffer
                        if(pipe->ReadPos - pipe->WritePos < remaining)
                                len = pipe->ReadPos - pipe->WritePos;
@@ -351,6 +384,7 @@ Uint64 FIFO_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buf
                Buffer = (Uint8*)Buffer + len;
        }
 
+       LEAVE('i', Length);
        return Length;
 }
 
@@ -365,11 +399,10 @@ tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
         int    namelen = strlen(Name) + 1;
         int    allocsize = sizeof(tPipe) + sizeof(tVFS_ACL) + Size + namelen;
        
-       ret = malloc(allocsize);
+       ret = calloc(1, allocsize);
        if(!ret)        return NULL;
        
        // Clear Return
-       memset(ret, 0, allocsize);
        ret->Flags = PF_BLOCKING;
        
        // Allocate Buffer
@@ -383,6 +416,7 @@ tPipe *FIFO_Int_NewPipe(int Size, const char *Name)
        //Semaphore_Init( &ret->Semaphore, 0, Size, "FIFO", ret->Name );
        
        // Set Node
+       ret->Node.ReferenceCount = 1;
        ret->Node.Size = 0;
        ret->Node.ImplPtr = ret;
        ret->Node.UID = Threads_GetUID();
index e62ab06..5580187 100644 (file)
        if(!(v)||!Syscall_Valid((size),(v))){ret=-1;err=-EINVAL;break;}
 #define CHECK_STR_NONULL(v)    \
        if(!(v)||!Syscall_ValidString((v))){ret=-1;err=-EINVAL;break;}
+#define CHECK_STR_ARRAY(arr)   do {\
+        int    i;\
+       char    **tmp = (char**)arr; \
+       CHECK_NUM_NONULL( tmp, sizeof(char**) ); \
+       for(i=0;tmp[i];i++) { \
+               CHECK_STR_NONULL( tmp[i] ); \
+               CHECK_NUM_NONULL( &tmp[i+1], sizeof(char*) ); \
+       }\
+       if(tmp[i]) break;\
+} while(0)
 
 // === IMPORTS ===
 extern Uint    Binary_Load(const char *file, Uint *entryPoint);
@@ -148,46 +158,34 @@ void SyscallHandler(tSyscallRegs *Regs)
        // ---
        // Binary Control
        // ---
+       // -- Create a new process
+       case SYS_SPAWN:
+               CHECK_STR_NONULL((const char*)Regs->Arg1);
+               CHECK_STR_ARRAY((const char**)Regs->Arg2);
+               CHECK_STR_ARRAY((const char**)Regs->Arg3);
+               CHECK_NUM_NONULL((void*)Regs->Arg5, Regs->Arg4*sizeof(int));
+               ret = Proc_SysSpawn(
+                       (const char*)Regs->Arg1, (const char**)Regs->Arg2, (const char**)Regs->Arg3,
+                       Regs->Arg4, (int*)Regs->Arg5
+                       );
+               break;
        // -- Replace the current process with another
        case SYS_EXECVE:
                CHECK_STR_NONULL((char*)Regs->Arg1);
-               // Check the argument arrays
-               {
-                        int    i;
-                       char    **tmp = (char**)Regs->Arg2;
-                       // Check ArgV (traverse array checking all string pointers)
-                       CHECK_NUM_NONULL( tmp, sizeof(char**) );
-                       //Log("tmp = %p", tmp);
-                       for(i=0;tmp[i];i++) {
-                               CHECK_NUM_NONULL( &tmp[i], sizeof(char*) );
-                               CHECK_STR_NONULL( tmp[i] );
-                       }
-                       if(ret == -1) break;
-                       // Check EnvP also
-                       // - EnvP can be NULL
-                       if( Regs->Arg3 )
-                       {
-                               tmp = (char**)Regs->Arg3;
-                               CHECK_NUM_NONULL(tmp, sizeof(char**));
-                               for(i=0;tmp[i];i++) {
-                                       CHECK_NUM_NONULL( &tmp[i], sizeof(char*) );
-                                       CHECK_STR_NONULL( tmp[i] );
-                               }
-                               if(ret == -1) break;
-                       }
-               }
+               CHECK_STR_ARRAY( (char**)Regs->Arg2 );
+               if( Regs->Arg3 )
+                       CHECK_STR_ARRAY( (char**)Regs->Arg3 );
                LEAVE('s', "Assuming 0");
                // Path, **Argv, **Envp, DataSize (=0 to tell it to create a copy)
-               ret = Proc_Execve( (const char*)Regs->Arg1, (const char**)Regs->Arg2, (const char**)Regs->Arg3, 0 );
+               ret = Proc_Execve(
+                       (const char*)Regs->Arg1, (const char**)Regs->Arg2, (const char**)Regs->Arg3,
+                       0
+                       );
                break;
        // -- Load a binary into the current process
        case SYS_LOADBIN:
-               if( !Syscall_ValidString( (char*) Regs->Arg1)
-               ||  !Syscall_Valid(sizeof(Uint), (Uint*)Regs->Arg2) ) {
-                       err = -EINVAL;
-                       ret = 0;
-                       break;
-               }
+               CHECK_STR_NONULL( (char*)Regs->Arg1 );
+               CHECK_NUM_NONULL( (Uint*)Regs->Arg2, sizeof(Uint) );
                // Path, *Entrypoint
                ret = Binary_Load((char*)Regs->Arg1, (Uint*)Regs->Arg2);
                break;
@@ -251,7 +249,7 @@ void SyscallHandler(tSyscallRegs *Regs)
        // Open a file that is a entry in an open directory
        case SYS_OPENCHILD:
                CHECK_STR_NONULL( (char*)Regs->Arg2 );
-               ret = VFS_OpenChild( Regs->Arg1, (char*)Regs->Arg2, Regs->Arg3);
+               ret = VFS_OpenChild( Regs->Arg1, (char*)Regs->Arg2, Regs->Arg3 | VFS_OPENFLAG_USER);
                break;
        
        // Change Directory
index e8658ba..439afc0 100644 (file)
@@ -61,7 +61,7 @@ int VFS_SelectNode(tVFS_Node *Node, int TypeFlags, tTime *Timeout, const char *N
        tThread *thisthread = Proc_GetCurThread();
         int    ret, type;
        
-       ENTER("pNode iTypeFlags pTimeout", Node, TypeFlags, Timeout);
+       ENTER("pNode iTypeFlags pTimeout sName", Node, TypeFlags, Timeout, Name);
        
        // Initialise
        for( type = 0; type < 3; type ++ )
@@ -180,7 +180,7 @@ int VFS_MarkAvaliable(tVFS_Node *Node, BOOL IsDataAvaliable)
 // Mark a node as having a full buffer
 int VFS_MarkFull(tVFS_Node *Node, BOOL IsBufferFull)
 {
-       ENTER("pNode bIsDataAvaliable", Node, IsBufferFull);
+       ENTER("pNode bIsBufferFull", Node, IsBufferFull);
        Node->BufferFull = !!IsBufferFull;
        if( !Node->BufferFull )
                VFS_int_Select_SignalAll(Node->WriteThreads);
@@ -191,7 +191,7 @@ int VFS_MarkFull(tVFS_Node *Node, BOOL IsBufferFull)
 // Mark a node as errored
 int VFS_MarkError(tVFS_Node *Node, BOOL IsErrorState)
 {
-       ENTER("pNode bIsDataAvaliable", Node, IsErrorState);
+       ENTER("pNode bIsErrorState", Node, IsErrorState);
        Node->ErrorOccurred = !!IsErrorState;
        if( Node->ErrorOccurred )
                VFS_int_Select_SignalAll(Node->ErrorThreads);
index 1415dea..e9c3de9 100644 (file)
@@ -150,9 +150,9 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
        tTCPConnection  *conn;
 
        Log_Log("TCP", "TCP_GetPacket: <Local>:%i from [%s]:%i, Flags= %s%s%s%s%s%s%s%s",
-               ntohs(hdr->SourcePort),
-               IPStack_PrintAddress(Interface->Type, Address),
                ntohs(hdr->DestPort),
+               IPStack_PrintAddress(Interface->Type, Address),
+               ntohs(hdr->SourcePort),
                (hdr->Flags & TCP_FLAG_CWR) ? "CWR " : "",
                (hdr->Flags & TCP_FLAG_ECE) ? "ECE " : "",
                (hdr->Flags & TCP_FLAG_URG) ? "URG " : "",
@@ -199,7 +199,11 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
                                if(conn->RemotePort != ntohs(hdr->SourcePort))  continue;
 
                                // Check Source IP
-                               if( IPStack_CompareAddress(conn->Interface->Type, &conn->RemoteIP, Address, -1) != 0 )
+                               Log_Debug("TCP", "TCP_GetPacket: conn->RemoteIP(%s)",
+                                       IPStack_PrintAddress(conn->Interface->Type, &conn->RemoteIP));
+                               Log_Debug("TCP", "                == Address(%s)",
+                                       IPStack_PrintAddress(conn->Interface->Type, Address));
+                               if( IPStack_CompareAddress(conn->Interface->Type, &conn->RemoteIP, Address, -1) == 0 )
                                        continue ;
 
                                Log_Log("TCP", "TCP_GetPacket: Matches connection %p", conn);
@@ -256,6 +260,7 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe
                        srv->ConnectionsTail = conn;
                        if(!srv->NewConnections)
                                srv->NewConnections = conn;
+                       VFS_MarkAvaliable( &srv->Node, 1 );
                        SHORTREL(&srv->lConnections);
 
                        // Send the SYN ACK
@@ -828,7 +833,7 @@ tVFS_Node *TCP_Server_Init(tInterface *Interface)
 {
        tTCPListener    *srv;
        
-       srv = malloc( sizeof(tTCPListener) );
+       srv = calloc( 1, sizeof(tTCPListener) );
 
        if( srv == NULL ) {
                Log_Warning("TCP", "malloc failed for listener (%i) bytes", sizeof(tTCPListener));
@@ -878,7 +883,6 @@ char *TCP_Server_ReadDir(tVFS_Node *Node, int Pos)
                if( srv->NewConnections != NULL )       break;
                SHORTREL( &srv->lConnections );
                Threads_Yield();        // TODO: Sleep until poked
-               continue;
        }
        
 
@@ -886,6 +890,9 @@ char *TCP_Server_ReadDir(tVFS_Node *Node, int Pos)
        // normal list)
        conn = srv->NewConnections;
        srv->NewConnections = conn->Next;
+
+       if( srv->NewConnections == NULL )
+               VFS_MarkAvaliable( Node, 0 );
        
        SHORTREL( &srv->lConnections );
        
@@ -940,6 +947,13 @@ tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, const char *Name)
                        if(conn->Node.ImplInt == id)    break;
                }
                SHORTREL( &srv->lConnections );
+
+               // If not found, ret NULL
+               if(!conn) {
+                       LOG("Connection %i not found", id);
+                       LEAVE('n');
+                       return NULL;
+               }
        }
        // Empty Name - Check for a new connection and if it's there, open it
        else
@@ -948,16 +962,15 @@ tVFS_Node *TCP_Server_FindDir(tVFS_Node *Node, const char *Name)
                conn = srv->NewConnections;
                if( conn != NULL )
                        srv->NewConnections = conn->Next;
+               VFS_MarkAvaliable( Node, srv->NewConnections != NULL );
                SHORTREL( &srv->lConnections );
+               if( !conn ) {
+                       LOG("No new connections");
+                       LEAVE('n');
+                       return NULL;
+               }
        }
                
-       // If not found, ret NULL
-       if(!conn) {
-               LOG("Connection %i not found", id);
-               LEAVE('n');
-               return NULL;
-       }
-       
        // Return node
        LEAVE('p', &conn->Node);
        return &conn->Node;
diff --git a/RunQemu b/RunQemu
index a07a91b..10776d5 100755 (executable)
--- a/RunQemu
+++ b/RunQemu
@@ -31,6 +31,9 @@ while [ $# -ne 0 ]; do
                shift
                QEMU_PARAMS=$QEMU_PARAMS" "$1
                ;;
+       -fwd)
+               _NETTYPE=$_NETTYPE",hostfwd=tcp::10023-10.0.2.10:23"
+               ;;
        -tuntap)
                _NETTYPE="tap"
        esac
index 198ddaa..8a66ad7 100644 (file)
@@ -36,7 +36,13 @@ int main(int argc, char *argv[])
        gaClients = calloc(giConfig_MaxClients, sizeof(tClient));
 
        // Open server
-       giServerFD = Net_OpenSocket(0, NULL, "tcps");
+       {
+               uint8_t data[16];
+                int    addrtype = Net_ParseAddress("10.0.2.10", data);
+                int    port = 23;
+               giServerFD = Net_OpenSocket(addrtype, data, "tcps");
+               ioctl(giServerFD, 4, &port);    // Set port and start listening
+       }
 
        // Event loop
        EventLoop();
@@ -57,11 +63,15 @@ void EventLoop(void)
 
        for( ;; )
        {
+               FD_ZERO(&fds);
                maxfd = 0;
                // Fill select
                FD_SET_MAX(&fds, giServerFD, &maxfd);
                for( int i = 0; i < giConfig_MaxClients; i ++ )
                {
+                       if( gaClients[i].Socket == 0 )  continue ;
+                       _SysDebug("Socket = %i, stdout = %i",
+                               gaClients[i].Socket, gaClients[i].stdout);
                        FD_SET_MAX(&fds, gaClients[i].Socket, &maxfd);
                        FD_SET_MAX(&fds, gaClients[i].stdout,  &maxfd);
                }
@@ -112,16 +122,17 @@ void Server_NewClient(int FD)
        }
        // Accept the connection
        clt->Socket = _SysOpenChild(FD, "", O_RDWR);
-       giNumClients ++;        
+       giNumClients ++;
        
        // Create stdin/stdout
-       clt->stdin = open("/Devices/fifo", O_RDWR);
-       clt->stdout = open("/Devices/fifo", O_RDWR);
+       clt->stdin = open("/Devices/fifo/anon", O_RDWR);
+       clt->stdout = open("/Devices/fifo/anon", O_RDWR);
        
        // TODO: Arguments and envp
        {
                int fds[3] = {clt->stdin, clt->stdout, clt->stdout};
-               _SysSpawn("/Acess/SBin/login", NULL, NULL, 3, fds);
+               const char      *argv[] = {NULL};
+               _SysSpawn("/Acess/SBin/login", argv, argv, 3, fds);
        }
 }
 
@@ -131,6 +142,7 @@ void HandleServerBoundData(tClient *Client)
         int    len;
        
        len = read(Client->Socket, buf, BUFSIZ);
+       if( len <= 0 )  return ;
        write(Client->stdin, buf, len);
 }
 
@@ -140,6 +152,7 @@ void HandleClientBoundData(tClient *Client)
         int    len;
        
        len = read(Client->stdout, buf, BUFSIZ);
+       if( len <= 0 )  return ;
        write(Client->Socket, buf, len);
 }
 
index b27fa71..cd20d80 100644 (file)
@@ -24,7 +24,7 @@ SYSCALL1(SysSetPri, SYS_SETPRI)
 SYSCALL3(SysSendMessage, SYS_SENDMSG)
 SYSCALL3(SysGetMessage, SYS_GETMSG)
 
-SYSCALL3(SysSpawn, SYS_SPAWN)
+SYSCALL5(_SysSpawn, SYS_SPAWN)
 SYSCALL3(execve, SYS_EXECVE)
 SYSCALL2(SysLoadBin, SYS_LOADBIN)
 SYSCALL1(SysUnloadBin, SYS_UNLOADBIN)
index 5e614e1..41ba01f 100644 (file)
@@ -45,7 +45,7 @@ const struct {
        EXP(SysSendMessage),
        EXP(SysGetMessage),
 
-       //EXP(SysSpawn),
+       EXP(_SysSpawn),
        EXP(execve),
        EXP(SysLoadBin),
        EXP(SysUnloadBin),

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