Eigene Dateien/Visual Studio 2005/Projects/DCPlusPlus/DCPlusPlus/Peer.cs

Go to the documentation of this file.
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         //TODO 
00015         //rewrite notes : download,upload,reuse connection,check of data during download
00016         //                resume,download block in middle of the file (also after file_end and add zeros before)
00017         //                simplify byte counters , tthl download , download to file or queue entry field
00018         //                filelists
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         //handshake randoms for priority selection
00192         private int handshake_my_value = 0;
00193         private int handshake_his_value = 0;
00194         private ConnectionDirection his_direction_wish = ConnectionDirection.Unknown;
00195         //private ConnectionDirection my_direction_wish = ConnectionDirection.Unknown;
00196 
00197 
00198         /*
00199         
00200         protected long filelength = 0;
00201         public long FileLength
00202         {
00203             get
00204             {
00205                 return (filelength);
00206             }
00207         }
00208 
00209         protected string output_filename="";
00210         public string OutputFilename
00211         {
00212             get
00213             {
00214                 return (output_filename);
00215             }
00216 
00217         }
00218 
00219         protected string filename = "";
00220         public string Filename
00221         {
00222             get
00223             {
00224                 return (filename);
00225             }
00226         }
00227         */
00228         //protected string input_filename="";
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)) //TODO -> this can be moved to client with an event handler (FirstBytesReceived(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             //TODO quite buggy divide by zero prob
00272             speed = (float)(((float)bytes_downloaded / 1024.0f) / ((float)(System.Environment.TickCount - start_tick) / 1000.0f));
00273             //Console.WriteLine("Received " + received_bytes + " bytes of data. with a speed of: " + (((System.Environment.TickCount - start_tick) / 1000) / (bytes_downloaded / 1024)) + " KB/s");
00274             if (stream == null)
00275             {//if we do not append we still have to create the output file
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                     /*if (Completed != null)
00292                         Completed(this);*/
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                 //Console.WriteLine("Connection socket.");
00319                 if (!receive_socket.Connected)
00320                 {
00321                     //Console.WriteLine("Connection connected.");
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)//we need to unclaim our used entry too
00331                         queue_entry.UnclaimEntry();
00332                     Console.WriteLine("Connection to peer dropped.");
00333                     /*if (Disconnected != null)
00334                         Disconnected(this);*/
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                         //Console.WriteLine("Received a string: "+received_string);
00350                         //interpret string and act accordingly
00351                         int bytes_used = InterpretReceivedString(received_string);
00352                         if (bytes_used != -1 && bytes_used < received_bytes)
00353                         {//we already received some data from the file ... 
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) //we need to unclaim our used entry too
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                 //Console.WriteLine("Exception during receive of data: " + ex.Message);
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         private void OnReceive(IAsyncResult result)
00398         {
00399             Socket receive_socket = (Socket)result.AsyncState;
00400             try
00401             {
00402                 if (!receive_socket.Connected)
00403                 {
00404                     try
00405                     {
00406                         if (queue_entry.Filesize > 0 && bytes_downloaded + bytes_already_downloaded == queue_entry.Filesize)
00407                         {
00408                             try
00409                             {
00410                                 if (Completed != null)
00411                                     Completed(this);
00412                                 return;
00413                             }
00414                             catch (Exception ex)
00415                             {
00416                                 Console.WriteLine("Exception in Completed Event: " + ex.Message);
00417                             }
00418                         }
00419                         if (first_bytes_received)
00420                             queue_entry.IsInUse = false;
00421                         Console.WriteLine("Connection to peer dropped.");
00422 
00423                         if (Disconnected != null)
00424                             Disconnected(this);
00425 
00426                     }
00427                     catch (Exception ex)
00428                     {
00429                         Console.WriteLine("Exception in Disconnected Event: " + ex.Message);
00430                     }
00431 
00432 
00433                 }
00434                 int received_bytes = receive_socket.EndReceive(result);
00435                 if (received_bytes > 0)
00436                 {
00437                     if (is_downloading)
00438                     {
00439                         if (!first_bytes_received)
00440                         {
00441                             if (queue_entry.TryToClaimEntry())
00442                             {
00443                                 first_bytes_received = true;
00444                             }
00445                             else Disconnect();
00446 
00447                         }
00448 
00449                         bytes_downloaded += received_bytes;
00450                         //TODO quite buggy divide by zero prob
00451                         speed = (float)(((float)bytes_downloaded / 1024.0f) / ((float)(System.Environment.TickCount - start_tick) / 1000.0f));
00452                         //Console.WriteLine("Received " + received_bytes + " bytes of data. with a speed of: " + (((System.Environment.TickCount - start_tick) / 1000) / (bytes_downloaded / 1024)) + " KB/s");
00453 
00454                         if (stream == null) //if we do not append we still have to create the output file
00455                             stream = new FileStream(queue_entry.OutputFilename, FileMode.Create, FileAccess.Write, System.IO.FileShare.ReadWrite);
00456 
00457                         stream.Write(receive_buffer, 0, received_bytes);
00458                         stream.Flush();
00459 
00460                         try
00461                         {
00462                             if (DataReceived != null)
00463                                 DataReceived(this);
00464                         }
00465                         catch (Exception ex)
00466                         {
00467                             Console.WriteLine("Exception in DataReceived Event: " + ex.Message);
00468                         }
00469 
00470                         if (queue_entry.Filesize > 0 && bytes_downloaded + bytes_already_downloaded == queue_entry.Filesize)
00471                         {
00472                             try
00473                             {
00474                                 if (Completed != null)
00475                                     Completed(this);
00476                             }
00477                             catch (Exception ex)
00478                             {
00479                                 Console.WriteLine("Exception in Completed Event: " + ex.Message);
00480                             }
00481                             if (!CheckForExtension("ADCGet"))
00482                                 SendCommand("Send");
00483                             Disconnect();
00484                         }
00485                     }
00486                     else
00487                     {
00488                         //string received_string = Encoding.ASCII.GetString(receive_buffer, 0, received_bytes);
00489                         string received_string = System.Text.Encoding.Default.GetString(receive_buffer, 0, received_bytes);
00490                         //Console.WriteLine("Received a string: "+received_string);
00491                         //interpret string and act accordingly
00492                         InterpretReceivedString(received_string);
00493 
00494                     }
00495                     AsyncCallback event_receive = new AsyncCallback(OnReceive);
00496                     receive_socket.BeginReceive(receive_buffer, 0, receive_buffer.Length, SocketFlags.None, event_receive, receive_socket);
00497                 }
00498                 else
00499                 {
00500                     try
00501                     {
00502                         if (queue_entry.Filesize > 0 && bytes_downloaded + bytes_already_downloaded == queue_entry.Filesize)
00503                         {
00504                             try
00505                             {
00506                                 if (Completed != null)
00507                                     Completed(this);
00508                                 return;
00509                             }
00510                             catch (Exception ex)
00511                             {
00512                                 Console.WriteLine("Exception in Completed Event: " + ex.Message);
00513                             }
00514                         }
00515                         if (first_bytes_received)
00516                             queue_entry.IsInUse = false;
00517                         Console.WriteLine("Connection to peer dropped.");
00518 
00519                         if (Disconnected != null)
00520                             Disconnected(this);
00521 
00522                     }
00523                     catch (Exception ex)
00524                     {
00525                         Console.WriteLine("Exception in Disconnected Event: " + ex.Message);
00526                     }
00527 
00528                 }
00529 
00530             }
00531             catch (Exception ex)
00532             {
00533                 try
00534                 {
00535                     if (queue_entry.Filesize > 0 && bytes_downloaded + bytes_already_downloaded == queue_entry.Filesize)
00536                     {
00537                         try
00538                         {
00539                             if (Completed != null)
00540                                 Completed(this);
00541                             return;
00542                         }
00543                         catch (Exception ex2)
00544                         {
00545                             Console.WriteLine("Exception in Completed Event: " + ex2.Message);
00546                         }
00547                     }
00548                     if (first_bytes_received)
00549                         queue_entry.IsInUse = false;
00550                     Console.WriteLine("Error receiving data from Peer: " + ex.Message);
00551                     if (Disconnected != null)
00552                         Disconnected(this);
00553 
00554                 }
00555                 catch (Exception ex2)
00556                 {
00557                     Console.WriteLine("Exception in Disconnected Event: " + ex2.Message);
00558                 }
00559 
00560             }
00561 
00562         }
00563 */
00564         public enum ConnectionDirection
00565         {
00566             //Incoming,Outgoing
00567             Upload, Download, Unknown
00568         }
00569         public void GetFileList(Queue.QueueEntry entry)
00570         {//try to download a filelist that the peer offers by his supports
00571             //it would be fine to have these converted on the spot to our standard filelist format (files.xml.bz2)
00572             this.queue_entry = entry;
00573             this.source = entry.Sources[0];//filelist queue entry have exactly one source , no more no less
00574             direction = ConnectionDirection.Download;
00575             long start_pos = 1;
00576             if (File.Exists(queue_entry.OutputFilename))
00577             {
00578                 File.Delete(queue_entry.OutputFilename);//delete old filelist if happen to be there
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         {//try to download a tthl block if peer offers this via supports
00604             this.queue_entry = entry;
00605             //this.source = entry.Sources[0];
00606             //this.source = source;
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");//delete old tthl file if happen to be there
00612             }
00613 
00614             bytes_already_downloaded = 0;
00615             /*if (File.Exists(queue_entry.OutputFilename))
00616             {
00617                 FileInfo fi = new FileInfo(queue_entry.OutputFilename);
00618                 if (fi.Length >= queue_entry.Filesize)
00619                 {//abort , file is complete or something else may happened here
00620                     Disconnect();
00621                     return;
00622                 }
00623                 start_pos = fi.Length + 1;
00624                 bytes_already_downloaded = fi.Length;
00625                 stream = new FileStream(queue_entry.OutputFilename, FileMode.Append, FileAccess.Write, System.IO.FileShare.ReadWrite);
00626             }
00627             else start_pos = 1;
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                 //SendCommand("ADCGET", "tthl " + source.Filename + " " + start_pos + " -1");
00634                 //Console.WriteLine("Trying to adc-fetch tthl file(" + entry.OutputFilename + ".tthl) from: '" + source.UserName + "'");
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; //TODO enhance Direction handling -> esp uploading if we have nothing to to download from the user
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                         {//abort , file is complete or something else may happened here
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                         {//abort , file is complete or something else may happened here
00687                             upload_length = fi.Length - upload_offset;
00688                         }
00689                         //Console.WriteLine("Trying to open file: "+f);
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;//TODO make this static and public
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;//TODO maybe better to change back after upload finished .. if we reuse peers
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                     //socket.BeginSend(upload_file_list_data, 0, upload_file_list_data.Length, SocketFlags.None, new AsyncCallback(UploadTransferCallback), socket);
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; //TODO add some download error_code ..and rename the whole thing to something more intuitive
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;//TODO maybe better to change back after upload finished .. if we reuse peers
00771                     byte[] send_bytes = new byte[upload_block_size];
00772                     //int bytes_read = stream.Read(send_bytes, (int)upload_offset + (int)bytes_uploaded, (int)upload_block_size);
00773                     int bytes_read = stream.Read(send_bytes, 0, (int)upload_block_size);
00774                     //Console.WriteLine("Already sent " + bytes_uploaded + " byte(s) of file: " + upload_request_filename);
00775                     //bytes_uploaded += bytes_read;
00776                     socket.BeginSend(send_bytes, 0, bytes_read, SocketFlags.None, new AsyncCallback(UploadTransferCallback), socket);
00777                     //socket.BeginSend(upload_file_list_data, 0, upload_file_list_data.Length, SocketFlags.None, new AsyncCallback(UploadTransferCallback), socket);
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                 {//abort , file is complete or something else may happened here
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             //this.output_filename = output_filename;
00839             //this.filename = filename;
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             //TODO counter possible packet splits in messages
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);//tell the receive handler that we dont want to use any rest bytes from the bytes read in the actual call
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                 //Console.WriteLine("Command: '" + command + "' ,Parameter(" + parameters.Length + "): '" + parameter + "'");
00899 
00900                 switch (command)
00901                 {
00902                     case "Direction":
00903                         //Console.WriteLine("Direction command received: " + parameter);
00904                         handshake_his_value = int.Parse(parameters[1]);
00905                         if (parameters[0] == "Download") //turns arround in terms of our perception of the direction.
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                         //Console.WriteLine("peer nick: "+peer_nick);
00914                         //handshake complete
00915                         break;
00916 
00917                     case "Supports":
00918                         //Console.WriteLine("Supports command received: " + parameter);
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                         //Console.WriteLine("GetListLen command received: " + parameter);
00935                         break;
00936                     //TODO check for correct direction ..else skip ,same for startdownload
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; //no offset given skip this request
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; //we want to send the first byte too , right ?
00971                             upload_length = -1;
00972                         }
00973                         FileRequestAnswer answer = FileRequestAnswer.FileNotAvailable;
00974                         if (upload_request_filename == "MyList.DcLst" || upload_request_filename == "MyList.bz2")
00975                         {//not supported right now,maybe never
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                         //give back answer and maybe disconnect if needed or start upload
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();//fail safe to secure downloads a bit 
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                     //break;
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();//fail safe to secure downloads a bit 
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                         //Console.WriteLine("Key command received: " + parameter);
01053                         //Random rnd = new Random();
01054                         //SendCommand("Direction","Download "+rnd.Next(49999).ToString());
01055                         //SendCommand("GetListLen");
01056 
01057                         /*
01058                         try
01059                         {
01060                             if (HandShakeCompleted != null)
01061                                 HandShakeCompleted(this);
01062 
01063                         }
01064                         catch (Exception ex)
01065                         {
01066                             Console.WriteLine("Exception in Handshake Event: " + ex.Message);
01067                         }
01068                         */
01069 
01070 
01071                         //SendCommand("Get", "extras series\\Extras - S01E05 [digitaldistractions].avi$1");
01072                         //SendCommand("Get", "MyList.DcLst$1");
01073                         //SendCommand("Get", "files.xml.bz2$1");
01074                         //out_stream = System.IO.File.Create("temp.avi");
01075                         //out_stream = new FileStream("temp.avi", FileMode.Create, FileAccess.Write, System.IO.FileShare.ReadWrite);
01076                         //SendCommand("Send");
01077                         break;
01078 
01079                     case "Lock":
01080                         //Console.WriteLine("Lock Command received: " + parameter);
01081                         if (parameters.Length > 1)
01082                         {
01083                             string key = parameters[0];
01084                             //Console.WriteLine("Key: " + key);
01085                             if (key.StartsWith("EXTENDEDPROTOCOL"))
01086                             {
01087                                 is_extended_protocol = true;
01088                                 //Console.WriteLine("Peer is using the dc++ protocol enhancements.");
01089                                 SendCommand("Supports", "MiniSlots XmlBZList TTHL TTHF ADCGet");
01090                                 //SendCommand("Supports", "MiniSlots XmlBZList ADCGet TTHL TTHF GetZBlock ZLIG ");
01091                                 //SendCommand("Supports", "MiniSlots XmlBZList TTHL TTHF GetZBlock ZLIG ");
01092                                 //SendCommand("Supports", "BZList TTHL TTHF GetZBlock´ZLIG ");
01093                             }
01094 
01095                             string decoded_key = L2K(key);
01096                             Random rnd = new Random();
01097                             handshake_my_value = rnd.Next(32767);
01098                             //StartHandShake();
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                             //Console.WriteLine("SendingDecoded key: " + decoded_key);
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             {//only decide once
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; //ip or adress property?
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             //Console.WriteLine("sending lock: '"+key+"'");
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                     //if (socket.Connected)
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                     //else Console.WriteLine("This peer is already disconnected");
01224             }
01225         }
01226         public void Connect()
01227         {
01228             if (is_connecting)
01229             {//better handling of fast user retries
01230                 error_code = ErrorCodes.UserDisconnect;
01231                 Disconnect();
01232             }
01233             if (!is_connected)
01234             {
01235                 try
01236                 {
01237                     is_connecting = true;
01238                     //Disconnect();//if still connected , disconnect first
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                     //Console.WriteLine("Successfully connected to peer: " + ip+":"+port);
01273                     is_connected = true;
01274                     is_connecting = false;
01275                     if (Connected != null)
01276                         Connected(this);
01277                 }
01278                 else
01279                 {
01280                     //Console.WriteLine("Unable to connect to peer");
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             //TODO remove all event handlers
01295             
01296         }
01297     }
01298 }

Generated on Wed Mar 7 19:09:20 2007 for DCPlusPlus by  doxygen 1.5.1-p1