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"; } }