/****************************************************************************** * Copyright © 2014-2016 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 "iguana777.h" #include "SuperNET.h" #define RPCARGS struct supernet_info *myinfo,uint16_t port,struct iguana_info *coin,cJSON *params[],int32_t n,cJSON *json,char *remoteaddr,cJSON *array #define GLUEARGS cJSON *json,struct supernet_info *myinfo,uint16_t port,struct iguana_info *coin,char *remoteaddr,cJSON *params[] #define CALLGLUE myinfo,port,coin,remoteaddr,params char *sglue(GLUEARGS,char *agent,char *method) { char *retstr,*rpcretstr,*walletstr; cJSON *retjson,*tmpjson,*result,*error,*wallet; int32_t i,j,len; if ( json == 0 ) json = cJSON_CreateObject(); //printf("sglue.(%s)\n",jprint(json,0)); jaddstr(json,"agent",agent); jaddstr(json,"method",method); jaddstr(json,"coin",coin->symbol); if ( (retstr= SuperNET_JSON(myinfo,json,remoteaddr,port)) != 0 ) { if ( (retjson= cJSON_Parse(retstr)) != 0 ) { if ( myinfo->dirty != 0 && myinfo->secret[0] != 0 ) { if ( (wallet= iguana_walletjson(myinfo)) != 0 ) { //printf("WALLETSTR.(%s)\n",jprint(wallet,0)); if ( (walletstr= SuperNET_login(myinfo,coin,json,remoteaddr,myinfo->handle,myinfo->secret,myinfo->permanentfile,0)) != 0 ) { free(walletstr); walletstr = myinfo->decryptstr, myinfo->decryptstr = 0; if ( walletstr != 0 && (tmpjson= cJSON_Parse(walletstr)) != 0 ) { jdelete(tmpjson,"wallet"); jadd(tmpjson,"wallet",wallet); if ( iguana_payloadupdate(myinfo,coin,jprint(tmpjson,1),0,0) == 0 ) { printf("wallet updated\n"); myinfo->dirty = 0; } else printf("iguana_payloadupdate error\n"); } else printf("error parsing decryptstr\n"); if ( walletstr != 0 ) free(walletstr); } else printf("ERROR: dirty wallet is unsaved, iguana_payloadupdate error\n"); } else printf("ERROR: dirty wallet is unsaved, unlock wallet\n"); } if ( jobj(retjson,"tag") != 0 ) jdelete(retjson,"tag"); ///printf("RPCret.(%s) n.%d\n",jprint(retjson,0),cJSON_GetArraySize(retjson)); result = cJSON_GetObjectItem(retjson,"result"); error = cJSON_GetObjectItem(retjson,"error"); if ( result != 0 && cJSON_GetArraySize(retjson) == 1 ) { if ( (error == 0 || (error->type&0xff) == cJSON_NULL) && (result->type&0xff) != cJSON_NULL ) { rpcretstr = cJSON_Print(result); len = (int32_t)strlen(rpcretstr); if ( rpcretstr[0] == '"' && rpcretstr[len-1] == '"' ) { for (i=1,j=0; itype&0xff) != cJSON_NULL || (result->type&0xff) != cJSON_NULL ) printf("<<<<<<<<<<< bitcoind_RPC: post_process_bitcoind_RPC error.%s\n",retstr); } free_json(retjson); } } //free_json(json); return(retstr); } char *sglue1(GLUEARGS,char *agent,char *method,char *field,cJSON *obj) { if ( json == 0 ) json = cJSON_CreateObject(); if ( obj != 0 && field != 0 ) jadd(json,field,obj); params[0] = 0; //printf("sglue1.(%s)\n",jprint(json,0)); return(sglue(json,CALLGLUE,agent,method)); } char *sglueN(GLUEARGS,char *agent,char *method,char *field,double num) { if ( json == 0 ) json = cJSON_CreateObject(); jaddnum(json,field,num); return(sglue(json,CALLGLUE,agent,method)); } char *sglue2(GLUEARGS,char *agent,char *method,char *field0,cJSON *obj0,char *field1,cJSON *obj1) { if ( json == 0 ) json = cJSON_CreateObject(); if ( obj1 != 0 && field1 != 0 ) jadd(json,field1,obj1); params[1] = 0; //printf("sglue2.(%s)\n",jprint(json,0)); return(sglue1(json,CALLGLUE,agent,method,field0,obj0)); } char *sglue3(GLUEARGS,char *agent,char *method,char *field0,cJSON *obj0,char *field1,cJSON *obj1,char *field2,cJSON *obj2) { if ( json == 0 ) json = cJSON_CreateObject(); if ( obj2 != 0 && field2 != 0 ) jadd(json,field2,obj2); params[2] = 0; //printf("sglue3.(%s)\n",jprint(json,0)); return(sglue2(json,CALLGLUE,agent,method,field0,obj0,field1,obj1)); } char *sglue4(GLUEARGS,char *agent,char *method,char *field0,cJSON *obj0,char *field1,cJSON *obj1,char *field2,cJSON *obj2,char *field3,cJSON *obj3) { if ( json == 0 ) json = cJSON_CreateObject(); if ( obj3 != 0 && field3 != 0 ) jadd(json,field3,obj3); params[3] = 0; return(sglue3(json,CALLGLUE,agent,method,field0,obj0,field1,obj1,field2,obj2)); } char *sglue5(GLUEARGS,char *agent,char *method,char *field0,cJSON *obj0,char *field1,cJSON *obj1,char *field2,cJSON *obj2,char *field3,cJSON *obj3,char *field4,cJSON *obj4) { if ( json == 0 ) json = cJSON_CreateObject(); if ( obj4 != 0 && field4 != 0 ) jadd(json,field4,obj4); params[4] = 0; return(sglue4(json,CALLGLUE,agent,method,field0,obj0,field1,obj1,field2,obj2,field3,obj3)); } char *sglue6(GLUEARGS,char *agent,char *method,char *field0,cJSON *obj0,char *field1,cJSON *obj1,char *field2,cJSON *obj2,char *field3,cJSON *obj3,char *field4,cJSON *obj4,char *field5,cJSON *obj5) { if ( json == 0 ) json = cJSON_CreateObject(); if ( obj5 != 0 && field5 != 0 ) jadd(json,field5,obj5); params[5] = 0; return(sglue5(json,CALLGLUE,agent,method,field0,obj0,field1,obj1,field2,obj2,field3,obj3,field4,obj4)); } // misc static char *help(RPCARGS) { return(sglue(0,CALLGLUE,"SuperNET","help")); } static char *stop(RPCARGS) { return(sglue(0,CALLGLUE,"iguana","pausecoin")); } static char *sendalert(RPCARGS) { return(sglue1(0,CALLGLUE,"iguana","sendalert","message",params[0])); } static char *SuperNET(RPCARGS) { return(SuperNET_JSON(myinfo,json,remoteaddr,port)); } static char *getrawmempool(RPCARGS) { return(sglue(0,CALLGLUE,"iguana","getrawmempool")); } // peers static char *getconnectioncount(RPCARGS) { return(sglue(0,CALLGLUE,"iguana","getconnectioncount")); } static char *getpeerinfo(RPCARGS) { return(sglue(0,CALLGLUE,"iguana","peers")); } static char *addnode(RPCARGS) { char *mode,*cmd = 0; if ( (mode= jstr(params[1],0)) != 0 ) { if ( strcmp(mode,"add") == 0 ) cmd = "addnode"; else if ( strcmp(mode,"remove") == 0 ) cmd = "removenode"; else if ( strcmp(mode,"onetry") == 0 ) cmd = "onetry"; if ( cmd != 0 ) return(sglue1(0,CALLGLUE,"iguana",cmd,"ipaddr",params[0])); } // addnode version 0.8 Attempts add or remove from the addnode list or try a connection to once. N return(clonestr("{\"error\":\"invalid addnode parameter\"}")); } // address and pubkeys static char *validateaddress(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","validateaddress","address",params[0])); } static char *validatepubkey(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","validatepubkey","pubkey",params[0])); } static char *createmultisig(RPCARGS) { return(sglue2(0,CALLGLUE,"bitcoinrpc","createmultisig","M",params[0],"pubkeys",params[1])); } static char *addmultisigaddress(RPCARGS) { return(sglue3(0,CALLGLUE,"bitcoinrpc","addmultisigaddress","M",params[0],"pubkeys",params[1],"account",params[2])); } // blockchain static char *getinfo(RPCARGS) { return(sglue(0,CALLGLUE,"bitcoinrpc","getinfo")); } static char *getbestblockhash(RPCARGS) { return(sglue(0,CALLGLUE,"bitcoinrpc","getbestblockhash")); } static char *getblockcount(RPCARGS) { return(sglue(0,CALLGLUE,"bitcoinrpc","getblockcount")); } static char *getblock(RPCARGS) { cJSON *obj; if ( params[1] == 0 ) params[1] = cJSON_CreateNumber(1); else { obj = params[1]; if ( is_cJSON_False(params[1]) != 0 ) params[1] = cJSON_CreateNumber(0); else params[1] = cJSON_CreateNumber(1); free_json(obj); } return(sglue3(0,CALLGLUE,"bitcoinrpc","getblock","blockhash",params[0],"verbose",params[1],"remoteonly",params[2])); } static char *getblockhash(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","getblockhash","height",params[0])); } static char *gettransaction(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","gettransaction","txid",params[0])); } static char *listtransactions(RPCARGS) { return(sglue3(0,CALLGLUE,"bitcoinrpc","listtransactions","account",params[0],"count",params[1],"from",params[2])); } static char *getreceivedbyaddress(RPCARGS) { return(sglue2(0,CALLGLUE,"bitcoinrpc","getreceivedbyaddress","address",params[0],"minconfs",params[1])); } static char *listreceivedbyaddress(RPCARGS) { return(sglue2(0,CALLGLUE,"bitcoinrpc","listreceivedbyaddress","minconf",params[0],"includeempty",params[1])); } static char *listsinceblock(RPCARGS) { return(sglue2(0,CALLGLUE,"bitcoinrpc","listsinceblock","blockhash",params[0],"target",params[1])); } // waccount and waddress funcs static char *getreceivedbyaccount(RPCARGS) { return(sglue2(0,CALLGLUE,"bitcoinrpc","getreceivedbyaccount","account",params[0],"minconfs",params[1])); } static char *listreceivedbyaccount(RPCARGS) { return(sglue2(0,CALLGLUE,"bitcoinrpc","listreceivedbyaccount","account",params[0],"includeempty",params[1])); } static char *getnewaddress(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","getnewaddress","account",params[0])); } static char *vanitygen(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","vanitygen","vanity",params[0])); } static char *makekeypair(RPCARGS) { return(sglue(0,CALLGLUE,"bitcoinrpc","makekeypair")); } static char *getaccountaddress(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","getaccountaddress","account",params[0])); } static char *setaccountrpc(RPCARGS) { return(sglue2(0,CALLGLUE,"bitcoinrpc","setaccount","address",params[0],"account",params[1])); } static char *getaccount(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","getaccount","address",params[0])); } static char *getaddressesbyaccount(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","getaddressesbyaccount","account",params[0])); } static char *listaddressgroupings(RPCARGS) { return(sglue(0,CALLGLUE,"bitcoinrpc","listaddressgroupings")); } static char *getbalance(RPCARGS) { return(sglue2(0,CALLGLUE,"bitcoinrpc","getbalance","account",params[0],"minconf",params[1])); } // wallet static char *listaccounts(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","listaccounts","minconf",params[0])); } static char *dumpprivkey(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","dumpprivkey","address",params[0])); } static char *importprivkey(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","importprivkey","wif",params[0])); } static char *dumpwallet(RPCARGS) { return(sglue(0,CALLGLUE,"bitcoinrpc","dumpwallet")); } static char *importwallet(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","importwallet","wallet",params[0])); } static char *walletpassphrase(RPCARGS) { return(sglue3(0,CALLGLUE,"bitcoinrpc","walletpassphrase","password",params[0],"permanentfile",params[2],"timeout",params[1])); } static char *walletpassphrasechange(RPCARGS) { return(sglue4(0,CALLGLUE,"bitcoinrpc","walletpassphrasechange","oldpassphrase",params[0],"newpassphrase",params[1],"oldpermanentfile",params[2],"oldpermanentfile",params[3])); } static char *walletlock(RPCARGS) { return(sglue(0,CALLGLUE,"bitcoinrpc","walletlock")); } static char *encryptwallet(RPCARGS) { return(sglue2(0,CALLGLUE,"bitcoinrpc","encryptwallet","passphrase",params[0],"password",params[1])); } static char *checkwallet(RPCARGS) { return(sglue(0,CALLGLUE,"bitcoinrpc","checkwallet")); } static char *repairwallet(RPCARGS) { return(sglue(0,CALLGLUE,"bitcoinrpc","repairwallet")); } static char *backupwallet(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","backupwallet","filename",params[0])); } // messages static char *signmessage(RPCARGS) { return(sglue2(0,CALLGLUE,"bitcoinrpc","signmessage","address",params[0],"message",params[1])); } static char *verifymessage(RPCARGS) { return(sglue3(0,CALLGLUE,"bitcoinrpc","verifymessage","address",params[0],"sig",params[1],"message",params[2])); } // unspents static char *listunspent(RPCARGS) { return(sglue3(0,CALLGLUE,"bitcoinrpc","listunspent","minconf",params[0],"maxconf",params[1],"array",params[2])); } static char *lockunspent(RPCARGS) { return(sglue2(0,CALLGLUE,"bitcoinrpc","lockunspent","flag",params[0],"array",params[1])); } static char *listlockunspent(RPCARGS) { return(sglue(0,CALLGLUE,"bitcoinrpc","listlockunspent")); } static char *gettxout(RPCARGS) { return(sglue3(0,CALLGLUE,"bitcoinrpc","gettxout","txid",params[0],"vout",params[1],"mempool",params[2])); } static char *gettxoutsetinfo(RPCARGS) { return(sglue(0,CALLGLUE,"bitcoinrpc","gettxoutsetinfo")); } // payments static char *sendtoaddress(RPCARGS) { return(sglue4(0,CALLGLUE,"bitcoinrpc","sendtoaddress","address",params[0],"amount",params[1],"comment",params[2],"comment2",params[3])); } static char *movecmd(RPCARGS) { return(sglue5(0,CALLGLUE,"bitcoinrpc","move","fromaccount",params[0],"toaccount",params[1],"amount",params[2],"minconf",params[3],"comment",params[4])); } static char *sendfrom(RPCARGS) { return(sglue6(0,CALLGLUE,"bitcoinrpc","sendfrom","fromaccount",params[0],"toaddress",params[1],"amount",params[2],"minconf",params[3],"comment",params[4],"comment2",params[5])); } static char *sendmany(RPCARGS) { return(sglue4(0,CALLGLUE,"bitcoinrpc","sendmany","fromaccount",params[0],"payments",params[1],"minconf",params[2],"comment",params[3])); } static char *settxfee(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","settxfee","amount",params[0])); } // rawtransaction static char *getrawtransaction(RPCARGS) { return(sglue2(0,CALLGLUE,"bitcoinrpc","getrawtransaction","txid",params[0],"verbose",params[1])); } static char *createrawtransaction(RPCARGS) { return(sglue3(0,CALLGLUE,"bitcoinrpc","createrawtransaction","vins",params[0],"vouts",params[1],"locktime",params[2])); } static char *decoderawtransaction(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","decoderawtransaction","rawtx",params[0])); } static char *decodescript(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","decodescript","scriptstr",params[0])); } static char *signrawtransaction(RPCARGS) { return(sglue4(0,CALLGLUE,"bitcoinrpc","signrawtransaction","rawtx",params[0],"vins",params[1],"privkeys",params[2],"sighash",params[3])); } static char *sendrawtransaction(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","sendrawtransaction","rawtx",params[0])); } static char *getrawchangeaddress(RPCARGS) { return(sglue1(0,CALLGLUE,"bitcoinrpc","getrawchangeaddress","account",params[0])); } #define true 1 #define false 0 struct RPC_info { char *name; char *(*rpcfunc)(RPCARGS); int32_t flag0,remoteflag; } RPCcalls[] = { { "validatepubkey", &validatepubkey, true, true }, { "makekeypair", &makekeypair, false, false }, { "listunspent", &listunspent, false, false }, { "getblockhash", &getblockhash, false, true }, { "walletpassphrase", &walletpassphrase, true, false }, { "SuperNET", &SuperNET, false, true }, //{ "SuperNETb", &SuperNET, false, true }, { "help", &help, true, false }, { "stop", &stop, true, true }, { "getbestblockhash", &getbestblockhash, true, true }, { "getblockcount", &getblockcount, true, true }, { "getconnectioncount", &getconnectioncount, true, true }, { "getpeerinfo", &getpeerinfo, true, true }, { "getinfo", &getinfo, true, true }, { "getnewaddress", &getnewaddress, true, false }, { "getnewpubkey", &makekeypair, true, false }, { "getaccountaddress", &getaccountaddress, true, false }, { "setaccount", &setaccountrpc, true, false }, { "getaccount", &getaccount, false, false }, { "getaddressesbyaccount", &getaddressesbyaccount, true, false }, { "sendtoaddress", &sendtoaddress, false, false }, { "getreceivedbyaddress", &getreceivedbyaddress, false, false }, { "getreceivedbyaccount", &getreceivedbyaccount, false, false }, { "listreceivedbyaddress", &listreceivedbyaddress, false, false }, { "listreceivedbyaccount", &listreceivedbyaccount, false, false }, { "backupwallet", &backupwallet, true, false }, { "walletpassphrasechange", &walletpassphrasechange, false, false }, { "walletlock", &walletlock, true, false }, { "encryptwallet", &encryptwallet, false, false }, { "validateaddress", &validateaddress, true, true }, { "getbalance", &getbalance, false, false }, { "move", &movecmd, false, false }, { "sendfrom", &sendfrom, false, false }, { "sendmany", &sendmany, false, false }, { "addmultisig", &addmultisigaddress, false, false }, { "addmultisigaddress", &addmultisigaddress, false, false }, { "getblock", &getblock, false, true }, { "gettransaction", &gettransaction, false, true }, { "listtransactions", &listtransactions, false, false }, { "listaddressgroupings", &listaddressgroupings, false, false }, { "signmessage", &signmessage, false, false }, { "verifymessage", &verifymessage, false, false }, { "listaccounts", &listaccounts, false, false }, { "settxfee", &settxfee, false, false }, { "listsinceblock", &listsinceblock, false, false }, { "dumpprivkey", &dumpprivkey, false, false }, { "dumpwallet", &dumpwallet, true, false }, { "importwallet", &importwallet, false, false }, { "importprivkey", &importprivkey, false, false }, { "getrawtransaction", &getrawtransaction, false, false }, { "createrawtransaction", &createrawtransaction, false, false }, { "decoderawtransaction", &decoderawtransaction, false, true }, { "decodescript", &decodescript, false, true }, { "signrawtransaction", &signrawtransaction, false, false }, { "sendrawtransaction", &sendrawtransaction, false, true }, { "checkwallet", &checkwallet, false, false }, { "repairwallet", &repairwallet, false, false }, { "sendalert", &sendalert, false, false }, // { "createmultisig", &createmultisig, false, false }, { "addnode", &addnode, false, false }, { "getrawmempool", &getrawmempool, false, true }, { "getrawchangeaddress", &getrawchangeaddress, false, false }, { "listlockunspent", &listlockunspent, false, false }, { "lockunspent", &lockunspent, false, false }, { "gettxout", &gettxout, false, true }, { "gettxoutsetinfo", &gettxoutsetinfo, false, true }, { "vanitygen", &vanitygen, false, false } #ifdef PEGGY //{ "peggytx", &peggytx, true, false }, //{ "peggypayments", &peggypayments, true, false }, //{ "getpeggyblock", &getpeggyblock, true, false }, #endif //{ "resendtx", &resendtx, false, true}, // { "addredeemscript", &addredeemscript, false, false }, // { "getrawmempool", &getrawmempool, true, false }, // { "getdifficulty", &getdifficulty, true, false }, // { "getsubsidy", &getsubsidy, true, false }, // { "getmininginfo", &getmininginfo, true, false }, // { "getstakinginfo", &getstakinginfo, true, false }, // { "getblockbynumber", &getblockbynumber, false, false }, //{ "getwork", &getwork, true, false }, //{ "getworkex", &getworkex, true, false }, // { "keypoolrefill", &keypoolrefill, true, false }, //{ "getblocktemplate", &getblocktemplate, true, false }, //{ "submitblock", &submitblock, false, false }, // { "getcheckpoint", &getcheckpoint, true, false }, // { "reservebalance", &reservebalance, false, true}, }; int32_t is_bitcoinrpc(struct supernet_info *myinfo,char *method,char *remoteaddr) { int32_t i; for (i=0; ipublicRPC != 0 ) return(i); } } return(-1); } char *iguana_bitcoinrpc(struct supernet_info *myinfo,uint16_t port,struct iguana_info *coin,char *method,cJSON *params[16],int32_t n,cJSON *json,char *remoteaddr,cJSON *array) { int32_t i; for (i=0; irpcport ) { if ( jstr(json,"coin") == 0 ) { strcpy(symbol,myinfo->rpcsymbol); if ( symbol[0] == 0 ) { c = 'B'; sprintf(symbol,"%c%c%c%c",c,'T',c+1,c+2); } } else safecopy(symbol,jstr(json,"coin"),sizeof(symbol)); if ( myinfo->rpcsymbol[0] == 0 ) strcpy(myinfo->rpcsymbol,symbol); } else { for (i=0; ichain->rpcport == port ) break; if ( i == IGUANA_MAXCOINS ) coin = 0; } if ( coin == 0 && symbol[0] != 0 ) coin = iguana_coinfind(symbol); //printf("method.(%s) (%s) remote.(%s) symbol.(%s)\n",method,jprint(json,0),remoteaddr,symbol); if ( method != 0 && symbol[0] != 0 && (coin != 0 || (coin= iguana_coinfind(symbol)) != 0) ) { if ( (array= jarray(&n,json,"params")) == 0 ) { i= 0, n = 0; } else if ( n > 0 ) { //printf("n.%d (%s)\n",n,jstr(array,0)); for (i=n-1; i>=0; i--) { params[i] = cJSON_DetachItemFromArray(array,i);//; //printf("add params[%d] of %d <- (%s) %p.(%p %p)\n",i,n,jprint(params[i],0),params[i],params[i]->next,params[i]->prev); } } retstr = iguana_bitcoinrpc(myinfo,IGUANA_RPCPORT,coin,method,params,n,json,remoteaddr,array); if ( n > 0 ) for (i=0; i= keymax-1 ) { *key = 0; printf("lineparse overflow key.(%s)\n",src); return(-1); } } *key = 0; //printf("-> key.(%s)\n",origkey); 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++; } //printf("key.(%s) value.(%s)\n",origkey,origvalue); 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; //printf("URLSTR[%d]=%s\n",i,&urlstr[len]); 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); //printf("urlconv.(%s)\n",jprint(json,0)); return(json); } char *SuperNET_rpcparse(struct supernet_info *myinfo,char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *postflagp,char *urlstr,char *remoteaddr,char *filetype,uint16_t port) { cJSON *tokens,*argjson,*json = 0; long filesize; char symbol[16],buf[4096],urlmethod[16],*data,url[1024],*retstr,*filestr,*token = 0; int32_t i,j,n,num=0; //printf("rpcparse.(%s)\n",urlstr); for (i=0; i0; i--) if ( url[i] == '.' || url[i] == '/' ) break; if ( url[i] == '.' ) strcpy(filetype,url+i+1); //printf("return filetype.(%s) size.%ld\n",filetype,filesize); return(filestr); } if ( strncmp(&url[i],"/api",strlen("/api")) == 0 ) { *jsonflagp = 1; i += strlen("/api"); } else *jsonflagp = 0; if ( strncmp(&url[i],"/bitmap",strlen("/bitmap")) == 0 ) { i += strlen("/bitmap"); *jsonflagp = 2; if ( url[i] == '/' ) i++; iguana_bitmap(retbuf,bufsize,&url[i]); return(retbuf); } //printf("URL.(%s)\n",url); if ( strcmp(url,"/favicon.ico") == 0 ) { *jsonflagp = 1; return(0); } if ( url[i] != '/' ) token = &url[i]; n = i; tokens = cJSON_CreateArray(); for (; url[i]!=0; i++) { //printf("i.%d (%c)\n",i,url[i]); if ( url[i] == '/' ) { url[i] = 0; if ( token != 0 ) { //printf("TOKEN.(%s) i.%d\n",token,i); jaddistr(tokens,token); num++; } token = &url[i+1]; i++; //printf("new token.(%s) i.%d\n",token,i+1); continue; } } if ( token != 0 ) { //printf("add token.(%s)\n",token); jaddistr(tokens,token); num++; } argjson = cJSON_CreateObject(); if ( num > 0 ) jaddstr(argjson,"agent",jstri(tokens,0)); if ( num > 1 ) jaddstr(argjson,"method",jstri(tokens,1)); //printf("urlstr.(%s)\n",urlstr+n); if ( (json= SuperNET_urlconv(retbuf,bufsize,urlstr+n)) != 0 ) { jadd(json,"tokens",tokens); jaddstr(json,"urlmethod",urlmethod); if ( (data= jstr(json,"POST")) == 0 || (argjson= cJSON_Parse(data)) == 0 ) { if ( (n= cJSON_GetArraySize(tokens)) > 0 ) { if ( n > 1 ) { if ( jstri(tokens,1) != 0 ) { char *key,*value; strcpy(buf,jstri(tokens,1)); key = value = 0; i = 0; for (; buf[i]!=0; i++) { if ( buf[i] == '?' ) { buf[i] = 0; jdelete(argjson,"method"); jaddstr(argjson,"method",buf); i++; key = &buf[i]; break; } } while ( buf[i] != 0 ) { //printf("iter.[%s]\n",&buf[i]); if ( buf[i] != 0 && key != 0 ) { for (; buf[i]!=0; i++) { if ( buf[i] == '=' ) { buf[i] = 0; i++; //printf("got key.(%s)\n",key); value = &buf[i]; break; } } if ( buf[i] != 0 && value != 0 ) { for (; buf[i]!=0; i++) { if ( buf[i] == '&' ) { buf[i] = 0; jaddstr(argjson,key,value); i++; //printf("got value.(%s)\n",value); value = 0; key = &buf[i]; break; } else if ( buf[i] == '+' ) buf[i] = ' '; } } } } if ( key != 0 && value != 0 ) jaddstr(argjson,key,value); } else { //jdelete(argjson,"method"); //jaddstr(argjson,"method",buf); } } for (i=2; i (%s) postflag.%d (%s)\n",urlstr,jprint(argjson,0),cJSON_Print(json),*postflagp,retstr); free_json(argjson); return(retstr); } *jsonflagp = 1; return(clonestr("{\"error\":\"couldnt process packet\"}")); } int32_t iguana_getcontentlen(char *buf,int32_t recvlen) { char *str,*clenstr = "Content-Length: "; int32_t len = -1; if ( (str= strstr(buf,clenstr)) != 0 ) { //printf("strstr.(%s)\n",str); str += strlen(clenstr); len = atoi(str); //printf("len.%d\n",len); } return(len); } int32_t iguana_getheadersize(char *buf,int32_t recvlen) { char *str,*delim = "\r\n\r\n"; if ( (str= strstr(buf,delim)) != 0 ) return((int32_t)(((long)str - (long)buf) + strlen(delim))); return(recvlen); } void iguana_rpcloop(void *args) { static char *jsonbuf; uint16_t port; struct supernet_info *myinfo = args; char filetype[128],content_type[128]; int32_t recvlen,flag,bindsock,postflag,contentlen,sock,remains,numsent,jsonflag,hdrsize,len; socklen_t clilen; char helpname[512],remoteaddr[64],*buf,*retstr,*space;//,*retbuf; ,n,i,m struct sockaddr_in cli_addr; uint32_t ipbits,i,size = IGUANA_WIDTH*IGUANA_HEIGHT*16 + 512; if ( (port= myinfo->argport) == 0 ) port = myinfo->rpcport; else myinfo->argport = 0; if ( jsonbuf == 0 ) jsonbuf = calloc(1,IGUANA_MAXPACKETSIZE); while ( (bindsock= iguana_socket(1,"127.0.0.1",port)) < 0 ) { //exit(-1); sleep(3); } printf(">>>>>>>>>> iguana_rpcloop 127.0.0.1:%d bind sock.%d iguana API enabled <<<<<<<<<\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,IGUANA_MAXPACKETSIZE); remains = (int32_t)(IGUANA_MAXPACKETSIZE - 1); buf = jsonbuf; recvlen = flag = 0; retstr = 0; while ( remains > 0 ) { //printf("flag.%d remains.%d recvlen.%d\n",flag,remains,recvlen); 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 ) { buf[len] = 0; if ( recvlen == 0 ) { if ( (contentlen= iguana_getcontentlen(buf,recvlen)) > 0 ) { hdrsize = iguana_getheadersize(buf,recvlen); if ( hdrsize > 0 ) { if ( len < (hdrsize + contentlen) ) { remains = (hdrsize + contentlen) - len; buf = &buf[len]; flag = 1; //printf("got.(%s) %d remains.%d of len.%d contentlen.%d hdrsize.%d remains.%d\n",buf,recvlen,remains,len,contentlen,hdrsize,(hdrsize+contentlen)-len); continue; } } } } recvlen += len; remains -= len; buf = &buf[len]; if ( flag == 0 || remains <= 0 ) break; } else { usleep(10000); //printf("got.(%s) %d remains.%d of total.%d\n",jsonbuf,recvlen,remains,len); //retstr = iguana_rpcparse(space,size,&postflag,jsonbuf); if ( flag == 0 ) break; } } } content_type[0] = 0; if ( recvlen > 0 ) { retstr = SuperNET_rpcparse(myinfo,space,size,&jsonflag,&postflag,jsonbuf,remoteaddr,filetype,port); if ( filetype[0] != 0 ) { static cJSON *mimejson; char *tmp,*typestr=0; long tmpsize; sprintf(helpname,"%s/mime.json",GLOBAL_HELPDIR); if ( (tmp= OS_filestr(&tmpsize,helpname)) != 0 ) { mimejson = cJSON_Parse(tmp); free(tmp); } if ( mimejson != 0 ) { if ( (typestr= jstr(mimejson,filetype)) != 0 ) sprintf(content_type,"Content-Type: %s\r\n",typestr); } else printf("parse error.(%s)\n",tmp); //printf("filetype.(%s) json.%p type.%p tmp.%p [%s]\n",filetype,mimejson,typestr,tmp,content_type); } } if ( retstr != 0 ) { char *response,hdrs[1024]; if ( jsonflag != 0 || postflag != 0 ) { response = malloc(strlen(retstr)+1024+1); sprintf(hdrs,"HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Credentials: true\r\nAccess-Control-Allow-Methods: GET, POST\r\nCache-Control : no-cache, no-store, must-revalidate\r\n%sContent-Length : %8d\r\n\r\n",content_type,(int32_t)strlen(retstr)); response[0] = '\0'; strcat(response,hdrs); strcat(response,retstr); if ( retstr != space ) free(retstr); retstr = response; } remains = (int32_t)strlen(retstr); i = 0; 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); } closesocket(sock); } }