/* queryResp.cpp  May 2002   
   Generate response message for ?IGATE? queries */

 
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif


#define _PTHREADS

#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <netdb.h>
#include <pthread.h>

#include <fstream>
#include <iostream>
#include <strstream>
#include <iomanip>
#include <errno.h>

#include <netinet/in.h>
#include <arpa/inet.h>

using namespace std;

#include "constant.h"
#include "utils.h"
#include "aprsString.h"
#include "queryResp.h"
#include "history.h"
#include "servers.h"


char szHostIP[HOSTIPSIZE];
int queryCounter;



void queryResp(int source, const aprsString* pkt)
{  int rc;
   struct hostent *h = NULL;
   struct hostent hostinfo_d;
   char h_buf[512];
   int h_err;

   aprsString *rfpacket, *inetpkt;
   char* hostname = new char[80];
   unsigned char hip[5];
   char* cp = new char[256];
   char* cpAck = new char[256];
   memset(cp,0,256);
   memset(cpAck,0,256);
   ostrstream reply(cp,255);
   ostrstream ack(cpAck,255);
   

   for (int i=0;i<4;i++) hip[i] = 0;

   /* Get hostname and host IP */
   rc = gethostname(hostname,80);
   if (rc != 0) strcpy(hostname,"Host_Unknown");
   else {

      //Thread-Safe verison of gethostbyname() 
      h = NULL;
      rc = gethostbyname_r(hostname,
                                &hostinfo_d,
                                h_buf,
                                512,
                                &h,
                                &h_err);
     
      
           
      if ((rc == 0) && (h!= NULL)) {
         
         strncpy(hostname,h->h_name,80);            //Copy Full host name
         hostname[79] = '\0';                      //Be sure it's terminated
         strncpy((char*)hip,h->h_addr_list[0],4);   //Copy Host IP
      }

      
   }


   /*debug*/
   /*
   cout  << "Hostname: " << hostname << endl
         << "IP: " 
         << (int)hip[0] << "." 
         << (int)hip[1] << "."
         << (int)hip[2] << "."
         << (int)hip[3] 
         <<endl; 
    */    



   //cout << pkt << endl;
      
   /* Now build the query specfic packet. 
      Only "IGATE" supported at this time. */

   if (pkt->query.compare("IGATE") == 0) {

      pthread_mutex_lock(pmtxCount) ;
      queryCounter++;                   //Count this query
      pthread_mutex_unlock(pmtxCount);

      reply << szServerCall << ">" << PGVERS << ",TCPIP*:"
      << "<IGATE,"
      << "MSG_CNT="
      << msg_cnt << ","
      << "LOC_CNT="
      << localCount() << ","    /* <--  scan history lists for local items */
      << "CALL=" 
      << MyCall << ","
      << "LOCATION="
      << MyLocation << ","
      << "HOST="
      << hostname << "," 
      << "IP="
      << (int)hip[0] << "." 
      << (int)hip[1] << "." 
      << (int)hip[2] << "." 
      << (int)hip[3] << ","
      << "EMAIL="
      << MyEmail << ","
      << "VERS="
      << VERS
      << "\r\n"  
      << ends;

  
      

      switch (source) {

      case SRC_IGATE:
            inetpkt = new aprsString(cp,SRC_INTERNAL,srcBEACON);
            inetpkt->addIIPPE('I');   //Make it an Internal packet
            inetpkt->addPath(MyCall,'*');
            sendQueue.write(inetpkt); //DeQueue() deletes the *msgbuf
            break;

      case SRC_TNC:  
         rfpacket = new aprsString(cp);   // Query reply                                                 
         
         //cout << rfpacket << endl;      //debug
         tncQueue.write(rfpacket);        // queue read deletes rfpacket

         break;


      default:   if (source >= 0) {
            inetpkt = new aprsString(cp,SRC_INTERNAL,srcBEACON);
            inetpkt->addIIPPE('I');   //Make it an Internal packet
            inetpkt->addPath(MyCall,'*');
            rc = send(source,(const void*)inetpkt->c_str(),strlen(inetpkt->c_str()),0);  //Only to one user
            delete inetpkt;
         }
      }

   }
  
   delete cp;
   delete cpAck;
   delete hostname;


}


//---------------------------------------



