1 /**
2  * @file reg.c  Register Client
3  *
4  * Copyright (C) 2010 Creytiv.com
5  */
6 #include <re.h>
7 #include <baresip.h>
8 #include "core.h"
9 
10 
11 /** Register client */
12 struct reg {
13 	struct le le;                /**< Linked list element                */
14 	struct ua *ua;               /**< Pointer to parent UA object        */
15 	struct sipreg *sipreg;       /**< SIP Register client                */
16 	int id;                      /**< Registration ID (for SIP outbound) */
17 
18 	/* status: */
19 	uint16_t scode;              /**< Registration status code           */
20 	char *srv;                   /**< SIP Server id                      */
21 	int af;                      /**< Cached address family for SIP conn */
22 };
23 
24 
destructor(void * arg)25 static void destructor(void *arg)
26 {
27 	struct reg *reg = arg;
28 
29 	list_unlink(&reg->le);
30 	mem_deref(reg->sipreg);
31 	mem_deref(reg->srv);
32 }
33 
34 
sipmsg_af(const struct sip_msg * msg)35 static int sipmsg_af(const struct sip_msg *msg)
36 {
37 	struct sa laddr;
38 	int err = 0;
39 
40 	if (!msg)
41 		return AF_UNSPEC;
42 
43 	switch (msg->tp) {
44 
45 	case SIP_TRANSP_UDP:
46 		err = udp_local_get(msg->sock, &laddr);
47 		break;
48 
49 	case SIP_TRANSP_TCP:
50 	case SIP_TRANSP_TLS:
51 		err = tcp_conn_local_get(sip_msg_tcpconn(msg), &laddr);
52 		break;
53 
54 	default:
55 		return AF_UNSPEC;
56 	}
57 
58 	return err ? AF_UNSPEC : sa_af(&laddr);
59 }
60 
61 
af_name(int af)62 static const char *af_name(int af)
63 {
64 	switch (af) {
65 
66 	case AF_INET:  return "v4";
67 	case AF_INET6: return "v6";
68 	default:       return "v?";
69 	}
70 }
71 
72 
sip_auth_handler(char ** username,char ** password,const char * realm,void * arg)73 static int sip_auth_handler(char **username, char **password,
74 			    const char *realm, void *arg)
75 {
76 	struct account *acc = arg;
77 	return account_auth(acc, username, password, realm);
78 }
79 
80 
contact_handler(const struct sip_hdr * hdr,const struct sip_msg * msg,void * arg)81 static bool contact_handler(const struct sip_hdr *hdr,
82 			    const struct sip_msg *msg, void *arg)
83 {
84 	struct reg *reg = arg;
85 	struct sip_addr addr;
86 	(void)msg;
87 
88 	if (sip_addr_decode(&addr, &hdr->val))
89 		return false;
90 
91 	/* match our contact */
92 	return 0 == pl_strcasecmp(&addr.uri.user, ua_local_cuser(reg->ua));
93 }
94 
95 
register_handler(int err,const struct sip_msg * msg,void * arg)96 static void register_handler(int err, const struct sip_msg *msg, void *arg)
97 {
98 	struct reg *reg = arg;
99 	const struct sip_hdr *hdr;
100 
101 	if (err) {
102 		warning("reg: %s: Register: %m\n", ua_aor(reg->ua), err);
103 
104 		reg->scode = 999;
105 
106 		ua_event(reg->ua, UA_EVENT_REGISTER_FAIL, NULL, "%m", err);
107 		return;
108 	}
109 
110 	hdr = sip_msg_hdr(msg, SIP_HDR_SERVER);
111 	if (hdr) {
112 		reg->srv = mem_deref(reg->srv);
113 		(void)pl_strdup(&reg->srv, &hdr->val);
114 	}
115 
116 	if (200 <= msg->scode && msg->scode <= 299) {
117 
118 		uint32_t n_bindings;
119 
120 		n_bindings = sip_msg_hdr_count(msg, SIP_HDR_CONTACT);
121 		reg->af    = sipmsg_af(msg);
122 
123 		if (msg->scode != reg->scode) {
124 			ua_printf(reg->ua, "{%d/%s/%s} %u %r (%s)"
125 				  " [%u binding%s]\n",
126 				  reg->id, sip_transp_name(msg->tp),
127 				  af_name(reg->af), msg->scode, &msg->reason,
128 				  reg->srv, n_bindings,
129 				  1==n_bindings?"":"s");
130 		}
131 
132 		reg->scode = msg->scode;
133 
134 		hdr = sip_msg_hdr_apply(msg, true, SIP_HDR_CONTACT,
135 					contact_handler, reg);
136 		if (hdr) {
137 			struct sip_addr addr;
138 			struct pl pval;
139 
140 			if (0 == sip_addr_decode(&addr, &hdr->val) &&
141 			    0 == msg_param_decode(&addr.params, "pub-gruu",
142 						  &pval)) {
143 				ua_pub_gruu_set(reg->ua, &pval);
144 			}
145 		}
146 
147 		ua_event(reg->ua, UA_EVENT_REGISTER_OK, NULL, "%u %r",
148 			 msg->scode, &msg->reason);
149 	}
150 	else if (msg->scode >= 300) {
151 
152 		warning("reg: %s: %u %r (%s)\n", ua_aor(reg->ua),
153 			msg->scode, &msg->reason, reg->srv);
154 
155 		reg->scode = msg->scode;
156 
157 		ua_event(reg->ua, UA_EVENT_REGISTER_FAIL, NULL, "%u %r",
158 			 msg->scode, &msg->reason);
159 	}
160 }
161 
162 
reg_add(struct list * lst,struct ua * ua,int regid)163 int reg_add(struct list *lst, struct ua *ua, int regid)
164 {
165 	struct reg *reg;
166 
167 	if (!lst || !ua)
168 		return EINVAL;
169 
170 	reg = mem_zalloc(sizeof(*reg), destructor);
171 	if (!reg)
172 		return ENOMEM;
173 
174 	reg->ua    = ua;
175 	reg->id    = regid;
176 
177 	list_append(lst, &reg->le, reg);
178 
179 	return 0;
180 }
181 
182 
reg_register(struct reg * reg,const char * reg_uri,const char * params,uint32_t regint,const char * outbound)183 int reg_register(struct reg *reg, const char *reg_uri, const char *params,
184 		 uint32_t regint, const char *outbound)
185 {
186 	struct account *acc;
187 	const char *routev[1];
188 	int err;
189 
190 	if (!reg || !reg_uri)
191 		return EINVAL;
192 
193 	reg->scode = 0;
194 	routev[0] = outbound;
195 	acc = ua_account(reg->ua);
196 
197 	reg->sipreg = mem_deref(reg->sipreg);
198 	err = sipreg_register(&reg->sipreg, uag_sip(), reg_uri,
199 			      ua_aor(reg->ua),
200 			      acc ? acc->dispname : NULL, ua_aor(reg->ua),
201 			      regint, ua_local_cuser(reg->ua),
202 			      routev[0] ? routev : NULL,
203 			      routev[0] ? 1 : 0,
204 			      reg->id,
205 			      sip_auth_handler, ua_account(reg->ua), true,
206 			      register_handler, reg,
207 			      params[0] ? &params[1] : NULL,
208 			      "Allow: %s\r\n", uag_allowed_methods());
209 	if (err)
210 		return err;
211 
212 	return 0;
213 }
214 
215 
reg_unregister(struct reg * reg)216 void reg_unregister(struct reg *reg)
217 {
218 	if (!reg)
219 		return;
220 
221 	reg->scode = 0;
222 	reg->af    = 0;
223 
224 	reg->sipreg = mem_deref(reg->sipreg);
225 }
226 
227 
reg_isok(const struct reg * reg)228 bool reg_isok(const struct reg *reg)
229 {
230 	if (!reg)
231 		return false;
232 
233 	return 200 <= reg->scode && reg->scode <= 299;
234 }
235 
236 
print_scode(uint16_t scode)237 static const char *print_scode(uint16_t scode)
238 {
239 	if (0 == scode)        return "\x1b[33m" "zzz" "\x1b[;m";
240 	else if (200 == scode) return "\x1b[32m" "OK " "\x1b[;m";
241 	else                   return "\x1b[31m" "ERR" "\x1b[;m";
242 }
243 
244 
reg_debug(struct re_printf * pf,const struct reg * reg)245 int reg_debug(struct re_printf *pf, const struct reg *reg)
246 {
247 	int err = 0;
248 
249 	if (!reg)
250 		return 0;
251 
252 	err |= re_hprintf(pf, "\nRegister client:\n");
253 	err |= re_hprintf(pf, " id:     %d\n", reg->id);
254 	err |= re_hprintf(pf, " scode:  %u (%s)\n",
255 			  reg->scode, print_scode(reg->scode));
256 	err |= re_hprintf(pf, " srv:    %s\n", reg->srv);
257 
258 	return err;
259 }
260 
261 
reg_status(struct re_printf * pf,const struct reg * reg)262 int reg_status(struct re_printf *pf, const struct reg *reg)
263 {
264 	if (!reg)
265 		return 0;
266 
267 	return re_hprintf(pf, " %s %s", print_scode(reg->scode), reg->srv);
268 }
269