/*
 * --- GSMP-COPYRIGHT-NOTE-BEGIN ---
 * 
 * This copyright note is auto-generated by ./scripts/Create-CopyPatch.
 * Please add additional copyright information _after_ the line containing
 * the GSMP-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by
 * the ./scripts/Create-CopyPatch script. Do not edit this copyright text!
 * 
 * GSMP: voip/src/UdpClient.cc
 * General Sound Manipulation Program is Copyright (C) 2000 - 2004
 *   Valentin Ziegler and René Rebe
 * 
 * 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; version 2. A copy of the GNU General
 * Public License can be found in the file LICENSE.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT-
 * ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 * 
 * --- GSMP-COPYRIGHT-NOTE-END ---
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h> /* memset() */
#include <sys/time.h> /* select() */ 

#include <iostream>

#include "Timer.hh"

#define REMOTE_SERVER_PORT 6666
#define MAX_MSG 100

int main (int argc, char *argv[]) {
  
  int sd, rc;
  struct sockaddr_in cliAddr, remoteServAddr;
  struct hostent *h;
  char msg[MAX_MSG];
  
  /* check command line args */
  if (argc < 3) {
    std::cerr << "usage: <server> <data1> ... <dataN>" << std::endl;
    return(1);
  }

  /* get server IP address (no check if input is IP address or DNS name */
  h = gethostbyname (argv[1]);
  if (h == NULL) {
    std::cerr << "unknown host " << argv[1] << std::endl;
    return(1);
  }

  std::cerr << "sending data to " << h->h_name << " ("
	    <<  inet_ntoa(*(struct in_addr*)h->h_addr_list[0])
	    << ")" << std::endl;

  remoteServAddr.sin_family = h->h_addrtype;
  memcpy ((char*) &remoteServAddr.sin_addr.s_addr, 
	  h->h_addr_list[0], h->h_length);
  remoteServAddr.sin_port = htons (REMOTE_SERVER_PORT);

  /* socket creation */
  sd = socket (AF_INET, SOCK_DGRAM, 0);
  if (sd < 0) {
    std::cerr << "cannot open socket" << std::endl;
    return(1);
  }
  
  /* bind any port */
  cliAddr.sin_family = AF_INET;
  cliAddr.sin_addr.s_addr = htonl (INADDR_ANY);
  cliAddr.sin_port = htons (0);
  
  rc = bind (sd, (struct sockaddr *) &cliAddr, sizeof(cliAddr));
  if (rc < 0) {
    std::cerr << "cannot bind port" << std::endl;
    return(1);
  }

  /* send data */
  for (int i = 2; i < argc; ++i) {
    Utility::AutoTimer<Utility::Timer> timer ("Roundtrip time");
    
    rc = sendto(sd, argv[i], strlen (argv[i])+1, 0, 
		(struct sockaddr*) &remoteServAddr, 
		sizeof (remoteServAddr));

    if (rc < 0) {
      std::cerr << "cannot send data " << i - 1 << std::endl;
      close (sd);
      return (1);
    }
    
    std::cerr << "waiting to get data back" << std::endl;
    memset(msg, 0x0, MAX_MSG);
    
    socklen_t resplen;
    struct sockaddr_in respAddr;

    int n = recvfrom (sd, msg, MAX_MSG, 0, (struct sockaddr *) &respAddr, &resplen); 
    
    if (n < 0) {
      std::cerr << "cannot receive data" << std::endl;
      continue;
    }
    
    std::cerr << "got back: " << msg << std::endl;
  }
  
  return 0;
}
