示例#1
0
        public void SendMessage(WSAgent agent, OSD message, ThrottleCategory category)
        {
            byte[] messageData = Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(message));
            byte[] data        = BuildMessageBuffer_00(messageData, true);

            SendMessageData(agent, data, category);
        }
示例#2
0
        /// <summary>
        /// Process a reception conforming to rev 00 of the WebSocket spec
        /// </summary>
        /// <param name="agent"></param>
        /// <param name="socket"></param>
        /// <param name="remoteEndPoint"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        private string HandleWebSocketReceive_00(WSAgent agent, Socket socket, IPEndPoint remoteEndPoint, SocketAsyncEventArgs args)
        {
            if (agent == null)
            {
                // m_log.Debug("Sending handshake response to " + remoteEndPoint);
                byte[] byteRequest = new byte[args.BytesTransferred];
                Buffer.BlockCopy(args.Buffer, args.Offset, byteRequest, 0, args.BytesTransferred);

                // create the controlling agent for this new stream
                agent = new WSAgent(m_server, m_throttle, m_throttleRates, UUID.Random(), UUID.Random(), socket, false);
                m_clients.Add(agent.ID, remoteEndPoint, agent);

                // there are some fields in the header that we must extract the values of
                string requestString = Encoding.UTF8.GetString(byteRequest, 0, byteRequest.GetLength(0));
                int    originIndex   = requestString.IndexOf("Origin: ");
                if (originIndex > 0)
                {
                    // if the client specified an origin, we must echo it back in the response
                    originIndex += 8;
                    int originEnd = requestString.IndexOf('\r', originIndex);
                    if (originEnd > 0)
                    {
                        m_webSocketOrigin = requestString.Substring(originIndex, originEnd - originIndex);
                    }
                }

                // This is an initial handshake
                // Process the header and send the response
                byte[] response = BuildHandshake(byteRequest);
                SendMessageFinal(socket, response);

                // tell those who care that we are connected
                WebSocketClientConnectedEventHandler handler = Connected;
                if (handler != null)
                {
                    handler(agent);
                }

                return(null);
            }

            // It is not the initial handshake so extract data from the header
            // and find the application data therein.
            int start = args.Offset;
            int end   = start + args.BytesTransferred;

            if (args.Buffer[start] == 0 && args.Buffer[end - 1] == 0xff)
            {
                // we know about the spec rev0 character padding
                string dataString = Encoding.UTF8.GetString(args.Buffer, start + 1, end - start - 2);
                return(dataString);
            }
            else
            {
                m_log.Warn("Received message not conforming to rev 00 of the WebSocket specification");
            }
            return(null);
        }
示例#3
0
        private void DataReceivedHandler(WSAgent agent, string data)
        {
            m_log.Debug("Agent from " + agent.Socket.RemoteEndPoint + " sent message \"" + data + "\"");

            OSDMap map = null;

            try { map = OSDParser.DeserializeJson(data) as OSDMap; }
            catch (Exception ex)
            {
                m_log.Error("Failed to deserialize message: " + ex.Message);
            }

            if (map != null)
            {
                string messageType = map["message"].AsString();
                // TODO: Stuff incoming messages in a blocking queue instead of
                // directly firing the handler. Otherwise, our semaphore will
                // start blocking IOCP threads
                MessageEvents.BeginRaiseEvent(map, agent);
            }
        }
示例#4
0
        /// <summary>
        /// Fire the events registered for this message type asynchronously
        /// </summary>
        /// <param name="incomingMessage">The incoming message</param>
        internal void BeginRaiseEvent(OSDMap incomingMessage, WSAgent agent)
        {
            MessageCallback callback;

            if (m_eventTable.TryGetValue(incomingMessage["Type"].AsString(), out callback) && callback != null)
            {
                while (!m_eventPool.WaitOne(Simian.LONG_SLEEP_INTERVAL))
                {
                    m_scheduler.ThreadKeepAlive();
                }

                MessageCallbackWrapper wrapper = new MessageCallbackWrapper {
                    Callback = callback, Message = incomingMessage, Agent = agent
                };
                m_scheduler.FireAndForget(MessageDelegate, wrapper);
            }
            else
            {
                m_log.Debug("No handler registered for message type \"" + incomingMessage["Type"].AsString() + "\"");
            }
        }
示例#5
0
 private void DisconnectedHandler(WSAgent agent)
 {
     m_log.Debug("Agent disconnected from " + agent.Socket.RemoteEndPoint);
 }
示例#6
0
 public void SendMessage(WSAgent agent, OSDMap message, ThrottleCategory category)
 {
     Server.SendMessage(agent, message, category);
 }
