// serwevw.cpp : implementation of the CSerwebView class
//

#include "stdafx.h"
#include "serweb.h"

#include "serwedoc.h"
#include "serwevw.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CSerwebView

IMPLEMENT_DYNCREATE(CSerwebView, CScrollView)

BEGIN_MESSAGE_MAP(CSerwebView, CScrollView)
	//{{AFX_MSG_MAP(CSerwebView)
	  ON_MESSAGE(CLIENT_MSG, OnWWWClientMsg) 
  	  ON_MESSAGE(INCOMING_MSG, OnWWWServerMsg) 
	ON_COMMAND(ID_PERIOD_OK, OnPeriodOk)
	ON_COMMAND(ID_SERVER_INACT, OnServerInact)
	ON_COMMAND(ID_UPDATE_STAT, OnUpdateStat)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSerwebView construction/destruction

CSerwebView::CSerwebView()
{
	// TODO: add construction code here
}

CSerwebView::~CSerwebView()
{
  int Loop;

    // Close the listening server first ....                      
    if (WWWServer != INVALID_SOCKET)
      if (closesocket(WWWServer) == SOCKET_ERROR)
        {
           sprintf(buf, "Windows Socket error %d:  Couldn't close the server socket.", WSAGetLastError());
	       MessageBox( buf,  AfxGetAppName(), MB_OK);
        }
                                            
    // Close any outstanding connections .....                                        
    for (Loop = 0; Loop < HowManyClients; Loop++)
       if (WWWConv[Loop].State != SOCK_FREE)
         if (closesocket(WWWConv[Loop].CliSock) == SOCKET_ERROR)
           {
              sprintf(buf, "Windows Socket error %d:  Couldn't close a client socket.", WSAGetLastError());
	          MessageBox( buf,  AfxGetAppName(), MB_OK);
           } 
           
    // Kill the timer ...
    KillTimer(IdEv);
    
}    

