Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
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;
}