home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / VSCPPv8.zip / VACPP / IBMCPP / samples / TOOLKIT / OS2 / NPIPE / SVRPTHRD.C < prev    next >
C/C++ Source or Header  |  1994-11-17  |  11KB  |  351 lines

  1. /*==============================================================*\
  2.  *  Svrpthrd.c - pipe processing routine: initialization and
  3.  *               and message display threads.
  4.  *
  5.  *      Copyright 1992, IBM Corp.
  6.  *
  7.  *  DISCLAIMER OF WARRANTIES.  The following [enclosed] code is
  8.  *  sample code created by IBM Corporation. This sample code is not
  9.  *  part of any standard or IBM product and is provided to you solely
  10.  *  for  the purpose of assisting you in the development of your
  11.  *  applications.  The code is provided "AS IS", without
  12.  *  warranty of any kind.  IBM shall not be liable for any damages
  13.  *  arising out of your use of the sample code, even if they have been
  14.  *  advised of the possibility of   such damages.                                                     *
  15.  *
  16.  *
  17. \*==============================================================*/
  18.  
  19.  
  20. #define INCL_DOSPROCESS
  21. #define INCL_DOSNMPIPES
  22. #define INCL_DOSSEMAPHORES
  23. #define INCL_DOSMEMMGR
  24. #define INCL_WINMESSAGEMGR
  25. #define INCL_DOSERRORS
  26. #define INCL_DOSFILEMGR
  27.  
  28. #include <os2.h>
  29.  
  30. #include <stddef.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <stdio.h>
  34.  
  35. #include "svrpglbl.h"
  36. #include "svrpmain.h"
  37. #include "svrpxtrn.h"
  38. #include "namepipe.h"
  39.  
  40.  
  41. #define STACKSIZE    8192
  42.  
  43.  
  44. HEV    hevMsgRcvd;   /* event semaphore for displaying pipe messages */
  45. HPIPE  hpStartPipe;  /* handle to pipe through which start requests are made */
  46.  
  47.  
  48. /* setup and start threads to manage pipes */
  49. HPIPE InitThreads()
  50. {
  51.    BOOL    fSuccess=FALSE;
  52.    ULONG   ulErrorMsg=0;
  53.  
  54.    if ((BOOL)DosCreateEventSem(NULL, &hevMsgRcvd, 0L, FALSE))
  55.    {
  56.       ulErrorMsg = IDMSG_CREATE_SEM_FAILED;
  57.    }
  58.  
  59.    else if((BOOL)DosCreateNPipe(START_PIPE_NAME,
  60.                             &hpStartPipe,
  61.                             FS_SVR_STARTPIPE_OPEN_MODE,
  62.                             FS_SVR_STARTPIPE_PIPE_MODE,
  63.                             sizeof(PIPE_MSG)*3,
  64.                             sizeof(PIPE_MSG)*3,
  65.                             PIPE_TIMEOUT))
  66.    {
  67.       ulErrorMsg = IDMSG_CREATE_PIPE_FAILED;
  68.    }
  69.  
  70.    else if (0 > _beginthread(DisplayPipeMsg,
  71.                              NULL,
  72.                              STACKSIZE,
  73.                              NULL))
  74.    {
  75.       ulErrorMsg = IDMSG_CREATE_THREAD_FAILED;
  76.    }
  77.  
  78.    else if (0 > _beginthread(ConnectPlayer,
  79.                              NULL,
  80.                              STACKSIZE,
  81.                              NULL))
  82.    {
  83.       ulErrorMsg = IDMSG_CREATE_THREAD_FAILED;
  84.    }
  85.  
  86.    else
  87.    {
  88.       fSuccess = TRUE;
  89.    }
  90.  
  91.    if (!fSuccess)
  92.    {
  93.       MessageBox(hwndMain, ulErrorMsg, MB_OK | MB_ERROR, TRUE);
  94.       hpStartPipe = (HPIPE)0;                                   /* TEST CODE */
  95.    }
  96.  
  97.    return (hpStartPipe);                                        /* TEST CODE */
  98. }
  99.  
  100.  
  101. VOID ConnectPlayer(VOID *dummy)
  102. {
  103.    USHORT  usMsgType, usErrorMsg=0;
  104.    HPIPE   hpGamePipe[2];  /* buffer pipe handles */
  105.    BOOL    fExit=FALSE;
  106.    int     iPipeIndex=0;
  107.    APIRET  apirc;
  108.  
  109.    while (!fAppExit &&  /* test for end before */
  110.           !fExit &&
  111.           !(BOOL)(apirc=DosConnectNPipe(hpStartPipe)) &&  /* wait to connect next player */
  112.           !fAppExit)    /* and after waiting */
  113.    {
  114.       usMsgType = ERROR_MSG;
  115.  
  116.       if ((BOOL)DosCreateNPipe(GAME_PIPE_NAME,  /* create pipe for next player */
  117.                        &hpGamePipe[iPipeIndex],
  118.                        FS_SVR_GAMEPIPE_OPEN_MODE,
  119.                        FS_SVR_GAMEPIPE_PIPE_MODE,
  120.                        sizeof(PIPE_MSG)*3,
  121.                        sizeof(PIPE_MSG)*3,
  122.                        PIPE_TIMEOUT))
  123.       {
  124.          usErrorMsg = IDMSG_CREATE_PIPE_FAILED;
  125.       }
  126.  
  127.       else if (0 > _beginthread(GameThread,   /* begin game thread */
  128.                                 NULL,
  129.                                 STACKSIZE,
  130.                                 (VOID *)&hpGamePipe[iPipeIndex]))
  131.       {
  132.          usErrorMsg = IDMSG_CREATE_THREAD_FAILED;
  133.          DosClose(hpGamePipe[iPipeIndex]);  /* close the created pipe */
  134.       }
  135.  
  136.       else
  137.       {
  138.          usMsgType = START_MSG;
  139.       }
  140.  
  141.       /* write start message to client, if we have an error, notify him */
  142.       /* and close pipe, 'cause we could care less about him now */
  143.       if ((BOOL)Pipe_IO(SERVER, hpStartPipe, &usMsgType, &usErrorMsg, 0) &&
  144.           usMsgType != ERROR_MSG)
  145.       {
  146.          usErrorMsg = IDMSG_PIPE_WRITE_FAILED;
  147.       }
  148.  
  149.       /* read confirmation from client. if he has an error, this is how he notifies us */
  150.       else if ((BOOL)Pipe_IO(CLIENT, hpStartPipe, &usMsgType, &usErrorMsg, 0))
  151.       {
  152.          usErrorMsg = IDMSG_PIPE_READ_FAILED;
  153.       }
  154.  
  155.       else if (ERROR_MSG == usMsgType)  /* the client cannot use the game pipe */
  156.       {
  157.          /* notify the thread here.  We can write to its pipe like
  158.             we were the client and tell it of a fatal error condition. */
  159.          if (Pipe_IO(SERVER, hpGamePipe[iPipeIndex], &usMsgType, &usErrorMsg, 0))
  160.          {
  161.             /* if we cannot talk to the thread, we are in deep doo-doo, as the
  162.                next client might try to grab the same busted pipe.  Disconnect
  163.                it, hope for the best, and let the game thread do what it will */
  164.             DosDisConnectNPipe(hpGamePipe[iPipeIndex]);
  165.             DosClose(hpGamePipe[iPipeIndex]);
  166.          }
  167.       }
  168.  
  169.       else
  170.       {
  171.          iPipeIndex = 1 - iPipeIndex;  /* flip index value */
  172.       }
  173.  
  174.       if ((BOOL)DosDisConnectNPipe(hpStartPipe))  /* disconnect start pipe */
  175.       {
  176.          usErrorMsg = IDMSG_START_PIPE_ERROR;
  177.          fExit = TRUE;
  178.       }
  179.  
  180.       if ((BOOL)usErrorMsg)
  181.       {
  182.          WinPostMsg(hwndMain, WM_MSG, MPFROMLONG(usErrorMsg), MPVOID);
  183.          usErrorMsg = 0;
  184.       }
  185.    }
  186.  
  187.    /* if the connect bombed, and not because we closed the pipe on it... */
  188.    if (!fAppExit)
  189.    {
  190.       WinPostMsg(hwndMain, WM_MSG, MPFROMLONG(IDMSG_CONNECT_FAILED), MPVOID);
  191.       WinPostMsg(hwndMain, WM_COMMAND, MPFROMLONG(IDM_FILEEXIT), MPVOID);
  192.       fAppExit = TRUE;
  193.    }
  194.  
  195.    DosPostEventSem(hevMsgRcvd);  /* notify DisplayPipeMsg */
  196.    DosClose(hpGamePipe[0]);      /* close what you can in case */
  197.    DosClose(hpGamePipe[1]);      /*   the game thread can't.   */
  198.    fThrdsDead = TRUE;            /* outta here... */
  199. }
  200.  
  201.  
  202. #define  BUFFSIZE  10
  203.  
  204. /* buffer for pipe messages to be formatted and displayed */
  205. struct
  206.    {
  207.       BOOL      fServer;
  208.       ULONG     ulID;
  209.       PIPE_MSG  pmsgMsg;
  210.       CHAR      pszMsgString[MESSAGE_LEN];
  211.    }
  212.    stMsgBuff[BUFFSIZE];
  213.  
  214.  
  215. /* Write or read to given pipe and write message to display buffer.
  216.  */
  217. APIRET Pipe_IO(BOOL fServer, HPIPE hpPipe, USHORT *usType, USHORT *usData, ULONG ulID)
  218. {
  219.    static int iMsgIndex=0;
  220.    PIPE_MSG   pmsgPipeMsg;
  221.    APIRET     apiRC;
  222.    ULONG      ulCount;
  223.  
  224.    if (fServer)  /* outgoing, from the server */
  225.    {
  226.       pmsgPipeMsg.usMsgType = *usType;
  227.       pmsgPipeMsg.usMsgData = *usData;
  228.       apiRC = DosWrite(hpPipe, (VOID *)&pmsgPipeMsg, sizeof(PIPE_MSG), &ulCount);
  229.  
  230.       DosEnterCritSec();   /* the update to the message buffer should be atomic */
  231.  
  232.       stMsgBuff[iMsgIndex].fServer = fServer;
  233.       stMsgBuff[iMsgIndex].pmsgMsg.usMsgType = *usType;
  234.       stMsgBuff[iMsgIndex].pmsgMsg.usMsgData = *usData;
  235.       stMsgBuff[iMsgIndex].ulID = ulID;
  236.       iMsgIndex = (iMsgIndex < BUFFSIZE-1) ? iMsgIndex+1 : 0;
  237.  
  238.       DosExitCritSec();
  239.  
  240.       DosPostEventSem(hevMsgRcvd);  /* tell displaypipemsg() to display */
  241.    }
  242.  
  243.    else if(!(apiRC = DosRead(hpPipe, (VOID *)&pmsgPipeMsg, sizeof(PIPE_MSG), &ulCount))
  244.            && ulCount > 0)
  245.    {
  246.       *usType = pmsgPipeMsg.usMsgType;
  247.       *usData = pmsgPipeMsg.usMsgData;
  248.  
  249.       DosEnterCritSec();
  250.  
  251.       stMsgBuff[iMsgIndex].fServer = fServer;
  252.       stMsgBuff[iMsgIndex].pmsgMsg.usMsgType = *usType;
  253.       stMsgBuff[iMsgIndex].pmsgMsg.usMsgData = *usData;
  254.       stMsgBuff[iMsgIndex].ulID = ulID;
  255.       iMsgIndex = (iMsgIndex < BUFFSIZE-1) ? iMsgIndex+1 : 0;
  256.  
  257.       DosExitCritSec();
  258.  
  259.       DosPostEventSem(hevMsgRcvd);
  260.    }
  261.  
  262.    /* DosRead returns an error code of 0 and 0 bytes read with a broken pipe */
  263.  
  264.    else if (0 == ulCount)
  265.    {
  266.       apiRC = ERROR_BROKEN_PIPE;
  267.    }
  268.  
  269.    return(apiRC);
  270. }
  271.  
  272.  
  273. VOID DisplayPipeMsg(VOID *dummy)
  274. {
  275.    ULONG       ulPosts;
  276.    static int  iMsgIndex=0;
  277.    CHAR        *pszSender, *pszType;
  278.  
  279.    while (!DosWaitEventSem(hevMsgRcvd, SEM_INDEFINITE_WAIT) &&
  280.           !fAppExit)
  281.    {
  282.       DosResetEventSem(hevMsgRcvd, &ulPosts);
  283.       while (ulPosts-- > 0)              /* format all of the messages posted */
  284.       {
  285.          /* format pipe message here */
  286.          if (stMsgBuff[iMsgIndex].fServer)
  287.          {
  288.             pszSender = "SERVER";
  289.          }
  290.  
  291.          else
  292.          {
  293.             pszSender = "CLIENT";
  294.          }
  295.  
  296.          switch (stMsgBuff[iMsgIndex].pmsgMsg.usMsgType)
  297.          {
  298.             case START_MSG:
  299.                pszType = START_MSG_TEXT;
  300.                break;
  301.  
  302.             case CLIENT_MOVE:
  303.                pszType = CLIENT_MOVE_TEXT;
  304.                break;
  305.  
  306.             case YOU_FIRST:
  307.                pszType = YOU_FIRST_TEXT;
  308.                break;
  309.  
  310.             case ERROR_MSG:
  311.                pszType = ERROR_MSG_TEXT;
  312.                break;
  313.  
  314.             case CLIENT_QUIT:
  315.                pszType = CLIENT_QUIT_TEXT;
  316.                break;
  317.  
  318.             case WIN_CLIENT:
  319.                pszType = WIN_CLIENT_TEXT;
  320.                break;
  321.  
  322.             case WIN_SERVER:
  323.                pszType = WIN_SERVER_TEXT;
  324.                break;
  325.  
  326.             case SERVER_MOVE:
  327.                pszType = SERVER_MOVE_TEXT;
  328.                break;
  329.  
  330.             case WIN_DRAW:
  331.                pszType = WIN_DRAW_TEXT;
  332.                break;
  333.  
  334.             default:
  335.                pszType = "UNKNOWN";
  336.          }
  337.  
  338.          /* format the text of the message */
  339.          sprintf(stMsgBuff[iMsgIndex].pszMsgString, "Thread %03u, %s Message: %s: %u", stMsgBuff[iMsgIndex].ulID, pszSender, pszType, stMsgBuff[iMsgIndex].pmsgMsg.usMsgData);
  340.  
  341.          /* post pointer to said message to the PM thread */
  342.          WinPostMsg(hwndMain, WM_PIPEMSG, MPFROMP(stMsgBuff[iMsgIndex].pszMsgString), MPVOID);
  343.  
  344.          /* increment circular list index */
  345.          iMsgIndex = (iMsgIndex < BUFFSIZE-1) ? iMsgIndex+1 : 0;
  346.       }
  347.    }
  348.  
  349.    DosCloseEventSem(hevMsgRcvd);
  350. }
  351.