braintag

公開してしまう備忘録

boost::asioで、sip messegeを送信する

boost::asioを使って、UDPの送受信をしてみる.

受信待ちは5秒でタイムアウト

本当は受信を先に動かしておかなければいけないんだろうな

#include "StdAfx.h"
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/system/error_code.hpp>

#include <Wincrypt.h>

class datagram_handler
{
	public:
	datagram_handler(io_service& ios):
		io_service_(ios),
		timer_(ios),
		socket_(ios, udp::endpoint(udp::v4(), 5060))
	{
		memset(data_,0,sizeof(data_));

		socket_.async_receive_from(
	        	boost::asio::buffer(data_, max_length), sender_endpoint_,
			boost::bind(
				&datagram_handler::handle_receive_from, this,
				boost::asio::placeholders::error,
				boost::asio::placeholders::bytes_transferred
			)
		);

		timer_.expires_from_now(boost::posix_time::seconds(5));//タイムアウト値のセット
		timer_.async_wait(boost::bind(&datagram_handler::close, this));//タイムアウトしたらclose
  	}

	void handle_receive_from(const boost::system::error_code& err,
		size_t /*length*/)
	{
		timer_.cancel();
		if (err){
			std::cerr << "Receive error: " << err.message() << "\n";
		}else{
			//ステータスコードの取得
			std::string line(data_);
			std::string statuscode;
			boost::regex reg_status("SIP/2.0 (\\d*)");
			boost::smatch result;
			if(boost::regex_search(line, result, reg_status)){//status
				statuscode = result.str(1);
			}else{
				std::cerr << "errror : status code not found.\n";
				return;
			}
			if(statuscode != "200"){
				std::cerr << "errror : status code not found.<< statuscode << "\n";
				return;
			}
			std::cout << "Successful receive\n";
		}
	}

	void close()
	{
		socket_.close();
	}

	private:
		io_service& io_service_;
		deadline_timer timer_;
		udp::socket socket_;
		udp::endpoint sender_endpoint_;
		enum { max_length = 512 };
		char data_[max_length];
};
std::string sjis2utf8(const std::string &sjisstr)
{
	//ShiftJIS  → UFT8 
	std::wstring wstr = ConvertMultiToWide(sjisstr); //UTF16に変換
	std::string strUtf8 = ConvertWideToMulti(wstr,CP_UTF8); //CP_UTF8に変換
	return strUtf8;
}
std::string MakeRandom()
{
	HCRYPTPROV hProv;
	BYTE buf[5];
	int i;

	CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0);

	CryptGenRandom(hProv, sizeof(buf), buf);

	 std::string callid;
	 for(i=0;i<sizeof(buf);i++){
		callid += boost::lexical_cast<std::string>(static_cast<int>(buf[i]));
		if(i != sizeof(buf)-1){
			callid += '-';
		}
	 }
	CryptReleaseContext(hProv, 0);
	return callid;
}
void handle_send_to(const boost::system::error_code& err)
{
	if (err){
		std::cerr << "Send error: " << err.message() << "\n";
	}

}
int main(){
	try{
		std::string _s_ip("192.168.1.1");//SIPサーバのアドレス
		std::string _l_ip("192.168.1.100");//自分のIPアドレス gethostname+gethostbynameで取得
		std::string _l_num("3000");//自分の番号
		std::string _s_num("3001");//相手の番号
		std::string msg("こんにちは");//送信メッセージ
	

		boost::asio::io_service io_service;
		udp::socket s(io_service, udp::endpoint(udp::v4(), 0));

		udp::resolver resolver(io_service);
		udp::resolver::query query(udp::v4(),_s_ip, "5060");//SIPポート
		udp::resolver::iterator iterator = resolver.resolve(query);

		std::string utf8message=sjis2utf8(msg.c_str());//utf-8に変換しておく

		using namespace std;
		std::string sendmessege="MESSAGE sip:";
		sendmessege+= num;
		sendmessege+= "@";
		sendmessege+= _s_ip;
		sendmessege+= ":15060 SIP/2.0\r\n";
		sendmessege+= "Via: SIP/2.0/UDP ";
		sendmessege+= _l_ip;
		sendmessege+= ":5060;branch=z9hG4bK";
		sendmessege+= MakeRandom();//ランダム値生成
		sendmessege+= "\r\n";
		sendmessege+= "From: <sip:";
		sendmessege+= _l_num;
		sendmessege+= "@";
		sendmessege+= _s_ip;
		sendmessege+= ":5060>;tag=da3676\r\n";
		sendmessege+= "To: <sip:";
		sendmessege+= num;
		sendmessege+= "@";
		sendmessege+= _s_ip;
		sendmessege+= ":5060>\r\n";
		sendmessege+= "Call-ID: ";
		sendmessege+= MakeRandom();
		sendmessege+= "@";
		sendmessege+= _l_ip;
		sendmessege+= "\r\n";
		sendmessege+= "CSeq: 1 MESSAGE\r\n";
		sendmessege+= "Content-Type: text/plain; charset=utf8\r\n";
		sendmessege+= "Max-forwards: 69\r\nContent-Length: ";
		sendmessege+= boost::lexical_cast<string>(utf8message.length());
		sendmessege+="\r\n\r\n";
		sendmessege+=utf8message;

		size_t request_length = sendmessege.length();//strlen(request);

		//SIP Message 送信
		s.async_send_to(
			boost::asio::buffer(sendmessege, request_length), *iterator,
			boost::bind(
				&handle_send_to,
	       			boost::asio::placeholders::error
			)
		);
/
		//応答を受信
		datagram_handler dh(io_service);

		//実行
		io_service.run();

		s.close();


	}catch (std::exception& e){
		std::cerr << "Exception: " << e.what() << "\n";
	}
}