Ejemplo n.º 1
0
void torflow_init(TorFlow* tf, TorFlowEventCallbacks* eventHandlers,
		ShadowLogFunc slogf, ShadowCreateCallbackFunc scbf,
		in_port_t controlPort, in_port_t socksPort, gint workerID) {
	g_assert(tf);
	g_assert(eventHandlers);

	tf->internal = g_new0(TorFlowInternal, 1);

	/* use epoll to asynchronously watch events for all of our sockets */
	tf->internal->epolld = epoll_create(1);
	if(tf->internal->epolld == -1) {
		tf->_base.slogf(SHADOW_LOG_LEVEL_ERROR, tf->_base.id,
				"Error in main epoll_create");
		close(tf->internal->epolld);
		return;
	}

	tf->internal->netSocksPort = socksPort;
	tf->internal->downloads = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) _torflow_freeDownload);

	/* store the child events */
	TorFlowEventCallbacks events = *eventHandlers;
	tf->internal->eventHandlers = events;
	/* intercept onFree so we can properly free our data */
	events.onFree = (FreeFunc) _torflow_onFree;

	torflowbase_init((TorFlowBase*)tf, &events, slogf, scbf, controlPort, tf->internal->epolld, workerID);
}
TorFlowManager* torflowmanager_new(gint argc, gchar* argv[], ShadowLogFunc slogf, ShadowCreateCallbackFunc scbf) {
	g_assert(slogf);
	g_assert(scbf);

	if(argc != 9) {
		slogf(SHADOW_LOG_LEVEL_WARNING, __FUNCTION__, USAGE);
		return NULL;
	}

	/* argv[0] is the 'program name' and should be ignored */
	gchar* v3bwPath = argv[1];
	gint pausetime = atoi(argv[2]);
	gint numWorkers = atoi(argv[3]);

	if(numWorkers < 1) {
		slogf(SHADOW_LOG_LEVEL_WARNING, __FUNCTION__,
            "Invalid number of torflow workers (%d). torflow will not operate.", numWorkers);
		return NULL;
	}

	gint slicesize = atoi(argv[4]);
	gdouble nodeCap = atof(argv[5]);

	gint hostControlPort = atoi(argv[6]);
	g_assert(hostControlPort <= G_MAXUINT16); // TODO log error instead
    in_port_t netControlPort = htons((in_port_t)hostControlPort);

    gint hostSocksPort = atoi(argv[7]);
    g_assert(hostSocksPort <= G_MAXUINT16); // TODO log error instead
    in_port_t netSocksPort = htons((in_port_t)hostSocksPort);

    /* get file server infos */
    GQueue* fileservers = g_queue_new();
    gchar** fsparts = g_strsplit(argv[8], ",", 0);
    gchar* fspart = NULL;
    for(gint i = 0; (fspart = fsparts[i]) != NULL; i++) {
        gchar** parts = g_strsplit(fspart, ":", 0);
        g_assert(parts[0] && parts[1]);

        /* the server domain name */
        gchar* name = parts[0];

        /* port in host order */
        gchar* hostFilePortStr = parts[1];
        gint hostFilePort = atoi(hostFilePortStr);
        g_assert(hostFilePort <= G_MAXUINT16); // TODO log error instead
        in_port_t netFilePort = htons((in_port_t)hostFilePort);

        TorFlowFileServer* fs = torflowfileserver_new(name, netFilePort);
        g_assert(fs);
        g_queue_push_tail(fileservers, fs);
        g_strfreev(parts);

        slogf(SHADOW_LOG_LEVEL_INFO, __FUNCTION__,
                "parsed file server %s at %s:%u",
                torflowfileserver_getName(fs),
                torflowfileserver_getHostIPStr(fs),
                ntohs(torflowfileserver_getNetPort(fs)));
    }
    g_strfreev(fsparts);

    g_assert(g_queue_get_length(fileservers) > 0); // TODO log error instead

    /* use epoll to asynchronously watch events for all of our sockets */
    gint mainEpollDescriptor = epoll_create(1);
    g_assert(mainEpollDescriptor > 0); // TODO log error instead

	TorFlowManager* tfm = g_new0(TorFlowManager, 1);
	tfm->slogf = slogf;
	tfm->scbf = scbf;
	tfm->workers = numWorkers;
	tfm->ed = mainEpollDescriptor;
	tfm->slicesize = slicesize;

	tfm->AllRelaysByFingerprint = g_hash_table_new_full(g_str_hash,
	        g_str_equal, NULL, (GDestroyNotify)_torflowmanager_freeRelay);
	tfm->currentSlices = g_queue_new();

    /* now start our controller to fetch descriptors */
	tfm->baseED = epoll_create(1);
	g_assert(tfm->baseED > 0); // TODO log error
	torflowutil_epoll(tfm->ed, tfm->baseED, EPOLL_CTL_ADD, EPOLLIN, tfm->slogf);
    TorFlowEventCallbacks handlers;
    memset(&handlers, 0, sizeof(TorFlowEventCallbacks));
    handlers.onBootstrapComplete = (BootstrapCompleteFunc) _torflowmanager_onBootstrapComplete;
    handlers.onDescriptorsReceived = (DescriptorsReceivedFunc) _torflowmanager_onDescriptorsReceived;
    torflowbase_init(&tfm->_base, &handlers, slogf, scbf, netControlPort, tfm->baseED, 0);
    torflowbase_start(&tfm->_base);

    /* helper to manage stat reports and create v3bw files */
    tfm->tfa = torflowaggregator_new(slogf, v3bwPath, nodeCap);

    /* workers that will probe the relays */
    tfm->probers = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) torflowbase_free);

    for(gint i = 1; i <= numWorkers; i++) {
        /* get the next fileserver */
        TorFlowFileServer* probeFileServer = g_queue_pop_head(fileservers);

        TorFlowProber* prober = torflowprober_new(slogf, scbf, tfm, i, numWorkers, pausetime,
                netControlPort, netSocksPort, probeFileServer);
        g_assert(prober); // TODO log error instead

        /* make sure we watch the prober events on our main epoll */
        gint proberED = torflow_getEpollDescriptor((TorFlow*)prober);
        torflowutil_epoll(tfm->ed, proberED, EPOLL_CTL_ADD, EPOLLIN, tfm->slogf);

        /* store the prober by its unique epoll descriptor */
        g_hash_table_replace(tfm->probers, GINT_TO_POINTER(proberED), prober);

        /* reuse the file server in round robin fashion */
        g_queue_push_tail(fileservers, probeFileServer);
    }

    /* the used file servers have been reffed by the probers;
     * the rest will be safely freed */
    g_queue_free_full(fileservers, (GDestroyNotify)torflowfileserver_unref);

    tfm->slogf(SHADOW_LOG_LEVEL_MESSAGE, __FUNCTION__,
                    "started torflow with %i workers on control port %i and socks port %i",
                    numWorkers, hostControlPort, hostSocksPort);

    return tfm;
}