main.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /* Copyright (C) 2014 Carlos Aguilar Melchor, Joris Barrier, Marc-Olivier Killijian
  2. * This file is part of XPIR.
  3. *
  4. * XPIR is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * XPIR is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with XPIR. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "main.hpp"
  18. // Client constants
  19. static const std::string DEFAULT_IP("127.0.0.1");
  20. static const int DEFAULT_PORT = 1234;
  21. static const bool DEFAULT_AUTOCHOICE = false;
  22. static const int DEFAULT_BATCHSIZE = 1;
  23. // Optimizer constants
  24. static const int DEFAULT_SECURITY = 80;
  25. static const unsigned long DEFAULT_N = 1000;
  26. static const unsigned int DEFAULT_L = 24000000;
  27. static const unsigned int DEFAULT_TUPC = 100000000;
  28. static const unsigned int DEFAULT_TDOC = 100000000;
  29. static const unsigned int DEFAULT_K = 80;
  30. static const unsigned int DEFAULT_ALPHAMAX = 0; // 0 means no limit
  31. static const unsigned int DEFAULT_DMAX = 4;
  32. static const unsigned int DEFAULT_DMIN = 1;
  33. static const FitnessType DEFAULT_FITNESSMETHOD = MAX;
  34. static const std::string DEFAULT_CRYPTO_PARAMS("LWE:80:1024:60:22");
  35. //Global vars
  36. string fileToOptimizeFrom;
  37. bool no_pipeline = false;
  38. void sighandler(int sig_num)
  39. {
  40. FixedVars fixedVars;
  41. cerr.flush();
  42. if(sig_num == SIGPIPE)
  43. cerr << "Broken pipe detected";
  44. cerr << endl << "Exiting client..." << endl << endl;
  45. exit(EXIT_SUCCESS);
  46. }
  47. void defineClientOptions(ClientParams* paramsPtr, po::options_description* odptr){
  48. odptr->add_options()
  49. ("help,h",
  50. "help message")
  51. ("serverip,ip",
  52. po::value<string>(&paramsPtr->server_ip)->default_value(DEFAULT_IP),
  53. "PIR server IP" )
  54. ("port,p",
  55. po::value<int>(&paramsPtr->port)->default_value(DEFAULT_PORT),
  56. "PIR server port")
  57. ("autochoice,c",
  58. "Auto-choose the first file")
  59. ("batchqueries,b",
  60. po::value<int>(&paramsPtr->batchSize)->default_value(DEFAULT_BATCHSIZE),
  61. "Auto-choose the first file")
  62. ("dry-run",
  63. "Enable dry-run mode")
  64. ("verbose-optim",
  65. "Ask the optimizer to be more verbose")
  66. ("dont-write",
  67. "Don't write result to a file")
  68. ("file,f",
  69. po::value<std::string>(&fileToOptimizeFrom),
  70. "Use a config file to test different optimizations in dry-run mode (see sample.conf)");
  71. }
  72. void defineOptimizerOptions(FixedVars* varsPtr, po::options_description* odptr){
  73. odptr->add_options()
  74. ("file-nbr,n",
  75. po::value<uint64_t>(),
  76. "Used in dry-run mode only: Number of database elements" )
  77. ("file-size,l",
  78. po::value<uint64_t>(),
  79. "Used in dry-run mode only: Database element size in bits")
  80. ("upload,up",
  81. po::value<double>(),
  82. "Force client upload speed in bits/s (bandwith test will be skipped)")
  83. ("download,down",
  84. po::value<double>(),
  85. "Force client download speed in bits/s (bandwidth test will be skipped)")
  86. ("crypto-params,r",
  87. po::value<string>(&varsPtr->manual_crypto_params),
  88. "Set cryptographic parameteres manually")
  89. ("security,k",
  90. po::value<unsigned int>(&varsPtr->k)->default_value(DEFAULT_SECURITY),
  91. "Security bits wanted")
  92. ("dmin",
  93. po::value<unsigned int>(&varsPtr->dMin)->default_value(DEFAULT_DMIN),
  94. "Min dimension value to test")
  95. ("dmax",
  96. po::value<unsigned int>(&varsPtr->dMax)->default_value(DEFAULT_DMAX),
  97. "Max dimension value to test")
  98. ("alphaMax,a",
  99. po::value<unsigned int>(&varsPtr->alphaMax)->default_value(DEFAULT_ALPHAMAX),
  100. "Max aggregation value to test (1 = no aggregation, 0 = no limit)")
  101. ("fitness,x",
  102. po::value<int>((int*)&varsPtr->fitness)->default_value((int)DEFAULT_FITNESSMETHOD),
  103. "Set fitness method to: \n0=SUM Sum of the times on each task\n1=MAX Max of server times + Max of client times\n2=CLOUD Dollars in a cloud model (see sourcecode)");
  104. }
  105. void defineHiddenOptions(FixedVars* varsPtr, po::options_description* odptr){
  106. odptr->add_options()
  107. ("no-pipeline", "No pipeline mode\n")
  108. ("reclvl",
  109. po::value<unsigned int>(),
  110. "Number of dimension used for database representation");
  111. }
  112. void processOptions(FixedVars* varsPtr, ClientParams* paramsPtr, po::variables_map vm){
  113. // Client options
  114. if(vm.count("serverip"))
  115. {
  116. std::cout << "CLI: Server ip set to " << paramsPtr->server_ip << std::endl;
  117. }
  118. if(vm.count("port"))
  119. {
  120. std::cout << "CLI: Upload port set to " << paramsPtr->port << std::endl;
  121. }
  122. if(vm.count("autochoice"))
  123. {
  124. std::cout << "CLI: Auto-choice activated" << std::endl;
  125. paramsPtr->autochoice = true;
  126. }
  127. if(vm.count("dry-run"))
  128. {
  129. std::cout << "CLI: Dry-run mode activated" << std::endl;
  130. paramsPtr->dryrunmode = true;
  131. varsPtr->n = DEFAULT_N;
  132. varsPtr->l = DEFAULT_L;
  133. varsPtr->Tupc = DEFAULT_TUPC;
  134. varsPtr->Tdos = DEFAULT_TUPC;
  135. varsPtr->Tdoc = DEFAULT_TDOC;
  136. varsPtr->Tups = DEFAULT_TDOC;
  137. std::cout << "CLI: Setting default values for dry-run mode (a thousand mp3 files, 100MBit/s connection)" <<std::endl;
  138. }
  139. if(vm.count("verbose-optim"))
  140. {
  141. std::cout << "CLI: Will ask the optimizer to be more verbose" << std::endl;
  142. paramsPtr->verboseoptim = true;
  143. }
  144. if(vm.count("dont-write"))
  145. {
  146. std::cout << "CLI: Will ask PIRReplyWriter not to write to a file" << std::endl;
  147. paramsPtr->dontwrite = true;
  148. }
  149. else paramsPtr->dontwrite = false;
  150. // Optimizer options
  151. if(vm.count("file-nbr"))
  152. {
  153. if(vm.count("dry-run"))
  154. {
  155. varsPtr->n = vm["file-nbr"].as<uint64_t>();
  156. std::cout << "CLI: Changing number of database elements to "\
  157. << varsPtr->n << std::endl;
  158. }
  159. else
  160. {
  161. std::cout << "CLI: Option -n,--file-nbr ignored as we are not in dry-run mode"\
  162. << std::endl;
  163. }
  164. }
  165. if(vm.count("file-size")) {
  166. if(vm.count("dry-run"))
  167. {
  168. varsPtr->l = vm["file-size"].as<uint64_t>();
  169. std::cout << "CLI: Changing database element size to " << varsPtr->l <<std::endl;
  170. }
  171. else
  172. {
  173. std::cout << "CLI: Option -l,--file-size ignored as we are not in dry-run mode"
  174. << std::endl;
  175. }
  176. }
  177. if (vm.count("upload"))
  178. {
  179. varsPtr->Tupc = vm["upload"].as<double>();
  180. varsPtr->Tdos = varsPtr->Tupc;
  181. cout << "CLI: Upload speed forced to "<< varsPtr->Tupc << endl;
  182. }
  183. if (vm.count("download"))
  184. {
  185. varsPtr->Tdoc = vm["download"].as<double>();
  186. varsPtr->Tups = varsPtr->Tdoc;
  187. cout << "CLI: Download speed forced to "<< varsPtr->Tdoc << endl;
  188. }
  189. if(vm.count("crypto-params"))
  190. {
  191. std::cout << "CLI: Crypto parameters set to " << varsPtr->manual_crypto_params << std::endl;
  192. std::vector<std::string> fields;
  193. boost::algorithm::split(fields, varsPtr->manual_crypto_params, boost::algorithm::is_any_of(":"));
  194. if (fields.size()>1 && atoi(fields[1].c_str()) > 0)
  195. {
  196. varsPtr->k = atoi(fields[1].c_str());
  197. }
  198. if (fields.size()>4)
  199. {
  200. std::cout << "CLI: WARNING Absorption size will be overriden by the optimizer" << varsPtr->manual_crypto_params << std::endl;
  201. varsPtr->k = 0;
  202. }
  203. }
  204. if(vm.count("security"))
  205. {
  206. std::cout << "CLI: Security set to " << varsPtr->k << std::endl;
  207. }
  208. if (vm.count("dmin"))
  209. {
  210. cout << "CLI: Minimum recursion level set to "<< varsPtr->dMin << endl;
  211. }
  212. if (vm.count("dmax"))
  213. {
  214. cout << "CLI: Maximum recursion level set to "<< varsPtr->dMax << endl;
  215. }
  216. if(vm.count("alphaMax"))
  217. {
  218. varsPtr->alphaMax = vm["alphaMax"].as<unsigned int>();
  219. cout << "CLI: Max aggregation set to "<< varsPtr->alphaMax << endl;
  220. }
  221. if(vm.count("fitness"))
  222. {
  223. cout << "CLI: Fitness method set to "<< varsPtr->fitness << endl;
  224. }
  225. // Hidden options
  226. if (vm.count("reclvl"))
  227. {
  228. varsPtr->dMax = vm["reclvl"].as<unsigned int>();
  229. varsPtr->dMin = vm["reclvl"].as<unsigned int>();
  230. cout << "CLI: Recursion level forced to "<< varsPtr->dMax << endl;
  231. }
  232. if (vm.count("no-pipeline"))
  233. {
  234. std::cout << "CLI: WARNING no pipeline mode activated" << std::endl;
  235. no_pipeline = true;
  236. }
  237. }
  238. int main(int argc, char** argv)
  239. {
  240. boost::asio::io_service ios;
  241. // Vars for the optimizer (and pot. client)
  242. FixedVars fixedVars = {}; // Inits to default value all fields
  243. // Vars for the client only
  244. ClientParams clientParams = {}; // Same here
  245. // Add and define options
  246. po::options_description od("Client options");
  247. po::options_description optimizeropts("Optimizer options");
  248. po::options_description hidden("Hidden options");
  249. defineOptimizerOptions(&fixedVars, &optimizeropts);
  250. defineClientOptions(&clientParams, &od);
  251. defineHiddenOptions(&fixedVars, &hidden);
  252. // Set which options are visible and which not
  253. po::options_description visible;
  254. visible.add(od).add(optimizeropts);
  255. po::options_description all;
  256. all.add(visible).add(hidden);
  257. po::variables_map vm;
  258. // Parse options from command line
  259. try {
  260. po::store(po::parse_command_line(argc, argv, all), vm);
  261. }
  262. catch (const std::exception& ex)
  263. {
  264. std::cout << "CLI: Error checking program options: " << ex.what() << std::endl;
  265. std::cout << visible << std::endl;
  266. return 1;
  267. }
  268. po::notify(vm);
  269. // Show usage help if requested
  270. if(vm.count("help")) {
  271. std::cout << visible << endl;
  272. return 0;
  273. }
  274. // Set variables according to options
  275. processOptions(&fixedVars, &clientParams, vm);
  276. // If we are on dry-run mode run only the optimizer not the client
  277. if(vm.count("dry-run"))
  278. {
  279. std::cout << "CLI: Dry-run mode activated" << std::endl;
  280. // The optimizer connects to the same PIR server but on a higher port for
  281. // optimization related exchanges
  282. PIROptimizer optimizer(clientParams.server_ip, clientParams.port, fixedVars.fitness);
  283. if (vm.count("file"))
  284. {
  285. int experience_nbr = OptimService::getNumberOfExperiences(fileToOptimizeFrom);
  286. if(experience_nbr == -1)
  287. {
  288. cout << "CLI: Unable to open : " << fileToOptimizeFrom << " aborting" << endl;
  289. cout << "CLI: Try exp/sample.conf to test a predefined set of configurations" << endl;
  290. return 1;
  291. }
  292. for (int exp_i = 0 ; exp_i <= experience_nbr ; exp_i++)
  293. {
  294. OptimService::readTestValues(exp_i, fixedVars, fileToOptimizeFrom);
  295. OptimService::writeHeadFile(exp_i, fixedVars);
  296. optimizer.optimize(fixedVars, exp_i);
  297. }
  298. }
  299. else
  300. {
  301. cout << "CLI: Default example : A thousand mp3 files, ADSL, no aggregation, k=80" << endl;
  302. cout << "CLI: n : " << fixedVars.n << " l : " << fixedVars.l;
  303. cout << "CLI: Tupc : " << fixedVars.Tupc << " Tdoc : " << fixedVars.Tdoc << endl;
  304. OptimService::writeHeadFile(0, fixedVars);
  305. optimizer.optimize(fixedVars, 0);
  306. }
  307. return 0;
  308. }
  309. // If we are not in dry-run mode create client and controller
  310. PIRClientSimple client(ios, clientParams, fixedVars);
  311. PIRController controller(client);
  312. // Set no_pipeline if needed
  313. if(no_pipeline) client.no_pipeline(true);
  314. // Start by connecting to the PIR server
  315. client.connect();
  316. // Downloads the file catalog
  317. client.downloadCatalog();
  318. // Get from the server whether we are in client-driven mode or not
  319. client.rcvPIRParamsExchangeMethod();
  320. // Use the optimizer to choose best parameters
  321. // (returns immediately in server-driven mode)
  322. client.optimize();
  323. // Send PIR and cryptographic parameters to the server in client-driven mode
  324. // and receive and process them in server-driven mode
  325. client.processCryptoParams();
  326. client.processPIRParams();
  327. /*User chooses the file here.*/
  328. client.chooseFile();
  329. double start = omp_get_wtime();
  330. clock_t pq_start, pq_stop, pr_start, pr_stop;
  331. pq_start = clock();
  332. /* Asynchronously generate and send the request
  333. separately in two threads*/
  334. client.startProcessQuery();
  335. pq_stop = clock();
  336. /* Receive asynchronously the response from the server and
  337. asynchronously writes it */
  338. pr_start = clock();
  339. client.startProcessResult();
  340. pr_stop = clock();
  341. client.joinAllThreads();
  342. double end = omp_get_wtime();
  343. //cout<<"ssasy : ProcessQuery time taken was " << (double) 1000 * double(pq_stop - pq_start) / double(CLOCKS_PER_SEC)<< "ms" <<endl;
  344. //cout<<"ssasy : ProcessResult time taken was " << (double) 1000 * double(pr_stop - pq_start) / double(CLOCKS_PER_SEC)<< "ms" <<endl;
  345. cout << "CLI: Query RTT was " << end-start << " seconds" << endl;
  346. cout << "CLI: Exiting..." << endl;
  347. return EXIT_SUCCESS;
  348. }