home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / winsock / finger10 / netwrkm.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  9.5 KB  |  368 lines

  1. //
  2. // Finger Version 1.0, a Windows Sockets Finger Client
  3. //
  4. // Copyright (C) 1994 by Zoran Dukic.
  5. //
  6. // Permission to use, modify, and distribute this software and its
  7. // documentation for any purpose and without fee is hereby granted, provided
  8. // that the above copyright notice appears in all copies and that both
  9. // that copyright notice and this permission notice appear in supporting
  10. // documentation.  Zoran Dukic makes no claims as to the suitability of this 
  11. // software for any purpose.
  12. //
  13. // Module NETWRKM uses Windows Sockets asynchronous (message based) calls to
  14. // query a remote finger server for a list of currently logged in users.
  15. // Module FINGER initiates the operation by calling FingerStart(), and
  16. // NETWRKM signals completion by calling FingerFinish(). 
  17. //
  18.    
  19. /*****************************************************************************
  20.    Module NETWRKM is reconstruction of the same module from the Finger 3.1, 
  21.    for C++, so here is the copyright notice for the Finger 3.1.
  22.  
  23.    Finger Version 3.1, a Windows Sockets Finger Client
  24.  
  25.    Copyright 1992, 1993 Network Research Corporation
  26.  
  27.    Permission to use, modify, and distribute this software and its
  28.    documentation for any purpose and without fee is hereby granted, provided
  29.    that the above copyright notice appears in all copies and that both
  30.    that copyright notice and this permission notice appear in supporting
  31.    documentation.  NRC makes no claims as to the suitability of this software
  32.    for any purpose.
  33.  
  34.    04/01/92 Lee Murach  Created.
  35.    11/30/92 Lee Murach  Adapted for WS 1.1 WSAAsyncSelect()
  36.    12/02/92 Lee Murach  Restructured for Finger 3.0 integrated release
  37.    01/15/92 Lee Murach  Change FD_READ to FD_READ | FD_CLOSE
  38.    03/01/93 Lee Murach  Added WSAEWOULDBLOCK check to DoConnect()
  39.    03/25/93 Lee Murach  Added per-user finger support.
  40. ******************************************************************************/
  41.  
  42.  
  43. #include "finger.h"
  44.  
  45. extern char     szAppName[];           // application's name
  46.  
  47.  
  48. TNetWnd::TNetWnd(PTWindowsObject AParent)
  49.     :TWindow(AParent, "")
  50. {
  51.      Attr.Style   = WS_OVERLAPPEDWINDOW;
  52.      Attr.X       = CW_USEDEFAULT;
  53.      Attr.Y       = CW_USEDEFAULT;
  54.      Attr.W       = CW_USEDEFAULT;
  55.      Attr.H       = CW_USEDEFAULT;
  56.  
  57.      pReceiveList = NULL;
  58.  
  59.      int err;
  60.  
  61.      if ((err = WSAStartup(WSVERSION, &WSAData)) != 0)    // register task with
  62.      {                                                    // winsock tcp/ip API
  63.      ((PTFingerWnd)Parent)->ReportWSError(err);
  64.      DestroyWindow(Parent->HWindow);              // kill application window &
  65.      }                                                    // signal app exit
  66. }
  67.  
  68.  
  69. TNetWnd::~TNetWnd()
  70. {
  71.    if(pReceiveList != NULL)delete pReceiveList;
  72.    WSACleanup();                             // disconnect from winsock
  73. }; 
  74.  
  75.  
  76.  
  77. LPSTR TNetWnd::GetClassName()
  78. {
  79.      return NETWINDOW;
  80. }
  81.  
  82.  
  83.  
  84. void TNetWnd::GetWindowClass(WNDCLASS& wndclass)
  85. {
  86.      TWindow::GetWindowClass(wndclass);
  87.  
  88.      wndclass.style         = 0;
  89.      wndclass.hIcon         = 0;
  90.      wndclass.hCursor       = 0;
  91.      wndclass.hbrBackground = 0;
  92. }
  93.  
  94.  
  95. //
  96. // FingerStart -- called by FINGER module to initiate a conversation with
  97. // the remote finger server.  We start by resolving the finger tcp service
  98. // to a port number. Windows Sockets WSAAsync routines signal completion
  99. // by posting messages, which are dispatched to appropriate handlers.
  100. //
  101. void TNetWnd::FingerStart()
  102. {
  103.    if (WSAAsyncGetServByName(HWindow, WM_SERVICE, "finger", "tcp",
  104.                  EntBuf, sizeof(EntBuf)) == NULL)
  105.    {
  106.       ReportFingerErr(FE_NOPORT);
  107.       FingerFinish(FE_ERROR);
  108.    }
  109. }
  110.  
  111.  
  112. // FingerFinish -- invoked when the finger operation is complete,
  113. // this function updates the display list & repaints the frame window
  114. // client area if the operation was successful.
  115. //
  116. void TNetWnd::FingerFinish(UINT Err)
  117. {  
  118.    ((PTFingerWnd)Parent)->FingerFinish(Err);
  119. }
  120.  
  121.  
  122. // ReportFingerErr -- prompt user with a finger specific error
  123. //
  124. void TNetWnd::ReportFingerErr(UINT Err)
  125. {
  126.    ((PTFingerWnd)Parent)->ReportFingerErr(Err);
  127. };
  128.  
  129.  
  130.  
  131. //
  132. // LoadEntBuf -- loads the EntBuf (sufficiently) with a HOSTENT and
  133. // referenced IPA.  This is so we can return IPAs in the same
  134. // manner as a WSAAsync call.
  135. //
  136. void TNetWnd::LoadEntBuf(IPA ipa)
  137. {
  138.    LPHOSTENT phe = (LPHOSTENT) EntBuf;
  139.    LPPIPA ppipa = (LPPIPA) (EntBuf + sizeof(HOSTENT));
  140.    LPIPA pipa = (LPIPA) (EntBuf + sizeof(HOSTENT) + sizeof(LPPIPA));
  141.  
  142.    _fmemset(phe, 0, sizeof(HOSTENT));
  143.    phe->h_addr_list = (char FAR * FAR *) ppipa;
  144.    *ppipa = pipa;
  145.    *pipa = ipa;
  146. }
  147.  
  148.  
  149. //
  150. // DoResolveHost -- resolves host specifier to an IP address.  Since we
  151. // allow a "dotted decimal" IP address to be entered in lieu of a DNS host
  152. // name, we check for this syntax before assuming a DNS name.
  153. //
  154. void TNetWnd::DoResolveHost(RTMessage Msg)
  155. {
  156.    IPA ipa;
  157.  
  158.    if (WSAGETSELECTERROR(Msg.LParam))
  159.    {
  160.       ReportFingerErr(FE_NOPORT);         // cannot locate finger service
  161.       FingerFinish(FE_ERROR);
  162.       return;
  163.    }
  164.  
  165.    Port = ((SERVENT *)EntBuf)->s_port;    // we're going to reuse the buffer
  166.  
  167.    // if host specifier is dotted decimal ip address, resolve right here
  168.    if ((ipa = INET_ADDR(szHostName)) != INADDR_NONE)
  169.    {
  170.       LoadEntBuf(ipa);
  171.       PostMessage(HWindow, WM_HOSTRESOLVED, 0, 0);
  172.       return;
  173.    }
  174.  
  175.    // assume specifier is DNS host name
  176.    if (WSAAsyncGetHostByName(HWindow, WM_HOSTRESOLVED, szHostName,
  177.                  EntBuf, sizeof(EntBuf)) == NULL)
  178.    {
  179.       ReportFingerErr(FE_NOHOST);
  180.       FingerFinish(FE_ERROR);
  181.    }
  182.  
  183.    return;
  184. }
  185.  
  186.  
  187. //
  188. // DoConnect -- allocates a socket and connects to remote finger server.
  189. //
  190. void TNetWnd::DoConnect(RTMessage Msg)
  191. {
  192.    if (WSAGETSELECTERROR(Msg.LParam))
  193.    {
  194.       ReportFingerErr(FE_NOHOST);       // could not resolve host name
  195.       FingerFinish(FE_ERROR);
  196.       return;
  197.    }
  198.  
  199.    if ((Sock = socket(AF_INET, SOCK_STREAM, 0)) < WSABASEERR)
  200.    {
  201.       SOCKADDR_IN server;
  202.       u_long block = FALSE;
  203.       HOSTENT *phe = (HOSTENT *) EntBuf;
  204.  
  205.       memset(&server, 0, sizeof(server));
  206.       server.sin_family = AF_INET;
  207.       server.sin_port = Port;
  208.       server.sin_addr = *((IN_ADDR FAR *) *phe->h_addr_list);
  209.  
  210.       // post message when connect is established
  211.       WSAAsyncSelect(Sock, HWindow, WM_CONNECTED, FD_CONNECT);
  212.  
  213.       if (  connect(Sock, (SOCKADDR *)&server, sizeof(server)) < 0 &&
  214.         WSAGetLastError() != WSAEWOULDBLOCK)
  215.       {
  216.      ReportFingerErr(FE_NOCONN);
  217.      FingerFinish(FE_ERROR);
  218.       }
  219.    }
  220.    else
  221.    {
  222.       ReportFingerErr(FE_NOSOCK);
  223.       FingerFinish(FE_ERROR);
  224.    }
  225.  
  226.    return;
  227. }
  228.  
  229.  
  230. //
  231. // DoQuery -- sends a query for all currently logged in users to remote
  232. // server.
  233. //
  234.  
  235. void TNetWnd::DoQuery(RTMessage Msg)
  236. {
  237.    char msg[MAXUSER+3];
  238.    int msglen;
  239.  
  240.    if (WSAGETSELECTERROR(Msg.LParam))
  241.    {
  242.       ReportFingerErr(FE_NOCONN);       // could not connect to server
  243.       FingerFinish(FE_ERROR);
  244.       return;
  245.    }
  246.  
  247.    // post message when data is available for read
  248.    WSAAsyncSelect(Sock, HWindow, WM_OKTORECV, FD_READ | FD_CLOSE);
  249.  
  250.    strcpy(msg, szUser);
  251.    strcat(msg, "\r\n");
  252.    msglen = strlen(msg);
  253.  
  254.    if (send(Sock, msg, msglen, 0) != msglen)
  255.    {
  256.       ReportFingerErr(FE_NOSEND);
  257.       FingerFinish(FE_ERROR);
  258.       return;
  259.    }
  260.  
  261.    LineLen = 0;
  262.    maxLineLen = 0;
  263.    pReceiveList = new Array(50,0,50);   // new receive list will contain received data
  264.    
  265.    return;
  266. }
  267.  
  268.  
  269. //
  270. // DoRetrieval -- fetches ascii text from remote finger server, and builds
  271. // display list until the end of the text stream.
  272. //
  273. void TNetWnd::DoRetrieval(RTMessage)
  274. {
  275.    static char buf[500];
  276.    int nchars, err = 0;
  277.  
  278.    /* receives data not to exceed buf size & reenables notification
  279.       of more data pending */
  280.  
  281.    if ((nchars = recv(Sock, (char FAR *)&buf, sizeof(buf), 0)) > 0)
  282.    {
  283.       PushChars(buf, nchars);        // adds character to display list
  284.       return;
  285.    }
  286.  
  287.    closesocket(Sock);                // don't need socket anymore
  288.  
  289.    if (nchars < 0)
  290.    {
  291.       delete pReceiveList;
  292.       ReportFingerErr(FE_NORECV);   // error during receive
  293.       err = FE_ERROR;
  294.    }
  295.  
  296.    FingerFinish(err);               // signal end-of-finger
  297.  
  298.    return;
  299. }
  300.  
  301.  
  302.  
  303. //
  304. // PushChars -- pushes buffer of characters into the display list;
  305. // expands tabs.
  306. //
  307. void TNetWnd::PushChars(char *buf, int buflen)
  308. {
  309.    while (buflen--)
  310.    {
  311.       if (*buf == '\t')
  312.      PushChars(TABSTRING, strlen(TABSTRING));
  313.       else
  314.      PushChar(*buf);
  315.    
  316.       buf++;
  317.    }
  318. }
  319.  
  320.  
  321. //
  322. // PushChar -- pushes a character into the LineBuf.  Pushes line into
  323. // the line list if <cr> encountered, or LineBuf is full.  Discards
  324. // linefeeds.
  325. //
  326. void TNetWnd::PushChar(char ch)
  327. {
  328.    if (LineLen < sizeof(LineBuf))
  329.       if (ch != LF)
  330.      if (ch != CR)
  331.         LineBuf[LineLen++] = ch;
  332.      else ;                            // discard carriage returns
  333.       else
  334.       {
  335.      LineBuf[LineLen++] = ' ';
  336.      PushLine();                       // linefeeds signal newline
  337.       }
  338.    else
  339.       PushLine();
  340. }
  341.  
  342. //
  343. // PushLine -- pushes a text line into the accumulating list of text lines.
  344. //
  345. void TNetWnd::PushLine(VOID)
  346. {
  347.    PTLine pLine = new TLine(LineBuf, LineLen);
  348.  
  349.    if(LineLen > maxLineLen) maxLineLen = LineLen;
  350.    LineLen = 0;
  351.  
  352.    pReceiveList->add((Object&)*pLine);
  353. }
  354.  
  355.  
  356. //
  357. // Constructor for TLine object
  358. //
  359.                   
  360. TLine::TLine(char *srcbuf, int Len)
  361. {
  362.     if ((sztext = (char *)malloc(Len)) != NULL)
  363.     {
  364.     strncpy(sztext, srcbuf, Len);
  365.     LLen = Len;
  366.     }
  367. };
  368.