home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 4 / FreshFish_May-June1994.bin / new / amigalibdisks / d992 / cyberpager / source / dialer / send.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-05  |  12.1 KB  |  535 lines

  1. #include "/include/memory.h"
  2.  
  3. #include "dialer.h"
  4.  
  5. BOOL online;
  6.  
  7. static UBYTE packetBuf[1024];
  8. static UBYTE safePacketBuf[8 * sizeof(packetBuf)];
  9.  
  10. static const UBYTE hexTable[] = "0123456789ABCDEF";
  11.  
  12. static LONG safeBufIndex = 0;
  13. static BOOL lastSafeSpecial;
  14. static BOOL lastSafeHex;
  15.  
  16.  /*
  17.   * add a character to the safe buf.  insert an intelligent name for special
  18.   * characers and convert unprintable to hex values. calling with a parameter
  19.   * of -1 means to close the buffer off.
  20.   */
  21.  
  22. static WORD AddToSafeBuf(WORD c)
  23. {
  24.     STRPTR specialName;
  25.  
  26.     if (safeBufIndex == 0) {
  27.         lastSafeSpecial = TRUE;
  28.         lastSafeHex = FALSE;
  29.     }
  30.  
  31.     if (c == -1) {
  32.         if (safeBufIndex == 0 || lastSafeSpecial == FALSE) {
  33.             if (safeBufIndex == 0)
  34.                 safePacketBuf[safeBufIndex++] = '\"';
  35.  
  36.             safePacketBuf[safeBufIndex++] = '\"';
  37.         }
  38.  
  39.         safePacketBuf[safeBufIndex] = '\0';
  40.         safeBufIndex = 0;
  41.     }
  42.     else {
  43.         switch (c) {
  44.         case HSHAKE_STX:
  45.             specialName = "STX";
  46.             break;
  47.  
  48.         case HSHAKE_ETX:
  49.             specialName = "ETX";
  50.             break;
  51.  
  52.         case HSHAKE_EOT:
  53.             specialName = "EOT";
  54.             break;
  55.  
  56.         case HSHAKE_ACK:
  57.             specialName = "ACK";
  58.             break;
  59.  
  60.         case HSHAKE_NAK:
  61.             specialName = "NAK";
  62.             break;
  63.  
  64.         case HSHAKE_ETB:
  65.             specialName = "ETB";
  66.             break;
  67.  
  68.         case HSHAKE_RS:
  69.             specialName = "RS";
  70.             break;
  71.  
  72.         case HSHAKE_US:
  73.             specialName = "US";
  74.             break;
  75.  
  76.         case '\r':
  77.             specialName = "CR";
  78.             break;
  79.  
  80.         case '\x1B':
  81.             specialName = "ESC";
  82.             break;
  83.  
  84.         default:
  85.             specialName = NULL;
  86.             break;
  87.         }
  88.  
  89.         if (specialName != NULL) {
  90.             if (lastSafeSpecial == FALSE) {
  91.                 safePacketBuf[safeBufIndex++] = '\"';
  92.                 lastSafeSpecial = TRUE;
  93.             }
  94.  
  95.             if (safeBufIndex)
  96.                 safePacketBuf[safeBufIndex++] = ' ';
  97.  
  98.             while (*specialName)
  99.                 safePacketBuf[safeBufIndex++] = *specialName++;
  100.  
  101.             lastSafeHex = FALSE;
  102.         }
  103.         else {
  104.             if (lastSafeSpecial) {
  105.                 if (safeBufIndex)
  106.                     safePacketBuf[safeBufIndex++] = ' ';
  107.  
  108.                 safePacketBuf[safeBufIndex++] = '\"';
  109.  
  110.                 lastSafeSpecial = FALSE;
  111.             }
  112.  
  113.             if (isprint(c)) {
  114.  
  115.                 /*
  116.                  * check to see if the last character was a
  117.                  * hex value.  if so, see if the current
  118.                  * characer is a valid hex digit.  if so,
  119.                  * insert " " so that one doesn't get
  120.                  * confused reading the translated output as
  121.                  * otherwise it would look like a larger hex
  122.                  * digit has been specified than really was.
  123.                  */
  124.                 if (lastSafeHex) {
  125.                     if (isxdigit(c)) {
  126.                         safePacketBuf[safeBufIndex++] = '\"';
  127.                         safePacketBuf[safeBufIndex++] = ' ';
  128.                         safePacketBuf[safeBufIndex++] = '\"';
  129.                     }
  130.  
  131.                     lastSafeHex = FALSE;
  132.                 }
  133.  
  134.                 if (c == '\"')
  135.                     safePacketBuf[safeBufIndex++] = '\\';
  136.  
  137.                 safePacketBuf[safeBufIndex++] = c;
  138.             }
  139.             else {
  140.                 safePacketBuf[safeBufIndex++] = '\\';
  141.                 safePacketBuf[safeBufIndex++] = 'x';
  142.                 safePacketBuf[safeBufIndex++] = hexTable[(c >> 4) & 0xF];
  143.                 safePacketBuf[safeBufIndex++] = hexTable[c & 0xF];
  144.                 lastSafeHex = TRUE;
  145.             }
  146.         }
  147.     }
  148.  
  149.     return c;
  150. }
  151.  
  152. static LONG GetPacket(STRPTR errorMsg)
  153. {
  154.     LONG index;
  155.     UWORD c;
  156.  
  157.     safeBufIndex = index = 0;
  158.  
  159.     while (c = SerGetRawChar(20)) {
  160.         if (c == TIMEOUT) {
  161.             ErrorMsg("%s: timed out trying to read packet from service.", errorMsg);
  162.             ULog(ph, -1, "%s: timed out trying to read packet from service.", errorMsg);
  163.             return -1;
  164.         }
  165.         else if (c == '\n')
  166.             continue;
  167.         else if (c == '\r')
  168.             break;
  169.  
  170.         packetBuf[index++] = AddToSafeBuf(c);
  171.  
  172.         if (index == (sizeof(packetBuf) - 2)) {
  173.             ErrorMsg("%s: panic attack - packet from service too long.", errorMsg);
  174.             ULog(ph, -1, "%s: panic attack - packet from service too long.", errorMsg);
  175.             return -2;
  176.         }
  177.     }
  178.  
  179.     packetBuf[index] = '\0';
  180.     AddToSafeBuf(-1);
  181.  
  182.     ULog(ph, 5, "getpacket: got %s", safePacketBuf);
  183.  
  184.     return index;
  185. }
  186.  
  187. #define MAX_LOGIN_RETRIES (5)
  188.  
  189. static int DialService(PagerService_t * svc)
  190. {
  191.     int retries;
  192.     LONG len;
  193.     STRPTR ptr;
  194.     BOOL doWrite;
  195.  
  196.     SwitchBaud(svc->svc_BaudRate);
  197.  
  198.     if (!InitModem())
  199.         return 2;
  200.  
  201.     SerWrite(svc->svc_Phone, strlen(svc->svc_Phone));
  202.     SerPutChar('\r');
  203.  
  204.     ULog(ph, -1, "dialed %s (%s) on modem %ld", svc->svc_Name, svc->svc_Phone, openedModem);
  205.  
  206.     if (SerWaitString("CONNECT", 60)) {
  207.         online = TRUE;
  208.  
  209.         /* eat up to the newline after the connect message */
  210.  
  211.         SerWaitString("\r\n", 1);
  212.  
  213.         Delay(TICKS_PER_SECOND);
  214.  
  215.         /* first look for the ID= prompt */
  216.  
  217.         for (retries = 0; retries < MAX_LOGIN_RETRIES; retries++) {
  218.             SerPutChar('\r');
  219.  
  220.             if (SerWaitString("ID=", 2))
  221.                 break;
  222.         }
  223.  
  224.         if (retries == MAX_LOGIN_RETRIES) {
  225.             ErrorMsg("login failed: no \"ID=\" from the service.");
  226.             ULog(ph, -1, "login failed: no \"ID=\" from the service.");
  227.             return 4;
  228.         }
  229.  
  230.         /* eat any characters trailing the ID= prompt */
  231.  
  232.         while (SerGetRawChar(1) != TIMEOUT) ;
  233.  
  234.         /* now try and log in in automatic mode */
  235.  
  236.         doWrite = TRUE;
  237.  
  238.         for (retries = 0; retries < MAX_LOGIN_RETRIES; retries++) {
  239.             if (doWrite) {
  240.                 SerWrite("\x1B" "PG", 3);
  241.                 SerWrite(svc->svc_Password, strlen(svc->svc_Password));
  242.                 SerPutChar('\r');
  243.                 doWrite = FALSE;
  244.             }
  245.  
  246.             if ((len = GetPacket("login failed")) < 0)
  247.                 return 4;
  248.             else {
  249.                 if (len == 1 && packetBuf[0] == HSHAKE_ACK) {
  250.                     for (retries = 0; retries < MAX_LOGIN_RETRIES; retries++) {
  251.                         if ((len = GetPacket("login failed")) < 0)
  252.                             return 4;
  253.                         else if (packetBuf[0] == '\x1B' && packetBuf[1] == '[' && packetBuf[2] == 'p') {
  254.                             ULog(ph, -1, "login successful");
  255.                             return 0;
  256.                         }
  257.                     }
  258.  
  259.                     ErrorMsg("login failed: retry limit exceeded");
  260.                     ULog(ph, -1, "login failed: retry limit exceeded");
  261.                     return 4;
  262.                 }
  263.                 else if (len == 1 && packetBuf[0] == HSHAKE_NAK) {
  264.                     doWrite = TRUE;
  265.                     continue;
  266.                 }
  267.                 else if (len == 2 && packetBuf[0] == '\x1B' && packetBuf[1] == HSHAKE_EOT) {
  268.                     ErrorMsg("login failed: service refused connection.");
  269.                     ULog(ph, -1, "login failed: service refused connection.");
  270.                     return 4;
  271.                 }
  272.                 else if (packetBuf[0]) {
  273.                     ptr = packetBuf;
  274.  
  275.                     while (isspace(*ptr))
  276.                         ptr++;
  277.  
  278.                     if (ptr[0] == 'I' && ptr[1] == 'D' && ptr[2] == '=') {
  279.                         retries--;
  280.                     }
  281.                     else {
  282.                         ULog(ph, 2, "login: unknown packet received - %s", safePacketBuf);
  283.                     }
  284.                 }
  285.             }
  286.         }
  287.  
  288.         ErrorMsg("login failed: retry limit exceeded");
  289.         ULog(ph, -1, "login failed: retry limit exceeded");
  290.         return 4;
  291.     }
  292.     else {
  293.         ErrorMsg("login failed: no carrier detected.");
  294.         ULog(ph, -1, "login failed: no carrier detected.");
  295.         return 4;
  296.     }
  297. }
  298.  
  299. static UBYTE inputBuffer[256];
  300.  
  301. static const UBYTE checkSumTable[] = "0123456789:;<=>?";
  302.  
  303. static int SendBlock(void)
  304. {
  305.     int sum;
  306.     int i, c;
  307.     int retries;
  308.     LONG len;
  309.     BOOL doWrite;
  310.  
  311.     sum = safeBufIndex = i = 0;
  312.  
  313.     while (c = inputBuffer[i++])
  314.         sum += AddToSafeBuf(c);
  315.  
  316.     i--;
  317.  
  318.     inputBuffer[i++] = AddToSafeBuf(checkSumTable[(sum >> 8) & 0xF]);
  319.     inputBuffer[i++] = AddToSafeBuf(checkSumTable[(sum >> 4) & 0xF]);
  320.     inputBuffer[i++] = AddToSafeBuf(checkSumTable[sum & 0xF]);
  321.     inputBuffer[i++] = AddToSafeBuf('\r');
  322.     AddToSafeBuf(-1);
  323.  
  324.     ULog(ph, 4, "sendblock: sent %s", safePacketBuf);
  325.  
  326.     doWrite = TRUE;
  327.  
  328.     for (retries = 0; retries < 100; retries++) {
  329.         if (doWrite) {
  330.             SerWrite(inputBuffer, i);
  331.             doWrite = FALSE;
  332.         }
  333.  
  334.         if ((len = GetPacket("sendblock failed")) < 0)
  335.             return 1;
  336.         else {
  337.             if (len == 1 && packetBuf[0] == HSHAKE_ACK)
  338.                 return 0;
  339.             else if (len == 1 && packetBuf[0] == HSHAKE_NAK) {
  340.                 ULog(ph, 2, "sendblock: received nak -- retrying");
  341.                 doWrite = TRUE;
  342.                 continue;
  343.             }
  344.             else if (len == 1 && packetBuf[0] == HSHAKE_RS) {
  345.                 ErrorMsg("sendblock failed: service rejected block");
  346.                 ULog(ph, -1, "sendblock failed: service rejected block");
  347.                 return 3;
  348.             }
  349.             else if (len == 2 && packetBuf[0] == '\x1B' && packetBuf[1] == HSHAKE_EOT) {
  350.                 ErrorMsg("sendblock failed: service requested hangup");
  351.                 ULog(ph, -1, "sendblock failed: service requested hangup");
  352.                 return 1;
  353.             }
  354.             else if (packetBuf[0]) {
  355.                 ULog(ph, 2, "sendblock: unknown packet received - %s", safePacketBuf);
  356.             }
  357.         }
  358.     }
  359.  
  360.     ErrorMsg("sendblock failed: retry limit exceeded");
  361.     ULog(ph, -1, "sendblock failed: retry limit exceeded");
  362.  
  363.     return 1;
  364. }
  365.  
  366. static int ProcessSpoolFile(PagerService_t * svc, BPTR fh, STRPTR spoolFileName, STRPTR nameBuffer, STRPTR pinBuffer)
  367. {
  368.     LONG tag, blockLen;
  369.     int readOffset;
  370.     int result;
  371.     int pageCount;
  372.  
  373.     /* make sure we are connected to the service. */
  374.  
  375.     if (!online)
  376.         if (result = DialService(svc))
  377.             return result;
  378.  
  379.     /* loop sending pages in the spoolfile to the service */
  380.  
  381.     for (tag = FGetC(fh), pageCount = result = 0; !result && tag != END_OF_SPOOL; pageCount++) {
  382.         if ((tag != PAGE_START) || ((tag = FGetC(fh)) == EOF)) {
  383.             ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  384.             ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  385.             return 3;
  386.         }
  387.  
  388.         inputBuffer[0] = HSHAKE_STX;
  389.         strcpy(&inputBuffer[1], pinBuffer);
  390.         readOffset = strlen(inputBuffer);
  391.         inputBuffer[readOffset++] = '\r';
  392.  
  393.         for (; !result && tag != PAGE_END;) {
  394.             if ((tag != BLOCK_START) ||
  395.                 ((blockLen = FGetC(fh)) == EOF) || (blockLen + readOffset + 1 > 250) ||
  396.                 (FRead(fh, &inputBuffer[readOffset], 1, blockLen) != blockLen) ||
  397.                 ((tag = FGetC(fh)) != BLOCK_END) || ((tag = FGetC(fh)) == EOF)) {
  398.                 ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  399.                 ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  400.                 return 3;
  401.             }
  402.  
  403.             if (tag == PAGE_END) {
  404.                 inputBuffer[readOffset + blockLen++] = '\r';
  405.                 inputBuffer[readOffset + blockLen++] = HSHAKE_ETX;
  406.             }
  407.             else
  408.                 inputBuffer[readOffset + blockLen++] = HSHAKE_US;
  409.  
  410.             inputBuffer[readOffset + blockLen] = 0;
  411.  
  412.             result = SendBlock();
  413.  
  414.             readOffset = 1;
  415.         }
  416.  
  417.         tag = FGetC(fh);
  418.     }
  419.  
  420.     if (!result)
  421.         ULog(ph, -1, "delivered message to %s (%s) in %ld page%s", pinBuffer, nameBuffer, pageCount, (pageCount == 1 ? "" : "s"));
  422.  
  423.     return result;
  424. }
  425.  
  426. static STRPTR ReadLongItem(BPTR fh, STRPTR spoolFileName)
  427. {
  428.     LONG longBuf;
  429.     STRPTR buffer;
  430.  
  431.     if (FRead(fh, &longBuf, sizeof(longBuf), 1) == 1) {
  432.         if (buffer = MyAllocVec(longBuf + 1)) {
  433.             if (FRead(fh, buffer, 1, longBuf) == longBuf) {
  434.                 buffer[longBuf] = '\0';
  435.                 return buffer;
  436.             }
  437.             else {
  438.                 ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  439.                 ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  440.             }
  441.  
  442.             MyFreeVec(buffer);
  443.         }
  444.         else
  445.             ErrorMsg("out of memory!");
  446.     }
  447.     else {
  448.         ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  449.         ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  450.     }
  451.  
  452.     return buffer;
  453. }
  454.  
  455. static UBYTE RenameBuf[FILENAME_BUF_SIZE];
  456.  
  457. int SendSpoolFile(PagerService_t * svc, STRPTR spoolFileName)
  458. {
  459.     BPTR fh;
  460.     STRPTR nameBuffer, pinBuffer;
  461.     int result;
  462.  
  463.     result = 4;
  464.  
  465.     if (LockFile(ph, spoolFileName)) {
  466.         if (fh = Open(spoolFileName, MODE_OLDFILE)) {
  467.             result = 3;
  468.  
  469.             if (FRead(fh, inputBuffer, 1, strlen(SPOOLMAGIC) + 1) == strlen(SPOOLMAGIC) + 1) {
  470.                 if (strcmp(inputBuffer, SPOOLMAGIC) == 0) {
  471.                     if (nameBuffer = ReadLongItem(fh, spoolFileName)) {
  472.                         if (pinBuffer = ReadLongItem(fh, spoolFileName)) {
  473.                             result = ProcessSpoolFile(svc, fh, spoolFileName, nameBuffer, pinBuffer);
  474.  
  475.                             MyFreeVec(pinBuffer);
  476.                         }
  477.  
  478.                         MyFreeVec(nameBuffer);
  479.                     }
  480.                 }
  481.                 else {
  482.                     ErrorMsg("\"%s\" is not a valid spool file", spoolFileName);
  483.                     ULog(ph, -1, "\"%s\" is not a valid spool file", spoolFileName);
  484.                 }
  485.             }
  486.             else {
  487.                 ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  488.                 ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  489.             }
  490.  
  491.             Close(fh);
  492.         }
  493.         else {
  494.             ErrorMsg("couldn't open spool file \"%s\"", spoolFileName);
  495.             ULog(ph, -1, "couldn't open spool file \"%s\"", spoolFileName);
  496.         }
  497.  
  498.         UnLockFile(ph, spoolFileName);
  499.     }
  500.     else {
  501.         ErrorMsg("couldn't lock spool file \"%s\"", spoolFileName);
  502.         ULog(ph, -1, "couldn't lock spool file \"%s\"", spoolFileName);
  503.     }
  504.  
  505.     /*
  506.      * if the spool file is bad (result = 3) then rename it so we don't
  507.      * get hung up on it.  in this case we return 0 so that we can
  508.      * continue sending other files while on-line
  509.      */
  510.  
  511.     if (result == 3) {
  512.         strcpy(RenameBuf, spoolFileName);
  513.         strcat(RenameBuf, ".bad");
  514.  
  515.         DeleteFile(RenameBuf);    /* sanity check */
  516.  
  517.         if (Rename(spoolFileName, RenameBuf) == DOSTRUE) {
  518.             ULog(ph, -1, "renamed \"%s\" to \"%s\".", spoolFileName, RenameBuf);
  519.             result = 0;
  520.         }
  521.         else
  522.             ULog(ph, -1, "unable to rename \"%s\" to \"%s\".", spoolFileName, RenameBuf);
  523.     }
  524.  
  525.     /*
  526.      * if we are all done and sent the spool file without any trouble
  527.      * then we need to delete the file
  528.      */
  529.  
  530.     if (!result)
  531.         DeleteFile(spoolFileName);
  532.  
  533.     return result;
  534. }
  535.