serverMain.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /**
  2. * serverMain.cpp
  3. * - compiles to bin/server
  4. * - runs a server program for experiments with PRSONA
  5. *
  6. * Stan Gurtler
  7. */
  8. #include <iostream>
  9. #include <fstream>
  10. #include "networkServer.hpp"
  11. using namespace std;
  12. /**
  13. * This program (bin/server) expects to be called as follows:
  14. * `bin/server <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. * <servers_are_malicious> - a bool (given as T/t or F/f)
  21. * which is true when servers are in malicious security
  22. * and false when they are in HBC security
  23. */
  24. int main(int argc, char *argv[])
  25. {
  26. /*
  27. * PRELIMINARY SETUP CODE
  28. */
  29. initialize_prsona_classes();
  30. #if USE_SSL
  31. mg_init_library(MG_FEATURES_SSL);
  32. #else
  33. mg_init_library(0);
  34. #endif
  35. // The id effectively tells the server what ip/port it is
  36. string id = "";
  37. if (argc > 1)
  38. id = argv[1];
  39. string output = "default";
  40. if (argc > 2)
  41. output = argv[2];
  42. string outputDir = "out/" + output + "/" + id;
  43. int mkdirOut = system(("mkdir -p " + outputDir).c_str());
  44. mutex epochBuildUpOutputMtx;
  45. string epochBuildUpOutputFilename = outputDir + "/epochUp.out";
  46. mutex epochBreakDownOutputMtx;
  47. string epochBreakDownOutputFilename = outputDir + "/epochDown.out";
  48. mutex epochUpdateOutputMtx;
  49. string epochUpdateOutputFilename = outputDir + "/epochUpdate.out";
  50. mutex voteUpdateOutputMtx;
  51. string voteUpdateOutputFilename = outputDir + "/voteUpdate.out";
  52. mutex fullEpochOutputMtx;
  53. string fullEpochOutputFilename = outputDir + "/overallEpoch.out";
  54. // Default to malicious security if not specified
  55. bool maliciousServers = true;
  56. if (argc > 3)
  57. {
  58. bool setting = argv[3][0] == 't' || argv[3][0] == 'T';
  59. maliciousServers = setting;
  60. }
  61. // Set malicious flags where necessary
  62. if (maliciousServers)
  63. PrsonaBase::set_server_malicious();
  64. // This seed is used to generate temp filenames.
  65. string seedStr;
  66. if (id.empty())
  67. seedStr = "default-server";
  68. else
  69. {
  70. seedStr = id;
  71. seedStr += "-server";
  72. }
  73. seed_seq seed(seedStr.begin(), seedStr.end());
  74. default_random_engine rng(seed);
  75. vector<string> serverIPs;
  76. vector<int> serverPorts;
  77. string selfIP, selfPortStr, dealerIP, dealerPortStr;
  78. int selfPort = 0, dealerPort = 0;
  79. // Read in from config files the server locations
  80. load_multiple_instances_config(serverIPs, serverPorts, "cfg/serverIPs.cfg");
  81. // Read in the ip/port corresponding to the id that this instance was given
  82. string selfConfigFilename = "cfg/selfIP";
  83. if (!id.empty())
  84. {
  85. selfConfigFilename += "-";
  86. selfConfigFilename += id;
  87. }
  88. selfConfigFilename += ".cfg";
  89. load_single_instance_config(selfIP, selfPortStr, selfPort, selfConfigFilename.c_str());
  90. // And finally the dealer location
  91. load_single_instance_config(dealerIP, dealerPortStr, dealerPort, "cfg/dealerIP.cfg");
  92. size_t numServers = serverIPs.size();
  93. bool bgnDealer = selfIP == dealerIP && selfPort == dealerPort;
  94. struct synchronization_tool exitSync, readySync;
  95. mutex updateMtx;
  96. unique_lock<mutex> *updateLockHolder = NULL;
  97. atomic<size_t> epochNum(0);
  98. const char *options[] = {"listening_ports", selfPortStr.c_str(), 0};
  99. CivetServer server(options);
  100. /*
  101. * SERVER SETUP CODE
  102. */
  103. cout << "[" << seedStr << "] Establishing PRSONA server with the following parameters: " << endl;
  104. cout << "[" << seedStr << "] " << numServers << " PRSONA servers" << endl;
  105. cout << "[" << seedStr << "] This server " << (bgnDealer ? "IS" : "is NOT") << " the trusted BGN dealer" << endl;
  106. cout << "[" << seedStr << "] Servers are set to " << (maliciousServers ? "MALICIOUS" : "HBC") << " security" << endl;
  107. cout << "[" << seedStr << "] This server is at IP address: " << selfIP << ":" << selfPort << endl;
  108. cout << "[" << seedStr << "] The BGN dealer is at IP address: " << dealerIP << ":" << dealerPort << endl;
  109. cout << endl;
  110. cout << "[" << seedStr << "] Creating PRSONA server object." << endl;
  111. PrsonaServer *prsonaServer = create_server(rng, dealerIP, dealerPort, bgnDealer, numServers);
  112. cout << "[" << seedStr << "] Setting up handlers for server." << endl;
  113. // Main handler
  114. PrsonaServerWebSocketHandler wsHandler(rng, prsonaServer, serverIPs, serverPorts, selfIP, selfPort, updateMtx, epochNum, epochBuildUpOutputMtx, epochBuildUpOutputFilename, epochBreakDownOutputMtx, epochBreakDownOutputFilename, epochUpdateOutputMtx, epochUpdateOutputFilename, voteUpdateOutputMtx, voteUpdateOutputFilename);
  115. server.addWebSocketHandler("/ws", wsHandler);
  116. // Exit handler (allows server to be brought down by making correct GET request)
  117. unique_lock<mutex> exitLock(exitSync.mtx);
  118. exitSync.val = 0;
  119. exitSync.val2 = 0;
  120. RemoteControlHandler exitHandler(&exitSync, "Server coming down!");
  121. server.addHandler(EXIT_URI, exitHandler);
  122. // Update mutex handler (allows servers to synchronize updates, like epochs and new users)
  123. UpdateLockWebSocketHandler lockHandler(updateMtx, &updateLockHolder, true);
  124. UpdateLockWebSocketHandler unlockHandler(updateMtx, &updateLockHolder, false);
  125. server.addWebSocketHandler(UPDATE_LOCK_URI, lockHandler);
  126. server.addWebSocketHandler(UPDATE_UNLOCK_URI, unlockHandler);
  127. // Epoch number handler (allows a server to indicate what epoch the system is on)
  128. EpochNumHandler epochNumHandler(epochNum);
  129. server.addHandler(WHICH_EPOCH_URI, epochNumHandler);
  130. // This handler (to determine system main loop readiness) is only used by the dealer
  131. RemoteControlHandler serverReadyHandler(&readySync, "ACK");
  132. // Similarly, this handler (to tell the orchestrator when epochs are ready to happen) is only used by the dealer
  133. EpochReadyHandler epochReadyHandler(&exitSync, &readySync, updateMtx, numServers);
  134. // Make-epoch trigger (which causes the dealer to initiate an epoch change)
  135. AltRemoteControlHandler triggerEpochHandler(1, &exitSync, "Server will initiate epoch!");
  136. // It's probably best to give them all a lifetime as long as the CivetWeb server object
  137. if (bgnDealer) // The dealer needs to wait for the other servers to check in, because it needs to lead forming the first fresh generator
  138. {
  139. // The readySync lock is only used here, while we're waiting for other servers to check in
  140. unique_lock<mutex> lck(readySync.mtx);
  141. readySync.val = 1;
  142. server.addHandler(SERVER_CHECK_IN_URI, serverReadyHandler);
  143. // In addition, there are also a few extra handlers only the dealer needs
  144. server.addHandler(TRIGGER_EPOCH_URI, triggerEpochHandler);
  145. server.addHandler(EPOCH_READY_URI, epochReadyHandler);
  146. cout << "[" << seedStr << "] Waiting for other servers to retrieve BGN details and check in." << endl;
  147. // Wait for the other servers to check in
  148. while (readySync.val < numServers)
  149. readySync.cv.wait(lck);
  150. // Once we're ready, form and distribute the first fresh generator and the H used in ElGamal operations
  151. initiate_generators(rng, prsonaServer, serverIPs, serverPorts, selfIP, selfPort);
  152. }
  153. else // Non-dealer servers need to check in with the dealer
  154. {
  155. cout << "[" << seedStr << "] Checking in with the BGN dealer." << endl;
  156. check_in_with_dealer(dealerIP, dealerPort);
  157. }
  158. /*
  159. * MAIN SERVER LOOP CODE
  160. */
  161. cout << "[" << seedStr << "] Entering main ready loop." << endl;
  162. if (bgnDealer)
  163. {
  164. while (!exitSync.val)
  165. {
  166. // exitSync.val controls when an exit is signaled.
  167. // exitSync.val2 controls when an epoch change is signaled
  168. while (!exitSync.val && !exitSync.val2)
  169. exitSync.cv.wait(exitLock);
  170. // exitSync.val2 is set by the make-epoch handler, and will be 0 in the event of signaling an exit
  171. if (exitSync.val2)
  172. {
  173. size_t currEpoch = epochNum.load();
  174. cout << "[" << seedStr << "] Executing epoch calculations (going from t = " << currEpoch << " to " << currEpoch + 1 << ")." << endl;
  175. make_epoch(rng, prsonaServer, serverIPs, serverPorts, selfIP, selfPort, updateMtx, epochNum, server, epochBuildUpOutputMtx, epochBuildUpOutputFilename, epochBreakDownOutputMtx, epochBreakDownOutputFilename, fullEpochOutputMtx, fullEpochOutputFilename);
  176. currEpoch = epochNum.load();
  177. cout << "[" << seedStr << "] Epoch calculations complete (now in t = " << currEpoch << ")." << endl;
  178. }
  179. // Make sure to reset this, so that we wait until something new is signaled to do
  180. exitSync.val2 = 0;
  181. }
  182. }
  183. else
  184. {
  185. // exitSync.val controls when an exit is signaled.
  186. // exitSync.val2 is not used by non-dealer servers.
  187. while (!exitSync.val)
  188. exitSync.cv.wait(exitLock);
  189. }
  190. /*
  191. * SHUTDOWN CODE
  192. */
  193. cout << "[" << seedStr << "] Shutting down." << endl;
  194. mg_exit_library();
  195. delete prsonaServer;
  196. return 0;
  197. }