pass_communication.c 52 KB

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