http_async_client: add parameters to enable/set tcp keepalive
authorFederico Cabiddu <federico.cabiddu@gmail.com>
Wed, 6 Feb 2019 16:16:18 +0000 (17:16 +0100)
committerFederico Cabiddu <federico.cabiddu@gmail.com>
Wed, 6 Feb 2019 16:16:18 +0000 (17:16 +0100)
src/modules/http_async_client/async_http.c
src/modules/http_async_client/async_http.h
src/modules/http_async_client/hm_hash.h
src/modules/http_async_client/http_async_client_mod.c
src/modules/http_async_client/http_multi.c

index 87a62ea..9117778 100644 (file)
@@ -307,6 +307,9 @@ void notification_socket_cb(int fd, short event, void *arg)
        query_params.tls_verify_peer = aq->query_params.tls_verify_peer;
        query_params.tls_verify_host = aq->query_params.tls_verify_host;
        query_params.authmethod = aq->query_params.authmethod;
+       query_params.tcp_keepalive = aq->query_params.tcp_keepalive;
+       query_params.tcp_ka_idle = aq->query_params.tcp_ka_idle;
+       query_params.tcp_ka_interval = aq->query_params.tcp_ka_interval;
 
        for (i = 0 ; i < aq->query_params.headers.len ; i++) {
                query_params.headers = curl_slist_append(query_params.headers, aq->query_params.headers.t[i]);
@@ -495,6 +498,9 @@ int async_send_query(sip_msg_t *msg, str *query, str *cbname)
        aq->query_params.tls_verify_host = ah_params.tls_verify_host;
        aq->query_params.suspend_transaction = suspend;
        aq->query_params.timeout = ah_params.timeout;
+       aq->query_params.tcp_keepalive = ah_params.tcp_keepalive;
+       aq->query_params.tcp_ka_idle = ah_params.tcp_ka_idle;
+       aq->query_params.tcp_ka_interval = ah_params.tcp_ka_interval;
        aq->query_params.headers = ah_params.headers;
        aq->query_params.method = ah_params.method;
        aq->query_params.authmethod = ah_params.authmethod;
@@ -641,6 +647,9 @@ void set_query_params(struct query_params *p) {
        p->timeout = http_timeout;
        p->method = AH_METH_DEFAULT;
        p->authmethod = default_authmethod;
+       p->tcp_keepalive = tcp_keepalive;
+       p->tcp_ka_idle = tcp_ka_idle;
+       p->tcp_ka_interval = tcp_ka_interval;
 
        if (p->tls_client_cert) {
                shm_free(p->tls_client_cert);
index 7514f20..9324f46 100644 (file)
@@ -50,6 +50,9 @@
 extern int num_workers;
 
 extern int http_timeout; /* query timeout in ms */
+extern int tcp_keepalive; 
+extern int tcp_ka_idle; 
+extern int tcp_ka_interval; 
 
 extern struct sip_msg *ah_reply;
 extern str ah_error;
@@ -98,6 +101,9 @@ struct query_params {
        unsigned int authmethod;
        char* username;
        char* password;
+       unsigned int tcp_keepalive;
+       unsigned int tcp_ka_idle;
+       unsigned int tcp_ka_interval;
 };
 
 extern struct query_params ah_params;
index a6ad061..868662d 100644 (file)
@@ -78,6 +78,9 @@ typedef struct hm_params {
        unsigned int authmethod;
        char* username;
        char* password;
+       int tcp_keepalive;
+       int tcp_ka_idle;
+       int tcp_ka_interval;
 } http_m_params_t;
 
 typedef struct http_m_cell
index 96d428c..7bfbb00 100644 (file)
@@ -66,6 +66,9 @@ extern unsigned int q_idx;
 extern char q_id[MAX_ID_LEN+1];
 
 int http_timeout = 500; /* query timeout in ms */
+int tcp_keepalive = 0; /* TCP keepalives (default disabled) */
+int tcp_ka_idle = 0; /* TCP keep-alive idle time wait */
+int tcp_ka_interval = 0; /* TCP keep-alive interval */
 int hash_size = 2048;
 int tls_version = 0; // Use default SSL version in HTTPS requests (see curl/curl.h)
 int tls_verify_host = 1; // By default verify host in HTTPS requests
@@ -121,7 +124,8 @@ enum http_req_name_t {
        E_HRN_TLS_CA_PATH, E_HRN_TLS_CLIENT_KEY,
        E_HRN_TLS_CLIENT_CERT, E_HRN_SUSPEND,
        E_HRN_BODY, E_HRN_AUTHMETHOD, E_HRN_USERNAME,
-       E_HRN_PASSWORD
+       E_HRN_PASSWORD, E_HRN_TCP_KA, E_HRN_TCP_KA_IDLE,
+       E_HRN_TCP_KA_INTERVAL
 };
 
 static cmd_export_t cmds[]={
@@ -143,6 +147,9 @@ static param_export_t params[]={
        {"tls_ca_path",                 PARAM_STRING,   &tls_ca_path},
        {"memory_manager",              PARAM_STRING,   &memory_manager},
        {"authmethod",                  PARAM_INT,              &default_authmethod },
+       {"tcp_keepalive",           INT_PARAM,          &tcp_keepalive},
+       {"tcp_ka_idle",         INT_PARAM,              &tcp_ka_idle},
+       {"tcp_ka_interval",         INT_PARAM,          &tcp_ka_interval},
        {0, 0, 0}
 };
 
@@ -249,6 +256,13 @@ static int mod_init(void)
        tls_verify_host = tls_verify_host?1:0;
        tls_verify_peer = tls_verify_peer?1:0;
 
+       if (tcp_keepalive) {
+               LM_INFO("TCP keepalives enabled\n");
+       }
+       /* check tcp keepalive parameters */
+       if ((tcp_ka_idle > 0 || tcp_ka_interval > 0) && !(tcp_keepalive > 0)) {
+               LM_WARN("either 'tcp_ka_idle' or 'tcp_ka_interval' are set but 'tcp_keepalive' is disabled: they will be ignored\n");
+       }
        /* init http parameters list */
        init_query_params(&ah_params);
 
@@ -556,6 +570,8 @@ static int ah_parse_req_name(pv_spec_p sp, str *in) {
                                sp->pvp.pvn.u.isname.name.n = E_HRN_TIMEOUT;
                        else if(strncmp(in->s, "suspend", 7)==0)
                                sp->pvp.pvn.u.isname.name.n = E_HRN_SUSPEND;
+                       else if(strncmp(in->s, "ka-idle", 7)==0)
+                               sp->pvp.pvn.u.isname.name.n = E_HRN_TCP_KA_IDLE;
                        else goto error;
                        break;
                case 8:
@@ -565,6 +581,11 @@ static int ah_parse_req_name(pv_spec_p sp, str *in) {
                                sp->pvp.pvn.u.isname.name.n = E_HRN_PASSWORD;
                        else goto error;
                        break;
+               case 9:
+                       if(strncmp(in->s, "keepalive", 9)==0)
+                               sp->pvp.pvn.u.isname.name.n = E_HRN_TCP_KA;
+                       else goto error;
+                       break;
                case 10:
                        if(strncmp(in->s, "authmethod", 10)==0)
                                sp->pvp.pvn.u.isname.name.n = E_HRN_AUTHMETHOD;
@@ -573,6 +594,8 @@ static int ah_parse_req_name(pv_spec_p sp, str *in) {
                case 11:
                        if(strncmp(in->s, "tls_ca_path", 11)==0)
                                sp->pvp.pvn.u.isname.name.n = E_HRN_TLS_CA_PATH;
+                       else if(strncmp(in->s, "ka-interval", 11)==0)
+                               sp->pvp.pvn.u.isname.name.n = E_HRN_TCP_KA_INTERVAL;
                        else goto error;
                        break;
                case 14:
@@ -723,6 +746,41 @@ static int ah_set_req(struct sip_msg* msg, pv_param_t *param,
                        set_query_cparam(&ah_params.password, tval->rs);
                }
                break;
+       case E_HRN_TCP_KA:
+               if (tval) {
+                       if (!(tval->flags & PV_VAL_INT)) {
+                               LM_ERR("invalid value type for $http_req(keepalive)\n");
+                               return -1;
+                       }
+                       ah_params.tcp_keepalive = tval->ri;
+               } else {
+                       ah_params.tcp_keepalive = tcp_keepalive;
+               }
+               break;
+
+       case E_HRN_TCP_KA_IDLE:
+               if (tval) {
+                       if (!(tval->flags & PV_VAL_INT)) {
+                               LM_ERR("invalid value type for $http_req(ka-idle)\n");
+                               return -1;
+                       }
+                       ah_params.tcp_ka_idle = tval->ri;
+               } else {
+                       ah_params.tcp_ka_idle = tcp_ka_idle;
+               }
+               break;
+
+       case E_HRN_TCP_KA_INTERVAL:
+               if (tval) {
+                       if (!(tval->flags & PV_VAL_INT)) {
+                               LM_ERR("invalid value type for $http_req(ka-interval)\n");
+                               return -1;
+                       }
+                       ah_params.tcp_ka_interval = tval->ri;
+               } else {
+                       ah_params.tcp_ka_interval = tcp_ka_interval;
+               }
+               break;
        }
 
        return 1;
@@ -755,4 +813,4 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2)
        pvra(&pv_api);
        sr_kemi_modules_add(sr_kemi_http_async_client_exports); 
        return 0;
-}
\ No newline at end of file
+}
index 1dd4b13..43936a7 100644 (file)
@@ -526,8 +526,24 @@ int new_request(str *query, http_m_params_t *query_params, http_multi_cbe_t cb,
        if (cell->params.password) {
                curl_easy_setopt(cell->easy, CURLOPT_PASSWORD, cell->params.password);
        }
+    
+    /* enable tcp keepalives for the handler */
+       if (cell->params.tcp_keepalive) {
+               LM_DBG("Enabling TCP keepalives\n");
+               curl_easy_setopt(cell->easy, CURLOPT_TCP_KEEPALIVE, 1L);
+               
+               if (cell->params.tcp_ka_idle) {
+                       curl_easy_setopt(cell->easy, CURLOPT_TCP_KEEPIDLE, cell->params.tcp_ka_idle);
+                       LM_DBG("CURLOPT_TCP_KEEPIDLE set to %d\n", cell->params.tcp_ka_idle);
+               }
 
-       LM_DBG("Adding easy %p to multi %p (%.*s)\n", cell->easy, g->multi, query->len, query->s);
+               if (cell->params.tcp_ka_interval) {
+                       curl_easy_setopt(cell->easy, CURLOPT_TCP_KEEPINTVL, cell->params.tcp_ka_interval);
+                       LM_DBG("CURLOPT_TCP_KEEPINTERVAL set to %d\n", cell->params.tcp_ka_interval);
+               }
+       }
+       
+    LM_DBG("Adding easy %p to multi %p (%.*s)\n", cell->easy, g->multi, query->len, query->s);
        rc = curl_multi_add_handle(g->multi, cell->easy);
        if (check_mcode(rc, cell->error) < 0) {
                LM_ERR("error adding curl handler: %s\n", cell->error);