blob: 1e1594f8610445b9dc098f1d1d6f6f2390263a3a [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
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
22static 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
33void 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
53uint64_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 */
71int 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}