#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

#include "shnet.h"
#include "shutil.h"

/* when did we last ping host X ? */
time_t ping_last_sent[SH_MAX_CLIENTS];
/* list of clients who haven't ponged back yet */
time_t outstanding_pings[SH_MAX_CLIENTS];

int shnet_init()
{
  /* set up data */
  memset((void *)&outstanding_pings, 0, sizeof(time_t) * SH_MAX_CLIENTS);
  return SH_SUCCESS;
}

int shnet_connect(sh_client_t *cli)
{
  struct hostent      *host;
  struct protoent     *prot;
  struct sockaddr_in   sin;
  int    s;
 
  /*
   *  sanity check - is this thing set to use the network?
   */
  if(cli->spawn_method == SH_SPAWN_NET)
  {
    dbg(DBG_ERROR, "shnet_connect(): client %d (%s) is not set up to "
                   "use setid\n",
                    cli->index, cli->hostname);
    return SH_ERR_NOTWERK;
  }
  
  memset((void *)&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;

  if((sin.sin_port = htons((u_short)cli->port)) == 0)
  {
    dbg(DBG_ERROR, "shnet_connect(): client %d (%s) has invalid port %d\n",
                   cli->index, cli->hostname, cli->port);
    return SH_ERR_NOTWERK;
  }
  
  if((host = gethostbyname(cli->hostname)) != NULL)
  {
    memcpy((void *)&sin.sin_addr, (void *)&host->h_addr, host->h_length);
  }
  else if((sin.sin_addr.s_addr = inet_addr(cli->hostname)) == INADDR_NONE)
  {
    dbg(DBG_ERROR, "shnet_connect(): can't resolve '%s'\n",
                   cli->hostname);
    return SH_ERR_NOTWERK;
  }
  
  if((prot = getprotobyname("tcp")) == NULL)
  {
    dbg(DBG_ERROR, "shnet_connect(): woo, getprotobyname() failed.  huh?\n");
    return SH_ERR_NOTWERK;
  }
  
  if((s = socket(PF_INET, SOCK_STREAM, prot->p_proto)) < 0)
  {
    dbg(DBG_ERROR, "shnet_connect(): couldn't allocate socket\n");
    return SH_ERR_NOTWERK;
  }
  
  if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
  {
    dbg(DBG_ERROR, "shnet_connect(): can't connect to %s:%d (rc=%d)\n",
                   cli->hostname, cli->port, errno);
    return SH_ERR_NOTWERK;
  }
  
  return s;
}

int shnet_close(sh_client_t *cli)
{
  /* send stop command if necessary */
  if(cli->detach == 0)
  {
    shnet_send_cmd(cli, SH_NET_CMD_KILL);
    sleep(1);  /* give it a sec to reply */
  }
   
  shutdown(cli->socket, 1);
  close(cli->socket);
  return SH_SUCCESS;
}

void shnet_idle()
{
}

int shnet_parse(sh_client_t *cli, char *line)
{
  printf("shnet_parse() got(%d): %s\n",
         cli->index, line);
  return SH_SUCCESS;
} 
 
int shnet_send_cmd(sh_client_t *cli, char *cmd)
{
  char tmp[80];
  
  strcpy (tmp, SH_NET_CMD_PREFIX);
  strncat(tmp, cmd, 80 - strlen(SH_NET_CMD_PREFIX));
  strcat (tmp, "\n");
  if(write(cli->socket, tmp, strlen(tmp)) < 0)
  {
    dbg(DBG_ERROR, "shnet_send_cmd() Couldn't write to socket\n");
    return SH_ERR_NOTWERK;
  }
  
  return SH_SUCCESS;
}


