Difference between revisions of "Peerd.c"

From Organic Design wiki
(remove serialise test from here)
(set the node constants from trieGetValue())
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
// Source: [[[[http://www.organicdesign.co.nz/peerd/files/C|peerd/files/C]]]] - the 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]]]]
// Compiled in Win32 by [[[[peerd.c/win32-makefile]]]] to [[[[http://www.organicdesign.co.nz/wiki/images/a/a2/Peerd.msi|peerd.msi]]]]
+
// SRC: [[[[http://www.organicdesign.co.nz/nodeSpace.c]]]]
// Compiled in Linux and OSX by [[[[rp]]]] to peerd.deb and peerd.dmg
+
// included in [[[[http://www.organicdesign.co.nz/category:peerd/files/C|peerd]]]][[[[http://www.organicdesign.co.nz/peerd.c|/peerd.c]]]]
// [[[[peerd.c/current|Current development]]]]
 
  
int this,loop,port = 32459;
+
typedef int node;       // node: a type for referring to nodes
char *peer = "default";
+
typedef void (code)(); // code: a type for executing functions from pointer
  
#include <unistd.h>
+
// Reserved nodes used by nodal reduction process (tmp)
#include <stdlib.h>
+
// - doesn't matter that these node indexes conflict with 128 ascii nodes
#include <stdio.h>
+
//  because these will not currently need anything stored in them
#include <string.h>
+
#define nodeLOOP 1
#include <errno.h>
+
#define nodeTRUE 1
#include <math.h>
+
#define nodeNEXT 2
#include <stdarg.h>
+
#define nodePREV 3
#include <time.h>
+
#define nodeCODE 4
#include <regex.h>
 
#include "util.h"          // [[[[util.c]]]]: General utils, file,log,string etc
 
  
// List & Node Space
+
// Runtime nodes
#include "listSpace.h"      // [[[[listSpace.c]]]]: listSpace and some C-specific extras: hash, trie, linked-list
+
node this;              // this: the current node, like cwd
#include "nodeSpace.h"      // [[[[nodeSpace.c]]]]: NodeSpace function declarations and initialisation
 
#include "serialise.h"      // [[[[serialise.c]]]]: Nodal-to-text and visa-versa
 
  
// Interface related
+
// stateless
#include "SDL.h"
+
node nodeINTERFACE;
#include "SDL_image.h"
+
node nodeSTREAMS;
#include "SDL_opengl.h"    // OpenGL example [[[[http://www.libsdl.org/cgi/docwiki.cgi/OpenGL_20Full_20Example|here]]]]
 
#include "interface.h"      // [[[[interface.c]]]]: Layer model, video, audio, input, OpenGL
 
  
// Peer daemon setup
+
// function ref
#if __WIN32__
+
node nodeEVENTS;
#include "servicate.h"      // [[[[servicate.c]]]]
+
node nodeIO;
#elif __APPLE__
+
node nodeSERVER;
#include "launchd.h"        // [[[[launchd.c]]]]
+
node nodeDESKTOP;
#elif __unix__
 
#include "daemonise.h"      // [[[[daemonise.c]]]]
 
#endif
 
  
// [[[[Storage and distribution]]]] related
+
// pointer to struct
#if __WIN32__
+
node nodeSTREAM;
#include <winsock.h>
+
node nodeWINDOW;
#else
 
#include <sys/socket.h>    // see [[[[http://www.opengroup.org/onlinepubs/009695399/functions/select.html|select()]]]]
 
#include <sys/select.h>
 
#include <netinet/in.h>
 
#include <sys/time.h>      // for select() related stuff
 
#include <fcntl.h>          // O_RDWR, O_NONBLOCK, F_GETFL, F_SETFL
 
#include <netdb.h>          // for [[[[http://www.opengroup.org/onlinepubs/009695399/basedefs/netdb.h.html|hostent struct]]]]
 
#endif
 
