/*
Class UDPClient:
	void UDPClient()
	void send()
	void receive()
	int portnumber

*/

#include "UDPClient.h"

using namespace std;
//constructor
UDPClient::UDPClient(){
}

UDPClient::~UDPClient(){
	shutdown(clientSocket, SD_BOTH);
	closesocket(clientSocket);
	WSACleanup (); 
}
bool UDPClient::startClient(char *ipAddress, int port){
	if(!initializeWinsock()) 
		cerr<<"Error initializing winsock"<<endl;
	if(!connectToServer(ipAddress, port)){
		cerr<<"Error connecting to server"<<endl;
	}
	else {
		return true;
	}
	return false;
}
//public methods
bool UDPClient::sendtoserver(char* msg){
	int len = strlen(msg);
	send(clientSocket, msg, len, 0);
	//send successful
	return true;
}
bool UDPClient::receivefromserver(){
	int retval;
	ZeroMemory(buffer, rcvbuffersize);
	retval = recv(clientSocket, buffer, rcvbuffersize, 0);
	if(retval > 0){
		return true;
	}
	else {
		retval = WSAGetLastError();
		connectionError(retval);
	}	
	return false;
}
//private methods
bool UDPClient::initializeWinsock(){
	WSADATA w;
	int error = WSAStartup(0x0202, &w);

	if (error)	{ 							// there was an error
	  return false;
	}
	if (w.wVersion != 0x0202){ 				// wrong WinSock version!
	  WSACleanup (); 						// unload ws2_32.dll
	  return false;
	}

	return true;
}

int UDPClient::connectToServer(char* ipAddress, int portno){

	portnumber = portno;
	LPHOSTENT host;
	in_addr hAddr;
	hAddr.s_addr = inet_addr(ipAddress);

	host = gethostbyaddr((const char *)&hAddr, sizeof(struct in_addr), AF_INET);
	
	cout<<"IP address: "<<ipAddress<<" port number: "<<portnumber<<endl;
	clientSocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
	// Fill a SOCKADDR_IN struct with address information
	SOCKADDR_IN serverInfo;

	serverInfo.sin_family = AF_INET;
	serverInfo.sin_addr = *((LPIN_ADDR)*host->h_addr_list);
	serverInfo.sin_port = htons(portnumber);

	// Connect to the server ( we do this so we can use send() instead of sendto()
	int retval = connect(clientSocket, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr));
	if (retval != 0) {  //error connecting to server
		retval = WSAGetLastError();
		//connectionError(retval);
		return 0;
	}
	cout<<"\tconnected..."<<endl;
	return 1;
}
void UDPClient::connectionError(int errorCode){
	switch(errorCode){
	case 10038: //WSAENOTSOCK
		cerr<<"Socket operation on nonsocket"<<endl;
		break;
	case 10050: //WSAENETDOWN
		cerr<<"Network is down"<<endl;
		break;
	case 10051: //WSAENETUNREACH
		cerr<<"Network is unreachable"<<endl;
		break;
	case 10054: //WSAECONNRESET
		cerr<<"Connection reset by peer"<<endl;
		break;
	default:
		cerr<<"error code "<<errorCode<<endl;
	}
}