SOL_API int sol_flow_send_packet(struct sol_flow_node *src, uint16_t src_port, struct sol_flow_packet *packet) { struct sol_flow_node *parent; struct sol_flow_node_container_type *parent_type; int ret; SOL_FLOW_NODE_CHECK_GOTO(src, err); parent = src->parent; if (!parent) { sol_flow_packet_del(packet); return 0; } inspector_will_send_packet(src, src_port, packet); /* TODO: consider caching send pointer into parent's node data to * reduce indirection. */ SOL_FLOW_NODE_TYPE_IS_CONTAINER_CHECK_GOTO(parent, err); parent_type = (struct sol_flow_node_container_type *)parent->type; ret = parent_type->send(parent, src, src_port, packet); if (ret != 0) sol_flow_packet_del(packet); return ret; err: sol_flow_packet_del(packet); return -EINVAL; }
static void flow_node_close(struct sol_flow_node *node, void *data) { struct flow_static_type *type = (struct flow_static_type *)node->type; struct flow_static_data *fsd = data; int i; if (fsd->delay_send) sol_timeout_del(fsd->delay_send); while (!sol_list_is_empty(&fsd->delayed_packets)) { struct delayed_packet *dp; struct sol_list *itr = fsd->delayed_packets.next; dp = SOL_LIST_GET_CONTAINER(itr, struct delayed_packet, list); sol_list_remove(itr); sol_flow_packet_del(dp->packet); free(dp); } teardown_connections(type, fsd); for (i = type->node_count - 1; i >= 0; i--) sol_flow_node_fini(fsd->nodes[i]); free(fsd->node_storage); free(fsd->nodes); if (type->owned_by_node) sol_flow_static_del_type(&type->base.base); }
static void flow_send_do(struct sol_flow_node *flow, struct flow_static_data *fsd, uint16_t src_idx, uint16_t source_out_port_idx, struct sol_flow_packet *packet) { struct flow_static_type *type = (struct flow_static_type *)flow->type; const struct sol_flow_static_conn_spec *spec; unsigned int i; bool is_error_packet, dispatched; is_error_packet = sol_flow_packet_get_type(packet) == SOL_FLOW_PACKET_TYPE_ERROR; dispatched = false; for (i = type->node_infos[src_idx].first_conn_idx, spec = type->conn_specs + i; spec->src == src_idx; spec++, i++) { const struct sol_flow_port_type_in *dst_port_type; struct sol_flow_node *dst; struct conn_info *ci; if (spec->src_port != source_out_port_idx) continue; dst = fsd->nodes[spec->dst]; dst_port_type = sol_flow_node_type_get_port_in(dst->type, spec->dst_port); ci = &type->conn_infos[i]; dispatch_process(dst, spec->dst_port, ci->in_conn_id, dst_port_type, packet); dispatched = true; } if (type->ports_out_count > 0) { const struct sol_flow_static_port_spec *pspec; uint16_t exported_out; for (pspec = type->exported_out_specs, exported_out = 0; pspec->node < UINT16_MAX; pspec++, exported_out++) { if (pspec->node == src_idx && pspec->port == source_out_port_idx) { /* Export the packet. Note that ownership of packet * will pass to the send() function. */ sol_flow_send_packet(flow, exported_out, packet); return; } } } if (is_error_packet && !dispatched) { const char *msg; int code; if (sol_flow_packet_get_error(packet, &code, &msg) == 0) { SOL_WRN("Error packet \'%d (%s)\' sent from \'%s (%p)\' was not handled", code, msg, flow->id, flow); } } sol_flow_packet_del(packet); }
static int http_composed_client_simple_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id, const struct sol_flow_packet *packet) { struct http_composed_client_data *hdata = data; if (hdata->inputs[port]) sol_flow_packet_del(hdata->inputs[port]); hdata->inputs[port] = sol_flow_packet_dup(packet); SOL_NULL_CHECK(hdata->inputs[port], -ENOMEM); return 0; }
static void http_composed_client_close(struct sol_flow_node *node, void *data) { struct sol_http_client_connection *connection; struct http_composed_client_data *cdata = data; uint16_t i; for (i = 0; i < cdata->inputs_len; i++) if (cdata->inputs[i]) sol_flow_packet_del(cdata->inputs[i]); SOL_PTR_VECTOR_FOREACH_IDX (&cdata->pending_conns, connection, i) sol_http_client_connection_cancel(connection); sol_ptr_vector_clear(&cdata->pending_conns); free(cdata->url); free(cdata->inputs); }
static int connect_nodes(struct flow_static_type *type, struct flow_static_data *fsd) { const struct sol_flow_static_conn_spec *spec; int i, r; for (i = 0, spec = type->conn_specs; i < type->conn_count; i++, spec++) { const struct sol_flow_port_type_out *src_port_type; const struct sol_flow_port_type_in *dst_port_type; struct sol_flow_node *src, *dst; struct conn_info *ci; struct sol_flow_packet *packet = NULL; src = fsd->nodes[spec->src]; dst = fsd->nodes[spec->dst]; ci = &type->conn_infos[i]; src_port_type = sol_flow_node_type_get_port_out(src->type, spec->src_port); dst_port_type = sol_flow_node_type_get_port_in(dst->type, spec->dst_port); SOL_FLOW_PORT_TYPE_OUT_API_CHECK(src_port_type, SOL_FLOW_PORT_TYPE_OUT_API_VERSION, -EINVAL); SOL_FLOW_PORT_TYPE_IN_API_CHECK(dst_port_type, SOL_FLOW_PORT_TYPE_IN_API_VERSION, -EINVAL); if (!src_port_type->packet_type) { CONNECT_NODES_WRN(spec, src->id, dst->id, "Invalid packet type for source port"); return -EINVAL; } if (!dst_port_type->packet_type) { CONNECT_NODES_WRN(spec, src->id, dst->id, "Invalid packet type for destination port"); return -EINVAL; } if (!match_packets(src_port_type->packet_type, dst_port_type->packet_type)) { CONNECT_NODES_WRN(spec, src->id, dst->id, "Error matching source and destination packet types: %s != %s: %s", src_port_type->packet_type->name, dst_port_type->packet_type->name, sol_util_strerrora(EINVAL)); r = -EINVAL; goto dispatch_error; } r = dispatch_connect_out(src, spec->src_port, ci->out_conn_id, src_port_type); if (r < 0) { CONNECT_NODES_WRN(spec, src->id, dst->id, "Error connecting source: %s", sol_util_strerrora(-r)); if (packet) sol_flow_packet_del(packet); goto dispatch_error; } r = dispatch_connect_in(dst, spec->dst_port, ci->in_conn_id, dst_port_type); if (r < 0) { CONNECT_NODES_WRN(spec, src->id, dst->id, "Error connecting destination: %s", sol_util_strerrora(-r)); dispatch_disconnect_out(src, spec->src_port, ci->out_conn_id, src_port_type); if (packet) sol_flow_packet_del(packet); goto dispatch_error; } inspector_did_connect_port(src, spec->src_port, ci->out_conn_id, dst, spec->dst_port, ci->in_conn_id); if (!packet) continue; dispatch_process(dst, spec->dst_port, ci->in_conn_id, dst_port_type, (const struct sol_flow_packet *)packet); sol_flow_packet_del(packet); } SOL_DBG("Making %u connections.", i); return 0; dispatch_error: /* Dispatch disconnections in reverse order. Skip current failed * iteration since it was handled inside the loop. */ i--; spec--; for (; i >= 0; i--, spec--) { const struct sol_flow_port_type_out *src_port_type; const struct sol_flow_port_type_in *dst_port_type; struct sol_flow_node *src, *dst; struct conn_info *ci; src = fsd->nodes[spec->src]; dst = fsd->nodes[spec->dst]; ci = &type->conn_infos[i]; dst_port_type = sol_flow_node_type_get_port_in(dst->type, spec->dst_port); dispatch_disconnect_in(dst, spec->dst_port, ci->in_conn_id, dst_port_type); src_port_type = sol_flow_node_type_get_port_out(src->type, spec->src_port); dispatch_disconnect_out(src, spec->src_port, ci->out_conn_id, src_port_type); } return r; }