pass_communication.c 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515
  1. /*
  2. * Copyright (c) 2019 Clementine Computing LLC.
  3. *
  4. * This file is part of PopuFare.
  5. *
  6. * PopuFare is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * PopuFare is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with PopuFare. If not, see <https://www.gnu.org/licenses/>.
  18. *
  19. */
  20. #include <sys/socket.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <sys/un.h>
  24. #include <netinet/in.h>
  25. #include <arpa/inet.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29. #include <errno.h>
  30. #include <poll.h>
  31. #include <time.h>
  32. #include <zlib.h>
  33. #include "../common/common_defs.h"
  34. #include "../commhub/commhub.h"
  35. #include "../commhub/client_utils.h"
  36. #include "passdb.h"
  37. #include "rules.h"
  38. #include "rfid_decoder.h"
  39. #include "fareqr.h"
  40. //----------GLOBAL STATE VARIABLES
  41. int flush_in_progress = 0; //This flag is used to tell if there is a flush in progress
  42. time_t last_sync_attempt = 0; //Time of the last sync attempt in seconds since epoch
  43. time_t last_sync_ack = 0; //Time of the last ack from the server (update, delete, or nop)
  44. int commhub_fd = -1; //File descriptor of our connection to the comm hub
  45. int server_fd = -1; //File descriptor of our connection to the sync server
  46. int zflush_in_progress = 0;
  47. void *zflush_data = NULL;
  48. int zflush_data_size = 0;
  49. int zflush_idx = 0;
  50. time_t last_piu_update = 0; //Last PIU status update
  51. pass_status real_pass_status = {0};
  52. int update_piu_status_message(int busy)
  53. {
  54. struct message_record outgoing;
  55. time_t now = time(NULL);
  56. struct tm t;
  57. char *status = "READY";
  58. int am_pm;
  59. int hour;
  60. if(busy)
  61. {
  62. status = "BUSY";
  63. }
  64. else
  65. {
  66. if( real_pass_status.flush_status == FLUSH_STATUS_APPLY )
  67. {
  68. status = "APPLY";
  69. }
  70. else if(real_pass_status.flush_status == FLUSH_STATUS_WRITE)
  71. {
  72. status = "SAVING";
  73. }
  74. else if( !rules_loaded() ||
  75. (real_pass_status.flush_status == FLUSH_STATUS_LEGACY) ||
  76. (real_pass_status.flush_status == FLUSH_STATUS_DOWNLOAD) )
  77. {
  78. status = "LOADING";
  79. }
  80. else if( !driver_stat.logged_in_driver )
  81. {
  82. status = "SEE DRIVER";
  83. }
  84. }
  85. if(commhub_fd >= 0)
  86. {
  87. localtime_r(&now, &t);
  88. if( (t.tm_hour < 12) )
  89. {
  90. am_pm = 0;
  91. if(t.tm_hour == 0)
  92. {
  93. hour = 12;
  94. }
  95. else
  96. {
  97. hour = t.tm_hour;
  98. }
  99. }
  100. else
  101. {
  102. am_pm = 1;
  103. if(t.tm_hour == 12)
  104. {
  105. hour = 12;
  106. }
  107. else
  108. {
  109. hour = t.tm_hour - 12;
  110. }
  111. }
  112. format_piu_message(&outgoing, 0, 0, 0, "%d/%d %d:%02d %s %s", t.tm_mon + 1, t.tm_mday, hour, t.tm_min, am_pm?"PM":"AM", status);
  113. send_message(commhub_fd, &outgoing);
  114. if(real_pass_status.flush_status == FLUSH_STATUS_DOWNLOAD)
  115. {
  116. format_piu_message(&outgoing, 1, 0, 0, "Downloading %d%%", real_pass_status.progress_indicator);
  117. send_message(commhub_fd, &outgoing);
  118. }
  119. else if(real_pass_status.flush_status == FLUSH_STATUS_APPLY)
  120. {
  121. format_piu_message(&outgoing, 1, 0, 0, "Applying %d%%", real_pass_status.progress_indicator);
  122. send_message(commhub_fd, &outgoing);
  123. }
  124. else if(real_pass_status.flush_status == FLUSH_STATUS_WRITE)
  125. {
  126. format_piu_message(&outgoing, 1, 0, 0, "Saving Database");
  127. send_message(commhub_fd, &outgoing);
  128. }
  129. else
  130. {
  131. format_piu_message(&outgoing, 1, 0, 0, "");
  132. send_message(commhub_fd, &outgoing);
  133. }
  134. }
  135. return 0;
  136. }
  137. //This function attempts to connect to the pass server...
  138. int connect_to_pass_server()
  139. {
  140. int fd;
  141. int retval;
  142. struct sockaddr_in addr;
  143. fd = socket(PF_INET, SOCK_STREAM, 0);
  144. if(fd < 0)
  145. return -1;
  146. addr.sin_family = AF_INET;
  147. addr.sin_port = htons(PASS_SERVER_PORT);
  148. inet_aton(PASS_SERVER_IP, &addr.sin_addr);
  149. retval = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
  150. if(retval < 0)
  151. {
  152. close(fd);
  153. return -2;
  154. }
  155. return fd;
  156. }
  157. int do_database_flush(passdb_context *ctx) {
  158. int retval;
  159. // Detach from the current pass database
  160. //
  161. detach_from_passdb(ctx);
  162. // Format a new database file...
  163. //
  164. format_new_passdb();
  165. retval = attach_to_passdb(ctx);
  166. // If we fail to attach to our new database
  167. //
  168. if( DB_FAIL(retval) ) {
  169. fprintf(stderr, "Error (%d) attaching to pass database during flush attempt\n", retval); //report failure
  170. return retval;
  171. }
  172. // Otherwise, report success.
  173. //
  174. else {
  175. printf("Pass database flushed!\n");
  176. return 0;
  177. }
  178. }
  179. int send_query_message(int fd, passdb_context *ctx)
  180. {
  181. char query[LINE_BUFFER_SIZE] = {0};
  182. int i, n;
  183. int retval;
  184. if(fd < 0)
  185. return -1;
  186. n = sprintf(query, "QUERY\t%llu\n", ctx->seq);
  187. // printf("Sending: \"%s\"\n", query);
  188. i = 0;
  189. while(i < n)
  190. {
  191. retval = send(fd, query + i, n - i, 0);
  192. if(retval <= 0)
  193. return -1;
  194. i += retval;
  195. }
  196. return 0;
  197. }
  198. int send_flushreq_message(int fd)
  199. {
  200. char query[LINE_BUFFER_SIZE] = {0};
  201. int i, n;
  202. int retval;
  203. if(fd < 0)
  204. return -1;
  205. n = sprintf(query, "QUERY\t0\n");
  206. // printf("Sending: \"%s\"\n", query);
  207. i = 0;
  208. while(i < n)
  209. {
  210. retval = send(fd, query + i, n - i, 0);
  211. if(retval <= 0)
  212. return -1;
  213. i += retval;
  214. }
  215. return 0;
  216. }
  217. // This function sends our local buspass state structure (real_pass_status) to other modules if either the force flag is set,
  218. //or if it differs from the last one received from the IPC hub.
  219. //
  220. // This function returns:
  221. //
  222. // < 0 Failure in communication (IPC socket is down...)
  223. // == 0 No news to send (force was not set and our status has not changed)
  224. // == 1 News was successfully sent.
  225. //
  226. // This is useful because often the next thing we want to do after sending a status update is update the display on the
  227. // PIU, but we only want to do that when the update represents a meaningful change which the user will notice (so as not
  228. // to flood that serial port with redundant change notifications).
  229. //
  230. int send_pass_state(int force)
  231. {
  232. struct message_record outgoing_msg;
  233. int retval;
  234. // Only actually perform the send if EITHER: The force flag has been set, OR the status message we are sending
  235. //differs from the last status message we received from ourselves via the IPC hub (which should model what other
  236. //modules think out status currently is).
  237. if(force || memcmp(&real_pass_status, &pass_stat, sizeof(real_pass_status)))
  238. {
  239. prepare_message(&outgoing_msg, MAILBOX_PASS_STATUS, &real_pass_status, sizeof(real_pass_status));
  240. retval = send_message(commhub_fd,&outgoing_msg);
  241. return (retval < 0)?retval:1;
  242. }
  243. return 0;
  244. }
  245. // This function updates our local buspass state structure (real_pass_status) from the internal state of other data structures
  246. //and using the two parameters (flush_status (see ../commhub/commhub.h for values) and a progress indicater (in percent),
  247. //a copy of our local status to other modules if it differs from the last state (using the send_pass_state() function above).
  248. int update_pass_state(int flush_status, int progress)
  249. {
  250. real_pass_status.progress_indicator = 0;
  251. switch(flush_status)
  252. {
  253. case FLUSH_STATUS_DOWNLOAD: //This means we're in the process of downloading a ZFLUSH dataset
  254. real_pass_status.flush_status = FLUSH_STATUS_DOWNLOAD;
  255. if(progress == 0) //if no progress indicator number is supplied
  256. {
  257. if(zflush_data_size != 0) //and it is possible to calculate
  258. {
  259. //use our download count / expected size to calculate a percentage
  260. real_pass_status.progress_indicator = (100 * zflush_idx) / zflush_data_size;
  261. }
  262. }
  263. else //if a progress indicator is supplied, simnply use it...
  264. {
  265. real_pass_status.progress_indicator = progress;
  266. }
  267. break;
  268. case FLUSH_STATUS_APPLY: //In the case of APPLY, WRITE, or LEGACY, just take the progress number on faith
  269. case FLUSH_STATUS_WRITE:
  270. case FLUSH_STATUS_LEGACY:
  271. {
  272. real_pass_status.flush_status = flush_status;
  273. real_pass_status.progress_indicator = progress;
  274. }
  275. break;
  276. default: //Otherwise, just let the other modules know we're feeling normal today...
  277. real_pass_status.flush_status = FLUSH_STATUS_NORMAL;
  278. break;
  279. }
  280. //inform other modules of any changes...
  281. return send_pass_state(0);
  282. }
  283. int do_zflush(passdb_context *ctx, void *data, int len);
  284. //Cleanup after (or abort in progress) a ZFLUSH attempt
  285. int zflush_cleanup()
  286. {
  287. zflush_idx = 0;
  288. flush_in_progress = 0;
  289. zflush_in_progress = 0;
  290. zflush_data_size = 0;
  291. if(zflush_data)
  292. {
  293. free(zflush_data);
  294. }
  295. zflush_data = NULL;
  296. return 0;
  297. }
  298. int handle_pass_update_request(char *line, passdb_context *ctx, int sync)
  299. {
  300. rider_record foo = {0};
  301. char buffer[LINE_BUFFER_SIZE];
  302. int input_idx = 0;
  303. int eol = 0;
  304. memset(buffer, 0, sizeof(char)*LINE_BUFFER_SIZE);
  305. //Extract the first tab-delimited field from the input line...
  306. input_idx += get_field(buffer, line + input_idx, sizeof(buffer), &eol);
  307. //If that field is blank, then we ignore this line
  308. if( buffer[0] == '\0' )
  309. {
  310. return 0;
  311. }
  312. if( !strcasecmp(buffer, "UPDATE") ) //========================================== UPDATE
  313. {
  314. //------------------------------------------------------------------ seq
  315. if( eol )
  316. {
  317. fprintf(stderr, "UPDATE: Premature end of line!\n");
  318. return -1;
  319. }
  320. //Get the next field (this should be sequence number...)
  321. input_idx += get_field(buffer, line + input_idx, sizeof(buffer), &eol);
  322. foo.seq = strtoull(buffer, NULL, 10);
  323. if( foo.seq == 0 )
  324. {
  325. fprintf(stderr, "UPDATE: Blank or zero sequence number not allowed!\n");
  326. return -1;
  327. }
  328. //------------------------------------------------------------------ ID
  329. if( eol )
  330. {
  331. fprintf(stderr, "UPDATE: Premature end of line!\n");
  332. return -1;
  333. }
  334. //Get the next field (this should be Rider ID...)
  335. input_idx += get_field(buffer, line + input_idx, sizeof(buffer), &eol);
  336. foo.id = strtoull(buffer, NULL, 10);
  337. if( foo.id == 0 )
  338. {
  339. fprintf(stderr, "UPDATE: Blank or zero rider ID not allowed!\n");
  340. return -1;
  341. }
  342. //------------------------------------------------------------------ Magstripe
  343. if( eol )
  344. {
  345. fprintf(stderr, "UPDATE: Premature end of line!\n");
  346. return -1;
  347. }
  348. //Get the next field (this should be the Magstripe Value...)
  349. input_idx += get_field(foo.magstripe_value, line + input_idx, sizeof(foo.magstripe_value), &eol);
  350. //------------------------------------------------------------------ RFID
  351. if( eol )
  352. {
  353. fprintf(stderr, "UPDATE: Premature end of line!\n");
  354. return -1;
  355. }
  356. //Get the next field (this should be the RFID Value...)
  357. input_idx += get_field(foo.rfid_value, line + input_idx, sizeof(foo.rfid_value), &eol);
  358. //------------------------------------------------------------------ Rule Name
  359. if( eol )
  360. {
  361. fprintf(stderr, "UPDATE: Premature end of line!\n");
  362. return -1;
  363. }
  364. //Get the next field (this should be the Rule Name...)
  365. input_idx += get_field(foo.rule_name, line + input_idx, sizeof(foo.rule_name), &eol);
  366. //------------------------------------------------------------------ Rule Parameter
  367. if( eol )
  368. {
  369. fprintf(stderr, "UPDATE: Premature end of line!\n");
  370. return -1;
  371. }
  372. //Get the next field (this should be the Rule Parameter...)
  373. input_idx += get_field(foo.rule_param, line + input_idx, sizeof(foo.rule_param), &eol);
  374. //If we have extra fields, that's BAD NEWS!
  375. if( !eol )
  376. {
  377. fprintf(stderr, "UPDATE: Too many fields!\n");
  378. return -1;
  379. }
  380. //If everything else is okay, go ahead and update our local database
  381. last_sync_ack = time(NULL);
  382. return update_rider(ctx, &foo, sync); //returning the status of that operation
  383. }
  384. else if( !strcasecmp(buffer, "DELETE") ) //========================================== DELETE
  385. {
  386. //------------------------------------------------------------------ seq
  387. if( eol )
  388. {
  389. fprintf(stderr, "DELETE: Premature end of line!\n");
  390. return -1;
  391. }
  392. //Get the next field (this should be sequence number...)
  393. input_idx += get_field(buffer, line + input_idx, sizeof(buffer), &eol);
  394. foo.seq = strtoull(buffer, NULL, 10);
  395. if( foo.seq == 0 )
  396. {
  397. fprintf(stderr, "DELETE: Blank or zero sequence number not allowed!\n");
  398. return -1;
  399. }
  400. //------------------------------------------------------------------ ID
  401. if( eol )
  402. {
  403. fprintf(stderr, "DELETE: Premature end of line!\n");
  404. return -1;
  405. }
  406. //Get the next field (this should be Rider ID...)
  407. input_idx += get_field(buffer, line + input_idx, sizeof(buffer), &eol);
  408. foo.id = strtoull(buffer, NULL, 10);
  409. if( foo.id == 0 )
  410. {
  411. fprintf(stderr, "DELETE: Blank or zero rider ID not allowed!\n");
  412. return -1;
  413. }
  414. //If we have extra fields, that's BAD NEWS!
  415. if( !eol )
  416. {
  417. fprintf(stderr, "DELETE: Too many fields!\n");
  418. return -1;
  419. }
  420. //If everything else is okay, go ahead and update our local database
  421. last_sync_ack = time(NULL);
  422. return delete_rider(ctx, &foo, sync); //returning the status of that operation
  423. }
  424. else if( !strcasecmp(buffer, "FLUSH") ) //========================================== FLUSH
  425. {
  426. flush_in_progress = 1;
  427. if(update_pass_state(FLUSH_STATUS_LEGACY, 0) > 0)
  428. {
  429. update_piu_status_message(0);
  430. }
  431. fprintf(stderr, "Legacy Flush Requested!\n");
  432. last_sync_ack = time(NULL);
  433. return do_database_flush(ctx);
  434. }
  435. else if( !strcasecmp(buffer, "FLUSHDONE") ) //========================================== FLUSHDONE
  436. {
  437. flush_in_progress = 0;
  438. if(update_pass_state(FLUSH_STATUS_NORMAL, 0) > 0)
  439. {
  440. update_piu_status_message(0);
  441. }
  442. fprintf(stderr, "Legacy Flush Done!\n");
  443. last_sync_ack = time(NULL);
  444. return 0;
  445. }
  446. else if( !strcasecmp(buffer, "ZFLUSH") ) //========================================== FLUSH
  447. {
  448. //------------------------------------------------------------------ seq
  449. if( eol )
  450. {
  451. fprintf(stderr, "ZFLUSH: Premature end of line!\n");
  452. return -1;
  453. }
  454. //Get the next field (this should be sequence number...)
  455. input_idx += get_field(buffer, line + input_idx, sizeof(buffer), &eol);
  456. zflush_data_size = strtoull(buffer, NULL, 10);
  457. zflush_data = malloc(zflush_data_size);
  458. if(zflush_data == NULL)
  459. {
  460. fprintf(stderr, "Can't malloc %d bytes for ZFLUSH!\n", zflush_data_size);
  461. return FAIL_MEM;
  462. }
  463. printf("ZFLUSH: Downloading %d bytes.\n", zflush_data_size);
  464. zflush_idx = 0;
  465. zflush_in_progress = 1;
  466. flush_in_progress = 1;
  467. if(update_pass_state(FLUSH_STATUS_DOWNLOAD, 0) > 0) //Let update_pass_state() calculate our download percentage
  468. {
  469. update_piu_status_message(0);
  470. }
  471. last_sync_ack = time(NULL);
  472. return 0;
  473. }
  474. else if( !strcasecmp(buffer, "ZFLUSHDONE") ) //========================================== FLUSHDONE
  475. {
  476. fprintf(stderr, "ZFlush applying...\n");
  477. if(update_pass_state(FLUSH_STATUS_APPLY, 0) > 0) //Mark that we're starting an apply operation
  478. {
  479. update_piu_status_message(0);
  480. }
  481. do_zflush(ctx, zflush_data, zflush_data_size);
  482. zflush_cleanup();
  483. if(update_pass_state(FLUSH_STATUS_NORMAL, 0) > 0)
  484. {
  485. update_piu_status_message(0);
  486. }
  487. fprintf(stderr, "ZFlush Done!\n");
  488. last_sync_ack = time(NULL);
  489. return 0;
  490. }
  491. else if( !strcasecmp(buffer, "NOP") ) //========================================== NOP (this just updates ACK time)
  492. {
  493. last_sync_ack = time(NULL);
  494. return 0;
  495. }
  496. else
  497. {
  498. fprintf(stderr, "Unrecognized command: %s\n", buffer);
  499. return -1;
  500. }
  501. }
  502. int do_zflush(passdb_context *ctx, void *data, int len)
  503. {
  504. char line[LINE_BUFFER_SIZE] = {0};
  505. z_stream foo = {0};
  506. int zretval;
  507. int retval;
  508. int i,j,k;
  509. int nout;
  510. struct message_record incoming_msg;
  511. foo.zalloc = Z_NULL;
  512. foo.zfree = Z_NULL;
  513. foo.opaque = Z_NULL;
  514. foo.next_in = zflush_data;
  515. foo.avail_in = zflush_data_size;
  516. foo.next_out = (void *)line;
  517. foo.avail_out = sizeof(line);
  518. foo.total_out = 0;
  519. // printf("do_zflush(%p, %p, %d)\n", ctx, data, len);
  520. memset(&incoming_msg, 0, sizeof(struct message_record));
  521. retval = inflateInit(&foo);
  522. if(retval != Z_OK)
  523. {
  524. fprintf(stderr, "inflateInit failed: Zlib error %d\n", retval);
  525. return FAIL_DATABASE;
  526. }
  527. retval = do_database_flush(ctx);
  528. if( DB_FAIL(retval) )
  529. {
  530. fprintf(stderr, "Database failure during ZFLUSH while performing flush\n");
  531. return retval;
  532. }
  533. do
  534. {
  535. RESET_WATCHDOG();
  536. //Respond to PING messages from the supervisor process lest we get killed off too early...
  537. while(message_socket_status(commhub_fd, MSG_RECV) & MSG_RECV)
  538. {
  539. if(get_message(commhub_fd, &incoming_msg) >= 0)
  540. {
  541. process_message(&incoming_msg);
  542. }
  543. }
  544. zretval = inflate(&foo, Z_NO_FLUSH);
  545. if( (zretval == Z_NEED_DICT) || (zretval == Z_DATA_ERROR) || (zretval == Z_MEM_ERROR) || (zretval == Z_STREAM_ERROR) )
  546. {
  547. fprintf(stderr, "Error inflating data: Zlib error %d\n", zretval);
  548. inflateEnd(&foo);
  549. return FAIL_DATABASE;
  550. }
  551. //The number of output bytes generated is the size of the buffer - number of free bytes
  552. nout = sizeof(line) - foo.avail_out;
  553. // printf("-- %d output bytes\n", nout);
  554. j = 0;
  555. //Scan through this buffer looking for EOL characters
  556. for(i=0; i < nout; i++)
  557. {
  558. if(line[i] == '\n') //if we've found one
  559. {
  560. line[i] = '\0'; //make it a terminating nul
  561. // printf("ZFLUSH->%s\n", line + j);
  562. //handle our pass update
  563. #ifdef ZFLUSH_SLOW_BUT_SAFE
  564. //In slow but safe mode, we msync() (or write()) the memory page containing each record after each update.
  565. //This is hell on the flash, and it takes a long time, but it means that we cannot POSSIBLY write a lower
  566. //sequence number record to the physical storage media before having physically written all previous
  567. //sequence numbers in the batch.
  568. retval = handle_pass_update_request(line + j, ctx, 1);
  569. #else
  570. //In fast mode, we apply all of our update to the memory window without calling msync() or write(), and then
  571. //(see below) when we're done rewriting the mmap()'d window for the local database, then we make one call
  572. //to msync() or write() and splat it all down to flash at once. This gets us a better compression ratio
  573. //on the large chunks of file which change infrequently and it produces less
  574. //filesystem fragmentation, but it means that it is theoretically possible for a power event to cause a
  575. //partial write to corrupt the local database (requiring a new flush). That being said, when running on
  576. //top of JFFS2, this should cause file truncation, which will be easily detectable and trigger another
  577. //flush request next time the application comes up.
  578. retval = handle_pass_update_request(line + j, ctx, 0);
  579. #endif
  580. if( DB_FAIL(retval) )
  581. {
  582. inflateEnd(&foo);
  583. fprintf(stderr, "Database failure during ZFLUSH while processing line \"%s\"\n", line + j);
  584. return retval;
  585. }
  586. //mark the first character of the next line
  587. j = i + 1;
  588. }
  589. }
  590. //k will be equal to the number of leftover bytes
  591. k = i - j;
  592. // printf("-- i = %d j = %d k = %d\n", i, j, k);
  593. //copy those leftovers back to the beginning
  594. for(i = 0; i < k; i++)
  595. {
  596. line[i] = line[j + i];
  597. }
  598. //and update our output buffer structure
  599. foo.next_out = (void *)(line + k);
  600. foo.avail_out = sizeof(line) - k;
  601. if(foo.avail_out == 0)
  602. {
  603. fprintf(stderr, "Line too long in decompressed ZFLUSH data!\n");
  604. inflateEnd(&foo);
  605. return FAIL_DATABASE;
  606. }
  607. // Update the other modules with our status (APPLY) and a progress indicator based on the amount of compressed data
  608. //read as a percentage of the total ZFLUSH data blob.
  609. if(update_pass_state(FLUSH_STATUS_APPLY, (foo.total_in * 100) / zflush_data_size) > 0)
  610. {
  611. update_piu_status_message(0);
  612. }
  613. } while(zretval != Z_STREAM_END);
  614. inflateEnd(&foo);
  615. //In fast mode, we have to ensure that we write our big block of changes back to secondary storage all at once
  616. #ifndef ZFLUSH_SLOW_BUT_SAFE
  617. if(update_pass_state(FLUSH_STATUS_WRITE, 0) > 0) //Let the other modules know we're performing the final write...
  618. {
  619. update_piu_status_message(0);
  620. }
  621. fprintf(stderr, "Doing one-shot file write...\n");
  622. // This resets the watchdog timer for a double-long timeframe (120 seconds these days...) allowing the write to be
  623. //slow as dirt (this is rarely needed, but if the flash was badly fragmented it can take some time to coalesce free
  624. //blocks and possibly perform some erase cycles.
  625. RESET_WATCHDOG_LONG(2);
  626. // This calls msync() if we're working with a non-broken implementation of mmap() (i.e. non-jffs2) or write()
  627. //to take our updated state from RAM and save it to the underlying file.
  628. sync_all_riders(ctx);
  629. fprintf(stderr, "Done.\n");
  630. #endif
  631. // After completing a ZFLUSH operation, we want to hang up on the server (and reconnect asap). The server should
  632. //also hang up on us after completing transmission of a ZFLUSH dataset. This effectively clears the buffers going both
  633. //ways which prevents tha case where a high communication (or server-side database) lag causes two "QUERY 0" messages
  634. //to be issued in a row, the first one triggering (correctly) a ZFLUSH which will be completed, then the server will read
  635. //the second (now obsolete) "QUERY 0" message and respond to it with another (now just useless and annoying) ZFLUSH.
  636. close(server_fd); //We just do a rude close... The server does a proper shutdown(fd, 2), and the FIN will have reached
  637. //us LONG before we execute this...
  638. server_fd = -1; //Mark the TCP connection to the server as dead so we flush buffers and restart the connection next
  639. //time through the loop.
  640. return 0;
  641. }
  642. //callback handles MAILBOX_UPDATE_PASSES
  643. message_callback_return handle_update_passes_message(struct message_record *msg, void *param)
  644. {
  645. //flag our last sync attempt as NEVER
  646. last_sync_attempt = 0;
  647. return MESSAGE_HANDLED_CONT;
  648. }
  649. //callback handles MAILBOX_FLUSH_PASSES
  650. message_callback_return handle_flush_passes_message(struct message_record *msg, void *param)
  651. {
  652. //We only want to allow a FLUSH_PASSES request to go through if the following conditions are met:
  653. if( (server_fd >= 0) && //1: We have a connection to the server
  654. (tunnel_is_up()) && //2: That connection is real (i.e. the SSH tunnel is in a known good state)
  655. (real_pass_status.flush_status == FLUSH_STATUS_NORMAL) //3: we are not currently in the middle of doing a flush...
  656. )
  657. {
  658. send_flushreq_message(server_fd);
  659. }
  660. return MESSAGE_HANDLED_CONT;
  661. }
  662. //callback handles MAILBOX_STATUS_REQUEST
  663. message_callback_return handle_status_request_message(struct message_record *msg, void *param)
  664. {
  665. // If we're responding to a status request message, we have to force a send even if it seems redundant because odds are
  666. //the requesting module just came on line and has no current status data for us.
  667. send_pass_state(1);
  668. return MESSAGE_HANDLED_CONT;
  669. }
  670. int reject_unknown_card(char *cred)
  671. {
  672. struct message_record bill_msg;
  673. struct message_record user_msg;
  674. struct message_record rider_msg;
  675. format_piu_message(&rider_msg, 1, PIU_PRIORITY_FARE, PASSENGER_MESSAGE_DURATION, "%s %s", REJECT_STR, "UNKNOWN CARD");
  676. format_driver_message(&user_msg, LOGLEVEL_REJECT, "Unknown card");
  677. format_billing_message(&bill_msg, REJECT_STR, "UNKNOWN-CARD", "", "Unknown card", cred, 0, 0);
  678. if(commhub_fd >= 0)
  679. {
  680. send_message(commhub_fd, &bill_msg);
  681. send_message(commhub_fd, &user_msg);
  682. send_message(commhub_fd, &rider_msg);
  683. return 0;
  684. }
  685. else
  686. {
  687. return -1;
  688. }
  689. }
  690. #ifdef REJECT_IF_NO_DRIVER
  691. int reject_no_driver()
  692. {
  693. struct message_record user_msg;
  694. struct message_record rider_msg;
  695. format_piu_message(&rider_msg, 1, PIU_PRIORITY_FARE, PASSENGER_MESSAGE_DURATION, "%s", "SEE DRIVER");
  696. format_driver_message(&user_msg, LOGLEVEL_REJECT, "Not Logged In!");
  697. if(commhub_fd >= 0)
  698. {
  699. send_message(commhub_fd, &user_msg);
  700. send_message(commhub_fd, &rider_msg);
  701. return 0;
  702. }
  703. else
  704. {
  705. return -1;
  706. }
  707. }
  708. #endif
  709. message_callback_return handle_token_mag_message(struct message_record *msg, void *param)
  710. {
  711. int idx;
  712. char cred[LINE_BUFFER_SIZE] = {0};
  713. passdb_context *ctx = (passdb_context *)param;
  714. if(!ctx)
  715. return MESSAGE_HANDLED_CONT;
  716. update_piu_status_message(1);
  717. #ifdef REJECT_IF_NO_DRIVER
  718. if( (driver_stat.logged_in_driver <= 0) || (stop_stat.paddle <= 0) )
  719. {
  720. reject_no_driver();
  721. return MESSAGE_HANDLED_CONT;
  722. }
  723. #endif
  724. idx = smart_find_mag(ctx, (char *)msg->payload, cred);
  725. if(idx < 0)
  726. {
  727. reject_unknown_card(cred);
  728. }
  729. else
  730. {
  731. process_rider(ctx, idx, cred);
  732. }
  733. return MESSAGE_HANDLED_CONT;
  734. }
  735. message_callback_return handle_token_rfid_message(struct message_record *msg, void *param)
  736. {
  737. int idx;
  738. char cred[LINE_BUFFER_SIZE] = {0};
  739. passdb_context *ctx = (passdb_context *)param;
  740. if(!ctx)
  741. return MESSAGE_HANDLED_CONT;
  742. update_piu_status_message(1);
  743. #ifdef REJECT_IF_NO_DRIVER
  744. if( (driver_stat.logged_in_driver <= 0) || (stop_stat.paddle <= 0) )
  745. {
  746. reject_no_driver();
  747. return MESSAGE_HANDLED_CONT;
  748. }
  749. #endif
  750. idx = smart_find_rf(ctx, (char *)msg->payload, cred);
  751. if(idx < 0)
  752. {
  753. reject_unknown_card(cred);
  754. }
  755. else
  756. {
  757. process_rider(ctx, idx, cred);
  758. }
  759. return MESSAGE_HANDLED_CONT;
  760. }
  761. message_callback_return handle_token_qr_message(struct message_record *msg, void *param) {
  762. int idx, r;
  763. char cred[LINE_BUFFER_SIZE] = {0};
  764. passdb_context *ctx = (passdb_context *)param;
  765. char clear_payload[MAX_PAYLOAD_LENGTH] = {0};
  766. if (!ctx) { return MESSAGE_HANDLED_CONT; }
  767. update_piu_status_message(1);
  768. #ifdef REJECT_IF_NO_DRIVER
  769. if( (driver_stat.logged_in_driver <= 0) || (stop_stat.paddle <= 0) ) {
  770. reject_no_driver();
  771. return MESSAGE_HANDLED_CONT;
  772. }
  773. #endif
  774. //---
  775. r = fareqr_lookup_decode(QRSEED_FILE, (char *)(msg->payload), clear_payload);
  776. if (r<0) {
  777. reject_unknown_card(cred);
  778. return MESSAGE_HANDLED_CONT;
  779. }
  780. //---
  781. idx = smart_find_mag(ctx, (char *)clear_payload, cred);
  782. if (idx < 0) { reject_unknown_card(cred); }
  783. else { process_rider(ctx, idx, cred); }
  784. return MESSAGE_HANDLED_CONT;
  785. }
  786. message_callback_return update_anti_passback_cache(struct message_record *msg, void *param)
  787. {
  788. apb_flush_if_needed();
  789. return MESSAGE_HANDLED_CONT;
  790. }
  791. message_callback_return handle_rule_call(struct message_record *msg, void *param)
  792. {
  793. process_driver_rulecall( (driver_rulecall *)msg->payload );
  794. return MESSAGE_HANDLED_CONT;
  795. }
  796. void maintain_ipc_hub_connect(char *progname)
  797. {
  798. struct message_record outgoing_msg;
  799. if(commhub_fd < 0) //if we have no connection to the communication hub
  800. {
  801. commhub_fd = connect_to_message_server(progname); //try and get one
  802. // printf("commhub_fd = %d\n", commhub_fd);
  803. if(commhub_fd >= 0) //if it worked
  804. {
  805. //Subscribe to the command mailboxes we act on
  806. prepare_message(&outgoing_msg, MAILBOX_SUBSCRIBE, MAILBOX_TOKEN_MAG, strlen(MAILBOX_TOKEN_MAG));
  807. send_message(commhub_fd,&outgoing_msg);
  808. prepare_message(&outgoing_msg, MAILBOX_SUBSCRIBE, MAILBOX_TOKEN_RFID, strlen(MAILBOX_TOKEN_RFID));
  809. send_message(commhub_fd,&outgoing_msg);
  810. prepare_message(&outgoing_msg, MAILBOX_SUBSCRIBE, MAILBOX_TOKEN_QR, strlen(MAILBOX_TOKEN_QR));
  811. send_message(commhub_fd,&outgoing_msg);
  812. prepare_message(&outgoing_msg, MAILBOX_SUBSCRIBE, MAILBOX_FLUSH_PASSES, strlen(MAILBOX_FLUSH_PASSES));
  813. send_message(commhub_fd,&outgoing_msg);
  814. prepare_message(&outgoing_msg, MAILBOX_SUBSCRIBE, MAILBOX_UPDATE_PASSES, strlen(MAILBOX_UPDATE_PASSES));
  815. send_message(commhub_fd,&outgoing_msg);
  816. prepare_message(&outgoing_msg, MAILBOX_SUBSCRIBE, MAILBOX_RULE_CALL, strlen(MAILBOX_RULE_CALL));
  817. send_message(commhub_fd,&outgoing_msg);
  818. //Subscribe to the relevant status management mailboxes
  819. subscribe_to_default_messages(commhub_fd);
  820. //Request updated status information...
  821. prepare_message(&outgoing_msg, MAILBOX_STATUS_REQUEST, "", 0);
  822. send_message(commhub_fd,&outgoing_msg);
  823. }
  824. }
  825. }
  826. int passdb_context_alloc(passdb_context *ctx) {
  827. ctx->logical_card_id_hash = (rider_node **)malloc(sizeof(rider_node *)*STORED_PASS_HASH);
  828. if (!(ctx->logical_card_id_hash)) { return -1; }
  829. ctx->rider_mag_hash = (rider_node **)malloc(sizeof(rider_node *)*STORED_PASS_HASH);
  830. if (!(ctx->rider_mag_hash)) { return -1; }
  831. ctx->rider_rf_hash = (rider_node **)malloc(sizeof(rider_node *)*STORED_PASS_HASH);
  832. if (!(ctx->rider_rf_hash)) { return -1; }
  833. memset(ctx->logical_card_id_hash, 0, sizeof(rider_node **)*STORED_PASS_HASH);
  834. memset(ctx->rider_mag_hash, 0, sizeof(rider_node **)*STORED_PASS_HASH);
  835. memset(ctx->rider_rf_hash, 0, sizeof(rider_node **)*STORED_PASS_HASH);
  836. return 0;
  837. }
  838. void passdb_context_dealloc(passdb_context *ctx) {
  839. if (ctx->logical_card_id_hash) { free(ctx->logical_card_id_hash); }
  840. if (ctx->rider_mag_hash) { free(ctx->rider_mag_hash); }
  841. if (ctx->rider_rf_hash) { free(ctx->rider_rf_hash); }
  842. }
  843. int main(int argc, char **argv)
  844. {
  845. struct pollfd fds[2];
  846. int nfds = 0;
  847. int poll_return = 0;
  848. int read_return = 0;
  849. int i;
  850. struct message_record incoming_msg;
  851. char input_line[LINE_BUFFER_SIZE] = {0};
  852. int input_idx = 0;
  853. int checked_idx = 0;
  854. #ifdef DEBUG_PRINT
  855. long long int _usec_now, _usec_prv, _usec_del;
  856. _usec_now = get_usec_time();
  857. _usec_prv = _usec_now;
  858. _usec_del = 60000000;
  859. #endif
  860. passdb_context ctx = {0};
  861. passdb_context_alloc(&ctx);
  862. //------------------
  863. memset(input_line, 0, sizeof(char)*LINE_BUFFER_SIZE);
  864. memset(&incoming_msg, 0, sizeof(struct message_record));
  865. //------------------
  866. configure_signal_handlers(argv[0]);
  867. maintain_ipc_hub_connect(argv[0]);
  868. read_return = attach_to_passdb(&ctx);
  869. if( read_return < 0 )
  870. {
  871. fprintf(stderr, "Database is missing or corrupt. Attempting to format new database.\n");
  872. read_return = format_new_passdb();
  873. if( read_return < 0 )
  874. {
  875. fprintf(stderr, "Database cannot be created. Aborting!\n");
  876. return -1;
  877. }
  878. else
  879. {
  880. read_return = attach_to_passdb(&ctx);
  881. if( read_return < 0 )
  882. {
  883. fprintf(stderr, "New database is ALSO missing or corrupt. Aborting.\n");
  884. return -1;
  885. }
  886. }
  887. }
  888. //Register our default keep-up-with-system status callbacks
  889. register_system_status_callbacks();
  890. //Add our module-specific callbacks
  891. register_dispatch_callback(MAILBOX_UPDATE_PASSES, CALLBACK_USER(1), handle_update_passes_message, NULL);
  892. register_dispatch_callback(MAILBOX_FLUSH_PASSES, CALLBACK_USER(2), handle_flush_passes_message, NULL);
  893. register_dispatch_callback(MAILBOX_STATUS_REQUEST, CALLBACK_USER(3), handle_status_request_message, NULL);
  894. register_dispatch_callback(MAILBOX_TOKEN_RFID, CALLBACK_USER(4), handle_token_rfid_message, &ctx);
  895. register_dispatch_callback(MAILBOX_TOKEN_MAG, CALLBACK_USER(5), handle_token_mag_message, &ctx);
  896. register_dispatch_callback(MAILBOX_RULE_CALL, CALLBACK_USER(6), handle_rule_call, &ctx);
  897. //Handle status updates which require us to check expiration of the anti-passback cache
  898. register_dispatch_callback(MAILBOX_GPS_STATUS, CALLBACK_USER(6), update_anti_passback_cache, NULL);
  899. register_dispatch_callback(MAILBOX_STOP_STATUS, CALLBACK_USER(7), update_anti_passback_cache, NULL);
  900. register_dispatch_callback(MAILBOX_TOKEN_QR, CALLBACK_USER(8), handle_token_qr_message, &ctx);
  901. while( exit_request_status == EXIT_REQUEST_NONE )
  902. {
  903. time_t now = time(NULL);
  904. RESET_WATCHDOG();
  905. #ifdef DEBUG_PRINT
  906. _usec_now = get_usec_time();
  907. if ((_usec_now - _usec_prv) > _usec_del) {
  908. printf("[%lli] passdb: heartbeat\n", get_usec_time());
  909. _usec_prv = _usec_now;
  910. }
  911. #endif
  912. maintain_ipc_hub_connect(argv[0]);
  913. if( (now - last_piu_update) > 0)
  914. {
  915. update_piu_status_message(0);
  916. last_piu_update = now;
  917. }
  918. if(server_fd < 0) //If we don't have a connection to the sync server...
  919. {
  920. if( (now - last_sync_attempt) > DEFAULT_CONNECT_RETRY ) //See if it is time to try again
  921. {
  922. if( tunnel_is_up() ) //and if the tunnel thinks it is up
  923. {
  924. server_fd = connect_to_pass_server(); //if so, try again...
  925. if(server_fd >= 0) //if it worked
  926. {
  927. input_idx = 0; //reset our buffer index
  928. last_sync_attempt = 0;
  929. zflush_cleanup();;
  930. }
  931. else
  932. {
  933. last_sync_attempt = now;
  934. }
  935. }
  936. }
  937. }
  938. if(!rules_loaded())
  939. {
  940. load_rules(RULES_FILE);
  941. }
  942. if(rfid_pattern_loaded() <= 0)
  943. {
  944. load_rfid_decode_patterns(RFID_PATTERN_FILE);
  945. }
  946. if(hup_request_status)
  947. {
  948. hup_request_status = 0;
  949. unload_rules();
  950. load_rules(RULES_FILE);
  951. load_rfid_decode_patterns(RFID_PATTERN_FILE);
  952. }
  953. nfds=0;
  954. if(server_fd >= 0)
  955. {
  956. fds[nfds].fd = server_fd;
  957. fds[nfds].events = POLLIN;
  958. if( (now - last_sync_attempt) > DEFAULT_PASS_SYNC_RETRY )
  959. {
  960. // printf("We want to sync...\n");
  961. fds[nfds].events |= POLLOUT;
  962. }
  963. nfds++;
  964. }
  965. if(commhub_fd >= 0)
  966. {
  967. fds[nfds].fd = commhub_fd;
  968. fds[nfds].events = POLLIN;
  969. nfds++;
  970. }
  971. if(nfds > 0)
  972. {
  973. poll_return = poll(fds, nfds, POLL_TIMEOUT);
  974. }
  975. else
  976. {
  977. usleep(POLL_TIMEOUT * 1000);
  978. poll_return = 0;
  979. }
  980. if(poll_return <= 0)
  981. {
  982. continue;
  983. }
  984. for(i=0; i < nfds; i++)
  985. {
  986. if( fds[i].fd == server_fd )
  987. {
  988. if(fds[i].revents & POLLIN) //If we just got some input...
  989. {
  990. if(zflush_in_progress) //And we're in the middle of downloading ZFLUSH data
  991. {
  992. //Read it into our ZFLUSH buffer
  993. read_return = recv(fds[i].fd, zflush_data + zflush_idx, zflush_data_size - zflush_idx, 0);
  994. //If the socket has closed politely (0), or had an error other than EINTR...
  995. if( (read_return == 0) || ((read_return < 0) && (errno != EINTR)) )
  996. {
  997. printf("Lost touch with server. This may be OK if we just finished downloading ZFLUSH data\n");
  998. close(server_fd);
  999. server_fd = -1;
  1000. break;
  1001. }
  1002. else
  1003. {
  1004. if(read_return > 0) //Otherwise, if we got some real data
  1005. {
  1006. zflush_idx += read_return; //advance our download pointer
  1007. //We want to let the update_pass_state() function compute our progress bar...
  1008. update_pass_state(FLUSH_STATUS_DOWNLOAD, 0);
  1009. update_piu_status_message(0);
  1010. last_sync_attempt = now; //remember our last sync time
  1011. if(zflush_idx == zflush_data_size) //if we've got the whole shebang...
  1012. {
  1013. //Flag that we're done downloading zflush blob and returning to command mode...
  1014. zflush_in_progress = 0;
  1015. // We don't have to do anything else about this, because the next thing we will hear
  1016. //from the server is ZFLUSHDONE which will cause us to apply our downloaded zflush data.
  1017. }
  1018. }
  1019. }
  1020. }
  1021. else //If we are not in the middle of a ZFLUSH
  1022. {
  1023. read_return = recv(fds[i].fd, input_line + input_idx, sizeof(input_line) - input_idx, 0);
  1024. //If the socket has closed politely (0), or had an error other than EINTR...
  1025. if( (read_return == 0) || ((read_return < 0) && (errno != EINTR)) )
  1026. {
  1027. printf("Lost touch with server.\n");
  1028. close(server_fd);
  1029. server_fd = -1;
  1030. break;
  1031. }
  1032. else
  1033. {
  1034. if(read_return > 0) //and we got some real data
  1035. {
  1036. input_idx += read_return; //advance our input index
  1037. do //loop through the data we've received...
  1038. {
  1039. if(zflush_in_progress) //if we have begun a ZFLUSH at some point,
  1040. {
  1041. if(input_idx >= zflush_data_size)
  1042. {
  1043. int j,k;
  1044. memcpy(zflush_data, input_line, zflush_data_size);
  1045. zflush_idx = zflush_data_size;
  1046. zflush_in_progress = 0;
  1047. k = input_idx - zflush_data_size;
  1048. for(j = 0; j < k; j++)
  1049. {
  1050. input_line[j] = input_line[j + zflush_data_size];
  1051. }
  1052. input_idx = j;
  1053. checked_idx = 0;
  1054. }
  1055. else
  1056. {
  1057. // Steal the rest of our input buffer and tack it on to the beginning of the zflush
  1058. //buffer. We do this because otherwise we'd have the beginning of the zflush data blob
  1059. //sitting around collecting dust in the line buffer and we'd download the rest into the
  1060. //zflush buffer and be unable to process it because the beginning would still be
  1061. //sitting around in this other buffer.
  1062. memcpy(zflush_data, input_line, input_idx);
  1063. zflush_idx = input_idx; //advance the zflush buffer index appropriately
  1064. checked_idx = input_idx = 0; //clear our line buffer index as it is now empty
  1065. last_sync_attempt = now; //mark our last sync time as now
  1066. //printf("Added %d leftover bytes to zflush_data\n", input_idx);
  1067. break; //break out of the do loop since we're done with our input buffer
  1068. }
  1069. }
  1070. //Advance until we either hit the end of the buffer, or we hit a line-terminator
  1071. while(checked_idx < input_idx)
  1072. {
  1073. if( (input_line[checked_idx] == '\r') || (input_line[checked_idx] == '\n') )
  1074. {
  1075. break;
  1076. }
  1077. else
  1078. {
  1079. checked_idx++;
  1080. }
  1081. }
  1082. //If we didn't hit the end of the input... (meaning we got a whole line...)
  1083. if(checked_idx != input_idx)
  1084. {
  1085. int j,k;
  1086. //Null terminate the line we got as a string...
  1087. input_line[checked_idx] = '\0';
  1088. //printf("Got Command \"%s\"\n", input_line);
  1089. if( handle_pass_update_request(input_line, &ctx, 1) < 0 )
  1090. {
  1091. // printf("Command Failed: \"%s\"\n", input_line);
  1092. }
  1093. else
  1094. {
  1095. real_pass_status.last_ack_time = now;
  1096. }
  1097. last_sync_attempt = now; //remember this server contact time
  1098. real_pass_status.last_sync_time = now; //add it to our passdb status
  1099. send_pass_state(0); //update other modules if this represents a change
  1100. // Now that we've done that, we can bump the rest of characters to the beginning
  1101. //of the next line...
  1102. k = input_idx - (checked_idx + 1);
  1103. //copy those characters the the beginning of the buffer...
  1104. for(j=0; j < k; j++)
  1105. {
  1106. input_line[j] = input_line[j + checked_idx + 1];
  1107. }
  1108. input_idx = j; //Move the index to point to the next free byte in the buffer
  1109. checked_idx = 0; // Move the 'checked' index to the beginning so that next time
  1110. //we start counting index 0 as the beginning of the next line when
  1111. //it is time to start scanning for EOL.
  1112. }
  1113. // If we have hit an overflow condition such that our buffer is full and no newline
  1114. //has been received, we want to hang up on the server and try again because something is
  1115. //seriously borked...
  1116. if(input_idx == sizeof(input_line))
  1117. {
  1118. fprintf(stderr, "Input overrun from server (line too long).\n");
  1119. close(server_fd);
  1120. server_fd = -1;
  1121. break;
  1122. }
  1123. } while(checked_idx < input_idx); // While we have unchecked data (that we have yet to check
  1124. //for containing an end-of-line.
  1125. }
  1126. }
  1127. }
  1128. }
  1129. else //Be sure we process all input before closing a remotely closed socket...
  1130. {
  1131. //If we've lost connection, break this loop and poll all over again
  1132. if(fds[i].revents & (POLLERR | POLLHUP | POLLNVAL))
  1133. {
  1134. printf("Lost touch with server.\n");
  1135. close(server_fd);
  1136. server_fd = -1;
  1137. break;
  1138. }
  1139. }
  1140. if(fds[i].revents & POLLOUT) //If we have flagged that we intend to send a query and poll says it's OK...
  1141. {
  1142. // printf("Trying to write to server...\n");
  1143. if(real_pass_status.flush_status == FLUSH_STATUS_NORMAL)
  1144. {
  1145. send_query_message(server_fd, &ctx);
  1146. real_pass_status.last_sync_time = now;
  1147. send_pass_state(0);
  1148. }
  1149. else
  1150. {
  1151. printf("Skipping query opportunity because we are mid-flush.\n");
  1152. }
  1153. //and then update our last sync attempt time
  1154. last_sync_attempt = now;
  1155. }
  1156. }
  1157. else if( fds[i].fd == commhub_fd )
  1158. {
  1159. //If we've lost connection, break this loop and poll all over again
  1160. if(fds[i].revents & (POLLERR | POLLHUP | POLLNVAL))
  1161. {
  1162. close(commhub_fd);
  1163. commhub_fd = -1;
  1164. break;
  1165. }
  1166. if(fds[i].revents & POLLIN)
  1167. {
  1168. // printf("Trying to read from hub...\n");
  1169. read_return = get_message(commhub_fd, &incoming_msg);
  1170. if( read_return < 0 )
  1171. {
  1172. close(commhub_fd);
  1173. commhub_fd = -1;
  1174. break;
  1175. }
  1176. process_message(&incoming_msg); //This passes the received message through the callback list
  1177. }
  1178. }
  1179. }
  1180. }
  1181. printf("Detatching from Pass Database\n");
  1182. detach_from_passdb(&ctx);
  1183. passdb_context_dealloc(&ctx);
  1184. printf("Closing connections\n");
  1185. if(server_fd >= 0)
  1186. {
  1187. close(server_fd);
  1188. server_fd = -1;
  1189. }
  1190. if(commhub_fd >= 0)
  1191. {
  1192. close(commhub_fd);
  1193. server_fd = -1;
  1194. }
  1195. printf("Unloading rules...\n");
  1196. unload_rules();
  1197. printf("Goodbye.\n");
  1198. return 0;
  1199. }