/source/Core/MessageImpl.cs
C# | 561 lines | 443 code | 81 blank | 37 comment | 62 complexity | 0d3c488b9a27fe566ad7881851e6c4c0 MD5 | raw file
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Web;
- using System.Configuration;
- using System.Web.Configuration;
- using System.Data;
- using System.Text;
- using System.Text.RegularExpressions;
- using System.Xml;
- using System.Threading;
- using Microsoft.JScript;
- using System.Reflection;
- using Core.IO;
-
- namespace Core
- {
- /// <summary>
- ///MessageManagement 的摘要说明
- /// </summary>
- public class MessageImpl
- {
- static MessageImpl m_Instance = new MessageImpl();
-
- static public MessageImpl Instance
- {
- get { return m_Instance; }
- }
-
- static MessageImpl()
- {
- Instance.Initialize(HttpContext.Current);
- }
-
- private MessageImpl()
- {
- m_Timer = new Timer(this.TimerProc);
- m_Timer.Change(0, 2 * 60 * 1000);
- }
-
- Timer m_Timer = null;
-
- private void TimerProc(object state)
- {
- WriteCache();
- }
-
- Object m_Lock = new Object();
- Int64 m_MaxKey = 1;
- DateTime m_MaxCreatedTime = DateTime.Now;
-
- # if DEBUG
- const Int32 MAX_CACHE_COUNT = 4;
- # else
- const Int32 MAX_CACHE_COUNT = 1024;
- # endif
-
- IMessageStorage m_IMessageStorage = null;
-
- public void Initialize(HttpContext context)
- {
- lock (m_Lock)
- {
- Configuration config = WebConfigurationManager.OpenWebConfiguration(
- HttpContext.Current.Request.ApplicationPath == "/" ? "/Lesktop" : HttpContext.Current.Request.ApplicationPath + "/Lesktop"
- );
-
- string accStorage = config.AppSettings.Settings["MessageStorageImpl"].Value;
- String[] accStorageInfo = accStorage.Split(new char[] { ' ' });
- Type type = Assembly.Load(accStorageInfo[0]).GetType(accStorageInfo[1]);
- ConstructorInfo ctor = type.GetConstructor(new Type[] { });
- m_IMessageStorage = ctor.Invoke(new object[] { }) as IMessageStorage;
-
- m_MaxKey = m_IMessageStorage.GetMaxKey();
- m_MaxCreatedTime = m_IMessageStorage.GetCreatedTime();
- }
- }
-
- public void Dispose()
- {
- }
-
- public List<Message> FindInDatabase(String receiver, String sender, Nullable<DateTime> from)
- {
- lock (m_Lock)
- {
- return m_IMessageStorage.Find(
- receiver == "*" ? 0 : AccountImpl.Instance.GetUserInfo(receiver).ID,
- sender == "*" ? 0 : AccountImpl.Instance.GetUserInfo(sender).ID,
- from
- );
- }
- }
-
- /// <summary>
- /// 插入新的消息,插入消息后将查询m_Listeners中是否有符合条件的监听器,如存在,同时将消息发送出去
- /// </summary>
- public Message NewMessage(String receiver, String sender, String content, Hashtable data)
- {
- lock (m_Lock)
- {
- Int64 key = ++m_MaxKey;
- content = HtmlUtil.ReplaceHtml(content);
- MsgAccessoryEval eval = new MsgAccessoryEval(key, receiver, sender, data);
- Regex reg = new Regex("{Accessory [^\f\n\r\t\v<>]+}");
- content = reg.Replace(content, eval.Replace);
-
-
- Message message = new Message(
- AccountImpl.Instance.GetUserInfo(sender),
- AccountImpl.Instance.GetUserInfo(receiver),
- content, new DateTime((DateTime.Now.Ticks / 10000) * 10000), key
- );
-
- List<Message> messages = new List<Message>();
- messages.Add(message);
-
- if (AccountImpl.Instance.GetUserInfo(receiver).Type == 0)
- {
- if (SessionManagement.Instance.IsOnline(receiver))
- {
- try
- {
- AccountState state = SessionManagement.Instance.GetAccountState(receiver);
- Hashtable config = state.GetConfig("message.conf");
-
- lock (config)
- {
- DateTime lrt = (DateTime)config["LastReceivedTime"];
- if (lrt < message.CreatedTime) config["LastReceivedTime"] = message.CreatedTime;
- }
-
- string cmdData = Utility.RenderHashJson(
- "Peer", sender,
- "Message", message
- );
-
- SessionManagement.Instance.Send(receiver, "GLOBAL:IM_MESSAGE_NOTIFY", cmdData);
- }
- catch
- {
- }
- }
- }
- else
- {
- AccountInfo groupInfo = AccountImpl.Instance.GetUserInfo(receiver);
- AccountInfo senderInfo = AccountImpl.Instance.GetUserInfo(sender);
- foreach (string member in groupInfo.Friends)
- {
- try
- {
- AccountInfo memberInfo = AccountImpl.Instance.GetUserInfo(member);
- if (senderInfo.Name.ToLower() != "administrator" && memberInfo.ID == senderInfo.ID) continue;
- if (SessionManagement.Instance.IsOnline(member))
- {
- AccountState state = SessionManagement.Instance.GetAccountState(memberInfo.Name);
- Hashtable config = state.GetConfig("message.conf");
-
- lock (config)
- {
- DateTime lrt = (DateTime)config["LastReceivedTime"];
- if (lrt < message.CreatedTime) config["LastReceivedTime"] = message.CreatedTime;
- }
-
- string cmdData = Utility.RenderHashJson(
- "Peer", groupInfo.Name,
- "Message", message
- );
-
- SessionManagement.Instance.Send(member, "GLOBAL:IM_MESSAGE_NOTIFY", cmdData);
- }
- }
- catch
- {
- }
- }
- }
-
- MessageCacheManagement.Instance.Insert(receiver, message);
-
- if (MessageCacheManagement.Instance.Count >= MAX_CACHE_COUNT)
- {
- WriteCache();
- }
-
- return message;
- }
- }
-
- public void WriteCache()
- {
- if (MessageCacheManagement.Instance.Count > 0)
- {
- List<Message> cacheMsgs = MessageCacheManagement.Instance.GetAll();
- m_IMessageStorage.Write(cacheMsgs);
- MessageCacheManagement.Instance.Clear();
- }
- }
-
- public List<Message> FindHistory(String receiver, String sender, DateTime from, DateTime to)
- {
- return m_IMessageStorage.FindHistory(
- AccountImpl.Instance.GetUserInfo(receiver).ID,
- AccountImpl.Instance.GetUserInfo(sender).ID,
- from, to
- );
- }
-
- /// <summary>
- /// 添加消息监听器,如果查找到符合监听器条件的消息,返回false,此时不会添加监听器
- /// 如果没有查找到符合监听器条件的消息,返回true,此时监听器将被添加到m_Listeners中
- /// </summary>
- public List<Message> Find(String receiver, String sender, Nullable<DateTime> from)
- {
- lock (m_Lock)
- {
- //获取用户receiver缓存的消息的最小发送时间
- Nullable<DateTime> min = MessageCacheManagement.Instance.GetMinCreatedTime(receiver);
-
- List<Message> messages = new List<Message>();
-
- //当from >= 缓存在内存中的消息的最小时间时,不必查询数据库
- if (min == null || from == null || from.Value < min.Value)
- {
- //查询数据库
- messages.AddRange(FindInDatabase(receiver, sender, from));
- if (AccountImpl.Instance.GetUserInfo(receiver).Type == 0)
- {
- messages.AddRange(FindInDatabase(sender, receiver, from));
- }
- }
-
- //在缓存中查询
- messages.AddRange(MessageCacheManagement.Instance.Find(receiver, sender, from.Value));
- if (AccountImpl.Instance.GetUserInfo(receiver).Type == 0)
- {
- messages.AddRange(MessageCacheManagement.Instance.Find(sender, receiver, from.Value));
- }
-
- return messages;
- }
- }
- }
-
- public class MessageCacheManagement
- {
- static MessageCacheManagement m_Instance = new MessageCacheManagement();
-
- static public MessageCacheManagement Instance
- {
- get { return m_Instance; }
- }
-
- private MessageCacheManagement()
- {
- }
-
- Int32 m_Count = 0;
- Hashtable m_Cache = new Hashtable();
-
- List<Message> GetUserMessageCache(String user)
- {
- if (!m_Cache.ContainsKey(user))
- {
- m_Cache.Add(user, new List<Message>());
- }
-
- return m_Cache[user] as List<Message>;
- }
-
- /// <summary>
- /// 清除缓存
- /// </summary>
- public void Clear()
- {
- lock (m_Cache)
- {
- List<Message> msgs = new List<Message>();
- foreach (DictionaryEntry ent in m_Cache)
- {
- (ent.Value as List<Message>).Clear();
- }
- m_Count = 0;
- }
- }
-
- /// <summary>
- /// 获取所有缓存的消息
- /// </summary>
- /// <returns></returns>
- public List<Message> GetAll()
- {
- lock (m_Cache)
- {
- List<Message> msgs = new List<Message>();
- foreach (DictionaryEntry ent in m_Cache)
- {
- foreach (Message msg in ent.Value as List<Message>)
- {
- msgs.Add(msg);
- }
- }
- return msgs;
- }
- }
-
- /// <summary>
- /// 获取某一用户缓存的消息的最小时间
- /// </summary>
- public Nullable<DateTime> GetMinCreatedTime(string user)
- {
- lock (m_Cache)
- {
- List<Message> userMsgs = GetUserMessageCache(user);
- return userMsgs.Count == 0 ? null : new Nullable<DateTime>(userMsgs[0].CreatedTime);
- }
- }
-
-
- /// <summary>
- /// 在缓存中插入一条消息
- /// </summary>
- /// <param name="user"></param>
- /// <param name="msg"></param>
- public void Insert(String user, Message msg)
- {
- List<Message> userMsgs = null;
-
- lock (m_Cache)
- {
- userMsgs = GetUserMessageCache(user);
- }
-
- lock (userMsgs)
- {
- userMsgs.Add(msg);
- m_Count++;
- }
- }
-
- /// <summary>
- /// 查找缓存中接受者为user,发送时间大于from的消息
- /// </summary>
- public List<Message> Find(String user, String sender, DateTime from)
- {
- List<Message> msgs = new List<Message>();
-
- {
- List<Message> userMsgs = null;
-
- lock (m_Cache)
- {
- userMsgs = GetUserMessageCache(user);
- }
-
- lock (userMsgs)
- {
-
- int i = 0;
- while (i < userMsgs.Count && userMsgs[i].CreatedTime <= from) i++;
-
- while (i < userMsgs.Count)
- {
- if (sender == null || sender == "*" || sender == userMsgs[i].Sender.Name) msgs.Add(userMsgs[i]);
- i++;
- }
- }
- }
-
- if (sender == null || sender == "*")
- {
- //在缓冲中查找群消息
- AccountInfo userInfo = AccountImpl.Instance.GetUserInfo(user);
- foreach (string groupName in userInfo.Groups)
- {
- AccountInfo groupInfo = AccountImpl.Instance.GetUserInfo(groupName);
-
- List<Message> groupMsgs = null;
- lock (m_Cache)
- {
- groupMsgs = GetUserMessageCache(groupName);
- }
-
- lock (groupMsgs)
- {
- if (from < groupInfo.GetGroupMemberRenewTime(user))
- {
- from = groupInfo.GetGroupMemberRenewTime(user);
- }
-
- int i = 0;
- while (i < groupMsgs.Count && groupMsgs[i].CreatedTime <= from) i++;
-
- while (i < groupMsgs.Count)
- {
- msgs.Add(groupMsgs[i]);
- i++;
- }
- }
- }
- }
- return msgs;
- }
-
- /// <summary>
- /// 获取消息总量
- /// </summary>
- public Int32 Count
- {
- get { return m_Count; }
- }
- }
-
- internal class MsgAccessoryEval
- {
- string m_Receiver, m_Sender;
- string m_ReceiverMsgDir, m_SenderMsgDir, m_MsgDir;
- Hashtable m_Data;
-
- public MsgAccessoryEval(Int64 key, String receiver, String sender, Hashtable data)
- {
- m_Receiver = receiver;
- m_Sender = sender;
-
- m_Data = data;
-
- m_ReceiverMsgDir = string.Format("/{0}/Message/MSG{1:00000000}", receiver, key);
- m_SenderMsgDir = string.Format("/{0}/Message/MSG{1:00000000}", sender, key);
- m_MsgDir = AccountImpl.Instance.GetUserInfo(receiver).Type == 1 ? string.Format("/{1}/Message/MSG{0:00000000}", key, receiver) : string.Format("Message/MSG{0:00000000}", key);
- }
-
- public string Replace(Match match)
- {
- XmlDocument xml = new XmlDocument();
- string value = match.Value;
- xml.LoadXml(string.Format("<{0} />", value.Substring(1, value.Length - 2)));
-
- string src = GlobalObject.unescape(xml.DocumentElement.GetAttribute("src"));
- string type = xml.DocumentElement.GetAttribute("type").ToLower();
- string data = xml.DocumentElement.GetAttribute("data");
-
- bool isPublic = ServerImpl.Instance.IsPublic(src);
-
- if (isPublic)
- {
- //公共资源不拷贝
- return String.Format("{0}", Path.GetRelativePath(src));
- }
- else
- {
- if (!Directory.Exists(m_ReceiverMsgDir)) Directory.CreateDirectory(m_ReceiverMsgDir);
- if (AccountImpl.Instance.GetUserInfo(m_Receiver).Type == 0)
- {
- if (!Directory.Exists(m_SenderMsgDir)) Directory.CreateDirectory(m_SenderMsgDir);
- }
-
- string fileOwnerName = Path.GetUser(src);
- if (String.IsNullOrEmpty(fileOwnerName))
- {
- fileOwnerName = m_Sender;
- src = String.Format("/{0}/{1}", fileOwnerName, src);
- }
-
- bool allowRead=true;
- try
- {
- ServerImpl.Instance.CheckPermission(HttpContext.Current, src, IOPermission.Read);
- }
- catch
- {
- allowRead = false;
- }
-
- if (data != "" || allowRead)
- {
- Hashtable _files = new Hashtable();
-
- string fileName;
- if (!_files.ContainsKey(src))
- {
- fileName = Path.GetFileName(src);
- int i = 1;
- while (_files.ContainsValue(fileName))
- {
- fileName = string.Format("{0}({1}){2}", System.IO.Path.GetFileNameWithoutExtension(fileName), i.ToString(), System.IO.Path.GetExtension(fileName));
- i++;
- }
-
- _files.Add(src, fileName);
-
- try
- {
- if (AccountImpl.Instance.GetUserInfo(m_Receiver).Type == 0)
- {
- if (data == "")
- {
- File.Copy(src, m_SenderMsgDir + "/" + fileName);
- }
- else
- {
- String dataBase64 = m_Data[data] as String;
- Byte[] buffer = System.Convert.FromBase64String(dataBase64);
-
- using (System.IO.Stream stream = File.Open(m_SenderMsgDir + "/" + fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
- {
- try
- {
- stream.Write(buffer, 0, buffer.Length);
- }
- finally
- {
- stream.Close();
- }
-
- }
- }
- }
- if (data == "")
- {
- File.Copy(src, m_ReceiverMsgDir + "/" + fileName);
- }
- else
- {
- String dataBase64 = m_Data[data] as String;
- Byte[] buffer = System.Convert.FromBase64String(dataBase64);
-
- using (System.IO.Stream stream = File.Open(m_ReceiverMsgDir + "/" + fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
- {
- try
- {
- stream.Write(buffer, 0, buffer.Length);
- }
- finally
- {
- stream.Close();
- }
-
- }
- }
- }
- catch
- {
- }
-
- }
- else
- fileName = _files[src] as string;
-
- string newUrl = GlobalObject.escape(string.Format("{0}/{1}", m_MsgDir, fileName));
-
- return newUrl;
- }
- else
- {
- return src;
- }
- }
- }
- }
- }