Composite commit (GUI / Networking)
authorJohn Hodge <[email protected]>
Sat, 6 Nov 2010 11:14:50 +0000 (19:14 +0800)
committerJohn Hodge <[email protected]>
Sat, 6 Nov 2010 11:14:50 +0000 (19:14 +0800)
- GUI Work, just fiddling with getting images supported
- Networking:
 > libnet being built for networking helpers
 > IPStack is being partially reworked to support routes and more versatile
   naming of interfaces (with the ultimate goal of removing integer names)
 > Basic IRC client in the works (testing the networking stack with it)
- Other Changes:
 > Cleanups to library code (implemented snprintf in libc)
 > Improved debugging and thread status naming in threads.c

21 files changed:
Kernel/include/threads.h
Kernel/lib.c
Kernel/threads.c
Modules/IPStack/ipstack.h
Modules/IPStack/main.c
Modules/IPStack/routing.c [new file with mode: 0644]
Modules/IPStack/tcp.c
Usermode/Applications/axwin2_src/WM/common.h
Usermode/Applications/axwin2_src/WM/decorator.c
Usermode/Applications/axwin2_src/WM/interface.c
Usermode/Applications/axwin2_src/WM/video.c
Usermode/Applications/axwin2_src/WM/wm.c
Usermode/Applications/irc_src/Makefile [new file with mode: 0644]
Usermode/Applications/irc_src/main.c [new file with mode: 0644]
Usermode/Libraries/libc.so_src/fileIO.c
Usermode/Libraries/libimage_sif.so_src/main.c
Usermode/Libraries/libnet.so_src/Makefile [new file with mode: 0644]
Usermode/Libraries/libnet.so_src/address.c [new file with mode: 0644]
Usermode/Libraries/libnet.so_src/net.h [new file with mode: 0644]
Usermode/include/net.h [new symlink]
Usermode/include/stdio.h

index 833a3c7..2b8f9fb 100644 (file)
@@ -76,8 +76,20 @@ enum {
        THREAD_STAT_MUTEXSLEEP, // Mutex Sleep
        THREAD_STAT_WAITING,    // ??? (Waiting for a thread)
        THREAD_STAT_PREINIT,    // Being created
-       THREAD_STAT_ZOMBIE,     // Died, just not removed
-       THREAD_STAT_DEAD        // Why do we care about these???
+       THREAD_STAT_ZOMBIE,     // Died/Killed, but parent not informed
+       THREAD_STAT_DEAD,       // Awaiting burial (free)
+       THREAD_STAT_BURIED      // If it's still on the list here, something's wrong
+};
+static const char * const casTHREAD_STAT[] = {
+       "THREAD_STAT_NULL",
+       "THREAD_STAT_ACTIVE",
+       "THREAD_STAT_SLEEPING",
+       "THREAD_STAT_MUTEXSLEEP",
+       "THREAD_STAT_WAITING",
+       "THREAD_STAT_PREINIT",
+       "THREAD_STAT_ZOMBIE",
+       "THREAD_STAT_DEAD",
+       "THREAD_STAT_BURIED"
 };
 
 enum eFaultNumbers
index 3a4f31f..66c9660 100644 (file)
@@ -477,7 +477,7 @@ char *strdup(const char *Str)
        strcpy(ret, Str);
        return ret;
 }
