/* ***************************************************************************+
 * ITX package (cnrg.itx) for telephony application programming.              *
 * Copyright (c) 1999  Cornell University, Ithaca NY                          *
 *                                                                            *
 * This program is free software; you can redistribute it and/or modify       *
 * it under the terms of the GNU General Public Liense as published by        *
 * the Free Software Foundation, either version 2 of the License, or (at      * 
 * your option) any later version.                                            *
 *                                                                            *
 * The ITX package 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.                                                          * 
 *                                                                            *
 * A copy of the license is distributed with this package.  Look in the docs  *
 * directory, filename GPL.                                                   *
 *                                                                            * 
 * Contact information:                                                       *
 * Donna Bergmark                                                             *
 * 484 Rhodes Hall                                                            *
 * Cornell University                                                         *
 * Ithaca, NY 14853-3801                                                      *
 * bergmark@cs.cornell.edu                                                    *
 ******************************************************************************/


// DatagramSocket.cpp: implementation of the CDatagramSocket class.
//
//////////////////////////////////////////////////////////////////////

/***************************
 * CE doesn't support Asynchronous
 * call-backs and MFC's CCeSocket
 * class has a bug in it - asychronous
 * call-backs are not enabled if the
 * socket is "accept"ed off a listening
 * socket.
 * So we implement out own asynchronous socket:
 * it starts a thread which selects
 * and calls the OnReceive method when data
 * is available
 ***************************/

#include "stdafx.h"
#include "itxcemfc.h"
#include "DatagramSocket.h"
#include "MainFrm.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDatagramSocket::CDatagramSocket(CMainFrame* pMFrame)
{
	m_pMainFrame = pMFrame;
}

CDatagramSocket::~CDatagramSocket()
{
	closesocket(m_socket);
}

BOOL CDatagramSocket::Create(int port)
{
	if((m_socket = socket(PF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
		return FALSE;
	
	struct sockaddr_in srv_addr;
	
	srv_addr.sin_port = htons((u_short) port);
	srv_addr.sin_family = PF_INET;
	srv_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

	peer_addr.sin_port = htons(1421);
	peer_addr.sin_family = PF_INET;
	peer_addr.sin_addr.S_un.S_addr = inet_addr("128.84.223.135");
	
	if (bind(m_socket, (sockaddr*) &srv_addr, sizeof(srv_addr)) == SOCKET_ERROR)
		return FALSE;

	unsigned long noblock = 1;
	ioctlsocket(m_socket, FIONBIO, &noblock);
	m_pDataThread = AfxBeginThread( DataThread, (LPVOID)this);
	if(!m_pDataThread) return FALSE;
	return TRUE;
	
}

unsigned int AFX_CDECL DataThread( LPVOID pvParams )
{
	CDatagramSocket *dsock = (CDatagramSocket*)pvParams;
	fd_set		stReadFDS;			// set of sockets to read
	int			rc;
	
	FD_ZERO (&stReadFDS);
	FD_SET  (dsock->m_socket, &stReadFDS);
	while(1) {
		rc = select (-1, &stReadFDS, NULL, NULL, NULL);
		if(rc == SOCKET_ERROR) return FALSE;
		dsock->OnReceive();
	}
}

void CDatagramSocket::OnReceive()
{
	m_pMainFrame->ReceivedData();
}

void CDatagramSocket::Send(char *buffer, int length)
{
	sendto(m_socket, buffer, length, 0, (sockaddr*)&peer_addr, sizeof(sockaddr_in));
}

void CDatagramSocket::SetPeerAddr(char *ip, int port)
{
	peer_addr.sin_port = htons(port);
	peer_addr.sin_addr.S_un.S_addr = inet_addr(ip);
}

int CDatagramSocket::GetPort()
{
	struct sockaddr_in addr;
	int length = sizeof(addr);
	getsockname(m_socket, (sockaddr*)&addr, &length);
	return ntohs(addr.sin_port);
}
