trigtest.c++
上传用户:weiyuanprp
上传日期:2020-05-20
资源大小:1169k
文件大小:10k
源码类别:

传真(Fax)编程

开发平台:

C/C++

  1. #include "Sys.h"
  2. #include "Trigger.h"
  3. #include "ModemExt.h"
  4. #include "JobExt.h"
  5. #include "FaxRecvInfo.h"
  6. #include "FaxSendInfo.h"
  7. #include "Socket.h"
  8. #include <stdio.h>
  9. #include <sys/types.h>
  10. #include <sys/select.h>
  11. #include <fcntl.h>
  12. #include <errno.h>
  13. #include <ctype.h>
  14. extern "C" {
  15. #include <netinet/in.h>
  16. }
  17. #include "config.h"
  18. bool verbose = false;
  19. static int
  20. openFIFO(const char* name, int mode)
  21. {
  22.     int fd = open(name, mode|O_NDELAY, 0);
  23.     if (fd == -1) {
  24. perror(name);
  25. return (-1);
  26.     }
  27.     if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NDELAY) < 0) {
  28. perror("fcntl");
  29. return (-1);
  30.     }
  31.     return (fd);
  32. }
  33. static void
  34. send(const char* msg, int msgLen)
  35. {
  36.     int fifo = openFIFO("FIFO", O_WRONLY);
  37.     if (fifo > 0) {
  38. if (write(fifo, msg, msgLen) != msgLen)
  39.     perror("write");
  40. close(fifo);
  41.     }
  42. }
  43. static void
  44. printTime(time_t t)
  45. {
  46.     char buf[80];
  47.     strftime(buf, sizeof (buf), "%h %d %T", localtime(&t));
  48.     printf("%s ", buf);
  49. }
  50. static void
  51. printHeader(const TriggerMsgHeader& h)
  52. {
  53.     printTime(h.tstamp);
  54.     if (verbose)
  55. printf("[ev=%2u, seq#%-3u, len=%3u> ", h.event, h.seqnum, h.length);
  56.     
  57. }
  58. static void
  59. printParams(const Class2Params& params)
  60. {
  61.     printf("<%s, %s, %s, %s, %s>"
  62. , (params.ln == LN_A4 ? "A4" : params.ln == LN_B4 ? "B4" : "INF")
  63. , params.verticalResName()
  64. , params.dataFormatName()
  65. , params.bitRateName()
  66. , params.scanlineTimeName()
  67.     );
  68. }
  69. extern const char* fmtTime(time_t);
  70. static fxStr strTime(time_t t) { return fxStr(fmtTime(t)); }
  71. static const char*
  72. printJob(const TriggerMsgHeader& h, const char* data)
  73. {
  74.     printHeader(h);
  75.     JobExt job;
  76.     data = job.decode(data);
  77.     if (verbose) {
  78. time_t now = Sys::now();
  79. printf(
  80.       "JOB " | job.jobid
  81.     | " (dest " | job.dest
  82.     | (const char*)fxStr::format(" pri %u", job.pri)
  83.     | " tts " | strTime(job.tts - now)
  84.     | " killtime " | strTime(job.killtime - now)
  85.     | "): ");
  86.     } else {
  87. printf(
  88.       "JOB " | job.jobid
  89.     | " (dest " | job.dest
  90.     | fxStr::format(" pri %u", job.pri)
  91.     | "): ");
  92.     }
  93.     return (data);
  94. }
  95. static void
  96. printJobEvent(const TriggerMsgHeader& h, const char* data)
  97. {
  98.     (void) printJob(h, data);
  99.     static const char* jobNames[16] = {
  100. "created",
  101. "suspended",
  102. "ready to send",
  103. "sleeping awaiting time-to-send",
  104. "marked dead",
  105. "being processed by scheduler",
  106. "corpus reaped",
  107. "activated",
  108. "rejected",
  109. "killed",
  110. "blocked by another job",
  111. "delayed by time-of-day restriction or similar",
  112. "parameters altered",
  113. "timed out",
  114. "preparation started",
  115. "preparation finished",
  116.     };
  117.     printf(jobNames[h.event&15]);
  118. }
  119. static void
  120. printSendEvent(const TriggerMsgHeader& h, const char* data)
  121. {
  122.     data = printJob(h, data);
  123.     if (h.event != Trigger::SEND_POLLRCVD) {
  124. static const char* sendNames[16] = {
  125.     "SEND FAX: begin attempt",
  126.     "SEND FAX: call placed (off-hook)",
  127.     "SEND FAX: connected to remote device",
  128.     "#%u",
  129.     "#%u",
  130.     "#%u",
  131.     "#%u",
  132.     "SEND FAX: finished attempt",
  133.     "SEND FAX: reformat documents because of capabilities mismatch",
  134.     "SEND FAX: requeue job",
  135.     "SEND FAX: job completed successfully",
  136.     "unknown event #11",
  137.     "unknown event #12",
  138.     "unknown event #13",
  139.     "unknown event #14",
  140.     "unknown event #15"
  141. };
  142. FaxSendInfo si;
  143. si.decode(data);
  144. switch (h.event) {
  145. case Trigger::SEND_PAGE: // page sent
  146.     printf("SEND FAX: page %u sent in %s (file %s) "
  147. , si.npages
  148. , fmtTime(si.time)
  149. , (const char*) si.qfile
  150.     );
  151.     printParams(si.params);
  152.     break;
  153. case Trigger::SEND_DOC: // document sent
  154.     si.decode(data);
  155.     printf("SEND FAX: document sent in %s (file %s)"
  156. , fmtTime(si.time)
  157. , (const char*) si.qfile
  158.     );
  159.     break;
  160. case Trigger::SEND_POLLDONE: // polling operation done
  161.     si.decode(data);
  162.     printf("SEND FAX: poll op done in %s (file %s)"
  163. , fmtTime(si.time)
  164. , (const char*) si.qfile
  165.     );
  166.     break;
  167. default:
  168.     printf(sendNames[h.event&15], h.event);
  169.     break;
  170. }
  171.     } else {
  172. FaxRecvInfo ri;
  173. ri.decode(data);
  174. printf("SEND FAX: recv polled document from %s, %u pages in %s, file %s"
  175.     , (const char*) ri.sender
  176.     , ri.npages
  177.     , fmtTime((time_t) ri.time)
  178.     , (const char*) ri.qfile
  179. );
  180.     }
  181. }
  182. static void
  183. printModemEvent(const TriggerMsgHeader& h, const char* data)
  184. {
  185.     printHeader(h);
  186.     ModemExt modem;
  187.     data = modem.decode(data);
  188.     static const char* modemNames[16] = {
  189. "MODEM %s, assigned to job",
  190. "MODEM %s, released by job",
  191. "MODEM %s, marked down",
  192. "MODEM %s, marked ready",
  193. "MODEM %s, marked busy",
  194. "MODEM %s, considered wedged",
  195. "MODEM %s, in-use by an outbound job",
  196. "MODEM %s, inbound data call begin",
  197. "MODEM %s, inbound data call completed",
  198. "MODEM %s, inbound voice call begin",
  199. "MODEM %s, inbound voice call completed",
  200. "#11",
  201. "unknown event #12",
  202. "unknown event #13",
  203. "unknown event #14",
  204. "unknown event #15"
  205.     };
  206.     switch (h.event) {
  207.     case Trigger::MODEM_CID:
  208. printf("MODEM %s, caller-id information: %s",
  209.     (const char*) modem.devID, data);
  210. break;
  211.     default:
  212. printf(modemNames[h.event&15], (const char*) modem.devID);
  213. break;
  214.     }
  215. }
  216. static void
  217. printRecvEvent(const TriggerMsgHeader& h, const char* data)
  218. {
  219.     printHeader(h);
  220.     FaxRecvInfo ri;
  221.     ri.decode(data);
  222.     switch (h.event) {
  223.     case Trigger::RECV_BEGIN:
  224. printf("RECV FAX: begin call");
  225. break;
  226.     case Trigger::RECV_END:
  227. printf("RECV FAX: end call");
  228. break;
  229.     case Trigger::RECV_START:
  230. printf("RECV FAX: session started, TSI "%s" "
  231.     , (const char*) ri.sender
  232. );
  233. printParams(ri.params);
  234. break;
  235.     case Trigger::RECV_PAGE:
  236. printf("RECV FAX: from %s, page %u in %s "
  237.     , (const char*) ri.sender
  238.     , ri.npages
  239.     , fmtTime((time_t) ri.time)
  240. );
  241. printParams(ri.params);
  242. break;
  243.     case Trigger::RECV_DOC:
  244. printf("RECV FAX: from %s, %u pages in %s, file %s"
  245.     , (const char*) ri.sender
  246.     , ri.npages
  247.     , fmtTime((time_t) ri.time)
  248.     , (const char*) ri.qfile
  249. );
  250. break;
  251.     default:
  252. printf("unknown event #%u", h.event);
  253. break;
  254.     }
  255. }
  256. #define MAX 5
  257. static char fifoName[80];
  258. void
  259. sigINT(...)
  260. {
  261.     unlink(fifoName);
  262.     exit(-1);
  263. }
  264. static void
  265. reapChildren(...)
  266. {
  267.     int s;
  268.     while (waitpid(-1, &s, WNOHANG) != -1)
  269. ;
  270.     signal(SIGCHLD, reapChildren);
  271. }
  272. void
  273. doProtocol(const char* trigger)
  274. {
  275.     fd_set rd, wr, ex;
  276.     int fd, n;
  277.     fxStr fn = fxStr::format("client/%u", getpid());
  278.     fxAssert(fn.length() >= sizeof(fifoName), "trigtest::doProtocol overrun!");
  279.     strcpy(fifoName, (const char*) fn);
  280.     if (Sys::mkfifo(fifoName, 0666) < 0 && errno != EEXIST) {
  281.         perror("mkfifo");
  282.         exit(-1);
  283.     }
  284.     signal(SIGINT, sigINT);
  285.     signal(SIGTERM, sigINT);
  286.     signal(SIGPIPE, SIG_IGN);
  287.     fd = openFIFO(fifoName, CONFIG_OPENFIFO);
  288.     if (fd < 0) {
  289.         unlink(fifoName);
  290.         exit(-1);
  291.     }
  292.     fxStr msg = fxStr::format("T%s:N%s", fifoName, trigger);
  293.     send((const char*)msg, msg.length() + 1);
  294.     for (;;) {
  295.         FD_ZERO(&rd);
  296.     FD_SET(fd, &rd);
  297.     FD_SET(fileno(stdin), &rd);
  298.         FD_ZERO(&wr);
  299.         FD_ZERO(&ex);
  300.         n = select(FD_SETSIZE, &rd, &wr, &ex, 0);
  301. if (n < 0) {
  302.     perror("select");
  303.     break;
  304. }
  305. if (n == 0) {
  306.     printf("timeoutn");
  307. } else if (n > 0) {
  308.     char buf[16*1024];
  309.     int cc;
  310.     if (FD_ISSET(fd, &rd)) {
  311. while ((cc = read(fd, buf, sizeof (buf)-1)) > 0) {
  312.     buf[cc] = '';
  313.     char* bp = &buf[0];
  314.     do {
  315. char* cp;
  316. switch (bp[0]) {
  317. case 'H': // HELLO
  318. case 'T': // create trigger response
  319.     cp = strchr(bp, '');
  320.     if (cp > bp) {
  321. if (cp[-1] == 'n')
  322.     cp[-1] = '';
  323. if (strncmp(bp, "HELLO", 5) == 0) {
  324.     printTime(Sys::now());
  325.     printf(" HELLO: (Server startup)n");
  326.     send((const char*)msg, msg.length() + 1);
  327. } else if (bp[0] == 'T') {
  328.     printTime(Sys::now());
  329.     if (bp[1] == '!')
  330. printf("TRIGGER: Syntax errorn");
  331.     else
  332. printf("TRIGGER: new trigger #%sn",
  333.     bp+1);
  334. } else {
  335. }
  336.     }
  337.     bp = cp+1;
  338.     break;
  339. case '!': // trigger event message
  340.     TriggerMsgHeader h;
  341.     memcpy(&h, bp, sizeof (h));
  342.     if (h.length > (&buf[cc] - bp)) {
  343. // need more data to complete message
  344.     }
  345.     switch (h.event>>4) {
  346.     case JOB_BASE>>4:
  347. printJobEvent(h, bp+sizeof (h));
  348. break;
  349.     case SEND_BASE>>4:
  350. printSendEvent(h, bp+sizeof (h));
  351. break;
  352.     case RECV_BASE>>4:
  353. printRecvEvent(h, bp+sizeof (h));
  354. break;
  355.     case MODEM_BASE>>4:
  356. printModemEvent(h, bp+sizeof (h));
  357. break;
  358.     default:
  359. printf("Unrecognzied message");
  360.     }
  361.     putc('n', stdout);
  362.     bp += h.length;
  363.     break;
  364. default:
  365.     printf("Unknown trigger messagen");
  366.     break;
  367. }
  368.     } while (bp < &buf[cc]);
  369. }
  370.     }
  371.     if (FD_ISSET(fileno(stdin), &rd)) {
  372. if (fgets(buf, sizeof (buf)-1, stdin) == NULL)
  373.     break; // connection closed
  374. char* cp = strchr(buf, 'n');
  375. if (cp)
  376.     *cp = '';
  377. if (strcmp(buf, "verbose") == 0) {
  378.     verbose = !verbose;
  379.     printf("Verbose %sn", verbose ? "enabled" : "disabled");
  380. }
  381.     }
  382. } else
  383.     printf("(n == 0)n");
  384. fflush(stdout);
  385.     }
  386.     unlink(fifoName);
  387. }
  388. void
  389. main(int argc, char* argv[])
  390. {
  391.     if (argc != 2 && argc != 3) {
  392. fprintf(stderr, "usage: %s [-v] trigger-specn", argv[0]);
  393. exit(-1);
  394.     }
  395.     if (argc == 3) {
  396. verbose = true;
  397. argc--, argv++;
  398.     }
  399.     if (chdir(FAX_SPOOLDIR) == -1) {
  400. perror(FAX_SPOOLDIR);
  401. exit(-1);
  402.     }
  403.     umask(0);
  404.     int s = socket(AF_INET, SOCK_STREAM, 0);
  405.     if (s < 0) {
  406. perror("socket:");
  407. exit(-1);
  408.     }
  409.     struct sockaddr_in sin;
  410.     memset(&sin, 0, sizeof (sin));
  411.     sin.sin_family = AF_INET;
  412.     sin.sin_addr.s_addr = INADDR_ANY;
  413.     sin.sin_port = 4554;
  414.     if (Socket::bind(s, &sin, sizeof (sin)) < 0) {
  415. perror("bind:");
  416. exit(-1);
  417.     }
  418.     signal(SIGCHLD, reapChildren);
  419.     listen(s, 5);
  420.     for (;;) {
  421. Socket::socklen_t sinlen = sizeof (sin);
  422. int c = Socket::accept(s, &sin, &sinlen);
  423. if (c < 0) {
  424.     if (errno == EINTR)
  425. continue;
  426.     perror("accept:");
  427.     exit(-1);
  428. }
  429. switch (fork()) {
  430. case 0: /* child, process protocol */
  431.     close(s);
  432.     if (dup2(c, fileno(stdin)) < 0 || dup2(c, fileno(stdout)) < 0) {
  433. perror("dup2:");
  434. exit(-1);
  435.     }
  436.     doProtocol(argv[1]);
  437.     exit(0);
  438.     /*NOTREACHED*/
  439. case -1: /* fork failure */
  440.     perror("fork:");
  441.     break;
  442. default: /* parent */
  443.     close(c);
  444.     break;
  445. }
  446.     }
  447. }