1 /**
2 * @file sip/keepalive.c SIP Keepalive
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6
7 #include <string.h>
8 #include <re_types.h>
9 #include <re_fmt.h>
10 #include <re_mem.h>
11 #include <re_mbuf.h>
12 #include <re_sa.h>
13 #include <re_list.h>
14 #include <re_sys.h>
15 #include <re_uri.h>
16 #include <re_udp.h>
17 #include <re_msg.h>
18 #include <re_sip.h>
19 #include "sip.h"
20
21
destructor(void * arg)22 static void destructor(void *arg)
23 {
24 struct sip_keepalive *ka = arg;
25
26 if (ka->kap)
27 *ka->kap = NULL;
28
29 list_unlink(&ka->le);
30 }
31
32
sip_keepalive_signal(struct list * kal,int err)33 void sip_keepalive_signal(struct list *kal, int err)
34 {
35 struct le *le = list_head(kal);
36
37 while (le) {
38
39 struct sip_keepalive *ka = le->data;
40 sip_keepalive_h *kah = ka->kah;
41 void *arg = ka->arg;
42
43 le = le->next;
44
45 list_unlink(&ka->le);
46 mem_deref(ka);
47
48 kah(err, arg);
49 }
50 }
51
52
sip_keepalive_wait(uint32_t interval)53 uint64_t sip_keepalive_wait(uint32_t interval)
54 {
55 return interval * (800 + rand_u16() % 201);
56 }
57
58
59 /**
60 * Start a keepalive handler on a SIP transport
61 *
62 * @param kap Pointer to allocated keepalive object
63 * @param sip SIP Stack instance
64 * @param msg SIP Message
65 * @param interval Keepalive interval in seconds
66 * @param kah Keepalive handler
67 * @param arg Handler argument
68 *
69 * @return 0 if success, otherwise errorcode
70 */
sip_keepalive_start(struct sip_keepalive ** kap,struct sip * sip,const struct sip_msg * msg,uint32_t interval,sip_keepalive_h * kah,void * arg)71 int sip_keepalive_start(struct sip_keepalive **kap, struct sip *sip,
72 const struct sip_msg *msg, uint32_t interval,
73 sip_keepalive_h *kah, void *arg)
74 {
75 struct sip_keepalive *ka;
76 int err;
77
78 if (!kap || !sip || !msg || !kah)
79 return EINVAL;
80
81 ka = mem_zalloc(sizeof(*ka), destructor);
82 if (!ka)
83 return ENOMEM;
84
85 ka->kah = kah;
86 ka->arg = arg;
87
88 switch (msg->tp) {
89
90 case SIP_TRANSP_UDP:
91 err = sip_keepalive_udp(ka, sip, (struct udp_sock *)msg->sock,
92 &msg->src, interval);
93 break;
94
95 case SIP_TRANSP_TCP:
96 case SIP_TRANSP_TLS:
97 err = sip_keepalive_tcp(ka, (struct sip_conn *)msg->sock,
98 interval);
99 break;
100
101 default:
102 err = EPROTONOSUPPORT;
103 break;
104 }
105
106 if (err) {
107 mem_deref(ka);
108 }
109 else {
110 ka->kap = kap;
111 *kap = ka;
112 }
113
114 return err;
115 }
116