/* GetURL
Retrieves a html page from a web server
This version uses a QProtocolStopMarkerHook with functionality according to alternative 2.
Entire lines of data are returned to the client. All data comes as one or more QMessages
with qm_ID=0.

Written by Håkan Parting <hakan@parting.nu>
2000-08-05
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <dos/dos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>

#include <clib/AMarquee_protos.h>

#include <pragmas/AMarquee_pragmas.h>
/* #define ASYNC_CONNECT */

struct Library * AMarqueeBase = NULL;
struct QSession * session     = NULL;

/* New in version 51. Use a hook */
__regargs ULONG HTMLProtocolStopMarkerHookFunc(__A2 struct QSession *session, __A1 struct QProtocolStopMarkerMessage *msg); 
static const struct Hook HTMLProtocolStopMarkerHook = { { NULL,NULL },(void *)HTMLProtocolStopMarkerHookFunc,NULL,NULL };

/* New in version 50. Return error code in a variable */
/* Limit the buffer to 100 bytes so our hook is used */
/* Use a hook that make sure that only entire lines are sent to the client */
/* We want to receive the last bytes of data even though the hook didn't recognize a line end */
LONG errid=0;
struct TagItem tags[]={QSESSION_ERRORCODEPTR,(ULONG)&errid,
QRAWSESSION_MAXBUFFERSIZE,100,
QRAWSESSION_PROTOCOLSTOPHOOK,(ULONG)&HTMLProtocolStopMarkerHook,
QRAWSESSION_RECEIVE_EXCEEDING_DATA,TRUE,
TAG_DONE};

void CleanExit(void)
{
   printf("\nCleaning up...\n");
   if (session)      QFreeSession(session);        /* This MUST be done before we close the library! */
   if (AMarqueeBase) CloseLibrary(AMarqueeBase);  
   printf("All done.\n");
}

/* Main program */
int main(int argc, char ** argv)
{
   char * connectTo;
   int port;
   char *connectStr="";
   BOOL terminate=FALSE;
    
   printf("Usage Note:  GetURL [url=localhost] [port=80]\n");  
   printf("e.g. GetURL \"ACS.hostile.cx\" port=80\n");

   atexit(CleanExit);
  
   connectTo = (argc>1) ? argv[1] : "localhost";
   port      = (argc>2) ? atoi(argv[2]) : 80;

   if ((AMarqueeBase = OpenLibrary("amarquee.library",51L)) == NULL)
   {
      printf("Couldn't open amarquee.library v51!\n");
      exit(RETURN_ERROR);
   }
   printf("Connecting to %s:%i\n",connectTo, port);

   #ifdef ASYNC_CONNECT
   if ((session = QNewSocketSessionAsync(connectTo, port,tags)) == NULL)
   {
      printf("Couldn't connect to server %s:%i\nError: %s\n",connectTo, port, QErrorName(errid));
      exit(RETURN_WARN);
   }
   #else
   if ((session = QNewSocketSession(connectTo, port,tags)) == NULL)
   {
      printf("Couldn't connect to server %s:%i\nError: %s\n",connectTo, port, QErrorName(errid));
      exit(RETURN_WARN);
   }
   #endif

   printf("Connected to server %s:%i\n",connectTo, port);
   printf("Retrieving index.html from %s ...\n", connectTo);

   connectStr="GET / HTTP/1.0\n\n";
   QSendRawOp(session,connectStr,strlen(connectStr));
   QGo(session,0L); /* Send it! */

   /* Wait for messages */
   while(!terminate)
   {
      struct QMessage * qMsg;
      ULONG signals = (1L << session->qMsgPort->mp_SigBit) | (SIGBREAKF_CTRL_C);

      /* Wait for next message from the server */
      signals = Wait(signals);
    
      if (signals & (1L << session->qMsgPort->mp_SigBit))
      {
         while(qMsg = (struct QMessage *) GetMsg(session->qMsgPort))
         {
            if (qMsg->qm_Status!=QERROR_NO_ERROR) {
               // Got an error!
               if (qMsg->qm_Status==QERROR_NO_CONNECTION) {
                  terminate=TRUE;
                  printf("Connection to remote host was closed.\n");
               }
            }
            else if (qMsg->qm_ID==0 && qMsg->qm_DataLen>0) { // Data sent to us
               // Print it out
               char *buffer;
               if ((buffer=malloc(qMsg->qm_DataLen+1))) {   
                  memcpy(buffer,qMsg->qm_Data,qMsg->qm_DataLen); buffer[qMsg->qm_DataLen]=0;
                  printf("**** START PACKET ****\n%s\n**** END PACKET ****\n",buffer);
                  free(buffer);
               }
            }

            FreeQMessage(session, qMsg);
         }
      }
      if (signals & SIGBREAKF_CTRL_C) break;  /* Quit if CTRL-C pressed */
   }
   /* CleanExit() called here! */
}

/*
A hook that make sure the client only get entire lines of HTML data
*/
__regargs ULONG HTMLProtocolStopMarkerHookFunc(__A2 struct QSession *session, __A1 struct QProtocolStopMarkerMessage *msg) {
    int i;
    for (i=msg->length-1; i>=0; i--) {
        if (msg->buffer[i]==10)
            break;
    }

    return (i>=0 ? i+1 : 0);
} 