//////////////////////////////////////////////////////////////////////////////
void CSerwebView::OnInitialUpdate()
{                           
    int err, Loop;
    CClientDC dc(this);
    TEXTMETRIC tm;
    CRect MyWin;
 
  CWnd* pParent = GetParent();
  CMenu* pMenu = pParent->GetMenu();                   
       
    // ************ Set the proper options here ......
    
    WWWPort = AfxGetApp()->GetProfileInt("SERWEB", "PortNumber",80);
    HowManyClients = AfxGetApp()->GetProfileInt("SERWEB", "HowManyClients",5);
    if (HowManyClients > MAX_CLIENTS)     // Can't have more than we have storage for .....
      {
         HowManyClients = MAX_CLIENTS;
         PrintSt("  Requested more than 10 clients.  Resetting to 10.\n");
      }
    if (AfxGetApp()->GetProfileInt("SERWEB", "ClosedServer",0) == 1)
      pMenu->CheckMenuItem(ID_SERVER_INACT, MF_CHECKED);
    else
      pMenu->CheckMenuItem(ID_SERVER_INACT, MF_UNCHECKED);

    if (AfxGetApp()->GetProfileInt("SERWEB", "PeriodAllowed",1) == 0)
      pMenu->CheckMenuItem(ID_PERIOD_OK, MF_CHECKED);
    else
      pMenu->CheckMenuItem(ID_PERIOD_OK, MF_UNCHECKED);

    if (AfxGetApp()->GetProfileInt("SERWEB", "PrintOut",1) == 1)
      pMenu->CheckMenuItem(ID_UPDATE_STAT, MF_CHECKED);
    else
      pMenu->CheckMenuItem(ID_UPDATE_STAT, MF_UNCHECKED);

    SendDir          = AfxGetApp()->GetProfileString("SERWEB", "SendDir","C:\\SERWEB");
    FileNotExistMsg  = AfxGetApp()->GetProfileString("SERWEB", "FileNotExistMsg","C:\\SERWEB\\nofile.htm");
    ClosedServerMsg  = AfxGetApp()->GetProfileString("SERWEB", "ClosedServerMsg","C:\\SERWEB\\closed.htm");
    PeriodAllowedMsg = AfxGetApp()->GetProfileString("SERWEB", "PeriodAllowedMsg","C:\\SERWEB\\period.htm");

    // SIze the frame window to a normal size and set the scrollers ....
    
    dc.GetTextMetrics(&tm);                        
    SetScrollSizes( MM_TEXT, CSize(0,0), CSize(0,(MAX_LINES*tm.tmHeight)), CSize(0, tm.tmHeight)); 
    
    GetWindowRect( MyWin );
    GetParentFrame()->MoveWindow( MyWin.left, MyWin.top, (COLUMN_MAX*tm.tmAveCharWidth), (24*tm.tmHeight), FALSE);


    // Initialize WinSocket code here ......
    
    WWWServer = INVALID_SOCKET;              // The server is not connected yet ....

     // and set all sockets structures to not used ....

     for (Loop = 0; Loop < HowManyClients; Loop++)
       WWWConv[Loop].State = SOCK_FREE;

    PrintSt("\n");
    WWWServer = socket(AF_INET, SOCK_STREAM, 0);
    if (WWWServer == INVALID_SOCKET)
      {
         sprintf(buf, "Windows Socket error %d:  Couldnot create server socket.", WSAGetLastError());
         PrintSt("  Initialization incorrect \n\n  Please correct the problem and restart.\n");
	     MessageBox( buf,  AfxGetAppName(), MB_OK);
	     return;   
       }
     
    srv_addr.sin_family = AF_INET;
    srv_addr.sin_addr.s_addr = INADDR_ANY;   
    srv_addr.sin_port = htons(WWWPort);
    
    if (bind(WWWServer, (LPSOCKADDR)&srv_addr, sizeof(srv_addr)) == SOCKET_ERROR)
       {
         sprintf(buf, "Windows Socket error %d:  Couldn't bind the server socket.", WSAGetLastError());
         PrintSt("  Initialization incorrect \n\n  Please correct the problem and restart.\n");
	     MessageBox( buf,  AfxGetAppName(), MB_OK);
	     return;   
       }
         
      err = WSAAsyncSelect(WWWServer, m_hWnd, INCOMING_MSG, FD_ACCEPT);
      if (err == SOCKET_ERROR) 
       {
         sprintf(buf, "Windows Socket error %d:  WSAAsyncSelect code did not work for the server.", WSAGetLastError());
         PrintSt("  Initialization incorrect \n\n  Please correct the problem and restart.\n");
	     MessageBox( buf,  AfxGetAppName(), MB_OK);
	     return;   
       }

    if (listen(WWWServer,2) == SOCKET_ERROR)
      {
         sprintf(buf, "Windows Socket error %d:  Couldn't setup the server to listen for clients.", WSAGetLastError());
         PrintSt("  Initialization incorrect \n\n  Please correct the problem and restart.\n");
	     MessageBox( buf,  AfxGetAppName(), MB_OK);
	     return;   
       }
     
     
     PrintSt("  Initialization was OK \n  Waiting for connections\n");  
     SetTimer(IdEv, TIME_TO_CHECK, NULL);
return;
}

/////////////////////////////////////////////////////////////////////////////
// CSerwebView drawing

void CSerwebView::OnDraw(CDC* pDC)
{
	CSerwebDoc* pDoc = GetDocument();
    TEXTMETRIC tm;
    int yval;
    CSize PositionHold;
    
    pDC->GetTextMetrics(&tm);
    yval = 0;
    for (int loop_index = 0; loop_index <= pDoc->line_number; loop_index++)
      {
        pDC->TextOut(0,yval,pDoc->data_string[loop_index], pDoc->data_string[loop_index].GetLength());
        yval += tm.tmHeight;
      }
     
/*     // Display cursor    ..........
     PositionHold = pDC->GetTextExtent(pDoc->data_string[pDoc->line_number], (int) pDoc->column_number);
     pDC->BitBlt((PositionHold.cx+2), (int) pDoc->line_number * tm.tmHeight, tm.tmAveCharWidth, tm.tmHeight, NULL, 0, 0, DSTINVERT);
*/
     SetScrollSizes( MM_TEXT, CSize(0, ((int) pDoc->line_number+1) * tm.tmHeight));
}



/////////////////////////////////////////////////////////////////////////////
// CSerwebView diagnostics

#ifdef _DEBUG
void CSerwebView::AssertValid() const
{
	CView::AssertValid();
}

void CSerwebView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CSerwebDoc* CSerwebView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSerwebDoc)));
	return (CSerwebDoc*) m_pDocument;
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CSerwebView message handlers
 