#include "io.h"            // [[[[io.c]]]]: Main server and stream setup and functions
 
  
int main(int argc, char **argv) {
 
  
logAdd("");             // Blank line in log to separate peerd sessions
+
// Prototypes
peerdInit();           // Set up as a daemon or service
+
node nodeTraverse(node subject,node key);
listInit();             // Initialise list-space and hash/trie functions
+
node nodeGetValue(node subject,node key);
nodeInit();             // Set up initial nodal structure for reduction loop
+
node nodeSetValue(node subject,node key,node value);
args(argc,argv);       // Handle command-line args and globals like peer and port
+
node nodeInsertKey(node subject,node key);
ifInit();               // Initialise interface aspects (video, audio, input, OpenGL)
+
node nodeRemoveKey(node subject,node key);
ioInit();               // Set up listening socket on specified port
+
node nodeLoopInsert(node subject,node insert);
 +
node nodeLoopRemove(node subject);
 +
void **nodeGetState(node subject,node key);
 +
int nodeInit();
 +
void nodeExit();
 +
void nodeReduce();
  
// Main nodal reduction loop
 
logAdd("Handing program execution over to nodal reduction...");
 
for (this=0;1;this=0) nodeReduce();
 
  
 +
// ----------------------------------------------------------------------------------------- //
 +
// nodeSpace.c
 +
 +
// - use array-of-node path?
 +
node nodeTraverse(node subject,node key) {
 +
return listTraverse((item)subject,(item)key);
 +
}
 +
 +
// set nodal value of node/path
 +
// - allows null key
 +
node nodeGetValue(node subject,node key) {
 +
return listGetValue(key?listTraverse((item)subject,(item)key):(item)subject);
 +
}
 +
 +
node nodeSetValue(node subject,node key,node value) {
 +
// todo: onChange
 +
return listSetValue(key?listTraverse((item)subject,(item)key):(item)subject, (item)value);
 +
}
 +
 +
// Returns a newly created node
 +
node nodeInsert() {
 +
return (node)listInsert();
 +
}
 +
 +
// Returns newly created node
 +
// - this is just traverse() but with an event raised
 +
node nodeInsertKey(node subject,node key) {
 +
// todo: onInstall
 +
node i = nodeTraverse(subject,key);
 +
return i;
 +
}
 +
 +
// Returns the node that was removed
 +
node nodeRemoveKey(node subject,node key) {
 +
// todo: onRemove
 +
node i = nodeTraverse(subject,key);
 +
// todo: delete
 +
return i;
 +
}
 +
 +
// Returns the inserted node as the new loop pointer
 +
// - this allows it to act as a stack if nodeLOOP (current-loop-node) is updated with returned node
 +
// - either can be 0 on entry (for new loop and/or new node)
 +
node nodeLoopInsert(node subject,node insert) {
 +
if (insert == 0) insert = nodeInsert();
 +
if (subject == 0) subject = insert;
 +
node next = nodeGetValue(subject,nodeNEXT);
 +
nodeSetValue(insert,nodeNEXT,next);
 +
nodeSetValue(subject,nodeNEXT,insert);
 +
nodeSetValue(insert,nodePREV,subject);
 +
return nodeSetValue(next,nodePREV,insert);
 +
}
 +
 +
// Returns the new loop pointer so nodeLOOP can be removed and updated
 +
node nodeLoopRemove(node subject) {
 +
node prev = nodeGetValue(subject,nodePREV);
 +
node next = nodeGetValue(subject,nodeNEXT);
 +
nodeSetValue(next,nodePREV,prev);
 +
return nodeSetValue(prev,nodeNEXT,next);
 +
}
 +
 +
void **nodeState(node subject,node key) {
 +
return hash(itob(key?(int)listTraverse((item)subject,(item)key):(int)subject,nssBuf));
 +
}
 +
 +
// Clean up all the mess and exit
 +
void nodeExit() {
 +
logAdd("Gracefully exiting.");
 +
ifExit();
 +
ioExit();
 +
listExit();
 +
exit(EXIT_SUCCESS);
 +
}
 +
 +
 +
// Set up initial nodal structure
 +
// - todo: this structure should be read from [[[[nodeSpace.txt]]]]
 +
char *serialise(node);
 +
void deserialise(char*);
 +
int nodeInit() {
 +
 +
char *file = "*[[0|root]]\n*[[1000|io]];[[1001|interface]];\n*[[io]]\n*[[1002|server]];[[1003|streams]];\n*[[1004|stream]]\n*[[interface]]\n*[[1005|events]];[[1006|desktop]];\n*[[1007|window]]\n";
 +
 +
/* nodeIO = nodeLoopInsert(0,0);
 +
nodeINTERFACE = nodeLoopInsert(nodeIO,0);
 +
nodeSERVER = nodeLoopInsert(0,0);
 +
nodeSTREAMS = nodeLoopInsert(nodeSERVER,0);
 +
nodeSTREAM = nodeInsert();
 +
nodeEVENTS = nodeLoopInsert(0,0);
 +
nodeDESKTOP = nodeLoopInsert(nodeEVENTS,0);
 +
nodeWINDOW = nodeInsert();
 +
nodeSetValue(0,nodeLOOP,nodeIO);
 +
nodeSetValue(nodeIO,nodeLOOP,nodeSERVER);
 +
nodeSetValue(nodeINTERFACE,nodeLOOP,nodeEVENTS); */
 +
 +
deserialise(file);
 +
 +
nodeIO        = trieGetValue("io"); logAdd("nodeIO = %d",nodeIO);
 +
nodeINTERFACE = trieGetValue("interface"); logAdd("nodeINTERFACE = %d",nodeINTERFACE);
 +
nodeSERVER    = trieGetValue("server"); logAdd("nodeSERVER = %d",nodeSERVER);
 +
nodeSTREAMS  = trieGetValue("streams"); logAdd("nodeSTREAMS = %d",nodeSTREAMS);
 +
nodeSTREAM    = trieGetValue("stream"); logAdd("nodeSTREAM = %d",nodeSTREAM);
 +
nodeEVENTS    = trieGetValue("events"); logAdd("nodeEVENTS = %d",nodeEVENTS);
 +
nodeDESKTOP  = trieGetValue("desktop"); logAdd("nodeDESKTOP = %d",nodeDESKTOP);
 +
nodeWINDOW    = trieGetValue("window"); logAdd("nodeWINDOW = %d",nodeWINDOW);
 +
 +
return EXIT_SUCCESS;
 +
}
 +
 +
// Moves "this" to current loop item if exists then rotates loop and executes or reduces the item
 +
// - THEN may not be needed since by default things should stay the same
 +
//  ie. a function would have to set THEN to change, so why not change loop directly itself?
 +
void nodeReduce() {
 +
if (this = nodeGetValue(loop = nodeTraverse(this,nodeLOOP),0)) {            // this = current loop item
 +
nodeSetValue(loop,0,nodeGetValue(this,nodeNEXT));                      // Rotate loop
 +
nodeGetValue(this,nodeCODE)?((code*)*nodeState(this,0))():nodeReduce(); // Exec or reduce item
 +
}
 
}
 
}

