public static FilePiece parse_packet(byte[] packet) { if (packet.Length < header_size){ // packet is shorter than the header has to be return null; } Int32 data_length = System.BitConverter.ToInt32(packet, 0); if (data_length <= 0){ // no data return null; } Int64 piece_number = System.BitConverter.ToInt64(packet, 4); byte[] checksum = new byte[16]; for(int i = 12; i < 28; i++){ checksum[i-12] = packet[i]; } byte[] data = new byte[data_length]; for (int i = 0; i < data_length; i++){ data[i] = packet[i+header_size]; } // do a checksum MD5 check = new MD5CryptoServiceProvider(); byte[] sum = check.ComputeHash(data); if (sum.Equals(checksum)){ return null; // data checksum doesn't match } FilePiece piece = new FilePiece(piece_number, data); return piece; }
public static FilePiece parse_packet(byte[] packet) { if (packet.Length < 28){ // header isn't long enough return null; } Int32 data_length = System.BitConverter.ToInt32(packet, 0); if (data_length < 0){ // no data return null; } Int64 piece_number = System.BitConverter.ToInt64(packet, 4); if (piece_number < 0){ // can't have less than 0 piece number return null; } byte[] checksum = new byte[16]; for(int i = 12; i < 28; i++){ checksum[i] = packet[i]; } System.ArraySegment<byte> data_segment = new System.ArraySegment<byte>(packet, 28, packet.Length-28); byte[] data = data_segment.Array; // do a checksum MD5 check = new MD5CryptoServiceProvider(); byte[] sum = check.ComputeHash(data); if (sum.Equals(checksum)){ return null; // data checksum doesn't match } FilePiece piece = new FilePiece(piece_number, data); return piece; }
public static byte[] get_missing_packet(Int64 missing_number) { byte[] number_data = System.BitConverter.GetBytes(missing_number); FilePiece piece = new FilePiece(-1, number_data); return piece.get_packet(); }
public FilePiece GetNextPiece() { if (writing){ // polymorphism in action! return null; } byte[] b = GetNextChunk(); FilePiece piece; if (b != null){ piece = new FilePiece(position, b); }else{ piece = null; } return piece; }
public void SendFileInfo() { if (file_stream == null){ return; } byte[] b = new byte[FilePiece.data_size]; for (int i = 0; i < b.Length ; i++){ b[i] = 0x000000; } byte[] file_name = file_stream.GetFileName(); file_name.CopyTo(b, 0); System.BitConverter.GetBytes(file_stream.GetExpectedSize()).CopyTo(b, 255); Encoding.UTF8.GetBytes(user_name).CopyTo(b, 255+8); FilePiece piece = new FilePiece(MESSAGE_FILEINFO , b); // Console.WriteLine("Raw data being sent:"); // for (int i = 0; i < b.Length; i ++){ // Console.Write(b[i].ToString()); // } // Console.WriteLine(); network.send(piece.get_packet()); }
public bool SendChecker() { // returns true if we're done sending if (file_stream == null ){ return true; } byte[] b; bool received_error = false; b = network.PopReceiveBuffer(); while (b != null){ // we have data in b! Deal with it. FilePiece piece = FilePiece.parse_packet(b); if (piece != null){ if (piece.number > 0){ // do nothing. We are not a receiver! }else if (piece.number == MESSAGE_RESEND){ // we are server! We must re-send this packet. received_error = true; packets_error++; Int64 actual_number = BitConverter.ToInt64(piece.get_data(), 0); if (actual_number != 0){ FilePiece specific_piece = new FilePiece(actual_number, file_stream.GetSpecificChunk(actual_number)); network.send(specific_piece.get_packet()); bytes_sent += specific_piece.get_packet_size(); }else{ Console.WriteLine("Hmm, something's wrong with that packet"); } } } b = network.PopReceiveBuffer(); } if (file_stream.GetFileStatus()){ // done sending, just sending corrections if (last_error == DateTime.MinValue){ Console.WriteLine("last_error is null"); last_error = new DateTime(); }else if (received_error){ last_error = DateTime.Now; }else if ((DateTime.Now.Subtract(last_error) ).TotalMilliseconds > CORRECTIONS_TIMEOUT){ Console.WriteLine("No error! Time out :)"); return true; } } // now that we're caught up, adjust the speed based on errors. if (received_error){ sending_speed *= change_with_error_decrease; }else{ sending_speed *= change_without_error_increase; } // returns true if all pieces have been sent. //Does some sending if there are things to send double time_spent = (DateTime.Now.AddSeconds(1) - start_time).TotalSeconds; while (sending_speed > (double)bytes_sent/(double)time_spent){ FilePiece fp = file_stream.GetNextPiece(); if (fp != null){ byte[] bytes = fp.get_packet(); if (bytes != null){ network.send(bytes); bytes_sent += bytes.Length; }else{ // exit loop if we're done sending file return true; } }else{ return true; } } return false; }
public void WritePiece(FilePiece piece) { if (!writing){ // polymorphism in action! return; } fs.Write(piece.data, 0, piece.data.Length); // TODO: Use BeginWrite to make it more responsive }
public void WriteSpecificPiece(FilePiece piece) { // NOTE: Requires that all data pieces be EXACTLY data_size in length! (see FilePiece.cs) if (!writing){ // polymorphism in action! return; } if (piece.number < 0){ return; } fs.Seek(piece.number * FilePiece.data_size, SeekOrigin.Begin); fs.Write(piece.data, 0, piece.data.Length); }
public void send_file_piece(FilePiece piece) { send( piece.get_packet()); }
public void WriteSpecificPiece(FilePiece piece) { // NOTE: Requires that all data pieces be EXACTLY data_size in length! (see FilePiece.cs) if (!writing){ // polymorphism in action! Console.WriteLine("We're not writing. Don't call this function!"); return; } if (piece.number < 0){ Console.WriteLine("Don't tell us to write a non-existant piece."); return; } fs.Seek(piece.number * FilePiece.data_size, SeekOrigin.Begin); fs.Write(piece.get_data(), 0, piece.data.Length); if (received_pieces.Count <= 1 && received_pieces[0].Equals(piece.number - 1)){ received_pieces.Clear(); received_pieces.Add(piece.number); }else{ if (received_pieces.Contains(piece.number)){ Console.WriteLine("Detected Duplicate packet"); received_pieces.Remove(piece.number); }else{ received_pieces.Add(piece.number); } } }
public bool SendChecker() { // returns true if we're done sending if (file_stream == null ){ return true; } byte[] b; bool received_error = false; b = network.PopReceiveBuffer(); while (b != null){ // we have data in b! Deal with it. FilePiece piece = FilePiece.parse_packet(b); if (piece != null){ if (piece.number > 0){ // do nothing. We are not a receiver! }else if (piece.number == MESSAGE_RESEND){ // we are server! We must re-send this packet. received_error = true; packets_error++; FilePiece specific_piece = new FilePiece(piece.number, file_stream.GetSpecificChunk(piece.number)); network.send(specific_piece.get_packet()); bytes_sent += specific_piece.get_packet_size(); } } b = network.PopReceiveBuffer(); } if (file_stream.GetFileStatus()){ return true; // done sending, just sending corrections } // now that we're caught up, adjust the speed based on errors. if (received_error){ sending_speed *= change_with_error_decrease; }else{ sending_speed *= change_without_error_increase; } // returns true if all pieces have been sent. //Does some sending if there are things to send if (!file_stream.GetFileStatus()){ double time_spent = (DateTime.Now.AddSeconds(1) - start_time).TotalSeconds; while (sending_speed > (double)bytes_sent/(double)time_spent){ FilePiece fp = file_stream.GetNextPiece(); if (fp != null){ byte[] bytes = fp.get_packet(); if (bytes != null){ network.send(bytes); bytes_sent += bytes.Length; }else{ // exit loop if we're done sending file return true; } }else{ return true; } } return false; }else{ // file stream is done, so we're done sending! return true; } }