Skip to content
This repository has been archived by the owner on Apr 2, 2024. It is now read-only.

Commit

Permalink
Adjusted Reverse DCC Support and Network Functions
Browse files Browse the repository at this point in the history
Adjusted the Reverse DCC support so it should now work on all systems
(getting wan address, listening on all instead of a single local ip).

Also adjusted the support so that if the bot doesn't connect to the us
after 1 minute ( will probably decrease this) that we abort and stop
trying, the pack will then be marked as failed.

Network functions for determining IP addresses (WAN and LAN) as well as
IP manipulation were added to XG.Business.Helper under the class
NetworkActions.
  • Loading branch information
PermaNulled committed Jun 7, 2015
1 parent ef0b25a commit 086e902
Show file tree
Hide file tree
Showing 5 changed files with 240 additions and 67 deletions.
103 changes: 103 additions & 0 deletions XG.Business/Helper/NetworkActions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
using System;
using System.Net;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;


namespace XG.Business.Helper
{
public static class NetworkActions
{
public static int CurPort = 0;
public static int[] Ports = { 9995, 9996, 9997, 9998, 9999 };

public static long IP2Long(IPAddress addr)
{
try
{
String[] ipbytes;
double num = 0;

ipbytes = addr.ToString().Split('.');
for (int i = ipbytes.Length - 1; i >= 0; i--)
num += ((int.Parse(ipbytes[i]) % 256) * Math.Pow(256, (3 - i)));

return (long)num;
}
catch
{
return -1;
}
}

private static IPAddress findMatch(IPAddress[] addresses, IPAddress gateway)
{
byte[] gatewayBytes = gateway.GetAddressBytes();
foreach (IPAddress ip in addresses)
{
byte[] ipBytes = ip.GetAddressBytes();
if (ipBytes[0] == gatewayBytes[0]
&& ipBytes[1] == gatewayBytes[1]
&& ipBytes[2] == gatewayBytes[2])
{
return ip;
}
}
return null;
}

private static string getInternetGateway()
{

Process tracert = new Process { Command = "tracert.exe", Arguments = "-h 1 8.8.8.8", Silent = true };
if (!tracert.Run())
{
Console.WriteLine("getLANAddress() - getInternetGateway() failed");
return "192.168.0.1"; // assign a default gateway not reliable at all.
}


// So hacky not even sure it will work on all configurations.
string[] lines = tracert.Output.Split( new string[] { Environment.NewLine }, StringSplitOptions.None );
string line = lines[3];
string[] spaces = line.Split(new string[] { " " }, StringSplitOptions.None);
string gateway = spaces[19];

return gateway;
}

public static IPAddress getLANAddress2()
{
IPAddress[] addresses = Dns.GetHostAddresses(Dns.GetHostName());
foreach(IPAddress address in addresses)
{
if(address.ToString() != "127.0.0.1")
{
return address;
}
}
return null;
}

public static IPAddress getLANAddress()
{
try
{
IPAddress[] addresses = Dns.GetHostAddresses(Dns.GetHostName());
IPAddress gateway = IPAddress.Parse(getInternetGateway());

return findMatch( addresses, gateway );
}
catch (FormatException e) { return null; }
}

public static IPAddress getWANAddress()
{
return IPAddress.Parse(new WebClient().DownloadString("http://bot.whatismyipaddress.com"));
}
}
}
34 changes: 21 additions & 13 deletions XG.Business/Helper/Process.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class Process
public string Arguments { get; set; }
public string Output { get; private set; }
public string Error { get; private set; }
public bool Silent { get; set; }

#endregion

