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
strcpy(ret, Str);
return ret;
}
-#endif
+#else
/**
* \fn char *_strdup(const char *File, int Line, const char *Str)
strcpy(ret, Str);
return ret;
}
+#endif
/**
* \brief Split a string using the passed character
{
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:
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);
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];
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;
#define ntohl(v) BigEndian32(v)
extern int IPStack_AddFile(tSocketFile *File);
+extern int IPStack_GetAddressSize(int AddressType);
#endif
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);
}
};
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;
{
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();
// 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;
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 ) ;
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')
{
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);
* \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;
card = IPStack_GetAdapter(Device);
- iface = malloc(sizeof(tInterface));
+ iface = malloc(sizeof(tInterface) + strlen(Name));
if(!iface) {
LEAVE('i', -2);
return -2; // Return ERR_MYBAD
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);
+ }
+}
--- /dev/null
+/*
+ * 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;
+}
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 )
TCP_StartConnection(conn);
return 1;
+
+ // Get recieve buffer length
+ case 8:
+ return conn->RecievedBuffer->Length;
}
return 0;
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
Element->Text
);
break;
+
+ case ELETYPE_IMAGE:
+ Video_DrawImage(
+ Element->CachedX, Element->CachedY,
+ Element->CachedW, Element->CachedH,
+ Element->Data
+ );
+ break;
}
}
/*
* Acess GUI (AxWin) Version 2
* By John Hodge (thePowersGang)
+ *
+ * interface.c
+ * > Main Overarching UI
*/
#include "common.h"
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 --
#include "common.h"
#include <acess/sys.h>
#include <acess/devices/terminal.h>
+#include <image.h>
// === PROTOTYPES ===
void Video_Setup(void);
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;
+ }
+}
*/
#include "common.h"
#include <stdlib.h>
-#include <strings.h>
+#include <string.h>
#include "wm.h"
// === IMPORTS ===
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 ;
}
// --- Pre-Rendering ---
+/**
+ * \name Pre-Rendering
+ * \brief Updates the element positions and sizes
+ * \{
+ */
/**
* \brief Updates the dimensions of an element
*
);
}
-
/**
* \brief Update the minimum dimensions of the element
* \note Called after a child's minimum dimensions have changed
// Recurse upwards
WM_UpdateMinDims(Element->Parent);
}
+/**
+ * \}
+ */
// --- Render ---
void WM_RenderWidget(tElement *Element)
--- /dev/null
+# Project: IRC Client
+
+-include ../Makefile.cfg
+
+LDFLAGS += -lnet
+
+OBJ = main.o
+BIN = ../ls
+
+-include ../Makefile.tpl
--- /dev/null
+/*\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
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
uint16_t flags;
uint16_t w, h;
int ofs, i;
- tImage_SIF *ret;
+ tImage *ret;
int bRevOrder;
int fileOfs = 0;
int comp, fmt;
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:
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
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 ) {
}
ofs += len;
}
+ // RLE
else {
uint8_t tmp[sampleSize];
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++ )
--- /dev/null
+# Acess 2 - Networking Helpers
+
+include ../Makefile.cfg
+
+CPPFLAGS +=
+CFLAGS += -Wall
+LDFLAGS += -lc -soname libnet.so
+
+OBJ = address.o
+BIN = ../libnet.so
+
+include ../Makefile.tpl
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+../Libraries/libnet.so_src/net.h
\ No newline at end of file
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