static int ws_execute(struct http_client *c, const char *frame, size_t frame_len) { struct cmd*(*fun_extract)(struct http_client *, const char *, size_t) = NULL; formatting_fun fun_reply = NULL; if((c->path_sz == 1 && strncmp(c->path, "/", 1) == 0) || strncmp(c->path, "/.json", 6) == 0) { fun_extract = json_ws_extract; fun_reply = json_reply; } else if(strncmp(c->path, "/.raw", 5) == 0) { fun_extract = raw_ws_extract; fun_reply = raw_reply; } if(fun_extract) { /* Parse websocket frame into a cmd object. */ struct cmd *cmd = fun_extract(c, frame, frame_len); if(cmd) { /* copy client info into cmd. */ cmd_setup(cmd, c); cmd->is_websocket = 1; if (c->pub_sub != NULL) { /* This client already has its own connection * to Redis due to a subscription; use it from * now on. */ cmd->ac = c->pub_sub->ac; } else if (cmd_is_subscribe(cmd)) { /* New subscribe command; make new Redis context * for this client */ cmd->ac = pool_connect(c->w->pool, cmd->database, 0); c->pub_sub = cmd; cmd->pub_sub_client = c; } else { /* get Redis connection from pool */ cmd->ac = (redisAsyncContext*)pool_get_context(c->w->pool); } /* send it off */ cmd_send(cmd, fun_reply); return 0; } } return -1; }
static int ws_execute(struct http_client *c, const char *frame, size_t frame_len) { struct cmd*(*fun_extract)(struct http_client *, const char *, size_t) = NULL; formatting_fun fun_reply = NULL; if((c->path_sz == 1 && strncmp(c->path, "/", 1) == 0) || strncmp(c->path, "/.json", 6) == 0) { fun_extract = json_ws_extract; fun_reply = json_reply; } else if(strncmp(c->path, "/.raw", 5) == 0) { fun_extract = raw_ws_extract; fun_reply = raw_reply; } if(fun_extract) { /* Parse websocket frame into a cmd object. */ struct cmd *cmd = fun_extract(c, frame, frame_len); if(cmd) { /* copy client info into cmd. */ cmd_setup(cmd, c); cmd->is_websocket = 1; /* get Redis connection from pool */ cmd->ac = (redisAsyncContext*)pool_get_context(c->w->pool); /* send it off */ cmd_send(cmd, fun_reply); return 0; } } return -1; }
cmd_response_t cmd_run(struct worker *w, struct http_client *client, const char *uri, size_t uri_len, const char *body, size_t body_len) { char *qmark = memchr(uri, '?', uri_len); char *slash; const char *p, *cmd_name = uri; int cmd_len; int param_count = 0, cur_param = 1; struct cmd *cmd; formatting_fun f_format; /* count arguments */ if(qmark) { uri_len = qmark - uri; } for(p = uri; p && p < uri + uri_len; param_count++) { p = memchr(p+1, '/', uri_len - (p+1-uri)); } if(body && body_len) { /* PUT request */ param_count++; } if(param_count == 0) { return CMD_PARAM_ERROR; } cmd = cmd_new(param_count); cmd->fd = client->fd; cmd->database = w->s->cfg->database; /* get output formatting function */ uri_len = cmd_select_format(client, cmd, uri, uri_len, &f_format); /* add HTTP info */ cmd_setup(cmd, client); /* check if we only have one command or more. */ slash = memchr(uri, '/', uri_len); if(slash) { /* detect DB number by checking if first arg is only numbers */ int has_db = 1; int db_num = 0; for(p = uri; p < slash; ++p) { if(*p < '0' || *p > '9') { has_db = 0; break; } db_num = db_num * 10 + (*p - '0'); } /* shift to next arg if a db was set up */ if(has_db) { char *next; cmd->database = db_num; cmd->count--; /* overcounted earlier */ cmd_name = slash + 1; if((next = memchr(cmd_name, '/', uri_len - (slash - uri)))) { cmd_len = next - cmd_name; } else { cmd_len = uri_len - (slash - uri + 1); } } else { cmd_len = slash - uri; } } else { cmd_len = uri_len; } /* there is always a first parameter, it's the command name */ cmd->argv[0] = malloc(cmd_len); memcpy(cmd->argv[0], cmd_name, cmd_len); cmd->argv_len[0] = cmd_len; /* check that the client is able to run this command */ if(!acl_allow_command(cmd, w->s->cfg, client)) { cmd_free(cmd); return CMD_ACL_FAIL; } if(cmd_is_subscribe(cmd)) { /* create a new connection to Redis */ cmd->ac = (redisAsyncContext*)pool_connect(w->pool, cmd->database, 0); /* register with the client, used upon disconnection */ client->pub_sub = cmd; cmd->pub_sub_client = client; } else if(cmd->database != w->s->cfg->database) { /* create a new connection to Redis for custom DBs */ cmd->ac = (redisAsyncContext*)pool_connect(w->pool, cmd->database, 0); } else { /* get a connection from the pool */ cmd->ac = (redisAsyncContext*)pool_get_context(w->pool); } /* no args (e.g. INFO command) */ if(!slash) { if(!cmd->ac) { cmd_free(cmd); return CMD_REDIS_UNAVAIL; } redisAsyncCommandArgv(cmd->ac, f_format, cmd, 1, (const char **)cmd->argv, cmd->argv_len); return CMD_SENT; } p = cmd_name + cmd_len + 1; while(p < uri + uri_len) { const char *arg = p; int arg_len; char *next = memchr(arg, '/', uri_len - (arg-uri)); if(!next || next > uri + uri_len) { /* last argument */ p = uri + uri_len; arg_len = p - arg; } else { /* found a slash */ arg_len = next - arg; p = next + 1; } /* record argument */ cmd->argv[cur_param] = decode_uri(arg, arg_len, &cmd->argv_len[cur_param], 1); cur_param++; } if(body && body_len) { /* PUT request */ cmd->argv[cur_param] = malloc(body_len); memcpy(cmd->argv[cur_param], body, body_len); cmd->argv_len[cur_param] = body_len; } /* send it off! */ if(cmd->ac) { cmd_send(cmd, f_format); return CMD_SENT; } /* failed to find a suitable connection to Redis. */ cmd_free(cmd); client->pub_sub = NULL; return CMD_REDIS_UNAVAIL; }
/* * Initialize mged, configure the path, set up the tcl interpreter. */ void mged_setup(Tcl_Interp **interpreter) { int try_auto_path = 0; int init_tcl = 1; int init_itcl = 1; struct bu_vls str = BU_VLS_INIT_ZERO; const char *name = bu_argv0_full_path(); /* locate our run-time binary (must be called before Tcl_CreateInterp()) */ if (name) { Tcl_FindExecutable(name); } else { Tcl_FindExecutable("mged"); } if (!interpreter ) { bu_log("mged_setup Error - interpreter is NULL!\n"); return; } if (*interpreter != NULL) Tcl_DeleteInterp(*interpreter); /* Create the interpreter */ *interpreter = Tcl_CreateInterp(); /* a two-pass init loop. the first pass just tries default init * routines while the second calls tclcad_auto_path() to help it * find other, potentially uninstalled, resources. */ while (1) { /* not called first time through, give Tcl_Init() a chance */ if (try_auto_path) { /* Locate the BRL-CAD-specific Tcl scripts, set the auto_path */ tclcad_auto_path(*interpreter); } /* Initialize Tcl */ Tcl_ResetResult(*interpreter); if (init_tcl && Tcl_Init(*interpreter) == TCL_ERROR) { if (!try_auto_path) { try_auto_path = 1; continue; } bu_log("Tcl_Init ERROR:\n%s\n", Tcl_GetStringResult(*interpreter)); break; } init_tcl = 0; /* Initialize [incr Tcl] */ Tcl_ResetResult(*interpreter); /* NOTE: Calling "package require Itcl" here is apparently * insufficient without other changes elsewhere. The * Combination Editor in mged fails with an iwidgets class * already loaded error if we don't perform Itcl_Init() here. */ if (init_itcl && Itcl_Init(*interpreter) == TCL_ERROR) { if (!try_auto_path) { Tcl_Namespace *nsp; try_auto_path = 1; /* Itcl_Init() leaves initialization in a bad state * and can cause retry failures. cleanup manually. */ Tcl_DeleteCommand(*interpreter, "::itcl::class"); nsp = Tcl_FindNamespace(*interpreter, "::itcl", NULL, 0); if (nsp) Tcl_DeleteNamespace(nsp); continue; } bu_log("Itcl_Init ERROR:\n%s\n", Tcl_GetStringResult(*interpreter)); break; } init_itcl = 0; /* don't actually want to loop forever */ break; } /* end iteration over Init() routines that need auto_path */ Tcl_ResetResult(*interpreter); /* if we haven't loaded by now, load auto_path so we find our tclscripts */ if (!try_auto_path) { /* Locate the BRL-CAD-specific Tcl scripts */ tclcad_auto_path(*interpreter); } /*XXX FIXME: Should not be importing Itcl into the global namespace */ /* Import [incr Tcl] commands into the global namespace. */ if (Tcl_Import(*interpreter, Tcl_GetGlobalNamespace(*interpreter), "::itcl::*", /* allowOverwrite */ 1) != TCL_OK) { bu_log("Tcl_Import ERROR: %s\n", Tcl_GetStringResult(*interpreter)); Tcl_ResetResult(*interpreter); } /* Initialize libbu */ if (Bu_Init(*interpreter) == TCL_ERROR) { bu_log("Bu_Init ERROR:\n%s\n", Tcl_GetStringResult(*interpreter)); Tcl_ResetResult(*interpreter); } /* Initialize libbn */ if (Bn_Init(*interpreter) == TCL_ERROR) { bu_log("Bn_Init ERROR:\n%s\n", Tcl_GetStringResult(*interpreter)); Tcl_ResetResult(*interpreter); } /* Initialize librt */ if (Rt_Init(*interpreter) == TCL_ERROR) { bu_log("Rt_Init ERROR:\n%s\n", Tcl_GetStringResult(*interpreter)); Tcl_ResetResult(*interpreter); } /* Initialize libged */ if (Go_Init(*interpreter) == TCL_ERROR) { bu_log("Ged_Init ERROR:\n%s\n", Tcl_GetStringResult(*interpreter)); Tcl_ResetResult(*interpreter); } BU_ALLOC(view_state->vs_gvp, struct ged_view); ged_view_init(view_state->vs_gvp); view_state->vs_gvp->gv_callback = mged_view_callback; view_state->vs_gvp->gv_clientData = (void *)view_state; MAT_DELTAS_GET_NEG(view_state->vs_orig_pos, view_state->vs_gvp->gv_center); if (gedp) { /* release any allocated memory */ ged_free(gedp); } else { BU_ALLOC(gedp, struct ged); } GED_INIT(gedp, NULL); /* register commands */ cmd_setup(); history_setup(); mged_global_variable_setup(*interpreter); mged_variable_setup(*interpreter); /* Tcl needs to write nulls onto subscripted variable names */ bu_vls_printf(&str, "%s(state)", MGED_DISPLAY_VAR); Tcl_SetVar(*interpreter, bu_vls_addr(&str), state_str[STATE], TCL_GLOBAL_ONLY); /* Set defaults for view status variables */ bu_vls_trunc(&str, 0); bu_vls_printf(&str, "set mged_display(.topid_0.ur,ang) {ang=(0.00 0.00 0.00)};\ set mged_display(.topid_0.ur,aet) {az=35.00 el=25.00 tw=0.00};\ set mged_display(.topid_0.ur,size) sz=1000.000;\ set mged_display(.topid_0.ur,center) {cent=(0.000 0.000 0.000)};\ set mged_display(units) mm"); Tcl_Eval(*interpreter, bu_vls_addr(&str)); Tcl_ResetResult(*interpreter); bu_vls_free(&str); }
void LGNetwork::set_mode(network_mode_t newMode) { cmd_enter(); cmd_reset(); cmd_setup(); cmd_set_channel(newMode); if(newMode == LGNETWORK_OPERATE) { #ifdef USE_NETWORK_SERVER cmd_set_short_address(-1); cmd_set_target_short_address(-1); cmd_set_coordinator(); #elif USE_NETWORK_CLIENT uint16_t short_addr = LGDB::read_address(); cmd_set_short_address(short_addr); // It will either be something we want, or -1 cmd_set_coordinator(); #endif } else { // LGNETWORK_DISCOVER #ifdef USE_NETWORK_SERVER cmd_set_short_address(-1); cmd_set_target_short_address(-1); cmd_set_coordinator(); // Get my uuid // Read the UUID (serial address) char ascii_id[17]; for(int i=0; i < sizeof(ascii_id); i++) ascii_id[i] = '0'; ascii_id[16] = 0; LGSerial::print_pgm( PSTR("ATSH") ); // Starting with the upper bits uint8_t high_chars_to_write = LGSerial::get(response_buf, '\r', 16) - 1; memcpy(ascii_id + (8 - high_chars_to_write), response_buf, high_chars_to_write); // Now the lower bits LGSerial::print_pgm( PSTR("ATSL") ); uint8_t low_chars_to_write = LGSerial::get(response_buf, '\r', 16) - 1; memcpy(ascii_id + 8 + (8 - low_chars_to_write), response_buf, low_chars_to_write); uint8_t *p = (uint8_t*)&(LGNetwork::myUUID); // Ptr to current byte for(int i=0; i < 16; i+=2) { // Convert to bin *(p++) = asciis_to_byte(ascii_id + i); } #elif USE_NETWORK_CLIENT cmd_set_short_address(-1); cmd_set_target_short_address(-1); cmd_set_coordinator(); #ifdef CLIENT_SENSOR LGSerial::print_pgm( PSTR("ATNIs") ); cmd_wait_for_ok(); #elif CLIENT_ACTUATOR LGSerial::print_pgm( PSTR("ATNIa") ); cmd_wait_for_ok(); #endif #endif } cmd_exit(); currentMode = newMode; }