@@ -416,12 +416,18 @@ pub fn http2_frames_get_header_value_vec(
416416 }
417417}
418418
419+ #[ derive( Debug , PartialEq ) ]
420+ enum Http2Header < ' a > {
421+ Single ( & ' a [ u8 ] ) ,
422+ Multiple ( Vec < u8 > ) ,
423+ }
424+
419425fn http2_frames_get_header_value < ' a > (
420- tx : & ' a mut HTTP2Transaction , direction : Direction , name : & str ,
421- ) -> Result < & ' a [ u8 ] , ( ) > {
426+ tx : & ' a HTTP2Transaction , direction : Direction , name : & str ,
427+ ) -> Option < Http2Header < ' a > > {
422428 let mut found = 0 ;
423429 let mut vec = Vec :: new ( ) ;
424- let mut single: Result < & [ u8 ] , ( ) > = Err ( ( ) ) ;
430+ let mut single = None ;
425431 let frames = if direction == Direction :: ToServer {
426432 & tx. frames_ts
427433 } else {
@@ -432,10 +438,10 @@ fn http2_frames_get_header_value<'a>(
432438 for block in blocks. iter ( ) {
433439 if block. name . as_ref ( ) == name. as_bytes ( ) {
434440 if found == 0 {
435- single = Ok ( & block. value ) ;
441+ single = Some ( Http2Header :: Single ( & block. value ) ) ;
436442 found = 1 ;
437443 } else if found == 1 && Rc :: strong_count ( & block. name ) <= 2 {
438- if let Ok ( s ) = single {
444+ if let Some ( Http2Header :: Single ( s ) ) = single {
439445 vec. extend_from_slice ( s) ;
440446 }
441447 vec. extend_from_slice ( b", " ) ;
@@ -450,14 +456,11 @@ fn http2_frames_get_header_value<'a>(
450456 }
451457 }
452458 if found == 0 {
453- return Err ( ( ) ) ;
459+ return None ;
454460 } else if found == 1 {
455461 return single;
456462 } else {
457- tx. escaped . push ( vec) ;
458- let idx = tx. escaped . len ( ) - 1 ;
459- let value = & tx. escaped [ idx] ;
460- return Ok ( value) ;
463+ return Some ( Http2Header :: Multiple ( vec) ) ;
461464 }
462465}
463466
@@ -553,92 +556,115 @@ pub unsafe extern "C" fn SCHttp2TxGetMethod(
553556
554557#[ no_mangle]
555558pub unsafe extern "C" fn SCHttp2TxGetHost (
556- tx : & mut HTTP2Transaction , buffer : * mut * const u8 , buffer_len : * mut u32 ,
559+ tx : & mut HTTP2Transaction , buffer : * mut * const u8 , buffer_len : * mut u32 , tbuf : * mut c_void ,
557560) -> u8 {
558- if let Ok ( value) = http2_frames_get_header_value ( tx, Direction :: ToServer , ":authority" ) {
559- * buffer = value. as_ptr ( ) ; //unsafe
560- * buffer_len = value. len ( ) as u32 ;
561- return 1 ;
562- }
563- return 0 ;
564- }
565-
566- fn http2_lower ( value : & [ u8 ] ) -> Option < Vec < u8 > > {
567- for i in 0 ..value. len ( ) {
568- if value[ i] . is_ascii_uppercase ( ) {
569- // we got at least one upper character, need to transform
570- let mut vec: Vec < u8 > = Vec :: with_capacity ( value. len ( ) ) ;
571- vec. extend_from_slice ( value) ;
572- for e in & mut vec {
573- e. make_ascii_lowercase ( ) ;
561+ let tbuf = cast_pointer ! ( tbuf, Http2ThreadBuf ) ;
562+ if let Some ( value) = http2_frames_get_header_value ( tx, Direction :: ToServer , ":authority" ) {
563+ match value {
564+ Http2Header :: Single ( v) => {
565+ * buffer = v. as_ptr ( ) ; //unsafe
566+ * buffer_len = v. len ( ) as u32 ;
567+ }
568+ Http2Header :: Multiple ( v) => {
569+ tbuf. data = v;
570+ * buffer = tbuf. data . as_ptr ( ) ; //unsafe
571+ * buffer_len = tbuf. data . len ( ) as u32 ;
574572 }
575- return Some ( vec) ;
576573 }
574+ return 1 ;
577575 }
578- return None ;
576+ return 0 ;
579577}
580578
581579// returns a tuple with the value and its size
582- fn http2_normalize_host ( value : & [ u8 ] ) -> & [ u8 ] {
583- match value. iter ( ) . position ( |& x| x == b'@' ) {
584- Some ( i) => {
585- let value = & value[ i + 1 ..] ;
586- match value. iter ( ) . position ( |& x| x == b':' ) {
587- Some ( i) => {
588- return & value[ ..i] ;
580+ fn http2_normalize_host ( ve : Http2Header ) -> Http2Header {
581+ let vs = match & ve {
582+ Http2Header :: Single ( v) => v,
583+ Http2Header :: Multiple ( v) => v. as_slice ( ) ,
584+ } ;
585+ let ( start, end) = match vs. iter ( ) . position ( |& x| x == b'@' ) {
586+ Some ( i) => match & vs[ i + 1 ..] . iter ( ) . position ( |& x| x == b':' ) {
587+ Some ( j) => ( i + 1 , i + 1 + j) ,
588+ None => ( i + 1 , vs. len ( ) ) ,
589+ } ,
590+ None => match vs. iter ( ) . position ( |& x| x == b':' ) {
591+ Some ( i) => ( 0 , i) ,
592+ None => ( 0 , vs. len ( ) ) ,
593+ } ,
594+ } ;
595+ return match ve {
596+ Http2Header :: Single ( v) => {
597+ let mut need_transform = false ;
598+ for c in v. iter ( ) . take ( end) . skip ( start) {
599+ if c. is_ascii_uppercase ( ) {
600+ need_transform = true ;
601+ break ;
589602 }
590- None => {
591- return value;
603+ }
604+ if need_transform {
605+ let mut vec: Vec < u8 > = Vec :: with_capacity ( end - start) ;
606+ for c in v. iter ( ) . take ( end) . skip ( start) {
607+ vec. push ( c. to_ascii_lowercase ( ) ) ;
592608 }
609+ Http2Header :: Multiple ( vec)
610+ } else {
611+ Http2Header :: Single ( & v[ start..end] )
593612 }
594613 }
595- None => match value . iter ( ) . position ( | & x| x == b':' ) {
596- Some ( i ) => {
597- return & value [ ..i ] ;
614+ Http2Header :: Multiple ( mut v ) => {
615+ if end < v . len ( ) {
616+ v . truncate ( end ) ;
598617 }
599- None => {
600- return value ;
618+ if start > 0 {
619+ v . drain ( 0 ..start ) ;
601620 }
602- } ,
603- }
621+ for e in & mut v {
622+ e. make_ascii_lowercase ( ) ;
623+ }
624+ Http2Header :: Multiple ( v)
625+ }
626+ } ;
604627}
605628
606629#[ no_mangle]
607630pub unsafe extern "C" fn SCHttp2TxGetHostNorm (
608- tx : & mut HTTP2Transaction , buffer : * mut * const u8 , buffer_len : * mut u32 ,
631+ tx : & mut HTTP2Transaction , buffer : * mut * const u8 , buffer_len : * mut u32 , tbuf : * mut c_void ,
609632) -> u8 {
610- if let Ok ( value) = http2_frames_get_header_value ( tx, Direction :: ToServer , ":authority" ) {
611- let r = http2_normalize_host ( value) ;
612- // r is a tuple with the value and its size
613- // this is useful when we only take a substring (before the port)
614- match http2_lower ( r) {
615- Some ( normval) => {
616- // In case we needed some normalization,
617- // the transaction needs to take ownership of this normalized host
618- tx. escaped . push ( normval) ;
619- let idx = tx. escaped . len ( ) - 1 ;
620- let resvalue = & tx. escaped [ idx] ;
621- * buffer = resvalue. as_ptr ( ) ; //unsafe
622- * buffer_len = resvalue. len ( ) as u32 ;
623- return 1 ;
633+ let tbuf = cast_pointer ! ( tbuf, Http2ThreadBuf ) ;
634+ if let Some ( value) = http2_frames_get_header_value ( tx, Direction :: ToServer , ":authority" ) {
635+ match http2_normalize_host ( value) {
636+ Http2Header :: Single ( v) => {
637+ * buffer = v. as_ptr ( ) ; //unsafe
638+ * buffer_len = v. len ( ) as u32 ;
624639 }
625- None => {
626- * buffer = r . as_ptr ( ) ; //unsafe
627- * buffer_len = r . len ( ) as u32 ;
628- return 1 ;
640+ Http2Header :: Multiple ( v ) => {
641+ tbuf . data = v ;
642+ * buffer = tbuf . data . as_ptr ( ) ; //unsafe
643+ * buffer_len = tbuf . data . len ( ) as u32 ;
629644 }
630645 }
646+ return 1 ;
631647 }
632648 return 0 ;
633649}
634650
635651#[ no_mangle]
636652pub unsafe extern "C" fn SCHttp2TxGetUserAgent (
637- tx : & mut HTTP2Transaction , buffer : * mut * const u8 , buffer_len : * mut u32 ,
653+ tx : & mut HTTP2Transaction , buffer : * mut * const u8 , buffer_len : * mut u32 , tbuf : * mut c_void ,
638654) -> u8 {
639- if let Ok ( value) = http2_frames_get_header_value ( tx, Direction :: ToServer , "user-agent" ) {
640- * buffer = value. as_ptr ( ) ; //unsafe
641- * buffer_len = value. len ( ) as u32 ;
655+ let tbuf = cast_pointer ! ( tbuf, Http2ThreadBuf ) ;
656+ if let Some ( value) = http2_frames_get_header_value ( tx, Direction :: ToServer , "user-agent" ) {
657+ match value {
658+ Http2Header :: Single ( v) => {
659+ * buffer = v. as_ptr ( ) ; //unsafe
660+ * buffer_len = v. len ( ) as u32 ;
661+ }
662+ Http2Header :: Multiple ( v) => {
663+ tbuf. data = v;
664+ * buffer = tbuf. data . as_ptr ( ) ; //unsafe
665+ * buffer_len = tbuf. data . len ( ) as u32 ;
666+ }
667+ }
642668 return 1 ;
643669 }
644670 return 0 ;
@@ -659,16 +685,37 @@ pub unsafe extern "C" fn SCHttp2TxGetStatus(
659685#[ no_mangle]
660686pub unsafe extern "C" fn SCHttp2TxGetCookie (
661687 tx : & mut HTTP2Transaction , direction : u8 , buffer : * mut * const u8 , buffer_len : * mut u32 ,
688+ tbuf : * mut c_void ,
662689) -> u8 {
690+ let tbuf = cast_pointer ! ( tbuf, Http2ThreadBuf ) ;
663691 if direction == u8:: from ( Direction :: ToServer ) {
664- if let Ok ( value) = http2_frames_get_header_value ( tx, Direction :: ToServer , "cookie" ) {
665- * buffer = value. as_ptr ( ) ; //unsafe
666- * buffer_len = value. len ( ) as u32 ;
692+ if let Some ( value) = http2_frames_get_header_value ( tx, Direction :: ToServer , "cookie" ) {
693+ match value {
694+ Http2Header :: Single ( v) => {
695+ * buffer = v. as_ptr ( ) ; //unsafe
696+ * buffer_len = v. len ( ) as u32 ;
697+ }
698+ Http2Header :: Multiple ( v) => {
699+ tbuf. data = v;
700+ * buffer = tbuf. data . as_ptr ( ) ; //unsafe
701+ * buffer_len = tbuf. data . len ( ) as u32 ;
702+ }
703+ }
667704 return 1 ;
668705 }
669- } else if let Ok ( value) = http2_frames_get_header_value ( tx, Direction :: ToClient , "set-cookie" ) {
670- * buffer = value. as_ptr ( ) ; //unsafe
671- * buffer_len = value. len ( ) as u32 ;
706+ } else if let Some ( value) = http2_frames_get_header_value ( tx, Direction :: ToClient , "set-cookie" )
707+ {
708+ match value {
709+ Http2Header :: Single ( v) => {
710+ * buffer = v. as_ptr ( ) ; //unsafe
711+ * buffer_len = v. len ( ) as u32 ;
712+ }
713+ Http2Header :: Multiple ( v) => {
714+ tbuf. data = v;
715+ * buffer = tbuf. data . as_ptr ( ) ; //unsafe
716+ * buffer_len = tbuf. data . len ( ) as u32 ;
717+ }
718+ }
672719 return 1 ;
673720 }
674721 return 0 ;
@@ -677,13 +724,24 @@ pub unsafe extern "C" fn SCHttp2TxGetCookie(
677724#[ no_mangle]
678725pub unsafe extern "C" fn SCHttp2TxGetHeaderValue (
679726 tx : & mut HTTP2Transaction , direction : u8 , strname : * const std:: os:: raw:: c_char ,
680- buffer : * mut * const u8 , buffer_len : * mut u32 ,
727+ buffer : * mut * const u8 , buffer_len : * mut u32 , tbuf : * mut c_void ,
681728) -> u8 {
729+ let tbuf = cast_pointer ! ( tbuf, Http2ThreadBuf ) ;
682730 let hname: & CStr = CStr :: from_ptr ( strname) ; //unsafe
683731 if let Ok ( s) = hname. to_str ( ) {
684- if let Ok ( value) = http2_frames_get_header_value ( tx, direction. into ( ) , & s. to_lowercase ( ) ) {
685- * buffer = value. as_ptr ( ) ; //unsafe
686- * buffer_len = value. len ( ) as u32 ;
732+ if let Some ( value) = http2_frames_get_header_value ( tx, direction. into ( ) , & s. to_lowercase ( ) )
733+ {
734+ match value {
735+ Http2Header :: Single ( v) => {
736+ * buffer = v. as_ptr ( ) ; //unsafe
737+ * buffer_len = v. len ( ) as u32 ;
738+ }
739+ Http2Header :: Multiple ( v) => {
740+ tbuf. data = v;
741+ * buffer = tbuf. data . as_ptr ( ) ; //unsafe
742+ * buffer_len = tbuf. data . len ( ) as u32 ;
743+ }
744+ }
687745 return 1 ;
688746 }
689747 }
@@ -1027,20 +1085,20 @@ mod tests {
10271085 #[ test]
10281086 fn test_http2_normalize_host ( ) {
10291087 let buf0 = "aBC.com:1234" . as_bytes ( ) ;
1030- let r0 = http2_normalize_host ( buf0) ;
1031- assert_eq ! ( r0, "aBC .com". as_bytes( ) . to_vec( ) ) ;
1088+ let r0 = http2_normalize_host ( Http2Header :: Single ( buf0) ) ;
1089+ assert_eq ! ( r0, Http2Header :: Multiple ( "abc .com". as_bytes( ) . to_vec( ) ) ) ;
10321090 let buf1 = "oisf.net" . as_bytes ( ) ;
1033- let r1 = http2_normalize_host ( buf1) ;
1034- assert_eq ! ( r1, "oisf.net" . as_bytes( ) . to_vec ( ) ) ;
1091+ let r1 = http2_normalize_host ( Http2Header :: Single ( buf1) ) ;
1092+ assert_eq ! ( r1, Http2Header :: Single ( "oisf.net" . as_bytes( ) ) ) ;
10351093 let buf2 = "localhost:3000" . as_bytes ( ) ;
1036- let r2 = http2_normalize_host ( buf2) ;
1037- assert_eq ! ( r2, "localhost" . as_bytes( ) . to_vec ( ) ) ;
1094+ let r2 = http2_normalize_host ( Http2Header :: Single ( buf2) ) ;
1095+ assert_eq ! ( r2, Http2Header :: Single ( "localhost" . as_bytes( ) ) ) ;
10381096 let buf3 = "user:pass@localhost" . as_bytes ( ) ;
1039- let r3 = http2_normalize_host ( buf3) ;
1040- assert_eq ! ( r3, "localhost" . as_bytes( ) . to_vec ( ) ) ;
1097+ let r3 = http2_normalize_host ( Http2Header :: Single ( buf3) ) ;
1098+ assert_eq ! ( r3, Http2Header :: Single ( "localhost" . as_bytes( ) ) ) ;
10411099 let buf4 = "user:pass@localhost:123" . as_bytes ( ) ;
1042- let r4 = http2_normalize_host ( buf4) ;
1043- assert_eq ! ( r4, "localhost" . as_bytes( ) . to_vec ( ) ) ;
1100+ let r4 = http2_normalize_host ( Http2Header :: Single ( buf4) ) ;
1101+ assert_eq ! ( r4, Http2Header :: Single ( "localhost" . as_bytes( ) ) ) ;
10441102 }
10451103
10461104 #[ test]
@@ -1091,12 +1149,12 @@ mod tests {
10911149 header : head,
10921150 data : txdata,
10931151 } ) ;
1094- match http2_frames_get_header_value ( & mut tx, Direction :: ToServer , "Host" ) {
1095- Ok ( x ) => {
1152+ match http2_frames_get_header_value ( & tx, Direction :: ToServer , "Host" ) {
1153+ Some ( Http2Header :: Multiple ( x ) ) => {
10961154 assert_eq ! ( x, "abc.com, efg.net" . as_bytes( ) ) ;
10971155 }
1098- Err ( e ) => {
1099- panic ! ( "Result should not have been an error: {:?}" , e ) ;
1156+ _ => {
1157+ panic ! ( "Result should have been a multiple header value" ) ;
11001158 }
11011159 }
11021160 }
0 commit comments