diff --git a/src/modules/lwsc/lwsc_mod.c b/src/modules/lwsc/lwsc_mod.c index 0281bf6b34f..8e5e068bdde 100644 --- a/src/modules/lwsc/lwsc_mod.c +++ b/src/modules/lwsc/lwsc_mod.c @@ -117,8 +117,6 @@ static void mod_destroy(void) return; } -#define WSURL_PATH_SIZE 64 - /** * */ @@ -126,11 +124,13 @@ typedef struct lwsc_endpoint { str wsurl; /* clone of wsurl for libwebsockets parsing with dropping in zeros */ str wsurlparse; - char wsurlpath[WSURL_PATH_SIZE]; + str wsurlpath; + str wsproto; /* first LWS_PRE bytes must preserved for headers */ str wbuf; str rbuf; int tlson; + struct lws_protocols protocols[2]; struct lws_context_creation_info crtinfo; struct lws_client_connect_info coninfo; struct lws_context *wsctx; @@ -343,16 +343,6 @@ static int ksr_lwsc_callback(struct lws *wsi, enum lws_callback_reasons reason, return lws_callback_http_dummy(wsi, reason, user, in, len); } -/** - * - */ -static struct lws_protocols _lwsc_protocols[] = { - { - "kmsg", ksr_lwsc_callback, - 0, 0, 0, NULL, 0 - }, - { NULL, NULL, 0, 0, 0, NULL, 0} -}; /** * @@ -412,21 +402,29 @@ static void* ksr_lwsc_thread(void *arg) /** * */ -static lwsc_endpoint_t* lwsc_get_endpoint(str *wsurl) +static lwsc_endpoint_t* lwsc_get_endpoint(str *wsurl, str *wsproto) { lwsc_endpoint_t *ep; int ssize = 0; const char *urlproto = NULL; const char *urlpath = NULL; int s = 0; + str lwsproto = STR_NULL; + + if(wsproto!=NULL && wsproto->s!=NULL && wsproto->len>0) { + lwsproto = *wsproto; + } else { + lwsproto = _lwsc_protocol; + } for(ep=_lwsc_endpoints; ep!=NULL; ep=ep->next) { - if(ep->wsurl.len==wsurl->len - && strncmp(ep->wsurl.s, wsurl->s, wsurl->len)==0) { + if(ep->wsurl.len==wsurl->len && ep->wsproto.len==lwsproto.len + && strncmp(ep->wsurl.s, wsurl->s, wsurl->len)==0 + && strncmp(ep->wsproto.s, lwsproto.s, lwsproto.len)==0) { return ep; } } - ssize = sizeof(lwsc_endpoint_t) + 2*(wsurl->len + 1); + ssize = sizeof(lwsc_endpoint_t) + 3*(wsurl->len + 1) + (lwsproto.len + 1); ep = (lwsc_endpoint_t*)pkg_malloc(ssize); if(ep==NULL) { PKG_MEM_ERROR; @@ -439,19 +437,24 @@ static lwsc_endpoint_t* lwsc_get_endpoint(str *wsurl) ep->wsurlparse.s = ep->wsurl.s + wsurl->len + 1; memcpy(ep->wsurlparse.s, wsurl->s, wsurl->len); ep->wsurlparse.len = wsurl->len; + ep->wsurlpath.s = ep->wsurlparse.s + wsurl->len + 1; + ep->wsurlpath.s[0] = '/'; + ep->wsurlpath.len = 1; + ep->wsproto.s = ep->wsurlpath.s + wsurl->len + 1; + memcpy(ep->wsproto.s, lwsproto.s, lwsproto.len); + ep->wsproto.len = lwsproto.len; + if (lws_parse_uri(ep->wsurlparse.s, &urlproto, &ep->coninfo.address, &ep->coninfo.port, &urlpath)) { LM_ERR("cannot parse ws url [%.*s]\n", wsurl->len, wsurl->s); goto error; } - if(strlen(urlpath) > WSURL_PATH_SIZE - 4) { - LM_ERR("url path is too long [%s]\n", urlpath); - goto error; + if(urlpath!=NULL && strlen(urlpath) > 0) { + strcpy(ep->wsurlpath.s + 1, urlpath); + ep->wsurlpath.len = strlen(ep->wsurlpath.s); } - ep->wsurlpath[0] = '/'; - strcpy(ep->wsurlpath+1, urlpath); - ep->coninfo.path = (const char*)ep->wsurlpath; + ep->coninfo.path = (const char*)ep->wsurlpath.s; if (strcmp(urlproto, "wss")==0 || strcmp(urlproto, "https")==0) { ep->tlson = 1; @@ -461,7 +464,9 @@ static lwsc_endpoint_t* lwsc_get_endpoint(str *wsurl) if(ep->tlson==1) { ep->crtinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; } - ep->crtinfo.protocols = _lwsc_protocols; + ep->protocols[0].name = ep->wsproto.s; + ep->protocols[0].callback = ksr_lwsc_callback; + ep->crtinfo.protocols = ep->protocols; ep->crtinfo.gid = -1; ep->crtinfo.uid = -1; ep->crtinfo.ws_ping_pong_interval = 5; /*secs*/ @@ -483,7 +488,7 @@ static lwsc_endpoint_t* lwsc_get_endpoint(str *wsurl) ep->coninfo.host = ep->coninfo.address; ep->coninfo.origin = ep->coninfo.address; ep->coninfo.ietf_version_or_minus_one = -1; - ep->coninfo.protocol = _lwsc_protocols[0].name; + ep->coninfo.protocol = ep->protocols[0].name; if(ep->tlson==1) { ep->coninfo.ssl_connection = LCCSCF_USE_SSL | LCCSCF_ALLOW_SELFSIGNED | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK; @@ -523,7 +528,8 @@ static lwsc_endpoint_t* lwsc_get_endpoint(str *wsurl) /** * */ -static int ki_lwsc_request(sip_msg_t* msg, str* wsurl, str* data) +static int lwsc_api_request(str* wsurl, str *wsproto, str* sdata, + str *rdata, int rtimeout) { lwsc_endpoint_t *ep = NULL; str wbuf = STR_NULL; @@ -531,13 +537,14 @@ static int ki_lwsc_request(sip_msg_t* msg, str* wsurl, str* data) int icount = 0; if(wsurl==NULL || wsurl->s==NULL || wsurl->len<=0 - || data==NULL || data->s==NULL || data->len<=0) { + || sdata==NULL || sdata->s==NULL || sdata->len<=0 + || rdata==NULL) { LM_ERR("invalid parameters\n"); return -1; } lwsc_set_logging(); - ep = lwsc_get_endpoint(wsurl); + ep = lwsc_get_endpoint(wsurl, wsproto); if(ep==NULL) { LM_ERR("endpoint not available\n"); return -1; @@ -552,21 +559,17 @@ static int ki_lwsc_request(sip_msg_t* msg, str* wsurl, str* data) } } - wbuf.s = (char*)pkg_malloc(LWS_PRE + data->len + 1); + wbuf.s = (char*)pkg_malloc(LWS_PRE + sdata->len + 1); if(wbuf.s==NULL) { PKG_MEM_ERROR; return -1; } - memset(wbuf.s, 0, LWS_PRE + data->len + 1); - memcpy(wbuf.s + LWS_PRE, data->s, data->len); - wbuf.len = LWS_PRE + data->len; + memset(wbuf.s, 0, LWS_PRE + sdata->len + 1); + memcpy(wbuf.s + LWS_PRE, sdata->s, sdata->len); + wbuf.len = LWS_PRE + sdata->len; - /* clear local receive buffer */ - if(_lwsc_rdata_buf.s!=NULL) { - pkg_free(_lwsc_rdata_buf.s); - _lwsc_rdata_buf.s = NULL; - _lwsc_rdata_buf.len = 0; - } + rdata->s = NULL; + rdata->len = 0; pthread_mutex_lock(&ep->wslock); if(ep->rbuf.s!=NULL) { @@ -589,18 +592,18 @@ static int ki_lwsc_request(sip_msg_t* msg, str* wsurl, str* data) do { pthread_mutex_lock(&ep->wslock); if(ep->rbuf.s!=NULL) { - _lwsc_rdata_buf = ep->rbuf; + *rdata = ep->rbuf; ep->rbuf.s = NULL; ep->rbuf.len = 0; } pthread_mutex_unlock(&ep->wslock); - if(_lwsc_rdata_buf.s==NULL) { + if(rdata->s==NULL) { usleep(10000); } rcount += 10000; - } while(rcount<_lwsc_timeout_read && _lwsc_rdata_buf.s==NULL); + } while(rcounts==NULL); - if(_lwsc_rdata_buf.s==NULL) { + if(rdata->s==NULL) { LM_DBG("no response data received before timeout\n"); return -2; } @@ -608,6 +611,22 @@ static int ki_lwsc_request(sip_msg_t* msg, str* wsurl, str* data) return 1; } +/** + * + */ +static int ki_lwsc_request(sip_msg_t* msg, str* wsurl, str* data) +{ + /* clear global per-process receive buffer */ + if(_lwsc_rdata_buf.s!=NULL) { + pkg_free(_lwsc_rdata_buf.s); + _lwsc_rdata_buf.s = NULL; + _lwsc_rdata_buf.len = 0; + } + + return lwsc_api_request(wsurl, NULL, data, &_lwsc_rdata_buf, + _lwsc_timeout_read); +} + /** * */ @@ -645,7 +664,7 @@ static int ki_lwsc_notify(sip_msg_t* msg, str* wsurl, str* data) lwsc_set_logging(); - ep = lwsc_get_endpoint(wsurl); + ep = lwsc_get_endpoint(wsurl, NULL); if(ep==NULL) { LM_ERR("endpoint not available\n"); return -1;