home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 2 / goldfish_vol2_cd1.bin / files / comm / misc / cyberpager / source / dialer / send.c < prev    next >
C/C++ Source or Header  |  1994-10-05  |  12KB  |  536 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.     Use8N1(svc->svc_Use8N1);
  197.     SwitchBaud(svc->svc_BaudRate);
  198.  
  199.     if (!InitModem())
  200.         return 2;
  201.  
  202.     SerWrite(svc->svc_Phone, strlen(svc->svc_Phone));
  203.     SerPutChar('\r');
  204.  
  205.     ULog(ph, -1, "dialed %s (%s) on modem %ld", svc->svc_Name, svc->svc_Phone, openedModem);
  206.  
  207.     if (SerWaitString("CONNECT", 60)) {
  208.         online = TRUE;
  209.  
  210.         /* eat up to the newline after the connect message */
  211.  
  212.         SerWaitString("\r\n", 1);
  213.  
  214.         Delay(TICKS_PER_SECOND);
  215.  
  216.         /* first look for the ID= prompt */
  217.  
  218.         for (retries = 0; retries < MAX_LOGIN_RETRIES; retries++) {
  219.             SerPutChar('\r');
  220.  
  221.             if (SerWaitString("ID=", 2))
  222.                 break;
  223.         }
  224.  
  225.         if (retries == MAX_LOGIN_RETRIES) {
  226.             ErrorMsg("login failed: no \"ID=\" from the service.");
  227.             ULog(ph, -1, "login failed: no \"ID=\" from the service.");
  228.             return 4;
  229.         }
  230.  
  231.         /* eat any characters trailing the ID= prompt */
  232.  
  233.         while (SerGetRawChar(1) != TIMEOUT) ;
  234.  
  235.         /* now try and log in in automatic mode */
  236.  
  237.         doWrite = TRUE;
  238.  
  239.         for (retries = 0; retries < MAX_LOGIN_RETRIES; retries++) {
  240.             if (doWrite) {
  241.                 SerWrite("\x1B" "PG", 3);
  242.                 SerWrite(svc->svc_Password, strlen(svc->svc_Password));
  243.                 SerPutChar('\r');
  244.                 doWrite = FALSE;
  245.             }
  246.  
  247.             if ((len = GetPacket("login failed")) < 0)
  248.                 return 4;
  249.             else {
  250.                 if (len == 1 && packetBuf[0] == HSHAKE_ACK) {
  251.                     for (retries = 0; retries < MAX_LOGIN_RETRIES; retries++) {
  252.                         if ((len = GetPacket("login failed")) < 0)
  253.                             return 4;
  254.                         else if (packetBuf[0] == '\x1B' && packetBuf[1] == '[' && packetBuf[2] == 'p') {
  255.                             ULog(ph, -1, "login successful");
  256.                             return 0;
  257.                         }
  258.                     }
  259.  
  260.                     ErrorMsg("login failed: retry limit exceeded");
  261.                     ULog(ph, -1, "login failed: retry limit exceeded");
  262.                     return 4;
  263.                 }
  264.                 else if (len == 1 && packetBuf[0] == HSHAKE_NAK) {
  265.                     doWrite = TRUE;
  266.                     continue;
  267.                 }
  268.                 else if (len == 2 && packetBuf[0] == '\x1B' && packetBuf[1] == HSHAKE_EOT) {
  269.                     ErrorMsg("login failed: service refused connection.");
  270.                     ULog(ph, -1, "login failed: service refused connection.");
  271.                     return 4;
  272.                 }
  273.                 else if (packetBuf[0]) {
  274.                     ptr = packetBuf;
  275.  
  276.                     while (isspace(*ptr))
  277.                         ptr++;
  278.  
  279.                     if (ptr[0] == 'I' && ptr[1] == 'D' && ptr[2] == '=') {
  280.                         retries--;
  281.                     }
  282.                     else {
  283.                         ULog(ph, 2, "login: unknown packet received - %s", safePacketBuf);
  284.                     }
  285.                 }
  286.             }
  287.         }
  288.  
  289.         ErrorMsg("login failed: retry limit exceeded");
  290.         ULog(ph, -1, "login failed: retry limit exceeded");
  291.         return 4;
  292.     }
  293.     else {
  294.         ErrorMsg("login failed: no carrier detected.");
  295.         ULog(ph, -1, "login failed: no carrier detected.");
  296.         return 4;
  297.     }
  298. }
  299.  
  300. static UBYTE inputBuffer[256];
  301.  
  302. static const UBYTE checkSumTable[] = "0123456789:;<=>?";
  303.  
  304. static int SendBlock(void)
  305. {
  306.     int sum;
  307.     int i, c;
  308.     int retries;
  309.     LONG len;
  310.     BOOL doWrite;
  311.  
  312.     sum = safeBufIndex = i = 0;
  313.  
  314.     while (c = inputBuffer[i++])
  315.         sum += AddToSafeBuf(c);
  316.  
  317.     i--;
  318.  
  319.     inputBuffer[i++] = AddToSafeBuf(checkSumTable[(sum >> 8) & 0xF]);
  320.     inputBuffer[i++] = AddToSafeBuf(checkSumTable[(sum >> 4) & 0xF]);
  321.     inputBuffer[i++] = AddToSafeBuf(checkSumTable[sum & 0xF]);
  322.     inputBuffer[i++] = AddToSafeBuf('\r');
  323.     AddToSafeBuf(-1);
  324.  
  325.     ULog(ph, 4, "sendblock: sent %s", safePacketBuf);
  326.  
  327.     doWrite = TRUE;
  328.  
  329.     for (retries = 0; retries < 100; retries++) {
  330.         if (doWrite) {
  331.             SerWrite(inputBuffer, i);
  332.             doWrite = FALSE;
  333.         }
  334.  
  335.         if ((len = GetPacket("sendblock failed")) < 0)
  336.             return 1;
  337.         else {
  338.             if (len == 1 && packetBuf[0] == HSHAKE_ACK)
  339.                 return 0;
  340.             else if (len == 1 && packetBuf[0] == HSHAKE_NAK) {
  341.                 ULog(ph, 2, "sendblock: received nak -- retrying");
  342.                 doWrite = TRUE;
  343.                 continue;
  344.             }
  345.             else if (len == 1 && packetBuf[0] == HSHAKE_RS) {
  346.                 ErrorMsg("sendblock failed: service rejected block");
  347.                 ULog(ph, -1, "sendblock failed: service rejected block");
  348.                 return 3;
  349.             }
  350.             else if (len == 2 && packetBuf[0] == '\x1B' && packetBuf[1] == HSHAKE_EOT) {
  351.                 ErrorMsg("sendblock failed: service requested hangup");
  352.                 ULog(ph, -1, "sendblock failed: service requested hangup");
  353.                 return 1;
  354.             }
  355.             else if (packetBuf[0]) {
  356.                 ULog(ph, 2, "sendblock: unknown packet received - %s", safePacketBuf);
  357.             }
  358.         }
  359.     }
  360.  
  361.     ErrorMsg("sendblock failed: retry limit exceeded");
  362.     ULog(ph, -1, "sendblock failed: retry limit exceeded");
  363.  
  364.     return 1;
  365. }
  366.  
  367. static int ProcessSpoolFile(PagerService_t * svc, BPTR fh, STRPTR spoolFileName, STRPTR nameBuffer, STRPTR pinBuffer)
  368. {
  369.     LONG tag, blockLen;
  370.     int readOffset;
  371.     int result;
  372.     int pageCount;
  373.  
  374.     /* make sure we are connected to the service. */
  375.  
  376.     if (!online)
  377.         if (result = DialService(svc))
  378.             return result;
  379.  
  380.     /* loop sending pages in the spoolfile to the service */
  381.  
  382.     for (tag = FGetC(fh), pageCount = result = 0; !result && tag != END_OF_SPOOL; pageCount++) {
  383.         if ((tag != PAGE_START) || ((tag = FGetC(fh)) == EOF)) {
  384.             ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  385.             ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  386.             return 3;
  387.         }
  388.  
  389.         inputBuffer[0] = HSHAKE_STX;
  390.         strcpy(&inputBuffer[1], pinBuffer);
  391.         readOffset = strlen(inputBuffer);
  392.         inputBuffer[readOffset++] = '\r';
  393.  
  394.         for (; !result && tag != PAGE_END;) {
  395.             if ((tag != BLOCK_START) ||
  396.                 ((blockLen = FGetC(fh)) == EOF) || (blockLen + readOffset + 1 > 250) ||
  397.                 (FRead(fh, &inputBuffer[readOffset], 1, blockLen) != blockLen) ||
  398.                 ((tag = FGetC(fh)) != BLOCK_END) || ((tag = FGetC(fh)) == EOF)) {
  399.                 ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  400.                 ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  401.                 return 3;
  402.             }
  403.  
  404.             if (tag == PAGE_END) {
  405.                 inputBuffer[readOffset + blockLen++] = '\r';
  406.                 inputBuffer[readOffset + blockLen++] = HSHAKE_ETX;
  407.             }
  408.             else
  409.                 inputBuffer[readOffset + blockLen++] = HSHAKE_US;
  410.  
  411.             inputBuffer[readOffset + blockLen] = 0;
  412.  
  413.             result = SendBlock();
  414.  
  415.             readOffset = 1;
  416.         }
  417.  
  418.         tag = FGetC(fh);
  419.     }
  420.  
  421.     if (!result)
  422.         ULog(ph, -1, "delivered message to %s (%s) in %ld page%s", pinBuffer, nameBuffer, pageCount, (pageCount == 1 ? "" : "s"));
  423.  
  424.     return result;
  425. }
  426.  
  427. static STRPTR ReadLongItem(BPTR fh, STRPTR spoolFileName)
  428. {
  429.     LONG longBuf;
  430.     STRPTR buffer;
  431.  
  432.     if (FRead(fh, &longBuf, sizeof(longBuf), 1) == 1) {
  433.         if (buffer = MyAllocVec(longBuf + 1)) {
  434.             if (FRead(fh, buffer, 1, longBuf) == longBuf) {
  435.                 buffer[longBuf] = '\0';
  436.                 return buffer;
  437.             }
  438.             else {
  439.                 ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  440.                 ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  441.             }
  442.  
  443.             MyFreeVec(buffer);
  444.         }
  445.         else
  446.             ErrorMsg("out of memory!");
  447.     }
  448.     else {
  449.         ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  450.         ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  451.     }
  452.  
  453.     return buffer;
  454. }
  455.  
  456. static UBYTE RenameBuf[FILENAME_BUF_SIZE];
  457.  
  458. int SendSpoolFile(PagerService_t * svc, STRPTR spoolFileName)
  459. {
  460.     BPTR fh;
  461.     STRPTR nameBuffer, pinBuffer;
  462.     int result;
  463.  
  464.     result = 4;
  465.  
  466.     if (LockFile(ph, spoolFileName)) {
  467.         if (fh = Open(spoolFileName, MODE_OLDFILE)) {
  468.             result = 3;
  469.  
  470.             if (FRead(fh, inputBuffer, 1, strlen(SPOOLMAGIC) + 1) == strlen(SPOOLMAGIC) + 1) {
  471.                 if (strcmp(inputBuffer, SPOOLMAGIC) == 0) {
  472.                     if (nameBuffer = ReadLongItem(fh, spoolFileName)) {
  473.                         if (pinBuffer = ReadLongItem(fh, spoolFileName)) {
  474.                             result = ProcessSpoolFile(svc, fh, spoolFileName, nameBuffer, pinBuffer);
  475.  
  476.                             MyFreeVec(pinBuffer);
  477.                         }
  478.  
  479.                         MyFreeVec(nameBuffer);
  480.                     }
  481.                 }
  482.                 else {
  483.                     ErrorMsg("\"%s\" is not a valid spool file", spoolFileName);
  484.                     ULog(ph, -1, "\"%s\" is not a valid spool file", spoolFileName);
  485.                 }
  486.             }
  487.             else {
  488.                 ErrorMsg("error reading spool file \"%s\"", spoolFileName);
  489.                 ULog(ph, -1, "error reading spool file \"%s\"", spoolFileName);
  490.             }
  491.  
  492.             Close(fh);
  493.         }
  494.         else {
  495.             ErrorMsg("couldn't open spool file \"%s\"", spoolFileName);
  496.             ULog(ph, -1, "couldn't open spool file \"%s\"", spoolFileName);
  497.         }
  498.  
  499.         UnLockFile(ph, spoolFileName);
  500.     }
  501.     else {
  502.         ErrorMsg("couldn't lock spool file \"%s\"", spoolFileName);
  503.         ULog(ph, -1, "couldn't lock spool file \"%s\"", spoolFileName);
  504.     }
  505.  
  506.     /*
  507.      * if the spool file is bad (result = 3) then rename it so we don't
  508.      * get hung up on it.  in this case we return 0 so that we can
  509.      * continue sending other files while on-line
  510.      */
  511.  
  512.     if (result == 3) {
  513.         strcpy(RenameBuf, spoolFileName);
  514.         strcat(RenameBuf, ".bad");
  515.  
  516.         DeleteFile(RenameBuf);    /* sanity check */
  517.  
  518.         if (Rename(spoolFileName, RenameBuf) == DOSTRUE) {
  519.             ULog(ph, -1, "renamed \"%s\" to \"%s\".", spoolFileName, RenameBuf);
  520.             result = 0;
  521.         }
  522.         else
  523.             ULog(ph, -1, "unable to rename \"%s\" to \"%s\".", spoolFileName, RenameBuf);
  524.     }
  525.  
  526.     /*
  527.      * if we are all done and sent the spool file without any trouble
  528.      * then we need to delete the file
  529.      */
  530.  
  531.     if (!result)
  532.         DeleteFile(spoolFileName);
  533.  
  534.     return result;
  535. }
  536.