int IMessageController.BroadcastToWire(SendBroadcastMemory message)
 {
     if (this.IsAlive)
         return CastTargetController.BroadcastToWire(message);
     else
         return 0;
 }
 int IMessageController.BroadcastToWire(SendBroadcastMemory message)
 {
     if (this.IsAlive)
     {
         return(CastTargetController.BroadcastToWire(message));
     }
     else
     {
         return(0);
     }
 }
        private void HandleReadDelete(string contentLocation,string eTag, List<int> senders, List<int> responsePath )
        {
            // handle proxy messages
            if (contentLocation.StartsWith(PROXY_PREFIX + "/"))
            {
                contentLocation = contentLocation.Substring(PROXYPREFIX_REMOVE);
                if (!keysToListen.IsSubscribed(contentLocation))
                {
                    keysToListen.AddSubscription(contentLocation, SubscriptionInitiator.AutoProxyKey);
                }
            }

            // read
            ResponseAction status = ReadDelete(contentLocation, eTag, new List<int>(senders));

            if (status == ResponseAction.ForwardToAll)
            {
                //conflict happened in data somewhere
                // return new data to sender
                senders.Clear();
            }

            if (status != ResponseAction.DoNotForward)
            {
                // send a notification of deleted content immediately
                DataEntry entry = P2PDictionary.GetEntry(this.data, this.dataLock, contentLocation);
                System.Diagnostics.Debug.Assert(entry != null);

                // add to wire to send out
                senders.Add(this.local_uid);// add my sender to the packet
                SendBroadcastMemory sendMsg = new SendBroadcastMemory(entry.key, senders);
                WriteMethodDeleted(sendMsg.MemBuffer, contentLocation, senders, responsePath, entry.lastOwnerID, entry.lastOwnerRevision);
                controller.BroadcastToWire(sendMsg);
            }

            if (responsePath != null)
            {
                // well, i still have to send out this message because there is a path requested to follow
                DataEntry entry = P2PDictionary.GetEntry(this.data, this.dataLock, contentLocation);
                System.Diagnostics.Debug.Assert(entry != null);

                SendMemoryToPeer sendMsg = new SendMemoryToPeer(entry.key, responsePath);
                senders.Add(this.local_uid);// add my sender to the packet
                WriteMethodDeleted(sendMsg.MemBuffer, PROXY_PREFIX + contentLocation, senders, responsePath, entry.lastOwnerID, entry.lastOwnerRevision);

            }
        }
        /// <summary>
        /// TODO: add in some code to reduce round-trips to simple data types 
        /// </summary>
        /// <param name="reader">File to read</param>
        /// <param name="sentFromList">Sent from list</param>
        /// <param name="getEntriesFromSender">This function fills in a list of entries that need to be requested from the sender</param>
        /// <param name="addEntriesToSender">These are entries that the sender does not know about</param>
        /// <seealso cref="ReadHeadStub"/>
        private void ReadDictionaryTextFile(StreamReader reader, List<int> sentFromList, List<DataHeader> getEntriesFromSender, List<SendMemoryToPeer> addEntriesToSender)
        {
            // 0 - key name
            // 1 - owner
            // 2 - revision
            // 3 - rw flag
            // 4 - MIME type

            // WriteDebug(this.local_uid + " ReadDictionaryTextFile");

            string nsLine = reader.ReadLine();
            string[] nsLineParts = nsLine.Split('\t');

            System.Diagnostics.Debug.Assert(nsLineParts[0] == DATA_NAMESPACE + "/");

            // if the owner of the dictionary is the same as myself, skip reading the changes
            if (nsLineParts[1] == this.local_uid.ToString())
            {
                throw new NotSupportedException("ReadDictionaryTextFile cannot read itself");// i want to see if this actually can happen (only when multiple connections happen on the same server)

            }

            int itemCount = int.Parse(nsLineParts[4]); // count of all the items in the dictionary

            List<DataEntry> entriesCovered = new List<DataEntry>(itemCount + this.data.Count);

            for (int i = 0; i < itemCount; i++)
            {
                nsLine = reader.ReadLine();
                nsLineParts = nsLine.Split('\t');
                //WriteDebug(nsLine);

                DataHeader getEntry = null;
                SendMemoryToPeer addEntryToSender = null;

                ETag tag = new ETag(int.Parse(nsLineParts[1]), int.Parse(nsLineParts[2]));

                // this entry is used only to call ReadMimeSimpleData
                DataEntry fakeEntry = new DataEntry("/fake", tag, new List<int>(0));
                fakeEntry.ReadMimeSimpleData(nsLineParts[4]);

                dataLock.EnterReadLock();
                try
                {
                    if (this.data.ContainsKey(nsLineParts[0]))
                    {
                        entriesCovered.Add(this.data[nsLineParts[0]]);
                    }
                }
                finally { dataLock.ExitReadLock(); }

                // the dictionary does not report the current sender so let's tack it on
                List<int> listOfSenders = new List<int>(GetArrayOf(nsLineParts[5]));
                if (!listOfSenders.Contains(this.remote_uid))
                    listOfSenders.Add(this.remote_uid);

                ResponseAction action = ReadDataStub(nsLineParts[0], fakeEntry.GetMime(), nsLineParts[1] + "." + nsLineParts[2], new List<int>( listOfSenders), out getEntry, out addEntryToSender);

                if (getEntry != null)
                {
                    getEntriesFromSender.Add(getEntry);
                }
                if (addEntryToSender != null)
                {
                    addEntriesToSender.Add(addEntryToSender);
                }

                if (action == ResponseAction.ForwardToAll)
                {
                    listOfSenders.Clear();
                }
                if (action != ResponseAction.DoNotForward)
                {
                    DataEntry get = P2PDictionary.GetEntry( this.data, this.dataLock, nsLineParts[0]);
                    System.Diagnostics.Debug.Assert(get != null);

                    listOfSenders.Add(this.local_uid);
                    SendBroadcastMemory msg = new SendBroadcastMemory(get.key , listOfSenders);
                    WriteMethodPush(get.key, listOfSenders, null, 0, get.GetMime(), get.GetETag(), get.IsEmpty, false, msg.MemBuffer);
                    this.controller.BroadcastToWire(msg);
                }
            }

            // now check to see which dictionary entries that the sender does not have; i'll send my entries to the caller
            this.dataLock.EnterWriteLock();
            try
            {
                foreach (KeyValuePair<string, DataEntry> senderDoesNotHave in this.data.SkipWhile(x => entriesCovered.Contains(x.Value)))
                {
                    DataEntry get = senderDoesNotHave.Value;

                    // i know about something that the sender does not know
                    SendMemoryToPeer mem = new SendMemoryToPeer(get.key, sentFromList);
                    WriteMethodPush(get.key, GetListOfThisLocalID(), null, 0, get.GetMime(), get.GetETag(), get.IsEmpty, false, mem.MemBuffer);
                    addEntriesToSender.Add(mem);
                }
            }
            finally { this.dataLock.ExitWriteLock();}
        }
        private void HandleReadPut(string contentLocation, string contentType, byte[] readData, string eTag, List<int> senders, List<int> responsePath)
        {
            // process the packet
                if (contentLocation == DATA_NAMESPACE)
                {
                    List<DataHeader> missingData = new List<DataHeader>();
                    List<SendMemoryToPeer> sendBack = new List<SendMemoryToPeer>();
                    ReadDictionaryTextFile(new StreamReader(new MemoryStream(readData)), new List<int>(senders), missingData, sendBack);

                    // and then update my copy of the dictionary
                    controller.PullFromPeer(missingData);

                    // and update the sender's dictionary
                    controller.SendToPeer(sendBack);
                }
                else
                {
                    if (contentLocation.StartsWith(PROXY_PREFIX + "/"))
                    {
                        // this is a pushed message from a proxy request
                        // so I should subscribe to the key

                        contentLocation = contentLocation.Substring(PROXYPREFIX_REMOVE);
                        if (!keysToListen.IsSubscribed(contentLocation))
                        {
                            keysToListen.AddSubscription(contentLocation, SubscriptionInitiator.AutoProxyKey);
                        }

                    }

                    ResponseAction status = ReadData(contentLocation, eTag, contentType, new List<int>(senders), readData);

                    // data propagation for following a proxy
                    if (responsePath != null)
                    {
                        List<int> followPath = new List<int>(responsePath);
                        followPath.Remove(this.remote_uid);

                        // send data along the path
                        senders.Add(this.local_uid);
                        SendMemoryToPeer sendMsg = CreateResponseMessage(contentLocation, PROXY_PREFIX + contentLocation, senders, followPath, responsePath);
                        controller.SendToPeer(sendMsg);
                    }

                    if (status == ResponseAction.ForwardToAll)
                    {
                        //conflict happened in data somewhere
                        // return new data to sender
                        senders.Clear();
                    }

                    if (status != ResponseAction.DoNotForward)
                    {
                        // add my sender to the packet
                        senders.Add(this.local_uid);

                        // add to wire to send out
                        SendBroadcastMemory sendMsg = new SendBroadcastMemory(contentLocation, senders);

                        DataEntry get = P2PDictionary.GetEntry(this.data, this.dataLock, contentLocation);
                        System.Diagnostics.Debug.Assert(get != null);

                        WriteMethodPush(contentLocation, senders, responsePath, 0, get.GetMime(), get.GetETag(), get.IsDeleted, false, sendMsg.MemBuffer);
                        //Response(verb, contentLocation, senders, this.data[contentLocation], sendMsg.MemBuffer, false);
                        controller.BroadcastToWire(sendMsg);
                    }

                }
        }
        private void HandleReadPush(string contentLocation, string contentType, string eTag, List<int> senders, int lastSender, List<int> responsePath)
        {
            ETag tag = ReadETag(eTag);

            if (contentLocation == DATA_NAMESPACE)
            {
                //// tell others that a new dictionary entered
                //// add to wire to send out
                //SendMemory sendMsg = new SendMemory(senders);
                //ResponseDictionary(verb, sendMsg.MemBuffer, senders, false);
                //controller.BroadcastToWire(sendMsg);

                // don't forward message because the GET method call will do it

                // let me update my model first by
                // requesting to pull data from the other side
                // before sending out a HEAD
                DataHeader hdr = new DataHeader(contentLocation, tag, lastSender);
                controller.PullFromPeer(hdr);

            }
            else
            {
                if (contentLocation.StartsWith(PROXY_PREFIX + "/"))
                {
                    // this is a pushed message from a proxy request
                    // so I should subscribe to the key

                    contentLocation = contentLocation.Substring(PROXYPREFIX_REMOVE);
                    throw new NotImplementedException();
                }

                DataHeader getEntryFromSender;
                SendMemoryToPeer addEntryToSender;

                ResponseAction action = ReadDataStub(contentLocation, contentType, eTag, new List<int>(senders), out getEntryFromSender, out addEntryToSender);

                if (action == ResponseAction.ForwardToAll)
                {
                    senders.Clear();
                }

                if (action != ResponseAction.DoNotForward)
                {
                    // forward a HEAD message (because we didn't do it when we got a 200/HEAD notification)
                    DataEntry get = P2PDictionary.GetEntry(this.data, this.dataLock, contentLocation);
                    System.Diagnostics.Debug.Assert(get != null);

                    senders.Add(this.local_uid);
                    SendBroadcastMemory sendMsg = new SendBroadcastMemory(contentLocation, senders);
                    WriteMethodPush(contentLocation, senders, responsePath, 0, get.GetMime(), get.GetETag(), get.IsDeleted, false, sendMsg.MemBuffer);
                    controller.BroadcastToWire(sendMsg);
                }

                if (getEntryFromSender != null)
                {
                    // and get data from the caller
                    controller.PullFromPeer(getEntryFromSender);
                }

                if (addEntryToSender != null)
                {
                    // send any updates to the peer
                    controller.SendToPeer(addEntryToSender);
                }
            }
        }