using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using SuperSocket.Common;
using SuperSocket.SocketBase.Logging;
using SuperSocket.SocketBase.Command;
using SuperSocket.SocketBase.Config;
using SuperSocket.SocketBase.Protocol;
using SuperWebSocket.Config;
using SuperSocket.SocketBase;
namespace SuperWebSocket.SubProtocol
{
///
/// Default basic sub protocol implementation
///
public class BasicSubProtocol : BasicSubProtocol
{
///
/// Initializes a new instance of the class.
///
public BasicSubProtocol()
: base(Assembly.GetCallingAssembly())
{
}
///
/// Initializes a new instance of the class.
///
/// The sub protocol name.
public BasicSubProtocol(string name)
: base(name, Assembly.GetCallingAssembly())
{
}
///
/// Initializes a new instance of the class.
///
/// The command assembly.
public BasicSubProtocol(Assembly commandAssembly)
: base(commandAssembly)
{
}
///
/// Initializes a new instance of the class.
///
/// The command assemblies.
public BasicSubProtocol(IEnumerable commandAssemblies)
: base(commandAssemblies)
{
}
///
/// Initializes a new instance of the class.
///
/// The sub protocol name.
/// The command assembly.
public BasicSubProtocol(string name, Assembly commandAssembly)
: base(name, commandAssembly)
{
}
///
/// Initializes a new instance of the class.
///
/// The sub protocol name.
/// The command assemblies.
public BasicSubProtocol(string name, IEnumerable commandAssemblies)
: base(name, commandAssemblies)
{
}
///
/// Initializes a new instance of the class.
///
/// The name.
/// The command assemblies.
/// The request info parser.
public BasicSubProtocol(string name, IEnumerable commandAssemblies, IRequestInfoParser requestInfoParser)
: base(name, commandAssemblies, requestInfoParser)
{
}
}
///
/// Default basic sub protocol implementation
///
public class BasicSubProtocol : SubProtocolBase
where TWebSocketSession : WebSocketSession, new()
{
///
/// Default basic sub protocol name
///
public const string DefaultName = "Basic";
private List m_CommandAssemblies = new List();
private Dictionary> m_CommandDict;
private ILog m_Logger;
private SubCommandFilterAttribute[] m_GlobalFilters;
internal static BasicSubProtocol CreateDefaultSubProtocol()
{
var commandAssembly = typeof(TWebSocketSession).Assembly;
if (commandAssembly == Assembly.GetExecutingAssembly())
commandAssembly = Assembly.GetEntryAssembly();
return new BasicSubProtocol(DefaultName, commandAssembly);
}
///
/// Initializes a new instance of the class with the calling aseembly as command assembly
///
public BasicSubProtocol()
: this(DefaultName, Assembly.GetCallingAssembly())
{
}
///
/// Initializes a new instance of the class with the calling aseembly as command assembly
///
/// The sub protocol name.
public BasicSubProtocol(string name)
: this(name, Assembly.GetCallingAssembly())
{
}
///
/// Initializes a new instance of the class with command assemblies
///
/// The command assemblies.
public BasicSubProtocol(IEnumerable commandAssemblies)
: this(DefaultName, commandAssemblies, new BasicSubCommandParser())
{
}
///
/// Initializes a new instance of the class with single command assembly.
///
/// The command assembly.
public BasicSubProtocol(Assembly commandAssembly)
: this(DefaultName, new List { commandAssembly }, new BasicSubCommandParser())
{
}
///
/// Initializes a new instance of the class with name and single command assembly.
///
/// The sub protocol name.
/// The command assembly.
public BasicSubProtocol(string name, Assembly commandAssembly)
: this(name, new List { commandAssembly }, new BasicSubCommandParser())
{
}
///
/// Initializes a new instance of the class with name and command assemblies.
///
/// The sub protocol name.
/// The command assemblies.
public BasicSubProtocol(string name, IEnumerable commandAssemblies)
: this(name, commandAssemblies, new BasicSubCommandParser())
{
}
///
/// Initializes a new instance of the class.
///
/// The name.
/// The command assemblies.
/// The request info parser.
public BasicSubProtocol(string name, IEnumerable commandAssemblies, IRequestInfoParser requestInfoParser)
: base(name)
{
//The items in commandAssemblies may be null, so filter here
m_CommandAssemblies.AddRange(commandAssemblies.Where(a => a != null));
SubRequestParser = requestInfoParser;
}
#region ISubProtocol Members
private void DiscoverCommands()
{
var subCommands = new List>();
foreach (var assembly in m_CommandAssemblies)
{
subCommands.AddRange(assembly.GetImplementedObjectsByInterface>());
}
#if DEBUG
var cmdbuilder = new StringBuilder();
cmdbuilder.AppendLine(string.Format("SubProtocol {0} found the commands below:", this.Name));
foreach (var c in subCommands)
{
cmdbuilder.AppendLine(c.Name);
}
m_Logger.Debug(cmdbuilder.ToString());
#endif
m_CommandDict = new Dictionary>(subCommands.Count, StringComparer.OrdinalIgnoreCase);
subCommands.ForEach(c =>
{
var fc = c as ISubCommandFilterLoader;
if (fc != null)
fc.LoadSubCommandFilters(m_GlobalFilters);
m_CommandDict.Add(c.Name, c);
}
);
}
///
/// Initializes with the specified config.
///
/// The app server.
/// The protocol config.
/// The logger.
///
public override bool Initialize(IAppServer appServer, SubProtocolConfig protocolConfig, ILog logger)
{
m_Logger = logger;
var config = appServer.Config;
m_GlobalFilters = appServer.GetType()
.GetCustomAttributes(true)
.OfType()
.Where(a => string.IsNullOrEmpty(a.SubProtocol) || Name.Equals(a.SubProtocol, StringComparison.OrdinalIgnoreCase)).ToArray();
if (Name.Equals(DefaultName, StringComparison.OrdinalIgnoreCase))
{
var commandAssembly = config.Options.GetValue("commandAssembly");
if (!string.IsNullOrEmpty(commandAssembly))
{
if (!ResolveCommmandAssembly(commandAssembly))
return false;
}
}
if (protocolConfig != null && protocolConfig.Commands != null)
{
foreach (var commandConfig in protocolConfig.Commands)
{
var assembly = commandConfig.Options.GetValue("assembly");
if (!string.IsNullOrEmpty(assembly))
{
if (!ResolveCommmandAssembly(assembly))
return false;
}
}
}
//Always discover commands
DiscoverCommands();
return true;
}
private bool ResolveCommmandAssembly(string definition)
{
try
{
var assemblies = AssemblyUtil.GetAssembliesFromString(definition);
if (assemblies.Any())
m_CommandAssemblies.AddRange(assemblies);
return true;
}
catch (Exception e)
{
m_Logger.Error(e);
return false;
}
}
///
/// Tries get command from the sub protocol's command inventory.
///
/// The name.
/// The command.
///
public override bool TryGetCommand(string name, out ISubCommand command)
{
return m_CommandDict.TryGetValue(name, out command);
}
#endregion
}
}