void CSerwebView::PrintChar(char nChar, char OutputIt)
{
  CSerwebDoc* pDoc = GetDocument();                 
  CClientDC dc(this);
  TEXTMETRIC tm;
  CPoint Position, Origin;
  CSize PositionHold;
  CRect MyWindowSize;
  CWnd* pParent = GetParent();
  CMenu* pMenu = pParent->GetMenu();                   
       
   // No need to update the stuff .............................
   if (pMenu->GetMenuState(ID_UPDATE_STAT, MF_BYCOMMAND) == MF_UNCHECKED) 
     return;
     
  OnPrepareDC(&dc);       
  dc.GetTextMetrics(&tm);                        
/*  if (OutputIt != 'n')
   {
     PositionHold = dc.GetTextExtent(pDoc->data_string[pDoc->line_number], (int) pDoc->column_number);
     dc.BitBlt((PositionHold.cx+2), (int) pDoc->line_number * tm.tmHeight, tm.tmAveCharWidth, tm.tmHeight, NULL, 0, 0, DSTINVERT);
   }                                                                 
*/
  if (nChar =='\n')
    {  
      pDoc->column_number = 0;          // we are on the left now
      if (pDoc->line_number == (MAX_LINES-1))
        {
          for (int loop_index=0; loop_index < MAX_LINES; loop_index++)
            {
              pDoc->data_string[loop_index] = pDoc->data_string[loop_index+1];
            }
          pDoc->data_string[loop_index].Empty;
          pDoc->UpdateAllViews(this, 0L, 0);
        }
      else
        pDoc->line_number++;
      SetScrollSizes( MM_TEXT, CSize(0, ((int) pDoc->line_number+1) * tm.tmHeight));
    }
  else
    {
      if (pDoc->column_number++ >= COLUMN_MAX)
        {
           pDoc->column_number = 1;
           if (pDoc->line_number == (MAX_LINES-1))
             {
               for (int loop_index=0; loop_index < MAX_LINES; loop_index++)
                 {
                    pDoc->data_string[loop_index] = pDoc->data_string[loop_index+1];
                 }
               pDoc->data_string[loop_index].Empty;
               pDoc->UpdateAllViews(this, 0L, 0);
             }
           else
             pDoc->line_number++;
        }   
      pDoc->data_string[pDoc->line_number] += nChar;
      if (OutputIt != 'n')
        dc.TextOut(0, (int) pDoc->line_number * tm.tmHeight,
                   pDoc->data_string[pDoc->line_number],
                   pDoc->data_string[pDoc->line_number].GetLength());
                   
    }                             
    
  // Scroll so user can see the line just outputted ...........
  
  if (OutputIt != 'n')
   {
    Position = GetScrollPosition(); 
    if ((int) pDoc->line_number * tm.tmHeight < Position.y)
      {
        Position.y = (int) pDoc->line_number * tm.tmHeight;
        ScrollToPosition( Position );
      }
    else
      {
        CScrollView::GetClientRect( MyWindowSize);                            
        if ( (( (int) pDoc->line_number * tm.tmHeight) + tm.tmHeight) > MyWindowSize.bottom)
          {                
            Origin = dc.GetViewportOrg();  
            Position.x = Origin.x;
            Position.y = ((int) pDoc->line_number * tm.tmHeight) + tm.tmHeight - MyWindowSize.bottom;
            ScrollToPosition( Position );
           }
        }    

/*      // Draw the cursor now ....
      PositionHold = dc.GetTextExtent(pDoc->data_string[pDoc->line_number], (int) pDoc->column_number);
      dc.BitBlt((PositionHold.cx+2), (int) pDoc->line_number * tm.tmHeight, tm.tmAveCharWidth, tm.tmHeight, NULL, 0, 0, DSTINVERT);
*/    }
    
}
                                                        
////////////////////////////////////////////////////////////////////////////////////////
void CSerwebView::PrintSt( CString StToPrint)

{
  CSerwebDoc* pDoc = GetDocument();                 
 
  int Loop=0;  
  CWnd* pParent = GetParent();
  CMenu* pMenu = pParent->GetMenu();                   
       
   if (pMenu->GetMenuState(ID_UPDATE_STAT, MF_BYCOMMAND) == MF_UNCHECKED) 
     return;
     
   
   if (StToPrint.GetLength() == 0)
     return;
   for ( Loop = 0; Loop < (StToPrint.GetLength()-1); Loop++)
      PrintChar( StToPrint[Loop], 'n');
   PrintChar( StToPrint[Loop], 'y');
   pDoc->UpdateAllViews(NULL, 0L, 0);
}

