Commit 9cc58d13 authored by Guillaume Roguez's avatar Guillaume Roguez

sip: fix display name parsing and saving

This patch parses optional display name that can be seen in From
and Contact SIP headers, for incoming calls.
Fallback on Contact header is made if From header is empty.

This also send the local display name in From header for outgoing
calls.

Issue: #77375
Change-Id: Iaef5e0e728a74427f3ced7efd947d09be91c0ac3
parent 989e9bdb
......@@ -1133,7 +1133,10 @@ RingAccount::matches(const std::string &userName, const std::string &server) con
std::string RingAccount::getFromUri() const
{
return "<sip:" + dht_.getId().toString() + "@ring.dht>";
const std::string uri = "<sip:" + dht_.getId().toString() + "@ring.dht>";
if (not displayName_.empty())
return "\"" + displayName_ + "\" " + uri;
return uri;
}
std::string RingAccount::getToUri(const std::string& to) const
......
......@@ -101,58 +101,36 @@ createRouteSet(const std::string &route, pj_pool_t *hdr_pool)
return route_set;
}
// FIXME: replace with regex
std::string
parseDisplayName(const char * buffer)
parseDisplayName(const pjsip_name_addr* sip_name_addr)
{
// Start in From: in short and long form
const char* from_header = strstr(buffer, "\nFrom: ");
if (!from_header)
from_header = strstr(buffer, "\nf: ");
if (!from_header)
return "";
if (not sip_name_addr->display.ptr or not sip_name_addr->display.slen)
return {};
std::string temp(from_header);
// Cut at end of line
temp = temp.substr(0, temp.find("\n", 1));
size_t begin_displayName = temp.find("\"");
size_t end_displayName;
if (begin_displayName != std::string::npos) {
// parse between quotes
end_displayName = temp.find("\"", begin_displayName + 1);
if (end_displayName == std::string::npos)
return "";
} else {
// parse without quotes
end_displayName = temp.find("<");
if (end_displayName != std::string::npos) {
begin_displayName = temp.find_first_not_of(" ", temp.find(":"));
if (begin_displayName == std::string::npos)
return "";
// omit trailing/leading spaces
begin_displayName++;
end_displayName--;
if (end_displayName == begin_displayName)
return "";
} else {
return "";
}
}
std::string displayName = temp.substr(begin_displayName + 1,
end_displayName - begin_displayName - 1);
std::string displayName {sip_name_addr->display.ptr,
static_cast<size_t>(sip_name_addr->display.slen)};
// Filter out invalid UTF-8 characters to avoid getting kicked from D-Bus
if (not utf8_validate(displayName)) {
if (not utf8_validate(displayName))
return utf8_make_valid(displayName);
}
return displayName;
}
std::string
parseDisplayName(const pjsip_from_hdr* header)
{
// PJSIP return a pjsip_name_addr for To, From and Contact headers
return parseDisplayName(reinterpret_cast<pjsip_name_addr*>(header->uri));
}
std::string
parseDisplayName(const pjsip_contact_hdr* header)
{
// PJSIP return a pjsip_name_addr for To, From and Contact headers
return parseDisplayName(reinterpret_cast<pjsip_name_addr*>(header->uri));
}
void
stripSipUriPrefix(std::string& sipUri)
{
......
......@@ -73,7 +73,9 @@ createRouteSet(const std::string &route, pj_pool_t *hdr_pool);
void stripSipUriPrefix(std::string& sipUri);
std::string parseDisplayName(const char * buffer);
std::string parseDisplayName(const pjsip_name_addr* sip_name_addr);
std::string parseDisplayName(const pjsip_from_hdr* header);
std::string parseDisplayName(const pjsip_contact_hdr* header);
std::string getHostFromUri(const std::string& sipUri);
......
......@@ -1355,7 +1355,10 @@ std::string SIPAccount::getFromUri() const
hostname = IpAddr(hostname).toString(false, true);
#endif
return "<" + scheme + username + "@" + hostname + transport + ">";
const std::string uri = "<" + scheme + username + "@" + hostname + transport + ">";
if (not displayName_.empty())
return "\"" + displayName_ + "\" " + uri;
return uri;
}
std::string SIPAccount::getToUri(const std::string& username) const
......
......@@ -194,14 +194,16 @@ transaction_request_cb(pjsip_rx_data *rdata)
RING_ERR("Missing From, To or Via fields");
return PJ_FALSE;
}
const pjsip_sip_uri *sip_to_uri = (pjsip_sip_uri *) pjsip_uri_get_uri(rdata->msg_info.to->uri);
const pjsip_sip_uri *sip_from_uri = (pjsip_sip_uri *) pjsip_uri_get_uri(rdata->msg_info.from->uri);
const auto sip_to_uri = reinterpret_cast<pjsip_sip_uri*>(pjsip_uri_get_uri(rdata->msg_info.to->uri));
const auto sip_from_uri = reinterpret_cast<pjsip_sip_uri*>(pjsip_uri_get_uri(rdata->msg_info.from->uri));
const pjsip_host_port& sip_via = rdata->msg_info.via->sent_by;
if (!sip_to_uri or !sip_from_uri or !sip_via.host.ptr) {
RING_ERR("NULL uri");
return PJ_FALSE;
}
std::string toUsername(sip_to_uri->user.ptr, sip_to_uri->user.slen);
std::string toHost(sip_to_uri->host.ptr, sip_to_uri->host.slen);
std::string viaHostname(sip_via.host.ptr, sip_via.host.slen);
......@@ -225,7 +227,6 @@ transaction_request_cb(pjsip_rx_data *rdata)
}
const auto& account_id = account->getAccountID();
auto peerDisplayName = sip_utils::parseDisplayName(rdata->msg_info.msg_buf);
pjsip_msg_body *body = rdata->msg_info.msg->body;
if (method->id == PJSIP_OTHER_METHOD) {
......@@ -286,7 +287,6 @@ transaction_request_cb(pjsip_rx_data *rdata)
return PJ_FALSE;
}
if (not remote_user.empty() and not remote_hostname.empty())
peerNumber = remote_user + "@" + remote_hostname;
......@@ -324,6 +324,16 @@ transaction_request_cb(pjsip_rx_data *rdata)
/* fallback on local address */
if (not addrSdp) addrSdp = addrToUse;
// Try to obtain display name from From: header first, fallback on Contact:
auto peerDisplayName = sip_utils::parseDisplayName(rdata->msg_info.from);
if (peerDisplayName.empty()) {
if (auto hdr = static_cast<const pjsip_contact_hdr*>(pjsip_msg_find_hdr(rdata->msg_info.msg,
PJSIP_H_CONTACT,
nullptr))) {
peerDisplayName = sip_utils::parseDisplayName(hdr);
}
}
call->setState(Call::ConnectionState::PROGRESSING);
call->setPeerNumber(peerNumber);
call->setPeerDisplayName(peerDisplayName);
......
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