#pragma once


namespace RLib
{

	class CUdpSocket
		:private boost::noncopyable
	{
		class CSocket;
		const boost::shared_ptr<CSocket>	m_spSocket;
	public:
		CUdpSocket(asio::io_service &ioService);
		~CUdpSocket();
		void Close();
		bool Bind(unsigned short nPort,boost::system::error_code &ec=boost::system::error_code());
		bool Connect(const std::string &sDomain,const std::string &sPort);
		bool SendTo(const boost::asio::ip::udp::endpoint &endPoint,const boost::shared_ptr<const vector<char>> &spData,boost::system::error_code &ec=boost::system::error_code());
		bool Send(const boost::shared_ptr<const vector<char>> &spData,boost::system::error_code &ec=boost::system::error_code());

		// データ受信
		// ・次の読み込み待ちにする場合には Receive(); をコールすべし。コールしない場合には何もしない。
		typedef boost::function<void (CUdpSocket &udpSocket,const boost::system::error_code &ec,const boost::asio::ip::udp::endpoint &endPointRemote,const boost::shared_ptr<const vector<char>> &spReceivedData)> FuncOnReceived;
		bool Receive(const FuncOnReceived &funcOnReceived,unsigned short nBufferSize=8192);

	public:
		static CString GetTextAddress(const asio::ip::udp::socket::endpoint_type &ep)
			{
				return CRString::Format(_T("%s:%d"),CString(ep.address().to_string().c_str()),ep.port());
			}
	};


}

//////////////////////////////////////////////////////////////////////////////////

class CUdpHolepunching 
{
	class CMain;
	CMain	&m_main;
public:
	typedef boost::function<void (const CString &s)> FuncMessage;
	CUdpHolepunching(const FuncMessage &funcMessage);
	~CUdpHolepunching();

	void Server(unsigned short nPort);
	void Client(const std::string &sDomain,const std::string &sPort);

};