void CSerwebView::PrintSt( char* AString)

{
  CSerwebDoc* pDoc = GetDocument();                 
 
  int Loop;  
  CWnd* pParent = GetParent();
  CMenu* pMenu = pParent->GetMenu();                   
       
   if (pMenu->GetMenuState(ID_UPDATE_STAT, MF_BYCOMMAND) == MF_UNCHECKED) 
     return;
     
   if (AString == NULL)
     return;
   for ( Loop = 0; AString[Loop+1] != NULL; Loop++)
      PrintChar( AString[Loop], 'n');
   PrintChar( AString[Loop], 'y');
   pDoc->UpdateAllViews(NULL, 0L, 0);
}

////////////////////////////////////////////////////////////////////////////////////////
void CSerwebView::OnUpdate(CView*, LPARAM, CObject*)
{                                              
  Invalidate();
}
                                                        
////////////////////////////////////////////////////////////////////////////////////////
void CSerwebView::KillConn(int SockNumber)

{             
   
   WWWConv[SockNumber].State = SOCK_FREE; 
   closesocket( WWWConv[SockNumber].CliSock );
   if (WWWConv[SockNumber].SendFile.m_hFile != (UINT)CFile::hFileNull)
      WWWConv[SockNumber].SendFile.Close();            // If there are problems, just ignore <-- Is this OK?
   PrintSt("  Connection closed.\n");
}
////////////////////////////////////////////////////////////////////////////////////////
void CSerwebView::SendBlockOfData(int SockNumber)
{           
   int err;                                   
  
   while (1==1)
    {
      if (WWWConv[SockNumber].HowManyInSendBuf == 0)
        {
          WWWConv[SockNumber].HowManyInSendBuf = WWWConv[SockNumber].SendFile.Read(WWWConv[SockNumber].SendBuf, SEND_BUF_LEN);
          WWWConv[SockNumber].OffsetToSend = 0;
        } 
        
                
     WWWConv[SockNumber].LastTime = CTime::GetCurrentTime();        // Update time of last action ..
      if (WWWConv[SockNumber].HowManyInSendBuf == 0)                                  // Lets guess that this is EOF for now.
        {
           PrintSt("  File sent OK -Terminating connection\n");
           KillConn( SockNumber);
           return;                                    // <--- ONE of 3 ways to get out
        }          
      else
        {
          err = send( WWWConv[SockNumber].CliSock, WWWConv[SockNumber].SendBuf+WWWConv[SockNumber].OffsetToSend, WWWConv[SockNumber].HowManyInSendBuf,0);    

             
          if (err == SOCKET_ERROR)
            {                    
              if (WSAGetLastError() == WSAEWOULDBLOCK)
                {         
                   #ifdef _DEBUG
                     PrintSt("  *** Can't send all of the data at once - Pausing now\n");
                   #endif
                   return;                            // <--- second way to get out ..
                } 
              else
               {         
               
                  PrintSt("  *** Error while sending to the client some data.\n");
                  KillConn( SockNumber );
                  return;                                    // <--- last of 3 ways to get out
                }
             }

          if (err != WWWConv[SockNumber].HowManyInSendBuf)
            {
              #ifdef _DEBUG
                 PrintSt("  Did not send all data\n");
              #endif
              WWWConv[SockNumber].OffsetToSend = WWWConv[SockNumber].OffsetToSend + err;
              WWWConv[SockNumber].HowManyInSendBuf = WWWConv[SockNumber].HowManyInSendBuf - err;
            }
           else
             {
               WWWConv[SockNumber].HowManyInSendBuf = 0;     // So we can get more data..
               WWWConv[SockNumber].OffsetToSend = 0;         // Not needed (TRACE IT AND SEE WHY) but JIC (Just In Case)
             }
        }
     }
}    
                                                        

////////////////////////////////////////////////////////////////////////////////////////
CString CSerwebView::GetFirstString(CString TheString, int WrdToGet)

