Browse code

lwsc: store lws protocols structure in endpoint

- more flexibility in specifying ws sub-protocols per connection

Daniel-Constantin Mierla authored on 24/03/2021 15:26:34
Showing 1 changed files
... ...
@@ -117,8 +117,6 @@ static void mod_destroy(void)
117 117
 	return;
118 118
 }
119 119
 
120
-#define WSURL_PATH_SIZE 64
121
-
122 120
 /**
123 121
  *
124 122
  */
... ...
@@ -126,11 +124,13 @@ typedef struct lwsc_endpoint {
126 124
 	str wsurl;
127 125
 	/* clone of wsurl for libwebsockets parsing with dropping in zeros */
128 126
 	str wsurlparse;
129
-	char wsurlpath[WSURL_PATH_SIZE];
127
+	str wsurlpath;
128
+	str wsproto;
130 129
 	/* first LWS_PRE bytes must preserved for headers */
131 130
 	str wbuf;
132 131
 	str rbuf;
133 132
 	int tlson;
133
+	struct lws_protocols protocols[2];
134 134
 	struct lws_context_creation_info crtinfo;
135 135
 	struct lws_client_connect_info coninfo;
136 136
 	struct lws_context *wsctx;
... ...
@@ -343,16 +343,6 @@ done:
343 343
 	return lws_callback_http_dummy(wsi, reason, user, in, len);
344 344
 }
345 345
 
346
-/**
347
- *
348
- */
349
-static struct lws_protocols _lwsc_protocols[] = {
350
-	{
351
-		"kmsg", ksr_lwsc_callback,
352
-		0, 0, 0, NULL, 0
353
-	},
354
-	{ NULL, NULL, 0, 0, 0, NULL, 0}
355
-};
356 346
 
357 347
 /**
358 348
  *
... ...
@@ -412,21 +402,29 @@ static void* ksr_lwsc_thread(void *arg)
412 402
 /**
413 403
  *
414 404
  */
