static void create_seconds(void) { const struct sol_flow_node_type **type; struct sol_flow_node_named_options named_opts = {}; const char *strv_opts[] = { "send_initial_packet=1", NULL }; struct sol_flow_node_options *opts; int err; err = sol_flow_get_node_type("wallclock", SOL_FLOW_NODE_TYPE_WALLCLOCK_SECOND, &type); if (err < 0) { fputs("could not find type: wallclock/second\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } seconds_port_enabled = sol_flow_node_find_port_in(*type, "ENABLED"); if (seconds_port_enabled == UINT16_MAX) { fputs("ERROR: couldn't find ouput port by name: ENABLED\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } seconds_port_out = sol_flow_node_find_port_out(*type, "OUT"); if (seconds_port_out == UINT16_MAX) { fputs("ERROR: couldn't find ouput port by name: OUT\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } err = sol_flow_node_named_options_init_from_strv(&named_opts, *type, strv_opts); if (err < 0) { fputs("could not parse options for wallclock/second\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } err = sol_flow_node_options_new(*type, &named_opts, &opts); sol_flow_node_named_options_fini(&named_opts); if (err < 0) { fputs("could not create options for wallclock/second\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } seconds = sol_flow_single_new("seconds", *type, opts, SOL_FLOW_SINGLE_CONNECTIONS(seconds_port_enabled), SOL_FLOW_SINGLE_CONNECTIONS(seconds_port_out), on_seconds_packet, NULL); sol_flow_node_options_del(*type, opts); }
static bool startup(void *data) { bool finished = true; int result = EXIT_FAILURE; the_runner = runner_new(args.filename); if (!the_runner) goto end; if (args.check_only) { printf("file: '%s' - Syntax OK\n", args.filename); result = EXIT_SUCCESS; goto end; } if (runner_run(the_runner) < 0) { SOL_ERR("Failed to run"); goto end; } finished = false; end: if (finished) sol_quit_with_code(result); return false; }
static bool on_watchdog(void *data) { SOL_WRN("watchdog expired - mainloop integration failed"); sol_quit_with_code(EXIT_FAILURE); return false; }
static void fail(const struct sol_flow_node *node) { mark_done(node); SOL_ERR("test/result node '%s' failed", sol_flow_node_get_id(node)); sol_quit_with_code(EXIT_FAILURE); }
static bool on_stdin(void *data, int fd, uint32_t flags) { if (flags & (SOL_FD_FLAGS_ERR | SOL_FD_FLAGS_HUP)) { fprintf(stderr, "ERROR: Something wrong happened with file descriptor: %d\n", fd); goto err; } if (flags & SOL_FD_FLAGS_IN) { int err; value.used = 0; /* this will loop trying to read as much data as possible to buffer. */ err = sol_util_load_file_fd_buffer(fd, &value); if (err < 0) { fprintf(stderr, "ERROR: failed to read from stdin: %s\n", sol_util_strerrora(-err)); goto err; } if (value.used == 0) { /* no data usually means ^D on the terminal, quit the application */ puts("no data on stdin, quitting."); sol_quit(); } else { printf("Now serving %zd bytes:\n--BEGIN--\n%.*s\n--END--\n", value.used, SOL_STR_SLICE_PRINT(sol_buffer_get_slice(&value))); } } return true; err: sol_quit_with_code(EXIT_FAILURE); return false; }
static bool startup(void *data) { bool finished = true; int result = EXIT_FAILURE; struct sol_ptr_vector *memory_maps; str_arena = sol_arena_new(); if (!str_arena) { fprintf(stderr, "Cannot create str arena\n"); goto end; } if (args.execute_type) { the_runner = runner_new_from_type(args.name, args.options); } else { the_runner = runner_new_from_file(args.name, args.options, &args.fbp_search_paths); } if (!the_runner) goto end; if (args.check_only) { printf("'%s' - Syntax OK\n", args.name); result = EXIT_SUCCESS; goto end; } if (args.provide_sim_nodes) { int err; err = runner_attach_simulation(the_runner); if (err < 0) { fprintf(stderr, "Cannot attach simulation nodes\n"); goto end; } } if (sol_conffile_resolve_memmap(&memory_maps)) { SOL_ERR("Couldn't resolve memory mappings on config file"); goto end; } if (memory_maps) load_memory_maps(memory_maps); if (runner_run(the_runner) < 0) { fprintf(stderr, "Failed to run\n"); goto end; } finished = false; end: if (finished) sol_quit_with_code(result); return false; }
static void startup(void) { session = sol_bt_enable(enabled, NULL); if (!session) { SOL_WRN("Couldn't create a Bluetooth session"); sol_quit_with_code(-ENOMEM); } }
static bool on_stdin(void *data, int fd, uint32_t flags) { uint16_t i; struct sol_http_progressive_response *sse; struct sol_buffer value = SOL_BUFFER_INIT_EMPTY; if (flags & (SOL_FD_FLAGS_ERR | SOL_FD_FLAGS_HUP)) { fprintf(stderr, "ERROR: Something wrong happened with file descriptor: %d\n", fd); goto err; } if (flags & SOL_FD_FLAGS_IN) { int err; struct sol_blob *blob; /* this will loop trying to read as much data as possible to buffer. */ err = sol_util_load_file_fd_buffer(fd, &value); if (err < 0) { fprintf(stderr, "ERROR: failed to read from stdin: %s\n", sol_util_strerrora(-err)); goto err; } if (value.used == 0) { /* no data usually means ^D on the terminal, quit the application */ printf("no data on stdin, quitting.\n"); should_quit = true; SOL_PTR_VECTOR_FOREACH_IDX (&responses, sse, i) sol_http_progressive_response_del(sse, true); goto end; } blob = sol_buffer_to_blob(&value); if (!blob) { fprintf(stderr, "Could not alloc the blob data\n"); goto err; } SOL_PTR_VECTOR_FOREACH_IDX (&responses, sse, i) sol_http_progressive_response_sse_feed(sse, blob); sol_blob_unref(blob); } sol_buffer_fini(&value); return true; err: sol_quit_with_code(EXIT_FAILURE); end: stdin_watch = NULL; sol_buffer_fini(&value); return false; }
static void startup(void) { guint id; if (pipe2(pfd, O_CLOEXEC) < 0) { SOL_WRN("pipe()"); goto error; } if (!sol_glib_integration()) { SOL_WRN("sol_glib_integration()"); goto error; } fork_run = sol_platform_linux_fork_run(on_fork, on_child_exit, NULL); if (!fork_run) { SOL_WRN("sol_platform_linux_fork_run()"); goto error; } id = g_idle_add(on_idle, NULL); if (id == 0) { SOL_WRN("g_idle_add()"); goto error; } id = g_timeout_add(100, on_timeout, NULL); if (id == 0) { SOL_WRN("g_timeout_add()"); goto error; } id = g_unix_fd_add(pfd[0], G_IO_IN, on_fd, NULL); if (id == 0) { SOL_WRN("g_unix_fd_add()"); goto error; } sol_timeout_add(5000, on_watchdog, NULL); return; error: sol_quit_with_code(EXIT_FAILURE); return; }
static void create_minutes(void) { const struct sol_flow_node_type **type; struct sol_flow_node_named_options named_opts = {}; const char *strv_opts[] = { "send_initial_packet=1", NULL }; struct sol_flow_node_options *opts; int err; /* Resolves the type based on its name. This will take care of * built-in modules and external modules, loading on demand as * required. This macro also handles static-compiles, so the * second parameter is the C symbol to be used in such case. */ err = sol_flow_get_node_type("wallclock", SOL_FLOW_NODE_TYPE_WALLCLOCK_MINUTE, &type); if (err < 0) { fputs("could not find type: wallclock/minute\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } /* For efficiency matters Soletta doesn't work with port names, * rather using port indexes. If * SOL_FLOW_NODE_TYPE_DESCRIPTION_ENABLED, then we can resolve * strings to numbers, otherwise it is required to check the port * numbers, which are often available in the header file such as * sol-flow/wallclock.h such as * SOL_FLOW_NODE_TYPE_WALLCLOCK_MINUTE__OUT__OUT. */ minutes_port_enabled = sol_flow_node_find_port_in(*type, "ENABLED"); if (minutes_port_enabled == UINT16_MAX) { fputs("ERROR: couldn't find ouput port by name: ENABLED\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } minutes_port_out = sol_flow_node_find_port_out(*type, "OUT"); if (minutes_port_out == UINT16_MAX) { fputs("ERROR: couldn't find ouput port by name: OUT\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } /* wallclock/minute takes a boolean option send_initial_packet. * We have couple of options to create it: * * 1 - include sol-flow/wallclock.h, declare a variable of type * struct sol_flow_node_type_wallclock_minute_options and fill * its members. This requires sol-flow/wallclock.h to be * avaiable, but is more efficient since goes straight to the * point, no parsing or memory allocations. It would look * like: * * #include <sol-flow/wallclock.h> * * struct sol_flow_node_type_wallclock_minute_options opts = * SOL_FLOW_NODE_TYPE_WALLCLOCK_MINUTE_OPTIONS_DEFAULTS( * .send_initial_packet = true); * * 2 - access type->options_size, * type->default_options and * type->description->options and manually * create the structure in runtime. This demands * SOL_FLOW_NODE_TYPE_DESCRIPTION_ENABLED, but may be useful * when converting from a different representation, like a * language binding such as JavaScript or Python where one can * get an object, hashmap or dictionary and convert straight * to the C structure needed by the flow node type. * * 3 - use helper sol_flow_node_named_options_init_from_strv() and * sol_flow_node_options_new(), giving it an array of * "key=value" strings. It will do the work described in #2 * for us, thus also depends on * SOL_FLOW_NODE_TYPE_DESCRIPTION_ENABLED. * * We'll use approach #3 since it is simpler. Language bindings * should go with option #2 and those that want to squeeze the * size and get performance should consider #1. */ err = sol_flow_node_named_options_init_from_strv(&named_opts, *type, strv_opts); if (err < 0) { fputs("could not parse options for wallclock/minute\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } /* convert the named options in the actual options structure */ err = sol_flow_node_options_new(*type, &named_opts, &opts); sol_flow_node_named_options_fini(&named_opts); if (err < 0) { fputs("could not create options for wallclock/minute\n", stderr); sol_quit_with_code(EXIT_FAILURE); return; } /* Build the single node wrapping the wanted 'wallclock/minute'. * For most matters the single node behaves like the inner node, * it will copy the descriptions and options. * * The difference is that if you call sol_flow_send_packet() on * its input ports, it will forward the packet to the inner * node. Likewise, packets originated at the outgoing ports of the * inner node will be delivered through the process callback * (on_packet()) provided to the single node. * * Note that ports you want to send (in) or receive (out) packets * must be connected with the connected_ports_in and * connected_ports_out parameters, or later with * sol_flow_single_port_in_connect() and * sol_flow_single_port_out_connect(). */ minutes = sol_flow_single_new("minutes", *type, opts, SOL_FLOW_SINGLE_CONNECTIONS(minutes_port_enabled), SOL_FLOW_SINGLE_CONNECTIONS(minutes_port_out), on_minutes_packet, NULL); sol_flow_node_options_del(*type, opts); }
SOL_API void sol_quit(void) { sol_quit_with_code(EXIT_SUCCESS); }
static void startup(void) { const char *algorithm = "sha256"; const char *key = NULL; char **argv = sol_argv(); int i, argc = sol_argc(); size_t chunk_size = -1; if (argc < 2) { fprintf(stderr, "Usage:\n\t%s [-a <algorithm>] [-c chunk_size] [-k key] <file1> .. <fileN>\n", argv[0]); sol_quit_with_code(EXIT_FAILURE); return; } for (i = 1; i < argc; i++) { struct feed_ctx *ctx; struct sol_message_digest_config cfg = { SOL_SET_API_VERSION(.api_version = SOL_MESSAGE_DIGEST_CONFIG_API_VERSION, ) .algorithm = algorithm, .on_feed_done = on_feed_done, .on_digest_ready = on_digest_ready, }; struct sol_file_reader *fr; struct sol_blob *blob; struct sol_message_digest *mdh; int r; if (argv[i][0] == '-') { if (argv[i][1] == 'a') { if (i + 1 < argc) { algorithm = argv[i + 1]; i++; continue; } else fputs("ERROR: argument -a missing value.\n", stderr); } else if (argv[i][1] == 'k') { if (i + 1 < argc) { key = argv[i + 1]; i++; continue; } else fputs("ERROR: argument -a missing value.\n", stderr); } else if (argv[i][1] == 'c') { if (i + 1 < argc) { chunk_size = atoi(argv[i + 1]); i++; continue; } else fputs("ERROR: argument -c missing value.\n", stderr); } else fprintf(stderr, "ERROR: unknown option %s\n", argv[i]); sol_quit_with_code(EXIT_FAILURE); return; } fr = sol_file_reader_open(argv[i]); if (!fr) { fprintf(stderr, "ERROR: could not open file '%s': %s\n", argv[i], sol_util_strerrora(errno)); continue; } blob = sol_file_reader_to_blob(fr); if (!blob) { fprintf(stderr, "ERROR: could not create blob for file '%s'\n", argv[i]); continue; } cfg.data = ctx = calloc(1, sizeof(struct feed_ctx)); if (!ctx) { fprintf(stderr, "ERROR: could not allocate context memory " "to process file '%s'\n", argv[i]); sol_blob_unref(blob); continue; } ctx->file = argv[i]; ctx->start = sol_util_timespec_get_current(); ctx->done = 0; ctx->chunk_size = chunk_size; if (key) cfg.key = sol_str_slice_from_str(key); mdh = sol_message_digest_new(&cfg); if (!mdh) { fprintf(stderr, "ERROR: could not create message digest for " " algorithm \"%s\": %s\n", algorithm, sol_util_strerrora(errno)); sol_blob_unref(blob); free(ctx); continue; } if (chunk_size <= 0) { r = sol_message_digest_feed(mdh, blob, true); if (r < 0) { fprintf(stderr, "ERROR: could not feed message for " " algorithm \"%s\": %s\n", algorithm, sol_util_strerrora(-r)); sol_blob_unref(blob); sol_message_digest_del(mdh); free(ctx); continue; } } else { size_t offset = 0; while (offset < blob->size) { size_t remaining = blob->size - offset; size_t clen = remaining > chunk_size ? chunk_size : remaining; uint8_t *cmem = (uint8_t *)blob->mem + offset; bool is_last = offset + clen == blob->size; struct sol_blob *chunk = sol_blob_new(&SOL_BLOB_TYPE_NO_FREE_DATA, blob, cmem, clen); if (!chunk) { fprintf(stderr, "ERROR: could not create chunk blob at " "mem %p, size=%zd\n", cmem, clen); sol_blob_unref(blob); sol_message_digest_del(mdh); free(ctx); continue; } r = sol_message_digest_feed(mdh, chunk, is_last); if (r < 0) { fprintf(stderr, "ERROR: could not feed chunk for " " algorithm \"%s\": %s\n", algorithm, sol_util_strerrora(-r)); sol_blob_unref(blob); sol_blob_unref(chunk); sol_message_digest_del(mdh); free(ctx); continue; } sol_blob_unref(chunk); offset += clen; } } sol_blob_unref(blob); pending++; }