Example #1
0
 public Partner(Socket s, SecondLevelCacheClusterTransportBase t)
 {
     ClientSocket = s;
     Definition   = t;
     HeaderBuffer = new byte[t.HeaderLength];
     alias        = name = s.RemoteEndPoint.ToString();
 }
Example #2
0
        static void ReadCallback(IAsyncResult ar)
        {
            // Retrieve the state object and the handler socket from the asynchronous state object.
            Partner source = (Partner)ar.AsyncState;

            bool close = false;

            try
            {
                // Read data from the client socket.
                int bytesRead = source.ClientSocket.EndReceive(ar);

                // TODO Handle situations when the messages get fragmented and not all bytes are returned immediately.
                if (bytesRead == source.Definition.HeaderLength)
                {
                    SecondLevelCacheClusterTransportBase.OpCode code;
                    int len = source.Definition.ReadHeader(source.HeaderBuffer, out code);
                    if (len > definition.MaxMessageSize)
                    {
                        close = true; // A little protection must be.
                    }
                    else if (len > 0 && (code & SecondLevelCacheClusterTransportBase.OpCode.Evict) != 0)
                    {
                        var tmp = new byte[len + source.Definition.HeaderLength];
                        Buffer.BlockCopy(source.HeaderBuffer, 0, tmp, 0, source.Definition.HeaderLength);

                        // Assumption: Because the sender pushes one message, we should have all bytes received in the
                        // OS already, and we can use synchronous calls here without negative effects.
                        if (SecondLevelCacheClusterTransportBase.ReceiveAll(source.ClientSocket, tmp, source.Definition.HeaderLength, len))
                        {
                            source.Evictions++;
                            var bc = new Broadcast()
                            {
                                Data = tmp, Sender = source
                            };
                            Console.WriteLine("RECEIVED #{0} of {1} bytes from {2}", bc.Number, tmp.Length, source);

                            // Let some other thread do the work of actually sending the message out.
                            ThreadPool.QueueUserWorkItem(PerformBroadcast, bc);
                        }
                        else
                        {
                            Console.WriteLine("Data truncation {0} bytes from {1}", len, source);
                            close = true;
                        }
                    }
                    else
                    {
                        if ((code & SecondLevelCacheClusterTransportBase.OpCode.Hello) != 0)
                        {
                            var nameBytes = new byte[len];
                            if (SecondLevelCacheClusterTransportBase.ReceiveAll(source.ClientSocket, nameBytes, 0, len))
                            {
                                try
                                {
                                    var name = Encoding.UTF8.GetString(nameBytes);
                                    source.SetAlias(name);
                                    Console.WriteLine("HELLO {0}", source);
                                    Buffer.BlockCopy(BitConverter.GetBytes((int)SecondLevelCacheClusterTransportBase.OpCode.Welcome), 0, source.HeaderBuffer, definition.HeaderLength - 4, 4);
                                    close = SecondLevelCacheClusterTransportBase.SendAll(source.ClientSocket, source.HeaderBuffer, 0, source.HeaderBuffer.Length) == false;
                                }
                                catch
                                {
                                    close = true;
                                }
                            }
                            else
                            {
                                close = true;
                            }
                        }
                        else
                        {
                            Console.WriteLine("RECEIVED {0} / {1} from {2}", code, len, source);
                        }
                    }
                }
                else
                {
                    close = true;
                }
            }
            catch
            {
                close = true;
            }

            if (close)
            {
                // Something went wrong, let's disconnect from the partner. Maybe a better handling can be done.
                source.ClientSocket.Shutdown(SocketShutdown.Both);
                source.ClientSocket.Close();
                source.ClientSocket.Dispose();
                lock (clients)
                {
                    clients.Remove(source);
                    Console.WriteLine("DISCONNECTED {0}", source);
                }
            }
            else
            {
                // Immediately try to receive the next message from the same partner.
                source.ClientSocket.BeginReceive(source.HeaderBuffer, 0, source.HeaderBuffer.Length, SocketFlags.None,
                                                 new AsyncCallback(ReadCallback), source);
            }
        }