home *** CD-ROM | disk | FTP | other *** search
/ Network Support Encyclopedia 96-1 / novell-nsepro-1996-1-cd2.iso / download / netware / ipxex3.exe / IPXRECV.CPP < prev    next >
C/C++ Source or Header  |  1995-01-27  |  8KB  |  253 lines

  1. /****************************************************************************
  2. ** File: IPXRECV.CPP
  3. **
  4. **    Description:
  5. **
  6. **         Sample OS/2 application that demonstrates setting up an IPX
  7. **         receiver application.  This file goes along with IPXSEND.CPP,
  8. **         which demonstrates the sending portion of this code. IPXRECV.CPP
  9. **           starts three threads to do IPXRECEIVE's, which are blocking calls.
  10. **         These threads continue to post receives until the main program
  11. **         tells them to terminate or until there is an unrecoverable error.
  12. **
  13. **    Disclaimer:
  14. **
  15. **         Novell, Inc. makes no representations or warranties with respect to
  16. **         any NetWare software, and specifically disclaims any express or
  17. **         implied warranties of merchantability, title, or fitness for a
  18. **         particular purpose.
  19. **
  20. **         Distribution of any NetWare software is forbidden without the
  21. **         express written consent of Novell, Inc.  Further, Novell reserves
  22. **         the right to discontinue distribution of any NetWare software.
  23. **
  24. **         Novell is not responsible for lost profits or revenue, loss of use
  25. **         of the software, loss of data, costs of re-creating lost data, the
  26. **         cost of any substitute equipment or program, or claims by any party
  27. **         other than you.  Novell strongly recommends a backup be made before
  28. **         any software is installed.   Technical support for this software
  29. **         may be provided at the discretion of Novell.
  30. **
  31. **    Programmers:
  32. **
  33. **         Ini    Who                    Firm
  34. **         -------------------------------------------------------------------
  35. **         DRS    Dan Stratton            Novell Developer Support
  36. **
  37. **    History:
  38. **
  39. **         When        Who    What
  40. **         -------------------------------------------------------------------
  41. **         12-09-94        DRS    First code.
  42. **           01-27-95        DRS    Modified to work with CSET/++ and Borland
  43. **                    C++ for OS/2 2.0
  44. */
  45.  
  46.  
  47.  
  48.  
  49. #define NWOS2
  50. #define IS32BIT
  51.  
  52.  
  53. #if defined (__BORLANDC__)
  54.     #define BCPP
  55.     void threadCode(void *);
  56. #elif (defined (__IBMC__) || defined(__IBMCPP__))
  57.     #define CSET2
  58.     #pragma    stack16(2048)
  59.     void  _Export _Optlink threadCode(void *);
  60. #endif
  61.  
  62.  
  63. #define INCL_DOSPROCESS
  64.  
  65. #include <os2.h>
  66. #include <stdio.h>
  67. #include <string.h>
  68. #include <ctype.h>
  69. #include <conio.h>
  70. #include <errno.h>
  71. #include <process.h>
  72. #include <stddef.h>
  73.  
  74. #ifdef __cplusplus
  75.   extern "C"{
  76. #endif
  77. #include <nwcalls.h>
  78. #include <ipxcalls.h>
  79. #ifdef __cplusplus
  80.   }
  81. #endif
  82.  
  83. #define IPX_SOCKET    0x4545
  84. #define MAXTHREAD    3
  85.  
  86.  
  87. USHORT ipxSocket;
  88. BOOL terminateAllThreads = FALSE;
  89.  
  90.  
  91.  
  92.  /* --------------------------------------------------------------------------
  93.  threadCode
  94.  
  95.  Notice that we set the transTime to 0.  This in effect, tells IPX to check the
  96.  LSL buffers and see if there is a waiting packet.  If there is, it passes back
  97.  the packet.  If there isn't, the call will immediately fail and return to this
  98.  procedure.
  99.  
  100.  ----------------------------------------------------------------------------*/
  101.  
  102. void threadCode(void *ECB)
  103. {
  104.     ULONG timeOut = 0;
  105.     int ccode = 0, i = 0;
  106.     BOOL killThisThread = FALSE;
  107.  
  108.     do{ /* Notice that we set the timeout to 0.  This is basically so that
  109.            we can have good response time if we want to shut the threads down,
  110.            etc.
  111.         */
  112.       ccode = IpxReceive(ipxSocket,timeOut,(IPX_ECB *)ECB);
  113.       if ( !ccode )
  114.       { /* These print statements are for demonstration (debugging) purposes
  115.          only.  You should probably take them out for production.
  116.          It is possible to print information somewhat garbled
  117.          if you receive large numbers of packets on multiple threads.
  118.          Basically, your thread gets timesliced and the next thread starts
  119.          printing before the other thread has finished.  You could do an
  120.          fflush(stdout), but this is just for debugging anyway.
  121.         */
  122.       printf("\nPacket received on thread %ld",_threadid);
  123.       printf("\nPacket size: %d",NWWordSwap(((UINT16)((IPX_HEADER *)(((IPX_ECB *)ECB)->fragList[0].fragAddress))->packetLen)));
  124.       printf("\nSending WS = %02X%02X%02X",
  125.     ((IPX_HEADER *)(((IPX_ECB *)ECB)->fragList[0].fragAddress))->sourceNode[0],
  126.     ((IPX_HEADER *)(((IPX_ECB *)ECB)->fragList[0].fragAddress))->sourceNode[1],
  127.     ((IPX_HEADER *)(((IPX_ECB *)ECB)->fragList[0].fragAddress))->sourceNode[2]);
  128.       printf("%02X%02X%02X\nPacket contents follow:\n",
  129.     ((IPX_HEADER *)(((IPX_ECB *)ECB)->fragList[0].fragAddress))->sourceNode[3],
  130.     ((IPX_HEADER *)(((IPX_ECB *)ECB)->fragList[0].fragAddress))->sourceNode[4],
  131.     ((IPX_HEADER *)(((IPX_ECB *)ECB)->fragList[0].fragAddress))->sourceNode[5]);
  132.  
  133.       /*
  134.       The NWWordSwap(((UINT16).....  gives you the packetLen field out of the IPX header.
  135.       If you subtract the size of the IPX_HEADER, you get the size of the data in the packet
  136.       */
  137.       for(i=0;i< NWWordSwap(((UINT16)((IPX_HEADER *)(((IPX_ECB *)ECB)->fragList[0].fragAddress))->packetLen))-sizeof(IPX_HEADER);++i)
  138.       {
  139.          printf("%c",*((char *)(((IPX_ECB *)ECB)->fragList[1].fragAddress)+i));
  140.  
  141.       }
  142.      printf("\n");
  143.      }
  144.      switch(ccode)     /* check for success or error condition */
  145.      {
  146.      case 0x0000:  break;
  147.      case 0x9001:  break;
  148.      case 0x8002:  printf("\nError: Bad Packet Received on thread %ld",_threadid);
  149.                break;
  150.      case 0x8006:  printf("\nError: Receive Overflow, buffer too small on thread %ld",_threadid);
  151.                break;
  152.      case 0x8007:  printf("\nError: IPXReceive canceled on thread %ld",_threadid);
  153.                break;
  154.      case 0x9004:  printf("\nError: Socket not open, Terminating thread %ld",_threadid);
  155.                killThisThread = TRUE;
  156.                break;
  157.      default:      printf("\nUnknown error during IPXReceive.  Terminating thread %ld, ccode %04X",_threadid,ccode);
  158.                killThisThread = TRUE;
  159.                break;
  160.      }
  161.  
  162.      /* Do one IPXRECEIVE, then go to sleep until the next timeslice */
  163.      DosSleep(0);
  164.    }while (!killThisThread && !terminateAllThreads);
  165.    _endthread();
  166.  
  167. }
  168.  
  169.  
  170.  
  171.  
  172.  
  173. int main()
  174. {
  175.     IPX_HEADER ipxHeader[MAXTHREAD];
  176.     IPX_ECB    ipxECB[MAXTHREAD];
  177.     char packetBuff[MAXTHREAD][512];
  178.     USHORT  ccode;
  179.     int i;
  180.     LONG threadId[MAXTHREAD];
  181.  
  182.     /* open up a socket to receive on */
  183.     ipxSocket = IPX_SOCKET;
  184.     ccode = IpxOpenSocket(&ipxSocket);
  185.     if ( ccode )
  186.     {
  187.       printf("Error in IpxOpenSocket: %4.4x\n",ccode);
  188.       DosExit(EXIT_PROCESS,1);
  189.     }
  190.  
  191.     printf("Starting receive threads\n");
  192.  
  193.     /*
  194.        Go through a loop to initialize ECB's and start receive threads.
  195.        Starts MAXTHREAD threads
  196.     */
  197.     for ( i=0; i<MAXTHREAD; ++i )
  198.     {
  199.  
  200.     /*
  201.       Initialize the Receive ECB
  202.       Notice that the IpxHeader is never set to anything, this is filled
  203.       in by IPX during the receive
  204.     */
  205.  
  206.       memset((char *)&ipxECB[i],0,sizeof(IPX_ECB));
  207.       memset((char *)&ipxHeader[i],0,sizeof(IPX_HEADER));
  208.       memset((char *)&packetBuff[i],0,sizeof(packetBuff[i]));
  209.       ipxECB[i].fragList[0].fragAddress = &ipxHeader[i];
  210.       ipxECB[i].fragList[0].fragSize = sizeof(IPX_HEADER);
  211.       ipxECB[i].fragList[1].fragAddress = &packetBuff[i];
  212.       ipxECB[i].fragList[1].fragSize = sizeof(packetBuff[i]);
  213.       ipxECB[i].fragCount = 2;
  214.       ipxECB[i].next = ipxECB[i].prev = NULL;
  215.  
  216.       /* Start MAXTHREAD threads to do receives.  Also, _beginthread is
  217.        different in CSET, so we need to do a conditional compilation here
  218.       */
  219.  
  220. #if    (defined(__IBMC__) || defined(__IBMCPP__))
  221.       if ((threadId[i] = _beginthread(threadCode, NULL, 4096,(void *)&ipxECB[i])) < 0)
  222. #else
  223.       if ((threadId[i] = _beginthread(threadCode, 4096, (void *)&ipxECB[i])) < 0)
  224. #endif
  225.        {
  226.          printf("Unable to create thread %d, errno = %d\n",i,errno);
  227.           return errno;
  228.        }
  229.       printf("Created thread %d, ID = %ld\n",i,threadId[i]);
  230.     }
  231.  
  232.  
  233.     printf("\nPress a key to terminate...\n");
  234.     while(!kbhit())
  235.     {
  236.      DosSleep(0);  /* Give up rest of time slice for this thread */
  237.     }
  238.     printf("\nTerminating all threads");
  239.  
  240.     terminateAllThreads=TRUE;   /* Set global var to terminate all threads */
  241.  
  242.     for (i=0;i<MAXTHREAD;++i)   /* Wait until all threads have terminated */
  243.     {
  244.       DosWaitThread((PTID)&threadId[i],DCWW_WAIT);
  245.     }
  246.  
  247.     IpxCloseSocket(ipxSocket);
  248.  
  249.     return 0;
  250. }
  251.  
  252.  
  253.