//! [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 reply_cb(struct sol_coap_server *server, struct sol_coap_packet *req, const struct sol_network_link_addr *cliaddr, void *data) { struct sol_str_slice *path = data; static int count; struct sol_buffer *buf; size_t offset; SOL_BUFFER_DECLARE_STATIC(addr, SOL_INET_ADDR_STRLEN); if (!req || !cliaddr) //timeout return false; sol_network_link_addr_to_str(cliaddr, &addr); SOL_INF("Got response from %.*s\n", SOL_STR_SLICE_PRINT(sol_buffer_get_slice(&addr))); sol_coap_packet_get_payload(req, &buf, &offset); SOL_INF("Payload: %.*s\n", (int)(buf->used - offset), (char *)sol_buffer_at(buf, offset)); if (++count == 10) disable_observing(req, server, path, cliaddr); return true; }
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 producer_make_data(void *data) { void *v; size_t size; struct sol_blob *blob; struct sol_buffer buf = SOL_BUFFER_INIT_EMPTY; static uint16_t packets_created = 0; bool keep_running = true; int r; //Stop the production until the pendind blob is sent if (pending_blob) { printf("Waiting for blob data: %.*s to be transfered.\n", SOL_STR_SLICE_PRINT(sol_str_slice_from_blob(pending_blob))); return true; } packets_created++; //Generate data if (packets_created != MAX_PACKETS) r = sol_util_uuid_gen(true, true, &buf); else { r = sol_buffer_append_slice(&buf, sol_str_slice_from_str("close")); keep_running = false; } if (r < 0) { fprintf(stderr, "Could not create the UUID - Reason: %s\n", sol_util_strerrora(-r)); goto err_exit; } v = sol_buffer_steal(&buf, &size); blob = sol_blob_new(&SOL_BLOB_TYPE_DEFAULT, NULL, v, size + 1); if (!blob) { fprintf(stderr, "Could not alloc memory for the blob\n"); goto err_exit; } //Send it if (!send_blob(blob)) goto err_exit; if (!keep_running) goto exit; return true; err_exit: sol_quit(); exit: producer_timeout = NULL; return false; }
static void on_feed_done_cb(void *data, struct sol_http_progressive_response *sse, struct sol_blob *blob, int status) { struct sol_str_slice slice = sol_str_slice_from_blob(blob); if (sol_str_slice_str_eq(slice, "data: ") || sol_str_slice_str_eq(slice, "\n\n")) return; if (isspace(slice.data[slice.len - 1])) slice.len--; printf("Blob data *%.*s* sent\n", SOL_STR_SLICE_PRINT(slice)); }
//! [uart write completed] static void producer_data_written(void *data, struct sol_uart *uart, struct sol_blob *blob, int status) { struct sol_str_slice slice; slice = sol_str_slice_from_blob(blob); if (status < 0) { fprintf(stderr, "Could not write the UUID %.*s - Reason: %s\n", SOL_STR_SLICE_PRINT(slice), sol_util_strerrora(-status)); sol_quit(); } else { printf("Producer: UUID %.*s written\n", SOL_STR_SLICE_PRINT(slice)); if (pending_blob) { //If we have a pending blob now it's the time to try to send it! if (!send_blob(pending_blob)) { fprintf(stderr, "Could not send the pending blob!\n"); sol_quit(); } } } }
static int extract_bootstrap_client_info(struct sol_coap_packet *req, struct sol_str_slice *client_name) { struct sol_str_slice query; int r; r = sol_coap_find_options(req, SOL_COAP_OPTION_URI_QUERY, &query, LWM2M_BOOTSTRAP_QUERY_PARAMS); SOL_INT_CHECK(r, < 0, r); struct sol_str_slice key, value; const char *sep; SOL_DBG("Query:%.*s", SOL_STR_SLICE_PRINT(query)); sep = memchr(query.data, '=', query.len); if (!sep) { SOL_WRN("Could not find the separator '=' at: %.*s", SOL_STR_SLICE_PRINT(query)); return -EINVAL; } key.data = query.data; key.len = sep - query.data; value.data = sep + 1; value.len = query.len - key.len - 1; if (sol_str_slice_str_eq(key, "ep")) { //Required info *client_name = value; } else { SOL_WRN("The client did not provide its name!"); return -EINVAL; } return 0; }
//! [uart read] static ssize_t consumer_read_available(void *data, struct sol_uart *uart, const struct sol_buffer *buf) { struct sol_str_slice slice = sol_buffer_get_slice(buf); char *sep; sep = memchr(slice.data, '\0', slice.len); if (!sep) return 0; //Bytes will not be removed fom the rx buffer //Close the UART! if (sol_str_slice_str_contains(slice, "close")) { sol_uart_close(uart); //This is completely safe consumer = NULL; printf("\n\n** Consumer **: Received the close command\n\n"); sol_quit(); } else { printf("\n\n** Consumer ** : Received UUID %.*s\n\n", SOL_STR_SLICE_PRINT(slice)); } return slice.len; //slice.len bytes will be removed from the rx buffer }
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; }
static void inspector_show_packet_value(const struct sol_flow_packet *packet) { const struct sol_flow_packet_type *type = sol_flow_packet_get_type(packet); if (type == SOL_FLOW_PACKET_TYPE_EMPTY) { fputs("<empty>", stdout); return; } else if (type == SOL_FLOW_PACKET_TYPE_ANY) { fputs("<any>", stdout); return; } else if (type == SOL_FLOW_PACKET_TYPE_ERROR) { int code; const char *msg; if (sol_flow_packet_get_error(packet, &code, &msg) == 0) { fprintf(stdout, "<error:%d \"%s\">", code, msg ? msg : ""); return; } } else if (type == SOL_FLOW_PACKET_TYPE_BOOL) { bool v; if (sol_flow_packet_get_bool(packet, &v) == 0) { fprintf(stdout, "<%s>", v ? "true" : "false"); return; } } else if (type == SOL_FLOW_PACKET_TYPE_BYTE) { unsigned char v; if (sol_flow_packet_get_byte(packet, &v) == 0) { fprintf(stdout, "<%#x>", v); return; } } else if (type == SOL_FLOW_PACKET_TYPE_IRANGE) { struct sol_irange v; if (sol_flow_packet_get_irange(packet, &v) == 0) { fprintf(stdout, "<val:%d|min:%d|max:%d|step:%d>", v.val, v.min, v.max, v.step); return; } } else if (type == SOL_FLOW_PACKET_TYPE_DRANGE) { struct sol_drange v; if (sol_flow_packet_get_drange(packet, &v) == 0) { fprintf(stdout, "<val:%g|min:%g|max:%g|step:%g>", v.val, v.min, v.max, v.step); return; } } else if (type == SOL_FLOW_PACKET_TYPE_STRING) { const char *v; if (sol_flow_packet_get_string(packet, &v) == 0) { fprintf(stdout, "<\"%s\">", v); return; } } else if (type == SOL_FLOW_PACKET_TYPE_BLOB) { struct sol_blob *v; if (sol_flow_packet_get_blob(packet, &v) == 0) { fprintf(stdout, "<mem=%p|size=%zd|refcnt=%hu|type=%p|parent=%p>", v->mem, v->size, v->refcnt, v->type, v->parent); return; } } else if (type == SOL_FLOW_PACKET_TYPE_JSON_OBJECT) { struct sol_blob *v; if (sol_flow_packet_get_json_object(packet, &v) == 0) { fprintf(stdout, "<%.*s>", SOL_STR_SLICE_PRINT(sol_str_slice_from_blob(v))); return; } } else if (type == SOL_FLOW_PACKET_TYPE_JSON_ARRAY) { struct sol_blob *v; if (sol_flow_packet_get_json_array(packet, &v) == 0) { fprintf(stdout, "<%.*s>", SOL_STR_SLICE_PRINT(sol_str_slice_from_blob(v))); return; } } else if (type == SOL_FLOW_PACKET_TYPE_RGB) { struct sol_rgb v; if (sol_flow_packet_get_rgb(packet, &v) == 0) { fprintf(stdout, "<red=%u|green=%u|blue=%u" "|red_max=%u|green_max=%u|blue_max=%u>", v.red, v.green, v.blue, v.red_max, v.green_max, v.blue_max); return; } } else if (type == SOL_FLOW_PACKET_TYPE_DIRECTION_VECTOR) { struct sol_direction_vector v; if (sol_flow_packet_get_direction_vector(packet, &v) == 0) { fprintf(stdout, "<x=%g|y=%g|z=%g|min=%g|max=%g>", v.x, v.y, v.z, v.min, v.max); return; } } else if (type == SOL_FLOW_PACKET_TYPE_LOCATION) { struct sol_location v; if (sol_flow_packet_get_location(packet, &v) == 0) { fprintf(stdout, "<lat=%g|lon=%g|alt=%g>", v.lat, v.lon, v.alt); return; } } else if (type == SOL_FLOW_PACKET_TYPE_TIMESTAMP) { struct timespec v; if (sol_flow_packet_get_timestamp(packet, &v) == 0) { struct tm cur_time; char buf[32]; tzset(); if (gmtime_r(&v.tv_sec, &cur_time)) { if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", &cur_time) > 0) { fprintf(stdout, "<%s>", buf); return; } } } } else if (type == SOL_FLOW_PACKET_TYPE_HTTP_RESPONSE) { int code; const char *url, *content_type; const struct sol_blob *content; struct sol_vector headers, cookies; if (sol_flow_packet_get_http_response(packet, &code, &url, &content_type, &content, &cookies, &headers) == 0) { fprintf(stdout, "<response_code:%d|content type:%s|url:%s|", code, content_type, url); fprintf(stdout, "|cookies: {"); inpector_print_key_value_array(&cookies); fprintf(stdout, "}|headers:{"); inpector_print_key_value_array(&headers); fprintf(stdout, "}|content:{mem=%p|size=%zd|refcnt=%hu|type=%p|parent=%p}>", content->mem, content->size, content->refcnt, content->type, content->parent); } return; } fputs("<?>", stdout); }