@@ -749,6 +749,170 @@ ngx_rtmp_add_prefix_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
749749}
750750
751751
752+ static u_char *
753+ ngx_rtmp_strlechr (u_char * p , u_char * last )
754+ {
755+ while (p != last ) {
756+ if ((* p >= '0' && * p <= '9' ) ||
757+ (* p >= 'a' && * p <= 'z' ) ||
758+ (* p >= 'A' && * p <= 'Z' ) ||
759+ * p == '_' )
760+ {
761+ p ++ ;
762+ continue ;
763+ }
764+
765+ return p ;
766+ }
767+
768+ return NULL ;
769+ }
770+
771+
772+ ngx_int_t
773+ ngx_rtmp_variable_transform_index (ngx_conf_t * cf , ngx_str_t * origin , ngx_str_t * target )
774+ {
775+ u_char * p , * e , * t ;
776+ u_char * wp , * we ;
777+ ngx_str_t str , var ;
778+ ngx_buf_t * buf ;
779+ ngx_int_t index ;
780+
781+ p = origin -> data ;
782+ e = origin -> data + origin -> len ;
783+
784+ buf = ngx_create_temp_buf (cf -> pool , 2 * origin -> len );
785+ if (buf == NULL ) {
786+ return NGX_ERROR ;
787+ }
788+
789+ wp = buf -> start ;
790+ we = buf -> end ;
791+
792+ while (p < e ) {
793+ t = ngx_strlchr (p , e , '$' );
794+ if (t == NULL ) {
795+ t = e ;
796+ }
797+ str .data = p ;
798+ str .len = t - p ;
799+ wp = ngx_slprintf (wp , we , "%V" , & str );
800+
801+ if (t == e ) {
802+ break ;
803+ }
804+
805+ var .data = ++ t ;
806+ t = ngx_rtmp_strlechr (t , e );
807+ if (t == NULL ) {
808+ t = e ;
809+ }
810+ var .len = t - var .data ;
811+
812+ index = ngx_rtmp_get_variable_index (cf , & var );
813+ if (index == NGX_ERROR ) {
814+ return NGX_ERROR ;
815+ }
816+
817+ wp = ngx_slprintf (wp , we , "$%d" , index );
818+ p = t ;
819+ }
820+
821+ target -> data = buf -> start ;
822+ target -> len = wp - buf -> start ;
823+
824+ return NGX_OK ;
825+ }
826+
827+
828+ ngx_int_t
829+ ngx_rtmp_fetch_variable (ngx_rtmp_session_t * s , ngx_pool_t * pool ,
830+ ngx_str_t * origin , ngx_str_t * target )
831+ {
832+ ngx_rtmp_variable_value_t * vv ;
833+ u_char * p , * e , * t ;
834+ u_char * wp , * we ;
835+ ngx_chain_t * ch , * cl , * ct ;
836+ u_char * pt ;
837+ ngx_uint_t length ;
838+ ngx_int_t index ;
839+ ngx_str_t var ;
840+
841+ length = 0 ;
842+ p = origin -> data ;
843+ e = p + origin -> len ;
844+
845+ #define NGX_RTMP_NOTIFY_BUF (__start__ , __end__ ) \
846+ ct = cl; \
847+ pt = ngx_pcalloc(pool, sizeof(ngx_chain_t) + \
848+ sizeof(ngx_buf_t) + __end__ - __start__); \
849+ cl = (ngx_chain_t*)pt; \
850+ cl->buf = (ngx_buf_t*)(pt + sizeof(ngx_chain_t)); \
851+ cl->buf->start = \
852+ cl->buf->pos = \
853+ cl->buf->last = pt + sizeof(ngx_chain_t) + sizeof(ngx_buf_t); \
854+ if (ch == NULL) { \
855+ ch = cl; \
856+ } else { \
857+ ct->next = cl; \
858+ } \
859+ cl->buf->last = ngx_cpymem(cl->buf->pos, __start__, __end__ - __start__); \
860+ length += __end__ - __start__
861+
862+ ch = cl = ct = NULL ;
863+
864+ while (p < e ) {
865+ t = ngx_strlchr (p , e , '$' );
866+ if (t == NULL ) {
867+ t = e ;
868+ }
869+ NGX_RTMP_NOTIFY_BUF (p , t );
870+ if (t == e ) {
871+ break ;
872+ }
873+
874+ var .data = ++ t ;
875+ t = ngx_rtmp_strlechr (t , e );
876+ if (t == NULL ) {
877+ t = e ;
878+ }
879+ var .len = t - var .data ;
880+ index = ngx_atoi (var .data , var .len );
881+ vv = ngx_rtmp_get_indexed_variable (s , index );
882+ if (vv == NULL ) {
883+ p = t ;
884+ continue ;
885+ }
886+ wp = vv -> data ;
887+ we = vv -> data + vv -> len ;
888+
889+ NGX_RTMP_NOTIFY_BUF (wp , we );
890+ p = t ;
891+ }
892+
893+ #undef NGX_RTMP_NOTIFY_BUF
894+
895+ wp = ngx_pcalloc (pool , length );
896+ we = wp ;
897+
898+ for (ct = ch ; ct ;) {
899+ we = ngx_cpymem (we , ct -> buf -> pos , ct -> buf -> last - ct -> buf -> pos );
900+ cl = ct -> next ;
901+ ngx_pfree (pool , ct );
902+ ct = cl ;
903+ }
904+ target -> data = wp ;
905+ target -> len = we - wp ;
906+ if (target -> len != length ) {
907+ ngx_log_error (NGX_LOG_ERR , s -> connection -> log , 0 ,
908+ "variable: fetch_variable| target len = %d, content length = %d" ,
909+ target -> len , length );
910+ return NGX_ERROR ;
911+ }
912+
913+ return NGX_OK ;
914+ }
915+
752916ngx_rtmp_variable_t *
753917ngx_rtmp_add_variable (ngx_conf_t * cf , ngx_str_t * name , ngx_uint_t flags )
754918{
@@ -829,9 +993,10 @@ ngx_rtmp_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
829993ngx_int_t
830994ngx_rtmp_get_variable_index (ngx_conf_t * cf , ngx_str_t * name )
831995{
832- ngx_uint_t i ;
833- ngx_rtmp_variable_t * v ;
996+ ngx_uint_t i = 0 s , n ;
997+ ngx_rtmp_variable_t * v , * av ;
834998 ngx_rtmp_core_main_conf_t * cmcf ;
999+ ngx_hash_key_t * key ;
8351000
8361001 if (name -> len == 0 ) {
8371002 ngx_conf_log_error (NGX_LOG_EMERG , cf , 0 ,
@@ -842,6 +1007,7 @@ ngx_rtmp_get_variable_index(ngx_conf_t *cf, ngx_str_t *name)
8421007 cmcf = ngx_rtmp_conf_get_module_main_conf (cf , ngx_rtmp_core_module );
8431008
8441009 v = cmcf -> variables .elts ;
1010+ key = cmcf -> variables_keys -> keys .elts ;
8451011
8461012 if (v == NULL ) {
8471013 if (ngx_array_init (& cmcf -> variables , cf -> pool , 4 ,
@@ -876,10 +1042,30 @@ ngx_rtmp_get_variable_index(ngx_conf_t *cf, ngx_str_t *name)
8761042
8771043 ngx_strlow (v -> name .data , name -> data , name -> len );
8781044
1045+ for (n = 0 ; n < cmcf -> variables_keys -> keys .nelts ; n ++ ) {
1046+ av = key [n ].value ;
1047+ if (av -> get_handler
1048+ && v -> name .len == key [n ].key .len
1049+ && ngx_strncmp (v -> name .data , key [n ].key .data , v -> name .len ) == 0 )
1050+ {
1051+ v -> get_handler = av -> get_handler ;
1052+ v -> data = av -> data ;
1053+ av -> flags = NGX_RTMP_VAR_INDEXED ;
1054+ v -> flags = av -> flags ;
1055+ av -> index = i ;
1056+
1057+ goto next ;
1058+ }
1059+ }
1060+
1061+ ngx_log_error (NGX_LOG_EMERG , cf -> log , 0 ,
1062+ "variables: get_variable_index| unknown \"%V\" variable" ,
1063+ & v -> name );
1064+
1065+ return NGX_ERROR ;
1066+
1067+ next :
8791068 v -> set_handler = NULL ;
880- v -> get_handler = NULL ;
881- v -> data = 0 ;
882- v -> flags = 0 ;
8831069 v -> index = cmcf -> variables .nelts - 1 ;
8841070
8851071 return v -> index ;
0 commit comments