Commit ae763dc2 authored by Erwan Croze's avatar Erwan Croze 👋🏻

Fix header value "path" in registrardb

parent df9b2849
Pipeline #1073 passed with stages
in 42 minutes and 54 seconds
......@@ -670,17 +670,6 @@ void RegistrarDbRedisAsync::handleBind(redisReply *reply, RegistrarUserData *dat
}
}
static string extractUniqueId(Record r, sip_contact_t *contact) {
while (contact) {
string lineValue = r.extractUniqueId(contact);
if (!lineValue.empty()) {
return lineValue;
}
contact = contact->m_next;
}
return "";
}
void RegistrarDbRedisAsync::doBind(const sip_t *sip, int globalExpire, bool alias, int version, const std::shared_ptr<ContactUpdateListener> &listener) {
// Update the AOR Hashmap using HSET
// If there is an error, try again
......@@ -703,7 +692,12 @@ void RegistrarDbRedisAsync::doBind(const sip_t *sip, int globalExpire, bool alia
serializeAndSendToRedis(data, sHandleBind);
} else {
const char *key = data->record.getKey().c_str();
string uid = extractUniqueId(data->record, sip->sip_contact);
string uid = "";
if (data->record.getExtendedContacts().empty()) {
LOGW("No extended contact found for %s, can't remove it from REDIS.", key);
} else {
uid = data->record.getExtendedContacts().front()->getUniqueId();
}
data->mIsUnregister = true;
check_redis_command(redisAsyncCommand(mContext, (void (*)(redisAsyncContext*, void*, void*))sHandleBind,
data, "HDEL fs:%s %s", key, uid.c_str()), data);
......
......@@ -293,7 +293,7 @@ void Record::insertOrUpdateBinding(const shared_ptr<ExtendedContact> &ec, const
SLOGD << "Trying to insert new contact " << *ec;
if (sAssumeUniqueDomains && mIsDomain){
if (sAssumeUniqueDomains && mIsDomain) {
mContacts.clear();
}
for (auto it = mContacts.begin(); it != mContacts.end();) {
......@@ -303,14 +303,14 @@ void Record::insertOrUpdateBinding(const shared_ptr<ExtendedContact> &ec, const
} else if (!(*it)->mUniqueId.empty() && (*it)->mUniqueId == ec->mUniqueId) {
if (ec->mExpireAt == now){
/*case of ;expires=0 in contact header*/
if ((*it)->mCSeq == ec->mCSeq && (*it)->mCallId == ec->mCallId){
if ((*it)->mCSeq == ec->mCSeq && (*it)->mCallId == ec->mCallId) {
/*this happens when a client (like Linphone) sends this kind of very ambiguous Contact header in a REGISTER
* Contact: <sip:marie_-jSau@ip1:39936;transport=tcp>;+sip.instance="<urn:uuid:bfb7514b-f793-4d85-b322-232044dc3731>"
* Contact: <sip:marie_-jSau@ip1:39934;transport=tcp>;+sip.instance="<urn:uuid:bfb7514b-f793-4d85-b322-232044dc3731>";expires=0
*
* We don't want the second line to unregister the first one, so don't touch anything*/
return;
}else{
} else {
/*this contact should be removed*/
it = mContacts.erase(it);
return;
......@@ -337,19 +337,18 @@ void Record::insertOrUpdateBinding(const shared_ptr<ExtendedContact> &ec, const
}
}
shared_ptr< multimap<string, string> > Record::extractInfoFromHeader(const char *urlHeaders) {
shared_ptr< multimap<string, string> > result = make_shared< multimap<string, string> >();
void ExtendedContact::extractInfoFromHeader(const char *urlHeaders) {
if (urlHeaders) {
SofiaAutoHome home;
msg_header_t *headers;
char *stringHeaders = url_query_as_header_string(home.home(), urlHeaders);
msg_t *msg = msg_create(sip_default_mclass(), 0);
if (msg_header_parse_str(msg, nullptr, stringHeaders) != 0) goto end;
if (msg_header_parse_str(msg, nullptr, stringHeaders) != 0) return;
// We need to add a sip_request to validate msg_serialize() contidition
if (msg_header_add_dup(msg, nullptr,
reinterpret_cast<msg_header_t*>(sip_request_make(home.home(), "MESSAGE sip:abcd SIP/2.0\r\n"))) != 0) goto end;
if (msg_serialize(msg, nullptr) != 0) goto end;
reinterpret_cast<msg_header_t*>(sip_request_make(home.home(), "MESSAGE sip:abcd SIP/2.0\r\n"))) != 0) return;
if (msg_serialize(msg, nullptr) != 0) return;
msg_prepare(msg);
headers = *msg_chain_head(msg);
......@@ -363,19 +362,26 @@ shared_ptr< multimap<string, string> > Record::extractInfoFromHeader(const char
msg_header_field_e(value, reinterpret_cast<msg_common_t*>(headers)->h_len, headers, 0);
valueStr = value;
delete[] value;
transform(valueStr.begin(), valueStr.end(), valueStr.begin(), [](unsigned char c){ return std::tolower(c); });
transform(keyStr.begin(), keyStr.end(), keyStr.begin(), [](unsigned char c){ return std::tolower(c); });
result->insert(pair<string, string>(keyStr, value));
delete[] value;
if (keyStr == "path") {
size_t bracket = valueStr.find('<');
if (bracket != string::npos) valueStr.erase(bracket, static_cast<size_t>(1));
bracket = valueStr.find('>');
if (bracket != string::npos) valueStr.erase(bracket, static_cast<size_t>(1));
mPath.push_back(valueStr);
} else if (keyStr == "accept") {
mAcceptHeader.push_back(valueStr);
} else if (keyStr == "user-agent") {
mUserAgent = valueStr;
}
}
headers = reinterpret_cast<msg_common_t*>(headers)->h_succ;
}
}
end:
return result;
}
static bool compare_contact_using_last_update (shared_ptr<ExtendedContact> first, shared_ptr<ExtendedContact> second) {
......@@ -464,17 +470,11 @@ string ExtendedContact::serializeAsUrlEncodedParams() {
oss << "usedAsRoute=" << (mUsedAsRoute ? "yes" : "no");
url_param_add(home.home(), contact->m_url, oss.str().c_str());
// User-agent
oss.str("");
oss.clear();
oss << "user-agent=" << mUserAgent;
url_param_add(home.home(), contact->m_url, oss.str().c_str());
// Path
ostringstream oss_path;
for (auto it = mPath.begin(); it != mPath.end(); ++it) {
if (it != mPath.begin()) oss_path << ",";
oss_path << *it;
oss_path << "<" << *it << ">";
}
// AcceptHeaders
......@@ -486,7 +486,7 @@ string ExtendedContact::serializeAsUrlEncodedParams() {
contact->m_url->url_headers = sip_headers_as_url_query(home.home(),
SIPTAG_PATH_STR(oss_path.str().c_str()), SIPTAG_ACCEPT_STR(oss_accept.str().c_str()),
TAG_END());
SIPTAG_USER_AGENT_STR(mUserAgent.c_str()) , TAG_END());
string contact_string(sip_header_as_string(home.home(), (sip_header_t const *)contact));
return contact_string;
......@@ -516,82 +516,77 @@ static bool extractBoolParam(url_t *url, const char *param) {
return (extracted_param.empty()) ? FALSE : (extracted_param.find("yes") != string::npos);
}
bool Record::updateFromUrlEncodedParams(const char *key, const char *uid, const char *full_url) {
bool result = false;
SofiaAutoHome home;
shared_ptr< multimap<string, string> > resultHeader;
void ExtendedContact::init() {
if (mSipContact) {
if (mSipContact->m_q) {
mQ = atof(mSipContact->m_q);
}
// Path
list<string> path;
// Accept headers
list<string> acceptHeaders;
int expire = resolveExpire(mSipContact->m_expires, mExpireNotAtMessage);
mExpireNotAtMessage = mUpdatedTime + expire;
expire = resolveExpire(getMessageExpires(mSipContact->m_params).c_str(), expire);
if (expire == -1) {
LOGE("no global expire (%li) nor local contact expire (%s)found", mExpireNotAtMessage, mSipContact->m_expires);
expire = 0;
}
mExpireAt = mUpdatedTime + expire;
mExpireAt = mExpireAt > mExpireNotAtMessage ? mExpireAt : mExpireNotAtMessage;
}
}
sip_contact_t *temp_contact = sip_contact_make(home.home(), full_url);
void ExtendedContact::extractInfoFromUrl(const char* full_url) {
sip_contact_t *temp_contact = sip_contact_make(mHome.home(), full_url);
url_t *url = nullptr;
if (temp_contact == nullptr) {
SLOGD << "Couldn't parse " << full_url << " as contact, fallback to url instead";
url = url_make(home.home(), full_url);
url = url_make(mHome.home(), full_url);
} else {
url = temp_contact->m_url;
}
// CallId
string call_id = extractStringParam(url, "callid");
mCallId = extractStringParam(url, "callid");
// Expire
int globalExpire = extractIntParam(url, "expires");
mExpireNotAtMessage = extractIntParam(url, "expires");
// Update time
unsigned long updatedAt = extractUnsignedLongParam(url, "updatedAt");
mUpdatedTime = extractUnsignedLongParam(url, "updatedAt");
// CSeq
uint32_t cseq = extractIntParam(url, "cseq");
mCSeq = extractIntParam(url, "cseq");
// Alias
bool alias = extractBoolParam(url, "alias");
mAlias = extractBoolParam(url, "alias");
// Used as route
bool usedAsRoute = extractBoolParam(url, "usedAsRoute");
// User-agent
string userAgent = extractStringParam(url, "user-agent");
mUsedAsRoute = extractBoolParam(url, "usedAsRoute");
resultHeader = extractInfoFromHeader(url->url_headers);
for (auto pair : *resultHeader) {
if (pair.first == "path") {
path.push_back(pair.second);
} else if (pair.first == "accept") {
acceptHeaders.push_back(pair.second);
}
}
extractInfoFromHeader(url->url_headers);
char transport[20] = {0};
url_param(url[0].url_params, "transport", transport, sizeof(transport) - 1);
url->url_headers = nullptr;
sip_contact_t *contact = nullptr;
if (temp_contact == nullptr) {
contact = sip_contact_create(home.home(), (url_string_t*)url, nullptr);
mSipContact = sip_contact_create(mHome.home(), (url_string_t*)url, nullptr);
} else {
contact = temp_contact;
mSipContact = temp_contact;
}
if (contact == nullptr) {
return result;
}
if (mSipContact) setupRegid();
}
ExtendedContactCommon ecc(key, path, call_id, uid);
auto exc = make_shared<ExtendedContact>(ecc, contact, globalExpire, cseq, updatedAt, alias, acceptHeaders, userAgent);
exc->setupRegid();
exc->mUsedAsRoute = usedAsRoute;
bool Record::updateFromUrlEncodedParams(const char *key, const char *uid, const char *full_url) {
auto exc = make_shared<ExtendedContact>(key, uid, full_url);
if (getCurrentTime() < exc->mExpireAt) {
if (exc->mSipContact && getCurrentTime() < exc->mExpireAt) {
insertOrUpdateBinding(exc, nullptr);
result = true;
return true;
}
return result;
return false;
}
void Record::update(const sip_t *sip, int globalExpire, bool alias, int version, const shared_ptr<ContactUpdateListener> &listener) {
......
......@@ -134,32 +134,32 @@ struct ExtendedContact {
std::string getOrgLinphoneSpecs();
void extractInfoFromHeader(const char *urlHeaders);
void setupRegid();
void transferRegId(const std::shared_ptr<ExtendedContact> &oldEc);
const std::string getMessageExpires(const msg_param_t *m_params);
void init();
void extractInfoFromUrl(const char* full_url);
ExtendedContact(const char *contactId, const char *uniqueId, const char* fullUrl)
: mCallId(), mUserAgent(), mSipContact(nullptr), mQ(1.0), mExpireAt(LONG_MAX), mExpireNotAtMessage(LONG_MAX),
mUpdatedTime(0), mCSeq(0), mAlias(false), mAcceptHeader({}), mUsedAsRoute(false), mRegId(0), mHome() {
if (contactId) mContactId = contactId;
if (uniqueId) mUniqueId = uniqueId;
extractInfoFromUrl(fullUrl);
init();
}
ExtendedContact(const ExtendedContactCommon &common, const sip_contact_t *sip_contact, int global_expire, uint32_t cseq,
time_t updateTime, bool alias, const std::list<std::string> &acceptHeaders, const std::string &userAgent)
: mContactId(common.mContactId), mCallId(common.mCallId), mUniqueId(common.mUniqueId), mPath(common.mPath),
mUserAgent(userAgent), mSipContact(nullptr), mQ(1.0), mUpdatedTime(updateTime), mCSeq(cseq), mAlias(alias),
mAcceptHeader(acceptHeaders), mUsedAsRoute(false), mRegId(0), mHome() {
mUserAgent(userAgent), mSipContact(nullptr), mQ(1.0),mExpireNotAtMessage(global_expire), mUpdatedTime(updateTime),
mCSeq(cseq), mAlias(alias), mAcceptHeader(acceptHeaders), mUsedAsRoute(false), mRegId(0), mHome() {
mSipContact = sip_contact_dup(mHome.home(), sip_contact);
mSipContact->m_next = nullptr;
if (mSipContact->m_q) {
mQ = atof(mSipContact->m_q);
}
int expire = resolveExpire(mSipContact->m_expires, global_expire);
mExpireNotAtMessage = updateTime + expire;
expire = resolveExpire(getMessageExpires(mSipContact->m_params).c_str(), expire);
if (expire == -1) {
LOGE("no global expire (%d) nor local contact expire (%s)found", global_expire, mSipContact->m_expires);
expire = 0;
}
mExpireAt = updateTime + expire;
mExpireAt = mExpireAt > mExpireNotAtMessage ? mExpireAt:mExpireNotAtMessage;
init();
}
ExtendedContact(const url_t *url, const std::string &route, const float q = 1.0)
......@@ -208,7 +208,6 @@ class Record {
static int sMaxContacts;
static bool sAssumeUniqueDomains;
Record(const url_t *aor);
std::shared_ptr< std::multimap<std::string, std::string> > extractInfoFromHeader(const char *url_headers);
static std::string extractUniqueId(const sip_contact_t *contact);
const std::shared_ptr<ExtendedContact> extractContactByUniqueId(std::string uid);
sip_contact_t *getContacts(su_home_t *home, time_t now);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment