home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 20 / AACD20.BIN / AACD / Programming / AmiSlate-Source / AmiSource-c / drawtcp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-04  |  13.7 KB  |  528 lines

  1. #define DICE_C
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <errno.h>
  6. #include <string.h>
  7.  
  8. #include <exec/types.h>
  9. #include <exec/memory.h>
  10. #include <libraries/dos.h>            /* contains RETURN_OK, RETURN_WARN #def's */
  11. #include <dos/dosextens.h>
  12. #include <clib/exec_protos.h>
  13. #include <clib/netlib_protos.h>
  14. #include <intuition/intuition.h>
  15.  
  16. #include <graphics/gfxbase.h>
  17. #include <proto/socket.h>
  18. #include <proto/exec.h>
  19. #include <sys/errno.h>
  20. #include <sys/types.h>
  21. #include <sys/socket.h>
  22. #include <sys/ioctl.h>
  23. #include <sys/syslog.h>
  24. #include <netdb.h>
  25. #include <rexx/rxslib.h>
  26. #include <rexx/storage.h>
  27.  
  28. #include <pragmas/socket_pragmas.h>
  29. #include <inetd.h>
  30.  
  31. #include "remote.h"
  32. #include "drawtcp.h"
  33. #include "drawlang.h"
  34. #include "StringRequest.h"
  35. #include "drawrexx.h"
  36. #include "drawrexx_aux.h"
  37. #include "tools.h"
  38. #include "amislate.h"
  39.  
  40. #define QUEUESAFETYMARGIN 50
  41.  
  42. /* Why does this come out as 18 unless I define it explicitely here?  Weird! */
  43. #define EWOULDBLOCK 35
  44.  
  45. struct sockaddr_in saSocketAddress, saRSocketAddress;
  46. struct hostent *hp;
  47. struct servent *sp;
  48.  
  49. extern int XPos, YPos;
  50. extern char targethost[100];
  51. extern ULONG ulIDCMPmask;
  52. extern BOOL BNetConnect;
  53. extern BOOL BPalettesLocked;
  54. extern struct Screen *Scr;
  55. extern struct Window *DrawWindow;
  56. extern struct RexxHost *rexxHost;
  57. extern ULONG timerSignal;
  58.  
  59. /* These are public to other modules */
  60. LONG lQLength;
  61. LONG lQMaxLength;
  62.  
  63. /* private vars for this module */
  64. static LONG   sSocket=-1;
  65. static USHORT port;
  66. static UBYTE  *uQ=NULL;
  67. static LONG   lQMaxLen;    
  68. static LONG   lQStart;
  69. static LONG   lQEnd;
  70.  
  71. static LONG   lQTest;    /* This area of mem is getting overwritten!?  This is here to protect lQEnd */
  72.  
  73. BOOL SetAsyncMode(BOOL BAsynch)
  74. {
  75.     LONG lNonBlockCode = BAsynch;
  76.     
  77.     if (IoctlSocket(sSocket, FIONBIO, (char *)&lNonBlockCode) < 0) return(FALSE);
  78.     return(TRUE);
  79. }
  80.  
  81. /* Sends screen info, should be called right after the line connects */
  82. BOOL SendScreenInfo(UWORD height, UWORD width, UBYTE depth, UWORD winheight, UWORD winwidth)
  83. {    
  84.     LONG lNonBlockCode = 1;
  85.     
  86.     if (SocketBase == NULL) return(FALSE);
  87.     
  88.     if (send(sSocket,(UBYTE *) &height,    sizeof(UWORD), 0L) < 0) return(FALSE);
  89.     if (send(sSocket,(UBYTE *) &width,     sizeof(UWORD), 0L) < 0) return(FALSE);
  90.     if (send(sSocket,(UBYTE *) &depth,     sizeof(UBYTE), 0L) < 0) return(FALSE);
  91.     if (send(sSocket,(UBYTE *) &winheight, sizeof(UWORD), 0L) < 0) return(FALSE);
  92.     if (send(sSocket,(UBYTE *) &winwidth,  sizeof(UWORD), 0L) < 0) return(FALSE);
  93.     
  94.     /* make socket non-blocking */
  95.     return(SetAsyncMode(TRUE));
  96. }
  97.  
  98.  
  99. /* Receives info on screen size, etc. from remote machine */
  100. /* Info:  Width  = 2 bytes(1 UWORD)  */
  101. /*        Height = 2 bytes(1 UWORD)  */
  102. /*        Depth  = 1 byte            */
  103. BOOL GetRemoteScreenInfo(UWORD *height, UWORD *width, UBYTE *depth, UWORD *winheight, UWORD *winwidth)
  104. {
  105.     LONG lNonBlockCode = 1;
  106.         
  107.     if (SocketBase == NULL) return(FALSE);
  108.     
  109.     if (recv(sSocket,(UBYTE *) height, sizeof(UWORD), 0L) != sizeof(UWORD)) return(FALSE);
  110.     if (recv(sSocket,(UBYTE *) width,  sizeof(UWORD), 0L) != sizeof(UWORD)) return(FALSE);
  111.     if (recv(sSocket,(UBYTE *) depth,  sizeof(UBYTE), 0L) != sizeof(UBYTE)) return(FALSE);
  112.     if (recv(sSocket,(UBYTE *) winheight, sizeof(UWORD), 0L) != sizeof(UWORD)) return(FALSE);
  113.     if (recv(sSocket,(UBYTE *) winwidth,  sizeof(UWORD), 0L) != sizeof(UWORD)) return(FALSE);
  114.  
  115.         /* Now make socket non-blocking */
  116.     return(SetAsyncMode(TRUE));
  117. }
  118.  
  119.  
  120.     
  121. /* Tries to copy the name of whoever is at the other end of our
  122.    socket into sBuffer, whose length is nBufLen.  */
  123. void GetDrawPeerName(char *sBuffer, int nBufLen)
  124. {
  125.     struct sockaddr_in saTempAdd;
  126.     LONG lLength = sizeof(struct sockaddr_in), lError;
  127.     struct hostent *hePeer;
  128.     
  129.         if (SocketBase == NULL) 
  130.         {
  131.         *sBuffer = '\0';    /* Can't do much w/o AmiTCP running */
  132.         return();
  133.     }
  134.     
  135.     lError = getpeername(sSocket, &saTempAdd, &lLength);
  136.     if (lError < 0) 
  137.     {
  138.         sprintf(sBuffer,"gpn err %i",errno);
  139.         MakeReq(NULL,sBuffer,NULL);
  140.         strncpy(sBuffer,"<Unknown>",nBufLen);    /* Return failure */
  141.         return;
  142.     }    
  143.     hePeer = gethostbyaddr((caddr_t)&saTempAdd.sin_addr, sizeof(saTempAdd.sin_addr), AF_INET);
  144.     sprintf(sBuffer,"%s",hePeer->h_name);
  145.     return;
  146. }    
  147.     
  148.  
  149.     
  150. BOOL AcceptDrawSocket(struct DaemonMessage *dm)
  151. {     
  152.     /* This function is called when we were started by inetd.  It hooks
  153.        us up with the calling program! */
  154.     if (dm == NULL) return(FALSE);    
  155.         if (SocketBase == NULL) return(FALSE);
  156.  
  157.       SetErrnoPtr(&errno, sizeof(errno));
  158.  
  159.     sSocket = ObtainSocket((LONG)dm->dm_Id,(LONG) dm->dm_Family,(LONG) dm->dm_Type, 0L);
  160.  
  161.     if (sSocket < 0) return(FALSE);    
  162.     
  163.     BNetConnect = TRUE;
  164.     return(TRUE);     
  165. }
  166.  
  167.  
  168.  
  169.  
  170.  
  171. int CloseDrawSocket(void)
  172. {
  173.     static const LONG lType = REXX_REPLY_DISCONNECT;
  174.     
  175.         if (SocketBase == NULL) return(FALSE);
  176.     
  177.     /* Out Palette is no longer locked */
  178.     BPalettesLocked = FALSE;
  179.     
  180.     /* Flush the output queue */
  181.     FlushQueue();
  182.         
  183.     /* Tell our peer we're outta here */
  184.     if (BNetConnect == TRUE)
  185.     {
  186.         OutputAction(FROM_IDCMP, COMMAND, COMMAND_QUIT, NOP_PAD, NOP_PAD, NOP_PAD, DEST_PEER|DEST_FILE);
  187.  
  188.         /* Tell ARexx client we've disconnected */
  189.         if (PState.uwRexxWaitMask & REXX_REPLY_DISCONNECT)
  190.         {
  191.             ((struct rxd_waitevent *) *(&RexxState.array))->res.type = &lType; 
  192.             SetStandardRexxReturns();
  193.         }
  194.     }
  195.     
  196.     if (sSocket >= 0) 
  197.     {
  198.         shutdown(sSocket, 2);        /* dispose of all pending data */
  199.         CloseSocket(sSocket);
  200.     }
  201.     BNetConnect = FALSE;    
  202.  
  203.     SetWindowTitle("Connection closed.");            
  204.     SetMenuValues();
  205.     return(TRUE);
  206. }
  207.  
  208.  
  209.  
  210.  
  211. int ConnectDrawSocket(BOOL BShowRequester)
  212. {
  213.     int nSuccess;
  214.     char sBuffer[100], *sTemp = sBuffer;   
  215.     
  216.     if (SocketBase == NULL) return(FALSE);
  217.     
  218.     strncpy(sBuffer,targethost,sizeof(sBuffer));    
  219.     if ((BShowRequester == TRUE) && (GetUserString(sBuffer,"AmiSlate Connect","Enter Name of Remote Amiga",sizeof(sBuffer)) == FALSE))
  220.     {
  221.         SetWindowTitle("Connect cancelled.");
  222.         return(FALSE);
  223.     }
  224.     
  225.     /* If the user tries to put in a user account name, ignore it. */
  226.     if (strchr(sBuffer,'@') != NULL)
  227.         sTemp = strchr(sBuffer,'@')+1;
  228.  
  229.     strncpy(targethost, sTemp, sizeof(targethost));
  230.     LowerCase(targethost);
  231.  
  232.     sprintf(sBuffer,"Connecting to %s",targethost);
  233.     SetWindowTitle(sBuffer);
  234.             
  235.         SetErrnoPtr(&errno, sizeof(errno));
  236.     
  237.     sp = getservbyname("AmiSlate","tcp");
  238.     if (sp == NULL) sp = getservbyname("Amislate","tcp");    /* Try almost all lowercase then! */    
  239.     if (sp == NULL) sp = getservbyname("amislate","tcp");    /* Try all lowercase then! */    
  240.     if (sp == NULL)
  241.     {
  242.         MakeReq(NULL,"Couldn't find Service entry in inetd.conf!","Better Add it");
  243.         SetWindowTitle("Connection Failed/Refused");
  244.         return(FALSE);
  245.     }
  246.     port = sp->s_port;
  247.                 
  248.     hp = gethostbyname(targethost);
  249.     if (hp == NULL)
  250.     {
  251.         SetWindowTitle("Connection Failed/Refused");
  252.         return(FALSE);
  253.     }
  254.     
  255.     bzero(&saSocketAddress, sizeof(saSocketAddress));
  256.         bcopy(hp->h_addr, (char *)&saSocketAddress.sin_addr, hp->h_length);
  257.     saSocketAddress.sin_family = hp->h_addrtype;
  258.     saSocketAddress.sin_port   = htons(port);    
  259.     
  260.     sSocket = socket(hp->h_addrtype,SOCK_STREAM,0);
  261.     if (sSocket < 0)
  262.     {
  263.         Printf("Couldn't get a socket, errno=[%i] s=[%i]\n",errno,sSocket);
  264.         SetWindowTitle("Connection Failed/Refused");
  265.         return(FALSE);
  266.     }
  267.     nSuccess = connect(sSocket, (struct sockaddr *) &saSocketAddress, sizeof(saSocketAddress));
  268.     if (nSuccess < 0)
  269.     {
  270.         MakeReq(NULL,"Unable to connect to remote machine",NULL);
  271.         CloseSocket(sSocket);
  272.         SetWindowTitle("Connection Failed/Refused");
  273.         return(FALSE);
  274.     }
  275.         
  276.     /* Send info on our screen! */
  277.     if (SendScreenInfo((UWORD) Scr->Height, (UWORD) Scr->Width, (UBYTE)Scr->RastPort.BitMap->Depth, 
  278.                        (UWORD) DrawWindow->Height, (UWORD) DrawWindow->Width) == FALSE)
  279.     {
  280.         CloseSocket(sSocket);
  281.         SetWindowTitle("Connection Failed/Refused");        
  282.         Printf("SendScreenInfo failed!\n");
  283.         return(FALSE);
  284.     }
  285.  
  286.     BNetConnect = TRUE;
  287.     
  288.     /* Get info about his screen */
  289.     OutputAction(FROM_IDCMP, COMMAND, COMMAND_SYNCH, NOP_PAD, NOP_PAD, NOP_PAD, DEST_PEER|DEST_FILE);
  290.     SetMenuValues();
  291.     return(TRUE);
  292. }
  293.  
  294.  
  295. /* This function sends the given string over the link */
  296. BOOL SendString(char *sString, int nLen)
  297. {
  298.     if (SocketBase == NULL) return(FALSE);
  299.     
  300.     /* If there is still stuff in the queue to be sent, add this to the queue 
  301.        and try to send some of that stuff instead */
  302.     if (lQLength > 0)
  303.     {
  304.         AddToQueue(sString,nLen);
  305.         return(ReduceQueue());
  306.     }
  307.     else if (send(sSocket,sString,nLen,0L) == -1)
  308.     {
  309.         /* Queue the bytes! */
  310.         return(AddToQueue(sString,nLen));
  311.     }
  312.     return(TRUE);
  313. }
  314.  
  315.  
  316.  
  317. /* Allocates the Queue with size lQMaxLen -- returns TRUE if
  318.    successful, else FALSE */
  319. BOOL AllocQueue(LONG lQMaxChars)
  320. {
  321.     if (uQ != NULL) return(FALSE);
  322.     
  323.     uQ = AllocMem(lQMaxChars, MEMF_PUBLIC|MEMF_ANY);
  324.     if (uQ == NULL) return(FALSE);
  325.  
  326.     lQMaxLength  = lQMaxChars; /* (Max length, in bytes)        */    
  327.     FlushQueue();
  328.     return(TRUE);
  329. }
  330.  
  331.  
  332. void FlushQueue(void)
  333. {
  334.     /* Set defaults for an empty Queue */
  335.     lQLength     = 0L;         /* (Current length, in bytes) */
  336.     lQStart      = 0L;          /* (array index, in bytes)        */
  337.     lQEnd        = 0L;          /* (array index, in bytes)        */
  338.     return;
  339. }
  340.  
  341.  
  342. BOOL FreeQueue(void)
  343. {
  344.     if (uQ == NULL) return(FALSE);
  345.     FreeMem(uQ, lQMaxLength);
  346.     uQ = NULL;
  347.     return(TRUE);
  348. }
  349.  
  350.  
  351.  
  352. /* Puts the string at the end of the queue for later transmission */
  353. BOOL AddToQueue(char *sString, LONG lLen)
  354. {
  355.     UBYTE * puTemp, * puEnd;
  356.     LONG lCount;
  357.  
  358.     if ((lQLength + lLen) > lQMaxLength) return(FALSE);  /* can't do it; buffer full */
  359.  
  360.     puTemp = &uQ[lQEnd];                              /* start at first free spot in array */    
  361.     puEnd  = uQ;    
  362.     puEnd += ((UBYTE *) lQMaxLength);      /* first location after end of array */
  363.  
  364.     for (lCount=0; lCount < lLen; lCount++)
  365.     {
  366.         *puTemp = sString[lCount];
  367.         puTemp++;
  368.         if (puTemp >= puEnd) puTemp = uQ;        
  369.     }
  370.  
  371.     lQEnd = (LONG)puTemp-(LONG)uQ;        /* translated back into array index */    
  372.     lQLength += lLen;
  373.  
  374.     if (lQLength > (lQMaxLength-QUEUESAFETYMARGIN)) 
  375.     {
  376.         /* Queue almost full--Set AmiTCP to wait next time, until
  377.            we have reduced it some. */
  378.         SetWindowTitle("Output buffer full:  Synchronous mode activated.");
  379.         SetAsyncMode(FALSE);
  380.     }       
  381.     return(TRUE);
  382. }
  383.     
  384.     
  385.     
  386.     
  387. /* Tries to send out Queue--returns TRUE if some of Queue sent, FALSE if
  388.        none was sent */    
  389. BOOL ReduceQueue(void)
  390. {
  391.     int nSuccess, nLen;
  392.     const LONG lMaxPacketSize = 20;    /* Max # of bytes to try to send at once */
  393.     BOOL BInAsync = FALSE;
  394.     
  395.     if (lQLength == 0) return(FALSE);
  396.     if (lQLength > (lQMaxLength-QUEUESAFETYMARGIN))    BInAsync = TRUE;
  397.     
  398.     /* Start at beginning of list */
  399.     nLen = lMaxPacketSize;             /* default */
  400.     if ((lQStart + nLen) > lQMaxLength)
  401.     {
  402.         /* would go off end of array; shorten packet! */
  403.         nLen = lQMaxLength - lQStart;
  404.     }
  405.     
  406.     /* Don't want to send more than we have! */
  407.     if (nLen > lQLength) nLen = lQLength;
  408.     
  409.     nSuccess = send(sSocket,&uQ[lQStart],nLen,0L);
  410.     if (nSuccess == -1) return(FALSE);
  411.     
  412.     /* bytes sent--update beginning of Queue */
  413.     lQStart += nLen;
  414.     if (lQStart > lQMaxLength) Printf("555:Warning!\n");
  415.     if (lQStart >= lQMaxLength) lQStart = 0;
  416.     lQLength -= nLen;
  417.     if (lQLength < 0) MakeReq("AmiSlate Error","Queue length is negative!","I'll tell Jeremy");
  418.     
  419.     /* If we were able to reduce the queue, go back to asynchronous mode */
  420.     if (BInAsync == TRUE) 
  421.     {
  422.         SetAsyncMode(TRUE);
  423.         SetWindowTitle("Resuming asynchronous transmission.");
  424.     }
  425.     return(TRUE);
  426. }
  427.  
  428.  
  429.  
  430.  
  431. /* This function sends the given char over the link */
  432. BOOL SendChar(char cChar)
  433. {
  434.     char sShortString[] = "\0\0";
  435.     
  436.     sShortString[0] = cChar;
  437.     
  438.     if (send(sSocket,sShortString,1,0L) != 1) return(FALSE);
  439.     
  440.     return(TRUE);
  441. }
  442.         
  443.  
  444. /* Returns Bytes read on success (can be 0), or -errno on error */
  445. int Receive(char *sBuffer, int nBufLength)
  446. {
  447.     int nBytesReceived;
  448.     
  449.     if (SocketBase == NULL) return(FALSE);
  450.     
  451.     /* Clean out buffer, sorta */
  452.     *sBuffer = '\0';
  453.  
  454.     nBytesReceived = recv(sSocket,sBuffer,nBufLength, 0L);
  455.         
  456.     if (nBytesReceived == -1) 
  457.     {
  458.         if (errno == EWOULDBLOCK) return(0);
  459.         return(-abs(errno));
  460.     }
  461.     else
  462.     return(nBytesReceived);
  463. }
  464.  
  465.  
  466. UBYTE DrawWait(void)
  467. {
  468.     static struct fd_set fsReadSet, fsWriteSet;
  469.     ULONG signals, tmask = ulIDCMPmask;
  470.     UBYTE bRet = 0;
  471.     
  472.     FD_ZERO(&fsReadSet);              /* Initialize socket read set */
  473.     FD_SET(sSocket, &fsReadSet);        /* Set it to our port--stop waiting when there's something to read */
  474.     FD_ZERO(&fsWriteSet);            /* Initialize socket write set */
  475.     FD_SET(sSocket, &fsWriteSet);        /* Set it to same */
  476.  
  477.     /* Only break the WaitSelect() on a socket_write_ready if there are things
  478.        in the Queue that are ready to go! */
  479.     if (BNetConnect == FALSE)
  480.     {
  481.         signals = Wait(tmask);        /* wait for IDCMP, CTRL-C, Timer */
  482.         if (signals & SIGBREAKF_CTRL_C) CleanExit(0);    /* go bye bye on ctrl-c */
  483.         if (signals & 1L<<(DrawWindow->UserPort->mp_SigBit)) bRet |= IDCMP_READY;
  484.         if ((rexxHost != NULL)&&(signals & 1L<<rexxHost->port->mp_SigBit)) bRet |= AREXX_READY;
  485.         if (signals & timerSignal) RexxTimeOut();            
  486.     }
  487.     else
  488.     {    /* wait for IDCMP, CTRL-C, Timer, Connection stuff */
  489.         if (lQLength > 0) WaitSelect(1, &fsReadSet, &fsWriteSet, NULL, NULL, &tmask);        
  490.                        else WaitSelect(1, &fsReadSet, NULL,        NULL, NULL, &tmask);
  491.         if (FD_ISSET(sSocket, &fsReadSet))  bRet |= READ_READY;
  492.         if (FD_ISSET(sSocket, &fsWriteSet)) bRet |= WRITE_READY;
  493.         if (tmask & SIGBREAKF_CTRL_C) CleanExit(0);    /* go bye bye on ctrl-c */
  494.         if (tmask & (1L<<(DrawWindow->UserPort->mp_SigBit))) bRet |= IDCMP_READY;
  495.         if ((rexxHost != NULL)&&(tmask & (1L<<(rexxHost->port->mp_SigBit)))) bRet |= AREXX_READY;
  496.         if (tmask & timerSignal) RexxTimeOut();
  497.     }    
  498.     return(bRet);
  499. }
  500.  
  501.  
  502.  
  503. void RexxTimeOut(void)
  504. {
  505.     static const lType = REXX_REPLY_TIMEOUT;
  506.     static LONG ltimeX, ltimeY;
  507.     int ndownX, ndownY;
  508.     
  509.     if (PState.uwRexxWaitMask & REXX_REPLY_TIMEOUT)
  510.     {
  511.         ndownX = XPos;
  512.         ndownY = YPos;
  513.         FixPos(&ndownX, &ndownY);
  514.         UnFixCoords(&ndownX, &ndownY);    /* translates coordinates back into 0,0 offset */
  515.         
  516.         ltimeX = ndownX;
  517.         ltimeY = ndownY;
  518.         
  519.            ((struct rxd_waitevent *) *(&RexxState.array))->res.x = <imeX;
  520.            ((struct rxd_waitevent *) *(&RexxState.array))->res.y = <imeY;        
  521.            ((struct rxd_waitevent *) *(&RexxState.array))->res.type = &lType;
  522.         SetStandardRexxReturns();
  523.     }
  524.     return;
  525. }
  526.  
  527.  
  528.