/*
* 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.Collections;
using System.Diagnostics;
using System.Text;
using DCSharp.Backend.Connections;
using DCSharp.Extras;
using DCSharp.Security.Cryptography;
using DCSharp.Text;
namespace DCSharp.Backend.Protocols.Nmdc{
public abstract class Protocol : IProtocol
{
protected Hashtable commands = new Hashtable(
StringComparer.OrdinalIgnoreCase);
private Tiger algorithm;
static Protocol()
{
defaultEncoding = Encoding.GetEncoding(1252);
}
protected Protocol()
{
algorithm = Tiger.Create();
}
#region Properties
/// <summary>
/// The protocol encoding.
/// </summary>
public Encoding Encoding
{
get { return encoding != null ? encoding : defaultEncoding; }
set { encoding = value; }
}
private Encoding encoding;
/// <summary>
/// The default protocol encoding.
/// </summary>
public static Encoding DefaultEncoding
{
get { return defaultEncoding; }
set { defaultEncoding = value; }
}
private static Encoding defaultEncoding;
public string MessageSeparator
{
get { return "|"; }
}
#endregion
#region Methods
public virtual void Initialize()
{
}
public virtual void Handle(string message)
{
if (message.StartsWith("$"))
{
int space = message.IndexOf(" ");
if (space > 0)
{
string command = message.Substring(0, space);
string argument = message.Substring(space + 1);
Invoke(command, argument);
}
else
{
Invoke(message, null);
}
}
}
protected virtual void Invoke(string command, string argument)
{
// TODO: Log errors
if(commands.ContainsKey(command))
{
try
{
object handler = commands[command];
if(handler is StringEventHandler)
{
((StringEventHandler)handler)(argument);
}
else if(handler is BlankEventHandler)
{
((BlankEventHandler)handler)();
}
}
catch(ObjectDisposedException)
{
// Connection disposed, do nothing
}
catch(InvalidOperationException e)
{
Debug.WriteLine(String.Format("Invalid operation: {0}", e));
}
catch(Exception e)
{
Debug.WriteLine(String.Format("Protocol exception: {0}", e));
throw;
}
}
else
{
Debug.WriteLine(String.Format("Unknown command {0} {1}", command,
argument));
}
}
protected Identity GetUser(HubConnection connection, string nick)
{
Identity localIdentity = connection.LocalIdentity;
if (localIdentity.Nick == nick && connection.Users.Contains(localIdentity))
{
return localIdentity;
}
Uid cid = MakeCid(nick, connection.Address);
return connection.Users[User.Create(cid, nick)];
}
protected Uid MakeCid(string nick, string address)
{
byte[] data = Encoding.UTF8.GetBytes(nick + address);
lock (algorithm)
{
return new Uid(algorithm.ComputeHash(data));
}
}
#region LockToKey
protected static string CalculateKey(string lockString, Encoding encoding)
{
lockString = GetLock(lockString);
if (lockString.Length <= 3)
{
throw new ArgumentOutOfRangeException();
}
byte[] lck = encoding.GetBytes(lockString);
int[] key = new int[lck.Length];
StringBuilder keyStr = new StringBuilder(lck.Length);
int[] invalid = new int[] {0, 5, 36, 96, 124, 126};
// Generate key
for (int i = 1; i < lck.Length; i++)
{
key[i] = lck[i] ^ lck[i-1];
}
key[0] = lck[0] ^ lck[lck.Length - 1] ^ lck[lck.Length - 2] ^ 5;
for (int i = 0; i < lck.Length; i++)
{
key[i] = ((key[i] << 4) | (key[i] >> 4)) & 255;
// Escape invalid chars
if(Array.IndexOf(invalid, key[i]) != -1)
{
keyStr.AppendFormat("/%DCN{0:000}%/", key[i]);
}
else
{
keyStr.Append((char)key[i]);
}
};
return keyStr.ToString();
}
private static string GetLock(string lck)
{
int end = lck.IndexOf(" Pk=");
if (end == -1)
{
end = lck.IndexOf(" ");
if (end == -1)
{
end = lck.Length;
}
}
return lck.Substring(0, end);
}
#endregion
#endregion
}
}
|