public void ActOnInMessage(IConMessage conMsg) { StrMessage message = (StrMessage)conMsg; #region INF if (message is INF) { INF inf = (INF)message; if (hub != null && inf.Type.Equals("I")) { if (hub.RegMode < 0) hub.RegMode = 0; UpdateInf(); Info = inf.UserInfo; if (hub != null && Info.Description == null) Update(con, new FmdcEventArgs(Actions.Name, new Containers.HubName(Info.DisplayName))); else if (hub != null) Update(con, new FmdcEventArgs(Actions.Name, new Containers.HubName(Info.DisplayName, Info.Description))); } else if (trans != null && inf.Type.Equals("C")) { string token = null; // CINF IDE3VACJVAXNOQLGRFQS7D5HYH4A6GLZDO3LJ33HQ TO2718662518 if (trans.Me != null && trans.Me.ContainsKey("TO")) token = trans.Me.Get("TO"); else if (inf.UserInfo.ContainsKey("TO")) token = inf.UserInfo.Get("TO"); TransferRequest req = new TransferRequest(token, null, inf.UserInfo); FmdcEventArgs eArgs = new FmdcEventArgs(0, req); RequestTransfer(trans, eArgs); req = eArgs.Data as TransferRequest; if (!eArgs.Handled || req == null) { // Can't see user/connection on my allow list trans.Disconnect("No match for Request"); return; } if (!((req.User.ContainsKey(UserInfo.CID) && inf.UserInfo.ContainsKey(UserInfo.CID)) && req.User.Get(UserInfo.CID).Equals(inf.UserInfo.Get(UserInfo.CID)))) { // For some reason user is trying to tell us it is a diffrent user. We dont like that. FmdcEventArgs e = new FmdcEventArgs((int)TransferErrors.USERID_MISMATCH); Error(trans, e); if (!e.Handled) { trans.Disconnect("User Id Mismatch"); return; } } if (trans.Me == null) trans.Me = req.Me; trans.User = req.User; info = trans.User; trans.Share = req.Share; trans.Source = req.Source; download = req.Download; con.Send(new INF(con, trans.Me)); if (download) { EnsureCurrentSegmentCancelation(); // Request new segment from user. IF we have found one. ELSE disconnect. if (GetSegment(true)) { OnDownload(); } else trans.Disconnect("All content downloaded"); } } else if (hub != null) { User usr = null; if ((usr = hub.GetUserById(inf.Id)) == null) { if (inf.UserInfo.Mode == ConnectionTypes.Unknown) { inf.UserInfo.Mode = ConnectionTypes.Passive; } Update(con, new FmdcEventArgs(Actions.UserOnline, inf.UserInfo)); } else { usr.UserInfo = inf.UserInfo; Update(con, new FmdcEventArgs(Actions.UserInfoChange, usr.UserInfo)); } // This is so we update our own reg/op hub count. if (string.Equals(hub.Me.ID,inf.Id)) { // Should we be marked with key? bool regmodeChanged = false; if (hub.RegMode < 2) { if (((UserInfo.ACCOUNT_FLAG_OPERATOR & inf.UserInfo.Account) == UserInfo.ACCOUNT_FLAG_OPERATOR)) { hub.RegMode = 2; regmodeChanged = true; } else if (((UserInfo.ACCOUNT_FLAG_SUPERUSER & inf.UserInfo.Account) == UserInfo.ACCOUNT_FLAG_SUPERUSER)) { hub.RegMode = 2; regmodeChanged = true; } else if (((UserInfo.ACCOUNT_FLAG_HUBOWNER & inf.UserInfo.Account) == UserInfo.ACCOUNT_FLAG_HUBOWNER)) { hub.RegMode = 2; regmodeChanged = true; } } // Should we be marked as reg? if (hub.RegMode < 1) { if (((UserInfo.ACCOUNT_FLAG_REGISTERED & inf.UserInfo.Account) == UserInfo.ACCOUNT_FLAG_REGISTERED)) { hub.RegMode = 1; regmodeChanged = true; } } if (regmodeChanged) UpdateInf(); IsReady = true; } } } #endregion #region MSG else if (message is MSG && hub != null) { MSG msg = (MSG)message; if (msg.PmGroup == null) { MainMessage main = new MainMessage(msg.From, msg.Content); Update(con, new FmdcEventArgs(Actions.MainMessage, main)); } else { PrivateMessage pm = new PrivateMessage(msg.To, msg.From, msg.Content, msg.PmGroup); Update(con, new FmdcEventArgs(Actions.PrivateMessage, pm)); } } #endregion #region SID else if (message is SID && hub != null) { SID sid = (SID)message; hub.Me.Set(UserInfo.SID, sid.Id); } #endregion #region STA else if (message is STA) { STA sta = (STA)message; if (hub != null) { MainMessage main = new MainMessage(info.ID, sta.Content); Update(con, new FmdcEventArgs(Actions.MainMessage, main)); } } #endregion #region GPA else if (message is GPA) { GPA gpa = (GPA)message; this.gpaString = gpa.RandomData; if (trans != null) { Update(con, new FmdcEventArgs(Actions.Password, null)); } if (hub != null && hub.HubSetting.Password.Length == 0) { Update(con, new FmdcEventArgs(Actions.Password, null)); } else hub.Send(new PAS(hub, gpa.RandomData, hub.HubSetting.Password)); } #endregion #region QUI else if (message is QUI && hub != null) { QUI qui = (QUI)message; User usr = null; if ((usr = hub.GetUserById(qui.Id)) != null) { Update(con, new FmdcEventArgs(Actions.UserOffline, usr.UserInfo)); if (usr.ID == hub.Me.ID) { // TODO : Banning and redirect handling hub.Disconnect(); // Redirect if (!string.IsNullOrEmpty(qui.Address)) Update(con, new FmdcEventArgs(Actions.Redirect, new RedirectInfo(qui.Address, qui.Message, qui.DisconnectedBy))); // Banned else { if (qui.Time != -1) // Sets reconnect attempt to infinite hub.KeepAliveInterval = 0; else hub.KeepAliveInterval = qui.Time; Update(con, new FmdcEventArgs(Actions.Banned, new BannedInfo(qui.Time, qui.Message, qui.DisconnectedBy))); } } } } #endregion #region SUP else if (message is SUP) { if (trans != null && !hasSentSUP) { con.Send(new SUP(con)); } supports = (SUP)message; // TODO : We should really care about what hub support. if (!supports.BASE && !supports.TIGR) { // We will just simply disconnect if hub doesnt support this right now con.Disconnect("Connection doesnt support BASE or BAS0"); } #if !COMPACT_FRAMEWORK // Encrypted transfers if (supports.ADCS) { if ( (hub != null && hub.Me.ContainsKey(UserInfo.SECURE)) || (trans != null && trans.Me.ContainsKey(UserInfo.SECURE)) ) { con.SecureProtocol = SecureProtocols.TLS; } } #endif } #endregion #region RES else if (message is RES) { RES res = (RES)message; SearchResultInfo srinfo = new SearchResultInfo(res.Info, res.Id, res.Token); if (hub != null) Update(con, new FmdcEventArgs(Actions.SearchResult, srinfo)); } #endregion #region SCH else if (message is SCH) { SCH sch = (SCH)message; UserInfo usr = null; if (hub != null) { User u = hub.GetUserById(sch.Id); if (u != null) usr = u.UserInfo; } else if (trans != null) usr = trans.User; SendRES(sch.Info, usr); } #endregion #region CTM else if (message is CTM && hub != null) { CTM ctm = (CTM)message; // We really hate buggy hubsofts. Only reason we will get this message is because hubsoft dont know diffrent between E and D messages. if (ctm.Id == hub.Me.ID) return; User usr = null; string addr = null; // Do we support same protocol? double version = 0.0; if (ctm.Protocol != null && (ctm.Protocol.StartsWith("ADC/") || ctm.Protocol.StartsWith("ADCS/"))) { try { version = double.Parse(ctm.Protocol.Substring( ctm.Protocol.IndexOf("/") +1), CultureInfo.GetCultureInfo("en-GB").NumberFormat); } catch { } } if (version > 1.0) { hub.Send(new STA(hub, ctm.Id, hub.Me.ID, "241", "Protocol is not supported. I only support ADC 1.0/ADCS 0.10 and prior", "TO" + ctm.Token + " PR" + ctm.Protocol)); return; } if ((usr = hub.GetUserById(ctm.Id)) != null && usr.UserInfo.ContainsKey(UserInfo.IP)) { addr = usr.UserInfo.Get(UserInfo.IP); Transfer trans = new Transfer(addr, ctm.Port); trans.Share = hub.Share; // We are doing this because we want to filter out PID and so on. User me = hub.GetUserById(hub.Me.ID); trans.Me = new UserInfo(me.UserInfo); trans.Protocol = new AdcProtocol(trans); #if !COMPACT_FRAMEWORK if (ctm.Secure) trans.SecureProtocol = SecureProtocols.TLS; #endif // Support for prior versions of adc then 1.0 string token = ctm.Token; if (version < 1.0 && ctm.Token.StartsWith("TO")) token = ctm.Token.Substring(2); trans.Me.Set("TO", token); Update(con, new FmdcEventArgs(Actions.TransferRequest, new TransferRequest(token, hub, usr.UserInfo,false))); Update(con, new FmdcEventArgs(Actions.TransferStarted, trans)); } } #endregion #region RCM else if (message is RCM && hub != null) { RCM rcm = (RCM)message; // We really hate buggy hubsofts. Only reason we will get this message is because hubsoft dont know diffrent between E and D messages. if (rcm.Id == hub.Me.ID) return; if (hub.Me.Mode != FlowLib.Enums.ConnectionTypes.Passive && hub.Share != null) { User usr = null; if ((usr = hub.GetUserById(rcm.Id)) != null) { // Do we support same protocol? double version = 0.0; if (rcm.Protocol != null && (rcm.Protocol.StartsWith("ADC/") || rcm.Protocol.StartsWith("ADCS/"))) { try { version = double.Parse(rcm.Protocol.Substring(rcm.Protocol.IndexOf("/") + 1), CultureInfo.GetCultureInfo("en-GB").NumberFormat); } catch { } if (version <= 1.0) { // Support for prior versions of adc then 1.0 string token = rcm.Token; if (version < 1.0 && rcm.Token.StartsWith("TO")) token = rcm.Token.Substring(2); Update(con, new FmdcEventArgs(Actions.TransferRequest, new TransferRequest(token, hub, usr.UserInfo, false))); if (rcm.Secure && hub.Me.ContainsKey(UserInfo.SECURE)) hub.Send(new CTM(hub, rcm.Id, rcm.IDTwo, rcm.Protocol, int.Parse(0 + hub.Me.Get(UserInfo.SECURE)), token)); else hub.Send(new CTM(hub, rcm.Id, rcm.IDTwo, rcm.Protocol, hub.Share.Port, token)); } else { hub.Send(new STA(hub, rcm.Id, hub.Me.ID, "241", "Protocol is not supported. I only support ADC 1.0 and prior", "TO" + rcm.Token + " PR" + rcm.Protocol)); return; } } } } else { // TODO : we should probably return a STA message. } } #endregion #region GFI else if (message is GFI && this.trans != null) { GFI gfi = (GFI)message; if (gfi.Identifier != null) { trans.Content = new ContentInfo(); switch (gfi.ContentType) { case "file": // Requesting file // This is because we have support for old DC++ client and mods like (DCDM who has ASCII encoding) if (gfi.Identifier.Equals("files.xml.bz2")) { trans.Content.Set(ContentInfo.FILELIST, Utils.FileLists.BaseFilelist.XMLBZ); trans.Content.Set(ContentInfo.VIRTUAL, System.Text.Encoding.UTF8.WebName + gfi.Identifier); } else if (gfi.Identifier.StartsWith("TTH/")) { trans.Content.Set(ContentInfo.TTH, gfi.Identifier.Substring(4)); } else { trans.Content.Set(ContentInfo.VIRTUAL, gfi.Identifier); } break; case "list": // TODO : We dont care about what subdirectoy user whats list for trans.Content.Set(ContentInfo.FILELIST, Utils.FileLists.BaseFilelist.XML); trans.Content.Set(ContentInfo.VIRTUAL, System.Text.Encoding.UTF8.WebName + "files.xml"); break; default: // We are not supporting type. Disconnect con.Send(new STA(con, "251", "Type not known:" + gfi.ContentType, null)); con.Disconnect(); return; } SearchInfo si = new SearchInfo(); if (trans.Content.ContainsKey(ContentInfo.TTH)) si.Set(SearchInfo.TYPE, trans.Content.Get(ContentInfo.TTH)); si.Set(SearchInfo.SEARCH, trans.Content.Get(ContentInfo.VIRTUAL)); SendRES(si, trans.User); } } #endregion #region GET else if (message is GET && this.trans != null) { GET get = (GET)message; // If we are supposed to download and other client tries to download. Disconnect. if (trans != null && this.download) { trans.Disconnect(); return; } bool firstTime = true; if (get.Identifier != null) { trans.Content = new ContentInfo(); switch (get.ContentType) { case "file": // Requesting file // This is because we have support for old DC++ client and mods like (DCDM who has ASCII encoding) if (get.Identifier.Equals("files.xml.bz2")) { trans.Content.Set(ContentInfo.FILELIST, Utils.FileLists.BaseFilelist.XMLBZ); trans.Content.Set(ContentInfo.VIRTUAL, System.Text.Encoding.UTF8.WebName + get.Identifier); } else if (get.Identifier.StartsWith("TTH/")) { trans.Content.Set(ContentInfo.TTH, get.Identifier.Substring(4)); } else { trans.Content.Set(ContentInfo.VIRTUAL, get.Identifier); } break; case "list": // TODO : We dont care about what subdirectoy user whats list for trans.Content.Set(ContentInfo.FILELIST, Utils.FileLists.BaseFilelist.XML); trans.Content.Set(ContentInfo.VIRTUAL, System.Text.Encoding.UTF8.WebName + "files.xml"); break; case "tthl": // TTH/DQSGG2MYKKLXX4N2P7TBPKSC5HVBO3ISYZPLMWA if (get.Identifier.StartsWith("TTH/")) { trans.Content.Set(ContentInfo.TTH, get.Identifier.Substring(4)); ContentInfo tmp = trans.Content; if (con.Share != null && con.Share.ContainsContent(ref tmp) && tmp.ContainsKey(ContentInfo.TTHL)) { byte[] bytes = Utils.Convert.Base32.Decode(tmp.Get(ContentInfo.TTHL)); #if !COMPACT_FRAMEWORK trans.CurrentSegment = new SegmentInfo(-1, 0, bytes.LongLength); #else trans.CurrentSegment = new SegmentInfo(-1, 0, bytes.Length); #endif con.Send(new SND(trans, get.ContentType, get.Identifier, new SegmentInfo(-1, trans.CurrentSegment.Start, trans.CurrentSegment.Length))); // Send content to user System.IO.MemoryStream ms = new System.IO.MemoryStream(bytes); ms.Flush(); bytes = ms.ToArray(); con.Send(new BinaryMessage(con, bytes, bytes.Length)); System.Console.WriteLine("TTH Leaves:" + FlowLib.Utils.Convert.Base32.Encode(bytes)); firstTime = true; } } if (!firstTime) { // We should not get here if file is in share. con.Send(new STA(con, "251", "File not available", null)); con.Disconnect(); } return; default: // We are not supporting type. Disconnect con.Send(new STA(con, "251", "Type not known:" + get.ContentType, null)); con.Disconnect(); return; } trans.CurrentSegment = get.SegmentInfo; byte[] bytesToSend = null; try { // TODO : ZLib compression here doesnt work as we want. It takes much memory and much cpu //Util.Compression.ZLib zlib = null; //if (adcget.ZL1) // zlib = new Fmdc.Util.Compression.ZLib(); while (connectionStatus != TcpConnection.Disconnected && (bytesToSend = GetContent(System.Text.Encoding.UTF8, trans.CurrentSegment.Position, trans.CurrentSegment.Length - trans.CurrentSegment.Position)) != null) { if (firstTime) { con.Send(new SND(trans, get.ContentType, get.Identifier, new SegmentInfo(-1, get.SegmentInfo.Start, trans.CurrentSegment.Length))); firstTime = false; } trans.CurrentSegment.Position += bytesToSend.Length; // We want to compress content with ZLib //if (zlib != null) //{ // zlib.Compress2(bytesToSend); // bytesToSend = zlib.Read(); //} con.Send(new BinaryMessage(trans, bytesToSend, bytesToSend.Length)); bytesToSend = null; } // If we compressing data with zlib. We need to send ending bytes too. //if (zlib != null && connectionStatus != Connection.Disconnected) // trans.Send(new ConMessage(trans, zlib.close())); } catch (System.Exception e) { System.Console.WriteLine("ERROR:" + e); } } trans.CurrentSegment = new SegmentInfo(-1); trans.Content = null; if (firstTime) { // We should not get here if file is in share. con.Send(new STA(con, "251", "File not available", null)); con.Disconnect(); } } #endregion #region SND else if (message is SND) { SND snd = (SND)message; if (!trans.Content.Get(ContentInfo.REQUEST).Equals(snd.Identifier)) { trans.Disconnect("I want my bytes.."); return; } if (trans.DownloadItem.ContentInfo.Size == -1) { trans.DownloadItem.ContentInfo.Size = snd.SegmentInfo.Length; trans.DownloadItem.SegmentSize = snd.SegmentInfo.Length; EnsureCurrentSegmentCancelation(); GetSegment(false); } else if (trans.CurrentSegment != null && trans.CurrentSegment.Length != snd.SegmentInfo.Length) { trans.Disconnect("Why would i want to get a diffrent length of bytes then i asked for?"); return; } this.IsRawData = true; trans.ShouldBlockOnSend = true; } #endregion }
protected StrMessage ParseMessage(string raw) { raw = raw.Replace(this.Seperator, ""); AdcBaseMessage msg = new AdcBaseMessage(con, raw); switch (msg.Action) { case "SUP": msg = new SUP(con, raw); break; case "SID": msg = new SID(con, raw); break; case "MSG": msg = new MSG(con, raw); break; case "INF": msg = new INF(con, raw); break; case "STA": msg = new STA(con, raw); break; case "QUI": msg = new QUI(con, raw); break; case "GPA": msg = new GPA(con, raw); break; case "CTM": msg = new CTM(con, raw); break; case "SND": msg = new SND(con, raw); break; case "GFI": msg = new GFI(con, raw); break; case "GET": msg = new GET(con, raw); break; case "RCM": msg = new RCM(con, raw); break; case "SCH": msg = new SCH(con, raw); break; case "RES": msg = new RES(con, raw); break; case "PAS": msg = new PAS(con, raw); break; } return msg; }