Пример #1
0
static TGenEvent _tgentransport_receiveSocksChoice(TGenTransport* transport) {
    /*
    2 socks choice client <-- server
    \x05 (version 5)
    \x00 (auth method choice - \xFF means none supported)
    */
    gchar buffer[8];
    memset(buffer, 0, 8);
    gssize bytesReceived = tgentransport_read(transport, buffer, 2);
    g_assert(bytesReceived == 2);
    transport->time.proxyChoice = g_get_monotonic_time();

    if(buffer[0] == 0x05 && buffer[1] == 0x00) {
        tgen_debug("socks choice supported by proxy %s", tgenpeer_toString(transport->proxy));

        _tgentransport_changeState(transport, TGEN_XPORT_PROXY_REQUEST);
        return TGEN_EVENT_WRITE;
    } else {
        tgen_debug("socks choice unsupported by proxy %s", tgenpeer_toString(transport->proxy));

        _tgentransport_changeState(transport, TGEN_XPORT_ERROR);
        _tgentransport_changeError(transport, TGEN_XPORT_ERR_PROXY_CHOICE);
        return TGEN_EVENT_NONE;
    }
}
Пример #2
0
static GError* _tgengraph_parseTransferVertex(TGenGraph* g, const gchar* idStr,
        igraph_integer_t vertexIndex) {
    TGEN_ASSERT(g);

    const gchar* typeStr = (g->knownAttributes&TGEN_VA_TYPE) ?
            VAS(g->graph, "type", vertexIndex) : NULL;
    const gchar* protocolStr = (g->knownAttributes&TGEN_VA_PROTOCOL) ?
            VAS(g->graph, "protocol", vertexIndex) : NULL;
    const gchar* sizeStr = (g->knownAttributes&TGEN_VA_SIZE) ?
            VAS(g->graph, "size", vertexIndex) : NULL;
    const gchar* peersStr = (g->knownAttributes&TGEN_VA_PEERS) ?
            VAS(g->graph, "peers", vertexIndex) : NULL;
    const gchar* timeoutStr = (g->knownAttributes&TGEN_VA_TIMEOUT) ?
            VAS(g->graph, "timeout", vertexIndex) : NULL;

    tgen_debug("found vertex %li (%s), type=%s protocol=%s size=%s peers=%s timeout=%s",
            (glong)vertexIndex, idStr, typeStr, protocolStr, sizeStr, peersStr, timeoutStr);

    GError* error = NULL;
    TGenAction* a = tgenaction_newTransferAction(typeStr, protocolStr, sizeStr, peersStr, timeoutStr, &error);

    if(a) {
        _tgengraph_storeAction(g, a, vertexIndex);
        if(!tgenaction_getPeers(a)) {
            g->transferMissingPeers = TRUE;
        }
    }

    return error;
}
Пример #3
0
static GError* _tgengraph_parseSynchronizeVertex(TGenGraph* g, const gchar* idStr,
        igraph_integer_t vertexIndex) {
    TGEN_ASSERT(g);

    tgen_debug("found vertex %li (%s)", (glong)vertexIndex, idStr);

    /* Count up the total incoming edges */

    /* initialize a vector to hold the result neighbor vertices for this action */
    igraph_vector_t* resultNeighborVertices = g_new0(igraph_vector_t, 1);

    /* initialize with 0 entries, since we dont know how many neighbors we have */
    gint result = igraph_vector_init(resultNeighborVertices, 0);
    if(result != IGRAPH_SUCCESS) {
        tgen_critical("igraph_vector_init return non-success code %i", result);
        g_free(resultNeighborVertices);
        return FALSE;
    }

    /* now get all incoming 1-hop neighbors of the given action */
    result = igraph_neighbors(g->graph, resultNeighborVertices, vertexIndex, IGRAPH_IN);
    if(result != IGRAPH_SUCCESS) {
        tgen_critical("igraph_neighbors return non-success code %i", result);
        igraph_vector_destroy(resultNeighborVertices);
        g_free(resultNeighborVertices);
        return NULL;
    }

    /* handle the results */
    glong totalIncoming = igraph_vector_size(resultNeighborVertices);
    tgen_debug("found %li neighbors to vertex %i", totalIncoming, (gint)vertexIndex);

    /* cleanup */
    igraph_vector_destroy(resultNeighborVertices);
    g_free(resultNeighborVertices);

    GError* error = NULL;
    TGenAction* a = tgenaction_newSynchronizeAction(totalIncoming, &error);

    if(a) {
        _tgengraph_storeAction(g, a, vertexIndex);
    }

    return error;
}
Пример #4
0
static void _tgenio_helper(TGenIO* io, TGenIOChild* child, gboolean in, gboolean out) {
    TGEN_ASSERT(io);
    g_assert(child);

    TGenEvent inEvents = TGEN_EVENT_NONE;

    /* check if we need read flag */
    if(in) {
        tgen_debug("descriptor %i is readable", child->descriptor);
        inEvents |= TGEN_EVENT_READ;
    }

    /* check if we need write flag */
    if(out) {
        tgen_debug("descriptor %i is writable", child->descriptor);
        inEvents |= TGEN_EVENT_WRITE;
    }

    /* activate the transfer */
    TGenEvent outEvents = child->notify(child->data, child->descriptor, inEvents);

    /* now check if we should update our epoll events */
    if(outEvents & TGEN_EVENT_DONE) {
        _tgenio_deregister(io, child->descriptor);
    } else if(inEvents != outEvents) {
        guint32 newEvents = 0;
        if(outEvents & TGEN_EVENT_READ) {
            newEvents |= EPOLLIN;
        }
        if(outEvents & TGEN_EVENT_WRITE) {
            newEvents |= EPOLLOUT;
        }

        struct epoll_event ee;
        memset(&ee, 0, sizeof(struct epoll_event));
        ee.events = newEvents;
        ee.data.fd = child->descriptor;

        gint result = epoll_ctl(io->epollD, EPOLL_CTL_MOD, child->descriptor, &ee);
        if(result != 0) {
            tgen_warning("epoll_ctl(): epoll %i descriptor %i returned %i error %i: %s",
                    io->epollD, child->descriptor, result, errno, g_strerror(errno));
        }
    }
}
Пример #5
0
static void _tgentransfer_onReadable(TGenTransfer* transfer) {
    TGEN_ASSERT(transfer);

    tgen_debug("active transfer %s is readable", _tgentransfer_toString(transfer));
    gsize startBytes = transfer->bytes.totalRead;

    /* first check if we need to read a command from the other end */
    if(!transfer->isCommander && transfer->state == TGEN_XFER_COMMAND) {
        _tgentransfer_readCommand(transfer);
    }

    if(transfer->isCommander && transfer->state == TGEN_XFER_RESPONSE) {
        _tgentransfer_readResponse(transfer);
    }

    /* check if we are responsible for reading payload bytes */
    if(transfer->type == TGEN_TYPE_GET && transfer->state == TGEN_XFER_PAYLOAD) {
        _tgentransfer_readPayload(transfer);
    }

    if(transfer->type == TGEN_TYPE_GET && transfer->state == TGEN_XFER_CHECKSUM) {
        _tgentransfer_readChecksum(transfer);
    }

    if(transfer->readBuffer ||
            (transfer->type == TGEN_TYPE_GET && transfer->state != TGEN_XFER_SUCCESS)) {
        /* we have more to read */
        transfer->events |= TGEN_EVENT_READ;
    } else {
        /* done reading */
        transfer->events &= ~TGEN_EVENT_READ;
    }

    gsize endBytes = transfer->bytes.totalRead;
    gsize totalBytes = endBytes - startBytes;
    tgen_debug("active transfer %s read %"G_GSIZE_FORMAT" more bytes",
            _tgentransfer_toString(transfer), totalBytes);

    if(totalBytes > 0) {
        transfer->time.lastProgress = g_get_monotonic_time();
    }
}
Пример #6
0
static void _tgentransfer_onWritable(TGenTransfer* transfer) {
    TGEN_ASSERT(transfer);

    tgen_debug("active transfer %s is writable", _tgentransfer_toString(transfer));
    gsize startBytes = transfer->bytes.totalWrite;

    /* first check if we need to send a command to the other end */
    if(transfer->isCommander && transfer->state == TGEN_XFER_COMMAND) {
        _tgentransfer_writeCommand(transfer);
    }

    if(!transfer->isCommander && transfer->state == TGEN_XFER_RESPONSE) {
        _tgentransfer_writeResponse(transfer);
    }

    /* check if we are responsible for writing payload bytes */
    if(transfer->type == TGEN_TYPE_PUT && transfer->state == TGEN_XFER_PAYLOAD) {
        _tgentransfer_writePayload(transfer);
    }

    if(transfer->type == TGEN_TYPE_PUT && transfer->state == TGEN_XFER_CHECKSUM) {
        _tgentransfer_writeChecksum(transfer);
    }

    if(transfer->writeBuffer ||
            (transfer->type == TGEN_TYPE_PUT && transfer->state == TGEN_XFER_PAYLOAD)) {
        /* we have more to write */
        transfer->events |= TGEN_EVENT_WRITE;
    } else {
        /* done writing */
        transfer->events &= ~TGEN_EVENT_WRITE;
    }

    gsize endBytes = transfer->bytes.totalWrite;
    gsize totalBytes = endBytes - startBytes;
    tgen_debug("active transfer %s wrote %"G_GSIZE_FORMAT" more bytes",
                _tgentransfer_toString(transfer), totalBytes);

    if(totalBytes > 0) {
        transfer->time.lastProgress = g_get_monotonic_time();
    }
}
Пример #7
0
GQueue* tgengraph_getNextActions(TGenGraph* g, TGenAction* action) {
    TGEN_ASSERT(g);

    /* given an action, get all of the next actions in the dependency graph */

    gpointer key = tgenaction_getKey(action);
    igraph_integer_t srcVertexIndex = (igraph_integer_t) GPOINTER_TO_INT(key);

    /* initialize a vector to hold the result neighbor vertices for this action */
    igraph_vector_t* resultNeighborVertices = g_new0(igraph_vector_t, 1);

    /* initialize with 0 entries, since we dont know how many neighbors we have */
    gint result = igraph_vector_init(resultNeighborVertices, 0);
    if(result != IGRAPH_SUCCESS) {
        tgen_critical("igraph_vector_init return non-success code %i", result);
        g_free(resultNeighborVertices);
        return FALSE;
    }

    /* now get all outgoing 1-hop neighbors of the given action */
    result = igraph_neighbors(g->graph, resultNeighborVertices, srcVertexIndex, IGRAPH_OUT);
    if(result != IGRAPH_SUCCESS) {
        tgen_critical("igraph_neighbors return non-success code %i", result);
        igraph_vector_destroy(resultNeighborVertices);
        g_free(resultNeighborVertices);
        return NULL;
    }

    /* handle the results */
    glong nVertices = igraph_vector_size(resultNeighborVertices);
    tgen_debug("found %li neighbors to vertex %i", nVertices, (gint)srcVertexIndex);

    GQueue* nextActions = g_queue_new();

    for (gint i = 0; i < nVertices; i++) {
        igraph_integer_t dstVertexIndex = igraph_vector_e(resultNeighborVertices, i);
        TGenAction* nextAction = _tgengraph_getAction(g, dstVertexIndex);
        if(nextAction) {
            g_queue_push_tail(nextActions, nextAction);
        }
    }

    /* cleanup */
    igraph_vector_destroy(resultNeighborVertices);
    g_free(resultNeighborVertices);

    return nextActions;
}
Пример #8
0
static GError* _tgengraph_parsePauseVertex(TGenGraph* g, const gchar* idStr,
        igraph_integer_t vertexIndex) {
    TGEN_ASSERT(g);

    const gchar* timeStr = (g->knownAttributes&TGEN_VA_TIME) ?
            VAS(g->graph, "time", vertexIndex) : NULL;

    tgen_debug("found vertex %li (%s), time=%s", (glong)vertexIndex, idStr, timeStr);

    GError* error = NULL;
    TGenAction* a = tgenaction_newPauseAction(timeStr, &error);

    if(a) {
        _tgengraph_storeAction(g, a, vertexIndex);
    }

    return error;
}
Пример #9
0
static TGenEvent _tgentransport_sendSocksInit(TGenTransport* transport) {
    TGEN_ASSERT(transport);

    /*
    1 socks init client --> server
    \x05 (version 5)
    \x01 (1 supported auth method)
    \x00 (method is "no auth")
    */
    gssize bytesSent = tgentransport_write(transport, "\x05\x01\x00", 3);
    g_assert(bytesSent == 3);

    transport->time.proxyInit = g_get_monotonic_time();
    tgen_debug("sent socks init to proxy %s", tgenpeer_toString(transport->proxy));

    _tgentransport_changeState(transport, TGEN_XPORT_PROXY_CHOICE);
    return TGEN_EVENT_READ;
}
Пример #10
0
static GError* _tgengraph_parseStartVertex(TGenGraph* g, const gchar* idStr,
        igraph_integer_t vertexIndex) {
    TGEN_ASSERT(g);

    const gchar* timeStr = (g->knownAttributes&TGEN_VA_TIME) ?
            VAS(g->graph, "time", vertexIndex) : NULL;
    const gchar* timeoutStr = (g->knownAttributes&TGEN_VA_TIMEOUT) ?
            VAS(g->graph, "timeout", vertexIndex) : NULL;
    const gchar* serverPortStr = (g->knownAttributes&TGEN_VA_SERVERPORT) ?
            VAS(g->graph, "serverport", vertexIndex) : NULL;
    const gchar* peersStr = (g->knownAttributes&TGEN_VA_PEERS) ?
            VAS(g->graph, "peers", vertexIndex) : NULL;
    const gchar* socksProxyStr = (g->knownAttributes&TGEN_VA_SOCKSPROXY) ?
            VAS(g->graph, "socksproxy", vertexIndex) : NULL;

    tgen_debug("validating action '%s' at vertex %li, time=%s timeout=%s serverport=%s socksproxy=%s peers=%s",
            idStr, (glong)vertexIndex, timeStr, timeoutStr, serverPortStr, socksProxyStr, peersStr);

    if(g->hasStartAction) {
        return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
                "only one start vertex is allowed in the action graph");
    }

    if(_tgengraph_hasSelfLoop(g, vertexIndex)) {
        return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
                "start vertex must not contain a self-loop");
    }

    GError* error = NULL;
    TGenAction* a = tgenaction_newStartAction(timeStr, timeoutStr, serverPortStr, peersStr, socksProxyStr, &error);

    if(a) {
        _tgengraph_storeAction(g, a, vertexIndex);
        g_assert(!g->hasStartAction);
        g->startActionVertexIndex = vertexIndex;
        g->hasStartAction = TRUE;
        if(tgenaction_getPeers(a)) {
            g->startHasPeers = TRUE;
        }
    }

    return error;
}
Пример #11
0
static gboolean _tgentransfer_getLine(TGenTransfer* transfer) {
    TGEN_ASSERT(transfer);

    /* create a new buffer if we have not done that yet */
    if(!transfer->readBuffer) {
        transfer->readBuffer = g_string_new(NULL);
    }

    gchar c;
    gssize bytes = 1;

    while(bytes > 0) {
        bytes = tgentransport_read(transfer->transport, &c, 1);

        if(bytes < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
            _tgentransfer_changeState(transfer, TGEN_XFER_ERROR);
            _tgentransfer_changeError(transfer, TGEN_XFER_ERR_READ);
            tgen_critical("read(): transport %s transfer %s error %i: %s",
                    tgentransport_toString(transfer->transport), _tgentransfer_toString(transfer),
                    errno, g_strerror(errno));
        } else if(bytes == 0) {
            _tgentransfer_changeState(transfer, TGEN_XFER_ERROR);
            _tgentransfer_changeError(transfer, TGEN_XFER_ERR_READ);
            tgen_critical("read(): transport %s transfer %s closed unexpectedly",
                    tgentransport_toString(transfer->transport), _tgentransfer_toString(transfer));
        } else if(bytes == 1) {
            transfer->bytes.totalRead += 1;
            if(c == '\n') {
                tgen_debug("finished receiving line: '%s'", transfer->readBuffer->str);
                return TRUE;
            }
            g_string_append_c(transfer->readBuffer, c);
        }
    }

    return FALSE;
}
Пример #12
0
static GError* _tgengraph_parseEndVertex(TGenGraph* g, const gchar* idStr,
        igraph_integer_t vertexIndex) {
    TGEN_ASSERT(g);

    /* the following termination conditions are optional */
    const gchar* timeStr = (g->knownAttributes&TGEN_VA_TIME) ?
            VAS(g->graph, "time", vertexIndex) : NULL;
    const gchar* countStr = (g->knownAttributes&TGEN_VA_COUNT) ?
            VAS(g->graph, "count", vertexIndex) : NULL;
    const gchar* sizeStr = (g->knownAttributes&TGEN_VA_SIZE) ?
            VAS(g->graph, "size", vertexIndex) : NULL;

    tgen_debug("found vertex %li (%s), time=%s count=%s size=%s",
            (glong)vertexIndex, idStr, timeStr, countStr, sizeStr);

    GError* error = NULL;
    TGenAction* a = tgenaction_newEndAction(timeStr, countStr, sizeStr, &error);

    if(a) {
        _tgengraph_storeAction(g, a, vertexIndex);
    }

    return error;
}
Пример #13
0
static GError* _tgengraph_parseGraphEdges(TGenGraph* g) {
    TGEN_ASSERT(g);

    tgen_debug("checking graph edges...");

    /* we will iterate through the edges */
    igraph_eit_t edgeIterator;

    gint result = igraph_eit_create(g->graph, igraph_ess_all(IGRAPH_EDGEORDER_ID), &edgeIterator);
    if(result != IGRAPH_SUCCESS) {
        return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
                "igraph_eit_create return non-success code %i", result);
    }

    /* count the edges as we iterate */
    igraph_integer_t edgeCount = 0;
    GError* error = NULL;

    while (!IGRAPH_EIT_END(edgeIterator)) {
        igraph_integer_t edgeIndex = IGRAPH_EIT_GET(edgeIterator);

        igraph_integer_t fromVertexIndex, toVertexIndex;

        gint result = igraph_edge(g->graph, edgeIndex, &fromVertexIndex, &toVertexIndex);
        if(result != IGRAPH_SUCCESS) {
            error = g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
                    "igraph_edge return non-success code %i", result);
            break;
        }

        const gchar* fromIDStr = (g->knownAttributes&TGEN_VA_ID) ?
                VAS(g->graph, "id", fromVertexIndex) : NULL;
        if(!fromIDStr) {
            error = g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_MISSING_ATTRIBUTE,
                    "found vertex %li with missing 'id' attribute", (glong)fromVertexIndex);
            break;
        }

        const gchar* toIDStr = (g->knownAttributes&TGEN_VA_ID) ?
                VAS(g->graph, "id", toVertexIndex) : NULL;
        if(!toIDStr) {
            error = g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_MISSING_ATTRIBUTE,
                    "found vertex %li with missing 'id' attribute", (glong)toVertexIndex);
            break;
        }

        tgen_debug("found edge %li from vertex %li (%s) to vertex %li (%s)",
                (glong)edgeIndex, (glong)fromVertexIndex, fromIDStr, (glong)toVertexIndex, toIDStr);

        const gchar* weightStr = (g->knownAttributes&TGEN_EA_WEIGHT) ?
                EAS(g->graph, "weight", edgeIndex) : NULL;
        if(weightStr != NULL) {
            if(g_ascii_strncasecmp(weightStr, "\0", (gsize) 1)) {
                gdouble weight = g_ascii_strtod(weightStr, NULL);
                _tgengraph_storeWeight(g, weight, edgeIndex);
            }
        }

        edgeCount++;
        IGRAPH_EIT_NEXT(edgeIterator);
    }

    igraph_eit_destroy(&edgeIterator);

    if(!error) {
        g->edgeCount = igraph_ecount(g->graph);
        if(g->edgeCount != edgeCount) {
            tgen_warning("igraph_vcount %f does not match iterator count %f", g->edgeCount, edgeCount);
        }

        tgen_info("%u graph edges ok", (guint) g->edgeCount);
    }

    return error;
}
Пример #14
0
static GError* _tgengraph_parseGraphProperties(TGenGraph* g) {
    TGEN_ASSERT(g);
    gint result = 0;

    tgen_debug("checking graph properties...");

    /* IGRAPH_WEAK means the undirected version of the graph is connected
     * IGRAPH_STRONG means a vertex can reach all others via a directed path */
    result = igraph_is_connected(g->graph, &(g->isConnected), IGRAPH_WEAK);
    if(result != IGRAPH_SUCCESS) {
        return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
                "igraph_is_connected return non-success code %i", result);
    }

    igraph_integer_t clusterCount;
    result = igraph_clusters(g->graph, NULL, NULL, &(g->clusterCount), IGRAPH_WEAK);
    if(result != IGRAPH_SUCCESS) {
        return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
                "igraph_clusters return non-success code %i", result);
    }

    /* it must be connected */
    if(!g->isConnected || g->clusterCount > 1) {
        return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
                "graph must be but is not connected");
    }

    g->isDirected = igraph_is_directed(g->graph);

    tgen_debug("checking graph attributes...");

    /* now check list of all attributes */
    igraph_strvector_t gnames, vnames, enames;
    igraph_vector_t gtypes, vtypes, etypes;
    igraph_strvector_init(&gnames, 25);
    igraph_vector_init(&gtypes, 25);
    igraph_strvector_init(&vnames, 25);
    igraph_vector_init(&vtypes, 25);
    igraph_strvector_init(&enames, 25);
    igraph_vector_init(&etypes, 25);

    result = igraph_cattribute_list(g->graph, &gnames, &gtypes, &vnames, &vtypes, &enames, &etypes);
    if(result != IGRAPH_SUCCESS) {
        return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
                "igraph_cattribute_list return non-success code %i", result);
    }

    gint i = 0;
    for(i = 0; i < igraph_strvector_size(&gnames); i++) {
        gchar* name = NULL;
        igraph_strvector_get(&gnames, (glong) i, &name);

        tgen_debug("found graph attribute '%s'", name);
    }
    for(i = 0; i < igraph_strvector_size(&vnames); i++) {
        gchar* name = NULL;
        igraph_strvector_get(&vnames, (glong) i, &name);

        tgen_debug("found vertex attribute '%s'", name);
        g->knownAttributes |= _tgengraph_vertexAttributeToFlag(name);
    }
    for(i = 0; i < igraph_strvector_size(&enames); i++) {
        gchar* name = NULL;
        igraph_strvector_get(&enames, (glong) i, &name);

        tgen_debug("found edge attribute '%s'", name);
        g->knownAttributes |= _tgengraph_edgeAttributeToFlag(name);
    }

    igraph_strvector_destroy(&gnames);
    igraph_vector_destroy(&gtypes);
    igraph_strvector_destroy(&vnames);
    igraph_vector_destroy(&vtypes);
    igraph_strvector_destroy(&enames);
    igraph_vector_destroy(&etypes);

    tgen_info("successfully verified graph properties and attributes");

    return NULL;
}
Пример #15
0
static GError* _tgengraph_parseGraphVertices(TGenGraph* g) {
    TGEN_ASSERT(g);

    tgen_debug("checking graph vertices...");

    /* we will iterate through the vertices */
    igraph_vit_t vertexIterator;

    gint result = igraph_vit_create(g->graph, igraph_vss_all(), &vertexIterator);
    if(result != IGRAPH_SUCCESS) {
        return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
                "igraph_vit_create return non-success code %i", result);
    }

    /* count the vertices as we iterate */
    igraph_integer_t vertexCount = 0;
    GError* error = NULL;

    while (!IGRAPH_VIT_END(vertexIterator)) {
        igraph_integer_t vertexIndex = (igraph_integer_t)IGRAPH_VIT_GET(vertexIterator);

        /* get vertex attributes: S for string and N for numeric */
        const gchar* idStr = (g->knownAttributes&TGEN_VA_ID) ?
                VAS(g->graph, "id", vertexIndex) : NULL;

        if(!idStr) {
            error = g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_MISSING_ATTRIBUTE,
                    "found vertex %li with missing action 'id' attribute", (glong)vertexIndex);
            break;
        }

        if(g_strstr_len(idStr, (gssize)-1, "start")) {
            error = _tgengraph_parseStartVertex(g, idStr, vertexIndex);
        } else if(g_strstr_len(idStr, (gssize)-1, "end")) {
            error = _tgengraph_parseEndVertex(g, idStr, vertexIndex);
        } else if(g_strstr_len(idStr, (gssize)-1, "pause")) {
            error = _tgengraph_parsePauseVertex(g, idStr, vertexIndex);
        } else if(g_strstr_len(idStr, (gssize)-1, "synchronize")) {
            error = _tgengraph_parseSynchronizeVertex(g, idStr, vertexIndex);
        } else if(g_strstr_len(idStr, (gssize)-1, "transfer")) {
            error = _tgengraph_parseTransferVertex(g, idStr, vertexIndex);
        } else if(g_strstr_len(idStr, (gssize)-1, "choose")) {
            error = _tgengraph_parseChooseVertex(g, idStr, vertexIndex);
        } else {
            error = g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
                    "found vertex %li (%s) with an unknown action id '%s'",
                    (glong)vertexIndex, idStr, idStr);
        }

        if(error) {
            break;
        }

        vertexCount++;
        IGRAPH_VIT_NEXT(vertexIterator);
    }

    /* clean up */
    igraph_vit_destroy(&vertexIterator);

    if(!g->startHasPeers && g->transferMissingPeers) {
        error = g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
                    "peers required in either the 'start' action, or *every* 'transfer' action");
    }

    if(!error) {
        g->vertexCount = igraph_vcount(g->graph);
        if(g->vertexCount != vertexCount) {
            tgen_warning("igraph_vcount %f does not match iterator count %f", g->vertexCount, vertexCount);
        }

        tgen_info("%u graph vertices ok", (guint) g->vertexCount);
    }

    return error;
}
Пример #16
0
static GError* _tgengraph_parseChooseVertex(TGenGraph* g, const gchar* idStr,
        igraph_integer_t vertexIndex) {
    TGEN_ASSERT(g);

    tgen_debug("found vertex %li (%s)", (glong)vertexIndex, idStr);

    GError* error = NULL;

    /* Assure the edges from this choose action have either all weights or no weights. Store in data */
    igraph_es_t edgeSelector;
    igraph_eit_t edgeIterator;

    gint result = igraph_es_incident(&edgeSelector, vertexIndex, IGRAPH_OUT);
    if(result != IGRAPH_SUCCESS) {
        return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, 
                "igraph_es_incident return non-success code %i", result);
    }

    result = igraph_eit_create(g->graph, edgeSelector, &edgeIterator);
    if(result != IGRAPH_SUCCESS) {
        return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, 
                "igraph_eit_create return non-success code %i", result);
    }

    /* Get initial case for first edge */
    igraph_integer_t edgeIndex = IGRAPH_EIT_GET(edgeIterator);
    gdouble* weight = _tgengraph_getWeight(g, edgeIndex);
    gboolean lastWeight;
    gdouble totalWeight = 0.0;
    if(weight != NULL) {
        lastWeight = TRUE;
        totalWeight += *weight;
    }
    else {
        lastWeight = FALSE;
    }
    IGRAPH_EIT_NEXT(edgeIterator);

    while (!IGRAPH_EIT_END(edgeIterator)) {
        edgeIndex = IGRAPH_EIT_GET(edgeIterator);
        gdouble* weight = _tgengraph_getWeight(g, edgeIndex);
        gboolean thisWeight;

        if(weight != NULL) {
            thisWeight = TRUE;
            totalWeight += *weight;
        }
        else {
            thisWeight = FALSE;
        }

        /* Assure weights is still constant */
        if (thisWeight != lastWeight){
            igraph_es_destroy(&edgeSelector);
            igraph_eit_destroy(&edgeIterator);
            return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
                    "choose action must have all weights or no weights");
        }

        lastWeight = thisWeight;
        IGRAPH_EIT_NEXT(edgeIterator);
    }
    TGenAction* a = tgenaction_newChooseAction(&error, lastWeight, totalWeight);

    /* clean up */
    igraph_es_destroy(&edgeSelector);
    igraph_eit_destroy(&edgeIterator);

    if(a) {
        _tgengraph_storeAction(g, a, vertexIndex);
    }

    return error;
}
Пример #17
0
static TGenEvent _tgentransport_sendSocksRequest(TGenTransport* transport) {
    /*
    3 socks request client --> server
    \x05 (version 5)
    \x01 (tcp stream)
    \x00 (reserved)

    the client asks the server to connect to a remote

    3a ip address client --> server
    \x01 (ipv4)
    in_addr_t (4 bytes)
    in_port_t (2 bytes)

    3b hostname client --> server
    \x03 (domain name)
    \x__ (1 byte name len)
    (name)
    in_port_t (2 bytes)
    */

    /* prefer name mode if we have it, and let the proxy lookup IP as needed */
    const gchar* name = tgenpeer_getName(transport->remote);
    if(name && g_str_has_suffix(name, ".onion")) { // FIXME remove suffix matching to have proxy do lookup for us
        /* case 3b - domain name */
        glong nameLength = g_utf8_strlen(name, -1);
        guint8 guint8max = -1;
        if(nameLength > guint8max) {
            nameLength = (glong)guint8max;
            tgen_warning("truncated name '%s' in socks request from %i to %u bytes",
                    name, nameLength, (guint)guint8max);
        }

        in_addr_t port = tgenpeer_getNetworkPort(transport->remote);

        gchar buffer[nameLength+8];
        memset(buffer, 0, nameLength+8);

        g_memmove(&buffer[0], "\x05\x01\x00\x03", 4);
        g_memmove(&buffer[4], &nameLength, 1);
        g_memmove(&buffer[5], name, nameLength);
        g_memmove(&buffer[5+nameLength], &port, 2);

        gssize bytesSent = tgentransport_write(transport, buffer, nameLength+7);
        g_assert(bytesSent == nameLength+7);
    } else {
        tgenpeer_performLookups(transport->remote); // FIXME remove this to have proxy do lookup for us
        /* case 3a - IPv4 */
        in_addr_t ip = tgenpeer_getNetworkIP(transport->remote);
        in_addr_t port = tgenpeer_getNetworkPort(transport->remote);

        gchar buffer[16];
        memset(buffer, 0, 16);

        g_memmove(&buffer[0], "\x05\x01\x00\x01", 4);
        g_memmove(&buffer[4], &ip, 4);
        g_memmove(&buffer[8], &port, 2);

        gssize bytesSent = tgentransport_write(transport, buffer, 10);
        g_assert(bytesSent == 10);
    }

    transport->time.proxyRequest = g_get_monotonic_time();
    tgen_debug("requested connection from %s through socks proxy %s to remote %s",
            tgenpeer_toString(transport->local), tgenpeer_toString(transport->proxy), tgenpeer_toString(transport->remote));

    _tgentransport_changeState(transport, TGEN_XPORT_PROXY_RESPONSE);
    return TGEN_EVENT_READ;
}