Expand All @@ -49,8 +50,12 @@ public bool Run()
{
bool result = true;

Log.Info("Run(" + Command + ", " + Arguments + ")");
try
if(!Silent)
{
Log.Info("Run(" + Command + ", " + Arguments + ")");
}

try
{
var p = new System.Diagnostics.Process
{
Expand Down Expand Up @@ -84,20 +89,23 @@ public bool Run()
}
catch (Exception ex)
{
Log.Fatal("Run(" + Command + ", " + Arguments + ")", ex);
result = false;
Log.Fatal("Run(" + Command + ", " + Arguments + ")", ex);
result = false;
}
finally
{
if (!String.IsNullOrWhiteSpace(Output))
{
Log.Info("Run(" + Command + ", " + Arguments + ") Output: " + Output);
}
if (!String.IsNullOrWhiteSpace(Error))
{
Log.Error("Run(" + Command + ", " + Arguments + ") Error: " + Error);
result = false;
}
if (!Silent)
{
if (!String.IsNullOrWhiteSpace(Output))
{
Log.Info("Run(" + Command + ", " + Arguments + ") Output: " + Output);
}
if (!String.IsNullOrWhiteSpace(Error))
{
Log.Error("Run(" + Command + ", " + Arguments + ") Error: " + Error);
result = false;
}
}
}

return result;
Expand Down
1 change: 1 addition & 0 deletions XG.Business/XG.Business.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
<Compile Include="App.cs" />
<Compile Include="Helper\FileActions.cs" />
<Compile Include="Helper\FileSystem.cs" />
<Compile Include="Helper\NetworkActions.cs" />
<Compile Include="Helper\Process.cs" />
<Compile Include="Helper\Rrd.cs" />
<Compile Include="Helper\Snapshots.cs" />
Expand Down
154 changes: 103 additions & 51 deletions XG.Plugin.Irc/BotDownload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Diagnostics;
using XG.Business.Helper;
using XG.Config.Properties;
using XG.Extensions;
Expand Down Expand Up @@ -192,59 +193,108 @@ protected override void StartRun()
Int32 port = 9995;
IPAddress localAddr = IPAddress.Parse("192.168.0.4");

_tcpListener = new TcpListener(localAddr, port);
//IP retrieval methods are too unreliable, should make this based on either user input or listen on all (Listening on ALL for now).
// IPAddress localAddr = NetworkActions.getLANAddress();
// if(localAddr == null)
// {
// Console.WriteLine("Reverse DCC: Failed to get local address, trying second method");
// IPAddress localAddr = NetworkActions.getLANAddress2();
// }

Stopwatch watch = new Stopwatch();
bool botConnected = true;

_tcpListener = new TcpListener(localAddr, iPort);

//Part of that race condition mentioned earlier.
NetworkActions.CurPort++;

_tcpListener.Start();

Console.WriteLine("StartRun(Reverse DCC) - Waiting for bot to connect...");
_tcpClient = _tcpListener.AcceptTcpClient();

Console.WriteLine("StartRun(Reverse DCC) - Bot has connected!");

_tcpClient.SendTimeout = Settings.Default.DownloadTimeoutTime * 1000;
_tcpClient.ReceiveTimeout = Settings.Default.DownloadTimeoutTime * 1000;

using (Stream stream = new ThrottledStream(_tcpClient.GetStream(), Settings.Default.MaxDownloadSpeedInKB * 1000))
{
InitializeWriting();
using (var reader = new BinaryReader(stream))
{
Int64 missing = MaxData;
Int64 max = Settings.Default.DownloadPerReadBytes;
byte[] data = null;

// start watch to look if our connection is still receiving data
StartWatch(Settings.Default.DownloadTimeoutTime, IP + ":" + Port);

int failCounter = 0;
do
{
data = reader.ReadBytes((int)(missing < max ? missing : max));
LastContact = DateTime.Now;

if (data != null && data.Length != 0)
{
SaveData(data);
missing -= data.Length;
}
else
{
failCounter++;
Console.WriteLine("StartRun(Reverse DCC) no data received - " + failCounter);

if (failCounter > Settings.Default.MaxNoDateReceived)
{
Console.WriteLine("StartRun(Reverse DCC) no data received - skipping");
break;
}
}
} while (AllowRunning && missing > 0);

}
Console.WriteLine("StartRun(Reverse DCC) end");
}


watch.Start();

//Check if a client is available without blocking in a separate function like AcceptTCPClient Does
//This way we can check the amount of time that has passed since we asked the bot to connect to us.
Console.WriteLine("Reverse DCC() Listening on " + localAddr + ":" + iPort);
Console.WriteLine("Reverse DCC() - Waiting for bot to connect...");


while (!_tcpListener.Pending())
{


//If the bot doesn't connect to us within 1 minute it's probably not going to, lets abort the operation and report it as failed.
if( watch.ElapsedMilliseconds > 60000 )
{
Console.WriteLine("Reverse DCC() - Timeout - Bot never connected");
Console.WriteLine("Reverse DCC() - Either bot is broken or your firewall/router is blocking it (Ports 9995-9999)");
watch.Stop();

botConnected = false;
break;
}
}

//stop the watch if the bot connected it wouldn't have been stopped by the timeout.
if (watch.IsRunning)
{
Console.WriteLine("Reverse DCC() Bot connected to us after {0} seconds", watch.Elapsed.Seconds);
watch.Stop();
}

if (botConnected)
{
_tcpClient = _tcpListener.AcceptTcpClient();
Console.WriteLine("Reverse DCC() - Starting download");

_tcpClient.SendTimeout = Settings.Default.DownloadTimeoutTime * 1000;
_tcpClient.ReceiveTimeout = Settings.Default.DownloadTimeoutTime * 1000;

using (Stream stream = new ThrottledStream(_tcpClient.GetStream(), Settings.Default.MaxDownloadSpeedInKB * 1000))
{
InitializeWriting();
using (var reader = new BinaryReader(stream))
{
Int64 missing = MaxData;
Int64 max = Settings.Default.DownloadPerReadBytes;
byte[] data = null;

// start watch to look if our connection is still receiving data
StartWatch(Settings.Default.DownloadTimeoutTime, IP + ":" + Port);

int failCounter = 0;
do
{
data = reader.ReadBytes((int)(missing < max ? missing : max));
LastContact = DateTime.Now;

if (data != null && data.Length != 0)
{
SaveData(data);
missing -= data.Length;
}
else
{
failCounter++;
Console.WriteLine("Reverse DCC (No Data Received) " + failCounter);

if (failCounter > Settings.Default.MaxNoDateReceived)
{
Console.WriteLine("Reverse DCC (No Data Received)- skipping");
break;
}
}
} while (AllowRunning && missing > 0);

}
Console.WriteLine("Reverse DCC (end)");
}
}
else
{
Console.WriteLine("Reverse DCC( failed ) - bot never connected.");
}

}
catch (ObjectDisposedException) { }
catch(SocketException e)
Expand All @@ -255,11 +305,13 @@ protected override void StartRun()
{
_log.Info("StartRun() Finishing (Reverse DCC)");
FinishWriting();

_writer = null;
_tcpClient = null;
_tcpListener.Stop();
_tcpListener = null;

//Back to that race condition again;
NetworkActions.CurPort--;
}

}
Expand Down
15 changes: 12 additions & 3 deletions XG.Plugin.Irc/Parser/Types/Dcc/DownloadFromBot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
using XG.Extensions;
using XG.Model.Domain;


