C++实现GB28181视频协议

      从事一年的视频开发工作和架构设计,现在想写点东西给大家分享下。

       远程访问控制视频设备有很多协议如RTSP等,但这些协议是要求设备是有明确IP的,因为它们只能完全被动接受请求。但GB28181协议就不是,它使设备主动链接平台 ,主动上线,上线后,平台可以给设备发视频请求等,实现视频的直播、回播等。这样的优势是只要平台在外网的IP段,设备找到平台后,所有设备就可以随意控制了,而设备不需要外围IP。

   程序分为好几个单元,下面分别介绍下:

  1. SipUdpChannel :主要是负责SIP消息UDP通信的类,负责接收设备发生过来的SIP消息,同时通过事件委托发给上层的SipServer,也提供了发送给设备SIP消息的方法,如:SendData等。
  2. SipServer :接受前面发送过来的SIP消息,调用解析类SipParser.实现对SIP 裸流消息的解析。它是设备和平台通信的核心入口类,是SIP消息转发中心。
  3. RtpChannel:是负责媒体数据传输的类。
  4. SipMonitor: 是负责具体某个设备会话的SIP对象。
  5. SipParser : 是负责解析和封装SIP消息的类。

代码如下:

SipParser.cpp

#include"stdafx.h"
#include
#include"SipParaser.h"
#include "String.h"
#include
using namespace std;
const string SipVersionInfo = "SIP/2.0";
const string NewLine = "\r\n";

SipParaser::SipParaser()
{

}

SipParaser::~SipParaser()
{

}

SipMessage SipParaser::ParseToSipMessage(string messageStr, bool isResponse)
{
	SipMessage sipMessage;
	vector msgArr = String::split(messageStr, " ");
	if (messageStr.find("SIP") == 0)
	{
		sipMessage.Status = (SIPResponseStatusCodesEnum)std::atoi(msgArr[1].c_str());
	}
	else
	{
		sipMessage.Method = SIPMethods::GetSIPMethodsEnum(msgArr[0]);// SIPMethods.GetMethod(messageStr.Substring(0, messageStr.IndexOf(" ")).Trim());
		sipMessage.URL = msgArr[1];
	}
	string m_CRLF = "\r\n";
	int endFistLinePosn = messageStr.find(m_CRLF);
	sipMessage.FirstLine = messageStr.substr(0, endFistLinePosn);

	string headerString = "";
	string bodyString = "";

	int endHeaderPosn = messageStr.find(m_CRLF + m_CRLF);//双倍回车换行表示头结束--廖高波
	if (endHeaderPosn == -1)
	{
		headerString = messageStr.substr(endFistLinePosn + 2, messageStr.size() - endFistLinePosn - 2);
	}
	else
	{
		headerString = messageStr.substr(endFistLinePosn + 2, endHeaderPosn - endFistLinePosn - 2);//去掉首行的数据-廖高波

		if (messageStr.size() > endHeaderPosn + 4)
		{
			bodyString = messageStr.substr(endHeaderPosn + 4);
		}
	}
	vector FromArr = String::split(headerString, m_CRLF);
	map  ValDic;
	ValDic.insert(pair("Via", &sipMessage.Via));

	ValDic.insert(pair("Via", &sipMessage.Via));
	ValDic.insert(pair("From", &sipMessage.From));
	ValDic.insert(pair("To", &sipMessage.To));
	ValDic.insert(pair("CSeq", &sipMessage.CSeq));
	ValDic.insert(pair("Contact", &sipMessage.Contact));
	ValDic.insert(pair("Expires", &sipMessage.Expires));
	ValDic.insert(pair("Max-Forwards", &sipMessage.MaxForwards));
	ValDic.insert(pair("User-Agent", &sipMessage.UserAgent));
	ValDic.insert(pair("Route", &sipMessage.Route));
	ValDic.insert(pair("Call-ID", &sipMessage.CallID));
	ValDic.insert(pair("Content-Type", &sipMessage.ContentType));
	ValDic.insert(pair("WWW-Authenticate", &sipMessage.WWWAuthenticate));
	ValDic.insert(pair("Authorization", &sipMessage.Authorization));

	for each (string  one in FromArr)
	{
		vector	oneArr = String::split(one, ":");
		map::iterator it = ValDic.find(oneArr[0]);
		if (it!= ValDic.end())
		{
			it->second->Value = one;
		}
	}

	if ((sipMessage.Expires.Value).length()>0)
	{
		int p = sipMessage.Expires.Value.find(":");
		string str = String::trim(sipMessage.Expires.Value.substr(p + 1));//少Trim()
		sipMessage.ExpiresTime = stoi(str);
	}

	if (sipMessage.From.Value.length() > 0)
	{
		//从From域解析出DeviceID和Realm
		//From: ;tag=1555746248

		if (isResponse == false)
		{
			string pat = "";//正确哦。
			regex reg1(pat);
			smatch s1;
			auto pos = sipMessage.From.Value.cbegin();
			auto end = sipMessage.From.Value.cend();

			regex_search(pos, end, s1, reg1);
			if (s1.size() >=2)
			{
				vector values = String::split(s1.str(1), "@");//可能要问题
				sipMessage.DeviceID = values[0];
				if (values.size() >= 2)
					sipMessage.Realm = values[1];
				else
					sipMessage.Realm = "0.0.0.0";
			}
		}

		int p = sipMessage.From.Value.find("tag=");
		sipMessage.FromTag = sipMessage.From.Value.substr(p + 4);
	}

	if (sipMessage.CallID.Value.length()>0)
	{
		int p = sipMessage.CallID.Value.find(":");
		string gid = String::trim(sipMessage.CallID.Value.substr(p + 1));
		sipMessage.SessionID = gid;
	}
	if (sipMessage.CSeq.Value.length()>0)
	{
		vector tmpArr = String::split(sipMessage.CSeq.Value," ");
		if (tmpArr.size() >= 3)
			sipMessage.CSeqID = stoi(tmpArr[1]);
	}

	if (sipMessage.To.Value.length() > 0)
	{
		if (isResponse == true)
		{
			string pat = "";//正确哦。
			regex reg1(pat);
			smatch s1;
			auto pos = sipMessage.To.Value.cbegin();
			auto end = sipMessage.To.Value.cend();

			regex_search(pos, end, s1, reg1);
			if (s1.size() >= 2)
			{
				vector values = String::split(s1.str(1), "@");//可能要问题
				sipMessage.DeviceID = values[0];
				if (values.size() >= 2)
					sipMessage.Realm = values[1];
				else
					sipMessage.Realm = "0.0.0.0";
			}
		}

		int p = sipMessage.To.Value.find("tag=");
		if (p >= 0)
			sipMessage.ToTag = sipMessage.To.Value.substr(p + 4);;
	}

	if (sipMessage.Via.Value.length()>0)
	{
		int p = sipMessage.Via.Value.find(":");
		if (p >=0)
			sipMessage.TopVia = String::trim(sipMessage.Via.Value.substr(p + 1));
	}
	if (sipMessage.Route.Value.length()>0)
	{
		int p = sipMessage.Route.Value.find(":");
		if (p > 0)
			sipMessage.RouteStr = String::trim(sipMessage.Route.Value.substr(p + 1));
	}
	sipMessage.BodyInfo = bodyString;
	return sipMessage;
}