{
   int Count, StPos,EndPos;
   
   if (TheString.GetLength() == 0)
     return CString("");
   EndPos = -1;                // Just follow the logic.  TRUST ME !
   Count = 0;
   while (Count < WrdToGet)
   {  
     StPos=EndPos+1;
     while ((StPos < TheString.GetLength()) && ((TheString[StPos]==' ') ||(TheString[StPos]=='\t'))) 
       StPos++;
     if (StPos == TheString.GetLength())
       return CString("");
     EndPos = StPos;
     while ((EndPos < TheString.GetLength()) && (TheString[EndPos]!=' ') && (TheString[EndPos]!='\t')) 
       EndPos++;
     Count++;
    }
   return TheString.Mid(StPos, (EndPos-StPos));
}
////////////////////////////////////////////////////////////////////////////////////////
void CSerwebView::ProcessRequest(int SockNumber)

{
   CString Testing;
   int Count = 1, Loop, err;
   CWnd* pParent = GetParent();
   CMenu* pMenu = pParent->GetMenu();                   
                      
   // Get the first word ......
   
   Testing = GetFirstString( WWWConv[SockNumber].InBuf, 1);
   
   if ( Testing.CompareNoCase("GET") == 0)
     {
       Testing = GetFirstString( WWWConv[SockNumber].InBuf, 2);

       // Lets ensure the slash is OK for DOS  - Just in case
       for (Loop = 0; Loop < Testing.GetLength(); Loop++)
         if (Testing[Loop] == '/')
            Testing.SetAt(Loop,'\\');
       
       if (Testing[0] != '\\')
         Testing = SendDir + CString("\\")+ Testing;
       else
         Testing = SendDir + Testing;

       // See if we are closed and send a message.
       if (pMenu->GetMenuState(ID_SERVER_INACT, MF_BYCOMMAND) == MF_CHECKED) 
         { 
           PrintSt("  Telling client server is off.\n");
           Testing = ClosedServerMsg;
          }
          
       // They want a file with .. - check to see if we allow ?
       if (pMenu->GetMenuState(ID_PERIOD_OK, MF_BYCOMMAND) == MF_UNCHECKED)
         if (Testing.Find("..") > -1)              // Found them ....
           {  
             PrintSt("  Telling server we do not allow .. on the URI.\n");
             Testing = PeriodAllowedMsg;
           }
        PrintSt("  Trying to send file - ");
        PrintSt(Testing);
        PrintSt("\n");
       
       // Lets try to open the file now ......
       if (!WWWConv[SockNumber].SendFile.Open(Testing, CFile::modeRead | CFile::typeBinary))
         {
             // We could not send the file ......
             PrintSt("  File does not exist - Sending Message\n");
             if (!WWWConv[SockNumber].SendFile.Open(FileNotExistMsg, CFile::modeRead | CFile::typeBinary))
                {
                   // DAMM, That file dows not exist either ...

                   err = send( WWWConv[SockNumber].CliSock, "HTTP/1.0 404 The file requested was not found\n",46,0);    
                   if (err == SOCKET_ERROR)
                      PrintSt("  Error while sending to the client the 404 msg.\n");
                   #ifdef _DEBUG
                     PrintSt("  *** Socket will be closed now ....\n");
                   #endif
                   
                   KillConn( SockNumber );  
                 }
               else
                 {
                    WWWConv[SockNumber].HowManyInSendBuf = 0;               // We have not sent any chars ....
                    SendBlockOfData(SockNumber);
                 }
          }
       else    
        {           
          WWWConv[SockNumber].HowManyInSendBuf = 0;               // We have not sent any chars ....
          SendBlockOfData(SockNumber);
         }
      }
  else
    {
       PrintSt("  Unrecognized method: ");
       PrintSt(WWWConv[SockNumber].InBuf);
       PrintSt("\n");
       
       err = send( WWWConv[SockNumber].CliSock, "HTTP/1.0 599 Unrecognized method request\n",41,0);    
       if (err == SOCKET_ERROR)
          PrintSt("  Error while sending to the client the 599 msg.\n");
       
       #ifdef _DEBUG
         PrintSt("  *** Socket will be closed now ....\n");
       #endif
        
       KillConn( SockNumber ); 
     }
}

////////////////////////////////////////////////////////////////////////////////////////
void CSerwebView::ProcessRead(int SockNumber)

