home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / mag&info / msjv7_4.zip / NETBIOS2.ARJ / SERVER.C < prev    next >
C/C++ Source or Header  |  1992-07-01  |  22KB  |  654 lines

  1. /****************************************************************************
  2.  
  3.     PROGRAM: SERVER.C
  4.  
  5.     PURPOSE: Contains Remote Browser Server routines. The Client
  6.              routines are in netio.c and browser.c
  7.  
  8.     NOTE:    The server has always only one pending NCB, be it
  9.              a Listen NCB or a Receive NCB. Hence, only one
  10.              client can connect to it at a time.
  11.  
  12.     FUNCTIONS:
  13.                 InitServer   - Initializes the Server". After initialization,
  14.                                any remote Client can contact the Server.
  15.                 DeleteServer - Removes the Server. It cancels any pending
  16.                                commands.
  17.                 Server       - A routine called during Windows Idle time
  18.                                to allow server accomplish some chores
  19.                 ListenCompleted- Called from browser.c when a pending
  20.                                Listen completes.
  21.                 ReceiveCompleted-Called from browser.c when a pending
  22.                                Receive completes.
  23.                 PostAListen  - Simply posts a asynchronous Listen
  24.                 PostAReceive - Simply posts a asynchronous Receive
  25.  
  26.     History:
  27.                 January, 1992       Alok Sinha      Created
  28.  
  29. ****************************************************************************/
  30.  
  31. // Includes
  32. #include <windows.h>
  33. #include "ncb.h"
  34. #include "state.h"
  35. #include "common.h"
  36. #include "netio.h"
  37. #include "wnetbios.h"
  38.  
  39.  
  40. #include <time.h>
  41. #include <string.h>
  42. #include <stdio.h>
  43.  
  44. /*
  45.  * Global data
  46.  */
  47. extern ServerFSM  ServerState;
  48. extern SendStatus enumSSendStatus;
  49. extern char  chLocalName[];
  50. extern char  chRemoteName[];
  51. extern char     szErrorBuffer[];
  52. char  chServerName [NETBIOS_NAME_LENGTH+1];
  53. /*
  54.  * Local static data
  55.  */
  56.  
  57. BYTE bNameNumS;                 /* Server Name Number in Name Table */
  58. BYTE bLsnS    ;                 /* LSN of the Server        */
  59.                                 /* Server Name              */
  60.  
  61. PNCB  pncbListenNCB;            /* Posted Listen             */
  62. LPSTR lpServerData;             /* Server Receives Data Here */
  63.  
  64. #define SERVER_RECEIVE_SIZE   (2048)
  65. #define FILE_LEN              (13)
  66.  
  67. char  szDirectory [ _MAX_DIR ];
  68.  
  69. extern VOID CopyName( char *pchLocalName, char *pchBuffer );
  70. /*
  71.  *  Internal functions
  72.  */
  73.  
  74. BYTE PostAReceive ( HWND hwnd);
  75. BYTE PostAListen  ( HWND  hwnd );
  76.  
  77. /****************************************************************************
  78.  
  79.     FUNCTION: InitServer()
  80.  
  81.     PURPOSE:  Initialize the Server. In this sample application, we
  82.               only have a single Listen pending at a time. We keep
  83.               a pointer to Listen NCB in static memory while Listen
  84.               NCB itself is in fixed memory.
  85.  
  86. ****************************************************************************/
  87.  
  88. VOID InitServer ( HWND hwndMain )
  89. {
  90.     BYTE bRc;
  91.  
  92.     //  Delete any old connection and name if existing
  93.     if ( ServerState !=  S_UNINITIALIZED)
  94.         DeleteServer( );
  95.  
  96.     // Create a Server name from the local name. Recall, local name
  97.     // is already blank padded.
  98.     memcpy ( chServerName, chLocalName, NETBIOS_NAME_LENGTH + 1);
  99.     chServerName [NETBIOS_NAME_LENGTH - 1] =  SERVER_NAME_END;
  100.  
  101.     // Set the Server back to uninitialized state
  102.     ServerState = S_UNINITIALIZED;
  103.  
  104.     if ((bRc = AddName((LPSTR)chServerName,
  105.                        &bNameNumS)) != NO_ERROR)
  106.     {
  107.         sprintf(szErrorBuffer,
  108.                 "Error Adding Server Name [%s] Error [%x]",
  109.                 chServerName,
  110.                 bRc
  111.                );
  112.  
  113.         MessageBox(hwndMain, (LPSTR)szErrorBuffer,
  114.                    "Error", MB_OK);
  115.  
  116.         return ;
  117.  
  118.     }
  119.     else
  120.         ServerState = S_INITIALIZED;
  121.  
  122.     /*
  123.      *  Now, post a async. LISTEN
  124.      */
  125.  
  126.     if ((bRc = PostAListen( hwndMain)) != NRC_PENDING)
  127.         return ;
  128.     else
  129.         ServerState = S_LISTENING;
  130.  
  131.      return ;
  132.  
  133. }
  134.  
  135. /****************************************************************************
  136.  
  137.     FUNCTION: DeleteServer()
  138.  
  139.     PURPOSE:  Delete the Server. Since, we can either have a Listen
  140.               pending or a Receive pending, cleanup is easy.
  141.  
  142. ****************************************************************************/
  143.  
  144. VOID DeleteServer( )
  145. {
  146.  
  147.     if (ServerState >= S_CONNECTED)
  148.     {
  149.         Hangup(bLsnS);
  150.         bLsnS = 0;
  151.         NcbFree ( (LPVOID) lpServerData); // Free the Previously Allocated Buffer
  152.     }
  153.     else if (ServerState == S_LISTENING)
  154.     {
  155.         Cancel(pncbListenNCB);
  156.         NcbFree( (LPVOID) pncbListenNCB);
  157.     }
  158.  
  159.     if ( ServerState >= S_INITIALIZED)
  160.     {
  161.         (void) DeleteName( (LPSTR) chServerName, bNameNumS);
  162.         bNameNumS = 0;
  163.     }
  164.  
  165.     ServerState = S_UNINITIALIZED;
  166.     return ;
  167.  
  168. }
  169.  
  170.  
  171. /****************************************************************************
  172.  
  173.     FUNCTION: Server()
  174.  
  175.     PURPOSE:  This gets called during Window Idle Time. We can do
  176.               Server specific chores here.
  177.  
  178. ****************************************************************************/
  179.  
  180. VOID Server(HWND hwndMain )
  181. {
  182.  
  183.  /*
  184.   * In this example, we do not do anything
  185.   */
  186.  
  187.  ;
  188.  
  189. }
  190.  
  191. /****************************************************************************
  192.  
  193.     FUNCTION: ListenCompleted()
  194.  
  195.     PURPOSE:  This gets called when a Listen is completed. Once
  196.               a Listen completes, we need to either issue
  197.               a Receive or just re-issue a Receive. In this
  198.               sample, only one Receive can be posted at a time.
  199.  
  200.               'hwndMain' has the window handle to originating window
  201.               and 'pncbNCB' has pointer to just completed NCB.
  202.  
  203. ****************************************************************************/
  204.  
  205. VOID ListenCompleted( HWND hwndMain, PNCB pncbNCB)
  206. {
  207.     BYTE      bRc;
  208.     BOOL      fNcbFreed = FALSE;
  209.  
  210.     // First find out if we timeout or error-ed out
  211.     if (pncbNCB->ncb_cmd_cplt == NRC_CMDTMO)
  212.     {
  213.         NcbFree ( (LPVOID) pncbNCB);
  214.         fNcbFreed = TRUE;
  215.  
  216.        /*
  217.         *  Now, post a async. LISTEN again
  218.         */
  219.         if ((bRc = PostAListen( hwndMain)) == NRC_PENDING)
  220.             ServerState = S_LISTENING;
  221.         return;
  222.     }
  223.     else if (pncbNCB->ncb_cmd_cplt == NRC_GOODRET)
  224.     {
  225.         // Somebody connected to us. Save the local session number
  226.         // and update UI.
  227.         bLsnS = pncbNCB->ncb_lsn;
  228.         _fmemcpy ( (LPVOID) chRemoteName,
  229.                    pncbNCB->ncb_callname,
  230.                    NETBIOS_NAME_LENGTH
  231.                  );
  232.         chRemoteName [ NETBIOS_NAME_LENGTH + 1] = '\0';
  233.         PostMessage (hwndMain, CLIENT_CONNECTED, 0, 0);
  234.  
  235.         // Free the NCB
  236.         NcbFree ( (LPVOID) pncbNCB);
  237.         fNcbFreed = TRUE;
  238.  
  239.         ServerState = S_CONNECTED;
  240.         // Now hang out a receive
  241.         if ((bRc = PostAReceive ( hwndMain)) == NRC_PENDING)
  242.         {
  243.             ServerState = S_RECEIVING;
  244.             return;
  245.         }
  246.         else
  247.         {
  248.             /*
  249.              *  Go back to LISTENing
  250.              */
  251.             if ((bRc = PostAListen( hwndMain)) == NRC_PENDING)
  252.             {
  253.                 ServerState = S_LISTENING;
  254.                 return;
  255.             }
  256.             // else go down to debug print out
  257.         }
  258.     }
  259.  
  260.     // We should never come here. Show error for debugging purposes
  261.  
  262.     sprintf(szErrorBuffer,
  263.             "Error [%d] in ListenComplete\n Aborting Hanging Listen\n Close Program",
  264.             pncbNCB->ncb_cmd_cplt
  265.            );
  266.     MessageBox(hwndMain, (LPSTR)szErrorBuffer,"Error", MB_OK);
  267.  
  268.     if (fNcbFreed = FALSE)
  269.         NcbFree ( (LPVOID) pncbNCB);
  270.  
  271. }
  272.  
  273. /****************************************************************************
  274.  
  275.     FUNCTION: ReceiveCompleted()
  276.  
  277.     PURPOSE:  This gets called when a Receive is completed.
  278.               If Receive simply time-ed out, we need
  279.               to post another Receive. If Client hang-up on
  280.               us, then we need to go back to listen mode.
  281.               Else we need to service a Client who has Sent
  282.               some packet.
  283.  
  284.               'hwndMain' has the window handle to originating window
  285.               and 'pncbNCB' has pointer to just completed NCB.
  286.  
  287. ****************************************************************************/
  288. VOID ReceiveCompleted( HWND hwndMain, PNCB pncbNCB)
  289. {
  290.     BYTE        bRc;
  291.     PACKET FAR *pacPtr;
  292.     char        *pszBuffer;
  293.     LPSTR      lpBuffer;
  294.     FINDFIRST FAR *pFindFirst;
  295.     FINDNEXT  FAR *pFindNext;
  296.     FINDT       findFileInfo;
  297.     FINDT     FAR *pFindToSend;
  298.     BOOL      fNcbFreed = FALSE;
  299.     char      chFileName [ FILE_LEN ];
  300.  
  301.  
  302.  
  303.  
  304.     // First find out if we timeout or error-ed out
  305.     if (pncbNCB->ncb_cmd_cplt == NRC_CMDTMO)
  306.     {
  307.         NcbFree ( (LPVOID) pncbNCB);      // Free the Receive NCB
  308.         NcbFree ( (LPVOID) lpServerData); // Free the Previously Allocated Buffer
  309.         fNcbFreed = TRUE;
  310.        /*
  311.         *  Now, post a async. RECEIVE again
  312.         */
  313.         if ((bRc = PostAReceive( hwndMain)) == NRC_PENDING)
  314.         {
  315.             ServerState = S_RECEIVING;
  316.             return;
  317.         }
  318.         else
  319.         {       /*
  320.                  * Some problem hanging receive. Abort Server Receives
  321.                  * Go Back to Listening
  322.                  */
  323.             if ((bRc = PostAListen( hwndMain)) == NRC_PENDING)
  324.             {
  325.                 ServerState = S_LISTENING;
  326.                 return;
  327.             }
  328.             else // else go down to debug print
  329.             {
  330.                 sprintf(szErrorBuffer, "Error upon Listen: %x", bRc);
  331.                 MessageBox ( GetActiveWindow(), szErrorBuffer , "ReceiveCmplt", MB_OK);
  332.             }
  333.         }
  334.     }
  335.     else if  ((pncbNCB->ncb_cmd_cplt == NRC_SCLOSED) ||
  336.               (pncbNCB->ncb_cmd_cplt == NRC_SABORT))
  337.     {
  338.         NcbFree ( (LPVOID) pncbNCB);      // Free the Receive NCB
  339.         NcbFree ( (LPVOID) lpServerData); // Free the Previously Allocated Buffer
  340.         fNcbFreed = TRUE;
  341.  
  342.         // Current Client hung up.  So go back to listening
  343.         if ((bRc = PostAListen( hwndMain)) == NRC_PENDING)
  344.         {
  345.             ServerState = S_LISTENING;
  346.             return;
  347.         }
  348.         else // else go down to debug print
  349.         {
  350.             sprintf(szErrorBuffer, "Error when posting Listen: %x", bRc);
  351.             MessageBox ( GetActiveWindow(), szErrorBuffer , "ReceiveCmplt", MB_OK);
  352.         }
  353.     }
  354.     else if (pncbNCB->ncb_cmd_cplt == NRC_GOODRET)
  355.     {
  356.         /*
  357.          * Ahh! We received a packet, but first check size of packet
  358.          */
  359.         ServerState = S_RECEIVED;
  360.         if ( pncbNCB->ncb_length < PACKET_SIZE)
  361.         {
  362.            NcbFree ( (LPVOID) pncbNCB);
  363.            NcbFree ( (LPVOID) lpServerData); // Free the Previously Allocated Buffer
  364.            fNcbFreed = TRUE;
  365.            /*
  366.             *  Go back to RECEIVE again
  367.             */
  368.             if ((bRc = PostAReceive( hwndMain)) == NRC_PENDING  )
  369.             {
  370.                 ServerState = S_RECEIVING;
  371.                 return;
  372.             }
  373.             else
  374.             {       /*
  375.                      * Some problem hanging receive. Abort Server Receives
  376.                      * Go Back to Listening
  377.                      */
  378.                 if ((bRc = PostAListen( hwndMain)) == NRC_PENDING)
  379.                 {
  380.                     ServerState = S_LISTENING;
  381.                     return;
  382.                 }
  383.                 else // else go down to debug print
  384.                 {
  385.                     sprintf(szErrorBuffer, "Error when posting Listen: %x", bRc);
  386.                     MessageBox ( GetActiveWindow(), szErrorBuffer , "ReceiveCmplt", MB_OK);
  387.                 }
  388.             }
  389.         }
  390.  
  391.         pacPtr = (PACKET FAR *) pncbNCB->ncb_buffer;
  392.  
  393.         // What is the command?
  394.         switch (pacPtr->bCommand)
  395.         {
  396.  
  397.             case R_GETCWD:
  398.                 // Service the command i.e. SEND  a packet
  399.                 ServerState = S_SENDING;
  400.                 // Allocate fixed memory
  401.                 lpBuffer = (LPSTR) NcbAllocBuf( (DWORD) _MAX_DIR);
  402.  
  403.                 if ((pszBuffer = getcwd (NULL, _MAX_DIR)) == NULL)
  404.                 {
  405.                     // Send  back made up directory
  406.                     lpBuffer[0] = '.';
  407.                     lpBuffer[1] = '\\';
  408.                 }
  409.                 else
  410.                 {    // Send back real path information and free memory
  411.                      // given by getcwd()
  412.  
  413.                     _fmemcpy ( lpBuffer, (LPVOID) pszBuffer, strlen(pszBuffer));
  414.                     free ( pszBuffer );
  415.                 }
  416.  
  417.                 bRc = Send (   hwndMain,                // handle to send message to
  418.                                lpBuffer,                // Data to Send
  419.                                _fstrlen(lpBuffer)+1,    // Data buffer size
  420.                                bLsnS,                   // Local Session Number
  421.                                BW_S_SEND_BACK,          // Message sent upon completion
  422.                                &enumSSendStatus         // A signal.
  423.                            );
  424.  
  425.                 NcbFree ( (LPVOID) lpBuffer);           // Release Buffer
  426.  
  427.                 if (bRc==NO_ERROR)
  428.                     break;
  429.                 else
  430.                 {
  431.                     MessageBox ( GetActiveWindow(),
  432.                                  "Error in Sending Data",
  433.                                  "GetCwd",
  434.                                   MB_OK);
  435.                     break;
  436.                  }
  437.                     The caller specifies a buffer in 'lpData' and buffer
  438.              length in 'wDataLen'. The caller must also specify
  439.              the local session number in 'bLsn' which should be
  440.              valid. The caller specifies the message (in 'iMessage')
  441.              that post routine should send to the originating
  442.              window recognized by 'hWnd'. Finally, a variable
  443.              'peSendStatus' pointer must be provided.
  444.              The pointer 'peSendStatus' allows for "sender" to be a stack based variable as _dos_findfirst
  445.                     // does not like global memory based variable
  446.  
  447.                     _fmemcpy ( (LPVOID) chFileName, pFindFirst->chFileName, FILE_LEN);
  448.                     bRc = (BYTE) _dos_findfirst ( chFileName,
  449.                                                   pFindFirst->uAttrib,
  450.                                                   &findFileInfo
  451.                                                 );
  452.                     if (bRc)
  453.                     {
  454.                         // Send  back made up information.
  455.                         findFileInfo.size    = -1;
  456.                     }
  457.  
  458.                     _fmemcpy ( (LPVOID) pFindToSend,
  459.                                (LPVOID) &findFileInfo,
  460.                                sizeof (FINDT)
  461.                              );
  462.                     bRc = Send (   hwndMain,                // handle to send message to
  463.                                    (LPSTR) pFindToSend,     // Data to Send
  464.                                    sizeof(FINDT),    // Data buffer size
  465.                                    bLsnS,                   // Local Session Number
  466.                                    BW_S_SEND_BACK,          // Message sent upon completion
  467.                                    &enumSSendStatus         // A signal.
  468.                                );
  469.  
  470.                     NcbFree ( (LPVOID) pFindToSend);           // Release Buffer
  471.  
  472.  
  473.                     if (bRc==NO_ERROR)
  474.                         break;
  475.                     else
  476.                     {
  477.                         MessageBox ( GetActiveWindow(),
  478.                                      "Error in Sending Data",
  479.                                      "Dos_Find_First",
  480.                                      MB_OK
  481.                                    );
  482.                         break;
  483.                     }
  484.             case R_FINDNEXT:
  485.                     // Service the command i.e. SEND  a packet back
  486.                     ServerState = S_SENDING;
  487.  
  488.                     pFindNext = (FINDNEXT FAR *) ( (LPSTR) pacPtr + sizeof ( BYTE));
  489.                     // Allocate fixed memory
  490.                     pFindToSend = (FINDT FAR *) NcbAllocBuf( (DWORD) sizeof (FINDT));
  491.                     if ( (pFindNext == NULL) || (pFindToSend == NULL))
  492.                         break;
  493.  
  494.                     // Copy file information onto a stack based variable as _dos_findnext
  495.                     // does not like global memory based variable
  496.  
  497.                     _fmemcpy ( (LPVOID) &findFileInfo, &(pFindNext->FileInfo), sizeof (FINDT));
  498.  
  499.                     bRc = (BYTE) _dos_findnext ( &findFileInfo );
  500.  
  501.                     if (bRc)
  502.                     {
  503.                         // Send  back made up information
  504.                         pFindToSend->size    = -1;
  505.                     }
  506.                     else
  507.                     {
  508.                         // Copy result back into global memory
  509.                         _fmemcpy ( pFindToSend, (LPVOID) &findFileInfo , sizeof (FINDT));
  510.                     }
  511.  
  512.                     bRc = Send (   hwndMain,                // handle to send message to
  513.                                    (LPSTR) pFindToSend,     // Data to Send
  514.                                    sizeof(FINDT),    // Data buffer size
  515.                                    bLsnS,                   // Local Session Number
  516.                                    BW_S_SEND_BACK,          // Message sent upon completion
  517.                                    &enumSSendStatus         // A signal.
  518.                                );
  519.  
  520.                 NcbFree ( (LPVOID) pFindToSend);           // Release Buffer
  521.  
  522.                 if (bRc==NO_ERROR)
  523.                     break;
  524.                 else
  525.                 {
  526.                     MessageBox ( GetActiveWindow(),
  527.                                  "Error in Sending Data",
  528.                                  "Dos_Find_Next",
  529.                                   MB_OK);
  530.                     break;
  531.                  }
  532.  
  533.             default:
  534.                 // Don't know what the command is
  535.                 sprintf(szErrorBuffer,
  536.                         "Error unknown command [%d]",
  537.                         pacPtr->bCommand
  538.                        );
  539.                 MessageBox(hwndMain, (LPSTR)szErrorBuffer,"Error", MB_OK);
  540.         }
  541.  
  542.  
  543.         //  Free up the Receive Packet
  544.         NcbFree ( (LPVOID) pncbNCB);
  545.         // Free up the old buffer
  546.         NcbFree ( (LPVOID) lpServerData);
  547.         fNcbFreed = TRUE;
  548.  
  549.         ServerState = S_CONNECTED;
  550.         // All Done.  Hang out a RECEIVE
  551.         if ((bRc = PostAReceive ( hwndMain)) == NRC_PENDING )
  552.         {
  553.             ServerState = S_RECEIVING;
  554.             return;
  555.         }
  556.         else
  557.         {
  558.             /*
  559.              *  Go back to LISTENing
  560.              */
  561.             if ((bRc = PostAListen( hwndMain)) == NRC_PENDING)
  562.             {
  563.                 ServerState = S_LISTENING;
  564.                 return;
  565.             }
  566.  
  567.         }
  568.     }
  569.  
  570.     // We should never come here. Show error for debugging purposes
  571.  
  572.     sprintf(szErrorBuffer,
  573.             "Error [%d] in ReceiveComplete\n Aborting \n Close Program",
  574.             pncbNCB->ncb_cmd_cplt
  575.            );
  576.     MessageBox(hwndMain, (LPSTR)szErrorBuffer,"Error", MB_OK);
  577.  
  578.     if ( fNcbFreed != TRUE)
  579.     {
  580.        // Free the NCB
  581.        NcbFree ( (LPVOID) pncbNCB);
  582.        // Free up the old buffer
  583.        NcbFree ( (LPVOID) lpServerData);
  584.     }
  585.     return;
  586. }
  587.  
  588. /****************************************************************************
  589.  
  590.     FUNCTION: PostAListen
  591.  
  592.     PURPOSE:  The function simply posts a Listen command. It
  593.               saves a pointer to posted NCB in a global variable.
  594.  
  595.  
  596. ****************************************************************************/
  597. BYTE PostAListen ( HWND  hwnd )
  598. {
  599.     BYTE  bRc;
  600.     char  chRemoteName[ NETBIOS_NAME_LENGTH + 1];
  601.  
  602.     // Listen to anyone
  603.     CopyName ( chRemoteName, "*");
  604.  
  605.     if ((bRc = Listen(hwnd,
  606.                       chServerName,
  607.                       chRemoteName,        /* Listen to anybody */
  608.                       RECEIVE_NCB_RTO,     /* Recv time out value*/
  609.                       SEND_NCB_STO,        /* Send time out value*/
  610.                       &pncbListenNCB       /* Posted Listen NCB  */
  611.                      )) != NRC_PENDING)
  612.     {
  613.         sprintf(szErrorBuffer,
  614.                 "Error posting a Listen Server [%s] Error [%x]",
  615.                 chServerName,
  616.                 bRc
  617.                );
  618.         MessageBox(hwnd, (LPSTR)szErrorBuffer,"Error", MB_OK);
  619.         return bRc;
  620.     }
  621.     return (bRc);
  622.  
  623. }
  624. /****************************************************************************
  625.  
  626.     FUNCTION: PostAReceive
  627.  
  628.     PURPOSE:  The function simply posts a Receive command. The routine
  629.               saves the pointer to data buffer allocated by Receive
  630.               routine in a global variable.
  631.  
  632. ****************************************************************************/
  633.  
  634. BYTE PostAReceive ( HWND hwnd)
  635. {
  636.     BYTE bRc;
  637.     if ((bRc =   Receive (   hwnd,    // Handle to send message to
  638.                         &lpServerData,// Pointer to Received buffer
  639.                         SERVER_RECEIVE_SIZE,       // Size of Receive buffer
  640.                         bLsnS,        // Local Session Number
  641.                         TRUE          // It is a Server
  642.                     )) != NRC_PENDING)
  643.     {
  644.         sprintf(szErrorBuffer,
  645.                 "Error posting a Receive Server %s Error [%x]",
  646.                 chServerName,
  647.                 bRc
  648.                );
  649.         MessageBox(hwnd, (LPSTR)szErrorBuffer, "Error", MB_OK);
  650.         return bRc;
  651.     }
  652.     return (bRc);
  653. }
  654.