usrloc: ability to send keep alive requests
authorDaniel-Constantin Mierla <miconda@gmail.com>
Thu, 26 Mar 2020 15:18:17 +0000 (16:18 +0100)
committerDaniel-Constantin Mierla <miconda@gmail.com>
Thu, 26 Mar 2020 15:18:17 +0000 (16:18 +0100)
- GH #2223
- work in progress

src/modules/usrloc/udomain.c
src/modules/usrloc/ul_keepalive.c [new file with mode: 0644]
src/modules/usrloc/ul_keepalive.h [new file with mode: 0644]
src/modules/usrloc/usrloc_mod.c

index 8050a21..59ddff9 100644 (file)
@@ -41,6 +41,7 @@
 #include "utime.h"
 #include "usrloc.h"
 #include "ul_callback.h"
+#include "ul_keepalive.h"
 #include "urecord.h"
 
 extern int ul_rm_expired_delay;
@@ -1228,6 +1229,7 @@ void mem_timer_udomain(udomain_t* _d, int istart, int istep)
                                ptr = ptr->next;
                                mem_delete_urecord(_d, t);
                        } else {
+                               ul_ka_urecord(ptr);
                                ptr = ptr->next;
                        }
                }
diff --git a/src/modules/usrloc/ul_keepalive.c b/src/modules/usrloc/ul_keepalive.c
new file mode 100644 (file)
index 0000000..7b6521a
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Usrloc module - keepalive
+ *
+ * Copyright (C) 2020 Asipto.com
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "../../core/dprint.h"
+#include "../../core/ut.h"
+#include "../../core/resolve.h"
+#include "../../core/forward.h"
+#include "../../core/parser/parse_uri.h"
+#include "../../core/parser/parse_from.h"
+#include "../../core/parser/parse_to.h"
+#include "../../core/parser/parse_rr.h"
+
+#include "ul_keepalive.h"
+
+static int ul_ka_send(str *kamsg, dest_info_t *kadst);
+
+/**
+ * 
+_KAMETHOD_ _URI_ SIP/2.0\r\n
+Via: SIP/2.0/_PROTO_ _IP_:_PORT_\r\n
+__KAROUTES__
+From: <_KAFROM_>;tag=_KAFROMTAG_\r\n
+To: <sip:_AOR_>\r\n
+Call-ID: _KACALLID_\r\n
+CSeq: 1 _KAMETHOD_\r\n
+Content-Length: 0\r\n\r\n"
+
+*/
+
+#define ULKA_CALLID_PREFIX "ksrulka-"
+#define ULKA_CALLID_PREFIX_LEN (sizeof(ULKA_CALLID_PREFIX) - 1)
+
+#define ULKA_MSG "%.*s %.*s SIP/2.0\r\n" \
+  "Via: SIP/2.0/%.*s %.*s:%.*s;branch=z9hG4bKx.%u.%u.0\r\n" \
+  "%.*s%.*s" \
+  "From: <%.*s>;tag=%.*s-%x-%lx-%x-%x.%x\r\n" \
+  "To: <sip:%.*s%s%.*s>\r\n" \
+  "Call-ID: " ULKA_CALLID_PREFIX "%u.%u\r\n" \
+  "CSeq: 80 %.*s\r\n" \
+  "Content-Length: 0\r\n\r\n"
+
+extern str ul_ka_from;
+extern str ul_ka_domain;
+extern str ul_ka_method;
+extern int ul_ka_mode;
+extern unsigned int nat_bflag;
+
+static unsigned int _ul_ka_counter = 0;
+
+int ul_ka_urecord(urecord_t *ur)
+{
+       ucontact_t *uc;
+#define ULKA_BUF_SIZE 2048
+       char kabuf[ULKA_BUF_SIZE];
+       int kabuf_len;
+       str kamsg;
+       str vaddr;
+       str vport;
+       str sdst = STR_NULL;
+       str sproto = STR_NULL;
+       sip_uri_t duri;
+       char dproto;
+       struct hostent *he;
+       socket_info_t *ssock;
+       dest_info_t idst;
+       unsigned int bcnt = 0;
+       int aortype = 0;
+       int i;
+       struct timeval tv;
+
+       if (ul_ka_mode == 0) {
+               return 0;
+       }
+       LM_DBG("keepalive for aor: %.*s\n", ur->aor.len, ur->aor.s);
+
+       for(i=0; i<ur->aor.len; i++) {
+               if(ur->aor.s[i] == '@') {
+                       aortype = 1;
+                       break;
+               }
+       }
+       _ul_ka_counter++;
+       for (uc = ur->contacts; uc != NULL; uc = uc->next) {
+               if (uc->c.len <= 0) {
+                       continue;
+               }
+               if(ul_ka_mode == 2) {
+                       /* keepalive for natted contacts only */
+                       if (nat_bflag == 0) {
+                               continue;
+                       }
+                       if ((uc->cflags & nat_bflag) != nat_bflag) {
+                               continue;
+                       }
+               }
+               if(uc->received.len > 0) {
+                       sdst = uc->received;
+               } else {
+                       if (uc->path.len > 0) {
+                               if(get_path_dst_uri(&uc->path, &sdst) < 0) {
+                                       LM_ERR("failed to get first uri for path\n");
+                                       continue;
+                               }
+                       } else {
+                               sdst = uc->c;
+                       }
+               }
+               if(parse_uri(sdst.s, sdst.len, &duri) < 0) {
+                       LM_ERR("cannot parse next hop uri\n");
+                       continue;
+               }
+
+               if(duri.port_no == 0) {
+                       duri.port_no = SIP_PORT;
+               }
+               dproto = duri.proto;
+               he = sip_resolvehost(&duri.host, &duri.port_no, &dproto);
+               if(he == NULL) {
+                       LM_ERR("can't resolve_host\n");
+                       continue;
+               }
+               init_dest_info(&idst);
+               hostent2su(&idst.to, he, 0, duri.port_no);
+               ssock = uc->sock;
+               if(ssock == NULL) {
+                       ssock = get_send_socket(0, &idst.to, dproto);
+               }
+               if(ssock == NULL) {
+                       LM_ERR("cannot get sending socket\n");
+                       continue;
+               }
+               idst.proto = dproto;
+               idst.send_sock = ssock;
+
+               if(ssock->useinfo.name.len > 0) {
+                       vaddr = ssock->useinfo.name;
+               } else {
+                       vaddr = ssock->address_str;
+               }
+               if(ssock->useinfo.port_no > 0) {
+                       vport = ssock->useinfo.port_no_str;
+               } else {
+                       vport = ssock->port_no_str;
+               }
+               get_valid_proto_string(dproto, 1, 1, &sproto);
+
+               bcnt++;
+               gettimeofday(&tv, NULL);
+               kabuf_len = snprintf(kabuf, ULKA_BUF_SIZE - 1, ULKA_MSG,
+                               ul_ka_method.len, ul_ka_method.s,
+                               uc->c.len, uc->c.s,
+                               sproto.len, sproto.s,
+                               vaddr.len, vaddr.s,
+                               vport.len, vport.s,
+                               _ul_ka_counter, bcnt,
+                               (uc->path.len>0)?uc->path.len:0,
+                               (uc->path.len>0)?uc->path.s:"",
+                               (uc->path.len>0)?2:0,
+                               (uc->path.len>0)?"\r\n":"",
+                               ul_ka_from.len, ul_ka_from.s,
+                               uc->ruid.len, uc->ruid.s, ur->aorhash,
+                               tv.tv_sec, tv.tv_usec, _ul_ka_counter, bcnt,
+                               ur->aor.len, ur->aor.s,
+                               (aortype==1)?"":"@",
+                               (aortype==1)?0:ul_ka_domain.len, (aortype==1)?"":ul_ka_domain.s,
+                               _ul_ka_counter, bcnt,
+                               ul_ka_method.len, ul_ka_method.s);
+               if(kabuf_len<=0 || kabuf_len>=ULKA_BUF_SIZE) {
+                       LM_ERR("failed to print the keepalive request\n");
+               } else {
+                       LM_DBG("keepalive request (len: %d) [[\n%.*s]]\n",
+                                       kabuf_len, kabuf_len, kabuf);
+                       kamsg.s = kabuf;
+                       kamsg.len = kabuf_len;
+                       ul_ka_send(&kamsg, &idst);
+               }
+
+       }
+       return 0;
+}
+
+static int ul_ka_send(str *kamsg, dest_info_t *kadst)
+{ 
+       if (kadst->proto == PROTO_UDP) {
+               return udp_send(kadst, kamsg->s, kamsg->len);
+       }
+
+#ifdef USE_TCP
+       else if(kadst->proto == PROTO_TCP) {
+               /*tcp*/
+               kadst->id=0;
+               return tcp_send(kadst, 0, kamsg->s, kamsg->len);
+       }
+#endif
+#ifdef USE_TLS
+       else if(kadst->proto == PROTO_TLS) {
+               /*tls*/
+               kadst->id=0;
+               return tcp_send(kadst, 0, kamsg->s, kamsg->len);
+       }
+#endif
+#ifdef USE_SCTP
+       else if(kadst->proto == PROTO_SCTP) {
+               /*sctp*/
+               return sctp_core_msg_send(kadst, kamsg->s, kamsg->len);
+       }
+#endif
+       else {
+               LM_ERR("unknown proto [%d] for sending keepalive\n",
+                               kadst->proto);
+               return -1;
+       }
+}
\ No newline at end of file
diff --git a/src/modules/usrloc/ul_keepalive.h b/src/modules/usrloc/ul_keepalive.h
new file mode 100644 (file)
index 0000000..1eaea7f
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Usrloc module - keepalive
+ *
+ * Copyright (C) 2020 Asipto.com
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _UL_KEEPALIVE_H_
+#define _UL_KEEPALIVE_H_
+
+#include "urecord.h"
+
+int ul_ka_urecord(urecord_t *ur);
+
+#endif
\ No newline at end of file
index eb05305..9b9c3f6 100644 (file)
@@ -116,6 +116,11 @@ int ul_version_table = 1;
 
 str ul_xavp_contact_name = {0};
 
+str ul_ka_from = str_init("sip:server@kamailio.org");
+str ul_ka_domain = str_init("kamailio.org");
+str ul_ka_method = str_init("OPTIONS");
+int ul_ka_mode = 0;
+
 /* sruid to get internal uid for mi/rpc commands */
 sruid_t _ul_sruid;
 
@@ -242,6 +247,10 @@ static param_export_t params[] = {
        {"db_timer_clean",      PARAM_INT, &ul_db_timer_clean},
        {"rm_expired_delay",    PARAM_INT, &ul_rm_expired_delay},
        {"version_table",       PARAM_INT, &ul_version_table},
+       {"ka_mode",             PARAM_INT, &ul_ka_mode},
+       {"ka_from",             PARAM_STR, &ul_ka_from},
+       {"ka_domain",             PARAM_STR, &ul_ka_domain},
+       {"ka_method",             PARAM_STR, &ul_ka_method},
        {0, 0, 0}
 };