www.pudn.com > finger31.zip > NETWRKM.C


// 
// Finger Version 3.1, a Windows Sockets Finger Client 
// 
// Copyright 1992, 1993 Network Research Corporation 
// 
// Permission to use, modify, and distribute this software and its 
// documentation for any purpose and without fee is hereby granted, provided 
// that the above copyright notice appears in all copies and that both 
// that copyright notice and this permission notice appear in supporting 
// documentation.  NRC makes no claims as to the suitability of this software 
// for any purpose. 
// 
// Module NETWRKM uses Windows Sockets asynchronous (message based) calls to 
// query a remote finger server for a list of currently logged in users. 
// Module FINGER initiates the operation by calling FingerStart(), and 
// NETWRKM signals completion by calling FingerFinish(). NETWRKM uses DSPLIST 
// functions to send the retrieved data to the FINGER user interface module. 
// 
// 04/01/92 Lee Murach  Created. 
// 11/30/92 Lee Murach  Adapted for WS 1.1 WSAAsyncSelect() 
// 12/02/92 Lee Murach  Restructured for Finger 3.0 integrated release 
// 01/15/92 Lee Murach  Change FD_READ to FD_READ | FD_CLOSE 
// 03/01/93 Lee Murach  Added WSAEWOULDBLOCK check to DoConnect() 
// 03/25/93 Lee Murach  Added per-user finger support. 
// 
 
#include  
#include  
#include  
#include  
#include "finger.h" 
 
// messages for windows sockets returns 
#define WM_SERVICE            (WM_USER + 1) 
#define WM_HOSTRESOLVED       (WM_USER + 2) 
#define WM_CONNECTED          (WM_USER + 3) 
#define WM_OKTORECV           (WM_USER + 4) 
#define NETWINDOW "NetWindow" 
 
LONG FAR APIENTRY NetWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam); 
LONG DoResolveHost(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam); 
LONG DoConnect(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam); 
LONG DoQuery(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam); 
LONG DoRetrieval(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam); 
void LoadEntBuf(IPA ipa); 
 
DECODEWORD netMsgs[] =                 // network window messages & handlers 
{ 
   WM_SERVICE,       DoResolveHost, 
   WM_HOSTRESOLVED,  DoConnect, 
   WM_CONNECTED,     DoQuery, 
   WM_OKTORECV,      DoRetrieval 
}; 
 
SOCKET   Sock;                         // connects to remote server's socket 
int      Port;                         // hold port for finger service 
char     EntBuf[MAXGETHOSTSTRUCT];     // buf for service & resolve returns 
HWND     hNetWnd;                      // network window handle 
 
// 
// InitNetApp -- registers window class for the network module's invisible 
// child window. This is called only for the first instance of finger. 
// 
VOID InitNetApp(VOID) 
{ 
   WNDCLASS wndclass; 
 
   wndclass.style         = 0; 
   wndclass.lpfnWndProc   = NetWndProc; 
   wndclass.cbClsExtra    = 0; 
   wndclass.cbWndExtra    = 0; 
   wndclass.hInstance     = hInst; 
   wndclass.hIcon         = 0; 
   wndclass.hCursor       = 0; 
   wndclass.hbrBackground = 0; 
   wndclass.lpszMenuName  = NULL; 
   wndclass.lpszClassName = NETWINDOW; 
 
   RegisterClass(&wndclass); 
} 
 
// 
// InitNetInst -- initializes the network module by creating an invisible 
// child of the main finger window which will be used to receive Windows 
// Sockets notification messages.  The window will be automatically 
// destroyed when the main window exits, so no finalization is required. 
// 
VOID InitNetInst(HWND hWnd) 
{ 
   hNetWnd = CreateWindow( NETWINDOW, "", WS_OVERLAPPEDWINDOW, 
                           CW_USEDEFAULT, CW_USEDEFAULT, 
                           CW_USEDEFAULT, CW_USEDEFAULT, 
                           hWnd, 0, hInst, NULL); 
} 
 
// 
// NetWndProc -- callback function for network window.  The network window 
// is a child window created especially to receive windows sockets network 
// messages.  The function decodes and routes to appropriate message handler. 
// 
LONG FAR APIENTRY NetWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) 
{ 
   int i; 
 
   for (i = 0; i < dim(netMsgs); i++) 
   { 
      if (wMsg == netMsgs[i].Code) 
         return((*netMsgs[i].Fxn)(hWnd, wMsg, wParam, lParam)); 
   } 
 
   return(DefWindowProc(hWnd, wMsg, wParam, lParam)); 
} 
 
// 
// FingerStart -- called by FINGER module to initiate a conversation with 
// the remote finger server.  We start by resolving the finger tcp service 
// to a port number. Windows Sockets WSAAsync routines signal completion 
// by posting messages, which are dispatched to appropriate handlers. 
// 
VOID FingerStart(VOID) 
{ 
   if (WSAAsyncGetServByName(hNetWnd, WM_SERVICE, "finger", "tcp", 
                             EntBuf, sizeof(EntBuf)) == -1) 
   { 
      ReportFingerErr(FE_NOPORT); 
      FingerFinish(FE_ERROR); 
   } 
} 
 