string SipParaser::ParseSipResponseToStr(SipMessage sipMessage)
{
	string sbdMsg;

	if (sipMessage.Status != SIPResponseStatusCodesEnum::None)
		sbdMsg.append(SipVersionInfo + " " + std::to_string(sipMessage.Status) + " "
			+ SIPMethods::GetStatusCodesEnumName(sipMessage.Status) + "\r\n");
	else
		sbdMsg.append(sipMessage.FirstLine);
	
	sbdMsg.append(sipMessage.To.Value.length() > 0 ? sipMessage.To.Value : "");

	if (sipMessage.ToTag.length() > 0)
	{
		sbdMsg.append(";tag=" + sipMessage.ToTag + NewLine);
	}
	else
		sbdMsg.append(NewLine);

	sbdMsg.append(!sipMessage.Via.Value.empty() ? sipMessage.Via.Value + NewLine : "");
	sbdMsg.append(!sipMessage.CSeq.Value.empty() ? sipMessage.CSeq.Value + NewLine : "");
	sbdMsg.append(!sipMessage.CallID.Value.empty() ? sipMessage.CallID.Value + NewLine : "");
	sbdMsg.append(!sipMessage.MaxForwards.Value.empty() ? sipMessage.MaxForwards.Value + NewLine : "");
	sbdMsg.append(!sipMessage.Route.Value.empty() ? sipMessage.Route.Value + NewLine : "");
	sbdMsg.append(!sipMessage.From.Value.empty() ? sipMessage.From.Value + NewLine : "");
	sbdMsg.append(!sipMessage.Contact.Value.empty() ? sipMessage.Contact.Value + NewLine : "");
	sbdMsg.append(!sipMessage.UserAgent.Value.empty() ? sipMessage.UserAgent.Value + NewLine : "");
	sbdMsg.append(!sipMessage.Authorization.Value.empty() && sipMessage.Authorization.Value != "" ? sipMessage.Authorization.Value + NewLine : "");
	sbdMsg.append(!sipMessage.Expires.Value.empty() ? sipMessage.Expires.Value + NewLine : "");
	sbdMsg.append(!sipMessage.Date.empty() ? sipMessage.Date + NewLine : "");
	sbdMsg.append(!sipMessage.TimeRevise.empty() ? sipMessage.TimeRevise + NewLine : "");
	if (!sipMessage.BodyInfo.empty())
	{
		if (!String::endsWith(sipMessage.BodyInfo, NewLine))
			sbdMsg.append(NewLine);
		sbdMsg.append("Content-Length: " + to_string(sipMessage.BodyInfo.length()));
		sbdMsg.append(NewLine);
		sbdMsg.append(sipMessage.BodyInfo);
		sbdMsg.append(NewLine);
	}
	else
	{
		sbdMsg.append("Content-Length: 0");
		sbdMsg.append(NewLine);
	}
	sbdMsg.append(NewLine);
	return sbdMsg;
}

