reSIProcate的时间格式
reSIProcate的Date时间格式和国标的不一致,reSIProcate的格式一般为“Mon, 04 Nov 2002 17:34:15 GMT”,显示的格林威治时间,国标规定的事件格式为“2022-03-10T11:11:11.123”,显示的一般是本地时间。
我的方案
我的修改方案是在reSIProcate的源码中增加一个if分支,通过if分支来判断哪种时间格式,如有更好的方案或错误望交流指正。涉及修改的文件如下:
修改的方法
1、修改Symbols头文件和源文件,增加‘T’的字符定义
头文件:
源文件:
2、修改DateCategory头文件,增加时间格式类型的枚举类型,并修改构造函数,增加默认的时间格式参数
(1)增加枚举定义:
(2)修改构造函数,默认还是原来的格式:
3、修改DateCategory源文件,增加国标的处理逻辑
(1)修改构造函数,增加参数后对应的修改
DateCategory::DateCategory(DateType dateType)
: ParserCategory(),
mDayOfWeek(Sun),
mDayOfMonth(),
mMonth(Jan),
mYear(0),
mHour(0),
mMin(0),
mSec(0),
mMillisec(0),
mDateType(dateType)
{
time_t now;
time(&now);
if (now == ((time_t)-1))
{
int e = getErrno();
DebugLog (<< "Failed to get time: " << strerror(e));
Transport::error(e);
return;
}
setDatetime(now);
}
DateCategory::DateCategory(time_t datetime,
DateType dateType)
: ParserCategory(),
mDayOfWeek(Sun),
mDayOfMonth(),
mMonth(Jan),
mYear(0),
mHour(0),
mMin(0),
mSec(0),
mMillisec(0),
mDateType(dateType)
{
setDatetime(datetime);
}
DateCategory::DateCategory(const HeaderFieldValue& hfv,
Headers::Type type,
PoolBase* pool,
DateType dateType)
: ParserCategory(hfv, type, pool),
mDayOfWeek(Sun),
mDayOfMonth(),
mMonth(Jan),
mYear(0),
mHour(0),
mMin(0),
mSec(0),
mMillisec(0),
mDateType(dateType)
{}
DateCategory::DateCategory(const DateCategory& rhs,
PoolBase* pool)
: ParserCategory(rhs, pool),
mDayOfWeek(rhs.mDayOfWeek),
mDayOfMonth(rhs.mDayOfMonth),
mMonth(rhs.mMonth),
mYear(rhs.mYear),
mHour(rhs.mHour),
mMin(rhs.mMin),
mSec(rhs.mSec),
mMillisec(rhs.mMillisec),
mDateType(rhs.mDateType)
{}
DateCategory&
DateCategory::operator=(const DateCategory& rhs)
{
if (this != &rhs)
{
ParserCategory::operator=(rhs);
mDayOfWeek = rhs.mDayOfWeek;
mDayOfMonth = rhs.mDayOfMonth;
mMonth = rhs.mMonth;
mYear = rhs.mYear;
mHour = rhs.mHour;
mMin = rhs.mMin;
mSec = rhs.mSec;
mMillisec = rhs.mMillisec,
mDateType = rhs.mDateType;
}
return *this;
}
(2)setDatetime添加获取本地时间的逻辑
bool
DateCategory::setDatetime(time_t datetime)
{
struct tm gmt;
#if defined(WIN32) || defined(__sun)
struct tm *gmtp=nullptr;
if(mDateType == reSIPDate)
gmtp = gmtime(&datetime);
else
gmtp = localtime(&datetime);
if (gmtp == 0)
{
int e = getErrno();
DebugLog (<< "Failed to convert to gmt: " << strerror(e));
Transport::error(e);
return false;
}
memcpy(&gmt,gmtp,sizeof(gmt));
#else
if (mDateType == reSIPDate)
{
if (gmtime_r(&datetime, &gmt) == 0)
{
int e = getErrno();
DebugLog(<< "Failed to convert to gmt: " << strerror(e));
Transport::error(e);
return false;
}
}
else
{
if (localtime_r(&datetime, &gmt) == 0)
{
int e = getErrno();
DebugLog(<< "Failed to convert to gmt: " << strerror(e));
Transport::error(e);
return false;
}
}
#endif
mDayOfWeek = static_cast<DayOfWeek>(gmt.tm_wday);
mDayOfMonth = gmt.tm_mday;
mMonth = static_cast<Month>(gmt.tm_mon);
mYear = gmt.tm_year + 1900;
mHour = gmt.tm_hour;
mMin = gmt.tm_min;
mSec = gmt.tm_sec;
DebugLog (<< "Set date: day=" << mDayOfWeek
<< " month=" << mMonth
<< " year=" << mYear
<< " " << mHour << ":" << mMin << ":" << mSec);
return true;
}
(3)修改parse函数,添加解析国标格式的逻辑(未验证)
void
DateCategory::parse(ParseBuffer& pb)
{
if (mDateType == reSIPDate)
{
// Mon, 04 Nov 2002 17:34:15 GMT
// Note: Day of Week is optional, so this is also valid: 04 Nov 2002 17:34:15 GMT
const char* anchor = pb.skipWhitespace();
// If comma is present, then DayOfWeek is present
pb.skipToChar(Symbols::COMMA[0]);
if (!pb.eof())
{
Data dayOfWeek;
pb.data(dayOfWeek, anchor);
mDayOfWeek = DateCategory::DayOfWeekFromData(dayOfWeek);
pb.skipChar(Symbols::COMMA[0]);
}
else
{
pb.reset(pb.start());
mDayOfWeek = DayOfWeek::NA;
}
pb.skipWhitespace();
mDayOfMonth = pb.integer();
anchor = pb.skipWhitespace();
pb.skipNonWhitespace();
Data month;
pb.data(month, anchor);
mMonth = DateCategory::MonthFromData(month);
pb.skipWhitespace();
mYear = pb.integer();
pb.skipWhitespace();
mHour = pb.integer();
pb.skipChar(Symbols::COLON[0]);
mMin = pb.integer();
pb.skipChar(Symbols::COLON[0]);
mSec = pb.integer();
pb.skipWhitespace();
pb.skipChar('G');
pb.skipChar('M');
pb.skipChar('T');
}
else
{
//Date: 2022-02-25T15:22:41.380
const char* anchor = pb.skipWhitespace();
mYear = pb.integer();
pb.skipChar(Symbols::DASH[0]);
mMonth = (Month)pb.integer();
pb.skipChar(Symbols::DASH[0]);
mDayOfMonth = pb.integer();
pb.skipChar(Symbols::GBTIMET[0]);
mHour = pb.integer();
pb.skipChar(Symbols::COLON[0]);
mMin = pb.integer();
pb.skipChar(Symbols::COLON[0]);
mSec = pb.integer();
pb.skipChar(Symbols::DOT[0]);
mMillisec = pb.integer();
}
pb.skipWhitespace();
pb.assertEof();
}
(4)添加填充3个占位的处理,修改encodeParsed,添加时间格式生成代码(已验证)
static void pad3(const int x, EncodeStream& str)
{
if (x < 100)
{
str << resip::Symbols::ZERO[0];
if (x < 10)
{
str << resip::Symbols::ZERO[0];
}
}
str << x;
}
EncodeStream&
DateCategory::encodeParsed(EncodeStream& str) const
{
if (mDateType == reSIPDate)
{
if (mDayOfWeek != DayOfWeek::NA)
{
str << DayOfWeekData[mDayOfWeek] // Mon
<< Symbols::COMMA[0] << Symbols::SPACE[0];
}
pad2(mDayOfMonth, str); // 04
str << Symbols::SPACE[0]
<< MonthData[mMonth] << Symbols::SPACE[0] // Nov
<< mYear << Symbols::SPACE[0]; // 2002
pad2(mHour, str);
str << Symbols::COLON[0];
pad2(mMin, str);
str << Symbols::COLON[0];
pad2(mSec, str);
str << " GMT";
}
else
{
pad2(this->year(), str);
str << Symbols::DASH[0];
pad2(this->month(), str);
str << Symbols::DASH[0];
pad2(this->dayOfMonth(), str);
str << Symbols::GBTIMET[0];
pad2(this->hour(), str);
str << Symbols::COLON[0];
pad2(this->minute(), str);
str << Symbols::COLON[0];
pad2(this->second(), str);
str << Symbols::DOT[0];
pad3(0, str);
}
return str;
}
使用方法
代码片段示例,详情参考https://blog.csdn.net/qq_24022755/article/details/121862063
resip::SipMessage success;
resip::Helper::makeResponse(success, reg, 200);
if (!reg.empty(resip::h_Paths))
{
success.header(resip::h_Paths) = reg.header(resip::h_Paths);
success.header(resip::h_Supporteds).push_back(resip::Token(resip::Symbols::Path));
}
//添加国标格式Date
resip::DateCategory curTime(resip::GB28181Date);
success.header(resip::h_Date) = curTime;
sr->accept(success);