protected StrMessage ParseMessage(string raw) { raw = raw.Replace(this.Seperator, ""); StrMessage msg = new StrMessage(trans, raw); switch (raw[0]) { case '$': int pos; string cmd = null; if ((pos = raw.IndexOf(' ')) != -1) cmd = raw.Substring(0, pos).ToLower(); else { if (raw.Length >= 10) break; cmd = raw.ToLower(); } if (cmd == null || cmd.Equals(string.Empty)) break; switch (cmd) { case "$mynick": msg = new MyNick(trans,raw); break; case "$lock": msg = new Lock(trans, raw); break; case "$supports": msg = new Supports(trans, raw); break; case "$send": msg = new Send(trans, raw); break; case "$key": msg = new Key(trans, raw); break; case "$direction": msg = new Direction(trans, raw); break; case "$get": msg = new Get(trans, raw); break; case "$ugetblock": msg = new UGetBlock(trans, raw); break; case "$ugetzblock": msg = new UGetZBlock(trans, raw); break; case "$adcget": msg = new ADCGET(trans, raw); break; case "$adcsnd": msg = new ADCSND(trans, raw); break; case "$filelength": msg = new FileLength(trans, raw); break; case "$sending": msg = new Sending(trans, raw); break; case "$error": msg = new Error(trans, raw); break; case "$getlistlen": msg = new GetListLen(trans, raw); break; case "$maxedout": msg = new MaxedOut(trans, raw); break; case "$failed": msg = new Failed(trans, raw); break; } break; default: break; // No command. Ignore. } return msg; }
public void ActOnInMessage(IConMessage conMsg) { StrMessage message = (StrMessage)conMsg; if (message is Lock) { Lock lk = (Lock)message; if (lk.Extended) trans.Send(mySupport = new Supports(trans)); GetSegment(true); Direction dir = new Direction(trans, this.download); this.downloadRandom = dir.Number; trans.Send(dir); trans.Send(new Key(lk.Key, trans)); } else if (message is Key) { OnDownload(); } else if (message is MyNick) { MyNick myNick = (MyNick)message; if (trans.Source != null && !string.IsNullOrEmpty(trans.Source.ConnectionId)) { string conId = trans.Source.ConnectionId; string usrId = trans.Source.UserId; if (string.IsNullOrEmpty(usrId)) { // connection Id + User Id will give us the users StoredId trans.Source = new Source(conId, conId + myNick.Info.ID); } } else { trans.Source = new Source(null, myNick.Info.ID); } trans.User = myNick.Info; TransferRequest req = new TransferRequest(trans.Source); FmdcEventArgs eArgs = new FmdcEventArgs(0, req); RequestTransfer(trans, eArgs); req = eArgs.Data as TransferRequest; if (!eArgs.Handled || req == null) { if (trans.Me == null || trans.Share == null) { // Can't see user on my allow list trans.Disconnect("No match for Request"); return; } else { // As developers already started to use this. // We need to support the same behaivor as before (not doing anything when we are passive). } } if (trans.Me == null || trans.Share == null) { trans.Me = req.Me; trans.User = req.User; trans.Share = req.Share; trans.Source = req.Source; trans.Send(new Lock(trans)); } else { trans.User = myNick.Info; //trans.Source.UserId = trans.Source.ConnectionId.Replace(":", string.Empty) + trans.User.StoreID; // Do we want to specify a Share for this connection? if (eArgs.Handled && req.Share != null) { trans.Share = req.Share; } } } else if (message is Supports) { // Sets Supports for protocol. Supports sup = (Supports)message; userSupport = sup; } else if (message is Direction) { userDir = (Direction)message; } else if (message is Sending) { Sending sending = (Sending)message; if (trans.DownloadItem.ContentInfo.Size == -1) { trans.DownloadItem.ContentInfo.Size = sending.Length; trans.DownloadItem.SegmentSize = sending.Length; EnsureCurrentSegmentCancelation(); GetSegment(false); } else if (trans.CurrentSegment != null && trans.CurrentSegment.Length != sending.Length) { trans.Disconnect("Why would i want to get a diffrent length of bytes then i asked for?"); return; } this.rawData = true; trans.ShouldBlockOnSend = true; } else if (message is FileLength) { FileLength fileLength = (FileLength)message; if (trans.DownloadItem.ContentInfo.Size == -1) { trans.DownloadItem.ContentInfo.Size = fileLength.Length; trans.DownloadItem.SegmentSize = fileLength.Length; EnsureCurrentSegmentCancelation(); GetSegment(false); } else if (trans.CurrentSegment != null && trans.CurrentSegment.Length != fileLength.Length) { trans.Disconnect("Why would i want to get a diffrent length of bytes then i asked for?"); return; } this.rawData = true; trans.ShouldBlockOnSend = true; } else if (message is ADCSND) { ADCSND adcsnd = (ADCSND)message; if (!trans.Content.Get(ContentInfo.REQUEST).Equals(adcsnd.Content)) { trans.Disconnect("I want my bytes.."); return; } if (trans.DownloadItem.ContentInfo.Size == -1) { trans.DownloadItem.ContentInfo.Size = adcsnd.Length; trans.DownloadItem.SegmentSize = adcsnd.Length; EnsureCurrentSegmentCancelation(); GetSegment(false); } else if (trans.CurrentSegment != null && trans.CurrentSegment.Length != adcsnd.Length) { trans.Disconnect("Why would i want to get a diffrent length of bytes then i asked for?"); return; } this.rawData = true; trans.ShouldBlockOnSend = true; } else if (message is Send) { if (this.download || bytesToSend == null || trans.CurrentSegment == null) { trans.Disconnect(); return; } trans.CurrentSegment.Position = bytesToSend.Length; long length = trans.Content.Size; do { trans.Send(new BinaryMessage(trans, bytesToSend, bytesToSend.Length)); trans.CurrentSegment.Position += bytesToSend.Length; } while (connectionStatus != TcpConnection.Disconnected && (bytesToSend = this.GetContent(System.Text.Encoding.ASCII, trans.CurrentSegment.Position, trans.CurrentSegment.Length - trans.CurrentSegment.Position)) != null); trans.Content = null; trans.Disconnect(); } else if (message is Get) { // If we are supposed to download and other client tries to download. Disconnect. if (this.download) { trans.Disconnect(); return; } Get get = (Get)message; trans.Content = new ContentInfo(ContentInfo.REQUEST, get.File); trans.CurrentSegment = new SegmentInfo(-1, get.Start, -1); if (get.File.Equals("files.xml.bz2")) { //trans.Content.VirtualName = System.Text.Encoding.ASCII.WebName + get.File; //trans.Content.IdType = ContentIdTypes.Filelist; trans.Content.Set(ContentInfo.FILELIST, Utils.FileLists.BaseFilelist.XMLBZ); trans.Content.Set(ContentInfo.VIRTUAL, System.Text.Encoding.ASCII.WebName + get.File); } else { //trans.Content.VirtualName = get.File; trans.Content.Set(ContentInfo.VIRTUAL, get.File); } bytesToSend = this.GetContent(System.Text.Encoding.ASCII, trans.CurrentSegment.Start + trans.CurrentSegment.Position, trans.CurrentSegment.Length - trans.CurrentSegment.Position); // Do file exist? if (trans.Content.Size > -1) { trans.Send(new FileLength(trans, trans.Content.Size)); } else { trans.Send(new Error("File Not Available", trans)); } } else if (message is GetBlocks) { // If we are supposed to download and other client tries to download. Disconnect. if (this.download) { trans.Disconnect(); return; } GetBlocks getblocks = (GetBlocks)message; trans.Content = new Containers.ContentInfo(ContentInfo.REQUEST, getblocks.FileName); if (getblocks.FileName.Equals("files.xml.bz2")) { //trans.Content.VirtualName = System.Text.Encoding.UTF8.WebName + getblocks.FileName; //trans.Content.IdType = ContentIdTypes.Filelist; trans.Content.Set(ContentInfo.VIRTUAL, System.Text.Encoding.UTF8.WebName + getblocks.FileName); trans.Content.Set(ContentInfo.FILELIST, Utils.FileLists.BaseFilelist.XMLBZ); } else { trans.Content.Set(ContentInfo.VIRTUAL, getblocks.FileName); } trans.CurrentSegment = new SegmentInfo(-1, getblocks.Start, getblocks.Length); bool firstTime = true; while (connectionStatus != TcpConnection.Disconnected && (bytesToSend = GetContent(System.Text.Encoding.UTF8, trans.CurrentSegment.Start + trans.CurrentSegment.Position, trans.CurrentSegment.Length - trans.CurrentSegment.Position)) != null) { if (firstTime) { trans.Send(new Sending(trans)); firstTime = false; } trans.Send(new BinaryMessage(trans, bytesToSend, bytesToSend.Length)); trans.CurrentSegment.Position += bytesToSend.Length; } if (firstTime) trans.Send(new Failed("File Not Available", trans)); trans.CurrentSegment = new SegmentInfo(-1); trans.Content = null; } else if (message is ADCGET) { // If we are supposed to download and other client tries to download. Disconnect. if (this.download) { trans.Disconnect(); return; } ADCGET adcget = (ADCGET)message; trans.Content = new ContentInfo(ContentInfo.REQUEST, adcget.Content); switch (adcget.Type.ToLower()) { case "file": if (adcget.Content.StartsWith("TTH/")) { //trans.Content.Id = adcget.Content.Substring(4); //trans.Content.IdType = ContentIdTypes.TTH | ContentIdTypes.Hash; trans.Content.Set(ContentInfo.TTH, adcget.Content.Substring(4)); } else { if (adcget.Content.Equals("files.xml.bz2")) { //trans.Content.VirtualName = System.Text.Encoding.UTF8.WebName + adcget.Content; //trans.Content.IdType = ContentIdTypes.Filelist; trans.Content.Set(ContentInfo.VIRTUAL, System.Text.Encoding.UTF8.WebName + adcget.Content); trans.Content.Set(ContentInfo.FILELIST, Utils.FileLists.BaseFilelist.XMLBZ); } else { trans.Content.Set(ContentInfo.VIRTUAL, adcget.Content); } } break; case "tthl": // TTH/DQSGG2MYKKLXX4N2P7TBPKSC5HVBO3ISYZPLMWA if (adcget.Content.StartsWith("TTH/")) { trans.Content.Set(ContentInfo.TTH, adcget.Content.Substring(4)); ContentInfo tmp = trans.Content; if (trans.Share != null && trans.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 ADCSND adcsend = new ADCSND(trans); adcsend.Type = adcget.Type; adcsend.Content = adcget.Content; adcsend.Start = trans.CurrentSegment.Start; adcsend.Length = trans.CurrentSegment.Length; adcsend.ZL1 = adcget.ZL1; trans.Send(adcsend); // Send content to user trans.Send(new BinaryMessage(trans, bytes, bytes.Length)); //System.Console.WriteLine("TTH Leaves:" + FlowLib.Utils.Convert.Base32.Encode(bytes)); trans.Content = null; //trans.Disconnect(); return; } } break; } trans.CurrentSegment = new SegmentInfo(-1, adcget.Start, adcget.Length); bool firstTime = true; 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.Start + trans.CurrentSegment.Position, trans.CurrentSegment.Length - trans.CurrentSegment.Position)) != null) { if (firstTime) { ADCSND adcsend = new ADCSND(trans); adcsend.Type = adcget.Type; adcsend.Content = adcget.Content; adcsend.Start = adcget.Start; adcsend.Length = trans.CurrentSegment.Length; adcsend.ZL1 = adcget.ZL1; trans.Send(adcsend); firstTime = false; } trans.CurrentSegment.Position += bytesToSend.Length; // We want to compress content with ZLib //if (zlib != null) //{ // zlib.Compress2(bytesToSend); // bytesToSend = zlib.Read(); //} trans.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. trans.Send(new Error("File Not Available", trans)); trans.Disconnect(); } } else if (message is MaxedOut) { FmdcEventArgs e = new FmdcEventArgs((int)TransferErrors.NO_FREE_SLOTS); Error(trans, e); if (!e.Handled) trans.Disconnect(); } else if (message is Error) { TransferNmdc.Error error = (TransferNmdc.Error)message; FmdcEventArgs e = null; // TODO : Add more error messages here. switch (error.Message) { case "File Not Available": e = new FmdcEventArgs((int)TransferErrors.FILE_NOT_AVAILABLE); break; default: e = new FmdcEventArgs((int)TransferErrors.UNKNOWN, error.Message); break; } Error(trans, e); if (!e.Handled) trans.Disconnect(); } else if (message is Failed) { Failed failed = (Failed)message; FmdcEventArgs e = null; // TODO : Add more error messages here. switch (failed.Message) { case "File Not Available": e = new FmdcEventArgs((int)TransferErrors.FILE_NOT_AVAILABLE); break; default: e = new FmdcEventArgs((int)TransferErrors.UNKNOWN, failed.Message); break; } Error(trans, e); if (!e.Handled) trans.Disconnect(); } }