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();
            }
        }