static struct server_data * server_ref(int32_t opt_port) { struct server_data *idata, *sdata = NULL; uint16_t i, port; port = validate_port(opt_port); if (!servers) { servers = calloc(1, sizeof(struct sol_ptr_vector)); SOL_NULL_CHECK(servers, NULL); sol_ptr_vector_init(servers); } SOL_PTR_VECTOR_FOREACH_IDX (servers, idata, i) { if (idata->port == port) { sdata = idata; break; } } if (!sdata) { int r; sdata = calloc(1, sizeof(struct server_data)); SOL_NULL_CHECK_GOTO(sdata, err_sdata); r = sol_ptr_vector_append(servers, sdata); SOL_INT_CHECK_GOTO(r, < 0, err_vec); sdata->server = sol_http_server_new(port); SOL_NULL_CHECK_GOTO(sdata->server, err_server); sdata->port = port; }
static bool thingspeak_channel_update_send(void *data) { struct thingspeak_channel_update_data *mdata = data; struct sol_http_param params; struct sol_http_client_connection *connection; char field_name[] = "fieldX"; size_t i; int r; sol_http_param_init(¶ms); if (!sol_http_param_add(¶ms, SOL_HTTP_REQUEST_PARAM_POST_FIELD("api_key", mdata->api_key))) { SOL_WRN("Could not add API key"); goto out; } if (mdata->status) { if (!sol_http_param_add(¶ms, SOL_HTTP_REQUEST_PARAM_POST_FIELD("status", mdata->status))) { SOL_WRN("Could not add status field to POST parameters"); goto out; } } for (i = 0; i < ARRAY_SIZE(mdata->fields); i++) { if (!mdata->fields[i]) continue; field_name[sizeof("field") - 1] = i + '1'; if (!sol_http_param_add(¶ms, SOL_HTTP_REQUEST_PARAM_POST_FIELD(strdupa(field_name), mdata->fields[i]))) { SOL_WRN("Could not add status field to POST %s parameters", field_name); goto out; } } connection = sol_http_client_request(SOL_HTTP_METHOD_POST, mdata->endpoint, ¶ms, thingspeak_channel_update_finished, mdata); if (!connection) { SOL_WRN("Could not create HTTP request"); goto out; } r = sol_ptr_vector_append(&mdata->pending_conns, connection); if (r < 0) { SOL_WRN("Failed to keep pending connection."); sol_http_client_connection_cancel(connection); } out: sol_http_param_free(¶ms); mdata->timeout = NULL; return false; }
SOL_API char * sol_arena_strndup(struct sol_arena *arena, const char *str, size_t n) { char *result; int r; SOL_NULL_CHECK(arena, NULL); SOL_NULL_CHECK(str, NULL); SOL_INT_CHECK(n, <= 0, NULL); result = strndup(str, n); SOL_NULL_CHECK(result, NULL); r = sol_ptr_vector_append(&arena->str_vector, result); if (r < 0) { free(result); return NULL; } return result; }
static bool thingspeak_execute_poll(void *data) { struct thingspeak_execute_data *mdata = data; struct sol_http_param params; struct sol_http_client_connection *connection; int r; sol_http_param_init(¶ms); if (!sol_http_param_add(¶ms, SOL_HTTP_REQUEST_PARAM_POST_FIELD("api_key", mdata->talkback.api_key))) { SOL_WRN("Could not set API key"); mdata->timeout = NULL; sol_http_param_free(¶ms); return false; } connection = sol_http_client_request(SOL_HTTP_METHOD_POST, mdata->talkback.endpoint, ¶ms, thingspeak_execute_poll_finished, mdata); sol_http_param_free(¶ms); if (!connection) { SOL_WRN("Could not create HTTP request"); mdata->timeout = NULL; return false; } r = sol_ptr_vector_append(&mdata->pending_conns, connection); if (r < 0) { SOL_WRN("Failed to keep pending connection."); sol_http_client_connection_cancel(connection); return false; } return true; }
static int read_file(void *data, const char *name, const char **buf, size_t *size) { struct runner *r = data; struct sol_file_reader *fr = NULL; struct sol_str_slice slice; char *path; int err; err = asprintf(&path, "%s/%s", r->dirname, name); if (err < 0) { err = -ENOMEM; goto error; } fr = sol_file_reader_open(path); if (!fr) { err = -errno; SOL_ERR("Couldn't open input file '%s': %s", path, sol_util_strerrora(errno)); goto error; } err = sol_ptr_vector_append(&r->file_readers, fr); if (err < 0) goto error; free(path); slice = sol_file_reader_get_all(fr); *buf = slice.data; *size = slice.len; return 0; error: free(path); if (fr) sol_file_reader_close(fr); return err; }
SOL_API int sol_arena_slice_sprintf(struct sol_arena *arena, struct sol_str_slice *dst, const char *fmt, ...) { va_list ap; char *str; int r; va_start(ap, fmt); r = vasprintf(&str, fmt, ap); va_end(ap); SOL_INT_CHECK(r, < 0, r); dst->data = str; dst->len = r; r = sol_ptr_vector_append(&arena->str_vector, str); if (r < 0) { free(str); return r; } return 0; }
SOL_API int sol_arena_slice_dup_str_n(struct sol_arena *arena, struct sol_str_slice *dst, const char *str, size_t n) { struct sol_str_slice slice; int r; SOL_NULL_CHECK(arena, -EINVAL); SOL_NULL_CHECK(str, -EINVAL); SOL_INT_CHECK(n, <= 0, -EINVAL); slice.data = strndup(str, n); SOL_NULL_CHECK(slice.data, -errno); slice.len = n; r = sol_ptr_vector_append(&arena->str_vector, (char *)slice.data); if (r < 0) { free((char *)slice.data); return r; } *dst = slice; return 0; }
static int thingspeak_add_in_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct thingspeak_add_data *mdata = data; const char *cmd_str; struct sol_http_param params; struct sol_http_client_connection *connection; int error_code = 0; int r; r = sol_flow_packet_get_string(packet, &cmd_str); if (r < 0) { SOL_WRN("Could not get command string from packet"); return -EINVAL; } sol_http_param_init(¶ms); if (!sol_http_param_add(¶ms, SOL_HTTP_REQUEST_PARAM_POST_FIELD("api_key", mdata->talkback.api_key))) { SOL_WRN("Could not add API key"); error_code = -ENOMEM; goto out; } if (!sol_http_param_add(¶ms, SOL_HTTP_REQUEST_PARAM_POST_FIELD("command_string", cmd_str))) { SOL_WRN("Could not add command string"); error_code = -ENOMEM; goto out; } if (mdata->position >= 0) { char position_str[3 * sizeof(int)]; char *pos_str; r = snprintf(position_str, sizeof(position_str), "%d", mdata->position); if (r < 0 || r >= (int)sizeof(position_str)) { SOL_WRN("Could not convert position to string"); error_code = -ENOMEM; goto out; } /* Use pos_str at SOL_HTTP_REQUEST_PARAM_POST_FIELD macro, otherwise the compiler will complain about an "always true" comparison. */ pos_str = position_str; if (!sol_http_param_add(¶ms, SOL_HTTP_REQUEST_PARAM_POST_FIELD("position", pos_str))) { SOL_WRN("Could not add position"); error_code = -ENOMEM; goto out; } } connection = sol_http_client_request(SOL_HTTP_METHOD_POST, mdata->talkback.endpoint, ¶ms, thingspeak_add_request_finished, mdata); if (!connection) { SOL_WRN("Could not create HTTP request"); error_code = -EINVAL; goto out; } r = sol_ptr_vector_append(&mdata->pending_conns, connection); if (r < 0) { SOL_WRN("Failed to keep pending connection."); sol_http_client_connection_cancel(connection); error_code = -ENOMEM; } out: sol_http_param_free(¶ms); return error_code; }
static bool parse_args(int argc, char *argv[]) { int opt, err; const char known_opts[] = "cho:stI:" #ifdef SOL_FLOW_INSPECTOR_ENABLED "D" #endif ; sol_ptr_vector_init(&args.fbp_search_paths); while ((opt = getopt(argc, argv, known_opts)) != -1) { switch (opt) { case 'c': args.check_only = true; break; case 's': args.provide_sim_nodes = true; break; case 'h': usage(argv[0]); exit(EXIT_SUCCESS); break; case 'o': if (args.options_count == MAX_OPTS) { printf("Too many options.\n"); exit(EXIT_FAILURE); } args.options[args.options_count++] = optarg; break; case 't': args.execute_type = true; break; #ifdef SOL_FLOW_INSPECTOR_ENABLED case 'D': inspector_init(); break; #endif case 'I': err = sol_ptr_vector_append(&args.fbp_search_paths, optarg); if (err < 0) { printf("Out of memory\n"); exit(1); } break; default: return false; } } if (optind == argc) return false; args.name = argv[optind]; if (args.execute_type) { args.provide_sim_nodes = true; } sol_args_set(argc - optind, &argv[optind]); return true; }
SOL_API struct sol_lwm2m_bootstrap_server * sol_lwm2m_bootstrap_server_new(uint16_t port, const char **known_clients, uint16_t num_sec_modes, ...) { struct sol_lwm2m_bootstrap_server *server; struct sol_network_link_addr servaddr = { .family = SOL_NETWORK_FAMILY_INET6, .port = port }; int r; struct sol_lwm2m_security_psk **known_psks = NULL, *cli_psk; struct sol_lwm2m_security_rpk *my_rpk = NULL; struct sol_blob **known_pub_keys = NULL, *cli_pub_key; enum sol_lwm2m_security_mode *sec_modes; enum sol_socket_dtls_cipher *cipher_suites; uint16_t i, j; va_list ap; SOL_LOG_INTERNAL_INIT_ONCE; SOL_NULL_CHECK(known_clients, NULL); SOL_INT_CHECK(num_sec_modes, == 0, NULL); va_start(ap, num_sec_modes); cipher_suites = calloc(num_sec_modes, sizeof(enum sol_socket_dtls_cipher)); SOL_NULL_CHECK_GOTO(cipher_suites, err_va_list); sec_modes = calloc(num_sec_modes, sizeof(enum sol_lwm2m_security_mode)); SOL_NULL_CHECK_GOTO(sec_modes, err_cipher_suites); for (i = 0; i < num_sec_modes; i++) { sec_modes[i] = va_arg(ap, enum sol_lwm2m_security_mode); SOL_EXP_CHECK_GOTO(sec_mode_is_repeated(sec_modes[i], sec_modes, i), err_sec_modes); switch (sec_modes[i]) { case SOL_LWM2M_SECURITY_MODE_PRE_SHARED_KEY: known_psks = va_arg(ap, struct sol_lwm2m_security_psk **); SOL_NULL_CHECK_GOTO(known_psks, err_sec_modes); cipher_suites[i] = SOL_SOCKET_DTLS_CIPHER_PSK_AES128_CCM8; break; case SOL_LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY: my_rpk = va_arg(ap, struct sol_lwm2m_security_rpk *); SOL_NULL_CHECK_GOTO(my_rpk, err_sec_modes); known_pub_keys = va_arg(ap, struct sol_blob **); SOL_NULL_CHECK_GOTO(known_pub_keys, err_sec_modes); cipher_suites[i] = SOL_SOCKET_DTLS_CIPHER_ECDHE_ECDSA_AES128_CCM8; break; case SOL_LWM2M_SECURITY_MODE_CERTIFICATE: SOL_WRN("Certificate security mode is not supported yet."); goto err_sec_modes; case SOL_LWM2M_SECURITY_MODE_NO_SEC: SOL_WRN("Bootstrap Server MUST use DTLS."); goto err_sec_modes; default: SOL_WRN("Unknown DTLS Security Mode: %d", sec_modes[i]); goto err_sec_modes; } } server = calloc(1, sizeof(struct sol_lwm2m_bootstrap_server)); SOL_NULL_CHECK_GOTO(server, err_sec_modes); //LWM2M Bootstrap Server MUST always use DTLS for (i = 0; i < num_sec_modes; i++) { if (sec_modes[i] == SOL_LWM2M_SECURITY_MODE_PRE_SHARED_KEY) { sol_vector_init(&server->known_psks, sizeof(sol_lwm2m_security_psk)); for (j = 0; known_psks[j]; j++) { cli_psk = sol_vector_append(&server->known_psks); SOL_NULL_CHECK_GOTO(cli_psk, err_copy_keys); cli_psk->id = sol_blob_ref(known_psks[j]->id); cli_psk->key = sol_blob_ref(known_psks[j]->key); } } else if (sec_modes[i] == SOL_LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY) { sol_ptr_vector_init(&server->known_pub_keys); for (j = 0; known_pub_keys[j]; j++) { r = sol_ptr_vector_append(&server->known_pub_keys, sol_blob_ref(known_pub_keys[j])); SOL_INT_CHECK_GOTO(r, < 0, err_copy_keys); } server->rpk_pair.private_key = sol_blob_ref(my_rpk->private_key); server->rpk_pair.public_key = sol_blob_ref(my_rpk->public_key); } }
static int bootstrap_request(void *data, struct sol_coap_server *coap, const struct sol_coap_resource *resource, struct sol_coap_packet *req, const struct sol_network_link_addr *cliaddr) { struct sol_lwm2m_bootstrap_client_info *bs_cinfo; struct sol_lwm2m_bootstrap_server *server = data; struct sol_coap_packet *response; struct sol_str_slice client_name = SOL_STR_SLICE_EMPTY; int r; size_t i; bool know_client = false; SOL_DBG("Client Bootstrap Request received"); response = sol_coap_packet_new(req); SOL_NULL_CHECK(response, -ENOMEM); r = extract_bootstrap_client_info(req, &client_name); SOL_INT_CHECK_GOTO(r, < 0, err_exit); for (i = 0; server->known_clients[i]; i++) { if (sol_str_slice_str_eq(client_name, server->known_clients[i])) know_client = true; } if (!know_client) { SOL_WRN("Client %.*s bootstrap request received, but this Bootstrap Server" " doesn't have Bootstrap Information for this client.", SOL_STR_SLICE_PRINT(client_name)); goto err_exit; } r = new_bootstrap_client_info(&bs_cinfo, cliaddr, client_name); SOL_INT_CHECK_GOTO(r, < 0, err_exit); r = sol_ptr_vector_append(&server->clients, bs_cinfo); SOL_INT_CHECK_GOTO(r, < 0, err_exit_del_client); r = sol_coap_header_set_code(response, SOL_COAP_RESPONSE_CODE_CHANGED); SOL_INT_CHECK_GOTO(r, < 0, err_exit_del_client_list); SOL_DBG("Client %s bootstrap request received." " Bootstrap Process will start now.", bs_cinfo->name); r = sol_coap_send_packet(coap, response, cliaddr); dispatch_bootstrap_event_to_server(server, bs_cinfo); return r; err_exit_del_client_list: sol_ptr_vector_remove(&server->clients, bs_cinfo); err_exit_del_client: bootstrap_client_info_del(bs_cinfo); err_exit: sol_coap_header_set_code(response, SOL_COAP_RESPONSE_CODE_BAD_REQUEST); sol_coap_send_packet(coap, response, cliaddr); return r; }