/*

File: udpSocket.h
Author: Sean Neubert

This file is for defining an interface for sending UDP packets across a network.

Todo: 

1.) add in something for IP addressing?

2.) Allow a UDP socket to change the port number it's sending data to 
dynamically?

3.) Test sources of packets for future extension of packet objects in the context of 
hostname/IP and port...port shoudln't be an issue...

4.) 



*/

#ifndef UDP_SOCKET_H
#define UDP_SOCKET_H

/* CPPDOC_BEGIN_EXCLUDE  */

// includes
#ifdef WIN32
    #include<winsock.h>
#else

#endif

#include "packet.h"
#include "socket.h"

/* CPPDOC_END_EXCLUDE  */

/**
This class provides an abstraction for a user datagram protocol socket.  The 
entire idea behind this class is to make sending and recieving packets as easy 
as possible.
*/
class udpSocket : public virtual Socket {

public:

// constructors

/**
This creates a socket that isn't connected to anything.  You'll have to call 
resetSocket before you send or receive data, lest you wish to get a socketException.

*/
udpSocket();

/**
This is for setting up a client's connection to a remote server.  The constructor 
will setup the socket so that when this returns, the socket is ready for 
communication.  It will throw exceptions should any error occur.


*/
udpSocket(char *hostname, int port);

// deconstructors
/**
Just your usual deconstructor.  If you forget to close your socket connection, the 
deconstructor will handle it for you.  
*/
~udpSocket();

// modifiers
/**
If connected, this will close our connection.  Subsequent reads and writes to 
this socket, however, will throw exceptions if you don't reconnect first.
*/
void closeSocket();

/**
If you're currently connected, this method will disconnect you from the current 
server and will attempt to connect to the hostname and port specified here.
*/
void resetSocket(char *hostname, int port);


/**
This method is for setting a simple option: whether you wish to receive datagrams 
from a host other than your intended server.  If you set this to true, than this 
socket will accept packets from other hosts.  Otherwise, it will throw a socket 
exception if it reads a packet from a host other than the server.

*/
void setAcceptOption( bool value );

    
/**
sets the timeout in seconds for how long we should read before throwing a 
timeout exception.  Setting this does not affect the timeout in milliseconds.
*/
void setTimeout( int timeoutSeconds );

/**
sets the timeout for both seconds and milliseconds for our timeout.  If you 
set these to 0 than the socket will be a blocking socket.  In UDP, that's 
generally a bad idea, but to each their own.
*/
void setTimeout( int timeoutSeconds, int timeoutUsecs );

/**
This returns the number of seconds that we have setup for our timeout
*/
int getTimeoutSecs();

/**
This returns the number of milliseconds for our current timeout
*/
int getTimeoutUsecs();

/////////////////
// OPERATORS
/////////////////

/**
This sends a packet off to our server.  Make sure that you don't 
send this a NULL pointer, because it won't work if you do.
*/
void operator<< (packet *thePacket);

/**
This reads in a packet from the server.  If you have a timeout set, than this 
method will throw a timedoutException.  If it receives a datagram from a host 
other than the server, and you have set the acceptAll option to false, than 
this method will throw a socketException.  Keep in mind that this is a datagram 
socket, so if you pass a packet with a small buffer, you may be losing data.

*/
void operator>> (packet *thePacket);

/**
This method may throw an encoding exception.
*/
void operator>> (sendable *toGet);

/**
This method may throw a decoding exception.
*/
void operator<< (sendable *toSend);

/**
This reads in a character string.  It's that simple.  Make sure it's 
long enough.
*/
void operator>> (char *myString);

/**
This sends a string.  This is simple.  
*/
void operator<< (char *myString);

protected:

////////////
// functions
////////////
void setup( char *hostname, int port );

////////////
// fields
////////////

// SOCKET STUFF...
#ifdef WIN32
    SOCKET mySocket;
#else
    int mySocket;
#endif

// a structure for our server and incoming packets
struct sockaddr_in server, incoming;
struct hostent *hostent; // where our host is...

// the length of our address
// windows using a normal integer - UNIX typically uses an 
// unsigned integer - so we'll do that for now...
#ifdef WIN32
    int addrLen;
#else
    unsigned int addrLen;
#endif

// the hostname
char *host;
int port;

// whether to accept packets from other hosts (other than the one specified)
bool acceptAll;

// whether we are connected or not...
bool connected;

// This is for our timeout
struct timeval myTime;

/*
int timeOutSec; // number of seconds
int timeOutUsec; // number of microseconds
*/

}; // end of udpSocket class

#endif