string SipParaser::ParseSIPRequestToStr(SipMessage sipMessage)
{
	string sbdMsg;
	sbdMsg.append(SIPMethods::GetSIPMethodsEnumName(sipMessage.Method) + " " + SipVersionInfo + " " + sipMessage.DeviceID + "@" + sipMessage.Realm);
	sbdMsg.append(NewLine);
	sbdMsg.append(SipVersionInfo + " " + to_string((int)sipMessage.Status) + " " + SIPMethods::GetStatusCodesEnumName(sipMessage.Status));
	sbdMsg.append(NewLine);
	sbdMsg.append(!sipMessage.To.Value.empty() ? sipMessage.To.Value + NewLine : "");
	sbdMsg.append(!sipMessage.Via.Value.empty() ? sipMessage.Via.Value + NewLine : "");
	sbdMsg.append(!sipMessage.CSeq.Value.empty() ? sipMessage.CSeq.Value + NewLine : "");
	sbdMsg.append(!sipMessage.CallID.Value.empty() ? sipMessage.CallID.Value + NewLine : "");
	sbdMsg.append(!sipMessage.MaxForwards.Value.empty() ? sipMessage.MaxForwards.Value + NewLine : "");
	sbdMsg.append(!sipMessage.Route.Value.empty() ? sipMessage.Route.Value + NewLine : "");
	sbdMsg.append(!sipMessage.From.Value.empty() ? sipMessage.From.Value + NewLine : "");
	sbdMsg.append(!sipMessage.Contact.Value.empty() ? sipMessage.Contact.Value + NewLine : "");
	sbdMsg.append(!sipMessage.UserAgent.Value.empty() ? sipMessage.UserAgent.Value + NewLine : "");
	if (!sipMessage.BodyInfo.empty())
	{
		if (!String::endsWith(sipMessage.BodyInfo, NewLine))
			sbdMsg.append(NewLine);

		sbdMsg.append("Content-Length: " +to_string( sipMessage.BodyInfo.length()));
		sbdMsg.append(NewLine);
		sbdMsg.append(NewLine);
		sbdMsg.append(sipMessage.BodyInfo);
	}
	sbdMsg.append(NewLine);
	return sbdMsg;
}
 static Authorization ParseAuthorization(string AuthString)
{
    Authorization auth;
	try
	{
		map valDic;
		valDic.insert(pair("Digestusername", &auth.Digest_username));
		valDic.insert(pair("nonce", &auth.nonce));
		valDic.insert(pair("uri", &auth.uri));
		valDic.insert(pair("response", &auth.response));
		valDic.insert(pair("opaque", &auth.opaque));
		valDic.insert(pair("algorithm", &auth.algorithm));
		valDic.insert(pair("realm", &auth.realm));

		int valPos = AuthString.find(':') + 1;
		AuthString=AuthString.substr(valPos);
		AuthString=String::replace_all(AuthString, " ", "");
		AuthString = String::replace_all(AuthString, "\"", "");
		vector  FromArr = String::split(AuthString, ",");

		for each (string  one in FromArr)
		{
			vector	oneArr = String::split(one, "=");
			map::iterator it = valDic.find(oneArr[0]);
			if (it != valDic.end())
			{
				it->second->Value = one;
			}
		}		
	}
	catch (exception ex)
	{
	}
	return auth;
}

 

SipUdpChannel

#include "stdafx.h"
#include "SipUdpChannel.h"
#include
#include
#include
#include"SipParaser.h"
#include"RTP.H"
#include
#include"SipConst.h"
#include
#include   
#include"EventBase.h"


#pragma warning(disable:4996) 
#pragma comment(lib, "WS2_32.lib")
using namespace std;

SipUdpChannel::SipUdpChannel()
{
	mtx = new std::mutex();
}

SipUdpChannel::~SipUdpChannel()
{
	if (receiveThread != nullptr)
		delete receiveThread;
	delete mtx;
	mtx = nullptr;
}
bool SipUdpChannel::Start(string ip, int port)
{
	if (InitSocket() < 0)
		return false;
	if (BindSocket(ip,  port) < 0)
		return false;
	this->IsRuning = true;
	receiveThread = new thread(&SipUdpChannel::ReceiveData, this);
	return true;
}

void SipUdpChannel::Stop()
{	
	this->IsRuning = false;
	receiveThread->join();
}

int SipUdpChannel::InitSocket()
{
	WSAData wsdata;
	if (WSAStartup(MAKEWORD(2, 2), &wsdata) != 0)
	{
		WSACleanup();
		printf("WSAStartup failured \r\n");
		return -1;
	}
	else
	{
		printf("WSAStartup OK\r\n");
	}
	return 0;
}