-#endif
+#else
 
 /**
  * \fn char *_strdup(const char *File, int Line, const char *Str)
@@ -491,6 +491,7 @@ char *_strdup(const char *File, int Line, const char *Str)
        strcpy(ret, Str);
        return ret;
 }
+#endif
 
 /**
  * \brief Split a string using the passed character
index dd4f0d2..b76fe59 100644 (file)
@@ -865,7 +865,7 @@ void Threads_Dump(void)
        {
                Log(" %i (%i) - %s (CPU %i)",
                        thread->TID, thread->TGID, thread->ThreadName, thread->CurCPU);
-               Log("  State %i", thread->Status);
+               Log("  State %i (%s)", thread->Status, casTHREAD_STAT[thread->Status]);
                switch(thread->Status)
                {
                case THREAD_STAT_MUTEXSLEEP:
@@ -909,7 +909,7 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last)
                thread = gDeleteThreads->Next;
                if( IS_LOCKED(&gDeleteThreads->IsLocked) ) {    // Only free if structure is unused
                        // Set to dead
-                       gDeleteThreads->Status = THREAD_STAT_DEAD;
+                       gDeleteThreads->Status = THREAD_STAT_BURIED;
                        // Free name
                        if( IsHeap(gDeleteThreads->ThreadName) )
                                free(gDeleteThreads->ThreadName);
index 4395394..20f645c 100644 (file)
@@ -17,6 +17,12 @@ typedef struct sSocketFile   tSocketFile;
 
 typedef void   (*tIPCallback)(tInterface *Interface, void *Address, int Length, void *Buffer);
 
+enum eInterfaceTypes {
+       AF_NULL,
+       AF_INET4 = 4,   // tIPv4
+       AF_INET6 = 6    // tIPv6
+};
+
 union uIPv4 {
        Uint32  L;
        Uint8   B[4];
@@ -38,6 +44,8 @@ struct sInterface {
        tAdapter        *Adapter;
         int    TimeoutDelay;   // Time in miliseconds before a packet times out
         int    Type;   // 0 for disabled, 4 for IPv4 and 6 for IPv6
+       
+       //TODO: Remove explicit mentions of IPv4/IPv6 and make more general
        union {
                struct  {
                        tIPv6   Address;
@@ -96,5 +104,6 @@ static const tMacAddr cMAC_BROADCAST = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};
 #define ntohl(v)       BigEndian32(v)
 
 extern int     IPStack_AddFile(tSocketFile *File);
+extern int     IPStack_GetAddressSize(int AddressType);
 
 #endif
index fe4bf0f..0deaf3a 100644 (file)
@@ -30,6 +30,7 @@ extern int    IPv6_Initialise();
 char   *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos);
 tVFS_Node      *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name);
  int   IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data);
  int   IPStack_AddInterface(char *Device);
 tAdapter       *IPStack_GetAdapter(char *Path);
 char   *IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos);
@@ -51,6 +52,21 @@ tDevFS_Driver        gIP_DriverInfo = {
        }
 };
 tShortSpinlock glIP_Interfaces;
+//! Loopback (127.0.0.0/8, ::1) Pseudo-Interface
+tInterface     gIP_LoopInterface = {
+       Node: {
+               ImplPtr: &gIP_LoopInterface,
+               Flags: VFS_FFLAG_DIRECTORY,
+               Size: -1,
+               NumACLs: 1,
+               ACLs: &gVFS_ACL_EveryoneRX,
+               ReadDir: IPStack_Iface_ReadDir,
+               FindDir: IPStack_Iface_FindDir,
+               IOCtl: IPStack_Iface_IOCtl
+       },
+       Adapter: NULL,
+       Type: 0
+};
 tInterface     *gIP_Interfaces = NULL;
 tInterface     *gIP_Interfaces_Last = NULL;
  int   giIP_NextIfaceId = 1;
@@ -67,12 +83,11 @@ int IPStack_Install(char **Arguments)
 {
         int    i = 0;
        
-       // Layer 2 - Data Link Layer
+       // Layer 3 - Network Layer Protocols
        ARP_Initialise();
-       // Layer 3 - Network Layer
        IPv4_Initialise();
        IPv6_Initialise();
-       // Layer 4 - Transport Layer
+       // Layer 4 - Transport Layer Protocols
        TCP_Initialise();
        UDP_Initialise();
        
@@ -81,12 +96,19 @@ int IPStack_Install(char **Arguments)
                // Parse module arguments
                for( i = 0; Arguments[i]; i++ )
                {
-                       //if(strcmp(Arguments[i], "Device") == '=') {
-                       //      
-                       //}
+                       // TODO:
+                       // Define interfaces by <Device>,<Type>,<HexStreamAddress>,<Bits>
+                       // Where:
+                       // - <Device> is the device path (E.g. /Devices/ne2k/0)
+                       // - <Type> is a number (e.g. 4) or symbol (e.g. AF_INET4)
+                       // - <HexStreamAddress> is a condensed hexadecimal stream (in big endian)
+                       //      (E.g. 0A000201 for 10.0.2.1 IPv4)
+                       // - <Bits> is the number of subnet bits (E.g. 24 for an IPv4 Class C)
                }
        }
        
+       gIP_LoopInterface.Adapter = IPStack_GetAdapter("/Devices/fifo/anon");
+       
        DevFS_AddDevice( &gIP_DriverInfo );
        
        return MODULE_ERR_OK;
@@ -112,6 +134,17 @@ char *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos)
        char    *name;
        ENTER("pNode iPos", Node, Pos);
        
+
+       // Routing Subdir
+       if( Pos == 0 ) {
+               return strdup("routes");
+       }
+       // Pseudo Interfaces
+       if( Pos == 1 ) {
+               return strdup("lo");
+       }
+       Pos -= 2;
+       
        // Traverse the list
        for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ;
        
@@ -161,6 +194,16 @@ tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name)
        
        ENTER("pNode sName", Node, Name);
        
+       // Routing subdir
+       if( strcmp(Name, "routes") == 0 ) {
+               return &gIP_RouteNode;
+       }
+       
+       // Loopback
+       if( strcmp(Name, "lo") == 0 ) {
+               return &gIP_LoopInterface.Node;
+       }
+       
        i = 0;  num = 0;
        while('0' <= Name[i] && Name[i] <= '9')
        {
@@ -222,7 +265,10 @@ int IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data)
        case 4:
                if( Threads_GetUID() != 0 )     LEAVE_RET('i', -1);
                if( !CheckString( Data ) )      LEAVE_RET('i', -1);
-               tmp = IPStack_AddInterface(Data);
+               {
+                       char    name[4] = "";
+                       tmp = IPStack_AddInterface(Data, name);
+               }
                LEAVE_RET('i', tmp);
        }
        LEAVE('i', 0);
@@ -513,7 +559,7 @@ int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data)
  * \fn int IPStack_AddInterface(char *Device)
  * \brief Adds an interface to the list
  */
