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; }