00001 using System;
00002 using System.Collections.Generic;
00003 using System.Text;
00004 using System.IO;
00005 using System.Net;
00006 using System.Net.Sockets;
00007 using NUnit.Framework;
00008
00009 namespace DCPlusPlus
00010 {
00011 [TestFixture]
00012 public class Peer : Connection
00013 {
00014
00015
00016
00017
00018
00019
00020 public delegate void ConnectedEventHandler(Peer peer);
00021 public event ConnectedEventHandler Connected;
00022 public delegate void DisconnectedEventHandler(Peer peer);
00023 public event DisconnectedEventHandler Disconnected;
00024 public delegate void UnableToConnectEventHandler(Peer peer);
00025 public event UnableToConnectEventHandler UnableToConnect;
00026 public delegate void HandShakeCompletedEventHandler(Peer peer);
00027 public event HandShakeCompletedEventHandler HandShakeCompleted;
00028 public delegate void CompletedEventHandler(Peer peer);
00029 public event CompletedEventHandler Completed;
00030 public delegate void DataReceivedEventHandler(Peer peer);
00031 public event DataReceivedEventHandler DataReceived;
00032 public enum FileRequestAnswer
00033 {
00034 FileNotAvailable, NoFreeSlots, LetsGo
00035 }
00036 public delegate FileRequestAnswer FileRequestReceivedEventHandler(Peer peer);
00037 public event FileRequestReceivedEventHandler FileRequestReceived;
00038 public delegate FileRequestAnswer FileListRequestReceivedEventHandler(Peer peer);
00039 public event FileListRequestReceivedEventHandler FileListRequestReceived;
00040 protected string peer_nick = "unknown";
00041 public string PeerNick
00042 {
00043 get
00044 {
00045 return (peer_nick);
00046 }
00047 set
00048 {
00049 peer_nick = value;
00050 }
00051 }
00052 private int start_tick = 0;
00053 protected long tthl_size = 0;
00054 public long TTHLSize
00055 {
00056 get
00057 {
00058 return (tthl_size);
00059 }
00060 }
00061 private Stream stream = null;
00062 protected long bytes_already_downloaded = 0;
00063 public long BytesAlreadyDownloaded
00064 {
00065 get
00066 {
00067 return (bytes_already_downloaded);
00068 }
00069 }
00070 protected long bytes_downloaded = 0;
00071 public long BytesDownloaded
00072 {
00073 get
00074 {
00075 return (bytes_downloaded);
00076 }
00077 }
00078 protected long bytes_already_uploaded = 0;
00079 public long BytesAlreadyUploaded
00080 {
00081 get
00082 {
00083 return (bytes_already_uploaded);
00084 }
00085 }
00086 protected long bytes_uploaded = 0;
00087 public long BytesUploaded
00088 {
00089 get
00090 {
00091 return (bytes_uploaded);
00092 }
00093 }
00094 protected float speed = 0;
00095 public float Speed
00096 {
00097 get
00098 {
00099 return (speed);
00100 }
00101 }
00102 protected ConnectionDirection direction = ConnectionDirection.Unknown;
00103 public ConnectionDirection Direction
00104 {
00105 get
00106 {
00107 return (direction);
00108 }
00109 }
00110 protected bool is_downloading = false;
00111 public bool IsDownloading
00112 {
00113 get
00114 {
00115 return (is_downloading);
00116 }
00117 }
00118 protected bool is_uploading = false;
00119 public bool IsUploading
00120 {
00121 get
00122 {
00123 return (is_uploading);
00124 }
00125 }
00126 protected Queue.QueueEntry queue_entry = new Queue.QueueEntry();
00127 public Queue.QueueEntry QueueEntry
00128 {
00129 get
00130 {
00131 return (queue_entry);
00132 }
00133 }
00134 protected Queue.QueueEntry.Source source = new Queue.QueueEntry.Source();
00135 public Queue.QueueEntry.Source Source
00136 {
00137 get
00138 {
00139 return (source);
00140 }
00141 }
00142 protected long upload_offset = 0;
00143 public long UploadOffset
00144 {
00145 get
00146 {
00147 return (upload_offset);
00148 }
00149 }
00150 protected long upload_length = 0;
00151 public long UploadLength
00152 {
00153 get
00154 {
00155 return (upload_length);
00156 }
00157 }
00158 protected string upload_request_filename = "";
00159 public string UploadRequestFilename
00160 {
00161 get
00162 {
00163 return (upload_request_filename);
00164 }
00165 }
00166 protected string upload_filename = "";
00167 public string UploadFilename
00168 {
00169 get
00170 {
00171 return (upload_filename);
00172 }
00173 set
00174 {
00175 upload_filename = value;
00176 }
00177 }
00178 protected byte[] upload_file_list_data = null;
00179 public byte[] UploadFileListData
00180 {
00181 get
00182 {
00183 return (upload_file_list_data);
00184 }
00185 set
00186 {
00187 upload_file_list_data = value;
00188 }
00189 }
00190 private bool first_bytes_received = false;
00191
00192 private int handshake_my_value = 0;
00193 private int handshake_his_value = 0;
00194 private ConnectionDirection his_direction_wish = ConnectionDirection.Unknown;
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 private void StartReceiving()
00230 {
00231 try
00232 {
00233 if (socket.Connected)
00234 {
00235 AsyncCallback event_receive = new AsyncCallback(OnReceive);
00236 receive_buffer = new byte[32768];
00237 socket.BeginReceive(receive_buffer, 0, receive_buffer.Length, SocketFlags.None, event_receive, socket);
00238 }
00239 else
00240 {
00241 Console.WriteLine("Connection to peer aborted.");
00242 error_code = ErrorCodes.Disconnected;
00243 Disconnect();
00244 }
00245
00246 }
00247 catch (Exception ex)
00248 {
00249 Console.WriteLine("Error during starting of receiving data from peer: " + ex.Message);
00250 error_code = ErrorCodes.Disconnected;
00251 Disconnect();
00252 }
00253
00254 }
00255 private void WriteDataToFile(int bytes_start, int bytes_end)
00256 {
00257 if (!first_bytes_received)
00258 {
00259 if (queue_entry.TryToClaimEntry(this))
00260 {
00261 first_bytes_received = true;
00262 }
00263 else
00264 {
00265 Console.WriteLine("Queue Entry already in use , disconnecting.");
00266 error_code = ErrorCodes.QueueEntryInUse;
00267 Disconnect();
00268 }
00269 }
00270 bytes_downloaded += bytes_end - bytes_start;
00271
00272 speed = (float)(((float)bytes_downloaded / 1024.0f) / ((float)(System.Environment.TickCount - start_tick) / 1000.0f));
00273
00274 if (stream == null)
00275 {
00276 if(queue_entry.WantTTHL)
00277 stream = new FileStream(queue_entry.OutputFilename+".tthl", FileMode.Create, FileAccess.Write, System.IO.FileShare.ReadWrite);
00278 else
00279 stream = new FileStream(queue_entry.OutputFilename, FileMode.Create, FileAccess.Write, System.IO.FileShare.ReadWrite);
00280 }
00281 stream.Write(receive_buffer, bytes_start, bytes_end);
00282 stream.Flush();
00283 if (DataReceived != null)
00284 DataReceived(this);
00285 if (queue_entry.WantTTHL)
00286 {
00287 if (tthl_size > 0 && bytes_downloaded + bytes_already_downloaded == tthl_size)
00288 {
00289 queue_entry.WantTTHL = false;
00290 queue_entry.UnclaimEntry();
00291
00292
00293 if (!CheckForExtension("ADCGet"))
00294 SendCommand("Send");
00295 error_code = ErrorCodes.NoErrorYet;
00296 Disconnect();
00297 }
00298 }
00299 else
00300 {
00301 if (queue_entry.Filesize > 0 && bytes_downloaded + bytes_already_downloaded == queue_entry.Filesize)
00302 {
00303 if (Completed != null)
00304 Completed(this);
00305 if (!CheckForExtension("ADCGet"))
00306 SendCommand("Send");
00307 error_code = ErrorCodes.NoErrorYet;
00308 Disconnect();
00309 }
00310 }
00311
00312 }
00313 private void OnReceive(IAsyncResult result)
00314 {
00315 try
00316 {
00317 Socket receive_socket = (Socket)result.AsyncState;
00318
00319 if (!receive_socket.Connected)
00320 {
00321
00322 if (queue_entry.Filesize > 0 && bytes_downloaded + bytes_already_downloaded == queue_entry.Filesize)
00323 {
00324 if (Completed != null)
00325 Completed(this);
00326 error_code = ErrorCodes.Disconnected;
00327 Disconnect();
00328 return;
00329 }
00330 if (first_bytes_received)
00331 queue_entry.UnclaimEntry();
00332 Console.WriteLine("Connection to peer dropped.");
00333
00334
00335 error_code = ErrorCodes.Disconnected;
00336 Disconnect();
00337 return;
00338 }
00339 int received_bytes = receive_socket.EndReceive(result);
00340 if (received_bytes > 0)
00341 {
00342 if (is_downloading)
00343 {
00344 WriteDataToFile(0, received_bytes);
00345 }
00346 else
00347 {
00348 string received_string = System.Text.Encoding.Default.GetString(receive_buffer, 0, received_bytes);
00349
00350
00351 int bytes_used = InterpretReceivedString(received_string);
00352 if (bytes_used != -1 && bytes_used < received_bytes)
00353 {
00354 WriteDataToFile(bytes_used, received_bytes);
00355 }
00356 }
00357 AsyncCallback event_receive = new AsyncCallback(OnReceive);
00358 receive_socket.BeginReceive(receive_buffer, 0, receive_buffer.Length, SocketFlags.None, event_receive, receive_socket);
00359 }
00360 else
00361 {
00362 if (queue_entry.Filesize > 0 && bytes_downloaded + bytes_already_downloaded == queue_entry.Filesize)
00363 {
00364 if (Completed != null)
00365 Completed(this);
00366 error_code = ErrorCodes.Disconnected;
00367 Disconnect();
00368 return;
00369 }
00370 if (first_bytes_received)
00371 queue_entry.UnclaimEntry();
00372 Console.WriteLine("Connection to peer dropped.");
00373 error_code = ErrorCodes.Disconnected;
00374 Disconnect();
00375 }
00376 }
00377 catch (Exception ex)
00378 {
00379
00380 if (queue_entry.Filesize > 0 && bytes_downloaded + bytes_already_downloaded == queue_entry.Filesize)
00381 {
00382 if (Completed != null)
00383 Completed(this);
00384 if (stream == null)
00385 stream.Close();
00386 return;
00387 }
00388 if (first_bytes_received)
00389 queue_entry.UnclaimEntry();
00390 Console.WriteLine("Error receiving data from Peer: " + ex.Message);
00391 error_code = ErrorCodes.Exception;
00392 Disconnect();
00393 }
00394
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564 public enum ConnectionDirection
00565 {
00566
00567 Upload, Download, Unknown
00568 }
00569 public void GetFileList(Queue.QueueEntry entry)
00570 {
00571
00572 this.queue_entry = entry;
00573 this.source = entry.Sources[0];
00574 direction = ConnectionDirection.Download;
00575 long start_pos = 1;
00576 if (File.Exists(queue_entry.OutputFilename))
00577 {
00578 File.Delete(queue_entry.OutputFilename);
00579 }
00580
00581 string filename = "MyList.DcLst";
00582 if (CheckForExtension("XmlBZList"))
00583 filename = "files.xml.bz2";
00584 else if (CheckForExtension("BZList"))
00585 filename = "MyList.bz2";
00586
00587 source.Filename = filename;
00588
00589 if (CheckForExtension("ADCGet"))
00590 {
00591 start_pos = start_pos - 1;
00592 SendCommand("ADCGET", "file " + source.Filename + " " + start_pos + " -1");
00593 Console.WriteLine("Trying to adc-fetch filelist(" + filename + ") from: '" + entry.Sources[0].UserName + "'");
00594 }
00595 else
00596 {
00597 SendCommand("Get", filename + "$" + start_pos);
00598 Console.WriteLine("Trying to fetch filelist(" + filename + ") from: '" + entry.Sources[0].UserName + "'");
00599 }
00600
00601 }
00602 public void GetTTHL(Queue.QueueEntry entry)
00603 {
00604 this.queue_entry = entry;
00605
00606
00607 direction = ConnectionDirection.Download;
00608 long start_pos = 0;
00609 if (File.Exists(queue_entry.OutputFilename + ".tthl"))
00610 {
00611 File.Delete(queue_entry.OutputFilename + ".tthl");
00612 }
00613
00614 bytes_already_downloaded = 0;
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 if (CheckForExtension("ADCGet") && CheckForExtension("TTHL") && CheckForExtension("TTHF") && queue_entry.HasTTH)
00631 {
00632 SendCommand("ADCGET", "tthl TTH/" + queue_entry.TTH + " " + start_pos + " -1");
00633
00634
00635 Console.WriteLine("Trying to adc-fetch tthl for file(" + entry.OutputFilename + ")");
00636 }
00637 else
00638 {
00639 Console.WriteLine("Trying to fetch tthl for file(" + entry.OutputFilename+") from: '" + source.UserName + "' that doesn't support it");
00640 }
00641
00642 }
00643 public void SendMaxedOut()
00644 {
00645 SendCommand("MaxedOut");
00646 error_code = ErrorCodes.NoErrorYet;
00647 Disconnect();
00648 }
00649 public void SendFileNotAvailableError()
00650 {
00651 SendError("File Not Available");
00652 error_code = ErrorCodes.NoErrorYet;
00653 Disconnect();
00654 }
00655 public void SendError(string message)
00656 {
00657 SendCommand("Error", message);
00658 }
00659 public void SendFailed(string message)
00660 {
00661 SendCommand("Failed", message);
00662 }
00663 public bool StartUpload()
00664 {
00665 direction = ConnectionDirection.Upload;
00666 if (!string.IsNullOrEmpty(upload_filename))
00667 {
00668 if (upload_file_list_data != null)
00669 {
00670 upload_length = upload_file_list_data.Length;
00671 stream = new MemoryStream(upload_file_list_data);
00672 stream.Seek(upload_offset, SeekOrigin.Begin);
00673 }
00674 else
00675 {
00676 if (File.Exists(upload_filename))
00677 {
00678 FileInfo fi = new FileInfo(upload_filename);
00679 if (fi.Length < upload_offset)
00680 {
00681 Console.WriteLine("error requesting data at offset: " + fi.Length + " after file end: " + upload_offset);
00682 Disconnect();
00683 return (false);
00684 }
00685 if (fi.Length < upload_offset + upload_length || upload_length == -1)
00686 {
00687 upload_length = fi.Length - upload_offset;
00688 }
00689
00690 try
00691 {
00692 stream = new FileStream(upload_filename, FileMode.Open, FileAccess.Read, System.IO.FileShare.ReadWrite);
00693 stream.Seek(upload_offset, SeekOrigin.Begin);
00694 }
00695 catch (Exception ex)
00696 {
00697 Console.WriteLine("exception opening file: " + ex.Message);
00698 SendFileNotAvailableError();
00699 return (false);
00700 }
00701 }
00702 else
00703 {
00704 Console.WriteLine("Requested file not found: " + upload_filename);
00705 SendFileNotAvailableError();
00706 return (false);
00707 }
00708 }
00709 if (CheckForExtension("ADCGet"))
00710 {
00711
00712 string send_parameters = "file " + upload_request_filename + " " + upload_offset + " " + upload_length;
00713 Console.WriteLine("adc send parameters : " + send_parameters);
00714 SendCommand("ADCSND", send_parameters);
00715 Console.WriteLine("Trying to adc-upload file: '" + upload_filename + "' starting from pos:" + upload_offset + " length: " + upload_length);
00716 StartUploadTransfer();
00717 }
00718 else
00719 {
00720 SendCommand("FileLength", upload_length.ToString());
00721 Console.WriteLine("Trying to upload file: '" + upload_filename + "' starting from pos:" + upload_offset + " length: " + upload_length);
00722 }
00723 return (true);
00724 }
00725 return (false);
00726 }
00727 private long upload_block_size = 1024;
00728 public void StartUploadTransfer()
00729 {
00730 is_uploading = true;
00731 start_tick = System.Environment.TickCount;
00732 bytes_uploaded = 0;
00733 if (socket != null)
00734 {
00735 if (!socket.Connected) return;
00736 try
00737 {
00738 if (upload_length < upload_block_size) upload_block_size = upload_length;
00739 byte[] send_bytes = new byte[upload_block_size];
00740 int bytes_read = stream.Read(send_bytes, (int)0, (int)upload_block_size);
00741 Console.WriteLine("Sending the first " + bytes_read + " byte(s) of file: " + upload_request_filename);
00742 socket.BeginSend(send_bytes, 0, bytes_read, SocketFlags.None, new AsyncCallback(UploadTransferCallback), socket);
00743
00744 }
00745 catch (Exception e)
00746 {
00747 Console.WriteLine("Error sending command to peer: " + e.Message);
00748 error_code = ErrorCodes.Exception;
00749 Disconnect();
00750 }
00751 }
00752
00753 }
00754 protected void UploadTransferCallback(IAsyncResult ar)
00755 {
00756 Socket upload_data_socket = (Socket)ar.AsyncState;
00757 try
00758 {
00759 int bytes_sent = upload_data_socket.EndSend(ar);
00760 bytes_uploaded += bytes_sent;
00761 if (socket != null)
00762 {
00763 if (bytes_uploaded == upload_length)
00764 {
00765 error_code = ErrorCodes.NoErrorYet;
00766 Disconnect();
00767 return;
00768 }
00769 if (!socket.Connected) return;
00770 if (upload_length - bytes_uploaded < upload_block_size) upload_block_size = upload_length - bytes_uploaded;
00771 byte[] send_bytes = new byte[upload_block_size];
00772
00773 int bytes_read = stream.Read(send_bytes, 0, (int)upload_block_size);
00774
00775
00776 socket.BeginSend(send_bytes, 0, bytes_read, SocketFlags.None, new AsyncCallback(UploadTransferCallback), socket);
00777
00778 }
00779
00780 }
00781 catch (Exception ex)
00782 {
00783 Console.WriteLine("exception during sending of data: " + ex.Message);
00784 error_code = ErrorCodes.Exception;
00785 Disconnect();
00786 }
00787 }
00788 public void StartDownloadTransfer()
00789 {
00790 is_downloading = true;
00791 start_tick = System.Environment.TickCount;
00792 bytes_downloaded = 0;
00793 if (!CheckForExtension("ADCGet"))
00794 {
00795 SendCommand("Send");
00796 }
00797 }
00798 public void StartDownload()
00799 {
00800 direction = ConnectionDirection.Download;
00801 long start_pos = 1;
00802 if (File.Exists(queue_entry.OutputFilename))
00803 {
00804 FileInfo fi = new FileInfo(queue_entry.OutputFilename);
00805 if (fi.Length >= queue_entry.Filesize)
00806 {
00807 Disconnect();
00808 return;
00809 }
00810 start_pos = fi.Length + 1;
00811 bytes_already_downloaded = fi.Length;
00812 stream = new FileStream(queue_entry.OutputFilename, FileMode.Append, FileAccess.Write, System.IO.FileShare.ReadWrite);
00813 }
00814 else start_pos = 1;
00815
00816 if (CheckForExtension("ADCGet"))
00817 {
00818 start_pos = start_pos - 1;
00819 if (CheckForExtension("TTHF") && queue_entry.HasTTH)
00820 SendCommand("ADCGET", "file TTH/" + queue_entry.TTH + " " + start_pos + " " + (queue_entry.Filesize - start_pos));
00821 else SendCommand("ADCGET", "file " + source.Filename + " " + start_pos + " " + (queue_entry.Filesize - start_pos));
00822 Console.WriteLine("Trying to adc-fetch file: '" + source.Filename + "' starting from pos:" + start_pos);
00823 }
00824 else
00825 {
00826 SendCommand("Get", source.Filename + "$" + start_pos);
00827 Console.WriteLine("Trying to fetch file: '" + source.Filename + "' starting from pos:" + start_pos);
00828 }
00829 }
00830 public void StartDownload(Queue.QueueEntry.Source source, Queue.QueueEntry entry)
00831 {
00832 this.queue_entry = entry;
00833 this.source = source;
00834 StartDownload();
00835 }
00836 public void StartDownload(string filename, string output_filename, long output_file_length)
00837 {
00838
00839
00840 queue_entry = new Queue.QueueEntry();
00841 queue_entry.OutputFilename = output_filename;
00842 queue_entry.Filesize = output_file_length;
00843 source = new Queue.QueueEntry.Source();
00844 source.Filename = filename;
00845 StartDownload();
00846 }
00856 private int InterpretReceivedString(string received_string)
00857 {
00858
00859 string[] received_strings = received_string.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
00860 int interpreter_pos = 0;
00861 for (int i = 0; i < received_strings.Length; i++)
00862 {
00863 interpreter_pos += received_strings[i].Length + 1;
00864 if (received_strings[i].StartsWith("$"))
00865 {
00866 if (InterpretCommand(received_strings[i]))
00867 return (interpreter_pos);
00868 }
00869 else Console.WriteLine("Received a non command line: " + received_strings[i]);
00870 }
00871 return (-1);
00872
00873 }
00882 private bool InterpretCommand(string received_command)
00883 {
00884 int command_end = received_command.IndexOf(" ");
00885 if (command_end == -1) command_end = received_command.Length;
00886
00887 if (command_end != -1)
00888 {
00889 string parameter = "";
00890 string[] parameters ={ };
00891 string command = received_command.Substring(1);
00892 if (command_end != received_command.Length)
00893 {
00894 command = received_command.Substring(1, command_end - 1);
00895 parameter = received_command.Substring(command_end + 1);
00896 parameters = parameter.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
00897 }
00898
00899
00900 switch (command)
00901 {
00902 case "Direction":
00903
00904 handshake_his_value = int.Parse(parameters[1]);
00905 if (parameters[0] == "Download")
00906 his_direction_wish = ConnectionDirection.Upload;
00907 else his_direction_wish = ConnectionDirection.Download;
00908 DecideDirection();
00909 break;
00910
00911 case "MyNick":
00912 peer_nick = parameters[0];
00913
00914
00915 break;
00916
00917 case "Supports":
00918
00919 supports = (string[])parameters.Clone();
00920 break;
00921
00922 case "MaxedOut":
00923 error_code = ErrorCodes.NoFreeSlots;
00924 Disconnect();
00925 break;
00926 case "Error":
00927 error_code = ErrorCodes.NoErrorYet;
00928 if (parameter == "File not found" || parameter == "File Not Available")
00929 error_code = ErrorCodes.FileNotAvailable;
00930 Disconnect();
00931 break;
00932
00933 case "GetListLen":
00934
00935 break;
00936
00937 case "ADCGET":
00938 case "Get":
00939 if (command == "ADCGET")
00940 {
00941 Console.WriteLine("ADCGET command received: " + parameter);
00942 upload_request_filename = parameters[1];
00943 try
00944 {
00945 upload_offset = long.Parse(parameters[2]);
00946 upload_length = long.Parse(parameters[3]);
00947 }
00948 catch (Exception ex)
00949 {
00950 Console.WriteLine("error parsing offsets: " + ex.Message);
00951 }
00952 }
00953 else if (command == "Get")
00954 {
00955 Console.WriteLine("Get command received: " + parameter);
00956 int offset_start = parameter.LastIndexOf("$");
00957 if (offset_start == -1)
00958 break;
00959 long offset = 1;
00960 string filename = parameter.Substring(0, offset_start);
00961 try
00962 {
00963 offset = long.Parse(parameter.Substring(offset_start + 1));
00964 }
00965 catch (Exception ex)
00966 {
00967 Console.WriteLine("error parsing offset: " + ex.Message);
00968 }
00969 upload_request_filename = filename;
00970 upload_offset = offset - 1;
00971 upload_length = -1;
00972 }
00973 FileRequestAnswer answer = FileRequestAnswer.FileNotAvailable;
00974 if (upload_request_filename == "MyList.DcLst" || upload_request_filename == "MyList.bz2")
00975 {
00976 SendFileNotAvailableError();
00977 error_code = ErrorCodes.FileNotAvailable;
00978 Disconnect();
00979 }
00980 else if (upload_request_filename == "files.xml.bz2")
00981 {
00982 if (FileListRequestReceived != null)
00983 answer = FileListRequestReceived(this);
00984 }
00985 else
00986 {
00987 if (FileRequestReceived != null)
00988 answer = FileRequestReceived(this);
00989 }
00990
00991
00992 if (answer == FileRequestAnswer.LetsGo)
00993 {
00994 Console.WriteLine("Ok lets go , upload something.");
00995 if (!StartUpload())
00996 {
00997 Console.WriteLine("Upload starting failed.Disconnecting...");
00998 Disconnect();
00999 }
01000 }
01001 else if (answer == FileRequestAnswer.FileNotAvailable)
01002 {
01003 Console.WriteLine("Sorry file not found replied.");
01004 SendFileNotAvailableError();
01005 Disconnect();
01006 }
01007 else if (answer == FileRequestAnswer.NoFreeSlots)
01008 {
01009 Console.WriteLine("Sorry no free slot for you.");
01010 SendMaxedOut();
01011 Disconnect();
01012 }
01013 break;
01014
01015 case "Send":
01016 Console.WriteLine("Send command received: " + parameter);
01017 StartUploadTransfer();
01018 break;
01019
01020 case "ADCSND":
01021 Console.WriteLine("ADCSEND command received: " + parameter);
01022 try
01023 {
01024 long temp_upload_offset = long.Parse(parameters[2]);
01025 long temp_upload_length = long.Parse(parameters[3]);
01026 if (queue_entry.Type == Queue.QueueEntry.EntryType.File && !queue_entry.WantTTHL && (temp_upload_length + temp_upload_offset) != queue_entry.Filesize) Disconnect();
01027 if (queue_entry.Type == Queue.QueueEntry.EntryType.FileList)
01028 queue_entry.Filesize = temp_upload_offset + temp_upload_length;
01029 if (queue_entry.Type == Queue.QueueEntry.EntryType.File && queue_entry.WantTTHL)
01030 tthl_size = temp_upload_length;
01031 }
01032 catch (Exception ex) { Console.WriteLine("Error parsing file length: " + ex.Message); }
01033 StartDownloadTransfer();
01034 return (true);
01035
01036
01037
01038 case "FileLength":
01039 Console.WriteLine("FileLength command received: " + parameter);
01040 try
01041 {
01042 long filelength = long.Parse(parameters[0]);
01043 if (queue_entry.Type == Queue.QueueEntry.EntryType.File && filelength != queue_entry.Filesize) Disconnect();
01044 if (queue_entry.Type == Queue.QueueEntry.EntryType.FileList)
01045 queue_entry.Filesize = filelength;
01046 }
01047 catch (Exception ex) { Console.WriteLine("Error parsing file length: " + ex.Message); }
01048 StartDownloadTransfer();
01049 break;
01050
01051 case "Key":
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077 break;
01078
01079 case "Lock":
01080
01081 if (parameters.Length > 1)
01082 {
01083 string key = parameters[0];
01084
01085 if (key.StartsWith("EXTENDEDPROTOCOL"))
01086 {
01087 is_extended_protocol = true;
01088
01089 SendCommand("Supports", "MiniSlots XmlBZList TTHL TTHF ADCGet");
01090
01091
01092
01093 }
01094
01095 string decoded_key = L2K(key);
01096 Random rnd = new Random();
01097 handshake_my_value = rnd.Next(32767);
01098
01099 if (direction == ConnectionDirection.Upload)
01100 SendCommand("Direction", "Upload " + handshake_my_value.ToString());
01101 else SendCommand("Direction", "Download " + handshake_my_value.ToString());
01102
01103 DecideDirection();
01104
01105
01106 SendCommand("Key", decoded_key);
01107
01108
01109 }
01110 break;
01111
01112 default:
01113 Console.WriteLine("Unknown Command received: " + command + ", Parameter: " + parameter);
01114 break;
01115 }
01116 }
01117 else Console.WriteLine("Error interpreting command: " + received_command);
01118 return (false);
01119 }
01120 private void DecideDirection()
01121 {
01122 if (direction == ConnectionDirection.Unknown && his_direction_wish != ConnectionDirection.Unknown)
01123 {
01124 if (handshake_my_value < handshake_his_value)
01125 direction = his_direction_wish;
01126 else direction = ConnectionDirection.Download;
01127
01128 try
01129 {
01130 if (HandShakeCompleted != null)
01131 HandShakeCompleted(this);
01132
01133 }
01134 catch (Exception ex)
01135 {
01136 Console.WriteLine("Exception in Handshake Event: " + ex.Message);
01137 }
01138
01139 }
01140 }
01141 public Peer(Socket client, string nick)
01142 {
01143 this.nick = nick;
01144 this.socket = client;
01145 is_connected = true;
01146 StartReceiving();
01147 }
01148 public Peer(Socket client)
01149 {
01150 is_connected = true;
01151 this.socket = client;
01152 StartReceiving();
01153 }
01154 public Peer(string dst_ip, int dst_port)
01155 {
01156 ip = dst_ip;
01157 port = dst_port;
01158 }
01159 public Peer(string address)
01160 {
01161 string tmp = address;
01162 int port_start = tmp.IndexOf(":");
01163 if (port_start != -1)
01164 {
01165 int tmp_port = 411;
01166 string tmp_port_string = tmp.Substring(port_start + 1);
01167 try
01168 {
01169 tmp_port = int.Parse(tmp_port_string);
01170 }
01171 catch (Exception)
01172 {
01173 Console.WriteLine("error parsing port : " + tmp_port_string);
01174 }
01175
01176 tmp = tmp.Substring(0, port_start);
01177 port = tmp_port;
01178 }
01179 ip = tmp;
01180 }
01181 public Peer()
01182 {
01183 ip = "";
01184 port = 0;
01185 socket = null;
01186 }
01187 public void StartHandShake()
01188 {
01189 SendCommand("MyNick", nick);
01190 string key = CreateKey(false);
01191
01192 SendCommand("Lock", key);
01193 }
01194 public override void Disconnect()
01195 {
01196 if (stream != null)
01197 {
01198 stream.Close();
01199 }
01200 if (is_connected || is_connecting)
01201 {
01202 if (socket != null)
01203 {
01204
01205
01206 this.socket.Close();
01207 } else Console.WriteLine("This socket is unused -> no disconnect needed.");
01208
01209 if (is_connected)
01210 {
01211 if (Disconnected != null)
01212 Disconnected(this);
01213 }
01214 else if (is_connecting)
01215 {
01216 if (UnableToConnect != null)
01217 UnableToConnect(this);
01218 }
01219 is_connected = false;
01220 is_connecting = false;
01221 is_downloading = false;
01222 is_uploading = false;
01223
01224 }
01225 }
01226 public void Connect()
01227 {
01228 if (is_connecting)
01229 {
01230 error_code = ErrorCodes.UserDisconnect;
01231 Disconnect();
01232 }
01233 if (!is_connected)
01234 {
01235 try
01236 {
01237 is_connecting = true;
01238
01239 socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
01240 socket.Blocking = false;
01241 IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(ip), port);
01242 AsyncCallback event_connect = new AsyncCallback(OnConnect);
01243 socket.BeginConnect(endpoint, event_connect, socket);
01244 socket.ReceiveTimeout = 500;
01245 socket.SendTimeout = 500;
01246 }
01247 catch (Exception ex)
01248 {
01249 Console.WriteLine("Error connecting to Peer: " + ip + ":" + port + "(exception:" + ex.Message + ")");
01250 error_code = ErrorCodes.UnableToConnect;
01251 Disconnect();
01252 }
01253 }
01254
01255 }
01256 public void ConnectTo(string dst_ip, int dst_port)
01257 {
01258 ip = dst_ip;
01259 port = dst_port;
01260 Connect();
01261 }
01262 private void OnConnect(IAsyncResult result)
01263 {
01264 Socket connect_socket = (Socket)result.AsyncState;
01265 try
01266 {
01267 if (connect_socket.Connected)
01268 {
01269 AsyncCallback event_receive = new AsyncCallback(OnReceive);
01270 receive_buffer = new byte[32768];
01271 connect_socket.BeginReceive(receive_buffer, 0, receive_buffer.Length, SocketFlags.None, event_receive, connect_socket);
01272
01273 is_connected = true;
01274 is_connecting = false;
01275 if (Connected != null)
01276 Connected(this);
01277 }
01278 else
01279 {
01280
01281 error_code = ErrorCodes.UnableToConnect;
01282 Disconnect();
01283 }
01284 }
01285 catch (Exception ex)
01286 {
01287 Console.WriteLine("Error during connect to peer(exception:" + ex.Message + ").");
01288 error_code = ErrorCodes.UnableToConnect;
01289 Disconnect();
01290 }
01291 }
01292 public void Ungrab()
01293 {
01294
01295
01296 }
01297 }
01298 }