-int IPStack_AddInterface(char *Device)
+int IPStack_AddInterface(const char *Device, const char *Name)
 {
        tInterface      *iface;
        tAdapter        *card;
@@ -522,7 +568,7 @@ int IPStack_AddInterface(char *Device)
        
        card = IPStack_GetAdapter(Device);
        
-       iface = malloc(sizeof(tInterface));
+       iface = malloc(sizeof(tInterface) + strlen(Name));
        if(!iface) {
                LEAVE('i', -2);
                return -2;      // Return ERR_MYBAD
@@ -652,3 +698,20 @@ tAdapter *IPStack_GetAdapter(char *Path)
        LEAVE('p', dev);
        return dev;
 }
+
+/**
+ * \brief Gets the size (in bytes) of a specified form of address
+ */
+int IPStack_GetAddressSize(int AddressType)
+{
+       switch(AddressType)
+       {
+       default:
+       case AF_NULL:
+               return 0;
+       case AF_INET4:
+               return sizeof(tIPv4);
+       case AF_INET6:
+               return sizeof(tIPv6);
+       }
+}
diff --git a/Modules/IPStack/routing.c b/Modules/IPStack/routing.c
new file mode 100644 (file)
index 0000000..9678ada
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Acess2 IP Stack
+ * - Routing Tables
+ */
+#include "ipstack.h"
+#include "link.h"
+
+
+// === TYPES ===
+typedef struct sRoute {
+       struct sRoute   *Next;
+       tVFS_Node       Node;
+       
+        int    AddressType;    // 0: Invalid, 4: IPv4, 6: IPv4
+       void    *Network;       // Pointer to tIPv4/tIPv6/... at end of structure
+        int    SubnetBits;
+       void    *NextHop;       // Pointer to tIPv4/tIPv6/... at end of structure
+       tInterface      *Interface;
+}      tRoute;
+
+// === PROTOTYPES ===
+// - Routes directory
+char   *IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos);
+tVFS_Node      *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name);
+ int   IPStack_RouteDir_IOCtl(tVFS_Node *Node, int ID, void *Data);
+ int   IPStack_Route_Create(const char *InterfaceName);
+// - Individual Routes
+Uint64 IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data);
+
+
+// === GLOBALS ===
+ int   giIP_NextRouteId = 1;
+tRoute *gIP_Routes;
+tRoute *gIP_RoutesEnd;
+tVFS_Node      gIP_RouteNode = {
+       Flags: VFS_FFLAG_DIRECTORY,
+       Size: -1,
+       NumACLs: 1,
+       ACLs: &gVFS_ACL_EveryoneRX,
+       ReadDir: IPStack_RouteDir_ReadDir,
+       FindDir: IPStack_RouteDir_FindDir,
+       IOCtl: IPStack_RouteDir_IOCtl
+};
+
+// === CODE ===
+/**
+ * \brief ReadDir for the /Devices/ip/routes/ directory
+ */
+char *IPStack_RouteDir_ReadDir(tVFS_Node *Node, int Pos)
+{
+       tRoute  *rt;
+       
+       for(rt = gIP_Routes; rt && Pos --; rt = rt->Next);
+       
+       if( !rt ) {
+               return NULL;
+       }
+       
+       {
+                int    len = snprintf(NULL, 12, "%i", rt->Node.Inode);
+               char    buf[len+1];
+               sprintf(buf, "%i", rt->Node.Inode);
+               return strdup(buf);
+       }
+}
+
+/**
+ * \brief FindDir for the /Devices/ip/routes/ directory
+ */
+tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name)
+{
+        int    num = atoi(Name);
+       
+       // Zero is invalid, sorry :)
+       if( !num )      return NULL;
+       
+       // The list is inherently sorted, so we can do a quick search
+       for(rt = gIP_Routes; rt && rt->Node.Inode < num; rt = rt->Next);
+       // Fast fail on larger number
+       if( rt->Node.Inode > num )
+               return NULL;
+       
+       return &rt->Node;
+}
+
+/**
+ * \brief Names for interface IOCtl Calls
+ */
+static const char *casIOCtls_RouteDir[] = {
+       DRV_IOCTLNAMES,
+       "add_route"     // Add a route - char *InterfaceName
+       NULL
+       };
+
+int IPStack_RouteDir_IOCtl(tVFS_Node *Node, int ID, void *Data)
+{
+       switch(ID)
+       {
+       // --- Standard IOCtls (0-3) ---
+       case DRV_IOCTL_TYPE:
+               LEAVE('i', DRV_TYPE_MISC);
+               return DRV_TYPE_MISC;
+       
+       case DRV_IOCTL_IDENT:
+               tmp = ModUtil_SetIdent(Data, STR(IDENT));
+               LEAVE('i', 1);
+               return 1;
+       
+       case DRV_IOCTL_VERSION:
+               LEAVE('x', VERSION);
+               return VERSION;
+       
+       case DRV_IOCTL_LOOKUP:
+               tmp = ModUtil_LookupString( (char**)casIOCtls_RouteDir, (char*)Data );
+               LEAVE('i', tmp);
+               return tmp;
+       
+       case 4: // Add Route
+               if( !CheckString(Data) )        return -1;
+               return IPStack_Route_Create(Data);
+       }
+       return 0;
+}
+
+/**
+ * \brief Create a new route entry
+ */
+int IPStack_Route_Create(const char *InterfaceName)
+{
+       tRoute  *rt;
+       tInterface      *iface;
+        int    size;
+       
+       // Get interface
+       // Note: Oh man! This is such a hack
+       {
+               tVFS_Node       *node = IPStack_Root_FindDir(NULL, InterfaceName);
+               if( !node )     return 0;
+               iface = node->ImplPtr;
+       }
+       
+       // Get the size of the specified address type
+       size = IPStack_GetAddressSize(iface->AddressType);
+       if( size == 0 ) {
+               return 0;
+       }
+       
+       // Allocate space
+       rt = calloc(1, sizeof(tRoute) + size*2 );
+       
+       rt->Next = NULL;
+       //rt->Node
+       
+       rt->AddressType = iface->AddressType;
+       rt->Network = (void *)( (tVAddr)rt + sizeof(tRoute) );
+       rt->SubnetBits = 0;
+       rt->NextHop = (void *)( (tVAddr)rt + sizeof(tRoute) + size );
+       rt->Interface = iface;
+}
index 8b486d2..99e6719 100644 (file)
@@ -881,7 +881,7 @@ int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data)
                if(conn->State != TCP_ST_CLOSED)        return -1;
                if(!CheckMem(Data, sizeof(Uint16)))     return -1;
                conn->RemotePort = *(Uint16*)Data;
