void httpIdle() { if (networkState != NETWORKSTATE_ONLINE) return; JsVar *arr = httpGetArray(HTTP_ARRAY_HTTP_SERVERS,false); if (arr) { JsArrayIterator it; jsvArrayIteratorNew(&it, arr); while (jsvArrayIteratorHasElement(&it)) { JsVar *server = jsvArrayIteratorGetElement(&it); SOCKET socket = (SOCKET)jsvGetIntegerAndUnLock(jsvObjectGetChild(server,HTTP_NAME_SOCKET,0))-1; // so -1 if undefined #ifndef USE_CC3000 // TODO: look for unreffed servers? fd_set s; FD_ZERO(&s); FD_SET(socket,&s); // check for waiting clients struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0; int n = select(socket+1,&s,NULL,NULL,&timeout); #else /* CC3000 works a different way - we set accept as nonblocking, * and then we just call it and see if it works or not... */ int n=1; #endif while (n-->0) { // we have a client waiting to connect... int theClient = accept(socket,NULL,NULL); // try and connect if (theClient > -1) { JsVar *req = jspNewObject(jsiGetParser(), 0, "httpSRq"); JsVar *res = jspNewObject(jsiGetParser(), 0, "httpSRs"); if (res && req) { // out of memory? JsVar *arr = httpGetArray(HTTP_ARRAY_HTTP_SERVER_CONNECTIONS, true); if (arr) { jsvArrayPush(arr, req); jsvUnLock(arr); } jsvObjectSetChild(req, HTTP_NAME_RESPONSE_VAR, res); jsvObjectSetChild(req, HTTP_NAME_SERVER_VAR, server); jsvUnLock(jsvObjectSetChild(req, HTTP_NAME_SOCKET, jsvNewFromInteger(theClient+1))); // on response jsvUnLock(jsvObjectSetChild(res, HTTP_NAME_CODE, jsvNewFromInteger(200))); jsvUnLock(jsvObjectSetChild(res, HTTP_NAME_HEADERS, jsvNewWithFlags(JSV_OBJECT))); } jsvUnLock(req); jsvUnLock(res); //add(new CNetworkConnect(theClient, this)); // add to service queue } } jsvUnLock(server); jsvArrayIteratorNext(&it); } jsvArrayIteratorFree(&it); jsvUnLock(arr); } httpServerConnectionsIdle(); httpClientConnectionsIdle(); }
/*JSON{ "type":"function", "name" : "eval", "description" : "Evaluate a string containing JavaScript code", "generate" : "jswrap_eval", "params" : [ [ "code", "JsVar", ""] ], "return" : ["JsVar", "The result of evaluating the string"] }*/ JsVar *jswrap_eval(JsVar *v) { if (!v) return 0; JsVar *s = jsvAsString(v, false); // get as a string JsVar *result = jspEvaluateVar(jsiGetParser(), s, 0); jsvUnLock(s); return result; }
JsVar *httpClientRequestNew(JsVar *options, JsVar *callback) { JsVar *arr = httpGetArray(HTTP_ARRAY_HTTP_CLIENT_CONNECTIONS,true); if (!arr) return 0; JsVar *req = jspNewObject(jsiGetParser(), 0, "httpCRq"); JsVar *res = jspNewObject(jsiGetParser(), 0, "httpCRs"); if (res && req) { // out of memory? jsvUnLock(jsvAddNamedChild(req, callback, HTTP_NAME_ON_CONNECT)); jsvArrayPush(arr, req); jsvObjectSetChild(req, HTTP_NAME_RESPONSE_VAR, res); jsvObjectSetChild(req, HTTP_NAME_OPTIONS_VAR, options); } jsvUnLock(res); jsvUnLock(arr); return req; }
/*JSON{ "type":"function", "name" : "trace", "ifndef" : "SAVE_ON_FLASH", "description" : "Output debugging information", "generate" : "jswrap_interface_trace", "params" : [ [ "root", "JsVarName", "The symbol to output (optional). If nothing is specified, everything will be output"] ] }*/ void jswrap_interface_trace(JsVar *root) { if (jsvIsUndefined(root)) { jsvTrace(jsvGetRef(jsiGetParser()->root), 0); } else { jsvTrace(jsvGetRef(root), 0); } }
JsVar *jswrap_interface_memory() { jsvGarbageCollect(); JsVar *obj = jsvNewWithFlags(JSV_OBJECT); if (obj) { unsigned int history = 0; JsVar *historyVar = jsvObjectGetChild(jsiGetParser()->root, JSI_HISTORY_NAME, 0); if (historyVar) { history = (unsigned int)jsvCountJsVarsUsed(historyVar); // vars used to store history jsvUnLock(historyVar); } unsigned int usage = jsvGetMemoryUsage() - history; unsigned int total = jsvGetMemoryTotal(); JsVar *v; v = jsvNewFromInteger(total-usage); jsvUnLock(jsvAddNamedChild(obj, v, "free")); jsvUnLock(v); v = jsvNewFromInteger(usage); jsvUnLock(jsvAddNamedChild(obj, v, "usage")); jsvUnLock(v); v = jsvNewFromInteger(total); jsvUnLock(jsvAddNamedChild(obj, v, "total")); jsvUnLock(v); v = jsvNewFromInteger(history); jsvUnLock(jsvAddNamedChild(obj, v, "history")); jsvUnLock(v); #ifdef ARM v = jsvNewFromInteger((JsVarInt)(unsigned int)&_end); jsvUnLock(jsvAddNamedChild(obj, v, "stackEndAddress")); jsvUnLock(v); #endif } return obj; }
/*JSON{ "type":"function", "name" : "require", "description" : "Load the given module, and return the exported functions", "generate" : "jswrap_require", "params" : [ [ "moduleName", "JsVar", "A String containing the name of the given module"] ], "return" : ["JsVar", "The result of evaluating the string"] }*/ JsVar *jswrap_require(JsVar *moduleName) { if (!jsvIsString(moduleName)) { jsWarn("Expecting a module name as a string, but got %t", moduleName); return 0; } // Search to see if we have already loaded this module JsVar *moduleList = jswrap_modules_getModuleList(); if (!moduleList) return 0; // out of memory JsVar *moduleExportName = jsvFindChildFromVar(moduleList, moduleName, true); jsvUnLock(moduleList); if (!moduleExportName) return 0; // out of memory JsVar *moduleExport = jsvSkipName(moduleExportName); if (moduleExport) { // Found the module! jsvUnLock(moduleExportName); return moduleExport; } // Now check if it is built-in char moduleNameBuf[32]; jsvGetString(moduleName, moduleNameBuf, sizeof(moduleNameBuf)); if (jswIsBuiltInLibrary(moduleNameBuf)) { // create a 'fake' module that Espruino can use to map its built-in functions against moduleExport = jspNewBuiltin(moduleNameBuf); } else { // Now try and load it JsVar *fileContents = 0; //if (jsvIsStringEqual(moduleName,"http")) {} //if (jsvIsStringEqual(moduleName,"fs")) {} #ifdef USE_FILESYSTEM JsVar *modulePath = jsvNewFromString( #ifdef LINUX "node_modules/" #else "NODE_M~1/" #endif ); if (!modulePath) { jsvUnLock(moduleExportName); return 0; } // out of memory jsvAppendStringVarComplete(modulePath, moduleName); jsvAppendString(modulePath,".js"); fileContents = wrap_fat_readFile(modulePath); jsvUnLock(modulePath); #endif if (!fileContents || jsvIsStringEqual(fileContents,"")) { jsvUnLock(moduleExportName); jsvUnLock(fileContents); jsWarn("Module not found"); return 0; } moduleExport = jspEvaluateModule(jsiGetParser(), fileContents); jsvUnLock(fileContents); } assert(moduleExport); jsvSetValueOfName(moduleExportName, moduleExport); // save in cache jsvUnLock(moduleExportName); return moduleExport; }
static void cc3000_state_change(const char *data) { JsVar *wlanObj = jsvObjectGetChild(jsiGetParser()->root, CC3000_OBJ_NAME, 0); JsVar *dataVar = jsvNewFromString(data); if (wlanObj) jsiQueueObjectCallbacks(wlanObj, CC3000_ON_STATE_CHANGE, dataVar, 0); jsvUnLock(dataVar); jsvUnLock(wlanObj);
bool run_test(const char *filename) { printf("----------------------------------\r\n"); printf("----------------------------- TEST %s \r\n", filename); char *buffer = (char *)read_file(filename); if (!buffer) return (false); jshInit(); jsiInit(false /* do not autoload!!! */); jspAddNativeFunction(jsiGetParser(), "function quit()", nativeQuit); jspAddNativeFunction(jsiGetParser(), "function interrupt()", nativeInterrupt); jsvUnLock(jspEvaluate(jsiGetParser(), buffer )); isRunning = true; while (isRunning && jsiHasTimers()) jsiLoop(); JsVar *result = jsvObjectGetChild(jsiGetParser()->root, "result", 0/*no create*/); bool pass = jsvGetBool(result); jsvUnLock(result); if (pass) printf("----------------------------- PASS %s\r\n", filename); else { printf("----------------------------------\r\n"); printf("----------------------------- FAIL %s <-------\r\n", filename); jsvTrace(jsvGetRef(jsiGetParser()->root), 0); printf("----------------------------- FAIL %s <-------\r\n", filename); printf("----------------------------------\r\n"); } printf("BEFORE: %d Memory Records Used\r\n", jsvGetMemoryUsage()); // jsvTrace(jsiGetParser()->root, 0); jsiKill(); printf("AFTER: %d Memory Records Used\r\n", jsvGetMemoryUsage()); jsvGarbageCollect(); printf("AFTER GC: %d Memory Records Used (should be 0!)\r\n", jsvGetMemoryUsage()); jsvShowAllocated(); jshKill(); //jsvDottyOutput(); printf("\r\n"); free(buffer); return pass; }
static JsVar *httpGetArray(const char *name, bool create) { JsVar *arrayName = jsvFindChildFromString(jsiGetParser()->root, name, create); JsVar *arr = jsvSkipName(arrayName); if (!arr && create) { arr = jsvNewWithFlags(JSV_ARRAY); jsvSetValueOfName(arrayName, arr); } jsvUnLock(arrayName); return arr; }
static JsVar *jswrap_modules_getModuleList() { JsVar *moduleListName = jsvFindChildFromString(jsiGetParser()->root, JSPARSE_MODULE_CACHE_NAME, true); if (!moduleListName) return 0; // out of memory JsVar *moduleList = jsvSkipName(moduleListName); if (!moduleList) { moduleList = jsvNewWithFlags(JSV_OBJECT); if (!moduleList) { jsvUnLock(moduleListName); return 0; } // out of memory jsvSetValueOfName(moduleListName, moduleList); // no need to unlock } jsvUnLock(moduleListName); return moduleList; }
void lcdSetPixel_JS(JsGraphics *gfx, short x, short y, unsigned int col) { // look up setPixel and execute it! // JsVar *lcdProto = jsvSkipNameAndUnLock(jsvFindChildFromString(gfx->graphicsVar, JSPARSE_PROTOTYPE_VAR, false)); // if (lcdProto) { JsVar *setPixel = jsvSkipNameAndUnLock(jsvFindChildFromString(gfx->graphicsVar/*lcdProto*/, "setPixel", false)); if (setPixel) { JsVar *args[3]; args[0] = jsvNewFromInteger(x); args[1] = jsvNewFromInteger(y); args[2] = jsvNewFromInteger(col); jspExecuteFunction(jsiGetParser(), setPixel, gfx->graphicsVar, 3, args); jsvUnLock(args[0]); jsvUnLock(args[1]); jsvUnLock(args[2]); jsvUnLock(setPixel); } // jsvUnLock(lcdProto); // } }
void cc3000_initialise(JsVar *wlanObj) { jsvObjectSetChild(jsiGetParser()->root, CC3000_OBJ_NAME, wlanObj); cc3000_spi_open(); wlan_init(cc3000_usynch_callback, sendNoPatch/*sendWLFWPatch*/, sendNoPatch/*sendDriverPatch*/, sendNoPatch/*sendBootLoaderPatch*/, cc3000_read_irq_pin, cc3000_irq_enable, cc3000_irq_disable, cc3000_write_en_pin); wlan_start(0/* No patches */); // Mask out all non-required events from CC3000 wlan_set_event_mask( HCI_EVNT_WLAN_KEEPALIVE | HCI_EVNT_WLAN_UNSOL_INIT); // TODO: check return value !=0 wlan_ioctl_set_connection_policy(0, 0, 0); // don't auto-connect wlan_ioctl_del_profile(255); // delete stored eeprom data
/*JSON{ "type":"staticmethod", "class" : "Modules", "name" : "addCached", "description" : "Add the given module to the cache", "generate" : "jswrap_modules_addCached", "params" : [ [ "id", "JsVar", "The module name to add" ], [ "sourcecode", "JsVar", "The module's sourcecode" ] ] }*/ void jswrap_modules_addCached(JsVar *id, JsVar *sourceCode) { if (!jsvIsString(id) || !jsvIsString(sourceCode)) { jsError("Both arguments to addCached must be strings"); return; } JsVar *moduleList = jswrap_modules_getModuleList(); if (!moduleList) return; // out of memory JsVar *moduleExport = jspEvaluateModule(jsiGetParser(), sourceCode); if (!moduleExport) { jsWarn("Unable to load module"); } else { JsVar *moduleName = jsvFindChildFromVar(moduleList, id, true); if (moduleName) jsvSetValueOfName(moduleName, moduleExport); jsvUnLock(moduleExport); } jsvUnLock(moduleList); }
/*JSON{ "type":"function", "name" : "edit", "description" : ["Fill the console with the contents of the given function, so you can edit it.", "NOTE: This is a convenience function - it will not edit 'inner functions'. For that, you must edit the 'outer function' and re-execute it."], "generate" : "jswrap_interface_edit", "params" : [ [ "funcName", "JsVarName", "The name of the function to edit (either a string or just the unquoted name)"] ] }*/ void jswrap_interface_edit(JsVar *funcName) { if (jsvIsString(funcName)) { JsVar *func = 0; if (jsvIsName(funcName)) func = jsvSkipName(funcName); else func = jsvSkipNameAndUnLock(jsvFindChildFromVar(jsiGetParser()->root, funcName, 0)); if (jsvIsFunction(func)) { JsVar *scopeVar = jsvFindChildFromString(func, JSPARSE_FUNCTION_SCOPE_NAME, false); JsVarRef scope = jsvGetRef(scopeVar); jsvUnLock(scopeVar); JsVar *newLine = jsvNewFromEmptyString(); if (newLine) { // could be out of memory jsvAppendStringVarComplete(newLine, funcName); if (scope) { // If we have a scope, it's an internal function so we will need to write different code jsvAppendString(newLine, ".replaceWith("); } else { jsvAppendString(newLine, " = "); } JsVar *funcData = jsvAsString(func, false); if (funcData) jsvAppendStringVarComplete(newLine, funcData); jsvUnLock(funcData); if (scope) { jsvAppendString(newLine, ");"); } else { jsvAppendString(newLine, ";"); } jsiReplaceInputLine(newLine); jsvUnLock(newLine); } } else { jsError("Edit should be called with the name of a function"); } jsvUnLock(func); } else { jsError("Edit should be called with edit(funcName) or edit('funcName')"); } }
JsVar *httpServerNew(JsVar *callback) { SOCKET sckt = socket(AF_INET, // Go over TCP/IP SOCK_STREAM, // This is a stream-oriented socket IPPROTO_TCP); // Use TCP rather than UDP if (sckt == INVALID_SOCKET) { httpError("socket creation failed"); return 0; } JsVar *arr = httpGetArray(HTTP_ARRAY_HTTP_SERVERS, true); if (!arr) return 0; // out of memory JsVar *server = jspNewObject(jsiGetParser(),0,"httpSrv"); if (!server) { jsvUnLock(arr); return 0; // out of memory } jsvObjectSetChild(server, HTTP_NAME_ON_CONNECT, callback); // no unlock needed jsvUnLock(jsvObjectSetChild(server, HTTP_NAME_SOCKET, jsvNewFromInteger(sckt+1))); #ifndef USE_CC3000 int optval = 1; if (setsockopt(sckt,SOL_SOCKET,SO_REUSEADDR,(const char *)&optval,sizeof(optval)) < 0) #else int optval = SOCK_ON; if (setsockopt(sckt,SOL_SOCKET,SOCKOPT_ACCEPT_NONBLOCK,(const char *)&optval,sizeof(optval)) < 0) #endif jsWarn("setsockopt failed\n"); // add to list of servers jsvArrayPush(arr, server); jsvUnLock(arr); return server; }
int espruino(int argc, char **argv) { int i; for (i=1;i<argc;i++) { if (argv[i][0]=='-') { // option char *a = argv[i]; if (!strcmp(a,"-h") || !strcmp(a,"--help")) { show_help(); return (1); } else if (!strcmp(a,"-e") || !strcmp(a,"--eval")) { if (i+1>=argc) die("Expecting an extra argument\n"); jshInit(); jsiInit(true); jspAddNativeFunction(jsiGetParser(), "function quit()", nativeQuit); jsvUnLock(jspEvaluate(jsiGetParser(), argv[i+1])); isRunning = true; //while (isRunning && jsiHasTimers()) jsiLoop(); jsiKill(); jshKill(); return (0); } else if (!strcmp(a,"--test")) { if (i+1>=argc) die("Expecting an extra argument\n"); bool ok = run_test(argv[i+1]); return (ok ? 0 : 1); } else if (!strcmp(a,"--test-all")) { bool ok = run_all_tests(); return (ok ? 0 : 1); } else if (!strcmp(a,"--test-mem-all")) { bool ok = run_memory_tests(0); return (ok ? 0 : 1); } else if (!strcmp(a,"--test-mem")) { if (i+1>=argc) die("Expecting an extra argument\n"); bool ok = run_memory_test(argv[i+1], 0); return (ok ? 0 : 1); } else if (!strcmp(a,"--test-mem-n")) { if (i+2>=argc) die("Expecting an extra 2 arguments\n"); bool ok = run_memory_test(argv[i+1], atoi(argv[i+2])); return (ok ? 0 : 1); } else { printf("Unknown Argument %s\n", a); show_help(); return -1; } } } if (argc==1) { printf("Interactive mode.\n"); } else if (argc==2) { // single file - just run it char *buffer = (char *)read_file(argv[1]); if (!buffer) return (1); // check for '#' as the first char, and if so, skip the first line char *cmd = buffer; if (cmd[0]=='#') { while (cmd[0] && cmd[0]!='\n') cmd++; if (cmd[0]=='\n') cmd++; } jshInit(); jsiInit(false /* do not autoload!!! */); jspAddNativeFunction(jsiGetParser(), "function quit()", nativeQuit); jsvUnLock(jspEvaluate(jsiGetParser(), cmd )); free(buffer); //isRunning = true; //while (isRunning && jsiHasTimers()) jsiLoop(); jsiKill(); jshKill(); return -1; } else { printf("Unknown arguments!\n"); show_help(); return -1; } printf("Size of JsVar is now %d bytes\n", (int)sizeof(JsVar)); printf("Size of JsVarRef is now %d bytes\n", (int)sizeof(JsVarRef)); jshInit(); jsiInit(true); jspAddNativeFunction(jsiGetParser(), "function quit()", nativeQuit); jspAddNativeFunction(jsiGetParser(), "function interrupt()", nativeInterrupt); while (isRunning) { jsiLoop(); } jsiConsolePrint("\n"); jsiKill(); jsvShowAllocated(); jshKill(); return 0; }
int main(int argc, char **argv) { int i; for (i=1;i<argc;i++) { if (argv[i][0]=='-') { // option char *a = argv[i]; if (!strcmp(a,"-h") || !strcmp(a,"--help")) { show_help(); exit(1); } else if (!strcmp(a,"-e") || !strcmp(a,"--eval")) { if (i+1>=argc) die("Expecting an extra argument"); jshInit(); jsiInit(true); jspAddNativeFunction(jsiGetParser(), "function quit()", nativeQuit); jsvUnLock(jspEvaluate(jsiGetParser(), argv[i+1])); isRunning = true; while (isRunning && jsiHasTimers()) jsiLoop(); jsiKill(); jshKill(); exit(0); } else if (!strcmp(a,"--test-all")) { bool ok = run_all_tests(); exit(ok ? 0 : 1); } else if (!strcmp(a,"--test-mem-all")) { bool ok = run_memory_tests(0); exit(ok ? 0 : 1); } else if (!strcmp(a,"--test-mem")) { if (i+1>=argc) die("Expecting an extra argument"); bool ok = run_memory_test(argv[i+1], 0); exit(ok ? 0 : 1); } else if (!strcmp(a,"--test-mem-n")) { if (i+2>=argc) die("Expecting an extra 2 arguments"); bool ok = run_memory_test(argv[i+1], atoi(argv[i+2])); exit(ok ? 0 : 1); } else { printf("Unknown Argument %s\n", a); show_help(); exit(1); } } } if (argc==1) { printf("Interactive mode.\n"); } else if (argc==2) { char *buffer = read_file(argv[1]); jshInit(); jsiInit(false /* do not autoload!!! */); jspAddNativeFunction(jsiGetParser(), "function quit()", nativeQuit); jsvUnLock(jspEvaluate(jsiGetParser(), buffer )); free(buffer); isRunning = true; while (isRunning && jsiHasTimers()) jsiLoop(); jsiKill(); jshKill(); exit(0); } else { printf("Unknown arguments!\n"); show_help(); exit(1); } printf("Size of JsVar is now %d bytes\n", (int)sizeof(JsVar)); printf("Size of JsVarRef is now %d bytes\n", (int)sizeof(JsVarRef)); struct sigaction sa; sa.sa_handler = sig_handler; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); if (sigaction(SIGINT, &sa, NULL) == -1) printf("Adding SIGINT hook failed\n"); else printf("Added SIGINT hook\n"); if (sigaction(SIGHUP, &sa, NULL) == -1) printf("Adding SIGHUP hook failed\n"); else printf("Added SIGHUP hook\n"); if (sigaction(SIGTERM, &sa, NULL) == -1) printf("Adding SIGTERM hook failed\n"); else printf("Added SIGTERM hook\n"); jshInit(); jsiInit(true); jspAddNativeFunction(jsiGetParser(), "function quit()", nativeQuit); jspAddNativeFunction(jsiGetParser(), "function interrupt()", nativeInterrupt); while (isRunning) { jsiLoop(); } jsiConsolePrint("\n"); jsiKill(); jsvShowAllocated(); jshKill(); return 0; }