int SipUdpChannel::BindSocket(string ip, int port)
{
	serverSocket = socket(AF_INET, SOCK_DGRAM, 0);
	if (serverSocket == SOCKET_ERROR)
	{
		printf("sockclient create fail ! \n");
		WSACleanup();
		return(-1);
	}
	struct	sockaddr_in serverAdd;
	serverAdd.sin_family = AF_INET;
	serverAdd.sin_addr.s_addr = htonl(INADDR_ANY);
	serverAdd.sin_port = htons(port);
	serverAdd.sin_addr.S_un.S_addr = inet_addr(LocalIP);
	if (::bind(serverSocket, (SOCKADDR*)&serverAdd, sizeof(SOCKADDR)) == SOCKET_ERROR)
	{
		WSACleanup();
		printf("Bind sipudp socket Failured %d\r\n", GetLastError());
		return -1;
	}
	else {
		printf("Bind sipudp OK\r\n");
	}
	return 0;
}



void SipUdpChannel::ReceiveData()
{
	char  buffer[1472] = { 0 };
	RTP_Header rtp;
	memset(&rtp, 0, sizeof(RTP_Header));

	int len = 1472;
	while (this->IsRuning)
	{
		try
		{
			sockaddr remoteEnd;
			ZeroMemory((void*)&buffer, sizeof(buffer));
			int reccout = recvfrom(serverSocket, buffer, (1472), 0, &remoteEnd, &len);
			if (reccout <= 20)
			{
				Sleep(10);
				continue;
			}
			string  strMsg(buffer);

			sockaddr_in sin;
			memcpy(&sin, &remoteEnd, sizeof(remoteEnd));

			string  ipAdress = string(inet_ntoa(sin.sin_addr));
			USHORT  remotePort = sin.sin_port;

			cout << "recieveMsg:\r\n" << strMsg << endl;

			if (strMsg.find("SIP") == 0)
			{
				if (this->Response != nullptr)
				{
					this->Response->OnResponse(remoteEnd, ipAdress, remotePort, strMsg);
				}
			}
			else
			{
				if (this->Request != nullptr)
				{
					this->Request->OnRequest(remoteEnd, ipAdress, remotePort, strMsg);
				}
			}
		}
		catch (exception ex)
		{
			cout << "SipUdpChannel::ReceiveData发生异常" << endl;
			cout << ex.what() << endl;
		}
	}
}
void SipUdpChannel::SendData(sockaddr remoteEnd, string messsage)
{
	if (!this->IsRuning)
	{
		return;
	}
	std::lock_guard mtx_locker(*mtx);
	sendto(this->serverSocket, messsage.c_str(), messsage.size(), 0, (sockaddr *)&remoteEnd, sizeof(remoteEnd));
	cout << "sendMsg:\r\n" << messsage << endl;

}

void SipUdpChannel::SendData(sockaddr remoteEnd, SipMessage messsage)
{
	if (!this->IsRuning)
	{
		return;
	}
	string msg = SipParaser::ParseSIPRequestToStr(messsage);
	std::lock_guard mtx_locker(*mtx);
	sendto(this->serverSocket, msg.c_str(), msg.size(), 0, (sockaddr *)&remoteEnd, sizeof(remoteEnd));
	cout << "sendMsg:\r\n" << msg << endl;
}

void SipUdpChannel::SendData(sockaddr remoteEnd, char *buffer)
{
	if (!this->IsRuning)
	{
		return;
	}
	std::lock_guard mtx_locker(*mtx);
	sendto(this->serverSocket, buffer, strlen(buffer), 0, (sockaddr *)&remoteEnd, sizeof(remoteEnd));
	cout << "sendMsg:\r\n" << buffer << endl;
}


SipServer

#include
#include "stdafx.h"
#include "SipServer.h"
#include 
#include
#include "Ws2tcpip.h"
#include
#include"SipConst.h"
using namespace std;
#pragma warning(disable:4996) 
SipServer::SipServer()
{	
	sipUdpChannel = new SipUdpChannel();
	sipUdpChannel->Request = this;
	sipUdpChannel->Response = this;
	LastLoginTimeMap = new map();
	this->ReadMonitorInfo();
}


SipServer::~SipServer()
{
	this->SaveMonitorInfo();
	if (sendRtpThread != nullptr)
		delete sendRtpThread;
	
	for (vector::iterator it = EventList.begin(); it != EventList.end(); it++)
		if (NULL != *it)
		{
			delete *it;
			*it = NULL;
		}
	EventList.clear();

	map::iterator iter = SipMonitorMap.begin();
	while (iter!= SipMonitorMap.end())
	{
		iter->second->StopRealplay();
		delete iter->second;
		iter++;
	}

	SipMonitorMap.clear();
	delete sipUdpChannel;
	delete LastLoginTimeMap;
}

