clientMain.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /**
  2. * clientMain.cpp
  3. * - compiles to bin/client
  4. * - runs a client program for experiments with PRSONA
  5. *
  6. * Stan Gurtler
  7. */
  8. #include <iostream>
  9. #include <fstream>
  10. #include "networkClient.hpp"
  11. using namespace std;
  12. /**
  13. * This program (bin/client) expects to be called as follows:
  14. * `bin/client <id> <output> <servers_are_malicious>`
  15. *
  16. * <id> - a name for this instance, which comes with a config file identifying
  17. * its IP address and port
  18. * <output> - a string that will name the file in which outputs for this run of
  19. * the program will be written (that is, timings and traffic data)
  20. * <lambda> - a positive integer that determines the absolute soundness parameter
  21. * for batched proofs
  22. * <servers_are_malicious> - a bool (given as T/t or F/f)
  23. * which is true when servers are in malicious security
  24. * and false when they are in HBC security
  25. */
  26. int main(int argc, char *argv[])
  27. {
  28. /*
  29. * PRELIMINARY SETUP CODE
  30. */
  31. initialize_prsona_classes();
  32. #if USE_SSL
  33. mg_init_library(MG_FEATURES_SSL);
  34. #else
  35. mg_init_library(0);
  36. #endif
  37. // The id effectively tells the client what ip/port it is
  38. string id = "";
  39. if (argc > 1)
  40. id = argv[1];
  41. string output = "default";
  42. if (argc > 2)
  43. output = argv[2];
  44. string outputDir = "out/" + output + "/" + id;
  45. int mkdirOut = system(("mkdir -p " + outputDir).c_str());
  46. mutex voteOutputMtx;
  47. string voteOutputFilename = outputDir + "/vote.out";
  48. mutex repProofOutputMtx;
  49. string repProofOutputFilename = outputDir + "/repProver.out";
  50. mutex repVerifyOutputMtx;
  51. string repVerifyOutputFilename = outputDir + "/repVerifier.out";
  52. // Default to not doing proof batching if not specified
  53. size_t lambda = 0;
  54. if (argc > 3)
  55. lambda = atoi(argv[3]);
  56. if (lambda > 0)
  57. PrsonaBase::set_lambda(lambda);
  58. // Default to malicious security if not specified
  59. bool maliciousServers = true;
  60. if (argc > 4)
  61. maliciousServers = argv[4][0] == 't' || argv[4][0] == 'T';
  62. // Set malicious flags where necessary
  63. if (maliciousServers)
  64. PrsonaBase::set_server_malicious();
  65. // This seed is used to generate temp filenames and decide which server to make requests to at any step.
  66. string seedStr;
  67. if (id.empty())
  68. seedStr = "default-client";
  69. else
  70. {
  71. seedStr = id;
  72. seedStr += "-" + output;
  73. seedStr += "-client";
  74. }
  75. seed_seq seed(seedStr.begin(), seedStr.end());
  76. default_random_engine rng(seed);
  77. vector<string> serverIPs, clientIPs;
  78. vector<int> serverPorts, clientPorts;
  79. string selfIP, selfPortStr;
  80. int selfPort = 0;
  81. string configDir = "cfg/" + output;
  82. // Read in from config files the server locations
  83. load_multiple_instances_config(serverIPs, serverPorts, (configDir + "/serverIPs.cfg").c_str());
  84. // And now the client locations
  85. load_multiple_instances_config(clientIPs, clientPorts, (configDir + "/clientIPs.cfg").c_str());
  86. // Finally, read in the ip/port corresponding to the id that this instance was given
  87. string selfConfigFilename = configDir + "/selfIP";
  88. if (!id.empty())
  89. {
  90. selfConfigFilename += "-";
  91. selfConfigFilename += id;
  92. }
  93. selfConfigFilename += ".cfg";
  94. load_single_instance_config(selfIP, selfPortStr, selfPort, selfConfigFilename.c_str());
  95. size_t numServers = serverIPs.size();
  96. size_t numClients = clientIPs.size();
  97. uniform_int_distribution<size_t> distribution(0, numServers - 1);
  98. const char *options[] = {"listening_ports", selfPortStr.c_str(), 0};
  99. CivetServer server(options);
  100. /*
  101. * CLIENT SETUP CODE
  102. */
  103. struct synchronization_tool exitSync;
  104. unique_lock<mutex> exitLock(exitSync.mtx);
  105. cout << "[" << seedStr << "] Establishing PRSONA client with the following parameters: " << endl;
  106. cout << "[" << seedStr << "] " << numServers << " PRSONA servers" << endl;
  107. cout << "[" << seedStr << "] " << numClients << " PRSONA clients" << endl;
  108. cout << "[" << seedStr << "] " << "Proof batching " << (lambda > 0 ? "IS" : "is NOT") << " in use." << endl;
  109. if (lambda > 0)
  110. cout << "[" << seedStr << "] Batch parameter: " << lambda << endl;
  111. cout << "[" << seedStr << "] Servers are set to " << (maliciousServers ? "MALICIOUS" : "HBC") << " security" << endl;
  112. cout << "[" << seedStr << "] This client is at IP address: " << selfIP << ":" << selfPort << endl;
  113. cout << endl;
  114. cout << "[" << seedStr << "] Creating PRSONA client object." << endl;
  115. PrsonaClient *prsonaClient = create_client(rng, serverIPs, serverPorts, numServers);
  116. cout << "[" << seedStr << "] Setting up handlers for client." << endl;
  117. // Main handler (in clients, only used for verifying reputation proofs)
  118. PrsonaClientWebSocketHandler wsHandler(rng, prsonaClient, serverIPs, serverPorts, repVerifyOutputMtx, repVerifyOutputFilename);
  119. server.addWebSocketHandler("/ws", wsHandler);
  120. // Exit handler (allows client to be brought down by making correct GET request)
  121. exitSync.val = 0;
  122. exitSync.val2 = 0;
  123. RemoteControlHandler exitHandler(&exitSync, "Client coming down!");
  124. server.addHandler(EXIT_URI, exitHandler);
  125. // This handler tells the orchestrator when the client has finished an assigned task
  126. ClientReadyHandler clientReadyHandler(&exitSync);
  127. server.addHandler(CLIENT_READY_URI, clientReadyHandler);
  128. // Make-vote handler (allows orchestrator to cause this client to make a new, random vote)
  129. AltRemoteControlHandler triggerVoteHandler(CLIENT_MAKE_VOTE, &exitSync, "Client will make new votes!");
  130. server.addHandler(TRIGGER_VOTE_URI, triggerVoteHandler);
  131. // Make-reputation handler (allows orchestrator to cause this client to make a new reputation proof, and specifies which other client to give it to)
  132. AltRemoteControlHandler triggerRepHandler(CLIENT_MAKE_REP_PROOF, &exitSync, "Client will make reputation proof!");
  133. server.addHandler(TRIGGER_REP_URI, triggerRepHandler);
  134. /*
  135. * MAIN CLIENT LOOP CODE
  136. */
  137. cout << "[" << seedStr << "] Entering main ready loop." << endl;
  138. while (!exitSync.val)
  139. {
  140. // exitSync.val controls when an exit is signaled.
  141. // exitSync.val2 controls when making a vote or making a reputation proof is signaled
  142. while (!exitSync.val && !exitSync.val2)
  143. exitSync.cv.wait(exitLock);
  144. size_t whichServer;
  145. string fullQuery, target;
  146. size_t colonLocation;
  147. int targetPort;
  148. // exitSync.val2 is set by the make-vote and make-reputation handlers, but will be 0 in the event of signaling an exit
  149. switch (exitSync.val2)
  150. {
  151. case CLIENT_MAKE_VOTE:
  152. cout << "[" << seedStr << "] Making new vote row." << endl;
  153. whichServer = distribution(rng);
  154. make_vote(rng, prsonaClient, serverIPs, serverPorts, serverIPs[whichServer], serverPorts[whichServer], numClients, server, voteOutputMtx, voteOutputFilename);
  155. cout << "[" << seedStr << "] New vote row complete." << endl;
  156. break;
  157. case CLIENT_MAKE_REP_PROOF:
  158. fullQuery = triggerRepHandler.getQuery();
  159. colonLocation = fullQuery.find(":");
  160. target = fullQuery.substr(0, colonLocation);
  161. targetPort = stoi(fullQuery.substr(colonLocation + 1));
  162. cout << "[" << seedStr << "] Making new reputation proof." << endl;
  163. make_reputation_proof(rng, prsonaClient, serverIPs, serverPorts, target, targetPort, numClients, server, repProofOutputMtx, repProofOutputFilename);
  164. cout << "[" << seedStr << "] New reputation proof complete." << endl;
  165. break;
  166. default: // Occurs when an exit is signaled; do nothing
  167. break;
  168. }
  169. // Make sure to reset this, so that we wait until something new is signaled to do
  170. exitSync.val2 = 0;
  171. }
  172. /*
  173. * SHUTDOWN CODE
  174. */
  175. cout << "[" << seedStr << "] Shutting down." << endl;
  176. mg_exit_library();
  177. delete prsonaClient;
  178. return 0;
  179. }