namespace XG.Plugin.Irc.Parser.Types.Dcc
{
public class DownloadFromBot : AParser
Expand Down Expand Up @@ -125,7 +126,7 @@ public override bool Parse(Message aMessage)
if (tPort <= 0)
{
Token = int.Parse(tDataList[5]);
Console.WriteLine("We're accepting reverse XDCC token: {0}", Token);
Console.WriteLine("Reverse DCC() Token: {0}", Token);
}

tPacket.RealName = tDataList[1];
Expand Down Expand Up @@ -214,8 +215,16 @@ public override bool Parse(Message aMessage)
//It's a reverse DCC Connection lets tell the bot we're listening.
if(tPort == 0)
{
Log.Info("Parse() - Reverse DCC - Sending our info to bot.");
FireSendMessage(this, new EventArgs<Server,SendType, string, string>(aMessage.Channel.Parent, SendType.CtcpRequest, tBot.Name, "DCC SEND " + tPacket.RealName + " IPLONG 9995 " + tPacket.RealSize + " " + Token));
//This is a race condition waiting to happen :)
int PortsInUse = NetworkActions.CurPort;
int iPort = NetworkActions.Ports[PortsInUse];
long WanAddr = NetworkActions.IP2Long(NetworkActions.getWANAddress());
string Wan = new IPAddress(WanAddr).ToString();

Console.WriteLine("Reverse DCC() - Sending our info to bot.");
string Message = "DCC SEND" + " " + tPacket.RealName + " " + WanAddr + " " + iPort + " " + tPacket.RealSize + " " + Token;

FireSendMessage(this, new EventArgs<Server,SendType, string, string>(aMessage.Channel.Parent, SendType.CtcpRequest, tBot.Name, Message));
}
}
return true;
Expand Down

0 comments on commit 086e902

Please sign in to comment.