networking.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <fstream>
  4. #include <cstring>
  5. #include <cstdlib>
  6. #include <cstdio>
  7. #include "networking.hpp"
  8. /*********************************************
  9. **** ****
  10. **** "public" generic helper functions ****
  11. **** ****
  12. *********************************************/
  13. void initialize_prsona_classes()
  14. {
  15. Scalar::init();
  16. PrsonaBase::init();
  17. PrsonaBase::set_client_malicious();
  18. }
  19. char *set_temp_filename(
  20. std::default_random_engine& rng,
  21. struct mg_connection *conn)
  22. {
  23. std::string filename = random_string(rng, TMP_FILE_SIZE);
  24. char *c_filename = new char[TMP_FILE_SIZE+TMP_DIR_SIZE+1];
  25. strncpy(c_filename, TMP_DIR, TMP_DIR_SIZE);
  26. for (size_t i = 0; i < TMP_FILE_SIZE; i++)
  27. c_filename[i + TMP_DIR_SIZE] = filename[i];
  28. c_filename[TMP_DIR_SIZE + TMP_FILE_SIZE] = 0;
  29. if (conn)
  30. mg_set_user_connection_data(conn, c_filename);
  31. return c_filename;
  32. }
  33. void load_multiple_instances_config(
  34. std::vector<std::string>& relevantIPs,
  35. std::vector<int>& relevantPorts,
  36. const char *filename)
  37. {
  38. relevantIPs.clear();
  39. relevantPorts.clear();
  40. char buffer[46], *helper;
  41. std::ifstream configFile(filename);
  42. while (!configFile.eof())
  43. {
  44. configFile.getline(buffer, 46);
  45. if (strlen(buffer) > 0)
  46. {
  47. helper = buffer;
  48. if (strchr(helper, ':')) // File specifies a port
  49. {
  50. helper = strtok(helper, ":");
  51. relevantIPs.push_back(std::string(helper));
  52. helper = strtok(NULL, ":");
  53. relevantPorts.push_back(atoi(helper));
  54. }
  55. else // We use a default port
  56. {
  57. relevantIPs.push_back(std::string(helper));
  58. relevantPorts.push_back(atoi(DEFAULT_PRSONA_PORT_STR));
  59. }
  60. }
  61. }
  62. }
  63. void load_single_instance_config(
  64. std::string& relevantIP,
  65. std::string& relevantPortStr,
  66. int& relevantPort,
  67. const char *filename)
  68. {
  69. char buffer[46], *helper;
  70. std::ifstream configFile(filename);
  71. while (!configFile.eof())
  72. {
  73. configFile.getline(buffer, 46);
  74. if (strlen(buffer) > 0)
  75. {
  76. helper = buffer;
  77. if (strchr(helper, ':')) // File specifies a port
  78. {
  79. helper = strtok(helper, ":");
  80. relevantIP = helper;
  81. helper = strtok(NULL, ":");
  82. relevantPortStr = helper;
  83. relevantPort = stoi(relevantPortStr);
  84. }
  85. else // We use default port
  86. {
  87. relevantIP = helper;
  88. relevantPortStr = DEFAULT_PRSONA_PORT_STR;
  89. relevantPort = stoi(relevantPortStr);
  90. }
  91. }
  92. }
  93. }
  94. std::vector<size_t> get_log_data(
  95. const struct mg_context *ctx)
  96. {
  97. std::vector<size_t> retval;
  98. char buffer[4096];
  99. mg_get_context_info(ctx, buffer, 4096);
  100. std::cout << "Log data: \n" << buffer << std::endl;
  101. retval.push_back(parse_log_for_data(buffer, "read"));
  102. retval.push_back(parse_log_for_data(buffer, "written"));
  103. return retval;
  104. }
  105. void write_log_data(
  106. std::mutex& outputMtx,
  107. const std::string& outputFilename,
  108. const std::vector<double>& timingData,
  109. const std::vector<size_t>& bandwidthData)
  110. {
  111. std::unique_lock<std::mutex> lck(outputMtx);
  112. FILE *outputFile = fopen(outputFilename.c_str(), "a");
  113. fprintf(outputFile, "%f,%f,%zu,%zu\n", timingData[0], timingData[1], bandwidthData[0], bandwidthData[1]);
  114. fclose(outputFile);
  115. }
  116. /***********************************************************
  117. **** ****
  118. **** "private" functions to help the generic helpers ****
  119. **** ****
  120. ***********************************************************/
  121. std::string random_string(
  122. std::default_random_engine& rng,
  123. size_t length)
  124. {
  125. const char charset[] =
  126. "0123456789_-"
  127. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  128. "abcdefghijklmnopqrstuvwxyz";
  129. const size_t max_index = (sizeof(charset) - 1);
  130. std::uniform_int_distribution<int> dist(0, max_index - 1);
  131. auto randchar = [&]() -> char
  132. {
  133. return charset[ dist(rng) ];
  134. };
  135. std::string retval(length, 0);
  136. std::generate_n(retval.begin(), length, randchar);
  137. return retval;
  138. }
  139. size_t parse_log_for_data(const char *input, const char *key)
  140. {
  141. size_t length = strlen(input);
  142. char *copy = new char[length + 1];
  143. strncpy(copy, input, length);
  144. copy[length] = 0;
  145. char *pos = strstr(copy, key) + strlen(key);
  146. pos = strtok(pos, "{}:,\" \n");
  147. size_t retval = strtoul(pos, NULL, 10);
  148. delete [] copy;
  149. return retval;
  150. }
  151. /***************************************
  152. **** ****
  153. **** websocket handler functions ****
  154. **** ****
  155. ***************************************/
  156. /*
  157. * NULL
  158. */
  159. int empty_websocket_data_handler(
  160. struct mg_connection *conn,
  161. int bits,
  162. char *data,
  163. size_t data_len,
  164. void *user_data)
  165. {
  166. return false;
  167. }
  168. void empty_websocket_close_handler(
  169. const struct mg_connection *conn,
  170. void *user_data)
  171. { /* */ }
  172. /*
  173. * SYNCHRONIZATION
  174. */
  175. int synchro_websocket_data_handler(
  176. struct mg_connection *conn,
  177. int bits,
  178. char *data,
  179. size_t data_len,
  180. void *user_data)
  181. {
  182. struct synchronization_tool *sync = (struct synchronization_tool *) user_data;
  183. std::unique_lock<std::mutex> lck(sync->mtx, std::defer_lock);
  184. switch (bits & 0xf)
  185. {
  186. case MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE:
  187. break;
  188. // Responder has indicated receipt of submitted data
  189. case MG_WEBSOCKET_OPCODE_DATACOMPLETE:
  190. lck.lock();
  191. sync->val++;
  192. break;
  193. // Something strange has happened
  194. default:
  195. std::cerr << "Unknown packet type received. Failing." << std::endl;
  196. break;
  197. }
  198. return false;
  199. }
  200. void synchro_websocket_close_handler(
  201. const struct mg_connection *conn,
  202. void *user_data)
  203. {
  204. struct synchronization_tool *synch = (struct synchronization_tool *) user_data;
  205. std::unique_lock<std::mutex> lck(synch->mtx);
  206. synch->val2 = 1;
  207. synch->cv.notify_all();
  208. }
  209. /*
  210. * RECEIVE SERIALIZED DATA
  211. */
  212. int file_websocket_data_handler(
  213. struct mg_connection *conn,
  214. int bits,
  215. char *data,
  216. size_t data_len,
  217. void *user_data)
  218. {
  219. struct synchronization_tool *sync = (struct synchronization_tool *) user_data;
  220. char *filename = (char *) mg_get_user_connection_data(conn);
  221. FILE *currFile = NULL;
  222. std::unique_lock<std::mutex> lck(sync->mtx, std::defer_lock);
  223. switch (bits & 0xf)
  224. {
  225. // Responder has indicated they have sent all relevant data
  226. case MG_WEBSOCKET_OPCODE_DATACOMPLETE:
  227. case MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE:
  228. break;
  229. // Responder has sent more data (which may theoretically be broken up into multiple packets)
  230. case MG_WEBSOCKET_OPCODE_BINARY:
  231. case MG_WEBSOCKET_OPCODE_CONTINUATION:
  232. lck.lock();
  233. currFile = fopen(filename, "ab");
  234. fwrite(data, sizeof(char), data_len, currFile);
  235. fclose(currFile);
  236. return true;
  237. // Something strange has happened
  238. default:
  239. std::cerr << "Unknown packet type received. Failing." << std::endl;
  240. break;
  241. }
  242. return false;
  243. }
  244. void file_websocket_close_handler(
  245. const struct mg_connection *conn,
  246. void *user_data)
  247. {
  248. struct synchronization_tool *sync = (struct synchronization_tool *) user_data;
  249. std::unique_lock<std::mutex> lck(sync->mtx);
  250. sync->val = 1;
  251. sync->val2 = 1;
  252. sync->cv.notify_all();
  253. }
  254. /*
  255. * SYNCHRONIZATION AND RECEIVE SERIALIZED DATA
  256. */
  257. int epoch_websocket_data_handler(
  258. struct mg_connection *conn,
  259. int bits,
  260. char *data,
  261. size_t data_len,
  262. void *user_data)
  263. {
  264. struct synchronization_tool *sync = (struct synchronization_tool *) user_data;
  265. char *filename = (char *) mg_get_user_connection_data(conn);
  266. FILE *currFile = NULL;
  267. std::unique_lock<std::mutex> lck(sync->mtx, std::defer_lock);
  268. switch (bits & 0xf)
  269. {
  270. case MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE:
  271. break;
  272. // Responder has indicated they have sent all relevant data
  273. case MG_WEBSOCKET_OPCODE_DATACOMPLETE:
  274. lck.lock();
  275. sync->val++;
  276. break;
  277. // Responder has sent more data (which may theoretically be broken up into multiple packets)
  278. case MG_WEBSOCKET_OPCODE_BINARY:
  279. case MG_WEBSOCKET_OPCODE_CONTINUATION:
  280. lck.lock();
  281. currFile = fopen(filename, "ab");
  282. fwrite(data, sizeof(char), data_len, currFile);
  283. fclose(currFile);
  284. return true;
  285. // Something strange has happened
  286. default:
  287. std::cerr << "Unknown packet type received. Failing." << std::endl;
  288. break;
  289. }
  290. return false;
  291. }
  292. void epoch_websocket_close_handler(
  293. const struct mg_connection *conn,
  294. void *user_data)
  295. {
  296. struct synchronization_tool *sync = (struct synchronization_tool *) user_data;
  297. std::unique_lock<std::mutex> lck(sync->mtx);
  298. sync->val2 = 1;
  299. sync->cv.notify_all();
  300. }
  301. /*
  302. * SPECIAL FOR HANDLING UNUSUAL DATA
  303. */
  304. int clients_websocket_data_handler(
  305. struct mg_connection *conn,
  306. int bits,
  307. char *data,
  308. size_t data_len,
  309. void *user_data)
  310. {
  311. struct synchronization_tool *sync = (struct synchronization_tool *) user_data;
  312. std::unique_lock<std::mutex> lck(sync->mtx, std::defer_lock);
  313. switch (bits & 0xf)
  314. {
  315. // Responder has indicated they have sent all relevant data
  316. case MG_WEBSOCKET_OPCODE_DATACOMPLETE:
  317. case MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE:
  318. break;
  319. // Responder has sent data
  320. case MG_WEBSOCKET_OPCODE_BINARY:
  321. lck.lock();
  322. if (data_len == sizeof(sync->val))
  323. sync->val = *((size_t *) data);
  324. break;
  325. // Something strange has happened
  326. default:
  327. std::cerr << "Unknown packet type received. Failing." << std::endl;
  328. break;
  329. }
  330. return false;
  331. }
  332. /********************************************
  333. **** ****
  334. **** Generic handler member functions ****
  335. **** ****
  336. ********************************************/
  337. /*
  338. * EXIT SYNCHRONIZATION HANDLER
  339. */
  340. RemoteControlHandler::RemoteControlHandler(
  341. struct synchronization_tool *sync)
  342. : sync(sync)
  343. { /* */ }
  344. RemoteControlHandler::RemoteControlHandler(
  345. struct synchronization_tool *sync,
  346. const std::string& message)
  347. : sync(sync), message(message)
  348. { /* */ }
  349. bool RemoteControlHandler::handleGet(
  350. CivetServer *server,
  351. struct mg_connection *conn)
  352. {
  353. std::unique_lock<std::mutex> lck(sync->mtx);
  354. mg_printf(conn, "HTTP/1.1 200 OK\r\n"
  355. "Content-Type: text/plain\r\n"
  356. "Connection: close\r\n\r\n");
  357. if (message.empty())
  358. mg_printf(conn, "Event triggered.\n");
  359. else
  360. mg_printf(conn, "%s\n", message.c_str());
  361. sync->val++;
  362. sync->cv.notify_all();
  363. return true;
  364. }
  365. /*
  366. * EXPERIMENT EVENT SYNCHRONIZATION HANDLER
  367. */
  368. AltRemoteControlHandler::AltRemoteControlHandler(
  369. size_t value,
  370. struct synchronization_tool *sync)
  371. : value(value), sync(sync)
  372. { /* */ }
  373. AltRemoteControlHandler::AltRemoteControlHandler(
  374. size_t value,
  375. struct synchronization_tool *sync,
  376. const std::string& message)
  377. : value(value), sync(sync), message(message)
  378. { /* */ }
  379. bool AltRemoteControlHandler::handleGet(
  380. CivetServer *server,
  381. struct mg_connection *conn)
  382. {
  383. std::unique_lock<std::mutex> lck(sync->mtx);
  384. const struct mg_request_info *info = mg_get_request_info(conn);
  385. if (info->query_string)
  386. query = info->query_string;
  387. mg_printf(conn, "HTTP/1.1 200 OK\r\n"
  388. "Content-Type: text/plain\r\n"
  389. "Connection: close\r\n\r\n");
  390. if (message.empty())
  391. mg_printf(conn, "Event triggered.\n");
  392. else
  393. mg_printf(conn, "%s\n", message.c_str());
  394. sync->val2 = value;
  395. sync->cv.notify_all();
  396. return true;
  397. }
  398. std::string AltRemoteControlHandler::getQuery() const
  399. {
  400. return query;
  401. }