commserver.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545
  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/un.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <unistd.h>
  25. #include <fcntl.h>
  26. #include <poll.h>
  27. #include <errno.h>
  28. #include <signal.h>
  29. #include "../common/common_defs.h"
  30. #include "commhub.h"
  31. // 10 seconds
  32. //
  33. #define COMMHUB_POLL_TIME (10000)
  34. //#define COMMHUB_DEBUG
  35. // Our listening socket
  36. //
  37. int listener_socket = -1;
  38. // Our list of user mailboxes
  39. //
  40. struct mailbox_record *mailboxes = NULL;
  41. // Our list of clients subscribed for wiretap access
  42. //
  43. struct subscriber_record *wiretap_list = NULL;
  44. // Our list of all clients not in wiretap mode (to prevent duplicate broadcasts)
  45. //
  46. struct subscriber_record *broadcast_list = NULL;
  47. // Our list of all clients (for fd/pid tracking)
  48. //
  49. struct subscriber_record *master_list = NULL;
  50. // Our active client count
  51. //
  52. int num_clients = 0;
  53. // A buffer to hold the poll() file descriptor table
  54. //
  55. struct pollfd fds[NUM_SUPPORTED_CLIENTS + 1];
  56. //state_info_t state_info = {0};
  57. int set_blocking_mode(int fd, int blocking) {
  58. int retval;
  59. int newflags;
  60. newflags = fcntl(fd, F_GETFL);
  61. if (newflags >= 0) {
  62. if(blocking) {
  63. newflags &= ~O_NONBLOCK;
  64. }
  65. else {
  66. newflags |= O_NONBLOCK;
  67. }
  68. retval = fcntl(fd, F_SETFL, newflags);
  69. if(retval) {
  70. printf("Cannot set O_NONBLOCK on socket %d to %s!\n", fd, blocking?"ON":"OFF");
  71. return -1;
  72. }
  73. }
  74. else {
  75. printf("Cannot get flags on socket %d! [%d / %X]\n", fd, newflags, newflags);
  76. return -1;
  77. }
  78. return 0;
  79. }
  80. #ifdef COMMHUB_O_NONBLOCK
  81. #define DO_SEND_MESSAGE(ret, fd, msg) {set_blocking_mode((fd),0); ret = send_message((fd), (msg)); set_blocking_mode((fd),1);}
  82. #else
  83. #define DO_SEND_MESSAGE(ret, fd, msg) {ret = send_message((fd), (msg));}
  84. #endif
  85. void debug_traverse_single_list(struct subscriber_record *p) {
  86. while(p) {
  87. printf(" [FD: %d PID: %d Prog: %s]", p->clientfd, p->pid, p->progname);
  88. p = p->next;
  89. }
  90. printf("\n");
  91. }
  92. // This function traverses the global state data structures and prints out a visual indication of state
  93. //
  94. int debug_traverse() {
  95. struct mailbox_record *p;
  96. printf("-------------------------------------------------\n");
  97. printf("ALL:");
  98. debug_traverse_single_list(master_list); //iterate through the master list
  99. printf("WIRETAP:");
  100. debug_traverse_single_list(wiretap_list); //iterate through the wiretap list
  101. printf("BROADCAST:");
  102. debug_traverse_single_list(broadcast_list); //do the same for the broadcast list
  103. printf("---User Lists---\n");
  104. p = mailboxes; //then iterate through each generic (user) mailbox
  105. while (p) {
  106. // display the mailbox name
  107. //
  108. printf("%s:",p->mailbox_name);
  109. debug_traverse_single_list(p->clients);
  110. p = p->next;
  111. }
  112. printf("\n");
  113. return 0;
  114. }
  115. void update_client_identifiers(struct subscriber_record *p, pid_t pid, char *progname) {
  116. if(!p) {
  117. return;
  118. }
  119. p->pid = pid;
  120. // if we have a program name, store it
  121. //
  122. if(progname) {
  123. strncpy(p->progname, progname, MAX_MODULE_NAME_LENGTH);
  124. p->progname[MAX_MODULE_NAME_LENGTH - 1] = '\0';
  125. }
  126. // otherwise, set a blank string
  127. else {
  128. memset(p->progname, '\0', MAX_MODULE_NAME_LENGTH);
  129. }
  130. }
  131. // This function adds a subscriber to a subscriber list (usually a mailbox or a 'special' list)
  132. // It is passed a file descriptor, optional PID, and a pointer to the listhead (so that we can insert at the head if we want)
  133. //
  134. int add_client(int fd, pid_t pid, char *progname, struct subscriber_record **list) {
  135. struct subscriber_record *p, *q;
  136. q = NULL;
  137. // iterate through all items
  138. //
  139. p = *list;
  140. while(p) {
  141. // the client is already on the list
  142. //
  143. if(p->clientfd == fd) {
  144. // update the PID and progname anyway
  145. //
  146. update_client_identifiers(p, pid, progname);
  147. return 0;
  148. }
  149. // move our pointers along
  150. //
  151. q = p;
  152. p = p->next;
  153. }
  154. // allocate a new subscriber_record structure
  155. //
  156. p = (struct subscriber_record *) malloc(sizeof(struct subscriber_record));
  157. if(p == NULL) {
  158. return -1;
  159. }
  160. // clear it and populate it
  161. memset(p,0,sizeof(struct subscriber_record));
  162. p->clientfd = fd;
  163. p->next = NULL;
  164. update_client_identifiers(p, pid, progname); //set our pid and progname
  165. // if we're not at the list head
  166. //
  167. if(q) {
  168. // insert at the end
  169. //
  170. q->next = p;
  171. }
  172. // if this is the list head (empty list)
  173. //
  174. else {
  175. // replace the head with our new node.
  176. //
  177. *list = p;
  178. }
  179. return 0;
  180. }
  181. // This function deletes a client from a subscriber list (again we pass a pointer to the listhead).
  182. //
  183. int del_client(int fd, struct subscriber_record **list) {
  184. struct subscriber_record *p, *q;
  185. q = NULL;
  186. // iterate through our list
  187. //
  188. p = *list;
  189. while(p) {
  190. // if we find our client
  191. //
  192. if (p->clientfd == fd) {
  193. // and we're not at the head of the list
  194. //
  195. if(q) {
  196. // snip it out
  197. //
  198. q->next = p->next;
  199. }
  200. // otherwise
  201. //
  202. else {
  203. // bump the listhead down one
  204. //
  205. *list = p->next;
  206. }
  207. // free the deleted node
  208. //
  209. free(p);
  210. // and return
  211. //
  212. return 0;
  213. }
  214. // advance our pointers
  215. //
  216. q=p;
  217. p=p->next;
  218. }
  219. // client not found
  220. //
  221. return -1;
  222. }
  223. // This function subscribes a client to a user mailbox. It is passed the client data (fd and pid)
  224. // as well as a mailbox name to search for.
  225. //
  226. int subscribe_client(int fd, pid_t pid, char *progname, char *mailbox) {
  227. struct mailbox_record *p, *q;
  228. if(mailbox == NULL) {
  229. return -1;
  230. }
  231. q = NULL;
  232. // traverse the mailboxes list
  233. //
  234. p = mailboxes;
  235. while(p) {
  236. // if we found a match
  237. //
  238. if( !strncmp(mailbox, p->mailbox_name, MAILBOX_NAME_MAX) ) {
  239. // try and add the client
  240. //
  241. return add_client(fd, pid, progname, &p->clients);
  242. }
  243. q = p; //advance our pointers
  244. p = p->next;
  245. }
  246. //if we have not found a mailbox, create one
  247. //
  248. p = (struct mailbox_record *) malloc(sizeof(struct mailbox_record));
  249. if(p == NULL) {
  250. return -1;
  251. }
  252. // clear the memory
  253. //
  254. memset(p, 0, sizeof(struct mailbox_record));
  255. // fill the mailbox name
  256. //
  257. strncpy(p->mailbox_name, mailbox, MAILBOX_NAME_MAX);
  258. p->mailbox_name[MAILBOX_NAME_MAX] = '\0';
  259. // add our shiny new subscriber
  260. //
  261. add_client(fd, pid, progname, &p->clients);
  262. p->next = NULL;
  263. // if we're not adding to an empty list
  264. //
  265. if(q) {
  266. q->next = p; //insert at the end
  267. }
  268. // otherwise
  269. //
  270. else {
  271. mailboxes = p; //replace the listhead
  272. }
  273. return 0;
  274. }
  275. //This function unsubscriber a client from a user mailbox
  276. //
  277. int unsubscribe_client(int fd, char *mailbox) {
  278. struct mailbox_record *p, *q;
  279. int retval;
  280. if(mailbox == NULL) {
  281. return -1;
  282. }
  283. q = NULL;
  284. // traverse the mailbox list
  285. //
  286. p = mailboxes;
  287. while(p) {
  288. // if we found a match
  289. //
  290. if( !strncmp(mailbox, p->mailbox_name, MAILBOX_NAME_MAX) ) {
  291. // try to unsubscribe
  292. //
  293. retval = del_client(fd, &p->clients);
  294. // if we just unsubscribed our last client, delete this list.
  295. //
  296. if(p->clients == NULL) {
  297. // if this is not the first list item
  298. //
  299. if(q) {
  300. //snip it from the middle
  301. //
  302. q->next = p->next;
  303. }
  304. else {
  305. // snip from the beginning (tweaking the listhead)
  306. //
  307. mailboxes = p->next;
  308. }
  309. //and free it
  310. //
  311. free(p);
  312. }
  313. // return the result of the removal
  314. //
  315. return retval;
  316. }
  317. // advance our pointers
  318. //
  319. q = p;
  320. p = p->next;
  321. }
  322. // not found!
  323. //
  324. return -1;
  325. }
  326. // This function scans the mailboxes to find the named mailbox, and if it is found
  327. // returns the client list associated with that mailbox. This is used in delivery.
  328. //
  329. struct subscriber_record *find_mailbox(char *mailbox) {
  330. struct mailbox_record *p;
  331. if(mailbox == NULL) {
  332. return NULL;
  333. }
  334. // iterate through the mailbox list
  335. //
  336. p = mailboxes;
  337. while(p) {
  338. // if we found a match
  339. //
  340. if( !strncmp(mailbox, p->mailbox_name, MAILBOX_NAME_MAX) ) {
  341. // return the client list associated
  342. //
  343. return p->clients;
  344. }
  345. // advance our pointer
  346. //
  347. p = p->next;
  348. }
  349. // not found
  350. //
  351. return NULL;
  352. }
  353. // This function walks all global state structures to purge all reference to a (disconnected) client
  354. //
  355. int purge_client(int fd) {
  356. struct mailbox_record *p, *q;
  357. // remove the client from all system lists
  358. //
  359. del_client(fd, &broadcast_list);
  360. del_client(fd, &wiretap_list);
  361. del_client(fd, &master_list);
  362. q = NULL;
  363. // then iterate through user mailboxes
  364. //
  365. p = mailboxes;
  366. while(p) {
  367. // removing the client when it is present
  368. //
  369. del_client(fd, &p->clients);
  370. // if we just unsubscribed our last client on this list, delete the list.
  371. //
  372. if(p->clients == NULL) {
  373. // save this pointer to delete after advancement
  374. //
  375. struct mailbox_record *r = p;
  376. // if we're deleting from the middle
  377. //
  378. if(q) {
  379. // snip out
  380. //
  381. q->next = p->next;
  382. }
  383. else {
  384. // advance the listhead
  385. //
  386. mailboxes = p->next;
  387. }
  388. // advance our pointer
  389. //
  390. p = p->next;
  391. // free the deleted node
  392. //
  393. free(r);
  394. // continue with the advanced pointer
  395. //
  396. continue;
  397. }
  398. // advance our pointers
  399. //
  400. q = p;
  401. p = p->next;
  402. }
  403. #ifdef COMMHUB_DEBUG
  404. printf("Purged client %d\n", fd);
  405. debug_traverse();
  406. #endif
  407. return 0;
  408. }
  409. int create_listener(char *pathname) {
  410. int fd;
  411. struct sockaddr_un addr;
  412. int len;
  413. int retval;
  414. // create a UNIX domain socket of type SOCK_SEQPACKET
  415. //
  416. fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
  417. if(fd < 0) {
  418. return -1;
  419. }
  420. // prepare our bind address structure
  421. //
  422. addr.sun_family = AF_UNIX;
  423. strncpy(addr.sun_path, pathname, sizeof(addr.sun_path) - 1);
  424. addr.sun_path[sizeof(addr.sun_path) - 1]='\0';
  425. // unlink any existing socket or file that lives there
  426. //
  427. unlink(pathname);
  428. // calculate the address length
  429. //
  430. len = strlen(pathname) + sizeof(addr.sun_family);
  431. // and perform the bind
  432. //
  433. retval = bind(fd,(struct sockaddr *)&addr,len);
  434. if(retval) {
  435. close(fd);
  436. return -2;
  437. }
  438. // set the socket in listening mode...
  439. //
  440. retval=listen(fd, 5);
  441. if(retval) {
  442. close(fd);
  443. return -3;
  444. }
  445. return fd;
  446. }
  447. // This function walks the master client list and rebuilds the file descriptor set used by poll()
  448. // to wait for input.
  449. //
  450. int rebuild_client_fds() {
  451. struct subscriber_record *p = master_list;
  452. int i = 0;
  453. // iterate through our master list
  454. //
  455. while(p) {
  456. // stopping if we have exceeded the space in the fds table.
  457. //
  458. if(i >= NUM_SUPPORTED_CLIENTS) {
  459. break;
  460. }
  461. // set the fd for this table slot
  462. //
  463. fds[i + 1].fd = p->clientfd;
  464. // specify that we're waiting for input
  465. //
  466. fds[i + 1].events = POLLIN;
  467. // count it
  468. //
  469. i++;
  470. // and advance our pointer
  471. //
  472. p=p->next;
  473. }
  474. // remember the number of clients we have so that we can reject new ones if they are
  475. //
  476. num_clients = i;
  477. // in excess of our table size.
  478. //
  479. return i;
  480. }
  481. // This function accepts a new client on the listener_socket and either rejects it with an error (if our table is full) or
  482. // accepts it and places it in the master (and broadcast) lists.
  483. //
  484. int accept_client() {
  485. int retval;
  486. int sendret = 0;
  487. struct message_record msg;
  488. // try to accept the new client
  489. //
  490. retval = accept(listener_socket, NULL, NULL);
  491. // if we got a valid file descriptor
  492. //
  493. if(retval >= 0) {
  494. // if we are out of room
  495. //
  496. if(num_clients >= NUM_SUPPORTED_CLIENTS) {
  497. #ifdef COMMHUB_DEBUG
  498. printf("Cannot add client %d (MAXCLIENTS)\n", retval);
  499. #endif
  500. // send an error
  501. //
  502. prepare_message(&msg,MAILBOX_ERROR,"MAXCLIENTS",10);
  503. DO_SEND_MESSAGE(sendret, retval, &msg);
  504. if (sendret < 0) { }
  505. // close the socket
  506. //
  507. close(retval);
  508. // and return
  509. //
  510. return -1;
  511. }
  512. // otherwise add it to our default lists (master, broadcast) with a bogus pid
  513. // which the client will (hopefully) correct with a HELLO message
  514. //
  515. add_client(retval, -1, "", &master_list);
  516. add_client(retval, -1, "", &broadcast_list);
  517. #ifdef COMMHUB_DEBUG
  518. printf("Added Client %d\n", retval);
  519. debug_traverse();
  520. #endif
  521. }
  522. else {
  523. if(errno != EINTR) {
  524. perror("Accept client failed: ");
  525. }
  526. }
  527. return 0;
  528. }
  529. // This helper function finds a client record by file descriptor
  530. //
  531. struct subscriber_record *find_client_by_fd(struct subscriber_record *list, int fd) {
  532. struct subscriber_record *p = list;
  533. while(p) {
  534. if (p->clientfd == fd) {
  535. break;
  536. }
  537. p = p->next;
  538. }
  539. return p;
  540. }
  541. // This helper function delivers a message to every subscriber on the provided list.
  542. //
  543. int deliver_message(struct message_record *msg, struct subscriber_record *dest) {
  544. struct subscriber_record *p = dest;
  545. int sendret;
  546. while(p) {
  547. DO_SEND_MESSAGE(sendret, p->clientfd, msg);
  548. if (sendret) {
  549. close(p->clientfd);
  550. }
  551. p = p->next;
  552. }
  553. return 0;
  554. }
  555. //This function is where the 'magic' happens. It picks out special messages (after first forwarding everything to the wiretap list)
  556. //Messages addressed to:
  557. // HELLO adds the client to the master and broadcast lists and updates its pid
  558. // >pid gets delivered to the client with the specified pid.
  559. // :modulename gets delivered to all clients registered with the supplied module name
  560. // SUBSCRIBE causes the sending client to be added to the named mailbox
  561. // UNSUBSCRIBE causes the sending client to be removed from the named mailbox
  562. // BROADCAST causes the message to be passed to all listeners
  563. // WIRETAP sets the wiretap state (on if payload = "ON" off otherwise)
  564. // PING replies with PONG
  565. //
  566. //All other messages are passed to their user mailbox and on to any subscribing clients. Messages with no receiver are dropped silently.
  567. //
  568. int route_message(int fd, struct message_record *msg) {
  569. struct subscriber_record dummy = {0};
  570. struct subscriber_record *dest;
  571. int pid;
  572. int sendret;
  573. // Implement wiretap for debug
  574. //
  575. if(wiretap_list) {
  576. deliver_message(msg, wiretap_list);
  577. }
  578. // Handle special mailboxes
  579. //
  580. //-------------------------------------------- PID addressed message
  581. //
  582. if( msg->header.mailbox_name[0] == '>' ) {
  583. // extract pid
  584. //
  585. pid = atoi( &msg->header.mailbox_name[1] );
  586. // look it up in the master list
  587. //
  588. dest = master_list;
  589. while (dest) {
  590. // if we have a match
  591. // stop looking
  592. //
  593. if(dest->pid == pid) {
  594. break;
  595. }
  596. // advance pointer
  597. //
  598. dest = dest->next;
  599. }
  600. if(dest != NULL) {
  601. // deliver the message
  602. //
  603. DO_SEND_MESSAGE(sendret, dest->clientfd, msg);
  604. if (sendret) {
  605. close(dest->clientfd);
  606. }
  607. }
  608. else {
  609. if (pid == getpid()) {
  610. // If this is a unicast PING to US...
  611. //
  612. if( !strncmp((char *)msg->payload, MAILBOX_PING, MAILBOX_NAME_MAX) ) {
  613. struct message_record outgoing;
  614. prepare_message(&outgoing, MAILBOX_PONG, msg->payload, msg->header.payload_length);
  615. dest = find_mailbox(MAILBOX_PONG);
  616. if (dest) {
  617. deliver_message(&outgoing, dest);
  618. }
  619. deliver_message(&outgoing, wiretap_list);
  620. }
  621. }
  622. }
  623. return 0;
  624. }
  625. //-------------------------------------------- module addressed message
  626. //
  627. else if( msg->header.mailbox_name[0] == ':' ) {
  628. // start looking through the master list
  629. //
  630. dest = master_list;
  631. while(dest) {
  632. //if we have a match on module name
  633. //
  634. if(! strncmp(&msg->header.mailbox_name[1], dest->progname, MAX_MODULE_NAME_LENGTH) ) {
  635. // deliver the message (but keep looking)
  636. //
  637. DO_SEND_MESSAGE(sendret, dest->clientfd, msg);
  638. if (sendret) {
  639. close(dest->clientfd);
  640. }
  641. }
  642. dest = dest->next; //advance pointer
  643. }
  644. return 0;
  645. }
  646. // ------------------------- HELLO message
  647. //
  648. else if( !strncmp(msg->header.mailbox_name, MAILBOX_HELLO, MAILBOX_NAME_MAX)) {
  649. // a HELLO message sets the client pid, adds it to master and broadcast, and removes it from wiretap
  650. // the payload should contain the module name
  651. //
  652. add_client(fd, msg->header.sender, (char *)msg->payload, &master_list);
  653. add_client(fd, msg->header.sender, (char *)msg->payload, &broadcast_list);
  654. del_client(fd, &wiretap_list);
  655. #ifdef COMMHUB_DEBUG
  656. printf("Associated client %d with PID %d (progname = %s)\n", fd, msg->header.sender, msg->payload);
  657. debug_traverse();
  658. #endif
  659. return 0; //return
  660. }
  661. // ------------------------- SUBSCRIBE message
  662. //
  663. else if( !strncmp(msg->header.mailbox_name, MAILBOX_SUBSCRIBE, MAILBOX_NAME_MAX)) {
  664. // a SUBSCRIBE message subscribes the client to the specified mailbox
  665. //
  666. // look up this client in the master list to obtain progname
  667. //
  668. dest = find_client_by_fd(master_list, fd);
  669. // if this fd is not found (this should NEVER happen, but still...) avoid a null ponter by using a dummy record of all 0's
  670. if(!dest) {
  671. fprintf(stderr,"Request from client %d which appears not to be in our master list!\n", fd);
  672. dest = &dummy;
  673. }
  674. subscribe_client(fd, msg->header.sender, dest->progname, (char *)msg->payload);
  675. #ifdef COMMHUB_DEBUG
  676. printf("Added Client %d to %s\n", fd, msg->payload);
  677. debug_traverse();
  678. #endif
  679. // return
  680. return 0;
  681. }
  682. // ------------------------- UNSUBSCRIBE message
  683. //
  684. else if( !strncmp(msg->header.mailbox_name, MAILBOX_UNSUBSCRIBE, MAILBOX_NAME_MAX)) {
  685. //an UNSUBSCRIBE message removes the client from the specified mailbox
  686. //
  687. unsubscribe_client(fd, (char *)msg->payload);
  688. #ifdef COMMHUB_DEBUG
  689. printf("Removed Client %d from %s\n", fd, msg->payload);
  690. debug_traverse();
  691. #endif
  692. // return
  693. return 0;
  694. }
  695. // ------------------------- BROADCAST message
  696. //
  697. else if( !strncmp(msg->header.mailbox_name, MAILBOX_BROADCAST, MAILBOX_NAME_MAX)) {
  698. // a BROADCAST message goes to everybody (except those who already got it through wiretap)
  699. //
  700. deliver_message(msg, broadcast_list);
  701. return 0;
  702. }
  703. // ------------------------- WIRETAP message
  704. //
  705. else if( !strncmp(msg->header.mailbox_name, MAILBOX_WIRETAP, MAILBOX_NAME_MAX)) {
  706. // a WIRETAP message sets the wiretap mode.
  707. //
  708. // look up this client in the master list to obtain progname
  709. //
  710. dest = find_client_by_fd(master_list, fd);
  711. // if this fd is not found (this should NEVER happen, but still...) avoid a null ponter by using a dummy record of all 0's
  712. //
  713. if (!dest) {
  714. fprintf(stderr,"Request from client %d which appears not to be in our master list!\n", fd);
  715. dest = &dummy;
  716. }
  717. // if we are turning wiretap mode ON
  718. //
  719. if( !strncmp((char *)msg->payload, "ON", MAX_PAYLOAD_LENGTH) ) {
  720. // add the client to the wiretap list
  721. //
  722. add_client(fd, msg->header.sender, dest->progname, &wiretap_list);
  723. // and remove from the broadcast list
  724. //
  725. del_client(fd, &broadcast_list);
  726. #ifdef COMMHUB_DEBUG
  727. printf("Added Client %d to wiretap list\n", fd);
  728. debug_traverse();
  729. #endif
  730. }
  731. // if we are turning wiretap mode OFF
  732. //
  733. else {
  734. // remove the client from the wiretap list
  735. //
  736. del_client(fd, &wiretap_list);
  737. // and add to the broadcast list
  738. //
  739. add_client(fd, msg->header.sender, dest->progname, &broadcast_list);
  740. #ifdef COMMHUB_DEBUG
  741. printf("Removed Client %d from wiretap list\n", fd);
  742. debug_traverse();
  743. #endif
  744. }
  745. return 0;
  746. }
  747. // Even we need to respond to a PING message
  748. //
  749. else if ( !strncmp(msg->header.mailbox_name, MAILBOX_PING, MAILBOX_NAME_MAX)) {
  750. struct message_record outgoing;
  751. prepare_message(&outgoing, MAILBOX_PONG, msg->payload, msg->header.payload_length);
  752. dest = find_mailbox(MAILBOX_PONG);
  753. if (dest) {
  754. deliver_message(&outgoing, dest);
  755. }
  756. deliver_message(&outgoing, wiretap_list);
  757. }
  758. //-------------------------------------------------------------------------------Normal delivery to user mailboxes...
  759. //
  760. dest = find_mailbox(msg->header.mailbox_name); //look up the mailbox client list
  761. // if it is non-NULL
  762. //
  763. if (dest) {
  764. // deliver the message to those clients
  765. //
  766. deliver_message(msg, dest);
  767. }
  768. return 0;
  769. }
  770. // this function frees our data structures and closes our file handles politely before exit
  771. //
  772. int cleanup() {
  773. struct mailbox_record *p, *q;
  774. struct subscriber_record *pp, *qq;
  775. q = NULL;
  776. // walk the list of user mailboxes
  777. //
  778. p = mailboxes;
  779. while(p) {
  780. q = p;
  781. // advance the pointers
  782. //
  783. p = p->next;
  784. qq = NULL;
  785. // walk the just-visited user mailbox
  786. //
  787. pp = q->clients;
  788. // and free all the subscriber records
  789. //
  790. while (pp) {
  791. qq = pp;
  792. pp = pp->next;
  793. free(qq);
  794. }
  795. // free the node
  796. //
  797. free(q);
  798. }
  799. // walk the wiretap list freeing all nodes
  800. //
  801. qq = NULL;
  802. pp = wiretap_list;
  803. while(pp) {
  804. qq = pp;
  805. pp = pp->next;
  806. free(qq);
  807. }
  808. // walk the broadcast list freeing all nodes
  809. //
  810. qq = NULL;
  811. pp = broadcast_list;
  812. while(pp) {
  813. qq = pp;
  814. pp = pp->next;
  815. free(qq);
  816. }
  817. // walk the master list freeing all nodes and closing the file descriptors
  818. qq = NULL;
  819. pp = master_list;
  820. while(pp) {
  821. qq = pp;
  822. pp = pp->next;
  823. close(qq->clientfd);
  824. free(qq);
  825. }
  826. // NULL our all of our pointers
  827. mailboxes = NULL;
  828. broadcast_list = NULL;
  829. wiretap_list = NULL;
  830. master_list = NULL;
  831. close(listener_socket);
  832. num_clients = 0;
  833. listener_socket = -1;
  834. return 0;
  835. }
  836. /*
  837. // DRIVER_STATE_FILE
  838. // GPS_STATE_FILE
  839. // STOP_STATE_FILE
  840. //
  841. int get_driver_state(driver_status *_driver_stat) {
  842. FILE *fp;
  843. int input_idx=0,
  844. n=0,
  845. ch;
  846. char buffer[LINE_BUFFER_SIZE];
  847. // 0 - logged_in_driver
  848. // 1 - driver_name
  849. // 2 - equip_num
  850. //
  851. int _read_state = 0;
  852. if (access(DRIVER_STATE_FILE, R_OK)!=0) {
  853. return -1;
  854. }
  855. memset(buffer, 0, sizeof(char)*LINE_BUFFER_SIZE);
  856. n = DRIVER_NAME_LEN;
  857. if (LINE_BUFFER_SIZE < n) {
  858. n = LINE_BUFFER_SIZE;
  859. }
  860. fp = fopen(DRIVER_STATE_FILE, "r");
  861. while ( (ch = fgetc(fp)) != EOF ) {
  862. if ((ch == '\n') || (ch == EOF)) {
  863. if (_read_state == 0) {
  864. _driver_stat->logged_in_driver = atoi(buffer);
  865. _read_state++;
  866. }
  867. else if (_read_state == 1) {
  868. n = input_idx+1;
  869. if (n > DRIVER_NAME_LEN) {
  870. n = DRIVER_NAME_LEN;
  871. }
  872. buffer[n-1] = '\0';
  873. memcpy(_driver_stat->driver_name, buffer, n);
  874. _read_state++;
  875. }
  876. else if (_read_state == 2) {
  877. _driver_stat->equip_num = atoi(buffer);
  878. _read_state++;
  879. }
  880. memset(buffer, 0, sizeof(char)*LINE_BUFFER_SIZE);
  881. input_idx=0;
  882. continue;
  883. }
  884. buffer[input_idx] = ch;
  885. input_idx++;
  886. if (input_idx >= LINE_BUFFER_SIZE) {
  887. input_idx = LINE_BUFFER_SIZE-1;
  888. buffer[LINE_BUFFER_SIZE-1] = 0;
  889. }
  890. }
  891. fclose(fp);
  892. if (_read_state < 3) {
  893. return -2;
  894. }
  895. return 0;
  896. }
  897. int get_stop_state(stop_status *_stop_stat) {
  898. FILE *fp;
  899. int input_idx=0,
  900. n=0,
  901. ch;
  902. char buffer[LINE_BUFFER_SIZE];
  903. // 0 - paddle
  904. // 1 - route
  905. // 2 - trip
  906. // 3 - stop
  907. // 4 - lat
  908. // 5 - lon
  909. // 6 - stopname
  910. //
  911. int _read_state = 0;
  912. if (access(STOP_STATE_FILE, R_OK)!=0) {
  913. return -1;
  914. }
  915. memset(buffer, 0, sizeof(char)*LINE_BUFFER_SIZE);
  916. fp = fopen(DRIVER_STATE_FILE, "r");
  917. while ( (ch = fgetc(fp)) != EOF ) {
  918. if ((ch == '\n') || (ch == EOF)) {
  919. if (_read_state == 0) {
  920. _stop_stat->paddle= atoi(buffer);
  921. _read_state++;
  922. }
  923. else if (_read_state == 1) {
  924. _stop_stat->route = atoi(buffer);
  925. _read_state++;
  926. }
  927. else if (_read_state == 2) {
  928. _stop_stat->trip = atoi(buffer);
  929. _read_state++;
  930. }
  931. else if (_read_state == 3) {
  932. _stop_stat->stop= atoi(buffer);
  933. _read_state++;
  934. }
  935. else if (_read_state == 4) {
  936. _stop_stat->lat = atof(buffer);
  937. _read_state++;
  938. }
  939. else if (_read_state == 5) {
  940. _stop_stat->lon = atof(buffer);
  941. _read_state++;
  942. }
  943. else if (_read_state == 6) {
  944. n = input_idx+1;
  945. if (n > STOP_NAME_LEN) {
  946. n = DRIVER_NAME_LEN;
  947. }
  948. buffer[n-1] = '\0';
  949. memcpy(_stop_stat->stopname, buffer, n);
  950. _read_state++;
  951. }
  952. memset(buffer, 0, sizeof(char)*LINE_BUFFER_SIZE);
  953. input_idx=0;
  954. continue;
  955. }
  956. buffer[input_idx] = ch;
  957. input_idx++;
  958. if (input_idx >= LINE_BUFFER_SIZE) {
  959. input_idx = LINE_BUFFER_SIZE-1;
  960. buffer[LINE_BUFFER_SIZE-1] = 0;
  961. }
  962. }
  963. fclose(fp);
  964. if (_read_state < 6) {
  965. return -2;
  966. }
  967. return 0;
  968. }
  969. int get_gps_state(gps_status *_gps_stat) {
  970. FILE *fp;
  971. int input_idx=0,
  972. ch;
  973. char buffer[LINE_BUFFER_SIZE];
  974. // 0 - lat
  975. // 1 - lon
  976. // 2 - heading
  977. // 3 - velocity
  978. // 4 - num_sats
  979. // 5 - gps_good
  980. // 6 - stamp
  981. // 7 - gpstime
  982. //
  983. int _read_state = 0;
  984. if (access(GPS_STATE_FILE, R_OK)!=0) {
  985. return -1;
  986. }
  987. memset(buffer, 0, sizeof(char)*LINE_BUFFER_SIZE);
  988. fp = fopen(DRIVER_STATE_FILE, "r");
  989. while ( (ch = fgetc(fp)) != EOF ) {
  990. if ((ch == '\n') || (ch == EOF)) {
  991. if (_read_state == 0) {
  992. _gps_stat->lat = atof(buffer);
  993. _read_state++;
  994. }
  995. else if (_read_state == 1) {
  996. _gps_stat->lon = atof(buffer);
  997. _read_state++;
  998. }
  999. else if (_read_state == 2) {
  1000. _gps_stat->heading = atof(buffer);
  1001. _read_state++;
  1002. }
  1003. else if (_read_state == 3) {
  1004. _gps_stat->velocity = atof(buffer);
  1005. _read_state++;
  1006. }
  1007. else if (_read_state == 4) {
  1008. _gps_stat->num_sats = atoi(buffer);
  1009. _read_state++;
  1010. }
  1011. else if (_read_state == 5) {
  1012. _gps_stat->gps_good = atoi(buffer);
  1013. _read_state++;
  1014. }
  1015. else if (_read_state == 6) {
  1016. _gps_stat->stamp = (time_t)atoi(buffer);
  1017. _read_state++;
  1018. }
  1019. else if (_read_state == 7) {
  1020. _gps_stat->gpstime = (time_t)atoi(buffer);
  1021. _read_state++;
  1022. }
  1023. memset(buffer, 0, sizeof(char)*LINE_BUFFER_SIZE);
  1024. input_idx=0;
  1025. continue;
  1026. }
  1027. buffer[input_idx] = ch;
  1028. input_idx++;
  1029. if (input_idx >= LINE_BUFFER_SIZE) {
  1030. input_idx = LINE_BUFFER_SIZE-1;
  1031. buffer[LINE_BUFFER_SIZE-1] = 0;
  1032. }
  1033. }
  1034. fclose(fp);
  1035. if (_read_state < 7) {
  1036. return -2;
  1037. }
  1038. return 0;
  1039. }
  1040. */
  1041. // which poll revents flags signal that we need to close and clean up a socket...
  1042. //
  1043. #define CLOSE_CONDITION (POLLERR | POLLNVAL | POLLHUP)
  1044. int main(int argc, char **argv) {
  1045. int i;
  1046. int retval;
  1047. int rebuild;
  1048. struct message_record msg;
  1049. #ifdef DEBUG_PRINT
  1050. long long int _usec_now, _usec_prv, _usec_del;
  1051. _usec_del = 60000000;
  1052. _usec_now = get_usec_time();
  1053. _usec_prv = _usec_now;
  1054. #endif
  1055. // Before anything load driver, stop and
  1056. // avls state into IPC server (from disk).
  1057. // Messages will override these values but in case
  1058. // the IPC server goes away while the others persist,
  1059. // this will allow the various state variables to retain
  1060. // their values across restarts.
  1061. //
  1062. //get_driver_state(&driver_stat);
  1063. //get_stop_state(&stop_stat);
  1064. //get_gps_state(&gps_stat);
  1065. //init_state_info();
  1066. // Install our signal handlers and watchdog
  1067. //
  1068. configure_signal_handlers(argv[0]);
  1069. // create our listening socket
  1070. //
  1071. listener_socket = create_listener(COMMHUB_ADDRESS);
  1072. // return an error if we can't
  1073. //
  1074. if (listener_socket < 0) {
  1075. printf("Can't create listener socket: %d\n", listener_socket);
  1076. return -1;
  1077. }
  1078. // set our listener socket up in the poll data structure
  1079. //
  1080. fds[0].fd = listener_socket;
  1081. fds[0].events = POLLIN;
  1082. // do the same for our (blank) client list
  1083. //
  1084. rebuild_client_fds();
  1085. rebuild = 0;
  1086. // while we have not yet received a signal telling us to stop
  1087. //
  1088. while( exit_request_status == EXIT_REQUEST_NONE ) {
  1089. #ifdef DEBUG_PRINT
  1090. _usec_now = get_usec_time();
  1091. if ((_usec_now - _usec_prv) > _usec_del) {
  1092. printf("[%lli] ipc_server: heartbeat\n", get_usec_time());
  1093. _usec_prv = _usec_now;
  1094. }
  1095. #endif
  1096. RESET_WATCHDOG();
  1097. // if we have been flagged to rebuild our client fd list
  1098. //
  1099. if(rebuild) {
  1100. rebuild_client_fds(); //do so, and clear the flag
  1101. rebuild = 0;
  1102. }
  1103. // poll for any I/O events that we need to service
  1104. //
  1105. retval = poll(fds, num_clients + 1, COMMHUB_POLL_TIME);
  1106. // if poll returned an error
  1107. if(retval < 0) {
  1108. // and it was just a signal interruption
  1109. //
  1110. if(errno == EINTR) {
  1111. continue;
  1112. }
  1113. // otherwise complain bitterly
  1114. //
  1115. else {
  1116. perror("commserver: Poll failed:");
  1117. break;
  1118. }
  1119. }
  1120. // if poll returns 0, that means a timeout with no events
  1121. //
  1122. else if(retval == 0) {
  1123. // so go back and wait some more...
  1124. //
  1125. continue;
  1126. }
  1127. //if we get a new client
  1128. //
  1129. if (fds[0].revents & POLLIN) {
  1130. // accept the connection
  1131. //
  1132. accept_client();
  1133. // flag a rebuild of the poll list
  1134. //
  1135. rebuild = 1;
  1136. // and poll again
  1137. //
  1138. continue;
  1139. }
  1140. // if our server socket fails, complain
  1141. //
  1142. if (fds[0].revents & CLOSE_CONDITION) {
  1143. fprintf(stderr, "commserver: Server socket failed: revents = %d\n", fds[0].revents);
  1144. break;
  1145. }
  1146. // for each connected client
  1147. //
  1148. for (i=1; i <= num_clients; i++) {
  1149. // check for input events...
  1150. //
  1151. if (fds[i].revents & POLLIN) {
  1152. // if we have one, try and get the message
  1153. //
  1154. retval = get_message(fds[i].fd, &msg);
  1155. // if that fails
  1156. //
  1157. if (retval == -1) {
  1158. // that means the client has disconnected, so we purge them
  1159. //
  1160. purge_client(fds[i].fd);
  1161. // close the socket
  1162. //
  1163. close(fds[i].fd);
  1164. // and flag a rebuild
  1165. //
  1166. rebuild = 1;
  1167. }
  1168. // if it worked
  1169. //
  1170. else {
  1171. // we route the message and keep on going
  1172. //
  1173. route_message(fds[i].fd, &msg);
  1174. }
  1175. }
  1176. // if we have an error condition on this socket
  1177. //
  1178. if(fds[i].revents & CLOSE_CONDITION) {
  1179. // do the purge, close, and rebuild drill
  1180. //
  1181. purge_client(fds[i].fd);
  1182. close(fds[i].fd);
  1183. rebuild = 1;
  1184. }
  1185. }
  1186. }
  1187. // clean up our resources
  1188. //
  1189. cleanup();
  1190. return 0;
  1191. }