home *** CD-ROM | disk | FTP | other *** search
/ Network Support Encyclopedia 96-1 / novell-nsepro-1996-1-cd2.iso / download / netware / gchatc.exe / GRPCHATC.C < prev    next >
Text File  |  1995-09-08  |  16KB  |  526 lines

  1. /*
  2.  
  3. Copyright (c) 1992 Novell, Inc.  All Rights Reserved.
  4.  
  5. THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
  6. TREATIES.  USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE
  7. LICENSE AGREEMENT ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK)
  8. THAT CONTAINS THIS WORK.
  9.  
  10. Pursuant to the SDK License Agreement, Novell hereby grants to
  11. Developer a royalty-free, non-exclusive license to include the
  12. sample code GRPCHATC.C and derivative binaries in its product.
  13. Novell grants to Developer worldwide distribution rights to market,
  14. distribute or sell the sample code GRPCHATC.C and derivative
  15. binaries as a component of Developer's product(s).  Novell shall
  16. have no obligations to Developer or Developer's customers with
  17. respect to this code.
  18.  
  19. DISCLAIMER:
  20.  
  21.     Novell, Inc. makes no representations or warranties with respect
  22. to the contents or use of this code, and specifically disclaims any
  23. express or implied warranties of merchantability or fitness for any
  24. particular purpose.  Further, Novell, Inc. reserves the right to revise
  25. this publication and to make changes to its content, at any time,
  26. without obligation to notify any person or entity of such revisions or
  27. changes.
  28.  
  29.     Further, Novell, Inc. makes no representations or warranties with
  30. respect to any software, and specifically disclaims any express or
  31. implied warranties of merchantability or fitness for any particular
  32. purpose.  Further, Novell, Inc. reserves the right to make changes to
  33. any and all parts of the software, at any time, without obligation to
  34. notify any person or entity of such changes.
  35.  
  36. ***************************************************************************
  37.     GRPCHATC.C
  38. **************************************************************************/
  39.  
  40. /**************************************************************************
  41. ** Description: This is a partner program to GRPCHATS.EXE and serves as a
  42. **                  chat client to GRPCHATS.EXE -- the server or passive connection.
  43. **              This sample code demonstates how to use TLI in non-blocking mode.
  44. **              The server simply echos everything sent by the client to all clients
  45. **                 currently connected. A timer is used to periodically check for 
  46. **              data that may have been received. When this application loads it
  47. **              presents a dialog box requesting the address of the server. Since 
  48. **              the server application must be loaded first read the address displayed
  49. **              on the server console and enter in this dialog box along with your
  50. **              name. Enter the address exactly as it is displayed on the server
  51. **              console, including the ':' delimeter between the NET:NODE.
  52. **               
  53. ** Compiler:     Borland C++ v4.5
  54. **
  55. ** Programmer :  Karl Bunnell
  56. ** Date:         08/24/1995
  57. **
  58. */
  59.  
  60. #include <windows.h>
  61. #define NWWIN
  62. #include <nwipxspx.h>     
  63. #include <mem.h>
  64. #include <string.h>
  65. #include "grpchatc.h"
  66. #include <ctype.h>
  67. #include <tispxipx.h>
  68. #include <tiuser.h>
  69.  
  70. #define SPX_SOCKET 31                                         // arbitrary socket
  71. #define MAX_MESSAGE_SIZE    1024
  72. #define ID_TIMER    1
  73.  
  74.  
  75. long FAR PASCAL _export WndProc(HWND, UINT, UINT, LONG);
  76. BOOL Terminate(int *fd);
  77. BOOL SPXDisconReason(int fd, HWND hwnd);
  78. BOOL strToHex(char *ascii, unsigned char *hex, int length);
  79. BOOL InitConnection(IPX_ADDR *spx_addr, SPX_OPTS *spx_options, t_call *tcall, 
  80.                             int *initComplete, int *fd, HWND hwnd);
  81. BOOL FAR PASCAL GetNetAddressDlgProc(HWND hDlg, WORD msg, WORD wParam, DWORD lParam);
  82. static char globalMessage[1024];
  83. char  displayMessage[1024];
  84. char  tempMessage[1024];
  85. static char inetString[25];
  86. static HANDLE globalhInstance;
  87. static char myName[16];
  88.  
  89. /*-----------------------------------------------------------------------------
  90. **
  91. */
  92. int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,
  93.                                         LPSTR lpszCmdLine, int nCmdShow)
  94. {
  95.     static char    szGRPCHATC[] = "GRPCHATC";
  96.     HWND                hwnd;
  97.     MSG                    msg;
  98.     WNDCLASS        wndclass;
  99.  
  100.     if(!hPrevInstance)
  101.     {
  102.         wndclass.style                    = CS_HREDRAW | CS_VREDRAW;
  103.  
  104.         wndclass.lpfnWndProc        =    WndProc;
  105.         wndclass.cbClsExtra            =    0;
  106.         wndclass.cbWndExtra            =    DLGWINDOWEXTRA;
  107.         wndclass.hInstance            =    hInstance;
  108.         wndclass.hIcon                    =    LoadIcon(NULL, IDI_APPLICATION);
  109.         wndclass.hCursor                = LoadCursor(NULL, IDC_ARROW);
  110.         wndclass.hbrBackground    = COLOR_WINDOW + 1;
  111.         wndclass.lpszMenuName        =    NULL;
  112.         wndclass.lpszClassName    = szGRPCHATC;
  113.  
  114.         RegisterClass(&wndclass);
  115.     }
  116.  
  117.     hwnd = CreateDialog(hInstance, "MainDialog", 0, NULL);
  118.  
  119.     globalhInstance = hInstance;
  120.  
  121.     while (!SetTimer (hwnd, ID_TIMER, 55, NULL))
  122.         if(IDCANCEL == MessageBox(hwnd, "Too many clocks or timers!", "GRPCHATC",
  123.                                         MB_ICONEXCLAMATION | MB_RETRYCANCEL))
  124.         return FALSE;
  125.  
  126.     SendMessage(hwnd, WM_INITWINDOW, NULL, NULL);
  127.  
  128.     ShowWindow(hwnd, nCmdShow);
  129.     while(GetMessage(&msg, NULL, 0,0))
  130.     {
  131.         TranslateMessage(&msg);
  132.         DispatchMessage(&msg);
  133.     }
  134.     return msg.wParam;
  135.  
  136. }
  137. //-----------------------------------------------------------------------------
  138. long far PASCAL _export WndProc ( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
  139. {
  140.     static IPX_ADDR    spx_addr;                                                                                               
  141.     static SPX_OPTS    spx_options;
  142.     static struct    t_call tcall;
  143.     char        buf[1024];
  144.     char        buf2[1024];
  145.     static int fd; 
  146.     int         flags;
  147.     int        rval;
  148.     int       bytesSent, bytesLeft, nBytes;
  149.     static int initComplete = 0;
  150.     static int connectFlg = 0;
  151.     static char fromName[25];
  152.     WORD    beep = 0;
  153.          
  154.      switch (message)
  155.      {
  156.  
  157.           case WM_INITWINDOW:
  158.  
  159.             if(!InitConnection(&spx_addr, &spx_options, &tcall, &initComplete, &fd, hwnd))
  160.                 {
  161.                 wsprintf(displayMessage, "Connection Initialization Failed \r\n Try setting the net address again.");
  162.                 MessageBox(NULL, displayMessage,"Connect Initialization Failed", MB_OK);
  163.                 }
  164.             wsprintf(fromName, "\r\n--From: %s\r\n", myName);
  165.  
  166.             break;
  167.  
  168.           case WM_TIMER:
  169.  
  170.           if(!initComplete)
  171.             break;
  172.  
  173.           /*-----------------------------------------------------------------------------------
  174.           ** Once the call to InitConnection() is complete and successful I enter the following 
  175.           ** conditional to complete establishment of the connection with t_rcvconnect. If the
  176.           ** address specifed in the t_call structure is correct and the server is loaded and
  177.           ** waiting for connections then t_rcvconnect will return 0 (success) indicating that
  178.           ** a connection was successfully established. A flag is set to ensure that this code
  179.           ** is not entered again after connection establishment. After the 2 init flags are
  180.           ** are set, then t_rcv is used to check for pending received data from the server.
  181.           */
  182.             
  183.           if(!connectFlg)
  184.              {
  185.              rval = t_rcvconnect(fd, &tcall);
  186.              if(rval == -1 && t_errno == TNODATA)
  187.                 break;
  188.              else if(((t_errno == TLOOK) && (t_look(fd) == T_CONNECT)) || rval == 0 )
  189.                         connectFlg = 1;
  190.                     else
  191.                         {
  192.                         rval = t_errno;
  193.                         t_error("t_rcvconnect failed");        
  194.                         break;
  195.                         }
  196.              }
  197.  
  198.           memset(buf, 0, sizeof(buf));
  199.  
  200.           flags = 0;        /* initialize for t_rcv call */
  201.  
  202.           while ( (t_rcv( fd, buf, sizeof( buf),&flags )) != -1  )                 
  203.               {
  204.                  /*-----------------------------------------------------------------------------------
  205.                  ** Because the connection was opened in non-blocking mode there is a good possibility 
  206.                  ** that the complete message has not been received, however, for the purposes of this
  207.                  ** example I'm sending each chunk as I receive it to all connected nodes. 
  208.                  */
  209.  
  210.               wsprintf(displayMessage, "%s\r\n", buf);
  211.           
  212.               if(strlen(displayMessage) + strlen(globalMessage) < MAX_MESSAGE_SIZE)
  213.                 {
  214.                 strcpy(tempMessage, displayMessage);
  215.                 strcat(tempMessage, globalMessage);
  216.                 strcpy(globalMessage, tempMessage);
  217.                 }
  218.               else
  219.                 {
  220.                 memset(globalMessage, 0, sizeof(globalMessage));
  221.                 strcpy(tempMessage, displayMessage);
  222.                 strcat(tempMessage, globalMessage);
  223.                 strcpy(globalMessage, tempMessage);
  224.                 }
  225.  
  226.               SendDlgItemMessage(hwnd, IDC_DISPLAY_DATA, WM_SETTEXT, 0, 
  227.                                     (LONG) (LPSTR) globalMessage);
  228.  
  229.               MessageBeep(beep);
  230.                       
  231.               }
  232.  
  233.           break;
  234.  
  235.  
  236.  
  237.           case WM_DESTROY :
  238.                 KillTimer (hwnd, ID_TIMER);
  239.                 Terminate(&fd);
  240.                 PostQuitMessage(0);
  241.                 return 0;
  242.  
  243.           case WM_COMMAND:
  244.                 switch(wparam)
  245.                 {
  246.                      case IDC_PUSHBUTTON1:
  247.                             KillTimer (hwnd, ID_TIMER);
  248.                             Terminate(&fd);
  249.                             PostQuitMessage(0);
  250.                             return FALSE;
  251.  
  252.                      case IDC_PUSHBUTTON2:
  253.  
  254.                          SendDlgItemMessage(hwnd, IDC_SEND_DATA, WM_GETTEXT, sizeof(buf2), 
  255.                                 (LONG) (LPSTR) buf2);
  256.  
  257.                          if((strlen(buf2) + strlen(fromName)) < MAX_MESSAGE_SIZE)
  258.                                 strcat(buf2, fromName);
  259.  
  260.                           nBytes = bytesLeft = strlen(buf2);
  261.  
  262.                           if( nBytes == 0)
  263.                             {
  264.                             MessageBox(NULL, "Nothing to send!","Data Not Sent", MB_OK);
  265.                             break;
  266.                             }
  267.  
  268.                  /*-----------------------------------------------------------------------------------
  269.                  **  Because the connection is in non-blocking mode, you must advance the pointer
  270.                  **  in the send buffer yourself. The following loop demonstates one way you might do this.
  271.                  */
  272.                             
  273.                           while (bytesLeft > 0)
  274.                             {  
  275.                                 do
  276.                                     {
  277.                                     bytesSent = t_snd( fd, &buf2[nBytes-bytesLeft], bytesLeft, 0 );
  278.                                     }while ((bytesSent == -1) && (t_errno == TFLOW));
  279.  
  280.                                 if (bytesSent == -1 ) 
  281.                                 {    
  282.                                     if (t_errno==TLOOK && t_look(fd) == T_DISCONNECT)
  283.                                         SPXDisconReason(fd, hwnd);
  284.                           
  285.                                     else
  286.                                         {
  287.                                         t_error("t_snd failed\n");
  288.                                         t_close(fd);
  289.                                         break;
  290.                                         }
  291.                                 }
  292.                                 else
  293.                                      bytesLeft -= bytesSent;
  294.                             } // end - while nBytes > 0
  295.  
  296.                       SendDlgItemMessage(hwnd, IDC_SEND_DATA, WM_SETTEXT, 0, 
  297.                                     (LONG) (LPSTR) "");
  298.  
  299.                       break;
  300.  
  301.                      case IDC_PUSHBUTTON3:
  302.  
  303.                         if(!InitConnection(&spx_addr, &spx_options, &tcall, &initComplete, &fd, hwnd))
  304.                             {
  305.                             wsprintf(displayMessage, "Connection Initialization Failed \r\n Try setting the net address again.");
  306.                             MessageBox(NULL, displayMessage,"Connect Initialization Failed", MB_OK);
  307.                             }
  308.                      break;
  309.                       
  310.                 }                                     
  311.  
  312.      }
  313.     return DefWindowProc(hwnd, message, wparam, lparam);
  314. }
  315.  
  316.  
  317. BOOL InitConnection(IPX_ADDR *spx_addr, SPX_OPTS *spx_options, t_call *tcall, int *initComplete, int *fd, HWND hwnd)
  318. {
  319.     static FARPROC lpfnGetNetAddressDlgProc;
  320.     char        tempString[22];
  321.     int        i, strCount=0;
  322.     int        rval;
  323.  
  324.     if(*(initComplete))
  325.         Terminate(fd);
  326.  
  327.           lpfnGetNetAddressDlgProc = MakeProcInstance ((FARPROC) GetNetAddressDlgProc, globalhInstance);
  328.  
  329.           rval = DialogBox(globalhInstance, "NET_ADDR", hwnd, lpfnGetNetAddressDlgProc);
  330.  
  331.           if(rval == -1)
  332.                 {
  333.                  wsprintf(displayMessage, "Call to DialogBox() returned %d", rval);
  334.                  MessageBox(NULL, displayMessage,"Function Failed", MB_OK);
  335.                 }
  336.  
  337.             for(i=0; i<22; ++i)
  338.                 {
  339.                 if(inetString[i] != ':')
  340.                     {
  341.                     tempString[strCount] = inetString[i];
  342.                     strCount +=1;
  343.                     }
  344.                 }
  345.  
  346.             strToHex(tempString, (unsigned char *)spx_addr, 10);
  347.  
  348.             /*-------------------------------------------------------------------
  349.             ** Connection is opened in non-blocking mode by using 0_NDELAY
  350.             */
  351.             
  352.             if ( ( *(fd) = t_open( "/dev/nspx", O_RDWR | O_NDELAY, ( struct t_info * )0 ) ) == -1 ) 
  353.             {    t_error( "Open of /dev/nspx failed" );
  354.                 return FALSE;
  355.             }
  356.  
  357.  
  358.             if ( t_bind( *(fd), ( struct t_bind * )0, ( struct t_bind * )0  ) == -1 ) 
  359.             {     t_error( "Bind failed!" );
  360.             return FALSE;
  361.             }
  362.             spx_addr->ipxa_socket[ 0 ]  = 0;         // Step 2       
  363.             spx_addr->ipxa_socket[ 1 ]  = SPX_SOCKET;
  364.  
  365.             tcall->addr.buf         = ( char * ) spx_addr;            // Step 3
  366.             tcall->addr.maxlen      = sizeof( *(spx_addr) );
  367.             tcall->addr.len         = sizeof( *(spx_addr) );
  368.             spx_options->spx_connectionID[ 0 ]    = 0;
  369.             spx_options->spx_connectionID[ 1 ]    = 0;
  370.             spx_options->spx_allocationNumber[ 0 ] = 0;
  371.             spx_options->spx_allocationNumber[ 1 ] = 0;
  372.             tcall->opt.buf        = ( char * )spx_options;
  373.             tcall->opt.len          = sizeof( *(spx_options) );
  374.             tcall->opt.maxlen       = sizeof( *(spx_options) );
  375.             tcall->udata.buf        = ( char * )0;
  376.             tcall->udata.maxlen     = 0;
  377.             tcall->udata.len        = 0;
  378.  
  379.             /*-------------------------------------------------------------------
  380.             ** The call to t_connect completes immediately in non-blocking mode 
  381.             ** and will typically return TNODATA. You will note that upon a 
  382.             ** timer message I check to see if init is complete, if it is then
  383.             ** I call t_rcvconnect to complete the establishment of the connection
  384.             ** with the server. You must call t_rcvconnect in non-blocking mode
  385.             ** to complete the establishment of the connection with the server.
  386.             */
  387.  
  388.             rval = t_connect( *(fd), ( struct t_call  far * )tcall, (  struct t_call  far *  )tcall );
  389.  
  390.             if ( (rval == -1) && (t_errno != TNODATA))                     
  391.                 {    
  392.                  t_error( "t_connect failed" );
  393.                  if ( t_errno == TLOOK && t_look( *(fd) ) == T_DISCONNECT )
  394.                          SPXDisconReason( *(fd), hwnd );
  395.                          return FALSE;
  396.                 }
  397.  
  398.             *(initComplete) = 1;
  399.  
  400.  
  401.     return TRUE;
  402. }
  403.  
  404. BOOL Terminate(int *fd)
  405. {
  406.     if ( t_snddis( *(fd), ( struct t_call * )0 ) == -1 )            
  407.         t_error( "t_snddis failed" );
  408.  
  409.     t_close( *(fd) );
  410.  
  411.     return TRUE;
  412. }
  413.  
  414. BOOL SPXDisconReason(int fd, HWND hwnd)
  415. {
  416.     struct  t_discon discon;
  417.     char    *msg;
  418.  
  419.     if (t_rcvdis(fd, &discon) == -1)
  420.           {
  421.           t_error( "t_rcvdis failed" );
  422.           return (TRUE);
  423.           }
  424.     switch( discon.reason )
  425.          {
  426.          case TLI_SPX_CONNECTION_FAILED:
  427.                  msg = "Connection failed";
  428.                  break;
  429.          case TLI_SPX_CONNECTION_TERMINATED:
  430.                  msg = "Connection terminated by client";
  431.  
  432.                  break;
  433.          case TLI_SPX_MALFORMED_PACKET:
  434.                  msg = "Internal SPX interface error -- malformed packet";
  435.                  break;
  436.          default:
  437.                  msg = "Unknown termination reason";
  438.          }
  439.  
  440.     memset(displayMessage, 0, sizeof(displayMessage));
  441.  
  442.     wsprintf(displayMessage, "\r\nSPX Connection number terminated: \r\n %s\r\n", msg);
  443.  
  444.     if(strlen(displayMessage) + strlen(globalMessage) < MAX_MESSAGE_SIZE)
  445.         {
  446.         strcpy(tempMessage, displayMessage);
  447.         strcat(tempMessage, globalMessage);
  448.         strcpy(globalMessage, tempMessage);
  449.         }
  450.     else
  451.         {
  452.         memset(globalMessage, 0, sizeof(globalMessage));
  453.         strcpy(tempMessage, displayMessage);
  454.         strcat(tempMessage, globalMessage);
  455.         strcpy(globalMessage, tempMessage);
  456.         }
  457.  
  458.     
  459.     SendDlgItemMessage(hwnd, IDC_DISPLAY_DATA, WM_SETTEXT, 0, 
  460.                                 (LONG) (LPSTR) globalMessage);
  461.  
  462.     return FALSE;
  463. }
  464.  
  465.  
  466. BOOL strToHex(char *ascii, unsigned char *hex, int length)
  467. {
  468.     int      i, j;
  469.     char     tmp_char;
  470.  
  471.     for (i=0, j=0; i<2*length; i+=2,j++)
  472.         {
  473.         if (!isxdigit(tmp_char=toupper(ascii[i])) )
  474.             {
  475.             return 0;
  476.             }
  477.         else
  478.             hex[j] = ((tmp_char>'9') ? (tmp_char-0x37) : (tmp_char-0x30)) << 4;
  479.  
  480.         if(!isxdigit(tmp_char=toupper(ascii[i+1])) )
  481.             {
  482.             return 0;
  483.             }
  484.         else
  485.             hex[j] += (tmp_char > '9') ? (tmp_char-0x37) : (tmp_char-0x30);
  486.  
  487.         }
  488.     return 1;
  489. }
  490.  
  491.  
  492. BOOL FAR PASCAL GetNetAddressDlgProc(HWND hDlg, WORD msg, WORD wParam, DWORD lParam)
  493. {
  494.     switch(msg)
  495.         {
  496.         case WM_INITDIALOG:
  497.  
  498.         return TRUE;
  499.  
  500.         case WM_COMMAND:
  501.               switch(wParam)
  502.                         {
  503.                         case GET_NET_ADDR:
  504.                             SendDlgItemMessage(hDlg, IDC_NET_ADDR, WM_GETTEXT, sizeof(inetString), 
  505.                                                         (LONG) (LPSTR) inetString);
  506.                             if(strlen(inetString) == 0)
  507.                                 {
  508.                                 MessageBox(NULL, (LPSTR)"You must enter net:node address!", "Error!", IDOK);
  509.                                 break; 
  510.                                 }
  511.  
  512.                             SendDlgItemMessage(hDlg, IDC_GET_NAME, WM_GETTEXT, sizeof(myName), 
  513.                                                         (LONG) (LPSTR) myName);
  514.  
  515.                             if(strlen(myName) == 0)
  516.                                 {
  517.                                 MessageBox(NULL, (LPSTR)"You must enter your first name!", "Error!", IDOK);
  518.                                 break; 
  519.                                 }
  520.                                 
  521.                             EndDialog(hDlg, TRUE);
  522.                             return TRUE;
  523.                         }
  524.         }
  525.         return FALSE;                
  526. }