/*
* Copyright (C) 2004-2005 Jonathan Bindel
* Copyright (C) 2006-2007 Eskil Bylund
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
using System;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using DCSharp.Backend.Connections;
using DCSharp.Backend.Objects;
namespace DCSharp.Backend.Protocols.Nmdc{
/// <summary>
/// A class that handles NMDC messages sent over Udp.
/// </summary>
public class UdpProtocol : Protocol
{
private const int MaxActiveResults = 10;
private const int MaxPassiveResults = 5;
public UdpProtocol(ISearchResultHandler handler,
ILegacyUserIdentifier userIdentifier)
{
if (handler == null)
{
throw new ArgumentNullException("handler");
}
if (userIdentifier == null)
{
throw new ArgumentNullException("userIdentifier");
}
this.handler = handler;
this.userIdentifier = userIdentifier;
}
/// <summary>
///
/// </summary>
public ISearchResultHandler ResultHandler
{
get { return handler; }
}
private ISearchResultHandler handler;
/// <summary>
///
/// </summary>
public ILegacyUserIdentifier UserIdentifier
{
get { return userIdentifier; }
}
private ILegacyUserIdentifier userIdentifier;
protected override void Invoke(string command, string argument)
{
if (command == "$SR")
{
ParseSearchResult(argument);
}
else
{
base.Invoke(command, argument);
}
}
protected void ParseSearchResult(string argument)
{
// $SR <nick> <result> <free slots>/<total slots><0x05><hubname> (<hubip:port>)
//
// <result> is one of the following:
//
// - For files: <filename><0x05><filesize>
// - For directories: <directory>
//
// If it's a TTH search <hubname> is: TTH:<tth>
int i = 0;
int j = argument.IndexOf(' ');
if (j <= 0)
return;
SearchResult result = new SearchResult();
string nick = argument.Substring(0, j);
string remaining = argument.Substring(j + 1);
char bit = (char)5;
int count = Regex.Matches(remaining, bit.ToString()).Count;
if (count == 1)
{
// We have a directory...find the first space beyond the first 0x05 from the back
// (dirs might contain spaces as well...clever protocol, eh?)
result.Type = ResultType.Directory;
// Get past the hubname that might contain spaces
j = remaining.LastIndexOf(bit);
if (j < 0)
return;
j = remaining.LastIndexOf(' ', j - 1);
if (j < 0)
return;
result.Path = remaining.Substring(0, j);
}
else if (count == 2)
{
result.Type = ResultType.File;
j = remaining.IndexOf(bit);
result.Path = remaining.Substring(0, j);
i = j + 1;
long size;
j = remaining.IndexOf(' ', i);
if (j < 0 || !long.TryParse(remaining.Substring(i, j - i), out size))
return;
result.Size = size;
}
else
{
return;
}
int slots;
i = j + 1;
j = remaining.IndexOf('/', i);
if (j < 0 || !int.TryParse(remaining.Substring(i, j - i), out slots))
return;
result.FreeSlots = slots;
i = j + 1;
j = remaining.IndexOf(bit, i);
if (j < 0 || !int.TryParse(remaining.Substring(i, j - i), out slots))
return;
result.Slots = slots;
i = j + 1;
j = remaining.LastIndexOf(" (");
if (j < 0)
return;
string hubName = remaining.Substring(i, j - i);
if (hubName.StartsWith("TTH:"))
{
result.TTH = hubName.Substring(4);
hubName = null;
}
i = j + 2;
j = remaining.IndexOf(')', i);
if (j < 0)
return;
string hubAddress = remaining.Substring(i, j - i);
result.User = GetIdentity(nick, hubName, hubAddress);
if (result.User != null)
{
handler.HandleSearchResult(result);
}
}
protected virtual Identity GetIdentity(string nick, string hubName,
string hubAddress)
{
Identity identity;
HubConnection hub;
userIdentifier.IdentifyUser(nick, hubName, hubAddress,
out hub, out identity);
return identity;
}
}
}
|