From: John Hodge Date: Mon, 30 Jan 2012 15:41:25 +0000 (+0800) Subject: Implementing telnet server, fixes everywhere X-Git-Tag: rel0.15~792^2~3 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;ds=sidebyside;h=30c11f371da98d13344e8bed3766d3e574a65ac9;p=tpg%2Facess2.git Implementing telnet server, fixes everywhere - TCP Server wait fixes - FIFO code was bug ridden --- diff --git a/Kernel/binary.c b/Kernel/binary.c index b776fed0..5213bf2d 100644 --- a/Kernel/binary.c +++ b/Kernel/binary.c @@ -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(;;); } diff --git a/Kernel/drv/fifo.c b/Kernel/drv/fifo.c index 4d3595b7..0779a60b 100644 --- a/Kernel/drv/fifo.c +++ b/Kernel/drv/fifo.c @@ -1,6 +1,7 @@ /* AcessOS * FIFO Pipe Driver */ +#define DEBUG 0 #include #include #include @@ -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(); diff --git a/Kernel/syscalls.c b/Kernel/syscalls.c index e62ab067..5580187d 100644 --- a/Kernel/syscalls.c +++ b/Kernel/syscalls.c @@ -20,6 +20,16 @@ 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 diff --git a/Kernel/vfs/select.c b/Kernel/vfs/select.c index e8658bac..439afc02 100644 --- a/Kernel/vfs/select.c +++ b/Kernel/vfs/select.c @@ -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); diff --git a/Modules/IPStack/tcp.c b/Modules/IPStack/tcp.c index 1415deaa..e9c3de98 100644 --- a/Modules/IPStack/tcp.c +++ b/Modules/IPStack/tcp.c @@ -150,9 +150,9 @@ void TCP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffe tTCPConnection *conn; Log_Log("TCP", "TCP_GetPacket: :%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 a07a91ba..10776d54 100755 --- 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 diff --git a/Usermode/Applications/telnetd_src/main.c b/Usermode/Applications/telnetd_src/main.c index 198ddaaf..8a66ad7a 100644 --- a/Usermode/Applications/telnetd_src/main.c +++ b/Usermode/Applications/telnetd_src/main.c @@ -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); } diff --git a/Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h b/Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h index b27fa71e..cd20d801 100644 --- a/Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h +++ b/Usermode/Libraries/ld-acess.so_src/arch/syscalls.s.h @@ -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) diff --git a/Usermode/Libraries/ld-acess.so_src/export.c b/Usermode/Libraries/ld-acess.so_src/export.c index 5e614e1e..41ba01f9 100644 --- a/Usermode/Libraries/ld-acess.so_src/export.c +++ b/Usermode/Libraries/ld-acess.so_src/export.c @@ -45,7 +45,7 @@ const struct { EXP(SysSendMessage), EXP(SysGetMessage), - //EXP(SysSpawn), + EXP(_SysSpawn), EXP(execve), EXP(SysLoadBin), EXP(SysUnloadBin),