Example #1
0
//Main
int main(int argc, char *argv[])
{
    //Get args
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <snapshot_file>\n", argv[0]);
        return 1;
    }
    snap_path = argv[1];

    //Allocate memory
    fprintf(stderr, "Allocating arena with size %.2f MBytes ...\n", (float)m / CHAR_BIT / MEGA);
    Bloom = malloc( (m + ( CHAR_BIT - 1)) / CHAR_BIT ); // Ceil byte length: bytes = bits + 7 / 8


    //Load or create snapshot file
    if (!access(snap_path, F_OK)) {
        fputs("Loading snapshot...\n", stderr);
        if (LoadSnap(Bloom, snap_path)) {
            fputs("Unable to load snapshot!\n", stderr);
            return -1;
        }
        fputs("Snapshot loaded.\n", stderr);
    } else {
        fputs("Initializing new file storage...\n", stderr);
        size_t shouldwrite = (m + (CHAR_BIT - 1)) / CHAR_BIT;
        memset(Bloom, 0, shouldwrite); 

        if (SaveSnap(Bloom, snap_path)) {
            fputs("Unable to save initial snapshot!\n", stderr);
            return -1;
        }
        fputs("Initial snapshot written.\n", stderr);
    }


    void OnReq(struct evhttp_request *req, void *arg)
    {
        struct evbuffer *OutBuf = evhttp_request_get_output_buffer(req);
        if (!OutBuf) {
            evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf);
            return;
        }
        struct evkeyvalq *Headers = evhttp_request_get_output_headers(req);
        if (!Headers) {
            evhttp_send_reply(req, HTTP_INTERNAL, "Internal Error", OutBuf);
            return;
        }
        const struct evhttp_uri *HTTPURI =  evhttp_request_get_evhttp_uri(req);
        if (!HTTPURI) {
            evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf);
            return;
        }
        const char *path =  evhttp_uri_get_path(HTTPURI);
        if (!path) {
            evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf);
        }
        const char *query_string = evhttp_uri_get_query(HTTPURI);
        if (!query_string) {
            evhttp_send_reply(req, HTTP_BADREQUEST, "Element Required", OutBuf);
            return;
        }
        struct evkeyvalq params;
        evhttp_parse_query_str(query_string, &params);
        const char *element = evhttp_find_header(&params, "e");
        if (!element) {
            evhttp_clear_headers(&params);
            evhttp_send_reply(req, HTTP_BADREQUEST, "Element Required", OutBuf);
            return;
        }

        int i;
        const char* (*Operation)(bloom_cell *, size_t []) = NULL;
        for (i=0; i< sizeof HandlerTable/ sizeof HandlerTable[0] ; i++)
            if (strncmp(HandlerTable[i][0], path, STR_MAX) == 0) {
                Operation = HandlerTable[i][1];
                break;
            }
        if (!Operation) {
            evhttp_clear_headers(&params);
            evhttp_send_reply(req, HTTP_NOTFOUND, "Not Found", OutBuf);
            return;
        }

        const char *response = Operation(Bloom, Hashes(element));

        evhttp_add_header(Headers, MIME_TYPE);
        evbuffer_add_printf(OutBuf, response);
        evhttp_send_reply(req, HTTP_OK, "OK", OutBuf);
        evhttp_clear_headers(&params);
    };

    if (!(base = event_base_new()))
        crash("Couldn't create an event_base: exiting\n", -1);

    if (!(http = evhttp_new(base)))
        crash("Couldn't create evhttp. Exiting.\n", -1);
    evhttp_set_gencb(http, OnReq, NULL);

    if (!(handle = evhttp_bind_socket_with_handle(http, BIND_ADDRESS, BIND_PORT)))
        crash("couldn't bind to port 8888. Exiting.\n", -1);

    if (signal(SIGINT, term_handler) == SIG_ERR)
        crash("Unable to set SIGINT handler!", -1);

    if (signal(SIGTERM, term_handler) == SIG_ERR)
        crash("Unable to set SIGTERM handler!", -1);

    if (signal(SIGCHLD, child_collector) == SIG_ERR)
        crash("Unable to set SIGCHLD handler!", -1);
    
    //This signal handled by event loop in order to avoid malloc deadlock
    if ((dump_event = evsignal_new(base, SIGUSR1, dump_handler, NULL)) == NULL)
        crash("Unable to create SIGUSR1 handler!", -1);
    else 
        if (event_add(dump_event, NULL) == -1)
            crash("Unable to add SIGUSR1 handler!", -1);

    if (event_base_dispatch(base) == -1)
        crash("Failed to run message loop.\n", -1);

    fputs("Exiting...\n", stderr);
    SaveSnap(Bloom, snap_path);
    evhttp_del_accept_socket(http, handle);
    evhttp_free(http);
    event_free(dump_event);
    event_base_free(base);
    free(Bloom);
    return 0;
}
Example #2
0
	/** Main Connection Thread. Handles all the networking to allow
	Mining threads the most performance. **/
	void ServerConnection::ServerThread()
	{

		/** Don't begin until all mining threads are Created. **/
		while (THREADS.size() != nThreads)
			Sleep(1000);


		/** Initialize the Server Connection. **/
		CLIENT = new LLP::Miner(IP, PORT);


		/** Initialize a Timer for the Hash Meter. **/
		TIMER.Start();
		unsigned int nTimerWait = 2;

		unsigned int nBestHeight = 0;
		loop
		{
			try
			{
				/** Run this thread at 1 Cycle per Second. **/
				Sleep(50);


				/** Attempt with best efforts to keep the Connection Alive. **/
				if (!CLIENT->Connected() || CLIENT->Errors())
				{
					ResetThreads();

					if (!CLIENT->Connect())
						continue;
					else
						CLIENT->SetChannel(2);
				}


				/** Check the Block Height. **/
				unsigned int nHeight = CLIENT->GetHeight(5);
				if (nHeight == 0)
				{
					printf("[MASTER] Failed to Update Height\n");
					CLIENT->Disconnect();
					continue;
				}

				/** If there is a new block, Flag the Threads to Stop Mining. **/
				if (nHeight != nBestHeight)
				{
					nBestHeight = nHeight;
					printf("[MASTER] Coinshield Network: New Block %u\n", nHeight);

					ResetThreads();
				}

				/** Rudimentary Meter **/
				if (TIMER.Elapsed() > nTimerWait)
				{
					double  Elapsed = (double)TIMER.ElapsedMilliseconds();
					unsigned long long nHashes = Hashes();
					//double khash = ((double)nHashes)/Elapsed;
					unsigned long long khash = nHashes / TIMER.ElapsedMilliseconds();
					unsigned int nDifficulty = THREADS[0]->GetBlock()->GetBits();
					nDifficulty = nDifficulty & 0xffffff;
					CBigNum target;
					target.SetCompact(nDifficulty);

					//double diff = (double)(0xFFFF * pow(2, 208)) / (double)nDifficulty;
					printf("[METERS] %llu kHash/s | Height = %u | Diff= %.08f\n", khash, nBestHeight, 1.0 / (double)nDifficulty);

					TIMER.Reset();
					if (nTimerWait == 2)
						nTimerWait = 20;
				}


				/** Check if there is work to do for each Miner Thread. **/
				for (unsigned int nIndex = 0; nIndex < THREADS.size(); nIndex++)
				{

					/** Attempt to get a new block from the Server if Thread needs One. **/

					if (THREADS[nIndex]->GetIsNewBlock())
					{
						/** Retrieve new block from Server. **/
						/** Delete the Block Pointer if it Exists. **/
						CBlock* pBlock = THREADS[nIndex]->GetBlock();
						if (pBlock != NULL)
						{
							delete(pBlock);
						}

						/** Retrieve new block from Server. **/
						pBlock = CLIENT->GetBlock(5);


						/** If the block is good, tell the Mining Thread its okay to Mine. **/
						if (pBlock)
						{
							THREADS[nIndex]->SetIsBlockFound(false);
							THREADS[nIndex]->SetIsNewBlock(false);
							THREADS[nIndex]->SetBlock(pBlock);
							THREADS[nIndex]->SetHashes(0); // reset hash count

						}

						/** If the Block didn't come in properly, Reconnect to the Server. **/
						else
						{
							CLIENT->Disconnect();

							break;
						}

					}

					/** Submit a block from Mining Thread if Flagged. **/
					else if (THREADS[nIndex]->GetIsBlockFound())
					{

						//							
						/** Attempt to Submit the Block to Network. **/
						unsigned char RESPONSE = CLIENT->SubmitBlock(THREADS[nIndex]->GetBlock()->GetMerkleRoot(), THREADS[nIndex]->GetBlock()->GetNonce(), 10);
						double  Elapsed = (double)TIMER.ElapsedMilliseconds();
						double  nHashes = THREADS[nIndex]->GetHashes();
						double khash = nHashes / Elapsed;
						Hashes();
						TIMER.Reset();
						if (RESPONSE == 200)
							printf("[MASTER] Block Found by %s on thread %d                   %.1f kHash/s (accepted) Yay !!!\n", device_name[nIndex], nIndex, khash);
						else if (RESPONSE == 201)
						{

							printf("[MASTER] Block Found by %s on thread %d                  %.1f kHash/s (rejected) Booo !!!\n", device_name[nIndex], nIndex, khash);
							THREADS[nIndex]->SetIsNewBlock(true);
							THREADS[nIndex]->SetIsBlockFound(false);
						}
						else
						{
							printf("[MASTER] Failure to Submit Block. Reconnecting...\n");
							CLIENT->Disconnect();
						}

						break;


					}
				}
			}

			catch (std::exception& e)
			{
				printf("%s\n", e.what());
			}
		}

	};
