diff --git a/SuperNET/Makefile b/SuperNET/Makefile
index 7310ee0d1..90045f33c 100644
--- a/SuperNET/Makefile
+++ b/SuperNET/Makefile
@@ -8,12 +8,12 @@
VALID_TOOLCHAINS := pnacl newlib glibc clang-newlib mac
NACL_SDK_ROOT ?= $(abspath $(CURDIR))
-
TARGET = SuperNET
EXTRA= -D__PNACL
include $(NACL_SDK_ROOT)/tools/common.mk
+include SuperNET.sources
CHROME_ARGS += --allow-nacl-socket-api=127.0.0.1
@@ -23,7 +23,7 @@ LIBS = crypto777 nanomsg curl ssl crypto z glibc-compat nacl_spawn ppapi nacl_i
CFLAGS = -Wall -D__PNACL -fno-strict-aliasing $(EXTRA)
LFLAGS = libs
-SOURCES = main.c SuperNET.c
+SOURCES = $(SOURCES)
# Build rules generated by macros from common.mk:
diff --git a/SuperNET/SuperNET.c b/SuperNET/SuperNET.c
index d7a7a23ac..5f807e552 100644
--- a/SuperNET/SuperNET.c
+++ b/SuperNET/SuperNET.c
@@ -14,6 +14,139 @@
******************************************************************************/
#include "SuperNET.h"
+#define IGUANA_FORMS "[ \
+\
+{\"disp\":\"simple explorer\",\"agent\":\"ramchain\",\"method\":\"explore\",\"fields\":[{\"skip\":1,\"field\":\"search\",\"cols\":65,\"rows\":1}]}, \
+{\"disp\":\"block height\",\"agent\":\"ramchain\",\"method\":\"block\",\"fields\":[{\"field\":\"height\",\"cols\":10,\"rows\":1}]}, \
+{\"disp\":\"block hash\",\"agent\":\"ramchain\",\"method\":\"block\",\"fields\":[{\"field\":\"hash\",\"cols\":65,\"rows\":1}]}, \
+{\"disp\":\"txid\",\"agent\":\"ramchain\",\"method\":\"txid\",\"fields\":[{\"skip\":1,\"field\":\"hash\",\"cols\":65,\"rows\":1}]}, \
+{\"disp\":\"status\",\"agent\":\"ramchain\",\"method\":\"status\",\"fields\":[{\"skip\":1,\"field\":\"coin\",\"cols\":1,\"rows\":1}]}, \
+{\"disp\":\"bundleinfo\",\"agent\":\"ramchain\",\"method\":\"bundleinfo\",\"fields\":[{\"skip\":1,\"field\":\"height\",\"cols\":12,\"rows\":1}]}, \
+\
+{\"disp\":\"addcoin\",\"agent\":\"iguana\",\"method\":\"addcoin\",\"fields\":[{\"skip\":1,\"field\":\"coin\",\"cols\":8,\"rows\":1}]}, \
+{\"disp\":\"pausecoin\",\"agent\":\"iguana\",\"method\":\"pausecoin\",\"fields\":[{\"skip\":1,\"field\":\"coin\",\"cols\":1,\"rows\":1}]}, \
+{\"disp\":\"startcoin\",\"agent\":\"iguana\",\"method\":\"startcoin\",\"fields\":[{\"skip\":1,\"field\":\"coin\",\"cols\":1,\"rows\":1}]}, \
+{\"disp\":\"addnode\",\"agent\":\"iguana\",\"method\":\"addnode\",\"fields\":[{\"skip\":1,\"field\":\"ipaddr\",\"cols\":32,\"rows\":1}]}, \
+{\"disp\":\"maxpeers\",\"agent\":\"iguana\",\"method\":\"maxpeers\",\"fields\":[{\"skip\":1,\"field\":\"max\",\"cols\":8,\"rows\":1}]}, \
+{\"disp\":\"peers\",\"agent\":\"iguana\",\"method\":\"peers\",\"fields\":[{\"field\":\"coin\",\"cols\":16,\"rows\":1}]}, \
+{\"disp\":\"nodestatus\",\"agent\":\"iguana\",\"method\":\"nodestatus\",\"fields\":[{\"skip\":1,\"field\":\"ipaddr\",\"cols\":32,\"rows\":1}]}, \
+\
+{\"disp\":\"rates\",\"agent\":\"PAX\",\"method\":\"rates\",\"fields\":[{\"skip\":1,\"field\":\"peg\",\"cols\":16,\"rows\":1}]},\
+{\"disp\":\"prices\",\"agent\":\"PAX\",\"method\":\"prices\",\"fields\":[{\"skip\":1,\"field\":\"peg\",\"cols\":16,\"rows\":1}]},\
+{\"agent\":\"PAX\",\"method\":\"lock\",\"fields\":[{\"skip\":1,\"field\":\"peg\",\"cols\":16,\"rows\":1},{\"skip\":1,\"field\":\"lockdays\",\"cols\":6,\"rows\":1},{\"skip\":1,\"field\":\"units\",\"cols\":12,\"rows\":1}]}, \
+{\"agent\":\"PAX\",\"method\":\"redeem\",\"fields\":[{\"skip\":1,\"field\":\"txid\",\"cols\":65,\"rows\":1},{\"skip\":1,\"field\":\"dest\",\"cols\":65,\"rows\":1}]},\
+{\"disp\":\"balance\",\"agent\":\"PAX\",\"method\":\"balance\",\"fields\":[{\"skip\":1,\"field\":\"address\",\"cols\":44,\"rows\":1}]},\
+{\"agent\":\"PAX\",\"method\":\"rollover\",\"fields\":[{\"skip\":1,\"field\":\"txid\",\"cols\":16,\"rows\":1},{\"skip\":1,\"field\":\"newpeg\",\"cols\":16,\"rows\":1},{\"skip\":1,\"field\":\"newlockdays\",\"cols\":6,\"rows\":1}]},\
+{\"agent\":\"PAX\",\"method\":\"swap\",\"fields\":[{\"skip\":1,\"field\":\"txid\",\"cols\":16,\"rows\":1},{\"skip\":1,\"field\":\"othertxid\",\"cols\":16,\"rows\":1}]},\
+{\"agent\":\"PAX\",\"method\":\"bet\",\"fields\":[{\"skip\":1,\"field\":\"peg\",\"cols\":16,\"rows\":1},{\"skip\":1,\"field\":\"price\",\"cols\":16,\"rows\":1},{\"skip\":1,\"field\":\"amount\",\"cols\":16,\"rows\":1}]},\
+\
+{\"agent\":\"InstantDEX\",\"method\":\"placebid\",\"fields\":[{\"skip\":1,\"field\":\"base\",\"cols\":8,\"rows\":1},{\"skip\":1,\"field\":\"rel\",\"cols\":8,\"rows\":1},{\"skip\":1,\"field\":\"exchange\",\"cols\":16,\"rows\":1},{\"field\":\"price\",\"cols\":16,\"rows\":1},{\"field\":\"volume\",\"cols\":16,\"rows\":1}]}, \
+{\"agent\":\"InstantDEX\",\"method\":\"placeask\",\"fields\":[{\"skip\":1,\"field\":\"base\",\"cols\":8,\"rows\":1},{\"skip\":1,\"field\":\"rel\",\"cols\":8,\"rows\":1},{\"skip\":1,\"field\":\"exchange\",\"cols\":16,\"rows\":1},{\"field\":\"price\",\"cols\":16,\"rows\":1},{\"field\":\"volume\",\"cols\":16,\"rows\":1}]}, \
+{\"agent\":\"InstantDEX\",\"method\":\"orderbook\",\"fields\":[{\"skip\":1,\"field\":\"base\",\"cols\":8,\"rows\":1},{\"skip\":1,\"field\":\"rel\",\"cols\":8,\"rows\":1},{\"skip\":1,\"field\":\"exchange\",\"cols\":16,\"rows\":1}]}, \
+{\"disp\":\"orderstatus\",\"agent\":\"InstantDEX\",\"method\":\"orderstatus\",\"fields\":[{\"skip\":1,\"field\":\"orderid\",\"cols\":32,\"rows\":1}]}, \
+{\"disp\":\"cancelorder\",\"agent\":\"InstantDEX\",\"method\":\"cancelorder\",\"fields\":[{\"skip\":1,\"field\":\"orderid\",\"cols\":32,\"rows\":1}]}, \
+{\"disp\":\"balance\",\"agent\":\"InstantDEX\",\"method\":\"balance\",\"fields\":[{\"skip\":1,\"field\":\"exchange\",\"cols\":16,\"rows\":1}]}, \
+{\"newline\":0,\"disp\":\"allorderbooks\",\"agent\":\"InstantDEX\",\"method\":\"allorderbooks\",\"fields\":[{\"skip\":1,\"field\":\"allorderbooks\",\"cols\":1,\"rows\":1}]}, \
+{\"newline\":0,\"disp\":\"openorders\",\"agent\":\"InstantDEX\",\"method\":\"openorders\",\"fields\":[{\"skip\":1,\"field\":\"openorders\",\"cols\":1,\"rows\":1}]}, \
+{\"newline\":0,\"disp\":\"tradehistory\",\"agent\":\"InstantDEX\",\"method\":\"tradehistory\",\"fields\":[{\"skip\":1,\"field\":\"tradehistory\",\"cols\":1,\"rows\":1}]}, \
+{\"disp\":\"allexchanges\",\"agent\":\"InstantDEX\",\"method\":\"allexchanges\",\"fields\":[{\"skip\":1,\"field\":\"allexchanges\",\"cols\":1,\"rows\":1}]}, \
+\
+{\"agent\":\"pangea\",\"method\":\"bet\",\"fields\":[{\"skip\":1,\"field\":\"tableid\",\"cols\":24,\"rows\":1},{\"skip\":1,\"field\":\"amount\",\"cols\":24,\"rows\":1}]}, \
+{\"disp\":\"call\",\"agent\":\"pangea\",\"method\":\"call\",\"fields\":[{\"skip\":1,\"field\":\"tableid\",\"cols\":1,\"rows\":1}]}, \
+{\"disp\":\"fold\",\"agent\":\"pangea\",\"method\":\"fold\",\"fields\":[{\"skip\":1,\"field\":\"tableid\",\"cols\":1,\"rows\":1}]}, \
+{\"disp\":\"status\",\"agent\":\"pangea\",\"method\":\"status\",\"fields\":[{\"skip\":1,\"field\":\"tableid\",\"cols\":1,\"rows\":1}]}, \
+{\"disp\":\"hand history\",\"agent\":\"pangea\",\"method\":\"handhistory\",\"fields\":[{\"skip\":1,\"field\":\"tableid\",\"cols\":1,\"rows\":1}]}, \
+{\"disp\":\"history\",\"agent\":\"pangea\",\"method\":\"history\",\"fields\":[{\"skip\":1,\"field\":\"coin\",\"cols\":1,\"rows\":1}]}, \
+{\"disp\":\"follow\",\"agent\":\"pangea\",\"method\":\"follow\",\"fields\":[{\"skip\":1,\"field\":\"tableid\",\"cols\":24,\"rows\":1}]}, \
+{\"disp\":\"lobby\",\"agent\":\"pangea\",\"method\":\"lobby\",\"fields\":[{\"skip\":1,\"field\":\"coin\",\"cols\":8,\"rows\":1}]}, \
+{\"disp\":\"join\",\"agent\":\"pangea\",\"method\":\"join\",\"fields\":[{\"skip\":1,\"field\":\"tableid\",\"cols\":24,\"rows\":1}]}, \
+{\"agent\":\"pangea\",\"method\":\"buyin\",\"fields\":[{\"skip\":1,\"field\":\"coin\",\"cols\":8,\"rows\":1},{\"skip\":1,\"field\":\"tableid\",\"cols\":24,\"rows\":1},{\"skip\":1,\"field\":\"amount\",\"cols\":12,\"rows\":1}]}, \
+{\"agent\":\"pangea\",\"method\":\"newtournament\",\"fields\":[{\"field\":\"mintables\",\"cols\":8,\"rows\":1},{\"field\":\"maxtables\",\"cols\":4,\"rows\":1},{\"field\":\"starttime\",\"cols\":16,\"rows\":1},{\"field\":\"prizefund\",\"cols\":12,\"rows\":1},{\"field\":\"coin\",\"cols\":12,\"rows\":1}]}, \
+{\"agent\":\"pangea\",\"method\":\"newtable\",\"fields\":[{\"field\":\"minplayers\",\"cols\":4,\"rows\":1},{\"field\":\"maxplayers\",\"cols\":4,\"rows\":1},{\"field\":\"rake\",\"cols\":4,\"rows\":1},{\"field\":\"bigblind\",\"cols\":12,\"rows\":1},{\"field\":\"ante\",\"cols\":12,\"rows\":1},{\"field\":\"minbuyin\",\"cols\":12,\"rows\":1},{\"field\":\"maxbuyin\",\"cols\":12,\"rows\":1}]}, \
+{\"disp\":\"leave\",\"agent\":\"pangea\",\"method\":\"leave\",\"fields\":[{\"skip\":1,\"field\":\"tableid\",\"cols\":8,\"rows\":1}]}, \
+\
+{\"agent\":\"jumblr\",\"method\":\"send\",\"fields\":[{\"skip\":1,\"field\":\"coin\",\"cols\":8,\"rows\":1},{\"skip\":1,\"field\":\"amount\",\"cols\":13,\"rows\":1},{\"skip\":1,\"field\":\"address\",\"cols\":8,\"rows\":1}]}, \
+{\"agent\":\"jumblr\",\"method\":\"invoice\",\"fields\":[{\"skip\":1,\"field\":\"coin\",\"cols\":8,\"rows\":1},{\"skip\":1,\"field\":\"amount\",\"cols\":13,\"rows\":1},{\"skip\":1,\"field\":\"address\",\"cols\":8,\"rows\":1}]}, \
+{\"agent\":\"jumblr\",\"method\":\"shuffle\",\"fields\":[{\"skip\":1,\"field\":\"coin\",\"cols\":8,\"rows\":1},{\"skip\":1,\"field\":\"amount\",\"cols\":13,\"rows\":1}]}, \
+{\"agent\":\"jumblr\",\"method\":\"balance\",\"fields\":[{\"skip\":1,\"field\":\"coin\",\"cols\":8,\"rows\":1},{\"skip\":1,\"field\":\"address\",\"cols\":13,\"rows\":1}]}, \
+\
+{\"newline\":0,\"disp\":\"InstantDEX\",\"agent\":\"iguana\",\"method\":\"setagent\",\"fields\":[{\"field\":\"InstantDEX\",\"cols\":1,\"rows\":1}]}, \
+{\"newline\":0,\"disp\":\"PAX\",\"agent\":\"iguana\",\"method\":\"setagent\",\"fields\":[{\"field\":\"PAX\",\"cols\":1,\"rows\":1}]}, \
+{\"newline\":0,\"disp\":\"pangea\",\"agent\":\"iguana\",\"method\":\"setagent\",\"fields\":[{\"field\":\"pangea\",\"cols\":1,\"rows\":1}]}, \
+{\"newline\":0,\"disp\":\"jumblr\",\"agent\":\"iguana\",\"method\":\"setagent\",\"fields\":[{\"field\":\"jumblr\",\"cols\":1,\"rows\":1}]}, \
+{\"disp\":\"ramchain\",\"agent\":\"iguana\",\"method\":\"setagent\",\"fields\":[{\"field\":\"ramchain\",\"cols\":1,\"rows\":1}]}, \
+{\"newline\":0,\"disp\":\"iguana\",\"agent\":\"iguana\",\"method\":\"setagent\",\"fields\":[{\"field\":\"iguana\",\"cols\":1,\"rows\":1}]}, \
+\
+{\"agent\":\"hash\",\"method\":\"NXT\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":100,\"rows\":1}]}, \
+{\"agent\":\"hash\",\"method\":\"curve25519\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"rmd160_sha256\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"sha256_sha256\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"base64_encode\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"base64_decode\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"crc32\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"sha512\",\"fields\":[{\"skip\":1,\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"sha384\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"sha256\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"sha224\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"rmd320\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"rmd256\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"rmd160\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"rmd128\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"sha1\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"md2\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"md4\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"md5\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"tiger\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"whirlpool\",\"fields\":[{\"skip\":1,\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"hmac_sha512\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":32,\"rows\":1},{\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"hmac_sha384\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":32,\"rows\":1},{\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"hmac_sha256\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":32,\"rows\":1},{\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"hmac_sha224\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":32,\"rows\":1},{\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"hmac_rmd320\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":32,\"rows\":1},{\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"hmac_rmd256\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":32,\"rows\":1},{\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"hmac_rmd160\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":32,\"rows\":1},{\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"hmac_rmd128\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":32,\"rows\":1},{\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"hmac_sha1\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":32,\"rows\":1},{\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"hmac_md2\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":32,\"rows\":1},{\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"hmac_md4\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":32,\"rows\":1},{\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"hmac_md5\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":32,\"rows\":1},{\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"hmac_tiger\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":32,\"rows\":1},{\"field\":\"message\",\"cols\":64,\"rows\":3}]}, \
+{\"agent\":\"hash\",\"method\":\"hmac_whirlpool\",\"fields\":[{\"skip\":1,\"field\":\"password\",\"cols\":32,\"rows\":1},{\"field\":\"message\",\"cols\":64,\"rows\":3}]}\
+]"
+
+char *HTMLheader =
+" \
+ \
+
\
+ \
+ \
+iguana \
+ \
+ \
+\
+ \
+";
+
+// Link
+
+char *HTMLfooter =
+" \
+\
+ \
+ \
+\
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+\
+ \
+";
+
+#define HTML_EMIT(str) if ( (str) != 0 && (str)[0] != 0 ) strcpy(&retbuf[size],str), size += (int32_t)strlen(str)
/*
struct endpoint find_epbits(struct relay_info *list,uint32_t ipbits,uint16_t port,int32_t type)
@@ -265,3 +398,339 @@ void SuperNET_init(struct supernet_info *myinfo,char *jsonstr)
init_SUPERNET_pullsock(myinfo,10,10);
}*/
+int32_t Supernet_lineparse(char *key,int32_t keymax,char *value,int32_t valuemax,char *src)
+{
+ int32_t a,b,c,n = 0;
+ key[0] = value[0] = 0;
+ while ( (c= src[n]) == ' ' || c == '\t' || c == '\n' || c == '\t' )
+ n++;
+ while ( (c= src[n]) != ':' && c != 0 )
+ {
+ *key++ = c;
+ if ( ++n >= keymax-1 )
+ {
+ *key = 0;
+ printf("lineparse overflow key.(%s)\n",src);
+ return(-1);
+ }
+ }
+ *key = 0;
+ if ( src[n] != ':' )
+ return(n);
+ n++;
+ while ( (c= src[n]) == ' ' || c == '\t' )
+ n++;
+ while ( (c= src[n]) != 0 && c != '\r' && c != '\n' )
+ {
+ if ( c == '%' && (a= src[n+1]) != 0 && (b= src[n+2]) != 0 )
+ c = ((unhex(a) << 4) | unhex(b)), n += 2;
+ *value++ = c;
+ n++;
+ if ( n >= valuemax-1 )
+ {
+ *value = 0;
+ printf("lineparse overflow.(%s)\n",src);
+ return(-1);
+ }
+ }
+ *value = 0;
+ if ( src[n] != 0 )
+ {
+ n++;
+ while ( (c= src[n]) == '\r' || c == '\n' )
+ n++;
+ }
+ return(n);
+}
+
+cJSON *SuperNET_urlconv(char *value,int32_t bufsize,char *urlstr)
+{
+ int32_t i,n,totallen,datalen,len = 0; cJSON *json,*array; char key[8192],*data;
+ json = cJSON_CreateObject();
+ array = cJSON_CreateArray();
+ totallen = (int32_t)strlen(urlstr);
+ while ( 1 )
+ {
+ for (i=len; urlstr[i]!=0; i++)
+ if ( urlstr[i] == '\r' || urlstr[i] == '\n' )
+ break;
+ if ( i == len && (urlstr[len] == '\r' || urlstr[len] == '\n') )
+ {
+ len++;
+ continue;
+ }
+ urlstr[i] = 0;
+ if ( (n= Supernet_lineparse(key,sizeof(key),value,bufsize,&urlstr[len])) > 0 )
+ {
+ if ( value[0] != 0 )
+ jaddstr(json,key,value);
+ else jaddistr(array,key);
+ len += (n + 1);
+ if ( strcmp(key,"Content-Length") == 0 && (datalen= atoi(value)) > 0 )
+ {
+ data = &urlstr[totallen - datalen];
+ data[-1] = 0;
+ //printf("post.(%s) (%c)\n",data,data[0]);
+ jaddstr(json,"POST",data);
+ }
+ } else break;
+ }
+ jadd(json,"lines",array);
+ return(json);
+}
+
+char *SuperNET_rpcparse(struct supernet_info *myinfo,char *retbuf,int32_t bufsize,int32_t *postflagp,char *urlstr,char *remoteaddr)
+{
+ cJSON *tokens,*argjson,*json = 0; char urlmethod[16],*data,url[1024],*retstr,*token = 0; int32_t i,j,n;
+ //printf("rpcparse.(%s)\n",urlstr);
+ for (i=0; i 0 )
+ {
+ jaddstr(argjson,"agent",jstri(tokens,0));
+ if ( n > 1 )
+ jaddstr(argjson,"method",jstri(tokens,1));
+ for (i=2; i (%s) postflag.%d (%s)\n",urlstr,cJSON_Print(json),*postflagp,jprint(argjson,0));
+ return(retstr);
+ }
+ return(clonestr("{\"error\":\"couldnt process packet\"}"));
+}
+
+#ifdef notyet
+int32_t iguana_htmlgen(char *retbuf,int32_t bufsize,char *result,char *error,cJSON *json,char *tabname,char *origjsonstr)
+{
+ char *url = "http://127.0.0.1:7778";
+ int i,j,m,size = 0,n,rows,cols; cJSON *array,*obj,*array2,*item,*tmp;
+ char formheader[512],formfooter[512],clickname[512],buf[512],fieldbuf[512],fieldindex[2],postjson[8192];
+ char *disp,*fieldname,*button,*agent,*method,*str;
+ bufsize--;
+ HTML_EMIT(" ");
+ sprintf(buf,"
");
+ //sprintf(buf,"
COIN: ");
+ //HTML_EMIT(buf);
+ //HTML_EMIT(" Agent: "); HTML_EMIT(Default_agent);
+
+ HTML_EMIT("
");
+ HTML_EMIT(origjsonstr); HTML_EMIT(" -> ");
+ HTML_EMIT("");
+ formheader[0] = formfooter[0] = 0;
+ if ( (array= jarray(&n,json,"forms")) != 0 )
+ {
+ for (i=0; i function click_%s()\n{\n",clickname);
+ HTML_EMIT(buf);
+ sprintf(postjson,"%s/%s",agent,method);
+ //printf("form.%s button.%s [%s]\n",formname,button,postjson);
+ if ( (array2= jarray(&m,item,"fields")) != 0 )
+ {
+ //sprintf(buf,"COIN = document.COIN_NAME.value;\n");
+ //sprintf(postjson+strlen(postjson),"/%s/' + %s + '","coin","COIN");
+ for (j=0; j (%s)\n",j,jprint(obj,0));
+ sprintf(fieldindex,"%c",'A'+j);
+ if ( (fieldname= jstr(obj,"field")) != 0 )
+ {
+ sprintf(buf,"%s = document.%s.%s.value;\n",fieldindex,clickname,fieldname);
+ HTML_EMIT(buf);
+ //sprintf(postjson+strlen(postjson),",\"%s\":\"' + %s + '\"",fieldname,fieldindex);
+ if ( juint(obj,"skip") == 0 )
+ sprintf(postjson+strlen(postjson),"/%s/' + %s + '",fieldname,fieldindex);
+ else sprintf(postjson+strlen(postjson),"/' + %s + '",fieldindex);
+ }
+ }
+ //strcat(postjson,"}");
+ sprintf(&retbuf[size],"location.href = '%s/%s';\n}\r\n",url,postjson), size += strlen(&retbuf[size]);
+ sprintf(formheader,"",button,clickname);
+ HTML_EMIT(formfooter);
+ }
+ }
+ }
+ HTML_EMIT("
"); HTML_EMIT(""); HTML_EMIT("
");
+ return((int32_t)strlen(retbuf));
+}
+#undef HTML_EMIT
+
+char *SuperNET_htmlresponse(char *retbuf,int32_t bufsize,int32_t *remainsp,int32_t localaccess,char *retstr,int32_t freeflag)
+{
+ static char *html = " %s ";
+ char *result=0,*error=0; int32_t n; cJSON *json,*formsjson;
+ retbuf[0] = 0;
+ /*if ( localaccess == 0 )
+ sprintf(retbuf+strlen(retbuf),"Access-Control-Allow-Origin: *\r\n");
+ else sprintf(retbuf+strlen(retbuf),"Access-Control-Allow-Origin: null\r\n");
+ sprintf(retbuf+strlen(retbuf),"Access-Control-Allow-Credentials: true\r\n");
+ sprintf(retbuf+strlen(retbuf),"Access-Control-Allow-Headers: Authorization, Content-Type\r\n");
+ sprintf(retbuf+strlen(retbuf),"Access-Control-Allow-Methods: GET, POST\r\n");
+ sprintf(retbuf+strlen(retbuf),"Cache-Control: no-cache, no-store, must-revalidate\r\n");
+ sprintf(retbuf+strlen(retbuf),"Content-type: text/html\r\n");
+ sprintf(retbuf+strlen(retbuf),"Content-Length: %8d\r\n\r\n",n);*/
+ sprintf(retbuf+strlen(retbuf),"\n\r");
+ n = (int32_t)strlen(retbuf);
+ formsjson = cJSON_Parse(IGUANA_FORMS);
+ if ( (json= cJSON_Parse(retstr)) == 0 )
+ json = cJSON_CreateObject();
+ jadd(json,"forms",formsjson);
+ error = jstr(json,"error");
+ result = jstr(json,"result");
+ //printf("process.(%s)\n",jprint(formsjson,0));
+ n = iguana_htmlgen(&retbuf[n],bufsize-n,result,error,json,"iguana",Currentjsonstr);
+ free_json(json);
+ if ( n == 0 )
+ {
+ n = (int32_t)(strlen(html) + strlen(retstr) + 1);
+ sprintf(retbuf+strlen(retbuf),html,retstr);
+ }
+ if ( freeflag != 0 )
+ free(retstr);
+ if ( n > bufsize )
+ {
+ printf("htmlresponse overflowed buffer[%d] with %d\n",bufsize,n);
+ exit(-1);
+ }
+ *remainsp = n;
+ return(retbuf);
+}
+#endif
diff --git a/SuperNET/SuperNET.h b/SuperNET/SuperNET.h
index c9e7efb55..7a3f7fd29 100644
--- a/SuperNET/SuperNET.h
+++ b/SuperNET/SuperNET.h
@@ -20,7 +20,7 @@
#include "../includes/cJSON.h"
#include "../includes/nanomsg/nn.h"
-#define SUPERNET_PORT 7774
+#define SUPERNET_PORT 7778
#define SUPERNET_NETWORKTIMEOUT 10000
#define SUPERNET_POLLTIMEOUT 1
#define SUPERNET_APIUSLEEP (SUPERNET_POLLTIMEOUT * 10000)
@@ -83,6 +83,8 @@ struct endpoint calc_epbits(char *transport,uint32_t ipbits,uint16_t port,int32_
int32_t badass_servers(char servers[][MAX_SERVERNAME],int32_t max,int32_t port);
int32_t crackfoo_servers(char servers[][MAX_SERVERNAME],int32_t max,int32_t port);
void SuperNET_init();
+char *SuperNET_JSON(struct supernet_info *myinfo,cJSON *argjson,char *remoteaddr);
+char *SuperNET_rpcparse(struct supernet_info *myinfo,char *retbuf,int32_t bufsize,int32_t *postflagp,char *urlstr,char *remoteaddr);
extern int32_t PULLsock;
extern struct relay_info RELAYS;
diff --git a/SuperNET/m_osx b/SuperNET/m_osx
index edf4f7b28..8ec8d6032 100755
--- a/SuperNET/m_osx
+++ b/SuperNET/m_osx
@@ -1 +1 @@
-gcc -o ../agents/SuperNET -O2 *.c ../agents/libcrypto777.a -lssl -lcrypto -lpthread -lm
+gcc -o ../agents/SuperNET -O2 *.c ../agents/libcrypto777.a -lnanomsg -lssl -lcrypto -lpthread -lm
diff --git a/SuperNET/m_unix b/SuperNET/m_unix
index a2dff2084..8ec8d6032 100755
--- a/SuperNET/m_unix
+++ b/SuperNET/m_unix
@@ -1 +1 @@
-gcc -o ../agents/SuperNET -O2 *.c ../agents/libcrypto777.a -lssl -lcrypto -lpthread -lm
+gcc -o ../agents/SuperNET -O2 *.c ../agents/libcrypto777.a -lnanomsg -lssl -lcrypto -lpthread -lm
diff --git a/SuperNET/main.c b/SuperNET/main.c
index 2d13dea5b..1ba57afe1 100644
--- a/SuperNET/main.c
+++ b/SuperNET/main.c
@@ -162,11 +162,6 @@ int32_t SuperNET_msgvalidate(struct supernet_msghdr *msg)
return(msglen);
}
-char *SuperNET_JSON(struct supernet_info *myinfo,char *jsonstr)
-{
- return(clonestr("{\"error\":\"SuperNET is just a stub for now\"}"));
-}
-
int32_t nn_settimeouts(int32_t sock,int32_t sendtimeout,int32_t recvtimeout)
{
int32_t retrymillis,maxmillis;
@@ -215,25 +210,10 @@ int32_t nn_createsocket(struct supernet_info *myinfo,char *endpoint,int32_t bind
bits256 SuperNET_OPRETURN(struct supernet_info *myinfo,char *symbol,double fee,uint8_t *buf,int32_t len)
{
bits256 txid;
+ printf("send OPRETURN\n");
return(txid);
}
-/*int32_t SuperNET_OPRETURN(uint8_t *data,char *announce)
-{
- static char *protocols[][2] = { {"pangea","GEA"}, {"peggy","PAX"} };
- int32_t i;
- for (i=0; i= 0 )
+ {
+ clilen = sizeof(cli_addr);
+ //printf("ACCEPT (%s:%d) on sock.%d\n","127.0.0.1",port,bindsock);
+ sock = accept(bindsock,(struct sockaddr *)&cli_addr,&clilen);
+ if ( sock < 0 )
+ {
+ //printf("iguana_rpcloop ERROR on accept usock.%d\n",sock);
+ continue;
+ }
+ memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits));
+ expand_ipbits(remoteaddr,ipbits);
+ memset(jsonbuf,0,sizeof(jsonbuf));
+ remains = (int32_t)(sizeof(jsonbuf) - 1);
+ buf = jsonbuf;
+ recvlen = 0;
+ retstr = 0;
+ while ( remains > 0 )
+ {
+ if ( (len= (int32_t)recv(sock,buf,remains,0)) < 0 )
+ {
+ if ( errno == EAGAIN )
+ {
+ printf("EAGAIN for len %d, remains.%d\n",len,remains);
+ usleep(10000);
+ }
+ break;
+ }
+ else
+ {
+ if ( len > 0 )
+ {
+ remains -= len;
+ recvlen += len;
+ buf = &buf[len];
+ retstr = SuperNET_rpcparse(myinfo,space,size,&postflag,jsonbuf,remoteaddr);
+ break;
+ } else usleep(10000);
+ }
+ }
+ if ( retstr != 0 )
+ {
+ i = 0;
+ if ( postflag == 0 )
+ {
+ //retstr = SuperNET_htmlresponse(space,size,&remains,1,retstr,1);
+ }
+ else remains = (int32_t)strlen(retstr);
+ printf("RETBUF.(%s)\n",retstr);
+ while ( remains > 0 )
+ {
+ if ( (numsent= (int32_t)send(sock,&retstr[i],remains,MSG_NOSIGNAL)) < 0 )
+ {
+ if ( errno != EAGAIN && errno != EWOULDBLOCK )
+ {
+ //printf("%s: %s numsent.%d vs remains.%d len.%d errno.%d (%s) usock.%d\n",retstr,ipaddr,numsent,remains,recvlen,errno,strerror(errno),sock);
+ break;
+ }
+ }
+ else if ( remains > 0 )
+ {
+ remains -= numsent;
+ i += numsent;
+ if ( remains > 0 )
+ printf("iguana sent.%d remains.%d of len.%d\n",numsent,remains,recvlen);
+ }
+ }
+ if ( retstr != space )
+ free(retstr);
+ }
+ //printf("done response sock.%d\n",sock);
+ closesocket(sock);
+ }
+}
+
int32_t SuperNET_msgrecv(struct supernet_info *myinfo,struct supernet_agent *agent,uint8_t *_buf,int32_t maxlen)
{
int32_t len,recvlen; void *buf = _buf; struct supernet_msghdr H;
@@ -647,7 +720,7 @@ void SuperNET_loop(struct supernet_info *myinfo)
void SuperNET_main(void *arg)
{
- struct supernet_info MYINFO; cJSON *json,*array; uint16_t port; int32_t i,n = 0;
+ struct supernet_info MYINFO; int32_t i;//cJSON *json,*array; uint16_t port;,n = 0;
memset(&MYINFO,0,sizeof(MYINFO));
if ( 1 )
{
@@ -658,8 +731,8 @@ void SuperNET_main(void *arg)
if ( MYINFO.POLLTIMEOUT == 0 )
MYINFO.POLLTIMEOUT = SUPERNET_POLLTIMEOUT;
}
- if ( arg == 0 || (json= cJSON_Parse(arg)) == 0 )
- SuperNET_acceptport(&MYINFO,MYINFO.port);
+ /*if ( arg == 0 || (json= cJSON_Parse(arg)) == 0 )
+ SuperNET_acceptport(&MYINFO,MYINFO.acceptport);
else
{
if ( (array= jarray(&n,json,"accept")) != 0 )
@@ -669,9 +742,9 @@ void SuperNET_main(void *arg)
SuperNET_acceptport(&MYINFO,port);
}
free_json(json);
- }
- sleep(3);
- printf("start SuperNET_loop on port.%u\n",MYINFO.port);
+ }*/
+ printf("start SuperNET_loop on port.%u\n",SUPERNET_PORT);
+ OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)SuperNET_rpcloop,&MYINFO);
for (i=0; i datenum + number of seconds
+ checkval = OS_conv_datenum(datenum,seconds/3600,(seconds/60)%60,seconds%60); // datenum+H:M:S -> unix time
+ if ( checkval != timestamp )
+ printf("%s i.%lld timestamp.%-12llu -> (%d:%06d) -> checkval.%-12llu diff.[%lld]\n",tai_str(str,t),(long long)i,(long long)timestamp,datenum,seconds,(long long)checkval,(long long)(timestamp-checkval));
+ }
+ printf("million tai compares in %.3f microseconds per encode/decode\n",1000. * (OS_milliseconds()-startmillis)/i);
+ }
return 0;
}
#endif
diff --git a/crypto777/ccgi.c b/crypto777/ccgi.c
new file mode 100755
index 000000000..e42349033
--- /dev/null
+++ b/crypto777/ccgi.c
@@ -0,0 +1,1328 @@
+/*
+ * C CGI Library version 1.1
+ *
+ * Author: Stephen C. Losen, University of Virginia
+ *
+ * Copyright 2009 Stephen C. Losen. Distributed under the terms
+ * of the GNU General Public License (GPL)
+ *
+ * C CGI is a C language library for parsing, decoding, storing and
+ * retrieving data passed from a web browser to a CGI program. C CGI
+ * supports URL encoded form data (application/x-www-form-urlencoded)
+ * and multipart (mutlipart/form-data), including file uploads. HTML
+ * cookies can also be stored and retrieved.
+ *
+ * The library builds one or more "variable lists" of type
+ * CGI_varlist. A list entry consists of a name (null terminated
+ * string) and one or more values (also null terminated strings)
+ * associated with the name. We allow multiple values because 1)
+ * some HTML form elements (such as checkboxes and selections)
+ * allow the form user to select multiple values and 2) different
+ * form elements may be given the same name.
+ *
+ * The library function CGI_lookup_all() searches a variable list for
+ * an entry with the specified name and returns the values in a
+ * null terminated array of pointers to null terminated strings.
+ *
+ * Variable list entries can be obtained iteratively with
+ * CGI_first_name(), CGI_next_name() and CGI_lookup_all().
+ *
+ * For a file upload, the user provides a filename template that
+ * is passed to mkstemp() to create a new file to hold the data.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "../includes/ccgi.h"
+#ifdef _WIN32
+#define mkstemp(name) _mktemp_s(name, sizeof(name))
+#endif
+
+/* CGI_val is an entry in a list of variable values */
+
+typedef struct CGI_val CGI_val;
+
+struct CGI_val {
+ CGI_val *next; /* next entry on list */
+ const char value[1]; /* variable value */
+};
+
+/*
+ * CGI_varlist is an entry in a list of variables. The fields
+ * "iter" and "tail" are only used in the first list entry.
+ */
+
+struct CGI_varlist {
+ CGI_varlist *next; /* next entry on list */
+ CGI_varlist *tail; /* last entry on list */
+ CGI_varlist *iter; /* list iteration pointer */
+ int numvalue; /* number of values */
+ CGI_val *value; /* linked list of values */
+ CGI_val *valtail; /* last value on list */
+ CGI_value *vector; /* array of values */
+ const char varname[1]; /* variable name */
+};
+
+/* strbuf is a string buffer of arbitrary size */
+
+typedef struct {
+ int size;
+ char str[1];
+}
+strbuf;
+
+/* mymalloc() is a malloc() wrapper that exits on failure */
+
+static void *
+mymalloc(int size) {
+ void *ret = malloc(size);
+ if (ret == 0) {
+ fputs("C CGI Library out of memory\n", stderr);
+ exit(1);
+ }
+ return ret;
+}
+
+/*
+ * sb_get() creates or extends a strbuf
+ */
+
+static strbuf *
+sb_get(strbuf *sb, int len) {
+ int size;
+ for (size = 128; size < len; size += size)
+ ;
+ if (sb == 0) {
+ sb = (strbuf *) mymalloc(sizeof(*sb) + size);
+ }
+ else {
+ sb = (strbuf *) realloc(sb, sizeof(*sb) + size);
+ if (sb == 0) {
+ fputs("C CGI Library out of memory\n", stderr);
+ exit(1);
+ }
+ }
+ sb->size = size;
+ return sb;
+}
+
+/* savechar() saves a character in a strbuf at index idx */
+
+static strbuf *
+savechar(strbuf *sb, int idx, int c) {
+ if (sb == 0 || idx >= sb->size) {
+ sb = sb_get(sb, idx + 1);
+ }
+ sb->str[idx] = c;
+ return sb;
+}
+
+/* savestr() saves a string in a strbuf */
+
+static strbuf *
+savestr(strbuf *sb, const char *str) {
+ int len = (int)strlen(str);
+ if (sb == 0 || len >= sb->size) {
+ sb = sb_get(sb, len + 1);
+ }
+ strcpy(sb->str, str);
+ return sb;
+}
+
+/*
+ * findvar() searches variable list "v" for an entry whose name
+ * is "varname" and returns a pointer to the entry or else null
+ * if not found. If varname is null then we return v->iter,
+ * which is the "current" variable entry.
+ */
+
+static CGI_varlist *
+findvar(CGI_varlist *v, const char *varname) {
+ if (varname == 0 && v != 0) {
+ return v->iter;
+ }
+ for (; v != 0; v = v->next) {
+ if (v->varname[0] == varname[0] &&
+ strcmp(v->varname, varname) == 0)
+ {
+ break;
+ }
+ }
+ return v;
+}
+
+/*
+ * hex() returns the numeric value of hexadecimal digit "digit"
+ * or returns -1 if "digit" is not a hexadecimal digit.
+ */
+
+static int
+hex(int digit) {
+ switch(digit) {
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ return digit - '0';
+
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ return 10 + digit - 'A';
+
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ return 10 + digit - 'a';
+
+ default:
+ return -1;
+ }
+}
+
+/* urlcount() returns the number of bytes needed to URL encode a string */
+
+static int
+urlcount(const char *p, const char *keep) {
+ int k;
+ for (k = 0; *p != 0; p++) {
+ if (isalnum((int32_t)*p) || *p == ' ' ||
+ (keep != 0 && strchr(keep, *p) != 0))
+ {
+ k++;
+ }
+ else {
+ k += 3;
+ }
+ }
+ return k;
+}
+
+/*
+ * urlencode() URL encodes string "in" into string "out" and
+ * returns a pointer to the null byte at the end of "out"
+ */
+
+static char *
+urlencode(const char *in, char *out, const char *keep) {
+ const char hexdigit[] = "0123456789ABCDEF";
+
+ for (; *in != 0; in++) {
+ if (isalnum((int32_t)*in) ||
+ (keep != 0 && strchr(keep, *in) != 0))
+ {
+ *out++ = *in;
+ }
+ else if (*in == ' ') {
+ *out++ = '+';
+ }
+ else {
+ *out++ = '%';
+ *out++ = hexdigit[(*in >> 4) & 0xf];
+ *out++ = hexdigit[*in & 0xf];
+ }
+ }
+ *out = 0;
+ return out;
+}
+
+/* scanspaces() scans over spaces and tabs in a string */
+
+static char *
+scanspaces(char *p) {
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ return p;
+}
+
+/*
+ * scanattr() scans for an attribute such as name="value" or
+ * name=value; saving the attribute name in attr[0] and saving
+ * the attribute value in attr[1]. If successful, we return a
+ * pointer to where the scan ended, otherwise we return null.
+ * The input string is modified.
+ */
+
+static char *
+scanattr(char *p, char *attr[2]) {
+ int quote = 0;
+
+ attr[0] = p = scanspaces(p);
+ while (*p != '=' && *p != 0) {
+ p++;
+ }
+ if (*p != '=' || p == attr[0]) {
+ return 0;
+ }
+ *p++ = 0;
+ if (*p == '"' || *p == '\'' || *p == '`') {
+ quote = *p++;
+ }
+ attr[1] = p;
+ if (quote != 0) {
+ while(*p != quote && *p != 0) {
+ p++;
+ }
+ if (*p != quote) {
+ return 0;
+ }
+ *p++ = 0;
+ if (*p == ';') {
+ p++;
+ }
+ }
+ else {
+ while (*p != ';' && *p != ' ' && *p != '\t' &&
+ *p != '\r' && *p != '\n' && *p != 0)
+ {
+ p++;
+ }
+ if (*p != 0) {
+ *p++ = 0;
+ }
+ }
+ return p;
+}
+
+/*
+ * scanheader() scans a line of input for a header name followed by
+ * a colon and the header value, such as:
+ *
+ * Content-Disposition: form-data;
+ *
+ * We place the header name in header[0] and the value in header[1].
+ * If successful we return a pointer to the character where the scan
+ * ended, otherwise we return null. The input string is modified.
+ */
+
+static char *
+scanheader(char *p, char *header[2]) {
+ if (isalnum((int32_t)*p) == 0) {
+ return 0;
+ }
+ header[0] = p;
+ while (*p != ':' && *p != 0) {
+ p++;
+ }
+ if (*p != ':') {
+ return 0;
+ }
+ *p++ = 0;
+ header[1] = p = scanspaces(p);
+ while (*p != ';' && *p != '\r' && *p != '\n' && *p != 0) {
+ p++;
+ }
+ if (*p != 0) {
+ *p++ = 0;
+ }
+ return p;
+}
+
+/*
+ * readline() reads characters from open file "in" into strbuf "line".
+ * We stop reading when we encounter '\n' or end of file. We null
+ * terminate "line" and return it. We return null if we encounter
+ * end of file without reading any characters.
+ */
+
+static strbuf *
+readline(strbuf *line, FILE *in) {
+ int c, i = 0;
+
+ while ((c = getc(in)) != EOF) {
+ line = savechar(line, i++, c);
+ if (c == '\n') {
+ break;
+ }
+ }
+ if (i == 0) {
+ if (line != 0) {
+ free(line);
+ }
+ return 0;
+ }
+ return savechar(line, i, 0); /* null terminate */
+}
+
+/*
+ * copyvalue() reads bytes from open file "in", which contains
+ * "multipart/form-data", delimited by "boundary". We read
+ * bytes until we encounter the boundary. If the flag "wantfile"
+ * is true then we write the bytes (minus the boundary) to open
+ * file pointer "out" (or discard the output if "out" is NULL).
+ * Otherwise we copy the bytes to "value".
+ */
+
+static strbuf *
+copyvalue(const char *boundary, FILE *in, const int wantfile,
+ strbuf *value, FILE *out)
+{
+ int c, i, k, matched;
+
+ matched = k = 0;
+
+ while ((c = getc(in)) != EOF) {
+
+ /*
+ * If we partially match the boundary, then we copy the
+ * entire matching prefix to the output. We do not need to
+ * backtrack and look for shorter matching prefixes because
+ * they cannot exist. The boundary always begins with '\r'
+ * and never contains another '\r'.
+ */
+
+ if (matched > 0 && c != boundary[matched]) {
+ for (i = 0; i < matched; i++) {
+ if (wantfile == 0) {
+ value = savechar(value, k++, boundary[i]);
+ }
+ else if (out != 0) {
+ fputc(boundary[i], out);
+ }
+ }
+ matched = 0;
+ }
+
+ /* check for full or partial boundary match */
+
+ if (c == boundary[matched]) {
+ if (boundary[++matched] == 0) {
+ break; /* full match */
+ }
+ continue; /* partial match */
+ }
+
+ /* no match, so copy byte to output */
+
+ if (wantfile == 0) {
+ value = savechar(value, k++, c);
+ }
+ else if (out != 0) {
+ fputc(c, out);
+ }
+ }
+ if (wantfile == 0) {
+ return savechar(value, k, 0);
+ }
+ return 0;
+}
+
+/*
+ * read_multipart() reads form data encoded as "multipart/form-data"
+ * and adds form field names and values to variable list "v" and
+ * returns "v".
+ *
+ * The input is split into parts delimited by a boundary string.
+ * Each part starts with this header:
+ *
+ * Content-Disposition: form-data; name="fieldname"; filename="filename"
+ *
+ * where "fieldname" is the name of the form field. The "filename="
+ * attribute is only present when this part contains file data for
+ * a file upload. A "Content-type:" header line may also be present
+ * with a file upload. After the header lines comes a blank line
+ * followed by the field data (or file data) terminated by "\r\n--"
+ * followed by the boundary string. If the boundary string is
+ * followed by "--\r\n" then this is the last part.
+ */
+
+static CGI_varlist *
+read_multipart(CGI_varlist *v, const char *template) {
+ const char *ctype, *name, *filename;
+ char *p, *token[2], *boundary, *localname = 0;
+ strbuf *bbuf = 0, *nbuf = 0, *fbuf = 0;
+ strbuf *line = 0, *value = 0;
+ int len, fd;
+ FILE *out;
+
+ /*
+ * get the boundary string from the environment and prepend
+ * "\r\n--" to it.
+ */
+
+ if ((ctype = getenv("CONTENT_TYPE")) == 0 ||
+ strncasecmp(ctype, "multipart/form-data;", len = 20) != 0)
+ {
+ return v;
+ }
+ bbuf = savestr(bbuf, ctype + len);
+ if (scanattr(bbuf->str, token) == 0 ||
+ strcasecmp(token[0], "boundary") != 0)
+ {
+ goto cleanup;
+ }
+ boundary = token[1] - 4;
+ memcpy(boundary, "\r\n--", 4);
+
+ /*
+ * first line is the boundary string, but with "\r\n"
+ * at the end rather than the start.
+ */
+
+ len = (int)strlen(boundary) - 2;
+ if ((line = readline(line, stdin)) == 0 ||
+ strncmp(line->str, boundary + 2, len) != 0 ||
+ line->str[len] != '\r' || line->str[len + 1] != '\n')
+ {
+ goto cleanup;
+ }
+
+ /* read all the parts */
+
+ for (;;) {
+
+ /* Scan header lines for the Content-Disposition: header */
+
+ name = filename = 0;
+ while ((line = readline(line, stdin)) != 0 &&
+ (p = scanheader(line->str, token)) != 0)
+ {
+ if (strcasecmp(token[0], "Content-Disposition") != 0 ||
+ strcasecmp(token[1], "form-data") != 0)
+ {
+ continue;
+ }
+
+ /* Content-Disposition: has field name and file name */
+
+ while ((p = scanattr(p, token)) != 0) {
+ if (name == 0 &&
+ strcasecmp(token[0], "name") == 0)
+ {
+ nbuf = savestr(nbuf, token[1]);
+ name = nbuf->str;
+ }
+ else if (filename == 0 &&
+ strcasecmp(token[0], "filename") == 0)
+ {
+ fbuf = savestr(fbuf, token[1]);
+ filename = fbuf->str;
+ }
+ }
+ }
+
+ /* after the headers is a blank line (just "\r\n") */
+
+ if (line == 0 || name == 0 ||
+ line->str[0] != '\r' || line->str[1] != '\n')
+ {
+ break;
+ }
+
+ /*
+ * If filename is non null (file upload) then we read file data,
+ * otherwise we read field data. In either case the data
+ * consists of everything up to, but not including the boundary.
+ */
+
+ if (filename != 0) {
+
+ /* copy file data to newly created file */
+
+ out = 0;
+ if (template != 0 && *filename != 0) {
+ if (localname == 0) {
+ localname = (char *) mymalloc((int)strlen(template) + 1);
+ }
+ strcpy(localname, template);
+ if ((fd = mkstemp(localname)) >= 0) {
+ out = fdopen(fd, "wb");
+ }
+ }
+ copyvalue(boundary, stdin, 1, 0, out);
+ if (out != 0) {
+ fclose(out);
+ v = CGI_add_var(v, name, localname);
+ v = CGI_add_var(v, name, filename);
+ }
+ }
+ else {
+ value = copyvalue(boundary, stdin, 0, value, 0);
+ v = CGI_add_var(v, name, value->str);
+ }
+
+ /*
+ * read the rest of the line after the boundary. If we
+ * get "--\r\n" then this is the last field. Otherwise
+ * we presumably get "\r\n" and we continue.
+ */
+
+ if ((line = readline(line, stdin)) != 0 &&
+ line->str[0] == '-' && line->str[1] == '-' &&
+ line->str[2] == '\r' && line->str[3] == '\n')
+ {
+ break;
+ }
+ }
+
+cleanup:
+ if (bbuf != 0) {
+ free(bbuf);
+ }
+ if (nbuf != 0) {
+ free(nbuf);
+ }
+ if (fbuf != 0) {
+ free(fbuf);
+ }
+ if (line != 0) {
+ free(line);
+ }
+ if (value != 0) {
+ free(value);
+ }
+ if (localname != 0) {
+ free(localname);
+ }
+ return v;
+}
+
+/*
+ * EXPORTED FUNCTIONS
+ *
+ * CGI_decode_url() returns a new string which is a copy of the input
+ * string with '+' converted to ' ' and %xx converted to the character
+ * whose hex numeric value is xx.
+ */
+
+char *
+CGI_decode_url(const char *p) {
+ char *out;
+ int i, k, L, R;
+
+ if (p == 0) {
+ return 0;
+ }
+ out = (char *) mymalloc((int)strlen(p) + 1);
+ for (i = k = 0; p[i] != 0; i++) {
+ switch(p[i]) {
+
+ case '+':
+ out[k++] = ' ';
+ continue;
+
+ case '%':
+ if ((L = hex(p[i + 1])) >= 0 &&
+ (R = hex(p[i + 2])) >= 0)
+ {
+ out[k++] = (L << 4) + R;
+ i += 2;
+ continue;
+ }
+ break;
+ }
+ out[k++] = p[i];
+ }
+ out[k] = 0;
+ return out;
+}
+
+/*
+ * CGI_encode_url() URL encodes a string and returns the result
+ * in memory from malloc().
+ */
+
+char *
+CGI_encode_url(const char *p, const char *keep) {
+ char *out;
+
+ if (p == 0) {
+ return 0;
+ }
+ out = mymalloc(urlcount(p, keep) + 1);
+ urlencode(p, out, keep);
+ return out;
+}
+
+/*
+ * CGI_encode_query() takes a variable arg list of strings
+ * and encodes them into a URL query string of the form
+ * name1=value1&name2=value2 ... where each name and value
+ * is URL encoded.
+ */
+
+char *
+CGI_encode_query(const char *keep, ...) {
+ char *out, *p;
+ va_list ap;
+ const char *name, *value;
+ int k;
+
+ /* calculate the size of the output string */
+
+ va_start(ap, keep);
+ k = 0;
+ while ((value = va_arg(ap, const char *)) != 0) {
+ k += urlcount(value, keep) + 1;
+ }
+ va_end(ap);
+ if (k == 0) {
+ return 0;
+ }
+ p = out = mymalloc(k);
+
+ /* url encode each name=value pair */
+
+ va_start(ap, keep);
+ while ((name = va_arg(ap, const char *)) != 0 &&
+ (value = va_arg(ap, const char *)) != 0)
+ {
+ if (p != out) {
+ *p++ = '&';
+ }
+ p = urlencode(name, p, keep);
+ *p++ = '=';
+ p = urlencode(value, p, keep);
+ }
+ va_end(ap);
+ *p = 0;
+ return out;
+}
+
+/*
+ * CGI_encode_varlist() encodes a CGI_varlist into a query
+ * string of the form name1=value1&name2=value2 ... where
+ * each name and value is URL encoded.
+ */
+
+char *
+CGI_encode_varlist(CGI_varlist *vlist, const char *keep) {
+ char *out, *p;
+ CGI_varlist *v;
+ CGI_val *value;
+ int k = 0;
+
+ /* calculate size of the output string */
+
+ for (v = vlist; v != 0; v = v->next) {
+ for (value = v->value; value != 0; value = value->next) {
+ k += 2 + urlcount(v->varname, keep) +
+ urlcount(value->value, keep);
+ }
+ }
+ if (k == 0) {
+ return 0;
+ }
+ p = out = mymalloc(k);
+
+ /* URL encode each name=value pair */
+
+ for (v = vlist; v != 0; v = v->next) {
+ for (value = v->value; value != 0; value = value->next) {
+ if (p != out) {
+ *p++ = '&';
+ }
+ p = urlencode(v->varname, p, keep);
+ *p++ = '=';
+ p = urlencode(value->value, p, keep);
+ }
+ }
+ *p = 0;
+ return out;
+}
+
+/*
+ * CGI_add_var() adds a new variable name and value to variable list
+ * "v" and returns the resulting list. If "v" is null or if the
+ * variable name is not on the list, then we create a new entry.
+ * We add the value to the appropriate list entry.
+ */
+
+CGI_varlist *
+CGI_add_var(CGI_varlist *v, const char *varname, const char *value) {
+ CGI_val *val;
+ CGI_varlist *v2;
+
+ if (varname == 0 || value == 0) {
+ return v;
+ }
+
+ /* create a new value */
+
+ val = (CGI_val *) mymalloc(sizeof(*val) + (int)strlen(value));
+ strcpy((char *) val->value, value);
+ val->next = 0;
+
+ /*
+ * find the list entry or else create a new one. Add the
+ * new value. We use "tail" pointers to keep the lists
+ * in the same order as the input.
+ */
+
+ if ((v2 = findvar(v, varname)) == 0) {
+ v2 = (CGI_varlist *) mymalloc((int)sizeof(*v2) + (int)strlen(varname));
+ strcpy((char *) v2->varname, varname);
+ v2->value = val;
+ v2->numvalue = 1;
+ v2->next = v2->iter = v2->tail = 0;
+ v2->vector = 0;
+ if (v == 0) {
+ v = v2;
+ }
+ else {
+ v->tail->next = v2;
+ }
+ v->tail = v2;
+ }
+ else {
+ v2->valtail->next = val;
+ v2->numvalue++;
+ }
+ v2->valtail = val;
+ if (v2->vector != 0) {
+ free((void *)v2->vector);
+ v2->vector = 0;
+ }
+ v->iter = 0;
+ return v;
+}
+
+/*
+ * CGI_decode_query() adds all the names and values in query string
+ * "query" to variable list "v" (which may be null) and returns the
+ * resulting variable list. The query string has the form
+ *
+ * name1=value1&name2=value2&name3=value3
+ *
+ * We convert '+' to ' ' and convert %xx to the character whose
+ * hex numeric value is xx.
+ */
+
+CGI_varlist *
+CGI_decode_query(CGI_varlist *v, const char *query) {
+ char *buf;
+ const char *name, *value;
+ int i, k, L, R, done;
+
+ if (query == 0) {
+ return v;
+ }
+ buf = (char *) mymalloc((int)strlen(query) + 1);
+ name = value = 0;
+ for (i = k = done = 0; done == 0; i++) {
+ switch (query[i]) {
+
+ case '=':
+ if (name != 0) {
+ break; /* treat extraneous '=' as data */
+ }
+ if (name == 0 && k > 0) {
+ name = buf;
+ buf[k++] = 0;
+ value = buf + k;
+ }
+ continue;
+
+ case 0:
+ done = 1; /* fall through */
+
+ case '&':
+ buf[k] = 0;
+ if (name == 0 && k > 0) {
+ name = buf;
+ value = buf + k;
+ }
+ if (name != 0) {
+ v = CGI_add_var(v, name, value);
+ }
+ k = 0;
+ name = value = 0;
+ continue;
+
+ case '+':
+ buf[k++] = ' ';
+ continue;
+
+ case '%':
+ if ((L = hex(query[i + 1])) >= 0 &&
+ (R = hex(query[i + 2])) >= 0)
+ {
+ buf[k++] = (L << 4) + R;
+ i += 2;
+ continue;
+ }
+ break; /* treat extraneous '%' as data */
+ }
+ buf[k++] = query[i];
+ }
+ free(buf);
+ return v;
+}
+
+/*
+ * CGI_get_cookie() adds all the cookie names and values from the
+ * environment variable HTTP_COOKIE to variable list "v" (which
+ * may be null) and returns the resulting variable list.
+ */
+
+CGI_varlist *
+CGI_get_cookie(CGI_varlist *v) {
+ const char *env;
+ char *buf, *p, *cookie[2];
+
+ if ((env = getenv("HTTP_COOKIE")) == 0) {
+ return v;
+ }
+ buf = (char *) mymalloc((int)strlen(env) + 1);
+ p = strcpy(buf, env);
+ while ((p = scanattr(p, cookie)) != 0) {
+ v = CGI_add_var(v, cookie[0], cookie[1]);
+ }
+ free(buf);
+ return v;
+}
+
+/*
+ * CGI_get_query() adds all the field names and values from the
+ * environment variable QUERY_STRING to variable list "v" (which
+ * may be null) and returns the resulting variable list.
+ */
+
+CGI_varlist *
+CGI_get_query(CGI_varlist *v) {
+ return CGI_decode_query(v, getenv("QUERY_STRING"));
+}
+
+/*
+ * CGI_get_post() reads field names and values from stdin and adds
+ * them to variable list "v" (which may be null) and returns the
+ * resulting variable list. We accept input encoded as
+ * "application/x-www-form-urlencoded" or as "multipart/form-data".
+ * In the case of a file upload, we write to a new file created
+ * with mkstemp() and "template". If the template is null or if
+ * mkstemp() fails then we silently discard the uploaded file data.
+ * The local name of the file (created by mkstemp()) and the remote
+ * name (as specified by the user) can be obtained with
+ * CGI_lookup_all(v, fieldname).
+ */
+
+CGI_varlist *
+CGI_get_post(CGI_varlist *v, const char *template) {
+ const char *env;
+ char *buf;
+ int len;
+
+ if ((env = getenv("CONTENT_TYPE")) != 0 &&
+ strcasecmp(env, "application/x-www-form-urlencoded") == 0 &&
+ (env = getenv("CONTENT_LENGTH")) != 0 &&
+ (len = atoi(env)) > 0)
+ {
+ buf = (char *) mymalloc(len + 1);
+ if (fread(buf, 1, len, stdin) == len) {
+ buf[len] = 0;
+ v = CGI_decode_query(v, buf);
+ }
+ free(buf);
+ }
+ else {
+ v = read_multipart(v, template);
+ }
+ return v;
+}
+
+/*
+ * CGI_get_all() returns a variable list that contains a combination of the
+ * following: cookie names and values from HTTP_COOKIE, field names and
+ * values from QUERY_STRING, and POSTed field names and values from stdin.
+ * File uploads are handled using "template" (see CGI_get_post())
+ */
+
+CGI_varlist *
+CGI_get_all(const char *template) {
+ CGI_varlist *v = 0;
+
+ v = CGI_get_cookie(v);
+ v = CGI_get_query(v);
+ v = CGI_get_post(v, template);
+ return v;
+}
+
+/* CGI_free_varlist() frees all memory used by variable list "v" */
+
+void
+CGI_free_varlist(CGI_varlist *v) {
+ CGI_val *val, *valnext;
+
+ if (v != 0) {
+ if (v->vector != 0) {
+ free((void *)v->vector);
+ }
+ for (val = v->value; val != 0; val = valnext) {
+ valnext = val->next;
+ free(val);
+ }
+ CGI_free_varlist(v->next);
+ free(v);
+ }
+}
+
+
+/*
+ * CGI_lookup() searches variable list "v" for an entry named
+ * "varname" and returns null if not found. Otherwise we return the
+ * first value associated with "varname", which is a null terminated
+ * string. If varname is null then we return the first value of the
+ * "current entry", which was set using the iterating functions
+ * CGI_first_name() and CGI_next_name().
+ */
+
+const char *
+CGI_lookup(CGI_varlist *v, const char *varname) {
+ return (v = findvar(v, varname)) == 0 ? 0 : v->value->value;
+}
+
+/*
+ * CGI_lookup_all() searches variable list "v" for an entry named
+ * "varname" and returns null if not found. Otherwise we return
+ * a pointer to a null terminated array of string pointers (see
+ * CGI_value) where each string is a value of the variable. If
+ * varname is null then we return the values of the "current entry",
+ * which was set using the iterating functions CGI_first_name() and
+ * CGI_next_name().
+ */
+
+CGI_value *
+CGI_lookup_all(CGI_varlist *v, const char *varname) {
+ CGI_val *val;
+ int i;
+
+ if ((v = findvar(v, varname)) == 0) {
+ return 0;
+ }
+ if (v->vector == 0) {
+ v->vector = (CGI_value *)
+ mymalloc(sizeof(CGI_value) * (v->numvalue + 1));
+ i = 0;
+
+ /* to initialize v->vector we must cast away const */
+
+ for (val = v->value; val != 0 && i < v->numvalue;
+ val = val->next)
+ {
+ ((const char **)v->vector)[i++] = val->value;
+ }
+ ((const char **)v->vector)[i] = 0;
+ }
+ return v->vector;
+}
+
+/*
+ * CGI_first_name() returns the name of the first entry in
+ * variable list "v", or null if "v" is null.
+ */
+
+const char *
+CGI_first_name(CGI_varlist *v) {
+ return v == 0 ? 0 : (v->iter = v)->varname;
+}
+
+/*
+ * CGI_next_name() returns the name of the next entry in variable list
+ * "v" after the most recent call to CGI_first_name() or CGI_next_name().
+ * We return null if there are no more entries
+ */
+
+const char *
+CGI_next_name(CGI_varlist *v) {
+ return v == 0 || v->iter == 0 || (v->iter = v->iter->next) == 0 ?
+ 0 : v->iter->varname;
+}
+
+/*
+ * CGI_encode_entity() converts null terminated string "in" to
+ * HTML entity encoding where > become > and < become <
+ * and & becomes & etc., and returns the result. Allocates
+ * memory for the result with malloc().
+ */
+
+char *
+CGI_encode_entity(const char *in) {
+ char *out, *p;
+ int i, k;
+
+ if (in == 0) {
+ return 0;
+ }
+ for (i = k = 0; in[i] != 0; i++) {
+ switch(in[i]) {
+
+ case '<':
+ case '>':
+ k += 4;
+ break;
+ case '&':
+ case '\'':
+ case '\r':
+ case '\n':
+ k += 5;
+ break;
+ case '"':
+ k += 6;
+ break;
+ default:
+ k++;
+ break;
+ }
+ }
+ out = p = mymalloc(k + 1);
+
+ for (i = 0; in[i] != 0; i++) {
+ switch(in[i]) {
+
+ case '<':
+ *p++ = '&';
+ *p++ = 'l';
+ *p++ = 't';
+ *p++ = ';';
+ break;
+ case '>':
+ *p++ = '&';
+ *p++ = 'g';
+ *p++ = 't';
+ *p++ = ';';
+ break;
+ case '&':
+ *p++ = '&';
+ *p++ = 'a';
+ *p++ = 'm';
+ *p++ = 'p';
+ *p++ = ';';
+ break;
+ case '\'':
+ *p++ = '&';
+ *p++ = '#';
+ *p++ = '3';
+ *p++ = '9';
+ *p++ = ';';
+ break;
+ case '\r':
+ *p++ = '&';
+ *p++ = '#';
+ *p++ = '1';
+ *p++ = '3';
+ *p++ = ';';
+ break;
+ case '\n':
+ *p++ = '&';
+ *p++ = '#';
+ *p++ = '1';
+ *p++ = '0';
+ *p++ = ';';
+ break;
+ case '"':
+ *p++ = '&';
+ *p++ = 'q';
+ *p++ = 'u';
+ *p++ = 'o';
+ *p++ = 't';
+ *p++ = ';';
+ break;
+ default:
+ *p++ = in[i];
+ break;
+ }
+ }
+ *p = 0;
+ return out;
+}
+
+/* base64 conversion */
+
+static const char b64encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz0123456789+/";
+
+#define BAD 100
+
+static const unsigned char b64decode[] = {
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, 62, BAD, BAD, BAD, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, BAD, BAD, BAD, BAD, BAD, BAD,
+
+ BAD, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, BAD, BAD, BAD, BAD, BAD,
+ BAD, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, BAD, BAD, BAD, BAD, BAD,
+
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD
+};
+
+/*
+ * CGI_decode_base64() decodes null terminated base64 encoded string p
+ * and returns the result. We store the length of the result in
+ * *len and we write a null byte after the last byte of the result.
+ * We allocate memory for the result with malloc();
+ */
+
+void *
+CGI_decode_base64(const char *p, int *len) {
+ const unsigned char *in = (const unsigned char *) p;
+ unsigned char *out;
+ int save = 0, nbits = 0, sixbits;
+ int i, k;
+
+ if (p == 0) {
+ return 0;
+ }
+ out = mymalloc(3 + 3 * (int)strlen(p) / 4);
+
+ /* every four base64 input characters becomes three output bytes */
+
+ for (i = k = 0; in[i] != 0; i++) {
+ if ((sixbits = b64decode[in[i]]) == BAD) {
+ continue;
+ }
+ save |= sixbits << (18 - nbits); /* 4 x 6 bits in */
+ if ((nbits += 6) == 24) {
+ out[k++] = save >> 16; /* 3 x 8 bits out */
+ out[k++] = save >> 8;
+ out[k++] = save;
+ nbits = 0;
+ save = 0;
+ }
+ }
+
+ /* convert leftover bits */
+
+ for (i = 16; i >= 0 && nbits >= 8; i -= 8) {
+ out[k++] = save >> i;
+ nbits -= 8;
+ }
+ out[k] = 0;
+ if (len != 0) {
+ *len = k;
+ }
+ return out;
+}
+
+/*
+ * CGI_encode_base64() base64 encodes bytes in array p of length len
+ * and returns the result, which is a null terminated base64 encoded
+ * string. We allocate memory for the result with malloc().
+ */
+
+char *
+CGI_encode_base64(const void *p, int len) {
+ const unsigned char *in = p;
+ char *out;
+ int save = 0, nbits = 0;
+ int i, k = 0;
+
+ if (in == 0 || len <= 0) {
+ return 0;
+ }
+ out = mymalloc(4 + 4 * len / 3);
+
+ /* every three input bytes becomes 4 base64 output characters */
+
+ for (i = 0; i < len; i++) {
+ save |= in[i] << (16 - nbits); /* 3 x 8 bits in */
+ if ((nbits += 8) == 24) {
+ out[k++] = b64encode[(save >> 18) & 077]; /* 4 x 6 bits out */
+ out[k++] = b64encode[(save >> 12) & 077];
+ out[k++] = b64encode[(save >> 6) & 077];
+ out[k++] = b64encode[ save & 077];
+ nbits = 0;
+ save = 0;
+ }
+ }
+
+ /* convert leftover bits */
+
+ if (nbits > 0) {
+ for (i = 18; i >= 0; i -= 6) {
+ if (nbits > 0) {
+ out[k++] = b64encode[(save >> i) & 077];
+ nbits -= 6;
+ }
+ else {
+ out[k++] = '=';
+ }
+ }
+ }
+ out[k] = 0;
+ return out;
+}
+
+/* hex conversion */
+
+/*
+ * CGI_decode_hex() decodes null terminated hex encoded string p
+ * and returns the result. We store the length of the result in
+ * *len and we write a null byte after the last byte of the result.
+ * We allocate memory for the result with malloc();
+ */
+
+void *
+CGI_decode_hex(const char *p, int *len) {
+ unsigned char *out;
+ int i, k, n, L, R;
+
+ if (p == 0 || ((n = (int)strlen(p)) & 1)) {
+ return 0; /* length of input must be even */
+ }
+ out = mymalloc(n / 2 + 1);
+ for (i = k = 0; i < n; i += 2) {
+ if ((L = hex(p[i])) >= 0 && (R = hex(p[i + 1])) >= 0) {
+ out[k++] = (L << 4) + R;
+ }
+ else {
+ free(out);
+ return 0;
+ }
+ }
+ out[k] = 0;
+ if (len != 0) {
+ *len = k;
+ }
+ return out;
+}
+
+/*
+ * CGI_encode_hex() hex encodes bytes in array p of length len
+ * and returns the result, which is a null terminated hex encoded
+ * string. We allocate memory for the result with malloc().
+ */
+
+char *
+CGI_encode_hex(const void *p, int len) {
+ const unsigned char *in = p;
+ int i, k;
+ char *out;
+ const char hexdigit[] = "0123456789ABCDEF";
+
+ if (in == 0 || len <= 0) {
+ return 0;
+ }
+ out = mymalloc(len * 2 + 1);
+ for (i = k = 0; i < len; i++) {
+ out[k++] = hexdigit[in[i] >> 4];
+ out[k++] = hexdigit[in[i] & 0xf];
+ }
+ out[k] = 0;
+ return out;
+}
diff --git a/crypto777/crypto777.sources b/crypto777/crypto777.sources
new file mode 100644
index 000000000..0b8882e8a
--- /dev/null
+++ b/crypto777/crypto777.sources
@@ -0,0 +1,11 @@
+JPEG_SRCS := ../crypto777/jpeg/jaricom.c ../crypto777/jpeg/jcapimin.c ../crypto777/jpeg/jcapistd.c ../crypto777/jpeg/jcarith.c ../crypto777/jpeg/jccoefct.c ../crypto777/jpeg/jccolor.c \
+ ../crypto777/jpeg/jcdctmgr.c ../crypto777/jpeg/jchuff.c ../crypto777/jpeg/jcinit.c ../crypto777/jpeg/jcmainct.c ../crypto777/jpeg/jcmarker.c ../crypto777/jpeg/jcmaster.c \
+ ../crypto777/jpeg/jcomapi.c ../crypto777/jpeg/jcparam.c ../crypto777/jpeg/jcprepct.c ../crypto777/jpeg/jcsample.c ../crypto777/jpeg/jctrans.c ../crypto777/jpeg/jdapimin.c \
+ ../crypto777/jpeg/jdapistd.c ../crypto777/jpeg/jdarith.c ../crypto777/jpeg/jdatadst.c ../crypto777/jpeg/jdatasrc.c ../crypto777/jpeg/jdcoefct.c ../crypto777/jpeg/jdcolor.c \
+ ../crypto777/jpeg/jddctmgr.c ../crypto777/jpeg/jdhuff.c ../crypto777/jpeg/jdinput.c ../crypto777/jpeg/jdmainct.c ../crypto777/jpeg/jdmarker.c ../crypto777/jpeg/jdmaster.c \
+ ../crypto777/jpeg/jdmerge.c ../crypto777/jpeg/jdpostct.c ../crypto777/jpeg/jdsample.c ../crypto777/jpeg/jdtrans.c ../crypto777/jpeg/jerror.c ../crypto777/jpeg/jfdctflt.c \
+ ../crypto777/jpeg/jfdctfst.c ../crypto777/jpeg/jfdctint.c ../crypto777/jpeg/jidctflt.c ../crypto777/jpeg/jidctfst.c ../crypto777/jpeg/jidctint.c ../crypto777/jpeg/jquant1.c \
+ ../crypto777/jpeg/jquant2.c ../crypto777/jpeg/jutils.c ../crypto777/jpeg/jmemmgr.c ../crypto777/jpeg/jmemnobs.c
+
+CRYPTO777_SRCS := ../crypto777/ccgi.c ../crypto777/cJSON.c ../crypto777/iguana_utils.c ../crypto777/OS_nonportable.c ../crypto777/curve25519-donna.c ../crypto777/inet.c ../crypto777/OS_portable.c ../crypto777/curve25519.c ../crypto777/libgfshare.c ../crypto777/OS_time.c ../crypto777/hmac_sha512.c ../crypto777/ramcoder.c ../crypto777/SaM.c ../crypto777/iguana_OS.c ../crypto777/iguana_serdes.c $(JPEG_SRCS)
+
diff --git a/crypto777/inet.c b/crypto777/inet.c
index ff0b486a6..0ef873257 100755
--- a/crypto777/inet.c
+++ b/crypto777/inet.c
@@ -19,6 +19,7 @@
#ifndef crypto777_inet_h
#define crypto777_inet_h
#include "OS_portable.h"
+#include
#ifdef _WIN32
#include
diff --git a/crypto777/m_win32 b/crypto777/m_win32
index 161160b46..6b5486e36 100755
--- a/crypto777/m_win32
+++ b/crypto777/m_win32
@@ -1,2 +1 @@
-echo do equivalent of: gcc -c -O2 *.c jpeg/*.c jpeg/win/*.c
-echo do equivalent of: rm ../agents/libcrypto777.a; ar rcu ../agents/libcrypto777.a *.o
+make -f mingw32
diff --git a/crypto777/mingw b/crypto777/mingw
new file mode 100755
index 000000000..ec2e9bfd1
--- /dev/null
+++ b/crypto777/mingw
@@ -0,0 +1,6 @@
+include crypto777.sources
+
+all:
+ $(TOOL_DIR)/$(MINGW)-gcc -D __MINGW -c $(CRYPTO777_SRCS)
+ $(TOOL_DIR)/$(MINGW)-ar rcu *.o ../agents/libcrypto777.a
+
diff --git a/crypto777/mingw32 b/crypto777/mingw32
new file mode 100755
index 000000000..311cdb763
--- /dev/null
+++ b/crypto777/mingw32
@@ -0,0 +1,2 @@
+include ../mingw.path
+include mingw
diff --git a/crypto777/mingw64 b/crypto777/mingw64
new file mode 100755
index 000000000..c2d0741ec
--- /dev/null
+++ b/crypto777/mingw64
@@ -0,0 +1,3 @@
+include ../mingw.path
+include mingw
+
diff --git a/deprecated/obsolete.h b/deprecated/obsolete.h
index 7e1d83b73..0fe41f05b 100644
--- a/deprecated/obsolete.h
+++ b/deprecated/obsolete.h
@@ -10184,5 +10184,840 @@ void iguana_dedicatedrecv(void *arg)
} else retjsonstr = clonestr("{\"error\":\"cant parse generic JSON\"}");
return(retjsonstr);
}*/
-
+
+ char *iguana_remoteparser(struct iguana_agent *agent,struct iguana_info *coin,char *method,cJSON *json)
+ {
+ int32_t i,n,remains,numsent; char *jsonstr = 0,*retstr = 0; uint8_t hdr[128];
+ if ( agent->sock < 0 )
+ agent->sock = iguana_socket(0,agent->hostname,agent->port);
+ if ( agent->sock >= 0 )
+ {
+ i = 0;
+ jsonstr = jprint(json,0);
+ n = (int32_t)strlen(jsonstr) + 1;
+ remains = n;
+ //printf("RETBUF.(%s)\n",retbuf);
+ while ( remains > 0 )
+ {
+ if ( (numsent= (int32_t)send(agent->sock,&jsonstr[i],remains,MSG_NOSIGNAL)) < 0 )
+ {
+ if ( errno != EAGAIN && errno != EWOULDBLOCK )
+ {
+ printf("%s: %s numsent.%d vs remains.%d of %d errno.%d (%s) usock.%d\n",jsonstr,agent->name,numsent,remains,n,errno,strerror(errno),agent->sock);
+ break;
+ }
+ }
+ else if ( remains > 0 )
+ {
+ remains -= numsent;
+ i += numsent;
+ if ( remains > 0 )
+ printf("iguana sent.%d remains.%d of len.%d\n",numsent,remains,n);
+ }
+ }
+ if ( (n= (int32_t)recv(agent->sock,hdr,sizeof(hdr),0)) >= 0 )
+ {
+ remains = (hdr[0] + ((int32_t)hdr[1] << 8) + ((int32_t)hdr[2] << 16));
+ retstr = mycalloc('p',1,remains + 1);
+ i = 0;
+ while ( remains > 0 )
+ {
+ if ( (n= (int32_t)recv(agent->sock,&retstr[i],remains,0)) < 0 )
+ {
+ if ( errno == EAGAIN )
+ {
+ printf("EAGAIN for len %d, remains.%d\n",n,remains);
+ usleep(10000);
+ }
+ break;
+ }
+ else
+ {
+ if ( n > 0 )
+ {
+ remains -= n;
+ i += n;
+ } else usleep(10000);
+ }
+ }
+ }
+ free(jsonstr);
+ }
+ if ( retstr == 0 )
+ retstr = clonestr("{\"error\":\"null return\"}");
+ return(retstr);
+ }
+
+ struct iguana_agent *Agents[16];
+
+ cJSON *iguana_agentinfojson(struct iguana_agent *agent)
+ {
+ cJSON *json= cJSON_CreateObject();
+ jaddstr(json,"name",agent->name);
+ jadd(json,"methods",agent->methods);
+ if ( agent->port != 0 )
+ jaddnum(json,"port",agent->port);
+ else jaddstr(json,"type","builtin");
+ return(json);
+ }
+
+ char *iguana_addagent(char *name,char *(*parsefunc)(struct iguana_agent *agent,struct iguana_info *coin,char *method,cJSON *json),char *hostname,cJSON *methods,uint16_t port,char *pubkeystr,char *privkeystr)
+ {
+ int32_t i; struct iguana_agent *agent; char retbuf[8192];
+ for (i=0; iname,name) == 0 )
+ {
+ if ( pubkeystr != 0 && privkeystr != 0 && strlen(pubkeystr) == 64 && strlen(privkeystr) == 64 )
+ {
+ decode_hex(agent->pubkey.bytes,sizeof(bits256),pubkeystr);
+ decode_hex(agent->privkey.bytes,sizeof(bits256),privkeystr);
+ }
+ if ( port != 0 && agent->port == 0 )
+ {
+ if ( agent->sock >= 0 )
+ close(agent->sock);
+ agent->port = port;
+ strcpy(agent->hostname,hostname);
+ agent->sock = iguana_socket(0,agent->hostname,port);
+ printf("set (%s) port.%d for %s -> sock.%d\n",hostname,port,agent->name,agent->sock);
+ }
+ if ( agent->port > 0 && agent->sock < 0 && agent->hostname[0] != 0 && (agent->sock= iguana_socket(0,agent->hostname,agent->port)) < 0 )
+ return(clonestr("{\"result\":\"existing agent couldnt connect to remote agent\"}"));
+ else return(clonestr("{\"result\":\"agent already there\"}"));
+ }
+ }
+ for (i=0; iname,name,sizeof(agent->name)-1);
+ strncpy(agent->hostname,hostname,sizeof(agent->hostname)-1);
+ agent->methods = methods, agent->nummethods = cJSON_GetArraySize(methods);
+ agent->sock = -1;
+ agent->port = port;
+ agent->parsefunc = (void *)parsefunc;
+ if ( pubkeystr != 0 && privkeystr != 0 && strlen(pubkeystr) == 64 && strlen(privkeystr) == 64 )
+ {
+ decode_hex(agent->pubkey.bytes,sizeof(bits256),pubkeystr);
+ decode_hex(agent->privkey.bytes,sizeof(bits256),privkeystr);
+ }
+ if ( port > 0 )
+ {
+ if ( (agent->sock= iguana_socket(0,hostname,port)) < 0 )
+ return(clonestr("{\"result\":\"agent added, but couldnt connect to remote agent\"}"));
+ }
+ sprintf(retbuf,"{\"result\":\"agent added\",\"name\"\"%s\",\"methods\":%s,\"hostname\":\"%s\",\"port\":%u,\"sock\":%d}",agent->name,jprint(agent->methods,0),agent->hostname,agent->port,agent->sock);
+ return(clonestr(retbuf));
+ }
+ }
+ return(clonestr("{\"error\":\"no more agent slots available\"}"));
+ }
+ else if ( strcmp(method,"addagent") == 0 )
+ {
+ char *hostname = "127.0.0.1",*name; uint16_t port;
+ if ( (name= jstr(json,"name")) != 0 && (methods= jarray(&n,json,"methods")) != 0 )
+ {
+ if ( (port= juint(json,"port")) != 0 )
+ {
+ if ( (hostname= jstr(json,"host")) == 0 )
+ {
+ if ( (hostname= jstr(json,"ipaddr")) == 0 )
+ hostname = "127.0.0.1";
+ }
+ if ( hostname == 0 )
+ return(clonestr("{\"error\":\"no host specified for remote agent\"}"));
+ }
+ else if ( strcmp(name,"pangea") != 0 && strcmp(name,"InstantDEX") != 0 && strcmp(name,"jumblr") != 0 )
+ return(clonestr("{\"error\":\"no port specified for remote agent\"}"));
+ return(iguana_addagent(name,iguana_remoteparser,hostname,methods,port,jstr(json,"pubkey"),jstr(json,"privkey")));
+ } else return(clonestr("{\"error\":\"cant addagent without name and methods\"}"));
+ }
+ if ( (retstr= iguana_addagent("ramchain",ramchain_parser,"127.0.0.1",cJSON_Parse("[\"block\", \"tx\", \"txs\", \"rawtx\", \"balance\", \"totalreceived\", \"totalsent\", \"utxo\", \"status\"]"),0,0,0)) != 0 )
+ printf("%s\n",retstr), free(retstr);
+
+
+ /*void iguana_issuejsonstrM(void *arg)
+ {
+ cJSON *json; int32_t fd; char *retjsonstr,*jsonstr = arg;
+ retjsonstr = iguana_JSON(jsonstr);
+ if ( (json= cJSON_Parse(jsonstr)) != 0 )
+ {
+ if ( (fd= juint(json,"retdest")) > 0 )
+ {
+ send(fd,jsonstr,(int32_t)strlen(jsonstr)+1,MSG_NOSIGNAL);
+ }
+ free_json(json);
+ return;
+ }
+ printf("%s\n",retjsonstr);
+ free(retjsonstr);//,strlen(retjsonstr)+1);
+ free(jsonstr);//,strlen(jsonstr)+1);
+ }*/
+
+ int32_t iguana_rpctestvector(struct iguana_info *coin,char *checkstr,char *jsonstr,int32_t maxlen,int32_t testi)
+ {
+ int32_t len,checklen;
+ sprintf(jsonstr,"{\"rpc.%s testvector.%d\"}",coin->symbol,testi);
+ sprintf(checkstr,"{\"rpc.%s testvector.%d checkstr should have all info needed to verify the rpc request\"}",coin->symbol,testi);
+ len = (int32_t)strlen(jsonstr);
+ checklen = (int32_t)strlen(checkstr);
+ if ( len > maxlen || checklen > maxlen )
+ printf("iguana_rpctestvector: i was bad and overflowed buffer len.%d checklen.%d\n",len,checklen), exit(-1);
+ if ( checklen > len )
+ len = checklen;
+ return(len);
+ }
+
+ int32_t iguana_rpctestcheck(struct iguana_info *coin,char *jsonstr,char *retjsonstr)
+ {
+ if ( (rand() % 100) == 0 ) // 1% failure rate
+ return(-1);
+ else return(0);
+ }
+
+ int32_t iguana_rpctest(struct iguana_info *coin)
+ {
+ /* static int32_t testi,good,bad;
+ char *retjsonstr,jsonstr[4096],checkstr[sizeof(jsonstr)]; // should be big enough
+ //if ( (rand() % 1000) < 999 ) // if no test active, just return 0
+ return(0);
+ if ( iguana_rpctestvector(coin,checkstr,jsonstr,sizeof(jsonstr),testi++) > 0 )
+ {
+ retjsonstr = iguana_rpc(coin,jsonstr);
+ if ( iguana_rpctestcheck(coin,jsonstr,retjsonstr) < 0 )
+ bad++, printf("rpctestcheck.%s error: (%s) -> (%s) | good.%d bad.%d %.2f%%\n",coin->symbol,jsonstr,retjsonstr,good,bad,100.*(double)good/(good+bad));
+ else good++;
+ free(retjsonstr);
+ return(1); // indicates was active
+ }*/
+ return(0);
+ }
+
+ char *iguana_agentjson(char *name,struct iguana_info *coin,char *method,cJSON *json,char *remoteaddr)
+ {
+ cJSON *retjson = 0,*array,*methods,*obj; int32_t i,n,j; struct iguana_agent *agent;
+ if ( strcmp(name,"SuperNET") != 0 )
+ {
+ for (i=0; iname,name) == 0 )
+ {
+ if ( agent->parsefunc != 0 )
+ {
+ for (j=0; jnummethods; j++)
+ {
+ if ( (obj= jitem(agent->methods,j)) != 0 )
+ {
+ if ( strcmp(method,jstr(obj,0)) == 0 )
+ return((*agent->parsefunc)(agent,method,json,remoteaddr));
+ }
+ }
+ return(clonestr("{\"result\":\"agent doesnt have method\"}"));
+ } else return(clonestr("{\"result\":\"agent doesnt have parsefunc\"}"));
+ }
+ }
+ }
+ else if ( remoteaddr == 0 || strcmp(remoteaddr,"127.0.0.1") != 0 ) // public api
+ {
+ char *coinstr; int32_t j,k,l,r,rr; struct iguana_peer *addr;
+ array = 0;
+ if ( strcmp(method,"getpeers") == 0 )
+ {
+ if ( (coinstr= jstr(json,"coin")) != 0 )
+ {
+ if ( (array= iguana_peersjson(iguana_coinfind(coinstr),1)) == 0 )
+ return(clonestr("{\"error\":\"coin not found\"}"));
+ }
+ else
+ {
+ n = 0;
+ array = cJSON_CreateArray();
+ r = rand();
+ for (i=0; ipeers.active[l];
+ if ( addr->usock >= 0 && addr->supernet != 0 )
+ {
+ jaddistr(array,addr->ipaddr);
+ if ( ++n >= 64 )
+ break;
+ }
+ }
+ }
+ }
+ }
+ if ( array != 0 )
+ {
+ retjson = cJSON_CreateObject();
+ jaddstr(retjson,"agent","SuperNET");
+ jaddstr(retjson,"method","mypeers");
+ jaddstr(retjson,"result","peers found");
+ jadd(retjson,"peers",array);
+ return(jprint(retjson,1));
+ } else return(clonestr("{\"error\":\"no peers found\"}"));
+ }
+ else if ( strcmp(method,"mypeers") == 0 )
+ {
+ printf("mypeers from %s\n",remoteaddr!=0?remoteaddr:"local");
+ }
+ }
+ else // local api
+ {
+ if ( strcmp(method,"list") == 0 )
+ {
+ retjson = cJSON_CreateObject();
+ array = cJSON_CreateArray();
+ for (i=0; isymbol[0] != 0 )
+ jaddistr(array,Coins[i]->symbol);
+ }
+ jadd(retjson,"coins",array);
+ array = cJSON_CreateArray();
+ for (i=0; iname[0] != 0 )
+ jaddi(array,iguana_agentinfojson(Agents[i]));
+ }
+ jadd(retjson,"agents",array);
+ return(jprint(retjson,1));
+ }
+ else if ( strcmp(method,"peers") == 0 )
+ {
+ retjson = cJSON_CreateObject();
+ array = cJSON_CreateArray();
+ for (i=0; isymbol[0] != 0 )
+ jaddi(array,iguana_peersjson(Coins[i],0));
+ }
+ jadd(retjson,"allpeers",array);
+ return(jprint(retjson,1));
+ }
+ }
+ return(clonestr("{\"result\":\"stub processed generic json\"}"));
+ }
+
+ char *iguana_jsonstr(struct iguana_info *coin,char *jsonstr,char *remoteaddr)
+ {
+ cJSON *json; char *retjsonstr,*methodstr,*agentstr;
+ //printf("iguana_jsonstr.(%s)\n",jsonstr);
+ if ( (json= cJSON_Parse(jsonstr)) != 0 )
+ {
+ if ( (methodstr= jstr(json,"method")) != 0 )
+ {
+ if ( (agentstr= jstr(json,"agent")) == 0 || strcmp(agentstr,"iguana") == 0 )
+ retjsonstr = iguana_coinjson(coin,methodstr,json);
+ else retjsonstr = iguana_agentjson(agentstr,coin,methodstr,json,remoteaddr);
+ } else retjsonstr = clonestr("{\"error\":\"no method in JSON\"}");
+ free_json(json);
+ } else retjsonstr = clonestr("{\"error\":\"cant parse JSON\"}");
+ printf("iguana_jsonstr.(%s)\n",retjsonstr);
+ return(retjsonstr);
+ }
+ char *iguana_htmlget(char *space,int32_t max,int32_t *jsonflagp,char *path,char *remoteaddr,int32_t localaccess)
+ {
+ char *iguana_coinjson(struct iguana_info *coin,char *method,cJSON *json);
+ struct iguana_info *coin = 0; cJSON *json; bits256 hash2; int32_t height,i;
+ char buf[64],jsonstr[1024],coinstr[64],*retstr;
+ for (i=0; path[i]!=0; i++)
+ if ( path[i] == ' ' )
+ break;
+ path[i] = 0;
+ if ( path[strlen(path)-1] == '/' )
+ path[strlen(path)-1] = 0;
+ if ( strncmp(path,"/api",strlen("/api")) == 0 )
+ {
+ *jsonflagp = 1;
+ path += strlen("/api");
+ } else *jsonflagp = 0;
+ iguana_coinset(coinstr,path);
+ if ( coinstr[0] != 0 )
+ coin = iguana_coinfind(coinstr);
+ else coin = 0;
+ if ( strncmp(path,"/bitmap",strlen("/bitmap")) == 0 )
+ {
+ path += strlen("/bitmap");
+ *jsonflagp = 2;
+ iguana_bitmap(space,max,path);
+ return(space);
+ }
+ //printf("GETCHECK.(%s)\n",path);
+ if ( strncmp(path,"/ramchain/",strlen("/ramchain/")) == 0 )
+ {
+ path += strlen("/ramchain/");
+ if ( strncmp(path,"block/",strlen("block/")) == 0 )
+ {
+ path += strlen("block/");
+ if ( strncmp(path,"height/",strlen("height/")) == 0 )
+ {
+ height = atoi(path + strlen("height/"));
+ sprintf(Currentjsonstr,"{\"agent\":\"ramchain\",\"method\":\"block\",\"coin\":\"%s\",\"height\":%d,\"txids\":1}",coinstr,height);
+ return(iguana_ramchain_glue(coin,"block",Currentjsonstr));
+ }
+ else if ( strncmp(path,"hash/",strlen("hash/")) == 0 )
+ {
+ decode_hex(hash2.bytes,sizeof(hash2),path + strlen("hash/"));
+ char str[65]; printf("ramchain blockhash.%s\n",bits256_str(str,hash2));
+ sprintf(Currentjsonstr,"{\"agent\":\"ramchain\",\"method\":\"block\",\"coin\":\"%s\",\"hash\":\"%s\",\"txids\":1}",coinstr,str);
+ return(iguana_ramchain_glue(coin,"block",Currentjsonstr));
+ }
+ }
+ else if ( strncmp(path,"txid/",strlen("txid/")) == 0 )
+ {
+ decode_hex(hash2.bytes,sizeof(hash2),path + strlen("txid/"));
+ char str[65]; bits256_str(str,hash2);
+ sprintf(Currentjsonstr,"{\"agent\":\"ramchain\",\"method\":\"tx\",\"coin\":\"%s\",\"txid\":\"%s\"}",coinstr,str);
+ return(iguana_ramchain_glue(coin,"tx",Currentjsonstr));
+ }
+ else if ( strncmp(path,"explore/",strlen("explore/")) == 0 )
+ {
+ path += strlen("explore/");
+ if ( coin != 0 )
+ {
+ sprintf(Currentjsonstr,"{\"agent\":\"iguana\",\"method\":\"explore\",\"coin\":\"%s\",\"search\":\"%s\"}",coinstr,path);
+ } else sprintf(Currentjsonstr,"{\"agent\":\"iguana\",\"method\":\"explore\",\"search\":\"%s\"}",path);
+ return(iguana_ramchain_glue(coin,"explore",Currentjsonstr));
+ }
+ else if ( strncmp(path,"bundleinfo/",strlen("bundleinfo/")) == 0 )
+ {
+ path += strlen("bundleinfo/");
+ sprintf(Currentjsonstr,"{\"agent\":\"iguana\",\"method\":\"bundleinfo\",\"coin\":\"%s\",\"height\":%d}",coinstr,atoi(path));
+
+ }
+ else
+ {
+ sprintf(Currentjsonstr,"{\"agent\":\"iguana\",\"method\":\"%s\",\"coin\":\"%s\"}",path,coinstr);
+ return(iguana_ramchain_glue(coin,path,Currentjsonstr));
+ }
+ }
+ else if ( strncmp(path,"/hash/",strlen("/hash/")) == 0 )
+ {
+ path += strlen("/hash/");
+ return(iguana_hashparse(path));
+ }
+ else if ( strncmp(path,"/iguana/",strlen("/iguana/")) == 0 )
+ {
+ strcpy(Currentjsonstr,path);
+ path += strlen("/iguana/");
+ if ( strncmp(path,"setagent/",strlen("setagent/")) == 0 )
+ {
+ path += strlen("setagent/");
+ if ( strncmp(path,"ramchain",strlen("ramchain")) == 0 || strncmp(path,"iguana",strlen("iguana")) == 0 || strncmp(path,"InstantDEX",strlen("InstantDEX")) == 0 || strncmp(path,"pangea",strlen("pangea")) == 0 || strncmp(path,"PAX",strlen("PAX")) == 0 || strncmp(path,"ALL",strlen("ALL")) == 0 || strncmp(path,"jumblr",strlen("jumblr")) == 0 )
+ {
+ if ( strncmp(Default_agent,path,strlen(path)) == 0 )
+ {
+ strcpy(Default_agent,"ALL");
+ return(clonestr("{\"result\":\"ALL agents selected\"}"));
+ }
+ strcpy(Default_agent,path);
+ if ( Default_agent[strlen(Default_agent)-1] == '/' )
+ Default_agent[strlen(Default_agent)-1] = 0;
+ sprintf(buf,"{\"result\":\"agent selected\",\"name\":\"%s\"}",path);
+ return(clonestr(buf));
+ }
+ return(clonestr("{\"error\":\"invalid agent specified\"}"));
+ }
+ else
+ {
+ if ( strncmp(path,"peers/",strlen("peers/")) == 0 )
+ {
+ path += strlen("peers/");
+ if ( coin != 0 )
+ {
+ sprintf(Currentjsonstr,"{\"agent\":\"iguana\",\"method\":\"peers\",\"coin\":\"%s\"}",coinstr);
+ } else sprintf(Currentjsonstr,"{\"agent\":\"iguana\",\"method\":\"peers\"}");
+ json = cJSON_Parse(Currentjsonstr);
+ retstr = iguana_coinjson(coin,"peers",json);
+ free_json(json);
+ return(retstr);
+ }
+ else if ( coin != 0 )
+ {
+ if ( strncmp(path,"addnode/",strlen("addnode/")) == 0 )
+ {
+ path += strlen("addnode/");
+ sprintf(Currentjsonstr,"{\"agent\":\"iguana\",\"method\":\"addnode\",\"coin\":\"%s\",\"ipaddr\":\"%s\"}",coinstr,path);
+ json = cJSON_Parse(Currentjsonstr);
+ retstr = iguana_coinjson(coin,"addnode",json);
+ free_json(json);
+ return(retstr);
+ }
+ else if ( strncmp(path,"nodestatus/",strlen("nodestatus/")) == 0 )
+ {
+ path += strlen("nodestatus/");
+ sprintf(Currentjsonstr,"{\"agent\":\"iguana\",\"method\":\"nodestatus\",\"coin\":\"%s\",\"ipaddr\":\"%s\"}",coinstr,path);
+ json = cJSON_Parse(Currentjsonstr);
+ retstr = iguana_coinjson(coin,"nodestatus",json);
+ free_json(json);
+ return(retstr);
+ }
+ else if ( strncmp(path,"addcoin",strlen("addcoin")) == 0 )
+ {
+ path += strlen("addcoin");
+ iguana_coinset(buf,path);
+ if ( (coin= iguana_coinadd(buf)) != 0 )
+ {
+ sprintf(Currentjsonstr,"{\"agent\":\"iguana\",\"method\":\"addcoin\",\"coin\":\"%s\"}",buf);
+ json = cJSON_Parse(Currentjsonstr);
+ retstr = iguana_coinjson(coin,"addcoin",json);
+ free_json(json);
+ }
+ else retstr = clonestr("{\"error\":\"cant create coin\"}");
+ return(retstr);
+ }
+ else if ( strncmp(path,"startcoin",strlen("startcoin")) == 0 )
+ {
+ path += strlen("startcoin");
+ iguana_coinset(buf,path);
+ if ( (coin= iguana_coinfind(buf)) != 0 )
+ {
+ sprintf(Currentjsonstr,"{\"agent\":\"iguana\",\"method\":\"startcoin\",\"coin\":\"%s\"}",buf);
+ json = cJSON_Parse(Currentjsonstr);
+ retstr = iguana_coinjson(coin,"startcoin",json);
+ free_json(json);
+ }
+ else retstr = clonestr("{\"error\":\"cant create coin\"}");
+ return(retstr);
+ }
+ else if ( strncmp(path,"pausecoin",strlen("pausecoin")) == 0 )
+ {
+ path += strlen("pausecoin");
+ iguana_coinset(buf,path);
+ if ( (coin= iguana_coinfind(buf)) != 0 )
+ {
+ sprintf(Currentjsonstr,"{\"agent\":\"iguana\",\"method\":\"pausecoin\",\"coin\":\"%s\"}",buf);
+ json = cJSON_Parse(Currentjsonstr);
+ retstr = iguana_coinjson(coin,"pausecoin",json);
+ free_json(json);
+ }
+ else retstr = clonestr("{\"error\":\"cant create coin\"}");
+ return(retstr);
+ }
+ else if ( strncmp(path,"maxpeers/",strlen("maxpeers/")) == 0 )
+ {
+ path += strlen("maxpeers/");
+ sprintf(Currentjsonstr,"{\"agent\":\"iguana\",\"method\":\"maxpeers\",\"coin\":\"%s\",\"max\":%d}",coinstr,atoi(path));
+ json = cJSON_Parse(Currentjsonstr);
+ retstr = iguana_coinjson(coin,"maxpeers",json);
+ free_json(json);
+ return(retstr);
+ }
+ return(clonestr("{\"result\":\"iguana method not found\"}"));
+ }
+ return(clonestr("{\"result\":\"iguana method needs coin\"}"));
+ }
+ }
+ else if ( strncmp(path,"/InstantDEX/",strlen("/InstantDEX/")) == 0 )
+ {
+ double price,volume; char base[16],rel[16],exchange[16];
+ path += strlen("/InstantDEX/");
+ jsonstr[0] = 0;
+ if ( strncmp(path,"placebid/",strlen("placebid/")) == 0 )
+ {
+ path += strlen("placebid/");
+ if ( iguana_InstantDEX(jsonstr,path,"placebid") == 0 )
+ return(clonestr("{\"error\":\"error with placebid parameters\"}"));
+ }
+ else if ( strncmp(path,"placeask/",strlen("placeask/")) == 0 )
+ {
+ path += strlen("placeask/");
+ if ( iguana_InstantDEX(jsonstr,path,"placeask") == 0 )
+ return(clonestr("{\"error\":\"error with placeask parameters\"}"));
+ }
+ else if ( strncmp(path,"orderbook/",strlen("orderbook/")) == 0 )
+ {
+ path += strlen("orderbook/");
+ iguana_parsebidask(base,rel,exchange,&price,&volume,path);
+ if ( exchange[0] == 0 )
+ strcpy(exchange,"active");
+ sprintf(jsonstr,"{\"agent\":\"InstantDEX\",\"method\":\"orderbook\",\"base\":\"%s\",\"rel\":\"%s\",\"exchange\":\"%s\",\"allfields\":1}",base,rel,exchange);
+ }
+ else if ( strncmp(path,"orderstatus/",strlen("orderstatus/")) == 0 )
+ {
+ path += strlen("orderstatus/");
+ sprintf(jsonstr,"{\"agent\":\"InstantDEX\",\"method\":\"orderstatus\",\"orderid\":\"%s\"}",path);
+ }
+ else if ( strncmp(path,"cancelorder/",strlen("cancelorder/")) == 0 )
+ {
+ path += strlen("cancelorder/");
+ sprintf(jsonstr,"{\"agent\":\"InstantDEX\",\"method\":\"cancelorder\",\"orderid\":\"%s\"}",path);
+ }
+ else if ( strncmp(path,"balance/",strlen("balance/")) == 0 )
+ {
+ path += strlen("balance/");
+ iguana_parsebidask(base,rel,exchange,&price,&volume,path);
+ if ( path[0] != ' ' && path[0] != '/' )
+ sprintf(jsonstr,"{\"agent\":\"InstantDEX\",\"method\":\"balance\",\"exchange\":\"%s\"}",path);
+ else sprintf(jsonstr,"{\"agent\":\"InstantDEX\",\"method\":\"balance\"}");
+ }
+ else if ( strncmp(path,"openorders",strlen("openorders")) == 0 )
+ {
+ path += strlen("openorders");
+ sprintf(jsonstr,"{\"agent\":\"InstantDEX\",\"method\":\"openorders\"}");
+ }
+ else if ( strncmp(path,"tradehistory",strlen("tradehistory")) == 0 )
+ {
+ path += strlen("tradehistory");
+ sprintf(jsonstr,"{\"agent\":\"InstantDEX\",\"method\":\"tradehistory\"}");
+ }
+ else if ( strncmp(path,"allorderbooks",strlen("allorderbooks")) == 0 )
+ {
+ path += strlen("allorderbooks");
+ sprintf(jsonstr,"{\"agent\":\"InstantDEX\",\"method\":\"allorderbooks\"}");
+ }
+ else if ( strncmp(path,"allexchanges",strlen("allexchanges")) == 0 )
+ {
+ path += strlen("allexchanges");
+ sprintf(jsonstr,"{\"agent\":\"InstantDEX\",\"method\":\"allexchanges\"}");
+ }
+ if ( jsonstr[0] != 0 )
+ {
+ strcpy(Currentjsonstr,jsonstr);
+ return(clonestr(jsonstr));
+ //return(InstantDEX(jsonstr,remoteaddr,localaccess));
+ }
+ return(clonestr("{\"error\":\"unrecognized InstantDEX API call\"}"));
+ }
+ else if ( strncmp(path,"/pangea/",strlen("/pangea/")) == 0 )
+ {
+ path += strlen("/pangea/");
+ }
+ else if ( strncmp(path,"/jumblr/",strlen("/jumblr/")) == 0 )
+ {
+ path += strlen("/jumblr/");
+ }
+ else printf("no match to (%s)\n",path);
+ return(0);
+ }
+
+ char *iguana_rpcparse(char *retbuf,int32_t bufsize,int32_t *postflagp,char *jsonstr)
+ {
+ cJSON *json = 0; int32_t i,n,localaccess,datalen,postflag = 0;
+ char *key,*reststr,*str,*retstr,remoteaddr[65],porturl[65],*data = 0,*value,*agent = "SuperNET";
+ //printf("rpcparse.(%s)\n",jsonstr);
+ localaccess = 1;
+ if ( (str= strstr("Referer: ",jsonstr)) != 0 )
+ {
+ for (i=0; str[i]!=' '&&str[i]!=0&&str[i]!='\n'&&str[i]!='\r'; i++)
+ remoteaddr[i] = str[i];
+ remoteaddr[i] = 0;
+ } else strcpy(remoteaddr,"127.0.0.1"); // need to verify this
+ *postflagp = 0;
+ if ( strncmp("POST",jsonstr,4) == 0 )
+ jsonstr += 6, *postflagp = postflag = 1;
+ else if ( strncmp("GET",jsonstr,3) == 0 )
+ {
+ jsonstr += 4;
+ str = 0;
+ sprintf(porturl,"Referer: http://127.0.0.1:%u",IGUANA_RPCPORT);
+ if ( (str= iguana_htmlget(retbuf,bufsize,postflagp,jsonstr,remoteaddr,localaccess)) == 0 && (reststr= strstr(jsonstr,porturl)) != 0 )
+ {
+ reststr += strlen(porturl);
+ str = iguana_htmlget(retbuf,bufsize,postflagp,reststr,remoteaddr,localaccess);
+ }
+ if ( str != 0 )
+ {
+ if ( *postflagp == 0 )
+ {
+ json = cJSON_CreateObject();
+ jaddstr(json,"result",str);
+ if ( str != retbuf )
+ free(str);
+ str = cJSON_Print(json);
+ free_json(json);
+ }
+ return(str);
+ }
+ jsonstr++;
+ }
+ else return(0);
+ n = (int32_t)strlen(jsonstr);
+ for (i=0; i 0 )
+ {
+ jsonstr[i] = 0;
+ agent = jsonstr;
+ jsonstr += i;
+ }
+ jsonstr++;
+ json = cJSON_CreateObject();
+ jaddstr(json,"agent",agent);
+ while ( 1 )
+ {
+ n = (int32_t)strlen(jsonstr);
+ key = jsonstr;
+ value = 0;
+ for (i=0; i 0. && volume > 0. )
+ {
+ sprintf(jsonstr,"{\"agent\":\"InstantDEX\",\"method\":\"%s\",\"base\":\"%s\",\"rel\":\"%s\",\"exchange\":\"%s\",\"price\":\%0.8f,\"volume\":%0.8f}",method,base,rel,exchange,price,volume);
+ return(jsonstr);
+ }
+ else return(0);
+ }
+ return(0);
+ }
+
+ void iguana_coinset(char *buf,char *path)
+ {
+ int32_t i;
+ if ( path[0] == '/' )
+ path++;
+ for (i=0; i<8&&path[i]!=0&&path[i]!=' '&&path[i]!='/'; i++)
+ buf[i] = path[i];
+ buf[i] = 0;
+ touppercase(buf);
+ }
+
+ char *iguana_ramchain_glue(struct iguana_info *coin,char *method,char *jsonstr)
+ {
+ cJSON *json; char *retstr;
+ json = cJSON_Parse(jsonstr);
+ retstr = ramchain_parser(0,method,json);
+ free_json(json);
+ return(retstr);
+ }
#endif
diff --git a/iguana/Makefile b/iguana/Makefile
index 53acc4163..518be082b 100644
--- a/iguana/Makefile
+++ b/iguana/Makefile
@@ -10,14 +10,11 @@ VALID_TOOLCHAINS := pnacl newlib glibc clang-newlib mac
NACL_SDK_ROOT ?= $(abspath $(CURDIR))
TARGET = iguana
-TARGETI = InstantDEX
-TARGETP = pangea
-TARGETX = PAX
EXTRA= -D__PNACL
include $(NACL_SDK_ROOT)/tools/common.mk
-
+include iguana.sources
CHROME_ARGS += --allow-nacl-socket-api=127.0.0.1
DEPS = nacl_io
@@ -26,14 +23,6 @@ LIBS = crypto777 curl ssl crypto z glibc-compat nacl_spawn ppapi nacl_io ppapi_
CFLAGS = -Wall -D__PNACL -fno-strict-aliasing $(EXTRA)
LFLAGS = libs
-SOURCES = main.c iguana777.c iguana_wallet.c iguana_init.c iguana_json.c iguana_recv.c iguana_chains.c iguana_ramchain.c iguana_bitmap.c iguana_rpc.c iguana_bundles.c iguana_pubkeys.c iguana_msg.c iguana_html.c iguana_blocks.c iguana_peers.c
-
-SOURCESI = InstantDEX/main.c InstantDEX/InstantDEX_main.c InstantDEX/prices777.c
-
-SOURCESP = pangea/main.c pangea/cards777.c pangea/pangea777.c pangea/pangeafunds.c pangea/poker.c pangea/tourney777.c
-
-SOURCESX = peggy/main.c peggy/peggy777.c peggy/peggytx.c peggy/txidind777.c peggy/opreturn777.c quotes777.c
-
# Build rules generated by macros from common.mk:
$(foreach dep,$(DEPS),$(eval $(call DEPEND_RULE,$(dep))))
diff --git a/iguana/SuperNET.c b/iguana/SuperNET.c
new file mode 100644
index 000000000..ded022edf
--- /dev/null
+++ b/iguana/SuperNET.c
@@ -0,0 +1,507 @@
+/******************************************************************************
+ * Copyright © 2014-2015 The SuperNET Developers. *
+ * *
+ * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
+ * the top-level directory of this distribution for the individual copyright *
+ * holder information and the developer policies on copyright and licensing. *
+ * *
+ * Unless otherwise agreed in a custom licensing agreement, no part of the *
+ * SuperNET software, including this file may be copied, modified, propagated *
+ * or distributed except according to the terms contained in the LICENSE file *
+ * *
+ * Removal or modification of this copyright notice is prohibited. *
+ * *
+ ******************************************************************************/
+
+#include "../crypto777/OS_portable.h"
+#include "SuperNET.h"
+
+void SuperNET_rpcloop(void *args)
+{
+ struct supernet_info *myinfo = args;
+ int32_t recvlen,bindsock,postflag,sock,remains,jsonflag,numsent,len; socklen_t clilen;
+ char remoteaddr[64],jsonbuf[8192],*buf,*retstr,*space;//,*retbuf; ,n,i,m
+ struct sockaddr_in cli_addr; uint32_t ipbits,i; uint16_t port;
+ int32_t size = 1024 * 1024 * 2;
+ port = SUPERNET_PORT;
+ bindsock = iguana_socket(1,"127.0.0.1",port);
+ printf("SuperNET_rpcloop 127.0.0.1:%d bind sock.%d\n",port,bindsock);
+ space = calloc(1,size);
+ while ( bindsock >= 0 )
+ {
+ clilen = sizeof(cli_addr);
+ //printf("ACCEPT (%s:%d) on sock.%d\n","127.0.0.1",port,bindsock);
+ sock = accept(bindsock,(struct sockaddr *)&cli_addr,&clilen);
+ if ( sock < 0 )
+ {
+ //printf("iguana_rpcloop ERROR on accept usock.%d\n",sock);
+ continue;
+ }
+ memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits));
+ expand_ipbits(remoteaddr,ipbits);
+ memset(jsonbuf,0,sizeof(jsonbuf));
+ remains = (int32_t)(sizeof(jsonbuf) - 1);
+ buf = jsonbuf;
+ recvlen = 0;
+ retstr = 0;
+ while ( remains > 0 )
+ {
+ if ( (len= (int32_t)recv(sock,buf,remains,0)) < 0 )
+ {
+ if ( errno == EAGAIN )
+ {
+ printf("EAGAIN for len %d, remains.%d\n",len,remains);
+ usleep(10000);
+ }
+ break;
+ }
+ else
+ {
+ if ( len > 0 )
+ {
+ remains -= len;
+ recvlen += len;
+ buf = &buf[len];
+ retstr = SuperNET_rpcparse(myinfo,space,size,&jsonflag,&postflag,jsonbuf,remoteaddr);
+ break;
+ } else usleep(10000);
+ }
+ }
+ if ( retstr != 0 )
+ {
+ i = 0;
+ if ( postflag == 0 && jsonflag == 0 )
+ retstr = SuperNET_htmlresponse(space,size,&remains,1,retstr,1);
+ else remains = (int32_t)strlen(retstr);
+ printf("RETBUF.(%s)\n",retstr);
+ while ( remains > 0 )
+ {
+ if ( (numsent= (int32_t)send(sock,&retstr[i],remains,MSG_NOSIGNAL)) < 0 )
+ {
+ if ( errno != EAGAIN && errno != EWOULDBLOCK )
+ {
+ //printf("%s: %s numsent.%d vs remains.%d len.%d errno.%d (%s) usock.%d\n",retstr,ipaddr,numsent,remains,recvlen,errno,strerror(errno),sock);
+ break;
+ }
+ }
+ else if ( remains > 0 )
+ {
+ remains -= numsent;
+ i += numsent;
+ if ( remains > 0 )
+ printf("iguana sent.%d remains.%d of len.%d\n",numsent,remains,recvlen);
+ }
+ }
+ if ( retstr != space )
+ free(retstr);
+ }
+ //printf("done response sock.%d\n",sock);
+ closesocket(sock);
+ }
+}
+/*
+struct endpoint find_epbits(struct relay_info *list,uint32_t ipbits,uint16_t port,int32_t type)
+{
+ int32_t i; struct endpoint epbits;
+ memset(&epbits,0,sizeof(epbits));
+ if ( list != 0 && list->num > 0 )
+ {
+ if ( type >= 0 )
+ type = nn_portoffset(type);
+ for (i=0; inum&&i<(int32_t)(sizeof(list->connections)/sizeof(*list->connections)); i++)
+ if ( list->connections[i].ipbits == ipbits && (port == 0 || port == list->connections[i].port) && (type < 0 || type == list->connections[i].nn) )
+ return(list->connections[i]);
+ }
+ return(epbits);
+}
+
+int32_t add_relay(struct relay_info *list,struct endpoint epbits)
+{
+ list->connections[list->num % (sizeof(list->connections)/sizeof(*list->connections))] = epbits, list->num++;
+ if ( list->num > (sizeof(list->connections)/sizeof(*list->connections)) )
+ printf("add_relay warning num.%d > %ld\n",list->num,(long)(sizeof(list->connections)/sizeof(*list->connections)));
+ return(list->num);
+}
+
+int32_t nn_add_lbservers(struct supernet_info *myinfo,uint16_t port,uint16_t globalport,uint16_t relaysport,int32_t priority,int32_t sock,char servers[][MAX_SERVERNAME],int32_t num)
+{
+ int32_t i; char endpoint[512],pubendpoint[512]; struct endpoint epbits; uint32_t ipbits;
+ if ( num > 0 && servers != 0 && nn_setsockopt(sock,NN_SOL_SOCKET,NN_SNDPRIO,&priority,sizeof(priority)) >= 0 )
+ {
+ for (i=0; i= 0 )
+ {
+ printf("+R%s ",endpoint);
+ add_relay(&myinfo->active,epbits);
+ }
+ if ( myinfo->subclient >= 0 )
+ {
+ if ( myinfo->iamrelay != 0 )
+ {
+ epbits = calc_epbits("tcp",ipbits,relaysport,NN_PUB);
+ expand_epbits(pubendpoint,epbits);
+ if ( nn_connect(myinfo->subclient,pubendpoint) >= 0 )
+ printf("+P%s ",pubendpoint);
+ }
+ epbits = calc_epbits("tcp",ipbits,globalport,NN_PUB);
+ expand_epbits(pubendpoint,epbits);
+ if ( nn_connect(myinfo->subclient,pubendpoint) >= 0 )
+ printf("+P%s ",pubendpoint);
+ }
+ }
+ }
+ printf("added priority.%d\n",priority);
+ priority++;
+ } else printf("error setting priority.%d (%s)\n",priority,nn_errstr());
+ return(priority);
+}
+
+int32_t _lb_socket(struct supernet_info *myinfo,uint16_t port,uint16_t globalport,uint16_t relaysport,int32_t maxmillis,char servers[][MAX_SERVERNAME],int32_t num,char backups[][MAX_SERVERNAME],int32_t numbacks,char failsafes[][MAX_SERVERNAME],int32_t numfailsafes)
+{
+ int32_t lbsock,timeout,retrymillis,priority = 1;
+ if ( (lbsock= nn_socket(AF_SP,NN_REQ)) >= 0 )
+ {
+ retrymillis = (maxmillis / 30) + 1;
+ printf("!!!!!!!!!!!! lbsock.%d !!!!!!!!!!!\n",lbsock);
+ if ( nn_setsockopt(lbsock,NN_SOL_SOCKET,NN_RECONNECT_IVL,&retrymillis,sizeof(retrymillis)) < 0 )
+ printf("error setting NN_REQ NN_RECONNECT_IVL_MAX socket %s\n",nn_errstr());
+ else if ( nn_setsockopt(lbsock,NN_SOL_SOCKET,NN_RECONNECT_IVL_MAX,&maxmillis,sizeof(maxmillis)) < 0 )
+ fprintf(stderr,"error setting NN_REQ NN_RECONNECT_IVL_MAX socket %s\n",nn_errstr());
+ timeout = SUPERNET_NETWORKTIMEOUT;
+ if ( 1 && nn_setsockopt(lbsock,NN_SOL_SOCKET,NN_RCVTIMEO,&timeout,sizeof(timeout)) < 0 )
+ printf("error setting NN_SOL_SOCKET NN_RCVTIMEO socket %s\n",nn_errstr());
+ timeout = 100;
+ if ( 1 && nn_setsockopt(lbsock,NN_SOL_SOCKET,NN_SNDTIMEO,&timeout,sizeof(timeout)) < 0 )
+ printf("error setting NN_SOL_SOCKET NN_SNDTIMEO socket %s\n",nn_errstr());
+ if ( num > 0 )
+ priority = nn_add_lbservers(myinfo,port,globalport,relaysport,priority,lbsock,servers,num);
+ if ( numbacks > 0 )
+ priority = nn_add_lbservers(myinfo,port,globalport,relaysport,priority,lbsock,backups,numbacks);
+ if ( numfailsafes > 0 )
+ priority = nn_add_lbservers(myinfo,port,globalport,relaysport,priority,lbsock,failsafes,numfailsafes);
+ } else printf("error getting req socket %s\n",nn_errstr());
+ //printf("myinfo->lb.num %d\n",myinfo->lb.num);
+ return(lbsock);
+}
+
+int32_t nn_lbsocket(struct supernet_info *myinfo,int32_t maxmillis,int32_t port,uint16_t globalport,uint16_t relaysport)
+{
+ char Cservers[32][MAX_SERVERNAME],Bservers[32][MAX_SERVERNAME],failsafes[4][MAX_SERVERNAME];
+ int32_t n,m,lbsock,numfailsafes = 0;
+ printf("redo lbsocket()\n"), exit(-1);
+ //strcpy(failsafes[numfailsafes++],"5.9.56.103");
+ //strcpy(failsafes[numfailsafes++],"5.9.102.210");
+ // n = crackfoo_servers(Cservers,sizeof(Cservers)/sizeof(*Cservers),port);
+ // m = badass_servers(Bservers,sizeof(Bservers)/sizeof(*Bservers),port);
+ lbsock = _lb_socket(myinfo,port,globalport,relaysport,maxmillis,Bservers,m,Cservers,n*0,failsafes,numfailsafes);
+ return(lbsock);
+}
+
+void add_standard_fields(char *request)
+{
+ cJSON *json; uint64_t tag;
+ if ( (json= cJSON_Parse(request)) != 0 )
+ {
+ if ( get_API_nxt64bits(cJSON_GetObjectItem(json,"NXT")) == 0 )
+ {
+ randombytes((void *)&tag,sizeof(tag));
+ sprintf(request + strlen(request) - 1,",\"NXT\":\"%s\",\"tag\":\"%llu\"}",myinfo->NXTADDR,(long long)tag);
+ if ( myinfo->iamrelay != 0 && (myinfo->hostname[0] != 0 || myinfo->ipaddr[0] != 0) )
+ sprintf(request + strlen(request) - 1,",\"iamrelay\":\"%s\"}",myinfo->hostname[0]!=0?myinfo->hostname:myinfo->myipaddr);
+ }
+ free_json(json);
+ }
+}
+
+char *nn_loadbalanced(struct supernet_info *myinfo,uint8_t *data,int32_t len)
+{
+ char *msg,*jsonstr = 0;
+ int32_t sendlen,i,lbsock,recvlen = 0;
+ if ( (lbsock= myinfo->lbclient) < 0 )
+ return(clonestr("{\"error\":\"invalid load balanced socket\"}"));
+ for (i=0; i<10; i++)
+ if ( (nn_socket_status(lbsock,1) & NN_POLLOUT) != 0 )
+ break;
+ if ( myinfo->Debuglevel > 2 )
+ printf("sock.%d NN_LBSEND.(%s)\n",lbsock,data);
+ //fprintf(stderr,"send to network\n");
+ if ( (sendlen= nn_send(lbsock,data,len,0)) == len )
+ {
+ for (i=0; i<10; i++)
+ if ( (nn_socket_status(lbsock,1) & NN_POLLIN) != 0 )
+ break;
+ if ( (recvlen= nn_recv(lbsock,&msg,NN_MSG,0)) > 0 )
+ {
+ if ( myinfo->Debuglevel > 2 )
+ printf("LBRECV.(%s)\n",msg);
+ jsonstr = clonestr((char *)msg);
+ nn_freemsg(msg);
+ }
+ else
+ {
+ printf("nn_loadbalanced got recvlen.%d %s\n",recvlen,nn_errstr());
+ jsonstr = clonestr("{\"error\":\"lb recv error, probably timeout\"}");
+ }
+ } else printf("got sendlen.%d instead of %d %s\n",sendlen,len,nn_errstr()), jsonstr = clonestr("{\"error\":\"lb send error\"}");
+ return(jsonstr);
+}
+
+cJSON *relay_json(struct relay_info *list)
+{
+ cJSON *json,*array; char endpoint[512]; int32_t i;
+ if ( list == 0 || list->num == 0 )
+ return(0);
+ array = cJSON_CreateArray();
+ for (i=0; inum&&i<(int32_t)(sizeof(list->connections)/sizeof(*list->connections)); i++)
+ {
+ expand_epbits(endpoint,list->connections[i]);
+ jaddistr(array,endpoint);
+ }
+ json = cJSON_CreateObject();
+ jadd(json,"endpoints",array);
+ //cJSON_AddItemToObject(json,"type",cJSON_CreateString(nn_typestr(list->mytype)));
+ //cJSON_AddItemToObject(json,"dest",cJSON_CreateString(nn_typestr(list->desttype)));
+ jaddnum(json,"total",list->num);
+ return(json);
+}
+
+char *relays_jsonstr(struct supernet_info *myinfo,char *jsonstr,cJSON *argjson)
+{
+ cJSON *json;
+ if ( myinfo->iamrelay != 0 && myinfo->ipaddr[0] != 0 )
+ {
+ json = cJSON_CreateObject();
+ jaddstr(json,"relay",myinfo->ipaddr);
+ if ( myinfo->active.num > 0 )
+ jadd(json,"relays",relay_json(&myinfo->active));
+ return(jprint(json,1));
+ }
+ else return(clonestr("{\"error\":\"get relay list from relay\"}"));
+}
+
+int32_t init_SUPERNET_pullsock(struct supernet_info *myinfo,int32_t sendtimeout,int32_t recvtimeout)
+{
+ char bindaddr[64],*transportstr; int32_t iter;
+ myinfo->pullsock = -1;
+ if ( (myinfo->pullsock= nn_socket(AF_SP,NN_PULL)) < 0 )
+ {
+ printf("error creating pullsock %s\n",nn_strerror(nn_errno()));
+ return(-1);
+ }
+ printf("got pullsock.%d\n",myinfo->pullsock);
+ if ( nn_settimeouts(myinfo->pullsock,sendtimeout,recvtimeout) < 0 )
+ {
+ printf("error settime pullsock timeouts %s\n",nn_strerror(nn_errno()));
+ return(-1);
+ }
+ printf("PULLsock.%d\n",myinfo->pullsock);
+ for (iter=0; iter<2; iter++)
+ {
+ transportstr = (iter == 0) ? "ipc" : "inproc";
+ sprintf(bindaddr,"%s://SuperNET.agents",transportstr);
+ if ( nn_bind(myinfo->pullsock,bindaddr) < 0 )
+ {
+ printf("error binding pullsock to (%s) %s\n",bindaddr,nn_strerror(nn_errno()));
+ return(-1);
+ }
+ }
+ return(0);
+}
+
+void busdata_init(struct supernet_info *myinfo,int32_t sendtimeout,int32_t recvtimeout,int32_t firstiter)
+{
+ char endpoint[512]; int32_t i;
+ myinfo->servicesock = myinfo->pubglobal = myinfo->pubrelays = myinfo->lbserver = -1;
+ endpoint[0] = 0;
+ if ( (myinfo->subclient= nn_createsocket(myinfo,endpoint,0,"NN_SUB",NN_SUB,0,sendtimeout,recvtimeout)) >= 0 )
+ {
+ myinfo->pfd[myinfo->numservers++].fd = myinfo->subclient, printf("numservers.%d\n",myinfo->numservers);
+ nn_setsockopt(myinfo->subclient,NN_SUB,NN_SUB_SUBSCRIBE,"",0);
+ } else printf("error creating subclient\n");
+ myinfo->lbclient = nn_lbsocket(myinfo,SUPERNET_NETWORKTIMEOUT,SUPERNET_PORT + LB_OFFSET,myinfo->port + PUBGLOBALS_OFFSET,myinfo->port + PUBRELAYS_OFFSET);
+ printf("LBclient.%d port.%d\n",myinfo->lbclient,SUPERNET_PORT + LB_OFFSET);
+ sprintf(endpoint,"%s://%s:%u",myinfo->transport,myinfo->ipaddr,myinfo->serviceport);
+ if ( (myinfo->servicesock= nn_createsocket(myinfo,endpoint,1,"NN_REP",NN_REP,myinfo->serviceport,sendtimeout,recvtimeout)) >= 0 )
+ myinfo->pfd[myinfo->numservers++].fd = myinfo->servicesock, printf("numservers.%d\n",myinfo->numservers);
+ else printf("error creating servicesock\n");
+ for (i=0; inumservers; i++)
+ myinfo->pfd[i].events = NN_POLLIN | NN_POLLOUT;
+ printf("myinfo->iamrelay %d, numservers.%d ipaddr.(%s://%s) port.%d serviceport.%d\n",myinfo->iamrelay,myinfo->numservers,myinfo->transport,myinfo->ipaddr,myinfo->port,myinfo->serviceport);
+}
+
+void SuperNET_init(struct supernet_info *myinfo,char *jsonstr)
+{
+ char *str;
+ if ( jsonstr != 0 && (str= SuperNET_JSON(myinfo,jsonstr)) != 0 )
+ free(str);
+ busdata_init(myinfo,10,1,0);
+ init_SUPERNET_pullsock(myinfo,10,10);
+}*/
+
+int32_t Supernet_lineparse(char *key,int32_t keymax,char *value,int32_t valuemax,char *src)
+{
+ int32_t a,b,c,n = 0;
+ key[0] = value[0] = 0;
+ while ( (c= src[n]) == ' ' || c == '\t' || c == '\n' || c == '\t' )
+ n++;
+ while ( (c= src[n]) != ':' && c != 0 )
+ {
+ *key++ = c;
+ if ( ++n >= keymax-1 )
+ {
+ *key = 0;
+ printf("lineparse overflow key.(%s)\n",src);
+ return(-1);
+ }
+ }
+ *key = 0;
+ if ( src[n] != ':' )
+ return(n);
+ n++;
+ while ( (c= src[n]) == ' ' || c == '\t' )
+ n++;
+ while ( (c= src[n]) != 0 && c != '\r' && c != '\n' )
+ {
+ if ( c == '%' && (a= src[n+1]) != 0 && (b= src[n+2]) != 0 )
+ c = ((unhex(a) << 4) | unhex(b)), n += 2;
+ *value++ = c;
+ n++;
+ if ( n >= valuemax-1 )
+ {
+ *value = 0;
+ printf("lineparse overflow.(%s)\n",src);
+ return(-1);
+ }
+ }
+ *value = 0;
+ if ( src[n] != 0 )
+ {
+ n++;
+ while ( (c= src[n]) == '\r' || c == '\n' )
+ n++;
+ }
+ return(n);
+}
+
+cJSON *SuperNET_urlconv(char *value,int32_t bufsize,char *urlstr)
+{
+ int32_t i,n,totallen,datalen,len = 0; cJSON *json,*array; char key[8192],*data;
+ json = cJSON_CreateObject();
+ array = cJSON_CreateArray();
+ totallen = (int32_t)strlen(urlstr);
+ while ( 1 )
+ {
+ for (i=len; urlstr[i]!=0; i++)
+ if ( urlstr[i] == '\r' || urlstr[i] == '\n' )
+ break;
+ if ( i == len && (urlstr[len] == '\r' || urlstr[len] == '\n') )
+ {
+ len++;
+ continue;
+ }
+ urlstr[i] = 0;
+ if ( (n= Supernet_lineparse(key,sizeof(key),value,bufsize,&urlstr[len])) > 0 )
+ {
+ if ( value[0] != 0 )
+ jaddstr(json,key,value);
+ else jaddistr(array,key);
+ len += (n + 1);
+ if ( strcmp(key,"Content-Length") == 0 && (datalen= atoi(value)) > 0 )
+ {
+ data = &urlstr[totallen - datalen];
+ data[-1] = 0;
+ //printf("post.(%s) (%c)\n",data,data[0]);
+ jaddstr(json,"POST",data);
+ }
+ } else break;
+ }
+ jadd(json,"lines",array);
+ return(json);
+}
+
+char *SuperNET_rpcparse(struct supernet_info *myinfo,char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *postflagp,char *urlstr,char *remoteaddr)
+{
+ cJSON *tokens,*argjson,*json = 0; char urlmethod[16],*data,url[1024],*retstr,*token = 0; int32_t i,j,n;
+ //printf("rpcparse.(%s)\n",urlstr);
+ for (i=0; i 0 )
+ {
+ jaddstr(argjson,"agent",jstri(tokens,0));
+ if ( n > 1 )
+ jaddstr(argjson,"method",jstri(tokens,1));
+ for (i=2; i (%s) postflag.%d (%s)\n",urlstr,cJSON_Print(json),*postflagp,jprint(argjson,0));
+ return(retstr);
+ }
+ return(clonestr("{\"error\":\"couldnt process packet\"}"));
+}
+
diff --git a/iguana/SuperNET.h b/iguana/SuperNET.h
new file mode 100644
index 000000000..4b5deadd6
--- /dev/null
+++ b/iguana/SuperNET.h
@@ -0,0 +1,91 @@
+/******************************************************************************
+ * Copyright © 2014-2015 The SuperNET Developers. *
+ * *
+ * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
+ * the top-level directory of this distribution for the individual copyright *
+ * holder information and the developer policies on copyright and licensing. *
+ * *
+ * Unless otherwise agreed in a custom licensing agreement, no part of the *
+ * SuperNET software, including this file may be copied, modified, propagated *
+ * or distributed except according to the terms contained in the LICENSE file *
+ * *
+ * Removal or modification of this copyright notice is prohibited. *
+ * *
+ ******************************************************************************/
+
+#ifndef INCLUDED_SUPERNET_H
+#define INCLUDED_SUPERNET_H
+
+#include "../crypto777/OS_portable.h"
+#include "../includes/cJSON.h"
+#include "../includes/nanomsg/nn.h"
+
+#define SUPERNET_PORT 7778
+#define SUPERNET_NETWORKTIMEOUT 10000
+#define SUPERNET_POLLTIMEOUT 1
+#define SUPERNET_APIUSLEEP (SUPERNET_POLLTIMEOUT * 10000)
+#define SUPERNET_MAXAGENTS 64
+#define NXT_TOKEN_LEN 160
+#define nn_errstr() nn_strerror(nn_errno())
+
+/*#define LB_OFFSET 1
+#define PUBGLOBALS_OFFSET 2
+#define PUBRELAYS_OFFSET 3
+
+
+#define MAX_SERVERNAME 128
+struct relayargs
+{
+ char name[16],endpoint[MAX_SERVERNAME];
+ int32_t sock,type,bindflag,sendtimeout,recvtimeout;
+};
+struct relay_info { int32_t sock,num,mytype,desttype; struct endpoint connections[1 << CONNECTION_NUMBITS]; };*/
+
+#define CONNECTION_NUMBITS 10
+struct endpoint { queue_t nnrecvQ; int32_t nnsock,nnind; uint64_t ipbits:32,port:16,transport:2,nn:4,directind:CONNECTION_NUMBITS; };
+
+struct direct_connection { char handler[16]; struct endpoint epbits; int32_t sock; };
+
+struct supernet_msghdr { uint8_t type,serlen[3]; char command[16]; uint8_t hdrdata[44]; uint8_t data[]; };
+
+struct supernet_agent
+{
+ struct queueitem DL; queue_t recvQ; uint64_t totalrecv,totalsent;
+ int32_t (*recvfunc)(void *myinfo,struct supernet_agent *,struct supernet_msghdr *msg,uint8_t *data,int32_t datalen);
+ cJSON *networks;
+ char name[9],ipaddr[64],reppoint[64],pubpoint[64]; int32_t reqsock,repsock,pubsock,subsock;
+ uint32_t ipbits,dead; int32_t num,sock; uint16_t port,pubport,repport;
+};
+
+struct supernet_info
+{
+ char ipaddr[64],transport[8]; int32_t APISLEEP; int32_t iamrelay; uint64_t my64bits; uint64_t ipbits;
+ int32_t Debuglevel,readyflag,dead,POLLTIMEOUT;
+ //int32_t pullsock,subclient,lbclient,lbserver,servicesock,pubglobal,pubrelays,numservers;
+ bits256 privkey,pubkey;
+ uint16_t port,serviceport,acceptport;
+ struct nn_pollfd pfd[SUPERNET_MAXAGENTS]; //struct relay_info active;
+ struct supernet_agent agents[SUPERNET_MAXAGENTS]; queue_t acceptQ; int32_t numagents;
+};
+
+struct supernet_endpoint
+{
+ char name[64]; struct endpoint ep;
+ int32_t (*nnrecvfunc)(struct supernet_info *,struct supernet_endpoint *,int32_t ind,uint8_t *msg,int32_t nnlen);
+ queue_t nnrecvQ;
+ int32_t nnsock,num; struct endpoint eps[];
+};
+
+void expand_epbits(char *endpoint,struct endpoint epbits);
+struct endpoint calc_epbits(char *transport,uint32_t ipbits,uint16_t port,int32_t type);
+
+void SuperNET_init();
+char *SuperNET_JSON(struct supernet_info *myinfo,cJSON *json,char *remoteaddr);
+
+char *pangea_parser(struct supernet_info *myinfo,char *method,cJSON *json,char *remoteaddr);
+char *ramchain_parser(struct supernet_info *myinfo,char *method,cJSON *json,char *remoteaddr);
+char *iguana_parser(struct supernet_info *myinfo,char *method,cJSON *json,char *remoteaddr);
+char *InstantDEX_parser(struct supernet_info *myinfo,char *method,cJSON *json,char *remoteaddr);
+
+#endif
+
diff --git a/iguana/iguana.sources b/iguana/iguana.sources
index 23a485ba6..50b735bff 100755
--- a/iguana/iguana.sources
+++ b/iguana/iguana.sources
@@ -1,9 +1 @@
-SOURCES := iguana_wallet.c iguana_pubkeys.c iguana_recv.c iguana_bundles.c iguana_msg.c iguana_rpc.c iguana777.c iguana_chains.c iguana_peers.c iguana_accept.c iguana_html.c iguana_bitmap.c iguana_init.c iguana_ramchain.c iguana_blocks.c iguana_json.c ../crypto777/cJSON.c ../crypto777/iguana_utils.c ../crypto777/OS_nonportable.c ../crypto777/curve25519-donna.c ../crypto777/inet.c ../crypto777/OS_portable.c ../crypto777/curve25519.c ../crypto777/libgfshare.c ../crypto777/OS_time.c ../crypto777/hmac_sha512.c ../crypto777/ramcoder.c ../crypto777/SaM.c ../crypto777/iguana_OS.c ../crypto777/iguana_serdes.c ../crypto777/jpeg/jaricom.c ../crypto777/jpeg/jcapimin.c ../crypto777/jpeg/jcapistd.c ../crypto777/jpeg/jcarith.c ../crypto777/jpeg/jccoefct.c ../crypto777/jpeg/jccolor.c \
- ../crypto777/jpeg/jcdctmgr.c ../crypto777/jpeg/jchuff.c ../crypto777/jpeg/jcinit.c ../crypto777/jpeg/jcmainct.c ../crypto777/jpeg/jcmarker.c ../crypto777/jpeg/jcmaster.c \
- ../crypto777/jpeg/jcomapi.c ../crypto777/jpeg/jcparam.c ../crypto777/jpeg/jcprepct.c ../crypto777/jpeg/jcsample.c ../crypto777/jpeg/jctrans.c ../crypto777/jpeg/jdapimin.c \
- ../crypto777/jpeg/jdapistd.c ../crypto777/jpeg/jdarith.c ../crypto777/jpeg/jdatadst.c ../crypto777/jpeg/jdatasrc.c ../crypto777/jpeg/jdcoefct.c ../crypto777/jpeg/jdcolor.c \
- ../crypto777/jpeg/jddctmgr.c ../crypto777/jpeg/jdhuff.c ../crypto777/jpeg/jdinput.c ../crypto777/jpeg/jdmainct.c ../crypto777/jpeg/jdmarker.c ../crypto777/jpeg/jdmaster.c \
- ../crypto777/jpeg/jdmerge.c ../crypto777/jpeg/jdpostct.c ../crypto777/jpeg/jdsample.c ../crypto777/jpeg/jdtrans.c ../crypto777/jpeg/jerror.c ../crypto777/jpeg/jfdctflt.c \
- ../crypto777/jpeg/jfdctfst.c ../crypto777/jpeg/jfdctint.c ../crypto777/jpeg/jidctflt.c ../crypto777/jpeg/jidctfst.c ../crypto777/jpeg/jidctint.c ../crypto777/jpeg/jquant1.c \
- ../crypto777/jpeg/jquant2.c ../crypto777/jpeg/jutils.c ../crypto777/jpeg/jmemmgr.c ../crypto777/jpeg/jmemnobs.c main.c
-
+SOURCES := iguana_wallet.c iguana_html.c iguana_pubkeys.c iguana_recv.c iguana_bundles.c iguana_msg.c iguana_rpc.c iguana777.c iguana_chains.c iguana_peers.c iguana_accept.c iguana_bitmap.c iguana_init.c iguana_ramchain.c iguana_blocks.c iguana_json.c $(CRYPTO777_SRCS) main.c
diff --git a/iguana/iguana777.c b/iguana/iguana777.c
index 0c5e8da7d..04106ab28 100755
--- a/iguana/iguana777.c
+++ b/iguana/iguana777.c
@@ -284,7 +284,7 @@ int32_t iguana_helpertask(FILE *fp,struct OS_memspace *mem,struct OS_memspace *m
void iguana_helper(void *arg)
{
- FILE *fp = 0; char fname[512],name[64],*helpername = 0; cJSON *argjson=0; int32_t i,flag;
+ FILE *fp = 0; char fname[512],name[64],*helpername = 0; cJSON *argjson=0; int32_t flag;
struct iguana_helper *ptr; struct iguana_info *coin; struct OS_memspace MEM,*MEMB;
if ( arg != 0 && (argjson= cJSON_Parse(arg)) != 0 )
helpername = jstr(argjson,"name");
@@ -302,6 +302,7 @@ void iguana_helper(void *arg)
MEMB = mycalloc('b',IGUANA_MAXBUNDLESIZE,sizeof(*MEMB));
while ( 1 )
{
+ iguana_jsonQ();
flag = 0;
if ( (ptr= queue_dequeue(&helperQ,0)) != 0 )
{
@@ -316,11 +317,11 @@ void iguana_helper(void *arg)
}
if ( flag == 0 )
{
- for (i=0; ilaunched != 0 )
flag += iguana_rpctest(coin);
- }
+ }*/
if ( flag == 0 )
usleep(10000);
}
diff --git a/iguana/iguana777.h b/iguana/iguana777.h
index b83bd6038..03009f3f3 100755
--- a/iguana/iguana777.h
+++ b/iguana/iguana777.h
@@ -132,7 +132,7 @@ extern int32_t IGUANA_NUMHELPERS;
#define IGUANA_ALLOC_MULT 1.1
#define IGUANA_ALLOC_INCR 1000
-#define IGUANA_JSONTIMEOUT 10000
+#define IGUANA_JSONTIMEOUT 1000
#define IGUANA_MAPRECVDATA 1
#define IGUANA_MAPTXIDITEMS 2
@@ -432,7 +432,7 @@ struct iguana_info
struct iguana_bitmap screen;
//struct pollfd fds[IGUANA_MAXPEERS]; struct iguana_peer bindaddr; int32_t numsocks;
struct OS_memspace TXMEM;
- queue_t acceptQ,bundlesQ,hdrsQ,blocksQ,priorityQ,possibleQ,jsonQ,finishedQ,TerminateQ,cacheQ;
+ queue_t acceptQ,bundlesQ,hdrsQ,blocksQ,priorityQ,possibleQ,TerminateQ,cacheQ;
double parsemillis,avetime; uint32_t Launched[8],Terminated[8];
portable_mutex_t peers_mutex,blocks_mutex;
struct iguana_bundle *bundles[IGUANA_MAXBUNDLES];
@@ -477,7 +477,7 @@ int32_t iguana_rwblock(int32_t rwflag,bits256 *hash2p,uint8_t *serialized,struct
int32_t iguana_serialize_block(bits256 *hash2p,uint8_t serialized[sizeof(struct iguana_msgblock)],struct iguana_block *block);
void iguana_blockconv(struct iguana_block *dest,struct iguana_msgblock *msg,bits256 hash2,int32_t height);
//void iguana_freetx(struct iguana_msgtx *tx,int32_t n);
-int32_t iguana_parser(struct iguana_info *coin,struct iguana_peer *addr,struct OS_memspace *rawmem,struct OS_memspace *txmem,struct OS_memspace *hashmem,struct iguana_msghdr *H,uint8_t *data,int32_t datalen);
+int32_t iguana_msgparser(struct iguana_info *coin,struct iguana_peer *addr,struct OS_memspace *rawmem,struct OS_memspace *txmem,struct OS_memspace *hashmem,struct iguana_msghdr *H,uint8_t *data,int32_t datalen);
// send message
int32_t iguana_validatehdr(struct iguana_msghdr *H);
@@ -559,7 +559,7 @@ double dxblend(double *destp,double val,double decay);
// json
int32_t iguana_processjsonQ(struct iguana_info *coin); // reentrant, can be called during any idletime
-char *iguana_JSON(struct iguana_info *coin,char *jsonstr,char *remoteaddr);
+char *iguana_JSON(char *jsonstr);
char *SuperNET_p2p(struct iguana_info *coin,int32_t *delaymillisp,char *ipaddr,uint8_t *data,int32_t datalen);
char *mbstr(char *str,double);
@@ -670,11 +670,14 @@ int32_t iguana_send_supernet(struct iguana_info *coin,struct iguana_peer *addr,c
struct iguana_waccount *iguana_waccountfind(struct iguana_info *coin,char *account);
struct iguana_waccount *iguana_waccountadd(struct iguana_info *coin,char *walletaccount,struct iguana_waddress *waddr);
-int32_t iguana_waccountswitch(struct iguana_info *coin,struct iguana_waddress *waddr,char *coinaddr);
-struct iguana_waddress *iguana_waddressfind(struct iguana_info *coin,char *coinaddr);
+int32_t iguana_waccountswitch(struct iguana_info *coin,char *account,struct iguana_waccount *oldwaddr,int32_t oldind,char *coinaddr);
+struct iguana_waddress *iguana_waddresscalc(struct iguana_info *coin,struct iguana_waddress *addr,bits256 privkey);
+struct iguana_waccount *iguana_waddressfind(struct iguana_info *coin,int32_t *indp,char *coinaddr);
char *iguana_coinjson(struct iguana_info *coin,char *method,cJSON *json);
cJSON *iguana_peersjson(struct iguana_info *coin,int32_t addronly);
int32_t btc_priv2wip(char *wipstr,uint8_t privkey[32],uint8_t addrtype);
int32_t btc_pub2rmd(uint8_t rmd160[20],uint8_t pubkey[33]);
+int32_t iguana_launchcoin(char *symbol,cJSON *json);
+int32_t iguana_jsonQ();
#endif
diff --git a/iguana/iguana_bitmap.c b/iguana/iguana_bitmap.c
index 1a8d57880..678af8bd2 100755
--- a/iguana/iguana_bitmap.c
+++ b/iguana/iguana_bitmap.c
@@ -123,7 +123,7 @@ void gen_jpegfile(char *fname,int32_t quality,uint8_t *bitmap,int32_t width,int3
int row_stride; /* physical row width in image buffer */
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
- if ((outfile = fopen(fname, "wb")) == NULL)
+ if ( (outfile= fopen(fname,"wb")) == NULL)
{
fprintf(stderr, "can't open %s\n", fname);
exit(1);
@@ -1131,11 +1131,10 @@ void iguana_bitmap(char *space,int32_t max,char *name)
//sprintf(space,"Content-type: text/standard\r\n");
//sprintf(space+strlen(space),"Content-Length: %ld\r\n\r\n",strlen(buf));
//strcpy(space,buf);
- //printf("bitmap.[%s]\n",space);
+ printf("bitmap.[%s]\n",space);
}
else
{
- sprintf(space,"{\"name\":\"%s\",\"status\":\"%s\",\"amplitude\":%u,\"width\":%d,\"height\":%d,\"pixels\":[",name,coin!=0?coin->statusstr:"no coin",rect->amplitude,rect->width,rect->height), len = (int32_t)strlen(space);
ptr = rect->data;
h = rect->height, w = rect->width;
for (y=0; ysymbol) == 0 )
{
+ printf("found.(%s)\n",name);
iguana_chaininit(chain,strcmp(chain->symbol,"BTC") == 0);
return(chain);
}
diff --git a/iguana/iguana_html.c b/iguana/iguana_html.c
index 83c4178b4..a87762154 100755
--- a/iguana/iguana_html.c
+++ b/iguana/iguana_html.c
@@ -14,7 +14,7 @@
******************************************************************************/
#include "iguana777.h"
-#include "../includes/cJSON.h"
+#include "SuperNET.h"
char Default_agent[64] = { "ALL" };
#define IGUANA_FORMS "[ \
@@ -152,552 +152,6 @@ char *HTMLfooter =
#define HTML_EMIT(str) if ( (str) != 0 && (str)[0] != 0 ) strcpy(&retbuf[size],str), size += (int32_t)strlen(str)
char Prevjsonstr[1024],Currentjsonstr[1024];
-char *iguana_rpc(char *agent,cJSON *json,char *data,int32_t datalen,char *remoteaddr)
-{
- //printf("agent.(%s) json.(%s) data[%d] %s\n",agent,jprint(json,0),datalen,data!=0?data:"");
- if ( data == 0 )
- return(iguana_JSON(0,jprint(json,0),remoteaddr));
- else return(iguana_JSON(0,data,remoteaddr));
-}
-
-void iguana_urldecode(char *str)
-{
- int32_t a,b,c; char *dest = str;
- while ( (c= *str) != 0 )
- {
- if ( c == '%' && (a= str[1]) != 0 && (b= str[2]) != 0 )
- *dest++ = (unhex(a)<<4) | unhex(b);
- else *dest++ = c;
- }
- *dest = 0;
-}
-
-char *iguana_parsebidask(char *base,char *rel,char *exchange,double *pricep,double *volumep,char *line)
-{
- int32_t i;
- for (i=0; i<16&&line[i]!='/'&&line[i]!=0; i++)
- base[i] = line[i];
- base[i] = 0;
- touppercase(base);
- line += (i + 1);
- for (i=0; i<16&&line[i]!='/'&&line[i]!=0; i++)
- rel[i] = line[i];
- rel[i] = 0;
- touppercase(rel);
- line += (i + 1);
- for (i=0; i<16&&line[i]!='/'&&line[i]!=0; i++)
- exchange[i] = line[i];
- exchange[i] = 0;
- line += (i + 1);
- if ( strncmp(line,"price/",strlen("price/")) == 0 )
- {
- line += strlen("price/");
- *pricep = atof(line);
- if ( (line= strstr(line,"volume/")) != 0 )
- {
- line += strlen("volume/");
- *volumep = atof(line);
- for (i=0; i<16&&line[i]!=0; i++)
- if ( line[i] == '/' )
- {
- i++;
- break;
- }
- return(line+i);
- }
- }
- return(0);
-}
-
-char *iguana_InstantDEX(char *jsonstr,char *path,char *method)
-{
- char *str,base[64],rel[64],exchange[64]; double price,volume;
- if ( (str= iguana_parsebidask(base,rel,exchange,&price,&volume,path)) != 0 )
- {
- if ( price > 0. && volume > 0. )
- {
- sprintf(jsonstr,"{\"agent\":\"InstantDEX\",\"method\":\"%s\",\"base\":\"%s\",\"rel\":\"%s\",\"exchange\":\"%s\",\"price\":\%0.8f,\"volume\":%0.8f}",method,base,rel,exchange,price,volume);
- return(jsonstr);
- }
- else return(0);
- }
- return(0);
-}
-
-void iguana_coinset(char *buf,char *path)
-{
- int32_t i;
- if ( path[0] == '/' )
- path++;
- for (i=0; i<8&&path[i]!=0&&path[i]!=' '&&path[i]!='/'; i++)
- buf[i] = path[i];
- buf[i] = 0;
- touppercase(buf);
-}
-
-char *iguana_ramchain_glue(struct iguana_info *coin,char *method,char *jsonstr)
-{
- char *ramchain_parser(struct iguana_agent *agent,struct iguana_info *coin,char *method,cJSON *json);
- cJSON *json; char *retstr;
- json = cJSON_Parse(jsonstr);
- retstr = ramchain_parser(0,coin,method,json);
- free_json(json);
- return(retstr);
-}
-
-char *iguana_hashparse(char *path)
-{
- int32_t i,j,len,iter,n; uint8_t databuf[512];
- char hexstr[1025],password[512],hashname[512],*name,*msg; cJSON *json;
- typedef void (*hashfunc)(char *hexstr,uint8_t *buf,uint8_t *msg,int32_t len);
- typedef char *(*hmacfunc)(char *dest,char *key,int32_t key_size,char *message);
- struct hashfunc_entry { char *name; hashfunc hashfunc; };
- struct hmacfunc_entry { char *name; hmacfunc hmacfunc; };
- struct hashfunc_entry hashes[] = { {"NXT",calc_NXTaddr}, {"curve25519",calc_curve25519_str }, {"base64_encode",calc_base64_encodestr}, {"base64_decode",calc_base64_decodestr}, {"crc32",calc_crc32str}, {"rmd160_sha256",rmd160ofsha256}, {"sha256_sha256",sha256_sha256}, {"sha256",vcalc_sha256}, {"sha512",calc_sha512}, {"sha384",calc_sha384}, {"sha224",calc_sha224}, {"rmd160",calc_rmd160}, {"rmd256",calc_rmd256}, {"rmd320",calc_rmd320}, {"rmd128",calc_rmd128}, {"sha1",calc_sha1}, {"md5",calc_md5str}, {"tiger",calc_tiger}, {"whirlpool",calc_whirlpool} };
- struct hmacfunc_entry hmacs[] = { {"hmac_sha256",hmac_sha256_str}, {"hmac_sha512",hmac_sha512_str}, {"hmac_sha384",hmac_sha384_str}, {"hmac_sha224",hmac_sha224_str}, {"hmac_rmd160",hmac_rmd160_str}, {"hmac_rmd256",hmac_rmd256_str}, {"hmac_rmd320",hmac_rmd320_str}, {"hmac_rmd128",hmac_rmd128_str}, {"hmac_sha1",hmac_sha1_str}, {"hmac_md5",hmac_md5_str}, {"hmac_tiger",hmac_tiger_str}, {"hmac_whirlpool",hmac_whirlpool_str} };
- n = (int32_t)sizeof(hashes)/sizeof(*hashes);
- for (j=0; j 0 )
- {
- jsonstr[i] = 0;
- agent = jsonstr;
- jsonstr += i;
- }
- jsonstr++;
- json = cJSON_CreateObject();
- jaddstr(json,"agent",agent);
- while ( 1 )
- {
- n = (int32_t)strlen(jsonstr);
- key = jsonstr;
- value = 0;
- for (i=0; i ");
+ HTML_EMIT(" SuperUGLY GUI> ");
sprintf(buf,"
");
- //sprintf(buf,"
COIN: ");
- //HTML_EMIT(buf);
- if ( 0 )
- {
- sprintf(formfooter,"\t","InstantDEX","iguana49_setagent"); HTML_EMIT(formfooter);
- sprintf(formfooter,"\t","PAX","iguana50_setagent"); HTML_EMIT(formfooter);
- sprintf(formfooter,"\t","pangea","iguana51_setagent"); HTML_EMIT(formfooter);
- sprintf(formfooter,"\t","jumblr","iguana52_setagent"); HTML_EMIT(formfooter);
- sprintf(formfooter,"\t","ramchain","iguana53_setagent"); HTML_EMIT(formfooter);
- sprintf(formfooter,"\t","iguana","iguana54_setagent"); HTML_EMIT(formfooter);
- }
- HTML_EMIT(" Agent: "); HTML_EMIT(Default_agent);
-
HTML_EMIT("
");
HTML_EMIT(origjsonstr); HTML_EMIT(" -> ");
- HTML_EMIT("