/**
 * Harbour Inet demo server program
 *
 * Giancarlo Niccolai
 *
 * In this program, the server uses just one thread
 * to demonstrate how to use timeout sockets.
 */

PROCEDURE Main( cPort )

   LOCAL Socket, s
   LOCAL nResponse, cResponse
   LOCAL nTurn := 0, nTurn1 := 0
   LOCAL bCont := .T.

   CLS

   IF Empty( cPort )
      cPort := "2000"
   ENDIF

   hb_inetInit()

   @ 1, 15 SAY "H A R B O U R - Inet Api Server Demo"
   @ 2,  5 SAY "Contact this server using telnet or the Harbour Inet Client demo"
   @ 3,  5 SAY "Press a [KEY] to terminate the program"
   @ 5,  5 SAY "Server listening on port " + cPort + "..."
   Socket := hb_inetServer( Val( cPort ) )
   hb_inetTimeout( Socket, 500 )

   DO WHILE bCont

      @ 6, 5 SAY Space( 70 )
      @ 7, 5 SAY Space( 70 )
      @ 8, 5 SAY Space( 70 )
      @ 9, 5 SAY Space( 70 )
      @ 6, 5

      // Accepting a connection
      DO WHILE bCont
         Progress( @nTurn, 5, 39 )
         s := hb_inetAccept( Socket )
         IF hb_inetErrorCode( Socket ) == 0
            EXIT
         ENDIF
         IF Inkey() != 0
            bCont := .F.
         ENDIF
      ENDDO

      IF ! bCont
         EXIT
      ENDIF

      hb_inetTimeout( s, 500 )

      @ 6, 5 SAY "Connection from: " + hb_inetAddress( s ) + ":" + Str( hb_inetPort( s ), 5 )
      @ 7, 5 SAY "Receiving: "
      @ 8, 5

      nResponse := hb_inetSend( s, "Welcome to my server!" + hb_eol() )

      DO WHILE bCont
         // This timeout ...
         hb_inetTimeout( s, 250 )
         // ... will trigger this periodic callback,
         hb_inetPeriodCallback( s, { @Progress(), @nTurn, 6, 39 } )
         // that will be called each TIMEOUT Milliseconds.
         cResponse := hb_inetRecvLine( s, @nResponse )
         // hb_inetRecvLine won't return until the periodic callback returns .F.,
         // or the Timelimit has been reached. Timelimit is currently -1, so
         // hb_inetRecvLine will wait forever.

         DO CASE
         CASE hb_inetErrorCode( s ) == 0
            IF Lower( cResponse ) == "quit"
               bCont := .F.
            ENDIF
            @ 8, 5 SAY Space( 70 )
            @ 8, 5 SAY cResponse
            cResponse := "Count: " + Str( nResponse ) + " characters" + hb_eol()
            hb_inetSend( s, cResponse )

         CASE hb_inetErrorCode( s ) == -1
            // idle (timed out)
            Progress( @nTurn1, 7, 17 )

         OTHERWISE
            @ 7, 5 SAY "Received Error " + Str( hb_inetErrorCode( s ) ) + ": " + hb_inetErrorDesc( s )
            @ 8, 5 SAY Space( 70 )
            @ 9, 5 SAY Space( 70 )
            @ 9, 5 SAY "Press a key to continue"
            Inkey( 0 )
            EXIT

         ENDCASE

         IF Inkey() != 0
            bCont := .F.
         ENDIF
      ENDDO
   ENDDO

   hb_inetCleanup()

   RETURN

PROCEDURE Progress( nProgress, nDrow, nDcol )

   LOCAL nRow := Row(), nCol := Col()

   @ nDrow, nDcol SAY "[ ]"

   DO CASE
   CASE nProgress == 0
      @ nDrow, nDcol + 1 SAY "-"
   CASE nProgress == 1
      @ nDrow, nDcol + 1 SAY "\"
   CASE nProgress == 2
      @ nDrow, nDcol + 1 SAY "|"
   CASE nProgress == 3
      @ nDrow, nDcol + 1 SAY "/"
   ENDCASE

   nProgress++

   IF nProgress == 4
      nProgress := 0
   ENDIF

   @ nRow, nCol

   RETURN
