//! [uart write] static bool send_blob(struct sol_blob *blob) { int err; bool r = true; //Actually write the blob into UART bus err = sol_uart_feed(producer, blob); if (err < 0) { //Oh no, there's no more space left. if (err == -ENOSPC) { pending_blob = blob; printf("No space left in the tx buffer - saving blob for later. Data: %.*s\n", SOL_STR_SLICE_PRINT(sol_str_slice_from_blob(pending_blob))); } else { fprintf(stderr, "Could not not perform an UART write - Reason: %s\n", sol_util_strerrora(-r)); r = false; sol_blob_unref(blob); } } else { sol_blob_unref(blob); if (blob == pending_blob) pending_blob = NULL; //Flag that data production can start once again! } return r; }
static bool on_err_read(void *data, int fd, uint32_t active_flags) { struct subprocess_data *mdata = data; struct sol_blob *blob = NULL; bool eof = true; int err = 0; if (active_flags & SOL_FD_FLAGS_ERR) err = -EBADF; else err = child_read(&blob, &eof, mdata->pipes.err[0]); if (eof || err < 0) { mdata->watches.err = NULL; if (err < 0) return false; } sol_flow_send_blob_packet(mdata->node, SOL_FLOW_NODE_TYPE_PROCESS_SUBPROCESS__OUT__STDERR, blob); sol_blob_unref(blob); if (eof) return false; return true; }
static bool on_write(void *data, int fd, uint32_t active_flags) { struct subprocess_data *mdata = data; int err = 0; if (active_flags & SOL_FD_FLAGS_ERR) err = -EBADF; else err = out_write(mdata); if (err < 0) { uint16_t i; struct write_data *w; SOL_VECTOR_FOREACH_IDX (&mdata->write_data, w, i) sol_blob_unref(w->blob); sol_vector_clear(&mdata->write_data); } if (mdata->write_data.len == 0) { mdata->watches.out = NULL; return false; } return true; }
void process_subprocess_close(struct sol_flow_node *node, void *data) { struct subprocess_data *mdata = data; if (mdata->fork_run) sol_platform_linux_fork_run_stop(mdata->fork_run); if (mdata->watches.in) sol_fd_del(mdata->watches.in); if (mdata->watches.err) sol_fd_del(mdata->watches.err); if (mdata->watches.out) { struct write_data *w; uint16_t i; sol_fd_del(mdata->watches.out); SOL_VECTOR_FOREACH_IDX (&mdata->write_data, w, i) sol_blob_unref(w->blob); sol_vector_clear(&mdata->write_data); } close(mdata->pipes.in[0]); close(mdata->pipes.in[1]); close(mdata->pipes.err[0]); close(mdata->pipes.err[1]); close(mdata->pipes.out[0]); close(mdata->pipes.out[1]); free(mdata->command); }
int process_subprocess_in_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct subprocess_data *mdata = data; struct sol_blob *blob; struct write_data *w; int ret; SOL_NULL_CHECK(mdata->fork_run, -EINVAL); ret = sol_flow_packet_get_blob(packet, &blob); SOL_INT_CHECK(ret, < 0, ret); w = sol_vector_append(&mdata->write_data); SOL_NULL_CHECK(w, -ENOMEM); w->offset = 0; w->blob = sol_blob_ref(blob); if (mdata->write_data.len > 1) return 0; mdata->watches.out = sol_fd_add(mdata->pipes.out[1], SOL_FD_FLAGS_OUT | SOL_FD_FLAGS_ERR, on_write, mdata); if (!mdata->watches.out) { sol_blob_unref(w->blob); sol_vector_del_last(&mdata->write_data); return -1; } return 0; }
static void on_feed_done_cb(void *data, struct sol_message_digest *md, struct sol_blob *input) { struct update_get_hash_handle *handle = data; char buf[CHUNK_SIZE], *blob_backend = NULL; struct sol_blob *blob = NULL; size_t size; bool last; int r; size = fread(buf, 1, sizeof(buf), handle->file); if (ferror(handle->file)) { SOL_WRN("Could not read file for feed hash algorithm"); goto err; } last = feof(handle->file); /* TODO Maybe this is a bug on sol_message_digest? Keeps calling on_feed_done * after send last chunk */ if (!size && last && input) { SOL_WRN("Nothing more to feed hash algorithm, ignoring on_feed_done request"); return; } blob_backend = malloc(size); SOL_NULL_CHECK_GOTO(blob_backend, err); blob = sol_blob_new(&SOL_BLOB_TYPE_DEFAULT, NULL, blob_backend, size); SOL_NULL_CHECK_GOTO(blob, err); memcpy(blob_backend, buf, size); r = sol_message_digest_feed(md, blob, last); SOL_INT_CHECK_GOTO(r, < 0, err); sol_blob_unref(blob); return; err: SOL_WRN("Could not feed data to check update file hash"); free(blob_backend); sol_blob_unref(blob); sol_message_digest_del(md); handle->cb((void *)handle->user_data, -EINVAL, NULL); delete_handle(handle); }
static void consumed_cb(void *data, uint32_t id, struct sol_blob *message) { printf("x86 receiving consumed confirmation id: %" PRIu32 " %p data: %s\n", id, message->mem, (char *)message->mem); sol_blob_unref(message); printf("After unref %p\n", message); }
static void file_reader_unload(struct file_reader_data *mdata) { if (mdata->idler) { sol_idle_del(mdata->idler); mdata->idler = NULL; } if (mdata->content_blob) { sol_blob_unref(mdata->content_blob); mdata->content_blob = NULL; } if (mdata->reader_blob) { sol_blob_unref(mdata->reader_blob); mdata->reader_blob = NULL; } SOL_DBG("unloaded path=\"%s\"", mdata->path ? mdata->path : ""); free(mdata->path); }
static void empty_receiver(void *data, uint32_t id, struct sol_blob *message) { struct sol_flow_node *node = data; sol_flow_send_empty_packet(node, SOL_FLOW_NODE_TYPE_IPM_EMPTY_READER__OUT__OUT); sol_blob_unref(message); }
static void direction_vector_receiver(void *data, uint32_t id, struct sol_blob *message) { struct sol_flow_node *node = data; sol_flow_send_direction_vector_packet(node, SOL_FLOW_NODE_TYPE_IPM_DIRECTION_VECTOR_READER__OUT__OUT, message->mem); sol_blob_unref(message); }
static void rgb_receiver(void *data, uint32_t id, struct sol_blob *message) { struct sol_flow_node *node = data; sol_flow_send_rgb_packet(node, SOL_FLOW_NODE_TYPE_IPM_RGB_READER__OUT__OUT, message->mem); sol_blob_unref(message); }
static void boolean_receiver(void *data, uint32_t id, struct sol_blob *message) { struct sol_flow_node *node = data; sol_flow_send_bool_packet(node, SOL_FLOW_NODE_TYPE_IPM_BOOLEAN_READER__OUT__OUT, *(bool *)message->mem); sol_blob_unref(message); }
static bool unref_cb(void *data) { struct sol_blob *blob = data; printf("ARC unrefing %p\n", blob->mem); sol_blob_unref(blob); return false; }
static bool unref_cb(void *data) { struct sol_blob *blob = data; printf("x86 unrefing %p - %s\n", blob->mem, (char *)blob->mem); sol_blob_unref(blob); return false; }
static void byte_receiver(void *data, uint32_t id, struct sol_blob *message) { struct sol_flow_node *node = data; sol_flow_send_byte_packet(node, SOL_FLOW_NODE_TYPE_IPM_BYTE_READER__OUT__OUT, *(unsigned char *)message->mem); sol_blob_unref(message); }
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; }
SOL_API void sol_blob_set_parent(struct sol_blob *blob, struct sol_blob *parent) { SOL_BLOB_CHECK(blob); if (parent) { SOL_BLOB_CHECK(parent); sol_blob_ref(parent); } if (blob->parent) sol_blob_unref(blob->parent); blob->parent = parent; }
SOL_API void sol_blob_unref(struct sol_blob *blob) { SOL_BLOB_CHECK(blob); blob->refcnt--; if (blob->refcnt > 0) return; if (blob->parent) sol_blob_unref(blob->parent); if (blob->type->free) blob->type->free(blob); else free(blob); }
static bool timeout_send_cb(void *data) { int r; char *str = strdup(samples[count % 4]); struct sol_blob *message = sol_blob_new(&SOL_BLOB_TYPE_DEFAULT, NULL, str, strlen(str) + 1); printf("ARC sending %s - %p\n", (char *)message->mem, message->mem); r = sol_ipm_send(MESSAGE_ID, message); if (r < 0) { printf("ARC could not send message: %d\n", r); } sol_blob_unref(message); /* Unref as we don't care about when it's consumed. Let blob be unref'ed and be happy happy*/ count++; return true; }
static int out_write(struct subprocess_data *mdata) { int ret = 0; struct timespec start = sol_util_timespec_get_current(); while (mdata->write_data.len) { struct timespec now = sol_util_timespec_get_current(); struct timespec elapsed; struct write_data *w = sol_vector_get(&mdata->write_data, 0); ssize_t r; sol_util_timespec_sub(&now, &start, &elapsed); if (elapsed.tv_sec > 0 || elapsed.tv_nsec > (time_t)CHUNK_MAX_TIME_NS) break; r = write(mdata->pipes.out[1], (uint8_t *)w->blob->mem + w->offset, w->blob->size - w->offset); if (r > 0) { w->offset += r; } else if (r < 0) { if (errno == EINTR) continue; else if (errno == EAGAIN) break; else { ret = -errno; break; } } if (w->blob->size <= w->offset) { sol_blob_unref(w->blob); sol_vector_del(&mdata->write_data, 0); } } return ret; }
static int file_reader_load(struct file_reader_data *mdata) { struct sol_file_reader *reader; struct sol_str_slice slice; if (!mdata->path) return 0; reader = sol_file_reader_open(mdata->path); if (!reader) { sol_flow_send_error_packet(mdata->node, errno, "Could not load \"%s\": %s", mdata->path, sol_util_strerrora(errno)); return -errno; } slice = sol_file_reader_get_all(reader); SOL_DBG("loaded path=\"%s\", data=%p, len=%zd", mdata->path, slice.data, slice.len); mdata->reader_blob = sol_blob_new(&file_reader_blob_type, NULL, reader, sizeof(reader)); SOL_NULL_CHECK_GOTO(mdata->reader_blob, err_reader); mdata->content_blob = sol_blob_new(SOL_BLOB_TYPE_NOFREE, mdata->reader_blob, slice.data, slice.len); SOL_NULL_CHECK_GOTO(mdata->content_blob, err_content); return sol_flow_send_blob_packet(mdata->node, SOL_FLOW_NODE_TYPE_FILE_READER__OUT__OUT, mdata->content_blob); err_content: sol_blob_unref(mdata->reader_blob); err_reader: sol_file_reader_close(reader); return -ENOMEM; }
static void on_fork_exit(void *data, uint64_t pid, int status) { struct subprocess_data *mdata = data; mdata->fork_run = NULL; if (mdata->watches.in) sol_fd_del(mdata->watches.in); if (mdata->watches.err) sol_fd_del(mdata->watches.err); if (mdata->watches.out) { struct write_data *w; uint16_t i; sol_fd_del(mdata->watches.out); SOL_VECTOR_FOREACH_IDX (&mdata->write_data, w, i) sol_blob_unref(w->blob); sol_vector_clear(&mdata->write_data); } mdata->watches.in = NULL; mdata->watches.err = NULL; mdata->watches.out = NULL; sol_flow_send_irange_value_packet(mdata->node, SOL_FLOW_NODE_TYPE_PROCESS_SUBPROCESS__OUT__STATUS, status); }
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++; }