{
 int err, RdLoop;
 u_long ulBytesToRead = 0L;
 char Buf[200];
   
   if (WWWConv[SockNumber].State != WAITING)
     {    
       #ifdef _DEBUG
          PrintSt("  *** The socket is trying to send information while we are in send mode. \n");
       #endif
       return;
      }       
   #ifdef _DEBUG   
      PrintSt("  *** I am able read from the client now \n");
   #endif
          
   ioctlsocket( WWWConv[SockNumber].CliSock, FIONREAD, &ulBytesToRead);
          
   while ((ulBytesToRead > 0L) && (WWWConv[SockNumber].State == WAITING))
      {
         // Just in case a nut desides to crash the thing ....
         if (ulBytesToRead > 199)
           ulBytesToRead = 200;                               
          
         err = recv( WWWConv[SockNumber].CliSock, Buf, (int) ulBytesToRead, 0);
    
         if (err == SOCKET_ERROR)
                {
                   PrintSt("  An error ocurred when reading from the client \n");
                   return;
                }        

              RdLoop = 0;
              while (RdLoop < err)
                if ((Buf[RdLoop] == '\n') ||(Buf[RdLoop] == '\r') ||(Buf[RdLoop] == 0x0D) || (Buf[RdLoop] == 0x0A))
                  {                                
                    WWWConv[SockNumber].State = SENDING;
                    break;
                  }
                else            
                  {
                     WWWConv[SockNumber].InBuf += Buf[RdLoop]; 
                     RdLoop++;
                  }

              ioctlsocket( WWWConv[SockNumber].CliSock, FIONREAD, &ulBytesToRead);
            }
           
        // If we received the request, lets address it .....
          
           #ifdef _DEBUG
              PrintSt("  *** Got the following so far ->");
              PrintSt(WWWConv[SockNumber].InBuf);
              PrintSt("<---\n");
           #endif
           
           if (WWWConv[SockNumber].State == SENDING)
              {
                ProcessRequest(SockNumber);

              } 


}

////////////////////////////////////////////////////////////////////////////////////////
LRESULT CSerwebView::OnWWWClientMsg(WPARAM wParam, LPARAM lParam)

{
// int err, Loop, RdLoop;
 int Loop;
 u_long ulBytesToRead = 0L;
// char Buf[200];
 
 
 if (WSAGETSELECTERROR(lParam) == 00)
   {

    // Lets get the socket that cried for help .....
    
     for (Loop = 0; Loop < HowManyClients; Loop++)
         if (WWWConv[Loop].CliSock == (SOCKET) wParam)
             break;

    // Just in case .....
     if (Loop == HowManyClients)
       {  
          #ifdef _DEBUG
             PrintSt("  *** A socket has cried but is not ours ????\n");
          #endif
          return 0L;
       }

     if (WWWConv[Loop].State == SOCK_FREE)
       {  
          #ifdef _DEBUG
             PrintSt("  *** A socket has cried but it is closed ????\n");
          #endif
          return 0L;
       }
     
     WWWConv[ Loop ].LastTime = CTime::GetCurrentTime();        // Update time of last action ..
     if (WSAGETSELECTEVENT(lParam) == FD_READ)
       {                                       
         ProcessRead( Loop );
         return 0L;     
            
       }

     if (WSAGETSELECTEVENT(lParam) == FD_WRITE)
       {      
          #ifdef _DEBUG                                 
             PrintSt("  *** I am able to write to the client now.\n");
          #endif
          if (WWWConv[Loop].State == SENDING)
            {
              SendBlockOfData(Loop);
            }
          return 0L;
       }

     if (WSAGETSELECTEVENT(lParam) == FD_CLOSE)
       {
          PrintSt("  Connection terminated by client.\n");

          KillConn( Loop );
          
	      return 0L;   
       }
   }                           
 
 return 0L;
}

////////////////////////////////////////////////////////////////////////////////////////
LRESULT CSerwebView::OnWWWServerMsg(WPARAM wParam, LPARAM lParam)

