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 >
Wrap
Text File
|
1995-09-08
|
16KB
|
526 lines
/*
Copyright (c) 1992 Novell, Inc. All Rights Reserved.
THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
TREATIES. USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE
LICENSE AGREEMENT ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK)
THAT CONTAINS THIS WORK.
Pursuant to the SDK License Agreement, Novell hereby grants to
Developer a royalty-free, non-exclusive license to include the
sample code GRPCHATC.C and derivative binaries in its product.
Novell grants to Developer worldwide distribution rights to market,
distribute or sell the sample code GRPCHATC.C and derivative
binaries as a component of Developer's product(s). Novell shall
have no obligations to Developer or Developer's customers with
respect to this code.
DISCLAIMER:
Novell, Inc. makes no representations or warranties with respect
to the contents or use of this code, and specifically disclaims any
express or implied warranties of merchantability or fitness for any
particular purpose. Further, Novell, Inc. reserves the right to revise
this publication and to make changes to its content, at any time,
without obligation to notify any person or entity of such revisions or
changes.
Further, Novell, Inc. makes no representations or warranties with
respect to any software, and specifically disclaims any express or
implied warranties of merchantability or fitness for any particular
purpose. Further, Novell, Inc. reserves the right to make changes to
any and all parts of the software, at any time, without obligation to
notify any person or entity of such changes.
***************************************************************************
GRPCHATC.C
**************************************************************************/
/**************************************************************************
** Description: This is a partner program to GRPCHATS.EXE and serves as a
** chat client to GRPCHATS.EXE -- the server or passive connection.
** This sample code demonstates how to use TLI in non-blocking mode.
** The server simply echos everything sent by the client to all clients
** currently connected. A timer is used to periodically check for
** data that may have been received. When this application loads it
** presents a dialog box requesting the address of the server. Since
** the server application must be loaded first read the address displayed
** on the server console and enter in this dialog box along with your
** name. Enter the address exactly as it is displayed on the server
** console, including the ':' delimeter between the NET:NODE.
**
** Compiler: Borland C++ v4.5
**
** Programmer : Karl Bunnell
** Date: 08/24/1995
**
*/
#include <windows.h>
#define NWWIN
#include <nwipxspx.h>
#include <mem.h>
#include <string.h>
#include "grpchatc.h"
#include <ctype.h>
#include <tispxipx.h>
#include <tiuser.h>
#define SPX_SOCKET 31 // arbitrary socket
#define MAX_MESSAGE_SIZE 1024
#define ID_TIMER 1
long FAR PASCAL _export WndProc(HWND, UINT, UINT, LONG);
BOOL Terminate(int *fd);
BOOL SPXDisconReason(int fd, HWND hwnd);
BOOL strToHex(char *ascii, unsigned char *hex, int length);
BOOL InitConnection(IPX_ADDR *spx_addr, SPX_OPTS *spx_options, t_call *tcall,
int *initComplete, int *fd, HWND hwnd);
BOOL FAR PASCAL GetNetAddressDlgProc(HWND hDlg, WORD msg, WORD wParam, DWORD lParam);
static char globalMessage[1024];
char displayMessage[1024];
char tempMessage[1024];
static char inetString[25];
static HANDLE globalhInstance;
static char myName[16];
/*-----------------------------------------------------------------------------
**
*/
int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
static char szGRPCHATC[] = "GRPCHATC";
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
if(!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = DLGWINDOWEXTRA;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = COLOR_WINDOW + 1;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szGRPCHATC;
RegisterClass(&wndclass);
}
hwnd = CreateDialog(hInstance, "MainDialog", 0, NULL);
globalhInstance = hInstance;
while (!SetTimer (hwnd, ID_TIMER, 55, NULL))
if(IDCANCEL == MessageBox(hwnd, "Too many clocks or timers!", "GRPCHATC",
MB_ICONEXCLAMATION | MB_RETRYCANCEL))
return FALSE;
SendMessage(hwnd, WM_INITWINDOW, NULL, NULL);
ShowWindow(hwnd, nCmdShow);
while(GetMessage(&msg, NULL, 0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//-----------------------------------------------------------------------------
long far PASCAL _export WndProc ( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
{
static IPX_ADDR spx_addr;
static SPX_OPTS spx_options;
static struct t_call tcall;
char buf[1024];
char buf2[1024];
static int fd;
int flags;
int rval;
int bytesSent, bytesLeft, nBytes;
static int initComplete = 0;
static int connectFlg = 0;
static char fromName[25];
WORD beep = 0;
switch (message)
{
case WM_INITWINDOW:
if(!InitConnection(&spx_addr, &spx_options, &tcall, &initComplete, &fd, hwnd))
{
wsprintf(displayMessage, "Connection Initialization Failed \r\n Try setting the net address again.");
MessageBox(NULL, displayMessage,"Connect Initialization Failed", MB_OK);
}
wsprintf(fromName, "\r\n--From: %s\r\n", myName);
break;
case WM_TIMER:
if(!initComplete)
break;
/*-----------------------------------------------------------------------------------
** Once the call to InitConnection() is complete and successful I enter the following
** conditional to complete establishment of the connection with t_rcvconnect. If the
** address specifed in the t_call structure is correct and the server is loaded and
** waiting for connections then t_rcvconnect will return 0 (success) indicating that
** a connection was successfully established. A flag is set to ensure that this code
** is not entered again after connection establishment. After the 2 init flags are
** are set, then t_rcv is used to check for pending received data from the server.
*/
if(!connectFlg)
{
rval = t_rcvconnect(fd, &tcall);
if(rval == -1 && t_errno == TNODATA)
break;
else if(((t_errno == TLOOK) && (t_look(fd) == T_CONNECT)) || rval == 0 )
connectFlg = 1;
else
{
rval = t_errno;
t_error("t_rcvconnect failed");
break;
}
}
memset(buf, 0, sizeof(buf));
flags = 0; /* initialize for t_rcv call */
while ( (t_rcv( fd, buf, sizeof( buf),&flags )) != -1 )
{
/*-----------------------------------------------------------------------------------
** Because the connection was opened in non-blocking mode there is a good possibility
** that the complete message has not been received, however, for the purposes of this
** example I'm sending each chunk as I receive it to all connected nodes.
*/
wsprintf(displayMessage, "%s\r\n", buf);
if(strlen(displayMessage) + strlen(globalMessage) < MAX_MESSAGE_SIZE)
{
strcpy(tempMessage, displayMessage);
strcat(tempMessage, globalMessage);
strcpy(globalMessage, tempMessage);
}
else
{
memset(globalMessage, 0, sizeof(globalMessage));
strcpy(tempMessage, displayMessage);
strcat(tempMessage, globalMessage);
strcpy(globalMessage, tempMessage);
}
SendDlgItemMessage(hwnd, IDC_DISPLAY_DATA, WM_SETTEXT, 0,
(LONG) (LPSTR) globalMessage);
MessageBeep(beep);
}
break;
case WM_DESTROY :
KillTimer (hwnd, ID_TIMER);
Terminate(&fd);
PostQuitMessage(0);
return 0;
case WM_COMMAND:
switch(wparam)
{
case IDC_PUSHBUTTON1:
KillTimer (hwnd, ID_TIMER);
Terminate(&fd);
PostQuitMessage(0);
return FALSE;
case IDC_PUSHBUTTON2:
SendDlgItemMessage(hwnd, IDC_SEND_DATA, WM_GETTEXT, sizeof(buf2),
(LONG) (LPSTR) buf2);
if((strlen(buf2) + strlen(fromName)) < MAX_MESSAGE_SIZE)
strcat(buf2, fromName);
nBytes = bytesLeft = strlen(buf2);
if( nBytes == 0)
{
MessageBox(NULL, "Nothing to send!","Data Not Sent", MB_OK);
break;
}
/*-----------------------------------------------------------------------------------
** Because the connection is in non-blocking mode, you must advance the pointer
** in the send buffer yourself. The following loop demonstates one way you might do this.
*/
while (bytesLeft > 0)
{
do
{
bytesSent = t_snd( fd, &buf2[nBytes-bytesLeft], bytesLeft, 0 );
}while ((bytesSent == -1) && (t_errno == TFLOW));
if (bytesSent == -1 )
{
if (t_errno==TLOOK && t_look(fd) == T_DISCONNECT)
SPXDisconReason(fd, hwnd);
else
{
t_error("t_snd failed\n");
t_close(fd);
break;
}
}
else
bytesLeft -= bytesSent;
} // end - while nBytes > 0
SendDlgItemMessage(hwnd, IDC_SEND_DATA, WM_SETTEXT, 0,
(LONG) (LPSTR) "");
break;
case IDC_PUSHBUTTON3:
if(!InitConnection(&spx_addr, &spx_options, &tcall, &initComplete, &fd, hwnd))
{
wsprintf(displayMessage, "Connection Initialization Failed \r\n Try setting the net address again.");
MessageBox(NULL, displayMessage,"Connect Initialization Failed", MB_OK);
}
break;
}
}
return DefWindowProc(hwnd, message, wparam, lparam);
}
BOOL InitConnection(IPX_ADDR *spx_addr, SPX_OPTS *spx_options, t_call *tcall, int *initComplete, int *fd, HWND hwnd)
{
static FARPROC lpfnGetNetAddressDlgProc;
char tempString[22];
int i, strCount=0;
int rval;
if(*(initComplete))
Terminate(fd);
lpfnGetNetAddressDlgProc = MakeProcInstance ((FARPROC) GetNetAddressDlgProc, globalhInstance);
rval = DialogBox(globalhInstance, "NET_ADDR", hwnd, lpfnGetNetAddressDlgProc);
if(rval == -1)
{
wsprintf(displayMessage, "Call to DialogBox() returned %d", rval);
MessageBox(NULL, displayMessage,"Function Failed", MB_OK);
}
for(i=0; i<22; ++i)
{
if(inetString[i] != ':')
{
tempString[strCount] = inetString[i];
strCount +=1;
}
}
strToHex(tempString, (unsigned char *)spx_addr, 10);
/*-------------------------------------------------------------------
** Connection is opened in non-blocking mode by using 0_NDELAY
*/
if ( ( *(fd) = t_open( "/dev/nspx", O_RDWR | O_NDELAY, ( struct t_info * )0 ) ) == -1 )
{ t_error( "Open of /dev/nspx failed" );
return FALSE;
}
if ( t_bind( *(fd), ( struct t_bind * )0, ( struct t_bind * )0 ) == -1 )
{ t_error( "Bind failed!" );
return FALSE;
}
spx_addr->ipxa_socket[ 0 ] = 0; // Step 2
spx_addr->ipxa_socket[ 1 ] = SPX_SOCKET;
tcall->addr.buf = ( char * ) spx_addr; // Step 3
tcall->addr.maxlen = sizeof( *(spx_addr) );
tcall->addr.len = sizeof( *(spx_addr) );
spx_options->spx_connectionID[ 0 ] = 0;
spx_options->spx_connectionID[ 1 ] = 0;
spx_options->spx_allocationNumber[ 0 ] = 0;
spx_options->spx_allocationNumber[ 1 ] = 0;
tcall->opt.buf = ( char * )spx_options;
tcall->opt.len = sizeof( *(spx_options) );
tcall->opt.maxlen = sizeof( *(spx_options) );
tcall->udata.buf = ( char * )0;
tcall->udata.maxlen = 0;
tcall->udata.len = 0;
/*-------------------------------------------------------------------
** The call to t_connect completes immediately in non-blocking mode
** and will typically return TNODATA. You will note that upon a
** timer message I check to see if init is complete, if it is then
** I call t_rcvconnect to complete the establishment of the connection
** with the server. You must call t_rcvconnect in non-blocking mode
** to complete the establishment of the connection with the server.
*/
rval = t_connect( *(fd), ( struct t_call far * )tcall, ( struct t_call far * )tcall );
if ( (rval == -1) && (t_errno != TNODATA))
{
t_error( "t_connect failed" );
if ( t_errno == TLOOK && t_look( *(fd) ) == T_DISCONNECT )
SPXDisconReason( *(fd), hwnd );
return FALSE;
}
*(initComplete) = 1;
return TRUE;
}
BOOL Terminate(int *fd)
{
if ( t_snddis( *(fd), ( struct t_call * )0 ) == -1 )
t_error( "t_snddis failed" );
t_close( *(fd) );
return TRUE;
}
BOOL SPXDisconReason(int fd, HWND hwnd)
{
struct t_discon discon;
char *msg;
if (t_rcvdis(fd, &discon) == -1)
{
t_error( "t_rcvdis failed" );
return (TRUE);
}
switch( discon.reason )
{
case TLI_SPX_CONNECTION_FAILED:
msg = "Connection failed";
break;
case TLI_SPX_CONNECTION_TERMINATED:
msg = "Connection terminated by client";
break;
case TLI_SPX_MALFORMED_PACKET:
msg = "Internal SPX interface error -- malformed packet";
break;
default:
msg = "Unknown termination reason";
}
memset(displayMessage, 0, sizeof(displayMessage));
wsprintf(displayMessage, "\r\nSPX Connection number terminated: \r\n %s\r\n", msg);
if(strlen(displayMessage) + strlen(globalMessage) < MAX_MESSAGE_SIZE)
{
strcpy(tempMessage, displayMessage);
strcat(tempMessage, globalMessage);
strcpy(globalMessage, tempMessage);
}
else
{
memset(globalMessage, 0, sizeof(globalMessage));
strcpy(tempMessage, displayMessage);
strcat(tempMessage, globalMessage);
strcpy(globalMessage, tempMessage);
}
SendDlgItemMessage(hwnd, IDC_DISPLAY_DATA, WM_SETTEXT, 0,
(LONG) (LPSTR) globalMessage);
return FALSE;
}
BOOL strToHex(char *ascii, unsigned char *hex, int length)
{
int i, j;
char tmp_char;
for (i=0, j=0; i<2*length; i+=2,j++)
{
if (!isxdigit(tmp_char=toupper(ascii[i])) )
{
return 0;
}
else
hex[j] = ((tmp_char>'9') ? (tmp_char-0x37) : (tmp_char-0x30)) << 4;
if(!isxdigit(tmp_char=toupper(ascii[i+1])) )
{
return 0;
}
else
hex[j] += (tmp_char > '9') ? (tmp_char-0x37) : (tmp_char-0x30);
}
return 1;
}
BOOL FAR PASCAL GetNetAddressDlgProc(HWND hDlg, WORD msg, WORD wParam, DWORD lParam)
{
switch(msg)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch(wParam)
{
case GET_NET_ADDR:
SendDlgItemMessage(hDlg, IDC_NET_ADDR, WM_GETTEXT, sizeof(inetString),
(LONG) (LPSTR) inetString);
if(strlen(inetString) == 0)
{
MessageBox(NULL, (LPSTR)"You must enter net:node address!", "Error!", IDOK);
break;
}
SendDlgItemMessage(hDlg, IDC_GET_NAME, WM_GETTEXT, sizeof(myName),
(LONG) (LPSTR) myName);
if(strlen(myName) == 0)
{
MessageBox(NULL, (LPSTR)"You must enter your first name!", "Error!", IDOK);
break;
}
EndDialog(hDlg, TRUE);
return TRUE;
}
}
return FALSE;
}