/***************************************************************************

Palm Chess Client
Copyright (C) 1999 David Barr (davidbarr@iname.com)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

****************************************************************************/

/*
 * This is based on code from Palm Ping, (c)1998 Machina Software Inc.
 */

#pragma pack(2)
#include <Common.h>
#include <System/SysAll.h>
#include <UI/UIAll.h>

#include "tcpip.h"



// Global variables required by Pilot API
Word AppNetRefnum;
long AppNetTimeout = MAXTIMEOUT;
Err errno;

// Our globals
Err error;                          // global error variable
char HostName[ MAXHOSTNAMELEN ];    // string to store host name
char IPAddress[ 16 ];               // string to store IP Address
NetHostInfoBufType HostInfoBuffer;
NetSocketAddrINType Destination;
Word Port;
NetIPAddr DestinationIPAddress;
NetServInfoBufType ServInfoBuffer;
unsigned char ReceiveBuffer[ 256 ];      // only used for echo/finger
NetSocketAddrType Sender;
Word SenderLength;

// statistics
DWord SavedNetSettings;  // to store previous settings
NetMasterPBType Stats;


int CheckForNetwork( void ) {
  Word err;
  Word ifErrs;
  //    Word settingSize = sizeof( DWord );
  //    DWord TraceNetSettings;

  if ( ( err = SysLibFind( "Net.lib", &AppNetRefnum ) ) ) {
    putstr("Net.lib not found");
    return 1;
  }

  err = NetLibOpen( AppNetRefnum, &ifErrs );
  if ( err == netErrAlreadyOpen ) {
    return 0;
  }

  if ( err || ifErrs ) {
    putstr("NetLibOpen failed");
    NetLibClose( AppNetRefnum, false );
    return 2;
  }

  return 0;
}

// lookup the host name or ip address, given a lookup name.
// The IP Address is stored in IPAddress[], and the host name in HostName[]
// Return 0 for no errors.
Word GetHost( CharPtr lookup ) {
  NetHostInfoPtr HostInfoPtr;
  NetIPAddr* temp;
  char tmpstr[64];

  // got an IP address?
  if ((Destination.addr = NetLibAddrAToIN(AppNetRefnum, lookup)) != -1) {
    putstr("AddrAToIN success");
/*      HostInfoPtr = NetLibGetHostByAddr(AppNetRefnum, */
/*  				      (BytePtr)&Destination.addr, */
/*  				      sizeof( Destination.addr), */
/*  				      netSocketAddrINET, */
/*  				      &HostInfoBuffer, */
/*  				      MAXTIMEOUT, &error ); */
/*      if ( HostInfoPtr ) { */
    if ( 1 ) {
/*        StrCopy( HostName, HostInfoBuffer.hostInfo.nameP ); */
      StrCopy( IPAddress, lookup );
    } else {
      putstr("NetLibGetHostByAddr failed");
      StrPrintF(tmpstr, "error = 0x%X\n", error);
      putstr(tmpstr);
      return 1;
    }
  } else {   // got a host name 
    HostInfoPtr = NetLibGetHostByName( AppNetRefnum,
				       lookup, &HostInfoBuffer,
				       MAXTIMEOUT,
				       &error );

    if ( HostInfoPtr ) {
      temp = (NetIPAddr*)HostInfoBuffer.hostInfo.addrListP[ 0 ];
      if ( *temp == 0 ) {
	++temp;
      }
      NetLibAddrINToA( AppNetRefnum, *temp, IPAddress );
      StrCopy( HostName, lookup );
    } else {
      putstr("couln't resolve address");
      return 1;
    }
  }

  return 0;
}


void Disconnect( NetSocketRef SocketNumber ) {
  if ( SocketNumber != 0 ) {
    NetLibSocketClose ( AppNetRefnum, SocketNumber, -1, &error );
    SocketNumber = 0;
  }
}


// create a socket and connect to name (either ip address or host name)
// and service. Return 0 if no error.
Word Connect( CharPtr name, CharPtr service, CharPtr protocol ) {
  NetSocketRef SocketNumber;
  int getservfailed=0;
  char tmpstr[64];

  // make sure any prior socket is closed
  // Disconnect();

  if ( GetHost( name ) ) {
    putstr("GetHost failed");
    return -1;
    //return ID_ErrHostNotFound;
  }

  if(!NetLibGetServByName( AppNetRefnum, service, protocol , &ServInfoBuffer,
			  MAXTIMEOUT, &error )) {
    getservfailed=1;
  }

  SocketNumber = NetLibSocketOpen( AppNetRefnum,
				   netSocketAddrINET,
				   netSocketTypeStream,
				   htons( 6 ), // ignored...
				   MAXTIMEOUT,
				   &error );

  if ( SocketNumber < 0 ) {
    putstr("NetLibSocketOpen failed");
    return -1;
    //return ID_ErrSocketOpen;
  }

  // attempt to connect socket to destination address
  bzero((char *)&Destination, sizeof( Destination ) );
  Destination.family = AF_INET;
  Destination.addr = NetLibAddrAToIN( AppNetRefnum, IPAddress );
  if(getservfailed) {
    Destination.port = htons(atoi(service));
  } else {
    Destination.port = ServInfoBuffer.servInfo.port;
  }

  if ( NetLibSocketConnect( AppNetRefnum,
			    SocketNumber,
			    (NetSocketAddrType*)&Destination,
			    sizeof( Destination ),
			    MAXTIMEOUT,
			    &error )  == -1 ) {
    StrPrintF(tmpstr, "NetLibSocketConnect failed, error = %d\n", error);
    putstr(tmpstr);
    NetLibSocketClose ( AppNetRefnum, SocketNumber, -1, &error );
    return -1;
    //return ID_ErrSocketConnect;
  }

  return SocketNumber;
}



Err SendData(NetSocketRef SocketNumber, VoidPtr data, Word length ) {
  Err serr;

  if ( !SocketNumber ) {
    return 1;
  }

  serr = NetLibSend( AppNetRefnum, SocketNumber, data, length,
		     netIOFlagDontRoute,  // flags
		     &Destination,
		     sizeof( Destination),
		     MAXTIMEOUT,
		     &error );

  if ( serr == 0 ) {
    return netErrSocketNotOpen;
  } else if ( serr == -1 ) {
    return error;
  } else {
    return 0;
  }
}


// receive data into the global ReceiveBuffer[]
Err ReceiveData( NetSocketRef SocketNumber ) {
  Err serr;
  int i;
  int middleofline=0;

  serr = NetLibReceive( AppNetRefnum,
			SocketNumber,
			ReceiveBuffer,
			sizeof( ReceiveBuffer ),
			0, // flags
			&Sender,
			&SenderLength,
			-1,
			&error );

  if ( serr == 0 ) {
    return netErrSocketNotOpen;
  } else if ( serr == -1 ) {
    return error;
  } else {
    for(i=0; i<serr; i++) {
      char c = ReceiveBuffer[i];
      if((c >= ' ') && (c <= '~')) {
	/* printf("%c", c); */
	middleofline=1;
      } else if(c == '\r') {
	// ignore CRs
      } else if(c == '\n') {
	/* printf("\n"); */
	middleofline=0;
      } else {
	if(middleofline) {
	  /* printf("\n"); */
	  middleofline=0;
	}
	/* printf("byte %d = %d\n", i, c); */
      }
    }
    /* printf("\nread %d bytes\n", serr); */
    return 0;
  }
}


CharPtr ConvertAddressToString( CharPtr string, NetIPAddr address ) {
  NetLibAddrINToA( AppNetRefnum, address, string );
  return string;
}

