// NetFindDppDlg.cpp : implementation file
//

#include "stdafx.h"
#include "UDpAsySk.h"
#include "NetFindDpp.h"
#include "NetFindDppDlg.h"
#include ".\NetFindDppdlg.h"

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

/////////////////////////////////////////////////////////////////////////////
// CNetFindDppDlg dialog

CNetFindDppDlg::CNetFindDppDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CNetFindDppDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CNetFindDppDlg)
	m_port = 3040;
	m_strReceive = _T("");
	m_strRemote = _T("");
	m_remoteport = 3040; //remote port doesn't have to be same to local port for UDP
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_pUDPSocket  = NULL;
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CNetFindDppDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CNetFindDppDlg)
	DDX_Text(pDX, IDC_RECEIVE, m_strReceive);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CNetFindDppDlg, CDialog)
	//{{AFX_MSG_MAP(CNetFindDppDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_NETFIND_DPP_DEVICES, OnBnClickedNetfindDppDevices)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CNetFindDppDlg message handlers

BOOL CNetFindDppDlg::OnInitDialog()
{
	CDialog::OnInitDialog();
	// Set the icon for this dialog. 
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	// seed random number generator
	srand((unsigned)time(NULL));	//Seed the random-number generator with current time
	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CNetFindDppDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CNetFindDppDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CNetFindDppDlg::SendBroadcast(BOOL NewRand)
{
	//-----------------------------------------------------------------
	// Send Broadcast Identity Request Packets
	//-----------------------------------------------------------------
	// Note: This section may be moved to a function to allow
	// multiple re-tries.

	unsigned char buff[6] = { 0,0,0,0,0xF4,0xFA };
	int dwBytes;
	
	if (NewRand) {
		do{
		
			m_rand = (rand()); // rand returns a number between 0 and 0x7FFF
		
		} while(m_rand == 0);    // make sure m_rand is not zero
	}

	buff[2] = (m_rand >> 8);
	buff[3] = (m_rand & 0x00FF);
	SOCKADDR_IN remoteAddr;
	remoteAddr.sin_family = AF_INET;
	remoteAddr.sin_port = htons(m_remoteport);
	remoteAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
	dwBytes = m_pUDPSocket->SendTo(buff, 6, (const SOCKADDR* )&remoteAddr, sizeof(remoteAddr));
	if(SOCKET_ERROR == dwBytes){
		CString str;
		str.Format("Error Code: %i.", GetLastError());			
		AfxMessageBox(str + " Unable To Send Packet. Please Check Network Connection.");
	}
}

void CNetFindDppDlg::OnCmdsend() 
{
	if (!m_pUDPSocket)
	{
		AfxMessageBox("Please create socket first.");
		return;
	}
	if (m_strRemote.GetLength() == 0)
	{
		AfxMessageBox ("Please Type the remote address to Send to");
		return;
	}
	m_pUDPSocket->m_nBytesSent = 0;
	SendBroadcast(TRUE);
	return;

}

void CNetFindDppDlg::OnCreatesk() 
{
	if (m_pUDPSocket) 
		AfxMessageBox("Socket alread created");
	else
	{
		if (m_port == 0)
		{
			AfxMessageBox ("Please enter a local port number");
			return;
		}
		if ((m_pUDPSocket = new CUdpAsySk(this)) == NULL) 
		{
			AfxMessageBox ("Failed to allocate UDP socket! Close and restart app.");
			return;
		}
		m_pUDPSocket->m_sendBuffer = "";   //for async send
		m_pUDPSocket->m_nBytesSent = 0;
		m_pUDPSocket->m_nBytesBufferSize = 0;

		if (!m_pUDPSocket->Create(m_port, SOCK_DGRAM))
		{
			wsprintf(m_szError, "Failed to create UDP socket: %d! Close and restart app.", m_pUDPSocket->GetLastError());
			delete m_pUDPSocket;
			m_pUDPSocket = NULL;
			AfxMessageBox (m_szError);
			return;
		}

		
		int rflag = 0, flag =1, len = 0;

		//SetSockOpt or GetSockOpt isn't necessary if we don't want to send or receive broadcast
		if (!m_pUDPSocket->SetSockOpt(SO_BROADCAST, &flag, sizeof(int)))
		{
			wsprintf(m_szError, "SetSockOpt failed to set SO_BROADCAST:% d", m_pUDPSocket->GetLastError());
			delete m_pUDPSocket;
			m_pUDPSocket = NULL;
			AfxMessageBox (m_szError);
		}

        len = sizeof(rflag);

		if (!m_pUDPSocket->GetSockOpt(SO_BROADCAST, &rflag, &len) && rflag == 0)
		{
			wsprintf(m_szError, "GetSockOpt failed to get SO_BROADCAST:% d", m_pUDPSocket->GetLastError());
			delete m_pUDPSocket;
			m_pUDPSocket = NULL;
			AfxMessageBox (m_szError);			
		}

	}
}

void CNetFindDppDlg::OnDestroy() 
{
	CDialog::OnDestroy();

	if (m_pUDPSocket)
	{
		m_pUDPSocket->Close();
		delete m_pUDPSocket;
	}	
}

void CNetFindDppDlg::OnClosesock() 
{
	if (m_pUDPSocket)
	{
		m_strReceive = _T("");
		m_strRemote = _T("");
		UpdateData(FALSE);
		m_pUDPSocket->Close();
		delete m_pUDPSocket;
		m_pUDPSocket = NULL;
	}	
	
}

void CNetFindDppDlg::OnBnClickedNetfindDppDevices()
{
	OnClosesock();
	m_strRemote = "255.255.255.255"; //local broadcast
	UpdateData(FALSE);
	OnCreatesk();
	OnCmdsend();
}


