415
-static lwsc_endpoint_t* lwsc_get_endpoint(str *wsurl)
405
+static lwsc_endpoint_t* lwsc_get_endpoint(str *wsurl, str *wsproto)
416 406
 {
417 407
 	lwsc_endpoint_t *ep;
418 408
 	int ssize = 0;
419 409
 	const char *urlproto = NULL;
420 410
 	const char *urlpath = NULL;
421 411
 	int s = 0;
412
+	str lwsproto = STR_NULL;
413
+
414
+	if(wsproto!=NULL && wsproto->s!=NULL && wsproto->len>0) {
415
+		lwsproto = *wsproto;
416
+	} else {
417
+		lwsproto = _lwsc_protocol;
418
+	}
422 419
 
423 420
 	for(ep=_lwsc_endpoints; ep!=NULL; ep=ep->next) {
424
-		if(ep->wsurl.len==wsurl->len
425
-				&& strncmp(ep->wsurl.s, wsurl->s, wsurl->len)==0) {
421
+		if(ep->wsurl.len==wsurl->len && ep->wsproto.len==lwsproto.len
422
+				&& strncmp(ep->wsurl.s, wsurl->s, wsurl->len)==0
423
+				&& strncmp(ep->wsproto.s, lwsproto.s, lwsproto.len)==0) {
426 424
 			return ep;
427 425
 		}
428 426
 	}
429
-	ssize = sizeof(lwsc_endpoint_t) + 2*(wsurl->len + 1);
427
+	ssize = sizeof(lwsc_endpoint_t) + 3*(wsurl->len + 1) + (lwsproto.len + 1);
430 428
 	ep = (lwsc_endpoint_t*)pkg_malloc(ssize);
431 429
 	if(ep==NULL) {
432 430
 		PKG_MEM_ERROR;
... ...
@@ -439,19 +437,24 @@ static lwsc_endpoint_t* lwsc_get_endpoint(str *wsurl)
439 437
 	ep->wsurlparse.s = ep->wsurl.s + wsurl->len + 1;
440 438
 	memcpy(ep->wsurlparse.s, wsurl->s, wsurl->len);
441 439
 	ep->wsurlparse.len = wsurl->len;
440
+	ep->wsurlpath.s = ep->wsurlparse.s + wsurl->len + 1;
441
+	ep->wsurlpath.s[0] = '/';
442
+	ep->wsurlpath.len = 1;
443
+	ep->wsproto.s = ep->wsurlpath.s + wsurl->len + 1;
444
+	memcpy(ep->wsproto.s, lwsproto.s, lwsproto.len);
445
+	ep->wsproto.len = lwsproto.len;
446
+
442 447
 
443 448
 	if (lws_parse_uri(ep->wsurlparse.s, &urlproto, &ep->coninfo.address,
444 449
 				&ep->coninfo.port, &urlpath)) {
445 450
 		LM_ERR("cannot parse ws url [%.*s]\n", wsurl->len, wsurl->s);
446 451
 		goto error;
447 452
 	}
448
-	if(strlen(urlpath) > WSURL_PATH_SIZE - 4) {
449
-		LM_ERR("url path is too long [%s]\n", urlpath);
450
-		goto error;
453
+	if(urlpath!=NULL && strlen(urlpath) > 0) {
454
+		strcpy(ep->wsurlpath.s + 1, urlpath);
455
+		ep->wsurlpath.len = strlen(ep->wsurlpath.s);
451 456
 	}
452
-	ep->wsurlpath[0] = '/';
453
-	strcpy(ep->wsurlpath+1, urlpath);
454
-	ep->coninfo.path = (const char*)ep->wsurlpath;
457
+	ep->coninfo.path = (const char*)ep->wsurlpath.s;
455 458
 
456 459
 	if (strcmp(urlproto, "wss")==0 || strcmp(urlproto, "https")==0) {
457 460
 		ep->tlson = 1;
... ...
@@ -461,7 +464,9 @@ static lwsc_endpoint_t* lwsc_get_endpoint(str *wsurl)
461 464
 	if(ep->tlson==1) {
462 465
 		ep->crtinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
463 466
 	}
464
-	ep->crtinfo.protocols = _lwsc_protocols;
467
+	ep->protocols[0].name = ep->wsproto.s;
468
+	ep->protocols[0].callback = ksr_lwsc_callback;
469
+	ep->crtinfo.protocols = ep->protocols;
465 470
 	ep->crtinfo.gid = -1;
466 471
 	ep->crtinfo.uid = -1;
467 472
 	ep->crtinfo.ws_ping_pong_interval = 5; /*secs*/
... ...
@@ -483,7 +488,7 @@ static lwsc_endpoint_t* lwsc_get_endpoint(str *wsurl)
483 488
 	ep->coninfo.host = ep->coninfo.address;
484 489
 	ep->coninfo.origin = ep->coninfo.address;
485 490
 	ep->coninfo.ietf_version_or_minus_one = -1;
486
-	ep->coninfo.protocol = _lwsc_protocols[0].name;
491
+	ep->coninfo.protocol = ep->protocols[0].name;
487 492
 	if(ep->tlson==1) {
488 493
 		ep->coninfo.ssl_connection = LCCSCF_USE_SSL | LCCSCF_ALLOW_SELFSIGNED
489 494
 			| LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
... ...
@@ -523,7 +528,8 @@ error:
523 528
 /**
524 529
  *
525 530
  */
526
-static int ki_lwsc_request(sip_msg_t* msg, str* wsurl, str* data)
531
+static int lwsc_api_request(str* wsurl, str *wsproto, str* sdata,
532
+		str *rdata, int rtimeout)
527 533
 {
528 534
 	lwsc_endpoint_t *ep = NULL;
529 535
 	str wbuf = STR_NULL;
... ...
@@ -531,13 +537,14 @@ static int ki_lwsc_request(sip_msg_t* msg, str* wsurl, str* data)
531 537
 	int icount = 0;
532 538
 
533 539
 	if(wsurl==NULL || wsurl->s==NULL || wsurl->len<=0
534
-			|| data==NULL || data->s==NULL || data->len<=0) {
540
+			|| sdata==NULL || sdata->s==NULL || sdata->len<=0
541
+			|| rdata==NULL) {
535 542
 		LM_ERR("invalid parameters\n");
536 543
 		return -1;
537 544
 	}
538 545
 
539 546
 	lwsc_set_logging();
540
-	ep = lwsc_get_endpoint(wsurl);
547
+	ep = lwsc_get_endpoint(wsurl, wsproto);
541 548
 	if(ep==NULL) {
542 549
 		LM_ERR("endpoint not available\n");
543 550
 		return -1;
... ...
@@ -552,21 +559,17 @@ static int ki_lwsc_request(sip_msg_t* msg, str* wsurl, str* data)
552 559
 		}
553 560
 	}
554 561
 
555
-	wbuf.s = (char*)pkg_malloc(LWS_PRE + data->len + 1);
562
+	wbuf.s = (char*)pkg_malloc(LWS_PRE + sdata->len + 1);
556 563
 	if(wbuf.s==NULL) {
557 564
 		PKG_MEM_ERROR;
558 565
 		return -1;
559 566
 	}
560
-	memset(wbuf.s, 0, LWS_PRE + data->len + 1);
561
-	memcpy(wbuf.s + LWS_PRE, data->s, data->len);
562
-	wbuf.len = LWS_PRE + data->len;
567
+	memset(wbuf.s, 0, LWS_PRE + sdata->len + 1);
568
+	memcpy(wbuf.s + LWS_PRE, sdata->s, sdata->len);
569
+	wbuf.len = LWS_PRE + sdata->len;
563 570
 
564
-	/* clear local receive buffer */
565
-	if(_lwsc_rdata_buf.s!=NULL) {
566
-		pkg_free(_lwsc_rdata_buf.s);
567
-		_lwsc_rdata_buf.s = NULL;
568
-		_lwsc_rdata_buf.len = 0;
569
-	}
571
+	rdata->s = NULL;
572
+	rdata->len = 0;
570 573
 
571 574
 	pthread_mutex_lock(&ep->wslock);
572 575
 	if(ep->rbuf.s!=NULL) {
... ...
@@ -589,18 +592,18 @@ static int ki_lwsc_request(sip_msg_t* msg, str* wsurl, str* data)
589 592
 	do {
590 593
 		pthread_mutex_lock(&ep->wslock);
591 594
 		if(ep->rbuf.s!=NULL) {
592
-			_lwsc_rdata_buf = ep->rbuf;
595
+			*rdata = ep->rbuf;
593 596
 			ep->rbuf.s = NULL;
594 597
 			ep->rbuf.len = 0;
595 598
 		}
596 599
 		pthread_mutex_unlock(&ep->wslock);
597
-		if(_lwsc_rdata_buf.s==NULL) {
600
+		if(rdata->s==NULL) {
598 601
 			usleep(10000);
599 602
 		}
600 603
 		rcount += 10000;
601
-	} while(rcount<_lwsc_timeout_read && _lwsc_rdata_buf.s==NULL);
604
+	} while(rcount<rtimeout && rdata->s==NULL);
602 605
 
603
-	if(_lwsc_rdata_buf.s==NULL) {
606
+	if(rdata->s==NULL) {
604 607
 		LM_DBG("no response data received before timeout\n");
605 608
 		return -2;
606 609
 	}
... ...
@@ -608,6 +611,22 @@ static int ki_lwsc_request(sip_msg_t* msg, str* wsurl, str* data)
608 611
 	return 1;
609 612
 }
610 613
 
614
+/**
615
+ *
616
+ */
617
+static int ki_lwsc_request(sip_msg_t* msg, str* wsurl, str* data)
618
+{
619
+	/* clear global per-process receive buffer */
620
+	if(_lwsc_rdata_buf.s!=NULL) {
621
+		pkg_free(_lwsc_rdata_buf.s);
622
+		_lwsc_rdata_buf.s = NULL;
623
+		_lwsc_rdata_buf.len = 0;
624
+	}
625
+
626
+	return lwsc_api_request(wsurl, NULL, data, &_lwsc_rdata_buf,
627
+			_lwsc_timeout_read);
628
+}
629
+
611 630
 /**
612 631
  *
613 632
  */
... ...
@@ -645,7 +664,7 @@ static int ki_lwsc_notify(sip_msg_t* msg, str* wsurl, str* data)
645 664
 
646 665
 	lwsc_set_logging();
647 666
 
648
-	ep = lwsc_get_endpoint(wsurl);
667
+	ep = lwsc_get_endpoint(wsurl, NULL);
649 668
 	if(ep==NULL) {
650 669
 		LM_ERR("endpoint not available\n");
651 670
 		return -1;