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(®->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(®->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, ®->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(®->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] ? ¶ms[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