bool SipServer::InitSocket()
{
	WSAData wsdata;
	if (WSAStartup(MAKEWORD(2, 2), &wsdata) != 0)
	{
		printf("client WSAStartup failured \r\n");
		return FALSE;
	}
	else
	{
		printf("client WSAStartup OK\r\n");
		return true;
	}
}
void SipServer::SaveMonitorInfo()
{
	ofstream savefile;
	savefile.open("monitor.cfg", std::ofstream::out);
	

	for (const auto& kv : *LastLoginTimeMap) {
		savefile << kv.first << "!" << kv.second.toString() << endl;
	}
	savefile.close();
}
void SipServer::ReadMonitorInfo()
{
	ifstream loadFile;
	
	loadFile.open("monitor.cfg");
	if (!loadFile)
		return;

	char  buffer[300];
	while (loadFile.getline(buffer,300 ))
	{
		string oneLine = buffer;
		vector  values = String::split(oneLine, "!");
		LastLoginTimeMap->insert(pair(values[0], ec::Date::Date(values[1])));
	}
	loadFile.close();
}
bool SipServer::Start(string ip, int port)
{
	if (InitSocket() == FALSE)
		return FALSE;

	this->isRuning = true;

	sendRtpThread = new thread(&SipServer:: SendRptDataToRemoteCenter, this);
	return	sipUdpChannel->Start(ip,port);
}

bool SipServer::Stop()
{
	/*for each (TaskWorking* oneTask in this->EventList)
	{
		this->RemoveEvent(oneTask);
	}*/

	this->isRuning = FALSE;
	if (sendRtpThread != nullptr)
	{
		sendRtpThread->join();
		delete sendRtpThread;
	}
	sipUdpChannel->Stop();
	return TRUE;
}

void SipServer::OnResponse(sockaddr remoteEndPoint, string ipAdress, USHORT port, string rawMessage)
{
	SipMessage response = SipParaser::ParseToSipMessage(rawMessage, TRUE);
	vector stopedList;
	for each (TaskWorking* oneTask in EventList)
	{
		if (oneTask->IsStoped())
		{
			stopedList.push_back(oneTask);
		}
		else
			oneTask->OnResponse(response);
	}
	for each (TaskWorking* oneTask in stopedList)
	{
		this->RemoveEvent(oneTask);
	}

	SipMonitor *currentMonitor = nullptr;
	map::iterator iter= SipMonitorMap.find(response.DeviceID);
	if (iter != SipMonitorMap.end())
		currentMonitor = iter->second;
	else
		return;

	if (response.Status == SIPResponseStatusCodesEnum::OK)
	{
		string contentType = String::toLower(response.ContentType.Value);
		if (!response.ContentType.Value.empty() && String::endsWith(contentType,"application/sdp"))
		{
			currentMonitor->AckRequest(response);
			//device.CurrentMonitor.AckRequest(response);//开启媒体通道RTP channel,廖高波
			//SDP sdp = SDP.ParseSDPDescription(response.BodyInfo);
			//ack.ContentType = "SDP";
			//ack.FileSize = sdp.filesize;
		}
		else
		{
			//设备给平台回复200 OK ,Bye后会收到
			currentMonitor->Receive200OK(response);
		}
	}
	else if (response.Status == SIPResponseStatusCodesEnum::Trying)
	{
		response.Status = SIPResponseStatusCodesEnum::OK;
	//	currentMonitor->Send200_OK_SDP(response);
	}
}

