From 9ff9a24c487ba5a93fb66a6aa92050790d280bcf Mon Sep 17 00:00:00 2001 From: "Alfred E. Heggestad" Date: Thu, 25 Sep 2014 07:51:19 +0000 Subject: [PATCH] sip: add sip contact, needed for GRUU - in sipsess and sipevent, the cuser parameter can now be a contact-username or a uri (e.g. GRUU) - Tested by Juha Heinanen (with baresip+gruu) --- include/re_sip.h | 14 ++++++++++ src/sip/contact.c | 57 ++++++++++++++++++++++++++++++++++++++++ src/sip/mod.mk | 1 + src/sipevent/notify.c | 13 ++++++--- src/sipevent/subscribe.c | 14 +++++----- src/sipreg/reg.c | 2 +- src/sipsess/accept.c | 22 ++++++++++------ src/sipsess/connect.c | 8 +++--- src/sipsess/modify.c | 6 +++-- src/sipsess/reply.c | 7 +++-- 10 files changed, 118 insertions(+), 26 deletions(-) create mode 100644 src/sip/contact.c diff --git a/include/re_sip.h b/include/re_sip.h index 7474b67..1bb06b4 100644 --- a/include/re_sip.h +++ b/include/re_sip.h @@ -214,6 +214,13 @@ struct sip_loopstate { uint16_t last_scode; }; +/** SIP Contact */ +struct sip_contact { + const char *uri; + const struct sa *addr; + enum sip_transp tp; +}; + struct sip; struct sip_lsnr; struct sip_request; @@ -303,6 +310,13 @@ int sip_auth_alloc(struct sip_auth **authp, sip_auth_h *authh, void sip_auth_reset(struct sip_auth *auth); +/* contact */ +void sip_contact_set(struct sip_contact *contact, const char *uri, + const struct sa *addr, enum sip_transp tp); +int sip_contact_print(struct re_printf *pf, + const struct sip_contact *contact); + + /* dialog */ int sip_dialog_alloc(struct sip_dialog **dlgp, const char *uri, const char *to_uri, diff --git a/src/sip/contact.c b/src/sip/contact.c new file mode 100644 index 0000000..6703384 --- /dev/null +++ b/src/sip/contact.c @@ -0,0 +1,57 @@ +/** + * @file sip/contact.c SIP contact functions + * + * Copyright (C) 2010 Creytiv.com + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + * Set contact parameters + * + * @param contact SIP Contact object + * @param uri Username or URI + * @param addr IP-address and port + * @param tp SIP Transport + */ +void sip_contact_set(struct sip_contact *contact, const char *uri, + const struct sa *addr, enum sip_transp tp) +{ + if (!contact) + return; + + contact->uri = uri; + contact->addr = addr; + contact->tp = tp; +} + + +/** + * Print contact header + * + * @param pf Print function + * @param contact SIP Contact object + * + * @return 0 for success, otherwise errorcode + */ +int sip_contact_print(struct re_printf *pf, const struct sip_contact *contact) +{ + if (!contact) + return 0; + + if (contact->uri && strchr(contact->uri, ':')) + return re_hprintf(pf, "Contact: <%s>\r\n", contact->uri); + else + return re_hprintf(pf, "Contact: \r\n", + contact->uri, + contact->addr, + sip_transp_param(contact->tp)); +} diff --git a/src/sip/mod.mk b/src/sip/mod.mk index 47e3abe..446c028 100644 --- a/src/sip/mod.mk +++ b/src/sip/mod.mk @@ -6,6 +6,7 @@ SRCS += sip/addr.c SRCS += sip/auth.c +SRCS += sip/contact.c SRCS += sip/cseq.c SRCS += sip/ctrans.c SRCS += sip/dialog.c diff --git a/src/sipevent/notify.c b/src/sipevent/notify.c index d368172..7a7a87d 100644 --- a/src/sipevent/notify.c +++ b/src/sipevent/notify.c @@ -177,11 +177,13 @@ static void response_handler(int err, const struct sip_msg *msg, void *arg) static int send_handler(enum sip_transp tp, const struct sa *src, const struct sa *dst, struct mbuf *mb, void *arg) { + struct sip_contact contact; struct sipnot *not = arg; (void)dst; - return mbuf_printf(mb, "Contact: \r\n", - not->cuser, src, sip_transp_param(tp)); + sip_contact_set(&contact, not->cuser, src, tp); + + return mbuf_printf(mb, "%H", sip_contact_print, &contact); } @@ -282,16 +284,19 @@ int sipnot_notify(struct sipnot *not) int sipnot_reply(struct sipnot *not, const struct sip_msg *msg, uint16_t scode, const char *reason) { + struct sip_contact contact; uint32_t expires; expires = (uint32_t)(tmr_get_expire(¬->tmr) / 1000); + sip_contact_set(&contact, not->cuser, &msg->dst, msg->tp); + return sip_treplyf(NULL, NULL, not->sip, msg, true, scode, reason, - "Contact: \r\n" + "%H" "Expires: %u\r\n" "Content-Length: 0\r\n" "\r\n", - not->cuser, &msg->dst, sip_transp_param(msg->tp), + sip_contact_print, &contact, expires); } diff --git a/src/sipevent/subscribe.c b/src/sipevent/subscribe.c index 237de75..fe6ba56 100644 --- a/src/sipevent/subscribe.c +++ b/src/sipevent/subscribe.c @@ -298,11 +298,13 @@ static void response_handler(int err, const struct sip_msg *msg, void *arg) static int send_handler(enum sip_transp tp, const struct sa *src, const struct sa *dst, struct mbuf *mb, void *arg) { + struct sip_contact contact; struct sipsub *sub = arg; (void)dst; - return mbuf_printf(mb, "Contact: \r\n", - sub->cuser, src, sip_transp_param(tp)); + sip_contact_set(&contact, sub->cuser, src, tp); + + return mbuf_printf(mb, "%H", sip_contact_print, &contact); } @@ -449,7 +451,7 @@ static int sipsub_alloc(struct sipsub **subp, struct sipevent_sock *sock, * @param event SIP Event to subscribe to * @param id SIP Event ID (optional) * @param expires Subscription expires value - * @param cuser Contact username + * @param cuser Contact username or URI * @param routev Optional route vector * @param routec Number of routes * @param authh Authentication handler @@ -496,7 +498,7 @@ int sipevent_subscribe(struct sipsub **subp, struct sipevent_sock *sock, * @param event SIP Event to subscribe to * @param id SIP Event ID (optional) * @param expires Subscription expires value - * @param cuser Contact username + * @param cuser Contact username or URI * @param authh Authentication handler * @param aarg Authentication handler argument * @param aref True to ref argument @@ -536,7 +538,7 @@ int sipevent_dsubscribe(struct sipsub **subp, struct sipevent_sock *sock, * @param uri SIP Request URI * @param from_name SIP From-header Name (optional) * @param from_uri SIP From-header URI - * @param cuser Contact username + * @param cuser Contact username or URI * @param routev Optional route vector * @param routec Number of routes * @param authh Authentication handler @@ -579,7 +581,7 @@ int sipevent_refer(struct sipsub **subp, struct sipevent_sock *sock, * @param subp Pointer to allocated SIP subscriber client * @param sock SIP Event socket * @param dlg Established SIP Dialog - * @param cuser Contact username + * @param cuser Contact username or URI * @param authh Authentication handler * @param aarg Authentication handler argument * @param aref True to ref argument diff --git a/src/sipreg/reg.c b/src/sipreg/reg.c index b3b039f..8a8faec 100644 --- a/src/sipreg/reg.c +++ b/src/sipreg/reg.c @@ -293,7 +293,7 @@ static int request(struct sipreg *reg, bool reset_ls) "Content-Length: 0\r\n" "\r\n", reg->regid > 0 - ? "Supported: outbound, path\r\n" : "", + ? "Supported: gruu, outbound, path\r\n" : "", reg->hdrs ? mbuf_buf(reg->hdrs) : NULL, reg->hdrs ? mbuf_get_left(reg->hdrs) : (size_t)0); } diff --git a/src/sipsess/accept.c b/src/sipsess/accept.c index d85dc17..b8d02f8 100644 --- a/src/sipsess/accept.c +++ b/src/sipsess/accept.c @@ -42,7 +42,7 @@ static void cancel_handler(void *arg) * @param msg Incoming SIP message * @param scode Response status code * @param reason Response reason phrase - * @param cuser Contact username + * @param cuser Contact username or URI * @param ctype Session content-type * @param desc Content description (e.g. SDP) * @param authh SIP Authentication handler @@ -103,17 +103,20 @@ int sipsess_accept(struct sipsess **sessp, struct sipsess_sock *sock, if (scode >= 200) err = sipsess_reply_2xx(sess, msg, scode, reason, desc, fmt, &ap); - else + else { + struct sip_contact contact; + + sip_contact_set(&contact, sess->cuser, &msg->dst, msg->tp); + err = sip_treplyf(&sess->st, NULL, sess->sip, msg, true, scode, reason, - "Contact: \r\n" + "%H" "%v" "%s%s%s" "Content-Length: %zu\r\n" "\r\n" "%b", - sess->cuser, &msg->dst, - sip_transp_param(msg->tp), + sip_contact_print, &contact, fmt, &ap, desc ? "Content-Type: " : "", desc ? sess->ctype : "", @@ -121,6 +124,7 @@ int sipsess_accept(struct sipsess **sessp, struct sipsess_sock *sock, desc ? mbuf_get_left(desc) : (size_t)0, desc ? mbuf_buf(desc) : NULL, desc ? mbuf_get_left(desc) : (size_t)0); + } va_end(ap); @@ -151,6 +155,7 @@ int sipsess_accept(struct sipsess **sessp, struct sipsess_sock *sock, int sipsess_progress(struct sipsess *sess, uint16_t scode, const char *reason, struct mbuf *desc, const char *fmt, ...) { + struct sip_contact contact; va_list ap; int err; @@ -159,16 +164,17 @@ int sipsess_progress(struct sipsess *sess, uint16_t scode, const char *reason, va_start(ap, fmt); + sip_contact_set(&contact, sess->cuser, &sess->msg->dst, sess->msg->tp); + err = sip_treplyf(&sess->st, NULL, sess->sip, sess->msg, true, scode, reason, - "Contact: \r\n" + "%H" "%v" "%s%s%s" "Content-Length: %zu\r\n" "\r\n" "%b", - sess->cuser, &sess->msg->dst, - sip_transp_param(sess->msg->tp), + sip_contact_print, &contact, fmt, &ap, desc ? "Content-Type: " : "", desc ? sess->ctype : "", diff --git a/src/sipsess/connect.c b/src/sipsess/connect.c index fe97a51..5f6317e 100644 --- a/src/sipsess/connect.c +++ b/src/sipsess/connect.c @@ -25,11 +25,13 @@ static int invite(struct sipsess *sess); static int send_handler(enum sip_transp tp, const struct sa *src, const struct sa *dst, struct mbuf *mb, void *arg) { + struct sip_contact contact; struct sipsess *sess = arg; (void)dst; - return mbuf_printf(mb, "Contact: \r\n", - sess->cuser, src, sip_transp_param(tp)); + sip_contact_set(&contact, sess->cuser, src, tp); + + return mbuf_printf(mb, "%H", sip_contact_print, &contact); } @@ -156,7 +158,7 @@ static int invite(struct sipsess *sess) * @param to_uri To SIP uri * @param from_name From display name * @param from_uri From SIP uri - * @param cuser Contact username + * @param cuser Contact username or URI * @param routev Outbound route vector * @param routec Outbound route vector count * @param ctype Session content-type diff --git a/src/sipsess/modify.c b/src/sipsess/modify.c index 027871c..452115f 100644 --- a/src/sipsess/modify.c +++ b/src/sipsess/modify.c @@ -109,11 +109,13 @@ static void reinvite_resp_handler(int err, const struct sip_msg *msg, static int send_handler(enum sip_transp tp, const struct sa *src, const struct sa *dst, struct mbuf *mb, void *arg) { + struct sip_contact contact; struct sipsess *sess = arg; (void)dst; - return mbuf_printf(mb, "Contact: \r\n", - sess->cuser, src, sip_transp_param(tp)); + sip_contact_set(&contact, sess->cuser, src, tp); + + return mbuf_printf(mb, "%H", sip_contact_print, &contact); } diff --git a/src/sipsess/reply.c b/src/sipsess/reply.c index 40970ab..4c3aa6f 100644 --- a/src/sipsess/reply.c +++ b/src/sipsess/reply.c @@ -82,6 +82,7 @@ int sipsess_reply_2xx(struct sipsess *sess, const struct sip_msg *msg, const char *fmt, va_list *ap) { struct sipsess_reply *reply; + struct sip_contact contact; int err = ENOMEM; reply = mem_zalloc(sizeof(*reply), destructor); @@ -93,15 +94,17 @@ int sipsess_reply_2xx(struct sipsess *sess, const struct sip_msg *msg, reply->msg = mem_ref((void *)msg); reply->sess = sess; + sip_contact_set(&contact, sess->cuser, &msg->dst, msg->tp); + err = sip_treplyf(&sess->st, &reply->mb, sess->sip, msg, true, scode, reason, - "Contact: \r\n" + "%H" "%v" "%s%s%s" "Content-Length: %zu\r\n" "\r\n" "%b", - sess->cuser, &msg->dst, sip_transp_param(msg->tp), + sip_contact_print, &contact, fmt, ap, desc ? "Content-Type: " : "", desc ? sess->ctype : "",