@ -15,7 +15,19 @@
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  *   02110 - 1301 ,   USA . 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  * / 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				// written by Victor Julien
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				/**
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  *    \ file 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  *    \ author   Victor   Julien   < victor @ inliniac . net > 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  * 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  *   Tracks   chunk   based   file   transfers .   Chunks   may   be   transfered   out 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  *   of   order ,   but   cannot   be   transfered   in   parallel .   So   only   one 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  *   chunk   at   a   time . 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  * 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  *   GAP   handling .   If   a   data   gap   is   encountered ,   the   file   is   truncated 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  *   and   new   data   is   no   longer   pushed   down   to   the   lower   level   APIs . 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  *   The   tracker   does   continue   to   follow   the   file . 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  * / 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				extern   crate   libc ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				use   log ::* ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				use   core ::* ; 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -23,10 +35,26 @@ use std::collections::HashMap;
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				use   std ::collections ::hash_map ::Entry ::{ Occupied ,   Vacant } ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				use   filecontainer ::* ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				#[ derive(Debug) ] 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				pub   struct  FileChunk   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     contains_gap : bool , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     chunk : Vec < u8 > , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				impl   FileChunk   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     pub   fn  new ( size : u32 )   -> FileChunk   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         FileChunk   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             contains_gap : false , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             chunk : Vec ::with_capacity ( size   as   usize ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				#[ derive(Debug) ] 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				pub   struct  FileTransferTracker   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     file_size : u64 , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     tracked : u64 , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     cur_ooo : u64 ,     // how many bytes do we have queued from ooo chunks
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     track_id : u32 , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     chunk_left : u32 , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -36,8 +64,9 @@ pub struct FileTransferTracker {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     pub   file_open : bool , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     chunk_is_last : bool , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     chunk_is_ooo : bool , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     file_is_truncated : bool , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     chunks : HashMap < u64 ,   Vec < u8 > > , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     chunks : HashMap < u64 ,   FileChunk > , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     cur_ooo_chunk_offset : u64 , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -46,6 +75,7 @@ impl FileTransferTracker {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         FileTransferTracker   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             file_size :0 , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             tracked :0 , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             cur_ooo :0 , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             track_id :0 , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             chunk_left :0 , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             tx_id :0 , 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -53,6 +83,7 @@ impl FileTransferTracker {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             file_open :false , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             chunk_is_last :false , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             chunk_is_ooo :false , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             file_is_truncated :false , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             cur_ooo_chunk_offset :0 , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             chunks :HashMap ::new ( ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         } 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -70,12 +101,25 @@ impl FileTransferTracker {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     pub   fn  close ( & mut   self ,   files : & mut   FileContainer ,   flags : u16 )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         files . file_close ( & self . track_id ,   flags ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         if   ! self . file_is_truncated   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             files . file_close ( & self . track_id ,   flags ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         self . file_open   =   false ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         self . tracked   =   0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         files . files_prune ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     pub   fn  trunc   ( & mut   self ,   files : & mut   FileContainer ,   flags : u16 )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         if   self . file_is_truncated   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             return ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         let   myflags   =   flags   |   1 ;   // TODO util-file.c::FILE_TRUNCATED
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         files . file_close ( & self . track_id ,   myflags ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         SCLogDebug ! ( "truncated file" ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         files . files_prune ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         self . file_is_truncated   =   true ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     pub   fn  create ( & mut   self ,   name : & [ u8 ] ,   file_size : u64 )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         if   self . file_open   = =   true   {   panic! ( "close existing file first" ) ;   } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -92,8 +136,15 @@ impl FileTransferTracker {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         SCLogDebug ! ( "NEW CHUNK: chunk_size {} fill_bytes {}" ,   chunk_size ,   fill_bytes ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // for now assume that is_last means its really the last chunk
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // so no out of order chunks coming after. This means that if
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         // the last chunk is out or order, we've missed chunks before.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         if   chunk_offset   ! =   self . tracked   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             SCLogDebug ! ( "NEW CHUNK IS OOO: expected {}, got {}" ,   self . tracked ,   chunk_offset ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             if   is_last   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 SCLogDebug ! ( "last chunk is out of order, this means we missed data before" ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 self . trunc ( files ,   flags ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             self . chunk_is_ooo   =   true ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             self . cur_ooo_chunk_offset   =   chunk_offset ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         } 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -108,14 +159,21 @@ impl FileTransferTracker {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             self . open ( config ,   files ,   flags ,   name ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         let   res   =   self . update ( files ,   flags ,   data  ); 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         let   res   =   self . update ( files ,   flags ,   data ,  0  ); 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         SCLogDebug ! ( "NEW CHUNK: update res {:?}" ,   res ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         res 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     /// update the file tracker
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     /// If gap_size > 0 'data' should not be used.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     /// return how much we consumed of data
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     pub   fn  update ( & mut   self ,   files : & mut   FileContainer ,   flags : u16 ,   data : & [ u8 ] )   -> u32  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     pub   fn  update ( & mut   self ,   files : & mut   FileContainer ,   flags : u16 ,   data : & [ u8 ] ,  gap_size : u32  )  -> u32  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         let   mut   consumed   =   0   as   usize ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         let   is_gap   =   gap_size   >   0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         if   is_gap   | |   gap_size   >   0   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             SCLogDebug ! ( "is_gap {} size {} ooo? {}" ,   is_gap ,   gap_size ,   self . chunk_is_ooo ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         if   self . chunk_left   +   self . fill_bytes   as   u32   = =   0   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             //SCLogDebug!("UPDATE: nothing to do");
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             return   0 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -140,7 +198,7 @@ impl FileTransferTracker {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 let   d   =   & data [ 0 .. self . chunk_left   as   usize ] ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 if   self . chunk_is_ooo   = =   false   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     let   res   =   files . file_append ( & self . track_id ,   d  ); 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     let   res   =   files . file_append ( & self . track_id ,   d ,  is_gap  ); 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     if   res   ! =   0   {   panic! ( "append failed" ) ;   } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     self . tracked   + =   self . chunk_left   as   u64 ; 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -149,11 +207,13 @@ impl FileTransferTracker {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                             d . len ( ) ,   self . cur_ooo_chunk_offset ,   self . tracked ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     let   c   =   match   self . chunks . entry ( self . cur_ooo_chunk_offset )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                         Vacant ( entry )   = >   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                             entry . insert ( Vec ::with_capacity ( self . chunk_left   as   usize ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                             entry . insert ( FileChunk ::new ( self . chunk_left ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                         } , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                         Occupied ( entry )   = >   entry . into_mut ( ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     } ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     c . extend ( d ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     self . cur_ooo   + =   d . len ( )   as   u64 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     c . contains_gap   | =   is_gap ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     c . chunk . extend ( d ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 consumed   + =   self . chunk_left   as   usize ; 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -169,7 +229,6 @@ impl FileTransferTracker {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                         SCLogDebug ! ( "CHUNK(post) fill bytes now still {}" ,   self . fill_bytes ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     self . chunk_left   =   0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     //return consumed as u32
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 }   else   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     self . chunk_left   =   0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -177,13 +236,14 @@ impl FileTransferTracker {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                         loop   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                             let   offset   =   self . tracked ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                             match   self . chunks . remove ( & self . tracked )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                 Some ( a )   = >   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                     let   res   =   files . file_append ( & self . track_id ,   &  a) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                     if   res   ! =   0   {   panic! ( "append failed ") ;   } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                 Some ( c )   = >   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                     let   res   =   files . file_append ( & self . track_id ,   & c. chunk ,   c . cont  ains_gap ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                     if   res   ! =   0   {   panic! ( "append failed : files.file_append() returned {} ",   res ) ;   } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                     self . tracked   + =   a . len ( )   as   u64 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                     self . tracked   + =   c . chunk . len ( )   as   u64 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                     self . cur_ooo   - =   c . chunk . len ( )   as   u64 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                     SCLogDebug ! ( "STORED OOO CHUNK at offset {}, tracked now {}, stored len {}" ,   offset ,   self . tracked ,   a . len ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                     SCLogDebug ! ( "STORED OOO CHUNK at offset {}, tracked now {}, stored len {}" ,   offset ,   self . tracked ,   c. chunk  . len ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                 } , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                 _   = >   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                     SCLogDebug ! ( "NO STORED CHUNK found at offset {}" ,   self . tracked ) ; 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -208,15 +268,17 @@ impl FileTransferTracker {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             }   else   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 if   self . chunk_is_ooo   = =   false   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     let   res   =   files . file_append ( & self . track_id ,   data  ); 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     let   res   =   files . file_append ( & self . track_id ,   data ,  is_gap  ); 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     if   res   ! =   0   {   panic! ( "append failed" ) ;   } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     self . tracked   + =   data . len ( )   as   u64 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 }   else   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     let   c   =   match   self . chunks . entry ( self . cur_ooo_chunk_offset )   { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                         Vacant ( entry )   = >   entry . insert ( Vec ::with_capacity ( 32768 ) ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                         Vacant ( entry )   = >   entry . insert ( FileChunk ::new ( 32768 ) ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                         Occupied ( entry )   = >   entry . into_mut ( ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     } ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     c . extend ( data ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     c . chunk . extend ( data ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     c . contains_gap   | =   is_gap ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     self . cur_ooo   + =   data . len ( )   as   u64 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                 self . chunk_left   - =   data . len ( )   as   u32 ; 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -226,4 +288,8 @@ impl FileTransferTracker {
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         files . files_prune ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         consumed   as   u32 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     pub   fn  get_queued_size ( & self )   -> u64  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         self . cur_ooo 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				}