void SipServer::OnRequest(sockaddr remoteEndPoint, string ipAdress, USHORT port, string rawMessage)
{
	SipMessage request = SipParaser::ParseToSipMessage(rawMessage, false);
	if (request.SessionID.empty())
	{
		request.Status = SIPResponseStatusCodesEnum::BadRequest;
		this->sipUdpChannel->SendData(remoteEndPoint, SipParaser::ParseSipResponseToStr(request));
		return;
	}

	SipMonitor *existSipMonitor = nullptr;

	map::iterator iter = SipMonitorMap.find(request.DeviceID);
	if (iter != SipMonitorMap.end())
	{
		existSipMonitor = iter->second;
	}

	if (request.Method == SIPMethodsEnum::REGISTER)
	{
		if (request.Authorization.Value.empty())
		{
			request.Status = SIPResponseStatusCodesEnum::Unauthorized;
			char  buffer[200];
			ec::Time now;
			__int64 ticks = now.getUTCFullSeconds();
			sprintf_s(buffer, 200, "WWW-Authenticate: Digest realm=\"%s\",nonce=\"%lld\"", SipDomain, ticks);
			request.Authorization.Value = buffer;
			request.ToTag = CallProperties::CreateNewTag();
			request.Contact.Value = "";
			request.MaxForwards.Value = "";
			request.UserAgent.Value = "";
			request.Via.Value = String::replace_all_distinct(request.Via.Value, "rport", "rport" + std::to_string(port) + ";received=" + ipAdress);
			string sendMsg = SipParaser::ParseSipResponseToStr(request);
			this->sipUdpChannel->SendData(remoteEndPoint, sendMsg);
		}
		else
		{
			ec::Date now;
			request.Date = "Date: " + now.toString();//test
			char buffer[200];
			sprintf_s(buffer, 200, "TimeRevise: %d4%d2%d2%d2%d2%d5", now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second());
			request.TimeRevise = buffer;
			request.Status = SIPResponseStatusCodesEnum::OK;//doRegister return
			string sendMsg = SipParaser::ParseSipResponseToStr(request);
			this->sipUdpChannel->SendData(remoteEndPoint, sendMsg);
			if (request.Status == SIPResponseStatusCodesEnum::OK)
			{
				if (existSipMonitor == nullptr)
				{
					existSipMonitor = new SipMonitor(this, this->sipUdpChannel, request.DeviceID, remoteEndPoint, ipAdress, port);
				}
				else
				{
					if (existSipMonitor->GetIpAdress() != ipAdress || existSipMonitor->GetRemotePort() != port)
					{
						SipMonitorMap.erase(request.DeviceID);
						delete	existSipMonitor;
						existSipMonitor = new SipMonitor(this, this->sipUdpChannel, request.DeviceID, remoteEndPoint, ipAdress, port);
					}
				}
				map::iterator result = LastLoginTimeMap->find(request.SessionID);
				if (result != LastLoginTimeMap->end())
				{
					result->second = ec::Date();
				}
				else
				{
					LastLoginTimeMap->insert(pair(request.DeviceID, ec::Date()));
				}
				existSipMonitor->SetRegisterTime(ec::Date::Date());
				SipMonitorMap.insert(std::pair(request.DeviceID, existSipMonitor));

				Sleep(2000);//test
				existSipMonitor->RealVideoReq();//test
			}
		}
	}
	else if (request.Method == SIPMethodsEnum::MESSAGE)
	{
		if (existSipMonitor != nullptr)
		{
			ec::Duration ts = ec::Date::Date() - existSipMonitor->LastRegisterTime;
			if (ts.valueAs(ec::Duration::Second) < 3600)
			{
				existSipMonitor->LastRegisterTime = ec::Date::Date();
			}
			else
			{
				request.Status = SIPResponseStatusCodesEnum::Unauthorized;
				this->sipUdpChannel->SendData(remoteEndPoint, SipParaser::ParseSipResponseToStr(request));
				return;
			}
			existSipMonitor->SetRegisterTime(ec::Date::Date());
			request.To.Value += ";tag=" + CallProperties::CreateNewTag();//Mesaage回复的时候,添加一个Tag就OK了,其它都一样。
			existSipMonitor->Send200_OK(request);

			map::iterator result = LastLoginTimeMap->find(request.DeviceID);
			if (result != LastLoginTimeMap->end())
			{
				result->second = ec::Date();
			}
			else
			{
				LastLoginTimeMap->insert(pair(request.DeviceID, ec::Date()));
			}
		}
		else
		{
			map::iterator result = LastLoginTimeMap->find(request.DeviceID);
			if (result != LastLoginTimeMap->end())
			{
				ec::Duration ts = ec::Date::Date() - result->second;
			//	if (ts.valueAs(ec::Duration::Second) < 3600) test先去掉
				{
					existSipMonitor = new SipMonitor(this, this->sipUdpChannel, request.DeviceID, remoteEndPoint, ipAdress, port);
					existSipMonitor->SetRegisterTime(ec::Date::Date());
					SipMonitorMap.insert(std::pair(request.DeviceID, existSipMonitor));
					result->second = ec::Date::Date();
					existSipMonitor->Send200_OK(request);
					existSipMonitor->RealVideoReq();//test
					cout << " 已发送视频请求" << endl;
				}
			}
		}
	}
	else if (request.Method == SIPMethodsEnum::BYE)
	{
		if (existSipMonitor != nullptr)
		{
			//	device.IsOnline = true;//公有消息,全部发布
			//	device.LastOnline = DateTime.Now;
			existSipMonitor->Send200_OK(request);
		}
	}
}

void SipServer::AddEvent(TaskWorking *event)
{
	this->EventList.push_back(event);
}
void SipServer::RemoveEvent(TaskWorking*event)
{
	vector::iterator it = find(EventList.begin(), EventList.end(), event);
	if (it != EventList.end())
	{
		EventList.erase(it);
		if (NULL != *it)
		{
			delete *it;
			*it = NULL;
		}
	}
}

//暂时不用
void SipServer::SendRptDataToRemoteCenter()
{
	struct sockaddr_in  addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(8060);
	addr.sin_addr.S_un.S_addr = inet_addr(LandServerIP);

	while (this->isRuning)
	{
		try
		{
			if (WaitSendRtpQueue.empty())
			{
				Sleep(10);
				continue;
			}
			std::lock_guard mtx_locker(RtpMtx);
			RtpDataPack onePack = WaitSendRtpQueue.front();
			WaitSendRtpQueue.pop();
			sendto(clientSocket, onePack.buffer, onePack.len, 0, (sockaddr *)&addr, sizeof(addr));
			delete onePack.buffer;
		}
		catch (exception ex)
		{
			cout << "SendRptDataToRemoteCenter发生异常" << endl;
			cout << ex.what() << endl;
		}
	}
}

SipMonitor

#include "stdafx.h"
#include "SipMonitor.h"
#include "SipServer.h"
#include "CommonData.h"
#include "SipConst.h"
#include "SipParaser.h"
#include "CallProperties.h"
#include "TaskWorking.h"

SipMonitor::SipMonitor(SipServer *asipServer, SipUdpChannel *udpChannel, string deviceID, sockaddr remoteEnd, string ipAdress, USHORT remotePort)
{
	DeviceID = deviceID;
	sipRemoteEnd = remoteEnd;
	sipUdpChannel = udpChannel;
	sipServer = asipServer;
	IpAdress = ipAdress;
	sipRemotePort = remotePort;
}