示例#7
0
        /// <summary>
        /// The WebSockets spec has been evolving. This routine processes data framing
        /// for verions 03 of the spec.
        /// </summary>
        /// <param name="agent"></param>
        /// <param name="socket"></param>
        /// <param name="remoteEndPoint"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        private string HandleWebSocketReceive_03(WSAgent agent, Socket socket, IPEndPoint remoteEndPoint, SocketAsyncEventArgs args)
        {
            if (agent == null)
            {
                // m_log.Debug("Sending handshake response to " + remoteEndPoint);
                byte[] byteRequest = new byte[args.BytesTransferred];
                Buffer.BlockCopy(args.Buffer, args.Offset, byteRequest, 0, args.BytesTransferred);

                // create the controlling agent for this new stream
                agent = new WSAgent(m_server, m_throttle, m_throttleRates, UUID.Random(), UUID.Random(), socket, false);
                m_clients.Add(agent.ID, remoteEndPoint, agent);

                // there are some fields in the header that we must extract the values of
                string requestString = Encoding.UTF8.GetString(byteRequest, 0, byteRequest.GetLength(0));
                int    originIndex   = requestString.IndexOf("Origin: ");
                if (originIndex > 0)
                {
                    // if the client specified an origin, we must echo it back in the response
                    originIndex += 8;
                    int originEnd = requestString.IndexOf('\r', originIndex);
                    if (originEnd > 0)
                    {
                        m_webSocketOrigin = requestString.Substring(originIndex, originEnd - originIndex);
                    }
                }

                // This is an initial handshake
                // Process the header and send the response
                byte[] response = BuildHandshake(byteRequest);
                SendMessageFinal(socket, response);

                // tell those who care that we are connected
                WebSocketClientConnectedEventHandler handler = Connected;
                if (handler != null)
                {
                    handler(agent);
                }

                return(null);
            }

            // It is not the initial handshake so extract data from the header
            // and find the application data therein.
            int start = args.Offset;
            int end   = start + args.BytesTransferred;

            bool headerMore = false;
            int  headerOp   = 0;
            int  headerLen  = 0;

            try {
                headerMore = (args.Buffer[start] & 0x80) != 0;
                headerOp   = args.Buffer[start] & 0x0f;
                headerLen  = args.Buffer[start + 1] & 0x7f;
                if (headerLen == 0x7e)
                {
                    headerLen = (args.Buffer[start + 2] << 8) + args.Buffer[start + 3];
                    start    += 2;
                }
                else
                {
                    if (headerLen == 0x7f)
                    {
                        headerLen = args.Buffer[start + 2] << 24
                                    + args.Buffer[start + 3] << 16
                                    + args.Buffer[start + 4] << 8
                                    + args.Buffer[start + 5];
                        start += 4;
                    }
                }
                start += 2;
            }
            catch (Exception e) {
                // failure decoding the header (probably short)
                m_log.Warn("HandleWebSocketReceive: Failure parsing message header: " + e.ToString());
                return(null);
            }
            if ((end - start) < headerLen)
            {
                // didn't receive enough data
                m_log.Warn("HandleWebSocketReceive: received less data than specified in length. Ignoring.");
                return(null);
            }

            // Opcode of '1' says 'close'
            if (headerOp == 1)
            {
                m_log.Warn("HandleWebSocketReceive: polite request to close connection");
                // TODO:
                return(null);
            }

            // Opcode of '2' says 'ping'
            if (headerOp == 2)
            {
                byte[] pingResponse = GeneratePingResponse();
                SendMessageFinal(socket, pingResponse);
                // The standard is undecided on whether a control message can also
                // include data. Here we presume not.
                return(null);
            }
            // TODO: someday do our own pings so we'll need to process pongs

            // if specified, remember the form of the data being received
            if (headerOp == 4)
            {
                agent.ReadingBinary = false;
            }
            if (headerOp == 5)
            {
                agent.ReadingBinary = true;
            }

            if (!agent.ReadingData)
            {
                // not yet reading data so initialize new buffers
                agent.ReadingData = true;
                agent.DataString  = new StringBuilder();
                agent.DataBinary  = null;
            }

            if (agent.ReadingBinary)
            {
                // If binary, build up a buffer of the binary data
                int doffset = 0;
                if (agent.DataBinary == null)
                {
                    agent.DataBinary = new byte[headerLen];
                }
                else
                {
                    byte[] temp = agent.DataBinary;
                    doffset          = temp.Length;
                    agent.DataBinary = new byte[doffset + headerLen];
                    Buffer.BlockCopy(temp, 0, agent.DataBinary, 0, doffset);
                }
                Buffer.BlockCopy(args.Buffer, start, agent.DataBinary, doffset, headerLen);
            }
            else
            {
                // if just text, get the UTF8 characters into our growing string
                agent.DataString.Append(Encoding.UTF8.GetString(args.Buffer, start, headerLen));
            }

            if (!headerMore)
            {
                // end of any fragmentation. no longer reading data
                agent.ReadingData = false;
                return(agent.DataString.ToString());
                // Note the race condition here for the binary data.
                // Binary is not handled correctly as it can be immediately overwritten
                // by the next message.
            }
            // if this is part of a fragmented message, don't return any data this time
            return(null);
        }