Revision as of 23:50, 14 September 2006

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

typedef int node; // node: a type for referring to nodes typedef void (code)(); // code: a type for executing functions from pointer

// Reserved nodes used by nodal reduction process (tmp) // - doesn't matter that these node indexes conflict with 128 ascii nodes // because these will not currently need anything stored in them

  1. define nodeLOOP 1
  2. define nodeTRUE 1
  3. define nodeNEXT 2
  4. define nodePREV 3
  5. define nodeCODE 4

// Runtime nodes node this; // this: the current node, like cwd

// stateless node nodeINTERFACE; node nodeSTREAMS;

// function ref node nodeEVENTS; node nodeIO; node nodeSERVER; node nodeDESKTOP;

// pointer to struct node nodeSTREAM; node nodeWINDOW;


// Prototypes node nodeTraverse(node subject,node key); node nodeGetValue(node subject,node key); node nodeSetValue(node subject,node key,node value); node nodeInsertKey(node subject,node key); node nodeRemoveKey(node subject,node key); node nodeLoopInsert(node subject,node insert); node nodeLoopRemove(node subject); void **nodeGetState(node subject,node key); int nodeInit(); void nodeExit(); void nodeReduce();


// ----------------------------------------------------------------------------------------- // // nodeSpace.c

// - use array-of-node path? node nodeTraverse(node subject,node key) { return listTraverse((item)subject,(item)key); }

// set nodal value of node/path // - allows null key node nodeGetValue(node subject,node key) { return listGetValue(key?listTraverse((item)subject,(item)key):(item)subject); }

