pass_communication.c 48 KB

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