-               return 0;
+               return conn->RemotePort;
 
        case 6: // Set Remote IP
                if( conn->State != TCP_ST_CLOSED )
@@ -906,6 +906,10 @@ int TCP_Client_IOCtl(tVFS_Node *Node, int ID, void *Data)
 
                TCP_StartConnection(conn);
                return 1;
+       
+       // Get recieve buffer length
+       case 8:
+               return conn->RecievedBuffer->Length;
        }
 
        return 0;
index eb21f3c..2df0b55 100644 (file)
@@ -31,6 +31,7 @@ extern void   Video_Update(void);
 extern void    Video_FillRect(short X, short Y, short W, short H, uint32_t Color);
 extern void    Video_DrawRect(short X, short Y, short W, short H, uint32_t Color);
 extern void    Video_DrawText(short X, short Y, short W, short H, void *Font, int Point, uint32_t Color, char *Text);
+extern void Video_DrawImage(short X, short Y, short W, short H, tImage *Image);
 // --- Debug Hack ---
 extern void    _SysDebug(const char *Format, ...);
 #endif
index 601f953..228e6aa 100644 (file)
@@ -72,5 +72,13 @@ void Decorator_RenderWidget(tElement *Element)
                        Element->Text
                        );
                break;
+       
+       case ELETYPE_IMAGE:
+               Video_DrawImage(
+                       Element->CachedX, Element->CachedY,
+                       Element->CachedW, Element->CachedH,
+                       Element->Data
+                       );
+               break;
        }
 }
index b71d944..af02429 100644 (file)
@@ -1,6 +1,9 @@
 /*
  * Acess GUI (AxWin) Version 2
  * By John Hodge (thePowersGang)
+ * 
+ * interface.c
+ * > Main Overarching UI
  */
 #include "common.h"
 
@@ -13,13 +16,18 @@ tElement    *gpInterface_TabBar;
 tElement       *gpInterface_TabContent;
 
 // === CODE ===
+/**
+ * \brief Initialise the UI
+ */
 void Interface_Init(void)
 {
        tElement        *area;
        tElement        *btn, *text;
        
+       // Calculate sizes
        giInterface_Width = giScreenWidth/16;
        
+       // Set root window to no-border
        WM_SetFlags(NULL, 0);
        
        // -- Create Sidebar --
index d17e0e5..7b56df7 100644 (file)
@@ -5,6 +5,7 @@
 #include "common.h"
 #include <acess/sys.h>
 #include <acess/devices/terminal.h>
+#include <image.h>
 
 // === PROTOTYPES ===
 void   Video_Setup(void);
@@ -94,7 +95,85 @@ void Video_DrawRect(short X, short Y, short W, short H, uint32_t Color)
        Video_FillRect(X+W-1, Y, 1, H, Color);
 }
 
+/**
+ * \brief Draw text to the screen
+ */
 void Video_DrawText(short X, short Y, short W, short H, void *Font, int Point, uint32_t Color, char *Text)
 {
        // TODO!
 }
+
+/**
+ * \brief Draw an image to the screen
+ * \todo Maybe have support for an offset in the image
+ */
+void Video_DrawImage(short X, short Y, short W, short H, tImage *Image)
+{
+        int    x, y;
+       uint8_t *buf = (uint8_t *)(gpScreenBuffer + Y*giScreenWidth + X);
+       uint8_t *data = Image->Data;
+       
+       // Bounds Check
+       if( X >= giScreenWidth )        return ;
+       if( Y >= giScreenHeight )       return ;
+       
+       // Wrap to image size
+       if( W > Image->Width )  W = Image->Width;
+       if( H > Image->Height ) H = Image->Height;
+       
+       // Wrap to screen size
+       if( X + W > giScreenWidth )     W = giScreenWidth - X;
+       if( Y + H > giScreenHeight )    H = giScreenHeight - Y;
+       
+       switch( Image->Format )
+       {
+       case IMGFMT_BGRA:
+               for( y = 0; y < H; y ++ )
+               {
+                        int    r, g, b, a;     // New
+                        int    or, og, ob;     // Original
+                       for( x = 0; x < W; x ++ ) {
+                               b = data[x*4+0]; g = data[x*4+1]; r = data[x*4+2]; a = data[x*4+3];
+                               if( a == 0 )    continue;       // 100% transparent
+                               ob = buf[x*4+0]; og = buf[x*4+1]; or = buf[x*4+2];
+                               // Handle Alpha
+                               switch(a)
+                               {
+                               // Transparent: Handled above
+                               // Solid
+                               case 0xFF:      break;
+                               // Half
+                               case 0x80:
+                                       r = (or + r) / 2;
+                                       g = (og + g) / 2;
+                                       b = (ob + b) / 2;
+                                       break;
+                               // General
+                               default:
+                                       r = (or * (255-a) + r * a) / 255;
+                                       g = (og * (255-a) + g * a) / 255;
+                                       b = (ob * (255-a) + b * a) / 255;
+                                       break;
+                               }
+                               buf[x*4+0] = b; buf[x*4+1] = g; buf[x*4+2] = r;
+                       }
+                       data += Image->Width * 4;
+                       buf += giScreenWidth * 4;
+               }
+               break;
+       
+       // RGB
+       case IMGFMT_RGB:
+               for( y = 0; y < H; y ++ )
+               {
+                       for( x = 0; x < W; x ++ ) {
+                               buf[x*4+0] = data[x*3+2];       // Blue
+                               buf[x*4+1] = data[x*3+1];       // Green
+                               buf[x*4+2] = data[x*3+0];       // Red
+                       }
+                       data += W * 3;
+                       buf += giScreenWidth * 4;
+               }
+               break;
+       }
+}
index a8fc96d..9bd5aa4 100644 (file)
@@ -6,7 +6,7 @@
  */
 #include "common.h"
 #include <stdlib.h>