SipMonitor::~SipMonitor()
{
	this->StopRealplay();
}

void SipMonitor::RealVideoReq()
{
	if (realVideoMsg != nullptr)
	{
		return;
	}

	string fromTag = CallProperties::CreateNewTag();
	sessionID = CallProperties::CreateNewCallId();
	string branch = CallProperties::CreateBranchId();
	int SeqRealVideoReq = CallProperties::CreateNewCSeq();
	
	string sdbBody;
	sdbBody.append("v=0"+ NewLine);
	char  buffer[300];
	_snprintf_s(buffer,300, "o=%s 0 0 IN IP4 %s", SipID, LandServerIP);
	sdbBody.append(buffer + NewLine);
	string channleID ="0";
	sdbBody.append("s=Play" + NewLine);
	sdbBody.append("u=" + channleID + ":3" + NewLine);//通道+类型
	
	_snprintf_s(buffer,300, "c=IN IP4 %s",  LandServerIP);
	sdbBody.append(buffer + NewLine);
	sdbBody.append("t=0 0");
	sdbBody.append(NewLine);
	_snprintf_s(buffer,300, "m=video %d RTP/AVP 96 98 97", CommonData::RPT_Port);

	sdbBody.append(buffer + NewLine);
	sdbBody.append("a=recvonly" + NewLine);
	sdbBody.append("a=rtpmap:96 PS/90000" + NewLine);
	sdbBody.append("a=rtpmap:98 H264/90000" + NewLine);
	sdbBody.append("a=rtpmap:97 MPEG4/90000" + NewLine);
	sdbBody.append("y=0100000001" + NewLine);
	sdbBody.append("a=stream:1" + NewLine);
	//主码流a=stream:0(子码流为a=stream:1)
	sdbBody.append("f=" + NewLine);
	string sbd;
	sprintf_s(buffer, 300, "INVITE sip:%s@%s:%d SIP/2.0", this->DeviceID.c_str(), this->IpAdress.c_str(), this->sipRemotePort);
	sbd.append(buffer+NewLine);

	sprintf_s(buffer, 300, "Call-ID: %s", sessionID.c_str());
	sbd.append(buffer);
	sbd.append(NewLine);
	sprintf_s(buffer, 300, "CSeq: %d INVITE", SeqRealVideoReq);
	sbd.append(buffer);
	sbd.append(NewLine);
	
	sprintf_s(buffer, 300, "From: ;tag=%s", SipID, LandServerIP, LandServerPort, fromTag.c_str());
	sbd.append(buffer);
	sbd.append(NewLine);
	sprintf_s(buffer, 300, "To: ", this->DeviceID.c_str(), this->IpAdress.c_str(), this->sipRemotePort);
	sbd.append(buffer);
	sbd.append(NewLine);
	sprintf_s(buffer, 300, "Via: SIP/2.0/UDP %s:%d;branch=%s", LandServerIP, LandServerPort, branch.c_str());
	sbd.append(buffer);
	sbd.append(NewLine);
	sbd.append("Max-Forwards: 70");
	sbd.append(NewLine);
	sprintf_s(buffer, 300, "Contact: \"%s\" ", SipID, LandServerIP, LandServerPort);
	sbd.append(buffer);
	sbd.append(NewLine);
	sbd.append("User-Agent: VisionVera1.0");
	//sbd.AppendLine("Subject:34020000001320000001:0,94020000002020000001:0");
	//Subject:媒体流发送者设备编码:发送端媒体流序列,媒体流接收者设备编码:接收端媒体流序列号
	sbd.append(NewLine);
	sbd.append("Content-Type: Application/SDP");
	sbd.append(NewLine);
	sprintf_s(buffer, 300, "Route: ", this->DeviceID.c_str(), this->IpAdress.c_str(), this->sipRemotePort);
	sbd.append(buffer);
	sbd.append(NewLine);
	sbd.append("User-Agent: yunkun2.0");
	sbd.append(NewLine);	
	sbd.append("Expires: ");
	sbd.append(to_string(SipConst::ExpiresTime));
	sbd.append(NewLine);
	sbd.append("Content-Length: ");
	sbd.append(to_string(sdbBody.size()));

	sbd.append(NewLine);
	sbd.append(NewLine);
	sbd.append(sdbBody);
	sbd.append(NewLine);
	
	SipMessage request = SipParaser::ParseToSipMessage(sbd, false);
	this->realVideoMsg = new SipMessage(request);
	request.SessionID = sessionID;
	sipUdpChannel->SendData(sipRemoteEnd, sbd);
	
	TaskWorking *taskWoking = new TaskWorking(sipServer, request,sipUdpChannel, sipRemoteEnd);
}

string SipMonitor::GetIpAdress()
{
	return this->IpAdress;
}

USHORT SipMonitor::GetRemotePort()
{
	return this->sipRemotePort;
}

string SipMonitor::GetDeviceID()
{
	return this->DeviceID;
}

