#define LOG_MODULE PacketLogModuleSdpLayer
#include "SdpLayer.h"
#include "Logger.h"
#include <stdlib.h>
#include <string>
#include <sstream>
namespace pcpp
{
std::vector<std::string> splitByWhiteSpaces(const std::string& str)
{
std::string buf;
std::stringstream stream(str);
std::vector<std::string> result;
while (stream >> buf)
result.push_back(buf);
return result;
}
SdpLayer::SdpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : TextBasedProtocolMessage(data, dataLen, prevLayer, packet)
{
m_Protocol = SDP;
m_FieldsOffset = 0;
parseFields();
}
SdpLayer::SdpLayer()
{
m_Protocol = SDP;
m_FieldsOffset = 0;
}
SdpLayer::SdpLayer(const std::string& username, long sessionID, long sessionVersion, IPv4Address ipAddress, const std::string& sessionName, long startTime, long stopTime)
{
m_Protocol = SDP;
m_FieldsOffset = 0;
m_Data = new uint8_t[1];
m_DataLen = 0;
addField(PCPP_SDP_PROTOCOL_VERSION_FIELD, "0");
std::stringstream sessionIDStream;
sessionIDStream << sessionID;
std::stringstream sessionVersionStream;
sessionVersionStream << sessionVersion;
std::string networkInfo = "IN IP4 " + ipAddress.toString();
std::string originatorFieldValue = username + " " + sessionIDStream.str() + " " + sessionVersionStream.str() + " " + networkInfo;
addField(PCPP_SDP_ORIGINATOR_FIELD, originatorFieldValue);
addField(PCPP_SDP_SESSION_NAME_FIELD, sessionName);
addField(PCPP_SDP_CONNECTION_INFO_FIELD, networkInfo);
std::stringstream startTimeStream;
startTimeStream << startTime;
std::stringstream stopTimeStream;
stopTimeStream << stopTime;
addField(PCPP_SDP_TIME_FIELD, startTimeStream.str() + " " + stopTimeStream.str());
}
std::string SdpLayer::toString() const
{
return "SDP Layer";
}
IPv4Address SdpLayer::getOwnerIPv4Address() const
{
HeaderField* originator = getFieldByName(PCPP_SDP_ORIGINATOR_FIELD);
if (originator == nullptr)
return IPv4Address::Zero;
std::vector<std::string> tokens = splitByWhiteSpaces(originator->getFieldValue());
if (tokens.size() < 6)
return IPv4Address::Zero;
if (tokens[3] != "IN" || tokens[4] != "IP4")
return IPv4Address::Zero;
return IPv4Address(tokens[5]);
}
uint16_t SdpLayer::getMediaPort(const std::string& mediaType) const
{
int mediaFieldIndex = 0;
HeaderField* mediaDesc = getFieldByName(PCPP_SDP_MEDIA_NAME_FIELD, mediaFieldIndex);
while (mediaDesc != nullptr)
{
std::vector<std::string> tokens = splitByWhiteSpaces(mediaDesc->getFieldValue());
if (tokens.size() >= 2 && tokens[0] == mediaType)
return atoi(tokens[1].c_str());
mediaFieldIndex++;
mediaDesc = getFieldByName(PCPP_SDP_MEDIA_NAME_FIELD, mediaFieldIndex);
}
return 0;
}
bool SdpLayer::addMediaDescription(const std::string& mediaType, uint16_t mediaPort, const std::string& mediaProtocol, const std::string& mediaFormat, std::vector<std::string> mediaAttributes)
{
std::stringstream portStream;
portStream << mediaPort;
std::string mediaFieldValue = mediaType + " " + portStream.str() + " " + mediaProtocol + " " + mediaFormat;
if (addField(PCPP_SDP_MEDIA_NAME_FIELD, mediaFieldValue) == nullptr)
{
PCPP_LOG_ERROR("Failed to add media description field");
return false;
}
for (std::vector<std::string>::iterator iter = mediaAttributes.begin(); iter != mediaAttributes.end(); iter++)
{
if (addField(PCPP_SDP_MEDIA_ATTRIBUTE_FIELD, *iter) == nullptr)
{
PCPP_LOG_ERROR("Failed to add media attribute '" << *iter << "'");
return false;
}
}
return true;
}
}