-#include <strings.h>
+#include <string.h>
 #include "wm.h"
 
 // === IMPORTS ===
@@ -90,6 +90,10 @@ void WM_SetSize(tElement *Element, int Size)
        return ;
 }
 
+/**
+ * \brief Set the text field of an element
+ * \note Used for the image path on ELETYPE_IMAGE
+ */
 void WM_SetText(tElement *Element, char *Text)
 {
        if(!Element)    return ;
@@ -125,6 +129,11 @@ void WM_SetText(tElement *Element, char *Text)
 }
 
 // --- Pre-Rendering ---
+/**
+ * \name Pre-Rendering
+ * \brief Updates the element positions and sizes
+ * \{
+ */
 /**
  * \brief Updates the dimensions of an element
  * 
@@ -286,7 +295,6 @@ void WM_UpdatePosition(tElement *Element)
                );
 }
 
-
 /**
  * \brief Update the minimum dimensions of the element
  * \note Called after a child's minimum dimensions have changed
@@ -331,6 +339,9 @@ void WM_UpdateMinDims(tElement *Element)
        // Recurse upwards
        WM_UpdateMinDims(Element->Parent);
 }
+/**
+ * \}
+ */
 
 // --- Render ---
 void WM_RenderWidget(tElement *Element)
diff --git a/Usermode/Applications/irc_src/Makefile b/Usermode/Applications/irc_src/Makefile
new file mode 100644 (file)
index 0000000..98fa2bb
--- /dev/null
@@ -0,0 +1,10 @@
+# Project: IRC Client
+
+-include ../Makefile.cfg
+
+LDFLAGS += -lnet
+
+OBJ = main.o
+BIN = ../ls
+
+-include ../Makefile.tpl
diff --git a/Usermode/Applications/irc_src/main.c b/Usermode/Applications/irc_src/main.c
new file mode 100644 (file)
index 0000000..c202c6b
--- /dev/null
@@ -0,0 +1,238 @@
+/*\r
+ * Acess2 IRC Client\r
+ */\r
+#include <acess/sys.h>\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <net.h>\r
+\r
+#define BUFSIZ 1023\r
+\r
+// === TYPES ===\r
+typedef struct sServer {\r
+        int    FD;\r
+       char    InBuf[BUFSIZ+1];\r
+        int    ReadPos;\r
+} tServer;\r
+\r
+// === PROTOTYPES ===\r
+ int   ParseArguments(int argc, const char *argv[]);\r
+void   ProcessIncoming(tServer *Server);\r
+ int   writef(int FD, const char *Format, ...);\r
+ int   OpenTCP(const char *AddressString, short PortNumber);\r
+\r
+// === GLOBALS ===\r
+char   *gsUsername = "root";\r
+char   *gsHostname = "acess";\r
+char   *gsRemoteAddress = NULL;\r
+char   *gsRealName = "Acess2 IRC Client";\r
+char   *gsNickname = "acess";\r
+short  giRemotePort = 6667;\r
+\r
+// ==== CODE ====\r
+int main(int argc, const char *argv[], const char *envp[])\r
+{\r
+        int    tmp;\r
+       tServer srv;\r
+       \r
+       memset(&srv, 0, sizeof(srv));\r
+       \r
+       if( (tmp = ParseArguments(argc, argv)) ) {\r
+               return tmp;\r
+       }\r
+       \r
+       srv.FD = OpenTCP( gsRemoteAddress, giRemotePort );\r
+       if( srv.FD == -1 ) {\r
+               fprintf(stderr, "Unable to create socket\n");\r
+               return -1;\r
+       }\r
+       \r
+       writef(srv.FD, "USER %s %s %s : %s\n", gsUsername, gsHostname, gsRemoteAddress, gsRealName);\r
+       writef(srv.FD, "NICK %s", gsNickname);\r
+       \r
+       ProcessIncoming(&srv);\r
+       \r
+       close(srv.FD);\r
+       return 0;\r
+}\r
+\r
+/**\r
+ * \todo Actually implement correctly :)\r
+ */\r
+int ParseArguments(int argc, const char *argv[])\r
+{\r
+       gsRemoteAddress = "130.95.13.18";       // irc.ucc.asn.au\r
+       \r
+       return 0;\r
+}\r
+\r
+void Cmd_PRIVMSG(tServer *Server, const char *Dest, const char *Src, const char *Message)\r
+{\r
+       printf("%p: %s => %s\t%s\n", Server, Src, Dest, Message);\r
+}\r
+\r
+/**\r
+ * \brief Read a space-separated value from a string\r
+ */\r
+char *GetValue(char *Src, int *Ofs)\r
+{\r
+        int    pos = *Ofs;\r
+       char    *ret = Src + pos;\r
+       char    *end;\r
+       \r
+       while( *ret == ' ' )    ret ++;\r
+       \r
+       end = strchr(ret, ' ');\r
+       if( end ) {\r
+               *end = '\0';\r
+       }\r
+       else {\r
+               end = ret + strlen(ret) - 1;\r
+       }\r
+       *Ofs = end - Src + 1;\r
+       \r
+       return ret;\r
+}\r
+\r
+/**\r
+ */\r
+void ParseServerLine(tServer *Server, char *Line)\r
+{\r
+        int    pos;\r
+       char    *ident, *cmd;\r
+       if( *Line == ':' ) {\r
+               // Message\r
+               ident = GetValue(Line, &pos);\r
+               pos ++; // Space\r
+               cmd = GetValue(Line, &pos);\r
+               \r
+               if( strcmp(cmd, "PRIVMSG") == 0 ) {\r
+                       char    *dest, *message;\r
+                       pos ++;\r
+                       dest = GetValue(Line, &pos);\r
+                       pos ++;\r
+                       if( Line[pos] == ':' ) {\r
+                               message = Line + pos + 1;\r
+                       }\r
+                       else {\r
+                               message = GetValue(Line, &pos);\r
+                       }\r
+                       Cmd_PRIVMSG(Server, dest, ident, message);\r
+               }\r
+       }\r
+       else {\r
+               // Command to client\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Process incoming lines from the server\r
+ */\r
+void ProcessIncoming(tServer *Server)\r
+{      \r
+       char    *ptr, *newline;\r
+        int    len;\r
+       \r
+       // While there is data in the buffer, read it into user memory and \r
+       // process it line by line\r
+       // ioctl#8 on a TCP client gets the number of bytes in the recieve buffer\r
+       // - Used to avoid blocking\r
+       while( ioctl(Server->FD, 8, NULL) )\r
+       {\r
+               // Read data\r
+               len = read(Server->FD, BUFSIZ - Server->ReadPos, Server->InBuf + Server->ReadPos);\r
+               Server->InBuf[Server->ReadPos + len] = '\0';\r
+               \r
+               // Break into lines\r
+               ptr = Server->InBuf;\r
+               while( (newline = strchr(ptr, '\n')) )\r
+               {\r
+                       *newline = '\0';\r
+                       printf("%s\n", ptr);\r
+                       ParseServerLine(Server, ptr);\r
+                       ptr = newline + 1;\r
+               }\r
+               \r
+               // Handle incomplete lines\r
+               if( ptr - Server->InBuf < len + Server->ReadPos ) {\r
+                       Server->ReadPos = ptr - Server->InBuf;\r
+                       memcpy(Server->InBuf, ptr, Server->ReadPos);\r
+               }\r
+               else {\r
+                       Server->ReadPos = 0;\r
+               }\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Write a formatted string to a file descriptor\r
+ * \r
+ */\r
+int writef(int FD, const char *Format, ...)\r
+{\r
+       va_list args;\r
+        int    len;\r
+       \r
+       va_start(args, Format);\r
+       len = vsnprintf(NULL, 1000, Format, args);\r
+       va_end(args);\r
+       \r
+       {\r
+               char    buf[len+1];\r
+               va_start(args, Format);\r
+               vsnprintf(buf, len+1, Format, args);\r
+               va_end(args);\r
+               \r
+               return write(FD, len, buf);\r
+       }\r
+}\r
+\r
+/**\r
+ * \brief Initialise a TCP connection to \a AddressString on port \a PortNumber\r
+ */\r
+int OpenTCP(const char *AddressString, short PortNumber)\r
+{\r
+        int    fd, addrType, iface;\r
+       char    addrBuffer[8];\r
+       \r
+       // Parse IP Address\r
+       addrType = Net_ParseAddress(AddressString, addrBuffer);\r
+       if( addrType == 0 ) {\r
+               fprintf(stderr, "Unable to parse '%s' as an IP address\n", AddressString);\r
+               return -1;\r
+       }\r
+       \r
+       // Finds the interface for the destination address\r
+       iface = Net_GetInterface(addrType, addrBuffer);\r
+       if( iface == -1 ) {\r
+               fprintf(stderr, "Unable to find a route to '%s'\n", AddressString);\r
+               return -1;\r
+       }\r
+       \r
+       // Open client socket\r
+       // TODO: Move this out to libnet?\r
+       {\r
+                int    len = snprintf(NULL, 100, "/Devices/ip/%i/tcpc", iface);\r
+               char    path[len+1];\r
+               snprintf(path, 100, "/Devices/ip/%i/tcpc", iface);\r
+               fd = open(path, OPENFLAG_READ|OPENFLAG_WRITE);\r
+       }\r
+       \r
+       if( fd == -1 ) {\r
+               return -1;\r
+       }\r
+\r
+       // Set remote port and address\r
+       ioctl(fd, 5, &PortNumber);\r
+       ioctl(fd, 6, addrBuffer);\r
+       \r
+       // Connect\r
+       if( ioctl(fd, 7, NULL) == 0 ) {\r
+               // Shouldn't happen :(\r
+               return -1;\r
+       }\r
+       \r
+       // Return descriptor\r
+       return fd;\r
+}\r
index 7149b3e..f26fada 100644 (file)
@@ -546,3 +546,17 @@ EXPORT int sprintf(char *buf, const char *format, ...)
        va_end(args);\r
        return ret;\r
 }\r
+\r
+/**\r
+ * \fn EXPORT int snprintf(const char *buf, size_t maxlen, char *format, ...)\r
+ * \brief Print a formatted string to a buffer\r
+ */\r
+EXPORT int snprintf(char *buf, size_t maxlen, const char *format, ...)\r
+{\r
+        int    ret;\r
+       va_list args;\r
+       va_start(args, format);\r
+       ret = vsnprintf((char*)buf, maxlen, (char*)format, args);\r
+       va_end(args);\r
+       return ret;\r
+}\r
index 455d3bc..7b076a3 100644 (file)
@@ -21,7 +21,7 @@ tImage *Image_SIF_Parse(void *Buffer, size_t Size)
        uint16_t        flags;
        uint16_t        w, h;
         int    ofs, i;
-       tImage_SIF      *ret;
+       tImage  *ret;
         int    bRevOrder;
         int    fileOfs = 0;
         int    comp, fmt;
@@ -46,21 +46,15 @@ tImage *Image_SIF_Parse(void *Buffer, size_t Size)
        w = *(uint16_t*)Buffer+fileOfs; fileOfs += 2;
        h = *(uint16_t*)Buffer+fileOfs; fileOfs += 2;
        
-       
-       // Allocate space
-       ret = calloc(1, sizeof(tImage) + w * h * sampleSize);
-       ret->Width = w;
-       ret->Height = h;
-       
        // Get image format
        switch(fmt)
        {
-       case 0: // ARGB
-               ret->Format = IMGFMT_ARGB;
+       case 0: // ARGB 32-bit Little Endian
+               fmt = IMGFMT_BGRA;
                sampleSize = 4;
                break;
-       case 1: // RGB
-               ret->Format = IMGFMT_RGB;
+       case 1: // RGB 24-bit big endian
+               fmt = IMGFMT_RGB;
                sampleSize = 3;
                break;
        default:
@@ -68,6 +62,12 @@ tImage *Image_SIF_Parse(void *Buffer, size_t Size)
                return NULL;
        }
        
+       // Allocate space
+       ret = calloc(1, sizeof(tImage) + w * h * sampleSize);
+       ret->Width = w;
+       ret->Height = h;
+       ret->Format = fmt;
+       
        switch(comp)
        {
        // Uncompressed 32-bpp data
@@ -89,6 +89,7 @@ tImage *Image_SIF_Parse(void *Buffer, size_t Size)
                        uint8_t len;
                        if( fileOfs + 1 > Size )        return ret;
                        len = *(uint8_t*)Buffer+fileOfs;        fileOfs += 1;
+                       // Verbatim
                        if(len & 0x80) {
                                len &= 0x7F;
                                if( fileOfs + len*sampleSize > Size ) {
@@ -100,6 +101,7 @@ tImage *Image_SIF_Parse(void *Buffer, size_t Size)
                                }
                                ofs += len;
                        }
+                       // RLE
                        else {
                                uint8_t tmp[sampleSize];
                                
@@ -118,6 +120,7 @@ tImage *Image_SIF_Parse(void *Buffer, size_t Size)
                return ret;
        
        // Channel 1.7.8 RLE
+       // - Each channel is separately 1.7 RLE compressed
        case 3:
                // Alpha, Red, Green, Blue
                for( i = 0; i < sampleSize; i++ )
diff --git a/Usermode/Libraries/libnet.so_src/Makefile b/Usermode/Libraries/libnet.so_src/Makefile
new file mode 100644 (file)
index 0000000..f92e7bc
--- /dev/null
@@ -0,0 +1,12 @@
+# Acess 2 - Networking Helpers
+
+include ../Makefile.cfg
+
+CPPFLAGS +=
+CFLAGS   += -Wall
+LDFLAGS  += -lc -soname libnet.so
+
+OBJ = address.o
+BIN = ../libnet.so
+
+include ../Makefile.tpl
diff --git a/Usermode/Libraries/libnet.so_src/address.c b/Usermode/Libraries/libnet.so_src/address.c
new file mode 100644 (file)
index 0000000..2b58444
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Acess2 Networking Toolkit
+ * By John Hodge (thePowersGang)
+ * 
+ * address.c
+ * - Address Parsing
+ */
+#include <net.h>
+#include <stdint.h>
+#define DEBUG  0
+
+/**
+ * \brief Read an IPv4 Address
+ * \param String       IPv4 dotted decimal address
+ * \param Addr Output 32-bit representation of IP address
+ * \return Boolean success
+ */
+static int Net_ParseIPv4Addr(const char *String, uint8_t *Addr)
+{
+        int    i = 0;
+        int    j;
+        int    val;
+       
+       for( j = 0; String[i] && j < 4; j ++ )
+       {
+               val = 0;
+               for( ; String[i] && String[i] != '.'; i++ )
+               {
+                       if('0' > String[i] || String[i] > '9') {
+                               #if DEBUG
+                               printf("0<c<9 expected, '%c' found\n", String[i]);
+                               #endif
+                               return 0;
+                       }
+                       val = val*10 + String[i] - '0';
+               }
+               if(val > 255) {
+                       #if DEBUG
+                       printf("val > 255 (%i)\n", val);
+                       #endif
+                       return 0;
+               }
+               Addr[j] = val;
+               
+               if(String[i] == '.')
+                       i ++;
+       }
+       if( j != 4 ) {
+               #if DEBUG
+               printf("4 parts expected, %i found\n", j);
+               #endif
+               return 0;
+       }
+       if(String[i] != '\0') {
+               #if DEBUG
+               printf("EOS != '\\0', '%c'\n", String[i]);
+               #endif
+               return 0;
+       }
+       return 1;
+}
+
+/**
+ * \brief Read an IPv6 Address
+ * \param String       IPv6 colon-hex representation
+ * \param Addr Output 128-bit representation of IP address
+ * \return Boolean success
+ */
+static int Net_ParseIPv6Addr(const char *String, uint8_t *Addr)
+{
+        int    i = 0;
+        int    j, k;
+        int    val, split = -1, end;
+       uint16_t        hi[8], low[8];
+       
+       for( j = 0; String[i] && j < 8; j ++ )
+       {
+               if(String[i] == ':') {
+                       if(split != -1) {
+                               #if DEBUG
+                               printf("Two '::'s\n");
+                               #endif
+                               return 0;
+                       }
+                       split = j;
+                       i ++;
+                       continue;
+               }
+               
+               val = 0;
+               for( k = 0; String[i] && String[i] != ':'; i++, k++ )
+               {
+                       val *= 16;
+                       if('0' <= String[i] && String[i] <= '9')
+                               val += String[i] - '0';
+                       else if('A' <= String[i] && String[i] <= 'F')
+                               val += String[i] - 'A' + 10;
+                       else if('a' <= String[i] && String[i] <= 'f')
+                               val += String[i] - 'a' + 10;
+                       else {
+                               #if DEBUG
+                               printf("%c unexpected\n", String[i]);
+                               #endif
+                               return 0;
+                       }
+               }
+               
+               if(val > 0xFFFF) {
+                       #if DEBUG
+                       printf("val (0x%x) > 0xFFFF\n", val);
+                       #endif
+                       return 0;
+               }
+               
+               if(split == -1)
+                       hi[j] = val;
+               else
+                       low[j-split] = val;
+               
+               if( String[i] == ':' ) {
+                       i ++;
+               }
+       }
+       end = j;
+       
+       // Create final address
+       // - First section
+       for( j = 0; j < split; j ++ )
+       {
+               Addr[j*2] = hi[j]>>8;
+               Addr[j*2+1] = hi[j]&0xFF;
+       }
+       // - Zero region
+       for( ; j < 8 - (end - split); j++ )
+       {
+               Addr[j*2] = 0;
+               Addr[j*2+1] = 0;
+       }
+       // - Tail section
+       k = 0;
+       for( ; j < 8; j ++, k++)
+       {
+               Addr[j*2] = hi[k]>>8;
+               Addr[j*2+1] = hi[k]&0xFF;
+       }
+       
+       return 1;
+}
+
+/**
+ * \brief Parse an address from a string
+ * \param String       String containing an IPv4/IPv6 address
+ * \param Addr Buffer for the address (must be >= 16 bytes)
+ * \return Address type
+ * \retval 0   Unknown address type
+ * \retval 4   IPv4 Address
+ * \retval 6   IPv6 Address
+ */
+int Net_ParseAddress(const char *String, void *Addr)
+{
+       if( Net_ParseIPv4Addr(String, Addr) )
+               return 4;
+       
+       if( Net_ParseIPv6Addr(String, Addr) )
+               return 6;
+       
+       return 0;
+}
diff --git a/Usermode/Libraries/libnet.so_src/net.h b/Usermode/Libraries/libnet.so_src/net.h
new file mode 100644 (file)
index 0000000..05deb9f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Acess2 Common Networking Library
+ * By John Hodge (thePowersGang)
+ */
+
+#ifndef __LIBNET_H_
+#define __LIBNET_H_
+
+/**
+ * \brief Parse a string as an IP Address
+ * \param String       Input string
+ * \param Addr Output binary format of the address
+ * \return Address family (0: Invalid, 4: IPv4, 6: IPv6)
+ */
+extern int     Net_ParseAddress(const char *String, void *Addr);
+
+/**
+ * \brief Get the interface required to reach \a Addr
+ * \param AddrType     Addresss Family (4: IPv4, 6: IPv6)
+ * \param Addr Address in binary format
+ * \return Interface number
+ */
+extern int     Net_GetInterface(int AddrType, void *Addr);
+
+#endif
diff --git a/Usermode/include/net.h b/Usermode/include/net.h
new file mode 120000 (symlink)
index 0000000..be2d196
--- /dev/null
@@ -0,0 +1 @@
+../Libraries/libnet.so_src/net.h
\ No newline at end of file
index 1223fe8..ce42a15 100644 (file)
@@ -19,6 +19,7 @@ extern int    printf(const char *format, ...);
 extern int     vsnprintf(char *buf, size_t __maxlen, const char *format, va_list args);\r
 extern int     vsprintf(char *buf, const char *format, va_list args);\r
 extern int     sprintf(char *buf, const char *format, ...);\r
+extern int snprintf(char *buf, size_t maxlen, const char *format, ...);\r
 \r
 extern FILE    *fopen(const char *file, const char *mode);\r
 extern FILE    *freopen(const char *file, const char *mode, FILE *fp);\r

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