// 
// DoResolveHost -- resolves host specifier to an IP address.  Since we 
// allow a "dotted decimal" IP address to be entered in lieu of a DNS host 
// name, we check for this syntax before assuming a DNS name. 
// 
LONG DoResolveHost(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) 
{ 
   IPA ipa; 
 
   if (WSAGETSELECTERROR(lParam)) 
   { 
      ReportFingerErr(FE_NOPORT);         // cannot locate finger service 
      FingerFinish(FE_ERROR); 
      return(FALSE); 
   } 
 
   Port = ((SERVENT *)EntBuf)->s_port;    // we're going to reuse the buffer 
 
   // if host specifier is dotted decimal ip address, resolve right here 
   if ((ipa = INET_ADDR(szHostName)) != INADDR_NONE) 
   { 
      LoadEntBuf(ipa); 
      PostMessage(hNetWnd, WM_HOSTRESOLVED, 0, 0); 
      return(FALSE); 
   } 
 
   // assume specifier is DNS host name 
   if (WSAAsyncGetHostByName(hNetWnd, WM_HOSTRESOLVED, szHostName, 
                             EntBuf, sizeof(EntBuf)) == -1) 
   { 
      ReportFingerErr(FE_NOHOST); 
      FingerFinish(FE_ERROR); 
   } 
 
   return(FALSE); 
} 
 
// 
// LoadEntBuf -- loads the EntBuf (sufficiently) with a HOSTENT and 
// referenced IPA.  This is so we can return IPAs in the same 
// manner as a WSAAsync call. 
// 
void LoadEntBuf(IPA ipa) 
{ 
   LPHOSTENT phe = (LPHOSTENT) EntBuf; 
   LPPIPA ppipa = (LPPIPA) (EntBuf + sizeof(HOSTENT)); 
   LPIPA pipa = (LPIPA) (EntBuf + sizeof(HOSTENT) + sizeof(LPPIPA)); 
 
   _fmemset(phe, 0, sizeof(HOSTENT)); 
   phe->h_addr_list = (char FAR * FAR *) ppipa; 
   *ppipa = pipa; 
   *pipa = ipa; 
} 
 
// 
// DoConnect -- allocates a socket and connects to remote finger server. 
// 
LONG DoConnect(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) 
{ 
   if (WSAGETSELECTERROR(lParam)) 
   { 
      ReportFingerErr(FE_NOHOST);       // could not resolve host name 
      FingerFinish(FE_ERROR); 
      return(FALSE); 
   } 
 
   if ((Sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0) 
   { 
      SOCKADDR_IN server; 
      u_long block = FALSE; 
      HOSTENT *phe = (HOSTENT *) EntBuf; 
 
      memset(&server, 0, sizeof(server)); 
      server.sin_family = AF_INET; 
      server.sin_port = Port; 
      server.sin_addr = *((IN_ADDR FAR *) *phe->h_addr_list); 
 
      // post message when connect is established 
      WSAAsyncSelect(Sock, hNetWnd, WM_CONNECTED, FD_CONNECT); 
 
      if (  connect(Sock, (SOCKADDR *)&server, sizeof(server)) < 0 && 
            WSAGetLastError() != WSAEWOULDBLOCK) 
      { 
         ReportFingerErr(FE_NOCONN); 
         FingerFinish(FE_ERROR); 
      } 
   } 
   else 
   { 
      ReportFingerErr(FE_NOSOCK); 
      FingerFinish(FE_ERROR); 
   } 
 
   return(FALSE); 
} 
 
// 
// DoQuery -- sends a query for all currently logged in users to remote 
// server. 
// 
LONG DoQuery(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) 
{ 
   char msg[MAXUSER+3]; 
   int msglen; 
 
   if (WSAGETSELECTERROR(lParam)) 
   { 
      ReportFingerErr(FE_NOCONN);       // could not connect to server 
      FingerFinish(FE_ERROR); 
      return(FALSE); 
   } 
 
   // post message when data is available for read 
   WSAAsyncSelect(Sock, hNetWnd, WM_OKTORECV, FD_READ | FD_CLOSE); 
 
   strcpy(msg, szUser); 
   strcat(msg, "\r\n"); 
   msglen = strlen(msg); 
 
   if (send(Sock, msg, msglen, 0) != msglen) 
   { 
      ReportFingerErr(FE_NOSEND); 
      FingerFinish(FE_ERROR); 
      return(FALSE); 
   } 
    
   OpenDisplayList();   // new display list will contain received data 
    
   return(FALSE); 
} 
 
// 
// DoRetrieval -- fetches ascii text from remote finger server, and builds 
// display list until the end of the text stream. 
// 
LONG DoRetrieval(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) 
{ 
   static char buf[500]; 
   int nchars, err = 0; 
 
   /* receives data not to exceed buf size & reenables notification 
      of more data pending */ 
 
   if ((nchars = recv(Sock, (char FAR *)&buf, sizeof(buf), 0)) > 0) 
   { 
      PushChars(buf, nchars);        // adds character to display list 
      return(FALSE); 
   } 
 
   CloseDisplayList();               // close list if error or end-of-data 
   closesocket(Sock);                // don't need socket anymore 
 
   if (nchars < 0) 
   { 
      FreeDisplayList(); 
      ReportFingerErr(FE_NORECV);   // error during receive 
      err = FE_ERROR; 
   } 
 
   FingerFinish(err);               // signal end-of-finger 
 
   return(FALSE); 
}