示例#8
0
 private void SendMessageData(WSAgent agent, byte[] data, ThrottleCategory category)
 {
     // TODO: Throttling
     SendMessageFinal(agent.Socket, data);
 }
示例#9
0
 private void SendMessageData(WSAgent agent, byte[] data, ThrottleCategory category)
 {
     // TODO: Throttling
     SendMessageFinal(agent.Socket, data);
 }
示例#10
0
        private string HandleWebSocketReceive(WSAgent agent, Socket socket, IPEndPoint remoteEndPoint, SocketAsyncEventArgs args)
        {
            if (agent == null)
            {
                //m_log.Debug("Sending handshake response to " + s.RemoteEndPoint);
                //string request = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);

                agent = new WSAgent(m_server, m_throttle, m_throttleRates, UUID.Random(), UUID.Random(), socket, false);
                m_clients.Add(agent.ID, remoteEndPoint, agent);

                // This is an initial handshake
                byte[] response = BuildHandshake();
                SendMessageFinal(socket, response);

                WebSocketClientConnectedEventHandler handler = Connected;
                if (handler != null)
                    handler(agent);

                return null;
            }

            int start = args.Offset;
            int end = start + args.BytesTransferred;

            // If we are not already reading something, look for the start byte 0x00
            if (!agent.ReadingData)
            {
                for (start = 0; start < end; start++)
                {
                    if (args.Buffer[start] == 0x00)
                    {
                        agent.ReadingData = true; // We found the start byte and can now start reading
                        agent.DataString = new StringBuilder();
                        start++; // Don't include the start byte in the string
                        break;
                    }
                }
            }

            if (agent.ReadingData)
            {
                bool endIsInThisBuffer = false;

                // Look for the end byte 0xFF
                for (int i = start; i < end; i++)
                {
                    if (args.Buffer[i] == 0xFF)
                    {
                        // We found the ending byte
                        endIsInThisBuffer = true;
                        break;
                    }
                }

                // Append this data into the string builder
                agent.DataString.Append(Encoding.UTF8.GetString(args.Buffer, start, end - start));

                // The end is in this buffer, which means we can construct a message
                if (endIsInThisBuffer)
                {
                    // We are no longer reading data
                    agent.ReadingData = false;
                    string data = agent.DataString.ToString();
                    agent.DataString = null;

                    return data;
                }
            }

            return null;
        }
示例#11
0
        public void SendMessage(WSAgent agent, OSDMap message, ThrottleCategory category)
        {
            byte[] messageData = Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(message));
            byte[] data = new byte[messageData.Length + 2];

            // Start with 0x00
            data[0] = 0x00;
            // Then the string
            Buffer.BlockCopy(messageData, 0, data, 1, messageData.Length);
            // End with 0xFF
            data[data.Length - 1] = 0xFF;

            SendMessageData(agent, data, category);
        }
示例#12
0
        /// <summary>
        /// Fire the events registered for this message type asynchronously
        /// </summary>
        /// <param name="incomingMessage">The incoming message</param>
        internal void BeginRaiseEvent(OSDMap incomingMessage, WSAgent agent)
        {
            MessageCallback callback;

            if (m_eventTable.TryGetValue(incomingMessage["Type"].AsString(), out callback) && callback != null)
            {
                while (!m_eventPool.WaitOne(Simian.LONG_SLEEP_INTERVAL))
                    m_scheduler.ThreadKeepAlive();

                MessageCallbackWrapper wrapper = new MessageCallbackWrapper { Callback = callback, Message = incomingMessage, Agent = agent };
                m_scheduler.FireAndForget(MessageDelegate, wrapper);
            }
            else
            {
                m_log.Debug("No handler registered for message type \"" + incomingMessage["Type"].AsString() + "\"");
            }
        }
示例#13
0
 public void SendMessage(WSAgent agent, OSDMap message, ThrottleCategory category)
 {
     Server.SendMessage(agent, message, category);
 }
示例#14
0
 private void DisconnectedHandler(WSAgent agent)
 {
     m_log.Debug("Agent disconnected from " + agent.Socket.RemoteEndPoint);
 }
示例#15
0
        private void DataReceivedHandler(WSAgent agent, string data)
        {
            m_log.Debug("Agent from " + agent.Socket.RemoteEndPoint + " sent message \"" + data + "\"");

            OSDMap map = null;
            try { map = OSDParser.DeserializeJson(data) as OSDMap; }
            catch (Exception ex)
            {
                m_log.Error("Failed to deserialize message: " + ex.Message);
            }

            if (map != null)
            {
                string messageType = map["message"].AsString();
                // TODO: Stuff incoming messages in a blocking queue instead of
                // directly firing the handler. Otherwise, our semaphore will
                // start blocking IOCP threads
                MessageEvents.BeginRaiseEvent(map, agent);
            }
        }