/// <summary> /// 发送在线状态变化信息 /// </summary> public void SendAbsenceMessage() { ulong options = 0ul; if (Config.IsInAbsenceMode) { options |= (ulong)Consts.Cmd_All_Option.Absence; } if (Config.EnableFileTransfer) { options |= (ulong)Define.Consts.Cmd_All_Option.FileAttach; } //插件 if (Config.Services != null) { Config.Services.ProviderExecute(s => options |= s.GenerateClientFeatures()); } string msg = Config.NickName; if (Config.IsInAbsenceMode) { msg += Config.AbsenceSuffix; } //广播 MessageProxy.SendWithNoCheck(null, Consts.Commands.Br_Absence, options, msg, Config.GroupName); //单个通知 options |= (ulong)Consts.Cmd_All_Option.DialUp; Config.KeepedHostList_Addr.ForEach(s => MessageProxy.SendByIp(new IPEndPoint(s, Config.Port), Consts.Commands.Br_Absence, options, msg, Config.GroupName)); }
//接收到文字消息 private void ProcessCommand_SendMsg(Message message, Host host) { if (host == null) { return; } //确认是否需要自动回复? if (!message.IsAutoSendMessage && (Config.AutoReply || (Config.AutoReplyWhenAbsence && Config.IsInAbsenceMode))) { string msg = string.IsNullOrEmpty(Config.AutoReplyMessage) ? Config.AutoReplyMessage : Config.AbsenceMessage; if (string.IsNullOrEmpty(msg)) { msg = Resources.CommandExecutor_ProcessCommand_SendMsg_AutoReplyMessage; } MessageProxy.SendWithNoCheck(host, Consts.Commands.SendMsg, (ulong)Consts.Cmd_Send_Option.AutoRet, msg, string.Empty); message.AutoReplyTime = DateTime.Now; } //触发事件 MessageEventArgs e = new MessageEventArgs(message, host); OnTextMessageReceiving(e); if (!e.IsHandled) { OnTextMessageReceived(e); } }
//发送离开信息? private void ProcessCommand_GetAbsenceInfo(Message message, Host host) { if (host == null) { return; } MessageProxy.SendWithNoCheck(host, Consts.Commands.SendAbsenceInfo, 0ul, Config.IsInAbsenceMode ? Config.AbsenceMessage : Resources.CommandExecutor_ProcessCommand_GetAbsenceInfo_NotAbsenceMode, ""); }
//捕捉主机离开状态变化 void Host_AbsendModeChanged(object sender, EventArgs e) { Host h = sender as Host; if (h.IsInAbsenceMode) { //如果处于离开模式,则要求获得对象离开信息 MessageProxy.SendWithNoCheck(h, Consts.Commands.GetAbsenceInfo, 0, "", ""); } }
/// <summary> /// 发送下线消息 /// </summary> public void SendExitEntryMessage() { ulong options = 0ul; //广播 MessageProxy.SendWithNoCheck(null, Consts.Commands.Br_Exit, options | (ulong)Consts.Cmd_Send_Option.BroadCast, Config.NickName, Config.GroupName); //单个通知 options |= (ulong)Consts.Cmd_All_Option.DialUp; Config.KeepedHostList_Addr.ForEach(s => MessageProxy.SendByIp(new IPEndPoint(s, Config.Port), Consts.Commands.Br_Exit, options, Config.NickName, Config.GroupName)); }
/// <summary> /// 发送消息 /// </summary> /// <param name="host">主机</param> /// <param name="remoteEndPoint">远程主机地址</param> /// <param name="cmd">命令</param> /// <param name="options">选项</param> /// <param name="msg">消息</param> /// <param name="extMsg">扩展消息</param> /// <param name="isBroadCast">是否是广播</param> /// <param name="sendCheck">是否需要确认收到</param> /// <param name="noAddList">是否忽略到主机列表</param> /// <param name="noLog">是否不记录日志</param> /// <param name="isAutoRet">是否是自动回复</param> /// <param name="isEncrypt">是否是加密信息</param> /// <param name="isSecret">是否需要阅读确认</param> /// <param name="noPopup">是否不自动弹出</param> /// <returns>发出去的消息包编号</returns> public ulong SendCommand(Host host, IPEndPoint remoteEndPoint, Consts.Commands cmd, ulong options, string msg, string extMsg, bool isBroadCast, bool sendCheck , bool noAddList, bool noLog, bool isAutoRet, bool isEncrypt, bool isSecret, bool noPopup) { if (isBroadCast) { options |= (ulong)Consts.Cmd_Send_Option.BroadCast; } if (sendCheck) { options |= (ulong)Consts.Cmd_Send_Option.SendCheck; } if (noAddList) { options |= (ulong)Consts.Cmd_Send_Option.NoAddList; } if (noLog) { options |= (ulong)Consts.Cmd_Send_Option.NoLog; } if (isAutoRet) { options |= (ulong)Consts.Cmd_Send_Option.AutoRet; } if (isEncrypt) { options |= (ulong)Consts.Cmd_All_Option.Encrypt; } if (isSecret) { options |= (ulong)Consts.Cmd_Send_Option.Secret; } if (noPopup) { options |= (ulong)Consts.Cmd_Send_Option.NoPopup; } if (sendCheck && host != null) { return(MessageProxy.SendWithCheck(host, cmd, options, msg, extMsg)); } else { if (host == null) { return(MessageProxy.SendByIp(remoteEndPoint, cmd, options, msg, extMsg)); } else { return(MessageProxy.SendWithNoCheck(host, cmd, options, msg, extMsg)); } } }
//请求查询版本信息 private void ProcessCommand_GetInfo(Message message, Host host) { if (host == null) { return; } string version = Config.VersionInfo; if (string.IsNullOrEmpty(version)) { version = System.Reflection.Assembly.GetExecutingAssembly().FullName; } MessageProxy.SendWithNoCheck(host, Consts.Commands.SendInfo, 0, version, ""); }
//Br_Exit void ProcessCommand_Br_Exit(Message m, Host h) { //如果开启了通知功能,则告知非本网段主机 if (h == null) { return; } LivedHost.Delete(h.HostSub.Ipv4Address.Address.ToString()); //通知非本网段主机 if (Config.EnableHostNotifyBroadcast && !Config.ForceOldContract) { Host[] list = LivedHost.Values.Where(s => s.HostSub.IPHeader != h.HostSub.IPHeader).Distinct(Helper.HostSubEqualityCompare.StaticObj).ToArray(); Array.ForEach(list, s => { MessageProxy.SendWithNoCheck(s, Consts.Commands.Br_Exit_Forward, 0, s.HostSub.Ipv4Address.Address.GetAddressBytes(), BitConverter.GetBytes(s.HostSub.PortNo)); }); } }
/// <summary> /// 发送确认打开消息的包 /// </summary> /// <param name="m">原始数据包</param> public void SendReadMessageSignal(Message m) { MessageProxy.SendWithNoCheck(m.Host, Consts.Commands.ReadMsg, 0, m.PackageNo.ToString(), ""); }
//Br_Entry void ProcessCommand_Br_Entry(Message m, Host h) { if (h == null && (Config.IgnoreNoAddListFlag || !Consts.Check(m.Options, Consts.Cmd_Send_Option.NoAddList))) { h = new Host() { ClientVersion = string.Empty, GroupName = m.ExtendMessage, HasShare = false, HostSub = new HostSub() { HostName = m.HostName, Ipv4Address = m.HostAddr, UserName = m.UserName }, Index = 0, IsEnhancedContractEnabled = Consts.Check(m.Options, Consts.Cmd_All_Option.EnableNewDataContract), NickName = m.NormalMsg, HostFeature = m.Options }; if (Consts.Check(m.Options, Consts.Cmd_All_Option.Absence)) { h.ChangeAbsenceMode(true, Resources.CommandExecutor_ProcessCommand_Br_Entry_LeaveModeText); } h.SupportEncrypt = Consts.Check(m.Options, Consts.Cmd_All_Option.Encrypt); h.SupportFileTransport = Consts.Check(m.Options, Consts.Cmd_All_Option.FileAttach); LivedHost.Add(m.HostAddr.Address.ToString(), h); h.AbsenceModeChanged += Host_AbsendModeChanged; //立刻查询离开消息 if (h.IsInAbsenceMode) { Host_AbsendModeChanged(h, null); } m.Host = h; } ulong opt = 0ul; if (Config.IsInAbsenceMode) { opt |= (ulong)Consts.Cmd_All_Option.Absence; } if (Config.EnableFileTransfer) { opt |= (ulong)Consts.Cmd_All_Option.FileAttach; } //插件 if (Config.Services != null) { Config.Services.ProviderExecute(s => opt |= s.GenerateClientFeatures()); } //回复证明自己在线 MessageProxy.SendWithNoCheck(h, Consts.Commands.AnsEntry, opt, Config.NickName, Config.GroupName); //如果开启了通知功能,则告知非本网段主机 if (h != null && Config.EnableHostNotifyBroadcast && !Config.ForceOldContract) { Host[] list = LivedHost.Values.Where(s => s.HostSub.IPHeader != h.HostSub.IPHeader && h.IsEnhancedContractEnabled).Distinct(Helper.HostSubEqualityCompare.StaticObj).ToArray(); Array.ForEach(list, s => MessageProxy.SendWithNoCheck(s, Consts.Commands.Br_Entry_Forward, 0, s.HostSub.Ipv4Address.Address.GetAddressBytes(), BitConverter.GetBytes(s.HostSub.PortNo))); } }
/// <summary> /// 将信息解密函数挂钩 /// </summary> /// <param name="cmd"></param> public void HandleEncryptedMessage(CommandExecutor cmd) { //加密信息预先解密 cmd.TextMessageReceiving += (s, e) => { if (!e.IsHandled && e.Message.IsEncrypt) { DecryptMessage(cmd, e); } }; cmd.MessageProxy.MessageSending += (s, e) => { if (!e.IsHandled && e.Message.Command == Consts.Commands.SendMsg && e.Message.IsEncrypt) { EncryptMessage(cmd, e); } }; cmd.MessageProcessing += (s, e) => { if (e.IsHandled || e.Host == null) { return; } if (e.Message.Command == Consts.Commands.AnsPubKey) { //发送确认消息 MessageProxy.SendWithNoCheck(e.Host, Consts.Commands.RecvMsg, 0ul, e.Message.PackageNo.ToString(), ""); //分析 int index = e.Message.NormalMsg.IndexOf(":"); if (index == -1) { return; } ulong capa; if (!ulong.TryParse(e.Message.NormalMsg.Substring(0, index++), System.Globalization.NumberStyles.AllowHexSpecifier, null, out capa)) { return; } if ((capa & EncryptCapa) == 0) { return; } e.Host.SupportEncrypt = true; e.Host.IsEncryptUseSmallKey = (capa & EncryptNormalCapa) == 0; int nextMatch; if ((nextMatch = e.Message.NormalMsg.IndexOf('-', index)) == -1) { return; } byte[] exp = e.Message.NormalMsg.Substring(index, nextMatch - index).ConvertToBytes(); if (exp == null) { return; } byte[] pubKey = e.Message.NormalMsg.Substring(nextMatch + 1).ConvertToBytes(); if (pubKey == null) { return; } e.Host.SetEncryptInfo(pubKey, exp); //查看有没有队列消息,有就发出去 if (e.Host.QueuedMessage != null && e.Host.QueuedMessage.Count > 0) { Message m = null; while (e.Host.QueuedMessage.Count > 0) { m = e.Host.QueuedMessage.Dequeue(); MessageProxy.Send(m); } } } else if (e.Message.Command == Consts.Commands.GetPubKey) { ulong capa; if (!ulong.TryParse(e.Message.NormalMsg, System.Globalization.NumberStyles.AllowHexSpecifier, null, out capa)) { return; } if ((capa & EncryptCapa) == 0) { return; } //返回响应 e.Host.SupportEncrypt = true; e.Host.IsEncryptUseSmallKey = (capa & EncryptNormalCapa) == 0; byte[] key = e.Host.IsEncryptUseSmallKey ? PublicKey_512 : PublicKey_1024; byte[] exp = e.Host.IsEncryptUseSmallKey ? Exponent_512 : Exponent_1024; string content = string.Format("{0}:{1}-{2}", EncryptCapa.ToString("x"), BitConverter.ToString(exp).Replace("-", ""), BitConverter.ToString(key).Replace("-", "")).ToLower(); MessageProxy.SendWithNoCheck(e.Host, Consts.Commands.AnsPubKey, 0ul, content, ""); } }; }