//Main Connection Thread. Handles all the networking to allow
//Mining threads the most performance.
void SKServerConnection::ServerThread()
{
	/** Don't begin until all mining threads are Created. **/
	while ((m_vecTHREADS.size() != m_nThreads) && !m_bIsShutDown)
		Sleep(1000);

	/** Initialize the Server Connection. **/
	m_pCLIENT = new LLP::Miner(m_szIP, m_szPORT);

	/** Initialize a Timer for the Hash Meter. **/
	m_tTIMER.Start();
	m_totalTIMER.Start();

	m_nBestHeight = 0;
	m_nNewBlocks = 0;
	loop
	{
		if (m_bIsShutDown)
		{
			break;
		}

		try
		{
			/** Run this thread at 1 Cycle per Second. **/
			Sleep(1000);

			if (!m_bIsEnabled)
			{
				continue;
			}

			/** Attempt with best efforts to keep the Connection Alive. **/
			if (!m_pCLIENT->Connected() || m_pCLIENT->Errors())
			{
				if (!m_pCLIENT->Connect())
					continue;

				/** Send to the server the Channel we will be Mining For. **/
				else
					m_pCLIENT->SetChannel(2);
			}

			/** Check the Block Height. **/
			unsigned int nHeight = m_pCLIENT->GetHeight(5);
			if (nHeight == 0)
			{
				printf("Failed to Update Height...\n");
				m_pCLIENT->Disconnect();
				continue;
			}

			/** If there is a new block, Flag the Threads to Stop Mining. **/
			if (nHeight != m_nBestHeight)
			{
				m_nBestHeight = nHeight;
				m_nNewBlocks++;

				printf("[MASTER] Coinshield Network | New Block %u\n", nHeight);

				ResetThreads();
			}


			/** Rudimentary Meter **/
			if (m_tTIMER.Elapsed() > 10)
			{
				//unsigned int nElapsed = m_tTIMER.ElapsedMilliseconds();
				//unsigned int nHashes = Hashes();
				double KHASH = Hashes();
				
				//double KHASH = (double)nHashes / nElapsed;
				printf("[METERS] %f KHash/s | Height = %u\n", KHASH, m_nBestHeight);

				m_tTIMER.Reset();
			}


			/** Check if there is work to do for each Miner Thread. **/
			for (int nIndex = 0; nIndex < m_vecTHREADS.size(); nIndex++)
			{
				if (m_bIsShutDown)
				{
					break;
				}

				if (!m_vecTHREADS[nIndex]->GetMinerData()->GetGPUData()->GetGPUSetting()->GetIsEnabled())
				{
					continue;
				}				

				/** Attempt to get a new block from the Server if Thread needs One. **/
				if (m_vecTHREADS[nIndex]->GetIsNewBlock())
				{
					/** Delete the Block Pointer if it Exists. **/
					Core::CBlock* pBlock = m_vecTHREADS[nIndex]->GetMinerData()->GetBlock();
					if (pBlock != NULL)
					{
						delete(pBlock);
						pBlock = NULL;
					}

					/** Retrieve new block from Server. **/
					m_pCLIENT->SetChannel(2);
					pBlock = m_pCLIENT->GetBlock(5);

					/** If the block is good, tell the Mining Thread its okay to Mine. **/
					if (pBlock && pBlock->GetChannel() == 2)
					{
						m_vecTHREADS[nIndex]->SetIsNewBlock(false);
						m_vecTHREADS[nIndex]->SetIsBlockFound(false);
						m_vecTHREADS[nIndex]->GetMinerData()->SetBlock(pBlock);
					}
					/** If the Block didn't come in properly, Reconnect to the Server. **/
					else
					{
						m_pCLIENT->Disconnect();
					}

				}
				/** Submit a block from Mining Thread if Flagged. **/
				else if (m_vecTHREADS[nIndex]->GetIsBlockFound())
				{
					/** Attempt to Submit the Block to Network. **/

					unsigned char RESPONSE = m_pCLIENT->SubmitBlock(m_vecTHREADS[nIndex]->GetMinerData()->GetBlock()->GetMerkleRoot(), m_vecTHREADS[nIndex]->GetMinerData()->GetBlock()->GetNonce(), 30);
					printf("[MASTER] Hash Found on Miner Thread %i\n", nIndex);

					unsigned long long truc = m_vecTHREADS[nIndex]->GetMinerData()->GetBlock()->GetNonce();
					printf("[MASTER] nonce %08x %08x\n", (uint32_t)(truc >> 32)), (uint32_t)(truc & 0xFFFFFFFFULL);

					/** Check the Response from the Server.**/
					if (RESPONSE == 200)
					{
						printf("[MASTER] Block Accepted By Coinshield Network.\n");

						m_vecTHREADS[nIndex]->SetBlocksFound(m_vecTHREADS[nIndex]->GetBlocksFound() + 1);
					}
					else if (RESPONSE == 201)
					{
						printf("[MASTER] Block Rejected by Coinshield Network.\n");

						m_vecTHREADS[nIndex]->SetRejected(m_vecTHREADS[nIndex]->GetRejected() + 1);
						m_vecTHREADS[nIndex]->SetIsNewBlock(true);
						m_vecTHREADS[nIndex]->SetIsBlockFound(false);
					}
					/** If the Response was Incomplete, Reconnect to Server and try to Submit Block Again. **/
					else
					{
						printf("[MASTER] Failure to Submit Block. Reconnecting...\n");
						m_pCLIENT->Disconnect();
					}

					break;                           
				}
			}
		}
		catch (std::exception& e)
		{ 
			std::cout << e.what() << std::endl;
		}
	}

	if (m_bIsShutDown)
	{
		for (size_t index = 0; index < m_vecTHREADS.size(); ++index)
		{
			m_vecTHREADS[index]->SetIsShuttingDown(true);

			while (!m_vecTHREADS[index]->GetDidShutDown()){}
		}

		m_bDidShutDown = true;
	}
}