{
 WORD err;
 int Loop;                        
 SOCKADDR sad;      // Accept socket variables ......
 int len = sizeof(sad);
 SOCKET TempSock;                       
 CFile  QFile;

 
 if (WSAGETSELECTERROR(lParam) == 0)
   {
     if (WSAGETSELECTEVENT(lParam) == FD_ACCEPT)
       {
          PrintSt("  Connection has arrived\n");

          for (Loop = 0; Loop < HowManyClients; Loop++)
             if (WWWConv[Loop].State == SOCK_FREE)
               break;

          if (Loop == HowManyClients)
            {
              PrintSt("  Maximun number of incoming connections reached.\n  Notifying request to try on a few seconds.\n");
              
              TempSock = accept(WWWServer, &sad, &len);
              if (TempSock == INVALID_SOCKET)
                {
                  PrintSt("  Could not accept the temporary socket.\n");
                  return 0L;
                }

              WSAAsyncSelect(TempSock, m_hWnd, 0, 0);       // Lets go raw !!! & pray (????)
              err = send( TempSock, "HTTP/1.0 400 Unable to satisfy request now - TRY IN A FEW SECONDS !!!\n",69,0);    
              if (err == SOCKET_ERROR)
                PrintSt("  Error while sending notice to temporary socket.\n");

              closesocket( TempSock );
             
              return 0L;          // Get out ....
            }
           WWWConv[Loop].InBuf = "";
          WWWConv[Loop].State = WAITING;
          WWWConv[Loop].CliSock = accept(WWWServer, &sad, &len);
          if (WWWConv[Loop].CliSock == INVALID_SOCKET)
             {
               PrintSt("  Could not accept the incoming connection.\n");
               WWWConv[Loop].State = SOCK_FREE;
               return 0L;
             }
          err = WSAAsyncSelect(WWWConv[Loop].CliSock, m_hWnd, CLIENT_MSG, FD_READ | FD_WRITE | FD_CLOSE);
          if (err == SOCKET_ERROR) 
             {
               sprintf(buf, "  Windows Socket error %d:  WSAAsyncSelect code did not work while accepting connection\n", WSAGetLastError());
               PrintSt(buf); 
               KillConn( Loop );
               return 0L;
             } 

          
          //  Important ..   
          ProcessRead(Loop);         // <---- WHY IS THIS NEEDED ???? SOME TIMES I DON'T RECEIVE FD_READ MSG (GUS)
          
          #ifdef _DEBUG
             PrintSt("  *** Waiting for input from the client now.\n");
          #endif
         
         
         }  

    }
 
 return 0L;
}

// Menu updates below .................................................
void CSerwebView::OnPeriodOk()
{
  CWnd* pParent = GetParent();
  CMenu* pMenu = pParent->GetMenu();                   
       
   if (pMenu->GetMenuState(ID_PERIOD_OK, MF_BYCOMMAND) == MF_UNCHECKED) 
      pMenu->CheckMenuItem(ID_PERIOD_OK, MF_CHECKED);
   else
      pMenu->CheckMenuItem(ID_PERIOD_OK, MF_UNCHECKED);
}

void CSerwebView::OnServerInact()
{
  CWnd* pParent = GetParent();
  CMenu* pMenu = pParent->GetMenu();                   
       
   if (pMenu->GetMenuState(ID_SERVER_INACT, MF_BYCOMMAND) == MF_UNCHECKED) 
      pMenu->CheckMenuItem(ID_SERVER_INACT, MF_CHECKED);
   else
      pMenu->CheckMenuItem(ID_SERVER_INACT, MF_UNCHECKED);
}

void CSerwebView::OnUpdateStat()
{
  CWnd* pParent = GetParent();
  CMenu* pMenu = pParent->GetMenu();                   
       
   if (pMenu->GetMenuState(ID_UPDATE_STAT, MF_BYCOMMAND) == MF_UNCHECKED) 
      pMenu->CheckMenuItem(ID_UPDATE_STAT, MF_CHECKED);
   else
      pMenu->CheckMenuItem(ID_UPDATE_STAT, MF_UNCHECKED);
}

///////////////////////////////////////////////////////////////////////////////////////
void CSerwebView::OnTimer(UINT nIDEvent)
{
  int Loop; 
  CTimeSpan TimeDiff; 
  CTime     TheTimeNow;
    
    #ifdef _DEBUG
      PrintSt("  *** Servicing the timer now\n");
    #endif
    for (Loop = 0; Loop < HowManyClients; Loop++) 
      {
       if (WWWConv[Loop].State != SOCK_FREE)
         {
            TimeDiff = CTime::GetCurrentTime() - WWWConv[Loop].LastTime;
            #ifdef _DEBUG
               afxDump << "Time now - " << TheTimeNow << " Lats time - " << WWWConv[Loop].LastTime << " Time diff - " << TimeDiff.GetTotalMinutes() << "\n";
            #endif
            if ((int) TimeDiff.GetTotalMinutes() > INACTIVE)
              {
                 PrintSt("  Connections has not responded for the last 3 minutes.\n");
                 KillConn( Loop );                                                    
              }
         }
      } 
}
