2323
2424// internals -------------------------------------------------------------------
2525
26- typedef struct nano_stream_listener_s {
27- nng_stream * stream ;
28- nng_stream_listener * list ;
29- nng_tls_config * tls ;
30- } nano_stream_listener ;
26+ typedef enum nano_stream_typ {
27+ DIALER ,
28+ LISTENER
29+ } nano_stream_typ ;
3130
32- typedef struct nano_stream_dialer_s {
31+ typedef struct nano_stream_s {
3332 nng_stream * stream ;
34- nng_stream_dialer * dial ;
33+ nano_stream_typ type ;
34+ union {
35+ nng_stream_dialer * dial ;
36+ nng_stream_listener * list ;
37+ } endpoint ;
3538 nng_tls_config * tls ;
36- } nano_stream_dialer ;
39+ } nano_stream ;
3740
3841SEXP mk_error_ncurl (const int xc ) {
3942
@@ -52,28 +55,19 @@ SEXP mk_error_ncurl(const int xc) {
5255
5356// finalizers ------------------------------------------------------------------
5457
55- static void stream_listener_finalizer (SEXP xptr ) {
56-
57- if (R_ExternalPtrAddr (xptr ) == NULL ) return ;
58- nano_stream_listener * xp = (nano_stream_listener * ) R_ExternalPtrAddr (xptr );
59- nng_stream_close (xp -> stream );
60- nng_stream_listener_close (xp -> list );
61- nng_stream_free (xp -> stream );
62- nng_stream_listener_free (xp -> list );
63- if (xp -> tls != NULL )
64- nng_tls_config_free (xp -> tls );
65- R_Free (xp );
66-
67- }
68-
69- static void stream_dialer_finalizer (SEXP xptr ) {
58+ static void stream_finalizer (SEXP xptr ) {
7059
7160 if (R_ExternalPtrAddr (xptr ) == NULL ) return ;
72- nano_stream_dialer * xp = (nano_stream_dialer * ) R_ExternalPtrAddr (xptr );
61+ nano_stream * xp = (nano_stream * ) R_ExternalPtrAddr (xptr );
7362 nng_stream_close (xp -> stream );
74- nng_stream_dialer_close (xp -> dial );
7563 nng_stream_free (xp -> stream );
76- nng_stream_dialer_free (xp -> dial );
64+ if (xp -> type == DIALER ) {
65+ nng_stream_dialer_close (xp -> endpoint .dial );
66+ nng_stream_dialer_free (xp -> endpoint .dial );
67+ } else {
68+ nng_stream_listener_close (xp -> endpoint .list );
69+ nng_stream_listener_free (xp -> endpoint .list );
70+ }
7771 if (xp -> tls != NULL )
7872 nng_tls_config_free (xp -> tls );
7973 R_Free (xp );
@@ -374,8 +368,9 @@ SEXP rnng_stream_dial(SEXP url, SEXP textframes, SEXP tls) {
374368 const char * add = CHAR (STRING_ELT (url , 0 ));
375369 if (tls != R_NilValue && R_ExternalPtrTag (tls ) != nano_TlsSymbol )
376370 Rf_error ("'tls' is not a valid TLS Configuration" );
377- nano_stream_dialer * nsd = R_Calloc (1 , nano_stream_dialer );
378- nsd -> tls = NULL ;
371+ nano_stream * nst = R_Calloc (1 , nano_stream );
372+ nst -> type = DIALER ;
373+ nst -> tls = NULL ;
379374 nng_url * up ;
380375 nng_aio * aiop ;
381376 int xc , frames = 0 ;
@@ -384,35 +379,35 @@ SEXP rnng_stream_dial(SEXP url, SEXP textframes, SEXP tls) {
384379 if ((xc = nng_url_parse (& up , add )))
385380 goto exitlevel1 ;
386381
387- xc = nng_stream_dialer_alloc_url (& nsd -> dial , up );
382+ xc = nng_stream_dialer_alloc_url (& nst -> endpoint . dial , up );
388383 if (xc )
389384 goto exitlevel2 ;
390385
391386 if (!strcmp (up -> u_scheme , "ws" ) || !strcmp (up -> u_scheme , "wss" )) {
392387 frames = * NANO_INTEGER (textframes );
393388 if (frames &&
394- ((xc = nng_stream_dialer_set_bool (nsd -> dial , "ws:recv-text" , 1 )) ||
395- (xc = nng_stream_dialer_set_bool (nsd -> dial , "ws:send-text" , 1 ))))
389+ ((xc = nng_stream_dialer_set_bool (nst -> endpoint . dial , "ws:recv-text" , 1 )) ||
390+ (xc = nng_stream_dialer_set_bool (nst -> endpoint . dial , "ws:send-text" , 1 ))))
396391 goto exitlevel3 ;
397392 }
398393
399394 if (!strcmp (up -> u_scheme , "wss" )) {
400395
401396 if (tls == R_NilValue ) {
402- if ((xc = nng_tls_config_alloc (& nsd -> tls , NNG_TLS_MODE_CLIENT )))
397+ if ((xc = nng_tls_config_alloc (& nst -> tls , NNG_TLS_MODE_CLIENT )))
403398 goto exitlevel3 ;
404399
405- if ((xc = nng_tls_config_server_name (nsd -> tls , up -> u_hostname )) ||
406- (xc = nng_tls_config_auth_mode (nsd -> tls , NNG_TLS_AUTH_MODE_NONE )) ||
407- (xc = nng_stream_dialer_set_ptr (nsd -> dial , NNG_OPT_TLS_CONFIG , nsd -> tls )))
400+ if ((xc = nng_tls_config_server_name (nst -> tls , up -> u_hostname )) ||
401+ (xc = nng_tls_config_auth_mode (nst -> tls , NNG_TLS_AUTH_MODE_NONE )) ||
402+ (xc = nng_stream_dialer_set_ptr (nst -> endpoint . dial , NNG_OPT_TLS_CONFIG , nst -> tls )))
408403 goto exitlevel4 ;
409404 } else {
410405
411- nsd -> tls = (nng_tls_config * ) R_ExternalPtrAddr (tls );
412- nng_tls_config_hold (nsd -> tls );
406+ nst -> tls = (nng_tls_config * ) R_ExternalPtrAddr (tls );
407+ nng_tls_config_hold (nst -> tls );
413408
414- if ((xc = nng_tls_config_server_name (nsd -> tls , up -> u_hostname )) ||
415- (xc = nng_stream_dialer_set_ptr (nsd -> dial , NNG_OPT_TLS_CONFIG , nsd -> tls )))
409+ if ((xc = nng_tls_config_server_name (nst -> tls , up -> u_hostname )) ||
410+ (xc = nng_stream_dialer_set_ptr (nst -> endpoint . dial , NNG_OPT_TLS_CONFIG , nst -> tls )))
416411 goto exitlevel4 ;
417412 }
418413
@@ -421,18 +416,18 @@ SEXP rnng_stream_dial(SEXP url, SEXP textframes, SEXP tls) {
421416 if ((xc = nng_aio_alloc (& aiop , NULL , NULL )))
422417 goto exitlevel4 ;
423418
424- nng_stream_dialer_dial (nsd -> dial , aiop );
419+ nng_stream_dialer_dial (nst -> endpoint . dial , aiop );
425420 nng_aio_wait (aiop );
426421 if ((xc = nng_aio_result (aiop )))
427422 goto exitlevel5 ;
428423
429- nsd -> stream = nng_aio_get_output (aiop , 0 );
424+ nst -> stream = nng_aio_get_output (aiop , 0 );
430425
431426 nng_aio_free (aiop );
432427 nng_url_free (up );
433428
434- PROTECT (sd = R_MakeExternalPtr (nsd , nano_StreamSymbol , R_NilValue ));
435- R_RegisterCFinalizerEx (sd , stream_dialer_finalizer , TRUE);
429+ PROTECT (sd = R_MakeExternalPtr (nst , nano_StreamSymbol , R_NilValue ));
430+ R_RegisterCFinalizerEx (sd , stream_finalizer , TRUE);
436431 Rf_setAttrib (sd , R_ModeSymbol , Rf_mkString ("dialer" ));
437432 Rf_setAttrib (sd , nano_StateSymbol , Rf_mkString ("opened" ));
438433 Rf_setAttrib (sd , nano_UrlSymbol , url );
@@ -449,14 +444,14 @@ SEXP rnng_stream_dial(SEXP url, SEXP textframes, SEXP tls) {
449444 exitlevel5 :
450445 nng_aio_free (aiop );
451446 exitlevel4 :
452- if (nsd -> tls != NULL )
453- nng_tls_config_free (nsd -> tls );
447+ if (nst -> tls != NULL )
448+ nng_tls_config_free (nst -> tls );
454449 exitlevel3 :
455- nng_stream_dialer_free (nsd -> dial );
450+ nng_stream_dialer_free (nst -> endpoint . dial );
456451 exitlevel2 :
457452 nng_url_free (up );
458453 exitlevel1 :
459- R_Free (nsd );
454+ R_Free (nst );
460455 ERROR_OUT (xc );
461456
462457}
@@ -466,8 +461,9 @@ SEXP rnng_stream_listen(SEXP url, SEXP textframes, SEXP tls) {
466461 const char * add = CHAR (STRING_ELT (url , 0 ));
467462 if (tls != R_NilValue && R_ExternalPtrTag (tls ) != nano_TlsSymbol )
468463 Rf_error ("'tls' is not a valid TLS Configuration" );
469- nano_stream_listener * nsl = R_Calloc (1 , nano_stream_listener );
470- nsl -> tls = NULL ;
464+ nano_stream * nst = R_Calloc (1 , nano_stream );
465+ nst -> type = LISTENER ;
466+ nst -> tls = NULL ;
471467 nng_url * up ;
472468 nng_aio * aiop ;
473469 int xc , frames = 0 ;
@@ -476,57 +472,57 @@ SEXP rnng_stream_listen(SEXP url, SEXP textframes, SEXP tls) {
476472 if ((xc = nng_url_parse (& up , add )))
477473 goto exitlevel1 ;
478474
479- xc = nng_stream_listener_alloc_url (& nsl -> list , up );
475+ xc = nng_stream_listener_alloc_url (& nst -> endpoint . list , up );
480476 if (xc )
481477 goto exitlevel2 ;
482478
483479 if (!strcmp (up -> u_scheme , "ws" ) || !strcmp (up -> u_scheme , "wss" )) {
484480 frames = * NANO_INTEGER (textframes );
485481 if (frames &&
486- ((xc = nng_stream_listener_set_bool (nsl -> list , "ws:recv-text" , 1 )) ||
487- (xc = nng_stream_listener_set_bool (nsl -> list , "ws:send-text" , 1 ))))
482+ ((xc = nng_stream_listener_set_bool (nst -> endpoint . list , "ws:recv-text" , 1 )) ||
483+ (xc = nng_stream_listener_set_bool (nst -> endpoint . list , "ws:send-text" , 1 ))))
488484 goto exitlevel3 ;
489485 }
490486
491487 if (!strcmp (up -> u_scheme , "wss" )) {
492488
493489 if (tls == R_NilValue ) {
494- if ((xc = nng_tls_config_alloc (& nsl -> tls , NNG_TLS_MODE_SERVER )))
490+ if ((xc = nng_tls_config_alloc (& nst -> tls , NNG_TLS_MODE_SERVER )))
495491 goto exitlevel3 ;
496492
497- if ((xc = nng_tls_config_auth_mode (nsl -> tls , NNG_TLS_AUTH_MODE_NONE )) ||
498- (xc = nng_stream_listener_set_ptr (nsl -> list , NNG_OPT_TLS_CONFIG , nsl -> tls )))
493+ if ((xc = nng_tls_config_auth_mode (nst -> tls , NNG_TLS_AUTH_MODE_NONE )) ||
494+ (xc = nng_stream_listener_set_ptr (nst -> endpoint . list , NNG_OPT_TLS_CONFIG , nst -> tls )))
499495 goto exitlevel4 ;
500496 } else {
501497
502- nsl -> tls = (nng_tls_config * ) R_ExternalPtrAddr (tls );
503- nng_tls_config_hold (nsl -> tls );
498+ nst -> tls = (nng_tls_config * ) R_ExternalPtrAddr (tls );
499+ nng_tls_config_hold (nst -> tls );
504500
505- if ((xc = nng_tls_config_server_name (nsl -> tls , up -> u_hostname )) ||
506- (xc = nng_stream_listener_set_ptr (nsl -> list , NNG_OPT_TLS_CONFIG , nsl -> tls )))
501+ if ((xc = nng_tls_config_server_name (nst -> tls , up -> u_hostname )) ||
502+ (xc = nng_stream_listener_set_ptr (nst -> endpoint . list , NNG_OPT_TLS_CONFIG , nst -> tls )))
507503 goto exitlevel4 ;
508504 }
509505
510506 }
511507
512- if ((xc = nng_stream_listener_listen (nsl -> list )))
508+ if ((xc = nng_stream_listener_listen (nst -> endpoint . list )))
513509 goto exitlevel4 ;
514510
515511 if ((xc = nng_aio_alloc (& aiop , NULL , NULL )))
516512 goto exitlevel4 ;
517513
518- nng_stream_listener_accept (nsl -> list , aiop );
514+ nng_stream_listener_accept (nst -> endpoint . list , aiop );
519515 nng_aio_wait (aiop );
520516 if ((xc = nng_aio_result (aiop )))
521517 goto exitlevel5 ;
522518
523- nsl -> stream = nng_aio_get_output (aiop , 0 );
519+ nst -> stream = nng_aio_get_output (aiop , 0 );
524520
525521 nng_aio_free (aiop );
526522 nng_url_free (up );
527523
528- PROTECT (sl = R_MakeExternalPtr (nsl , nano_StreamSymbol , R_NilValue ));
529- R_RegisterCFinalizerEx (sl , stream_listener_finalizer , TRUE);
524+ PROTECT (sl = R_MakeExternalPtr (nst , nano_StreamSymbol , R_NilValue ));
525+ R_RegisterCFinalizerEx (sl , stream_finalizer , TRUE);
530526 Rf_setAttrib (sl , R_ModeSymbol , Rf_mkString ("listener" ));
531527 Rf_setAttrib (sl , nano_StateSymbol , Rf_mkString ("opened" ));
532528 Rf_setAttrib (sl , nano_UrlSymbol , url );
@@ -543,14 +539,14 @@ SEXP rnng_stream_listen(SEXP url, SEXP textframes, SEXP tls) {
543539 exitlevel5 :
544540 nng_aio_free (aiop );
545541 exitlevel4 :
546- if (nsl -> tls != NULL )
547- nng_tls_config_free (nsl -> tls );
542+ if (nst -> tls != NULL )
543+ nng_tls_config_free (nst -> tls );
548544 exitlevel3 :
549- nng_stream_listener_free (nsl -> list );
545+ nng_stream_listener_free (nst -> endpoint . list );
550546 exitlevel2 :
551547 nng_url_free (up );
552548 exitlevel1 :
553- R_Free (nsl );
549+ R_Free (nst );
554550 ERROR_OUT (xc );
555551
556552}
@@ -560,13 +556,7 @@ SEXP rnng_stream_close(SEXP stream) {
560556 if (R_ExternalPtrTag (stream ) != nano_StreamSymbol )
561557 Rf_error ("'stream' is not a valid or active Stream" );
562558
563- SEXP mode = Rf_getAttrib (stream , R_ModeSymbol );
564- const char * mod = CHAR (STRING_ELT (mode , 0 ));
565- if (!strncmp (mod , "dialer" , 6 )) {
566- stream_dialer_finalizer (stream );
567- } else {
568- stream_listener_finalizer (stream );
569- }
559+ stream_finalizer (stream );
570560 R_SetExternalPtrTag (stream , R_NilValue );
571561 R_ClearExternalPtr (stream );
572562 Rf_setAttrib (stream , nano_StateSymbol , Rf_mkString ("closed" ));
0 commit comments