James Kuszmaul | 82f6c04 | 2021-01-17 11:30:16 -0800 | [diff] [blame] | 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 | |
| 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 | |
| 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 | |
| 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 | */ |
| 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 | } |