node nodeSetValue(node subject,node key,node value) { // todo: onChange return listSetValue(key?listTraverse((item)subject,(item)key):(item)subject, (item)value); }

// Returns a newly created node node nodeInsert() { return (node)listInsert(); }

// Returns newly created node // - this is just traverse() but with an event raised node nodeInsertKey(node subject,node key) { // todo: onInstall node i = nodeTraverse(subject,key); return i; }

// Returns the node that was removed node nodeRemoveKey(node subject,node key) { // todo: onRemove node i = nodeTraverse(subject,key); // todo: delete return i; }

// Returns the inserted node as the new loop pointer // - this allows it to act as a stack if nodeLOOP (current-loop-node) is updated with returned node // - either can be 0 on entry (for new loop and/or new node) node nodeLoopInsert(node subject,node insert) { if (insert == 0) insert = nodeInsert(); if (subject == 0) subject = insert; node next = nodeGetValue(subject,nodeNEXT); nodeSetValue(insert,nodeNEXT,next); nodeSetValue(subject,nodeNEXT,insert); nodeSetValue(insert,nodePREV,subject); return nodeSetValue(next,nodePREV,insert); }

// Returns the new loop pointer so nodeLOOP can be removed and updated node nodeLoopRemove(node subject) { node prev = nodeGetValue(subject,nodePREV); node next = nodeGetValue(subject,nodeNEXT); nodeSetValue(next,nodePREV,prev); return nodeSetValue(prev,nodeNEXT,next); }

void **nodeState(node subject,node key) { return hash(itob(key?(int)listTraverse((item)subject,(item)key):(int)subject,nssBuf)); }

// Clean up all the mess and exit void nodeExit() { logAdd("Gracefully exiting."); ifExit(); ioExit(); listExit(); exit(EXIT_SUCCESS); }


// Set up initial nodal structure // - todo: this structure should be read from [[nodeSpace.txt]] char *serialise(node); void deserialise(char*); int nodeInit() {

char *file = "*root\n*io;interface;\n*io\n*server;streams;\n*stream\n*interface\n*events;desktop;\n*window\n";

/* nodeIO = nodeLoopInsert(0,0); nodeINTERFACE = nodeLoopInsert(nodeIO,0); nodeSERVER = nodeLoopInsert(0,0); nodeSTREAMS = nodeLoopInsert(nodeSERVER,0); nodeSTREAM = nodeInsert(); nodeEVENTS = nodeLoopInsert(0,0); nodeDESKTOP = nodeLoopInsert(nodeEVENTS,0); nodeWINDOW = nodeInsert(); nodeSetValue(0,nodeLOOP,nodeIO); nodeSetValue(nodeIO,nodeLOOP,nodeSERVER); nodeSetValue(nodeINTERFACE,nodeLOOP,nodeEVENTS); */

deserialise(file);

nodeIO = trieGetValue("io"); logAdd("nodeIO = %d",nodeIO); nodeINTERFACE = trieGetValue("interface"); logAdd("nodeINTERFACE = %d",nodeINTERFACE); nodeSERVER = trieGetValue("server"); logAdd("nodeSERVER = %d",nodeSERVER); nodeSTREAMS = trieGetValue("streams"); logAdd("nodeSTREAMS = %d",nodeSTREAMS); nodeSTREAM = trieGetValue("stream"); logAdd("nodeSTREAM = %d",nodeSTREAM); nodeEVENTS = trieGetValue("events"); logAdd("nodeEVENTS = %d",nodeEVENTS); nodeDESKTOP = trieGetValue("desktop"); logAdd("nodeDESKTOP = %d",nodeDESKTOP); nodeWINDOW = trieGetValue("window"); logAdd("nodeWINDOW = %d",nodeWINDOW);

return EXIT_SUCCESS; }

// Moves "this" to current loop item if exists then rotates loop and executes or reduces the item // - THEN may not be needed since by default things should stay the same // ie. a function would have to set THEN to change, so why not change loop directly itself? void nodeReduce() { if (this = nodeGetValue(loop = nodeTraverse(this,nodeLOOP),0)) { // this = current loop item nodeSetValue(loop,0,nodeGetValue(this,nodeNEXT)); // Rotate loop nodeGetValue(this,nodeCODE)?((code*)*nodeState(this,0))():nodeReduce(); // Exec or reduce item } }