void SipMonitor::SetRegisterTime(ec::Date lastRegisterTime)
{
	LastRegisterTime = lastRegisterTime;
}

void SipMonitor::Send200_OK(SipMessage request)
{//200 OK 是不考虑重发的哦。
 //  ISipSession sipSession;
 //  _device.SipMessageSessions.TryRemove(request.SessionID, out sipSession);
	request.BodyInfo = "";
	request.Status = SIPResponseStatusCodesEnum::OK;
	string rawMsg = SipParaser::ParseSipResponseToStr(request);

	this->sipUdpChannel->SendData(this->sipRemoteEnd, rawMsg);
	cout <<"sendMessage:"<< rawMsg << endl;
}
void SipMonitor::Send200_OK_SDP(SipMessage request)
{//200 OK 是不考虑重发的哦。
 //  ISipSession sipSession;
 //  _device.SipMessageSessions.TryRemove(request.SessionID, out sipSession);
	request.Status = SIPResponseStatusCodesEnum::OK;
	string rawMsg = SipParaser::ParseSipResponseToStr(request);
	this->sipUdpChannel->SendData(this->sipRemoteEnd, rawMsg);
}
 void  SipMonitor::SayBye(SipMessage sipMsg)
{
	string sdbBye;
	char buffer[200];
	sprintf_s(buffer, 200, "BYTE sip:%s@%s:%d SIP/2.0", this->DeviceID.c_str(), this->IpAdress.c_str(), this->sipRemotePort);
	sdbBye.append(buffer + NewLine);

	sdbBye.append(sipMsg.CallID.Value + NewLine);
	sdbBye.append(sipMsg.To.Value + NewLine);
	string fromTag = CallProperties::CreateNewTag();

	sprintf_s(buffer, 200, "Via: SIP/2.0/UDP %s:%d;branch=%s", this->IpAdress.c_str(), this->sipRemotePort,fromTag.c_str());
	sdbBye.append(buffer + NewLine);
	sprintf_s(buffer, 200, "CSeq: %d BYE", CallProperties::CreateNewCSeq());
	sdbBye.append(buffer + NewLine);

	sdbBye.append(sipMsg.From.Value + NewLine);
	sdbBye.append("Max-Forwards: 70" + NewLine);
	sdbBye.append("Content-Length: 0" + NewLine);
	sdbBye.append(NewLine);
	SipMessage sipResult = SipParaser::ParseToSipMessage(sdbBye, false);
	this->sipUdpChannel->SendData(this->sipRemoteEnd, sdbBye);

	TaskWorking *taskWoking = new TaskWorking(sipServer, sipResult, sipUdpChannel, sipRemoteEnd);
}
 void SipMonitor::Receive200OK(SipMessage response)
 {

 }
 void  SipMonitor::AckRequest(SipMessage response)
 {
	 if (rtpChannel != nullptr)
		 return;

	// this->StopRealplay();
	 string sbd;
	 char buffer[300];
	 sprintf_s(buffer, 300, "ACK sip:%s@%s:%d SIP/2.0", this->DeviceID.c_str(), this->IpAdress.c_str(), this->sipRemotePort);
	 sbd.append(buffer + NewLine);
	 sbd.append(!response.From.Value.empty() ? response.From.Value + NewLine : "");
	 sbd.append(!response.To.Value.empty() ? response.To.Value + NewLine : "");
	 sbd.append("Max-Forwards: 70"+NewLine);

	
	 string fromTag = CallProperties::CreateNewTag();
	 sprintf_s(buffer, 300, "Via: SIP/2.0/UDP %s:%d;branch=%s", this->IpAdress.c_str(), this->sipRemotePort, fromTag.c_str());
	 sbd.append(buffer + NewLine);

	 int cSeq = CallProperties::CreateNewCSeq();
	 sprintf_s(buffer, 300, "CSeq: %d INVITE", cSeq);
	 sbd.append(buffer + NewLine);

	 sbd.append(response.CallID.Value + NewLine);
	 sbd.append("User-Agent: sunq1.0" + NewLine);
	 sbd.append("Content-Length: 0" + NewLine);
	 sbd.append(NewLine);
	 this->sipUdpChannel->SendData(this->sipRemoteEnd, sbd);
	 rtpChannel = new RtpChannel(CommonData::RPT_Port, this->DeviceID, &sipServer->RtpMtx, &sipServer->WaitSendRtpQueue);

	// SipMessage sipResult = SipParaser::ParseToSipMessage(sbd, false);
	// TaskWorking *taskWoking = new TaskWorking(sipServer, sipResult, sipUdpChannel, sipRemoteEnd);
 }

 void SipMonitor::StopRealplay()
 {
	 if (realVideoMsg != nullptr)
	 {
		 this->SayBye(*realVideoMsg);
		 delete realVideoMsg;
		 realVideoMsg = nullptr;
	 }
	 if (rtpChannel != nullptr)
	 {
		 rtpChannel->Stop();
		 delete rtpChannel;
		 rtpChannel = nullptr;
	 }
 }

 

你可能感兴趣的:(c++,Socket)