00001 using System;
00002 using System.Collections.Generic;
00003 using System.Text;
00004 using System.Net;
00005 using System.Net.Sockets;
00006 using System.Threading;
00007
00008 namespace DCPlusPlus
00009 {
00016 public class ListeningSockets
00017 {
00022 public delegate void SearchResultReceivedEventHandler(SearchResults.SearchResult result);
00027 public event SearchResultReceivedEventHandler SearchResultReceived;
00032 public event Peer.ConnectedEventHandler PeerConnected;
00033 protected string ip = "";
00037 public string IP
00038 {
00039 get
00040 {
00041 return (ip);
00042 }
00043 }
00044 protected string external_ip = "";
00049 public string ExternalIP
00050 {
00051 get
00052 {
00053 return (external_ip);
00054 }
00055 set
00056 {
00057 external_ip = value;
00058 }
00059 }
00060 protected int tcp_port = 0;
00065 public int TcpPort
00066 {
00067 get
00068 {
00069 return (tcp_port);
00070 }
00071 set
00072 {
00073 tcp_port = value;
00074 }
00075 }
00076 protected int udp_port = 0;
00081 public int UdpPort
00082 {
00083 get
00084 {
00085 return (udp_port);
00086 }
00087 set
00088 {
00089 udp_port = value;
00090 }
00091
00092 }
00093 protected int max_tcp_connections = 100;
00097 public int MaxTcpConnections
00098 {
00099 get
00100 {
00101 return (max_tcp_connections);
00102 }
00103 set
00104 {
00105 max_tcp_connections = value;
00106 }
00107 }
00108
00109
00110
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00146 public ListeningSockets()
00147 {
00148 UpdateIP();
00149 SetupListeningSocket();
00150 }
00155 private void UpdateIP()
00156 {
00157 string host_name = Dns.GetHostName();
00158 IPHostEntry host_entry = Dns.GetHostEntry(host_name);
00159 if (host_entry.AddressList.Length == 0) return;
00160 ip = host_entry.AddressList[0].ToString();
00161 }
00162 protected bool listening = false;
00166 public bool IsListening
00167 {
00168 get
00169 {
00170 return (listening);
00171 }
00172 }
00177 private Socket tcp_socket = null;
00182 private IAsyncResult tcp_callback = null;
00187 private Socket udp_socket = null;
00191 private byte[] receive_from_buffer = new byte[1024];
00196 private IPEndPoint receive_from_endpoint = new IPEndPoint(IPAddress.None, 0);
00202 public void UpdateConnectionSettings()
00203 {
00204 if (listening)
00205 CloseListeningSocket();
00206 SetupListeningSocket();
00207 }
00212 ~ListeningSockets()
00213 {
00214 CloseListeningSocket();
00215 }
00219 public void Close()
00220 {
00221 CloseListeningSocket();
00222 }
00227 private void CloseListeningSocket()
00228 {
00229
00230 lock (listening_lock)
00231 {
00232 if (listening)
00233 {
00234 listening = false;
00235 try
00236 {
00237 if (udp_socket != null)
00238 {
00239 udp_socket.ReceiveTimeout = 0;
00240
00241
00242 udp_socket.Close();
00243
00244 udp_socket = null;
00245 Thread.Sleep(10);
00246 Console.WriteLine("Closed Listening udp socket.");
00247 }
00248 if (tcp_socket != null)
00249 {
00250
00251
00252
00253 tcp_socket.ReceiveTimeout = 0;
00254 tcp_socket.Close();
00255
00256 tcp_socket = null;
00257 Thread.Sleep(10);
00258 Console.WriteLine("Closed Listening tcp socket.");
00259 }
00260
00261 }
00262 catch (Exception ex)
00263 {
00264 Console.WriteLine("Error closing listening socket: " + ex.Message);
00265 }
00266 }
00267 }
00268 }
00272 private object listening_lock = new Object();
00277 private void SetupListeningSocket()
00278 {
00279
00280
00281
00282
00283
00284
00285 lock (listening_lock)
00286 {
00287 if (!listening)
00288 {
00289 listening = true;
00290 if (tcp_socket == null)
00291 {
00292 try
00293 {
00294 tcp_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
00295 IPEndPoint tcp_local_endpoint = new IPEndPoint(IPAddress.Any, tcp_port);
00296 tcp_socket.Bind(tcp_local_endpoint);
00297 tcp_port = ((IPEndPoint)tcp_socket.LocalEndPoint).Port;
00298 tcp_socket.Blocking = false;
00299
00300 tcp_socket.Listen(max_tcp_connections);
00301 AsyncCallback event_accept = new AsyncCallback(OnAccept);
00302 tcp_callback = tcp_socket.BeginAccept(event_accept, tcp_socket);
00303 Console.WriteLine("Bound listening tcp socket to port: " + tcp_port);
00304 }
00305 catch (Exception ex)
00306 {
00307 Console.WriteLine("Exception opening local peer tcp port");
00308 }
00309 }
00310 else Console.WriteLine("tcp port already in use :" + tcp_port);
00311 if (udp_socket == null)
00312 {
00313 try
00314 {
00315 udp_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
00316 IPEndPoint udp_local_endpoint = new IPEndPoint(IPAddress.Any, udp_port);
00317 udp_socket.Bind(udp_local_endpoint);
00318 udp_port = ((IPEndPoint)udp_socket.LocalEndPoint).Port;
00319 udp_socket.Blocking = false;
00320
00321 EndPoint temp_receive_from_endpoint = (EndPoint)receive_from_endpoint;
00322 AsyncCallback event_receive_from = new AsyncCallback(OnReceiveFrom);
00323 udp_socket.BeginReceiveFrom(receive_from_buffer, 0, receive_from_buffer.Length, SocketFlags.None, ref temp_receive_from_endpoint, event_receive_from, udp_socket);
00324 Console.WriteLine("Bound UDP-Channel to port: " + udp_port);
00325 }
00326 catch (Exception ex)
00327 {
00328 Console.WriteLine("Exception opening local peer udp port");
00329 }
00330
00331 }
00332 else Console.WriteLine("udp port already in use :" + udp_port);
00333 }
00334 }
00335 }
00340 private void OnReceiveFrom(IAsyncResult result)
00341 {
00342 if (udp_socket != null)
00343 {
00344 if (!udp_socket.IsBound) return;
00345 try
00346 {
00347 if (udp_socket != ((Socket)result.AsyncState)) return;
00348 Socket receive_from_socket = (Socket)result.AsyncState;
00349 if (receive_from_socket == null) return;
00350
00351
00352
00353 EndPoint temp_receive_from_endpoint = (EndPoint)receive_from_endpoint;
00354
00355 int received_bytes = udp_socket.EndReceiveFrom(result, ref temp_receive_from_endpoint);
00356
00357
00358 if (received_bytes > 0)
00359 {
00360
00361 string received_string = System.Text.Encoding.Default.GetString(receive_from_buffer, 0, received_bytes);
00362
00363 InterpretReceivedString(received_string);
00364 }
00365 else Console.WriteLine("Empty packet received");
00366
00367
00368
00369 }
00370
00371
00372
00373 catch (Exception ex)
00374 {
00375 Console.WriteLine("Error in ReceiveFrom callback: " + ex.Message);
00376 }
00377 try
00378 {
00379 EndPoint temp_receive_from_endpoint = (EndPoint)receive_from_endpoint;
00380 AsyncCallback event_receive_from = new AsyncCallback(OnReceiveFrom);
00381 udp_socket.BeginReceiveFrom(receive_from_buffer, 0, receive_from_buffer.Length, SocketFlags.None, ref temp_receive_from_endpoint, event_receive_from, udp_socket);
00382 }
00383 catch (Exception ex)
00384 {
00385 Console.WriteLine("Fatal Error in ReceiveFrom callback: " + ex.Message);
00386 }
00387
00388
00389 }
00390 else Console.WriteLine("ReceiveFrom on udp socket aborted.");
00391 }
00400 private void InterpretReceivedString(string received_string)
00401 {
00402
00403
00404
00405
00406 string[] received_strings = received_string.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
00407 for (int i = 0; i < received_strings.Length; i++)
00408 {
00409
00410 if (received_strings[i].StartsWith("$")) InterpretCommand(received_strings[i]);
00411 else Console.WriteLine("Received a non command line: " + received_strings[i]);
00412 }
00413
00414 }
00420 private void InterpretCommand(string received_command)
00421 {
00422 int command_end = received_command.IndexOf(" ");
00423 if (command_end != -1)
00424 {
00425 string command = received_command.Substring(1, command_end - 1);
00426 string parameter = received_command.Substring(command_end + 1);
00427 string[] parameters = parameter.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
00428
00429
00430 switch (command)
00431 {
00432 case "SR":
00433
00434 SearchResults.SearchResult result = new SearchResults.SearchResult();
00435 result.ResultLine = parameter;
00436 try
00437 {
00438 if (SearchResultReceived != null)
00439 SearchResultReceived( result);
00440 }
00441 catch (Exception ex)
00442 {
00443 Console.WriteLine("Exception in event handler: " + ex.Message);
00444 }
00445
00446 break;
00447
00448
00449 default:
00450 Console.WriteLine("Unknown Command received: " + command + ", Parameter: " + parameter);
00451 break;
00452 }
00453 }
00454 else Console.WriteLine("Error interpreting command: " + received_command);
00455 }
00460 private void OnAccept(IAsyncResult result)
00461 {
00462 if (tcp_socket != null)
00463 {
00464
00465 if (!tcp_socket.IsBound) return;
00466 if (!result.IsCompleted) return;
00467 try
00468 {
00469
00470 if (tcp_socket != ((Socket)result.AsyncState)) return;
00471 Socket accept_socket = (Socket)result.AsyncState;
00472 if (accept_socket == null) return;
00473 if (!accept_socket.IsBound) return;
00474
00475
00476
00477 Socket client = tcp_socket.EndAccept(result);
00478 if (!client.Connected) return;
00479
00480 Peer new_peer = new Peer(client);
00481 try
00482 {
00483 if (PeerConnected != null)
00484 {
00485 PeerConnected(new_peer);
00486 }
00487
00488 }
00489 catch (Exception ex)
00490 {
00491 Console.WriteLine("Exception in Peer Connected Event: " + ex.Message);
00492 }
00493
00494
00495 }
00496 catch (Exception ex)
00497 {
00498 Console.WriteLine("Error accepting connection: " + ex.Message);
00499 }
00500 try
00501 {
00502 AsyncCallback event_accept = new AsyncCallback(OnAccept);
00503 tcp_socket.BeginAccept(event_accept, tcp_socket);
00504 }
00505 catch (Exception ex)
00506 {
00507 Console.WriteLine("Fatal Error accepting connection: " + ex.Message);
00508 }
00509
00510
00511 }
00512 else Console.WriteLine("Accept on tcp socket aborted.");
00513 }
00522 public void SearchReply(string result_name, long filesize, Hub hub, Hub.SearchParameters search)
00523 {
00524 try
00525 {
00526 string temp_hub = hub.Name;
00527 if (search.HasTTH) temp_hub = "TTH:" + search.tth;
00528 string reply = "$SR " + hub.Nick + " " + result_name + (char)0x05 + filesize + " 1/1" + (char)0x05 + temp_hub + " (" + hub.IP + ":" + hub.Port + ")|";
00529 Console.WriteLine("Replying to active search: " + reply);
00530 IPEndPoint udp_reply_endpoint = new IPEndPoint(IPAddress.Parse(search.ip), search.port);
00531
00532
00533 byte[] send_bytes = System.Text.Encoding.Default.GetBytes(reply);
00534 udp_socket.BeginSendTo(send_bytes, 0, send_bytes.Length, SocketFlags.None,udp_reply_endpoint, new AsyncCallback(SearchReplyCallback), udp_socket);
00535 }
00536 catch(Exception ex)
00537 {
00538 Console.WriteLine("Exception during sending of SearchReply to: "+search.ip+":"+search.port+" : "+ex.Message);
00539 }
00540 }
00545 protected void SearchReplyCallback(IAsyncResult ar)
00546 {
00547 Socket search_reply_socket = (Socket)ar.AsyncState;
00548 try
00549 {
00550 int bytes_sent = search_reply_socket.EndSend(ar);
00551
00552 }
00553 catch (Exception ex)
00554 {
00555 Console.WriteLine("exception during sending of SearchReply: " + ex.Message);
00556 }
00557 }
00558 }
00559 }