@@ -788,7 +788,14 @@ ngx_rtmp_notify_parse_http_retcode(ngx_rtmp_session_t *s,
788
788
if (c >= (u_char )'0' && c <= (u_char )'9' ) {
789
789
ngx_log_debug1 (NGX_LOG_DEBUG_RTMP , s -> connection -> log , 0 ,
790
790
"notify: HTTP retcode: %dxx" , (int )(c - '0' ));
791
- return c == (u_char )'2' ? NGX_OK : NGX_ERROR ;
791
+ switch (c ) {
792
+ case (u_char ) '2' :
793
+ return NGX_OK ;
794
+ case (u_char ) '3' :
795
+ return NGX_AGAIN ;
796
+ default :
797
+ return NGX_ERROR ;
798
+ }
792
799
}
793
800
794
801
ngx_log_error (NGX_LOG_INFO , s -> connection -> log , 0 ,
@@ -813,39 +820,194 @@ ngx_rtmp_notify_parse_http_retcode(ngx_rtmp_session_t *s,
813
820
}
814
821
815
822
823
+ static ngx_int_t
824
+ ngx_rtmp_notify_parse_http_header (ngx_rtmp_session_t * s ,
825
+ ngx_chain_t * in , ngx_str_t * name , u_char * data , size_t len )
826
+ {
827
+ ngx_buf_t * b ;
828
+ ngx_int_t matched ;
829
+ u_char * p , c ;
830
+ ngx_uint_t n ;
831
+
832
+ enum {
833
+ parse_name ,
834
+ parse_space ,
835
+ parse_value ,
836
+ parse_value_newline
837
+ } state = parse_name ;
838
+
839
+ n = 0 ;
840
+ matched = 0 ;
841
+
842
+ while (in ) {
843
+ b = in -> buf ;
844
+
845
+ for (p = b -> pos ; p != b -> last ; ++ p ) {
846
+ c = * p ;
847
+
848
+ if (c == '\r' ) {
849
+ continue ;
850
+ }
851
+
852
+ switch (state ) {
853
+ case parse_value_newline :
854
+ if (c == ' ' || c == '\t' ) {
855
+ state = parse_space ;
856
+ break ;
857
+ }
858
+
859
+ if (matched ) {
860
+ return n ;
861
+ }
862
+
863
+ if (c == '\n' ) {
864
+ return NGX_OK ;
865
+ }
866
+
867
+ n = 0 ;
868
+ state = parse_name ;
869
+
870
+ case parse_name :
871
+ switch (c ) {
872
+ case ':' :
873
+ matched = (n == name -> len );
874
+ n = 0 ;
875
+ state = parse_space ;
876
+ break ;
877
+ case '\n' :
878
+ n = 0 ;
879
+ break ;
880
+ default :
881
+ if (n < name -> len &&
882
+ ngx_tolower (c ) == ngx_tolower (name -> data [n ]))
883
+ {
884
+ ++ n ;
885
+ break ;
886
+ }
887
+ n = name -> len + 1 ;
888
+ }
889
+ break ;
890
+
891
+ case parse_space :
892
+ if (c == ' ' || c == '\t' ) {
893
+ break ;
894
+ }
895
+ state = parse_value ;
896
+
897
+ case parse_value :
898
+ if (c == '\n' ) {
899
+ state = parse_value_newline ;
900
+ break ;
901
+ }
902
+
903
+ if (matched && n + 1 < len ) {
904
+ data [n ++ ] = c ;
905
+ }
906
+
907
+ break ;
908
+ }
909
+ }
910
+
911
+ in = in -> next ;
912
+ }
913
+
914
+ return NGX_OK ;
915
+ }
916
+
917
+
816
918
static ngx_int_t
817
919
ngx_rtmp_notify_connect_handle (ngx_rtmp_session_t * s ,
818
920
void * arg , ngx_chain_t * in )
819
921
{
820
- if (ngx_rtmp_notify_parse_http_retcode (s , in ) != NGX_OK ) {
922
+ ngx_rtmp_connect_t * v = arg ;
923
+ ngx_int_t rc ;
924
+ u_char app [NGX_RTMP_MAX_NAME ];
925
+
926
+ static ngx_str_t location = ngx_string ("location" );
927
+
928
+ rc = ngx_rtmp_notify_parse_http_retcode (s , in );
929
+ if (rc == NGX_ERROR ) {
821
930
return NGX_ERROR ;
822
931
}
823
932
824
- return next_connect (s , (ngx_rtmp_connect_t * )arg );
933
+ if (rc == NGX_AGAIN ) {
934
+ ngx_log_debug0 (NGX_LOG_DEBUG_RTMP , s -> connection -> log , 0 ,
935
+ "notify: connect redirect received" );
936
+
937
+ rc = ngx_rtmp_notify_parse_http_header (s , in , & location , app ,
938
+ sizeof (app ) - 1 );
939
+ if (rc > 0 ) {
940
+ * ngx_cpymem (v -> app , app , rc ) = 0 ;
941
+ ngx_log_error (NGX_LOG_INFO , s -> connection -> log , 0 ,
942
+ "notify: connect redirect to '%s'" , v -> app );
943
+ }
944
+ }
945
+
946
+ return next_connect (s , v );
825
947
}
826
948
827
949
828
950
static ngx_int_t
829
951
ngx_rtmp_notify_publish_handle (ngx_rtmp_session_t * s ,
830
952
void * arg , ngx_chain_t * in )
831
953
{
832
- if (ngx_rtmp_notify_parse_http_retcode (s , in ) != NGX_OK ) {
954
+ ngx_rtmp_publish_t * v = arg ;
955
+ ngx_int_t rc ;
956
+ u_char name [NGX_RTMP_MAX_NAME ];
957
+
958
+ static ngx_str_t location = ngx_string ("location" );
959
+
960
+ rc = ngx_rtmp_notify_parse_http_retcode (s , in );
961
+ if (rc == NGX_ERROR ) {
833
962
return NGX_ERROR ;
834
963
}
835
964
836
- return next_publish (s , (ngx_rtmp_publish_t * )arg );
965
+ if (rc == NGX_AGAIN ) {
966
+ ngx_log_debug0 (NGX_LOG_DEBUG_RTMP , s -> connection -> log , 0 ,
967
+ "notify: publish redirect received" );
968
+
969
+ rc = ngx_rtmp_notify_parse_http_header (s , in , & location , name ,
970
+ sizeof (name ) - 1 );
971
+ if (rc > 0 ) {
972
+ * ngx_cpymem (v -> name , name , rc ) = 0 ;
973
+ ngx_log_error (NGX_LOG_INFO , s -> connection -> log , 0 ,
974
+ "notify: publish redirect to '%s'" , v -> name );
975
+ }
976
+ }
977
+
978
+ return next_publish (s , v );
837
979
}
838
980
839
981
840
982
static ngx_int_t
841
983
ngx_rtmp_notify_play_handle (ngx_rtmp_session_t * s ,
842
984
void * arg , ngx_chain_t * in )
843
985
{
844
- if (ngx_rtmp_notify_parse_http_retcode (s , in ) != NGX_OK ) {
986
+ ngx_rtmp_play_t * v = arg ;
987
+ ngx_int_t rc ;
988
+ u_char name [NGX_RTMP_MAX_NAME ];
989
+
990
+ static ngx_str_t location = ngx_string ("location" );
991
+
992
+ rc = ngx_rtmp_notify_parse_http_retcode (s , in );
993
+ if (rc == NGX_ERROR ) {
845
994
return NGX_ERROR ;
846
995
}
847
996
848
- return next_play (s , (ngx_rtmp_play_t * )arg );
997
+ if (rc == NGX_AGAIN ) {
998
+ ngx_log_debug0 (NGX_LOG_DEBUG_RTMP , s -> connection -> log , 0 ,
999
+ "notify: play redirect received" );
1000
+
1001
+ rc = ngx_rtmp_notify_parse_http_header (s , in , & location , name ,
1002
+ sizeof (name ) - 1 );
1003
+ if (rc > 0 ) {
1004
+ * ngx_cpymem (v -> name , name , rc ) = 0 ;
1005
+ ngx_log_error (NGX_LOG_INFO , s -> connection -> log , 0 ,
1006
+ "notify: play redirect to '%s'" , v -> name );
1007
+ }
1008
+ }
1009
+
1010
+ return next_play (s , v );
849
1011
}
850
1012
851
1013
0 commit comments