Difference between revisions of "Peerd.c"

From Organic Design wiki
(#include <regex.h>)
(oops, crashes if no args supplied)
Line 1: Line 1:
 
// [[[[http://www.organicdesign.co.nz/peerd|peerd]]]] - nodal p2p wiki daemon
 
// [[[[http://www.organicdesign.co.nz/peerd|peerd]]]] - nodal p2p wiki daemon
// [[[[http://www.organicdesign.co.nz/peerd/files/C|C language version]]]] for *ix,OSX,NT platforms
+
// This article and all its includes are licenced under LGPL
// This article and all its includes are licenced under [[[[http://www.gnu.org/copyleft/lesser.html|LGPL]]]]
+
// GPL: [[[[http://www.gnu.org/copyleft/lesser.html]]]]
// SRC: [[[[http://www.organicdesign.co.nz/peerd.c]]]]
+
// SRC: [[[[http://www.organicdesign.co.nz/util.c]]]]
// NOTE: for automatic source syncronisation with peers in the field,
+
// included in [[[[http://www.organicdesign.co.nz/category:peerd/files/C|peerd]]]][[[[http://www.organicdesign.co.nz/peerd.c|/peerd.c]]]]
//      keep [[[[Bender/fileSync]]]] up to date!
 
// Compiled in Win32 by [[[[peerd.c/win32-makefile]]]]
 
// Compiled in Linux and OSX by [[[[rp]]]]
 
// [[[[peerd.c/current|Current development]]]]
 
  
int this,loop,port = 32459;
 
char *peer = "default";
 
  
#include <unistd.h>
+
// Output a log entry with timestamp
#include <stdlib.h>
+
// - Message can contain format like printf but only %s and %d
#include <stdio.h>
+
// - todo: Should use [[[[io.c]]]] to send multiplexly
#include <string.h>
+
char *laMsg = NULL;
#include <errno.h>
+
void logAdd(char *format, ... ) {
#include <math.h>
+
if (laMsg == NULL) laMsg = malloc(1000);
#include <stdarg.h>
+
char *msg = laMsg;
#include <time.h>
+
va_list args;
#include <regex.h>
+
va_start(args,format);
#include "util.c"          // [[[[util.c]]]]: General utils, file,log,string etc
+
time_t now = time(NULL);
 +
char *nowtext = ctime(&now);
 +
if (nowtext) while (*msg++ = *nowtext++);
 +
*(msg-2) = ':';
 +
*(msg-1) = ' ';
 +
while (*format) {
 +
if (strncmp(format,"%d",2)==0) {
 +
msg += sprintf(msg,"%d",va_arg(args,int));
 +
format += 2;
 +
}
 +
else if (strncmp(format,"%s",2)==0) {
 +
char *arg = va_arg(args,char*);
 +
while (*arg) *msg++ = *arg++;
 +
format += 2;
 +
}
 +
else *msg++ = *format++;
 +
}
 +
va_end(args);
 +
*msg++ = '\n';
 +
*msg++ = '\0';
 +
printf(laMsg);
 +
}
  
// List & Node Space
 
#include "listSpace.c"      // [[[[listSpace.c]]]]: listSpace and some C-specific extras: hash, trie, linked-list
 
#include "nodeSpace.c"      // [[[[nodeSpace.c]]]]: NodeSpace function declarations and initialisation
 
#include "serialise.c"      // [[[[serialise.c]]]]: Nodal-to-text and visa-versa
 
  
// Interface related
+
// Return an array of strings resulting from splitting passed text at passed character
#include "SDL.h"
+
// - the array is terminated by a NULL pointer
#include "SDL_image.h"
+
char **split(char c,char *text) {
#include "SDL_opengl.h"    // OpenGL example [[[[http://www.libsdl.org/cgi/docwiki.cgi/OpenGL_20Full_20Example|here]]]]
+
int len = strlen(text), items = 0, size = 10;
#include "interface.c"      // [[[[interface.c]]]]: Layer model, video, audio, input, OpenGL
+
char **list = malloc(size);
 +
char *i = malloc(len+1), *j = i, *k = i, *item = i;
 +
while(*j++ = *text++);
 +
while(i <= k+len) {
 +
if (*i == c) *i = '\0';
 +
if ((*i++ == '\0')&&strlen(item)) {
 +
if (items>size-2) realloc(list,size+=10);
 +
list[items++] = item;
 +
list[items] = NULL;
 +
item = i;
 +
}
 +
}
 +
return list;
 +
}
  
// Peer daemon setup
+
// Replaces missing itoa() and is specialised for binary return a string of \1 and \2 characters
#if __WIN32__
+
char *itob(int value, char *buf) {
#include "servicate.c"      // [[[[servicate.c]]]]
+
int i;
#elif __APPLE__
+
char *j = buf;
#include "launchd.c"        // [[[[launchd.c]]]]
+
for (i=1; i<=value>>1; i<<=1) *j++ = value&i ? '\1' : '\2';
#elif __unix__
+
*j = '\0';
#include "daemonise.c"      // [[[[daemonise.c]]]]
+
return buf;
#endif
+
}
  
// Storage & distribution related
+
// ----------------------------------------------------------------------------------------- //
#if __WIN32__
+
// Global Pointer List
#include <winsock.h>
+
// - use insertPointer() and removePointer() to access the dynamically allocating pointer-array
#else
+
// - internally uses freePush() and freePop() to maintain a linked-list of free array slots
#include <sys/socket.h>
+
int psize = 100, pitem = 0;
#include <sys/select.h>
+
void **plist = NULL;
#include <netinet/in.h>
+
typedef struct fi {
#include <sys/time.h>      // for select()
+
int index;
#include <fcntl.h>          // O_RDWR, O_NONBLOCK, F_GETFL, F_SETFL
+
struct fi *next;
#endif
+
} fitem;
#include "io.c"            // [[[[io.c]]]]: Main server and stream setup and functions
+
fitem *flist = NULL;
  
int main(int argc, char **argv) {
+
// add a new pointer to the list, try using slots from the free-list before extending array
 +
int insertPointer(void *ptr) {
 +
int index;
 +
if (plist == NULL) plist = malloc(psize*sizeof(void*));
 +
if (flist) {
 +
fitem *kill = flist;
 +
flist = (fitem*)kill->next;
 +
index = kill->index;
 +
free(kill);
 +
}
 +
else if ((index = ++pitem) > psize) realloc(plist,psize += 100);
 +
plist[index] = ptr;
 +
return index;
 +
}
  
regex_t *preg = malloc(1000);
+
// push the index onto the free-list, returning the pointer at that index
regcomp(preg, "[cmprs]at", 0);
+
void *removePointer(int index) {
 +
fitem *newfree = (fitem*)malloc(sizeof(fitem));
 +
newfree->next = flist ? flist : NULL;
 +
flist = newfree;
 +
return plist[newfree->index = index];
 +
}
  
logAdd("");            // Blank line in log to separate peerd sessions
 
peerdInit();            // Set up as a daemon or service
 
listInit();            // Initialise list-space and hash/trie functions
 
nodeInit();            // Set up initial nodal structure for reduction loop
 
args(argc,argv);        // Handle command-line args and globals like peer and port
 
ifInit();              // Initialise interface aspects (video, audio, input, OpenGL)
 
ioInit();              // Set up listening socket on specified port
 
  
// Main nodal reduction loop
+
// Store the command-line args in the listSpace hash, eg char *name = *hash("name")
logAdd("Handing program execution over to nodal reduction...");
+
void **hash(unsigned char*);
for (this=0;1;this=0) nodeReduce();
+
void args(int argc, char **argv) {
  
 +
if (argc>1) {
 +
int l = strlen(argv[1]);
 +
peer = strncpy(malloc(l+1),argv[1],l);
 +
while(argc-->2) {
 +
char **arg = split('=',argv[argc]);
 +
*hash(*arg) = arg[1]?strncpy(malloc(l=strlen(arg[1])+1),arg[1],l):"1";
 +
free(arg);
 +
}
 +
}
 +
 +
// Make a global peer name and port number
 +
char *p = *hash("port");
 +
if (p) port = atoi(p);
 +
 +
#if __unix__
 +
// Set name as seen in ps list if ux
 +
char *tmp = *argv;
 +
for (l=40;l--;) *tmp++ = '\0';
 +
sprintf(*argv,"peerd: %s (http%d)",peer,port);
 +
#endif
 
}
 
}

Revision as of 05:59, 21 August 2006

// [[[[1]]]] - nodal p2p wiki daemon // This article and all its includes are licenced under LGPL // GPL: [[[[2]]]] // SRC: [[[[3]]]] // included in [[[[4]]]][[[[5]]]]


// Output a log entry with timestamp // - Message can contain format like printf but only %s and %d // - todo: Should use [[io.c]] to send multiplexly char *laMsg = NULL; void logAdd(char *format, ... ) { if (laMsg == NULL) laMsg = malloc(1000); char *msg = laMsg; va_list args; va_start(args,format); time_t now = time(NULL); char *nowtext = ctime(&now); if (nowtext) while (*msg++ = *nowtext++); *(msg-2) = ':'; *(msg-1) = ' '; while (*format) { if (strncmp(format,"%d",2)==0) { msg += sprintf(msg,"%d",va_arg(args,int)); format += 2; } else if (strncmp(format,"%s",2)==0) { char *arg = va_arg(args,char*); while (*arg) *msg++ = *arg++; format += 2; } else *msg++ = *format++; } va_end(args); *msg++ = '\n'; *msg++ = '\0'; printf(laMsg); }


// Return an array of strings resulting from splitting passed text at passed character // - the array is terminated by a NULL pointer char **split(char c,char *text) { int len = strlen(text), items = 0, size = 10; char **list = malloc(size); char *i = malloc(len+1), *j = i, *k = i, *item = i; while(*j++ = *text++); while(i <= k+len) { if (*i == c) *i = '\0'; if ((*i++ == '\0')&&strlen(item)) { if (items>size-2) realloc(list,size+=10); list[items++] = item; list[items] = NULL; item = i; } } return list; }

// Replaces missing itoa() and is specialised for binary return a string of \1 and \2 characters char *itob(int value, char *buf) { int i; char *j = buf; for (i=1; i<=value>>1; i<<=1) *j++ = value&i ? '\1' : '\2'; *j = '\0'; return buf; }

// ----------------------------------------------------------------------------------------- // // Global Pointer List // - use insertPointer() and removePointer() to access the dynamically allocating pointer-array // - internally uses freePush() and freePop() to maintain a linked-list of free array slots int psize = 100, pitem = 0; void **plist = NULL; typedef struct fi { int index; struct fi *next; } fitem; fitem *flist = NULL;

// add a new pointer to the list, try using slots from the free-list before extending array int insertPointer(void *ptr) { int index; if (plist == NULL) plist = malloc(psize*sizeof(void*)); if (flist) { fitem *kill = flist; flist = (fitem*)kill->next; index = kill->index; free(kill); } else if ((index = ++pitem) > psize) realloc(plist,psize += 100); plist[index] = ptr; return index; }

// push the index onto the free-list, returning the pointer at that index void *removePointer(int index) { fitem *newfree = (fitem*)malloc(sizeof(fitem)); newfree->next = flist ? flist : NULL; flist = newfree; return plist[newfree->index = index]; }


// Store the command-line args in the listSpace hash, eg char *name = *hash("name") void **hash(unsigned char*); void args(int argc, char **argv) {

if (argc>1) { int l = strlen(argv[1]); peer = strncpy(malloc(l+1),argv[1],l); while(argc-->2) { char **arg = split('=',argv[argc]); *hash(*arg) = arg[1]?strncpy(malloc(l=strlen(arg[1])+1),arg[1],l):"1"; free(arg); } }

// Make a global peer name and port number char *p = *hash("port"); if (p) port = atoi(p);

#if __unix__ // Set name as seen in ps list if ux char *tmp = *argv; for (l=40;l--;) *tmp++ = '\0'; sprintf(*argv,"peerd: %s (http%d)",peer,port); #endif }