Ejemplo n.º 1
0
        /// <summary>
        /// Handles the <see cref="AsyncSocket.DidAccept"/> event.
        /// </summary>
        /// <param name="sender">The listening <see cref="AsyncSocket"/></param>
        /// <param name="newSocket">The new <see cref="AsyncSocket"/> that was accepted</param>
        private void listenSocket_DidAccept(AsyncSocket sender, AsyncSocket newSocket)
        {
            LogInfo("Accepted client {0}:{1}", newSocket.RemoteAddress, newSocket.RemotePort);

            // check origin
            bool isLocal = IPAddress.IsLoopback(newSocket.RemoteAddress);
            bool isLAN = Growl.CoreLibrary.IPUtilities.IsInSameSubnet(newSocket.LocalAddress, newSocket.RemoteAddress);
            if (!this.allowNetworkNotifications && !isLocal)
            {
                // remote connections not allowed - Should we return a GNTP error response? i think this is better (no reply at all)
                LogInfo("Blocked network request from '{0}'", newSocket.RemoteAddress);
                newSocket.Close();
                return;
            }

            bool passwordRequired = true;
            if (isLocal && !this.RequireLocalPassword) passwordRequired = false;
            else if (isLAN && !this.RequireLANPassword) passwordRequired = false;

            // SUPER IMPORTANT
            newSocket.AllowMultithreadedCallbacks = true;

            MessageHandler mh = new MessageHandler(this.serverName, this.passwordManager, passwordRequired, this.logFolder, this.loggingEnabled, this.allowNetworkNotifications, this.allowWebNotifications, this.allowSubscriptions);
            newSocket.DidClose += new AsyncSocket.SocketDidClose(newSocket_DidClose);
            mh.MessageParsed += new MessageHandler.MessageHandlerMessageParsedEventHandler(mh_MessageParsed);
            mh.Error += new MessageHandler.MessageHandlerErrorEventHandler(mh_Error);
            mh.SocketUsageComplete += new MessageHandler.MessageHandlerSocketUsageCompleteEventHandler(mh_SocketUsageComplete);

            // lock here since in very rare cases, we can get flooded with so many incoming sockets that
            // the Add() throws an IndexOutOfRange exception (only ever happened when running GrowlHammer with loads of
            // simultaneous connections)
            lock (syncLock)
            {
                connectedSockets.Add(new ConnectedSocket(newSocket));
                connectedHandlers.Add(newSocket, mh);
            }

            mh.InitialRead(newSocket);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Handles the socket's DidRead event.
        /// </summary>
        /// <param name="socket">The <see cref="AsyncSocket"/></param>
        /// <param name="readBytes">Array of <see cref="byte"/>s that were read</param>
        /// <param name="tag">The tag identifying the read operation</param>
        protected override void SocketDidRead(AsyncSocket socket, byte[] readBytes, long tag)
        {
            try
            {
                int numberOfBytesToReadNext = 0;
                long nextTag = 0;

                if (tag == CONNECTION_ESTABLISHED_TAG)
                {
                    // wait for a frame and read the first two bytes (containing the FIN, opcode, masking info, and payload length)
                    this.Socket.Read(2, TIMEOUT_UNLIMITED, BEGIN_FRAMING_TAG);
                }

                else if (tag == BEGIN_FRAMING_TAG)
                {
                    // reset this
                    this.AlreadyReceivedData.Remove(0, this.AlreadyReceivedData.Length);
                    this.ParserTag = 1; //TODO:

                    byte bFrameControl = readBytes[0];
                    byte bDataControl = readBytes[1];

                    bool end = (bFrameControl & BYTE_FIN_FINAL) == BYTE_FIN_FINAL;
                    // TODO: handle fragments

                    if ((bFrameControl & BYTE_OPCODE_PONG) == BYTE_OPCODE_PONG)
                    {
                        // unsolicited Pong - we dont need to do anything
                    }
                    else if ((bFrameControl & BYTE_OPCODE_PING) == BYTE_OPCODE_PING)
                    {
                        // need to response with Pong
                        // TODO: handle this case
                    }
                    else if ((bFrameControl & BYTE_OPCODE_CLOSE) == BYTE_OPCODE_CLOSE)
                    {
                        // we dont really care about this
                    }
                    else if ((bFrameControl & BYTE_OPCODE_BINARY) == BYTE_OPCODE_BINARY)
                    {
                        // we dont really care about this
                    }
                    else if ((bFrameControl & BYTE_OPCODE_TEXT) == BYTE_OPCODE_TEXT)
                    {
                        // we dont really care about this
                    }
                    else if ((bFrameControl & BYTE_OPCODE_CONTINUATION) == BYTE_OPCODE_CONTINUATION)
                    {
                        // TODO: handle fragments
                    }

                    masked = (bDataControl & BYTE_MASKED_YES) == BYTE_MASKED_YES;
                    int length = (int)(bDataControl & ~BYTE_MASKED_YES);
                    if ((bDataControl & BYTE_LENGTH_16) == BYTE_LENGTH_16)
                    {
                        // read next two bytes for length
                        numberOfBytesToReadNext = 2;
                        nextTag = PAYLOAD_LENGTH_TAG;
                    }
                    else if ((bDataControl & BYTE_LENGTH_64) == BYTE_LENGTH_64)
                    {
                        // read next 8 bytes for length
                        numberOfBytesToReadNext = 8;
                        nextTag = PAYLOAD_LENGTH_TAG;
                    }
                    else
                    {
                        if (masked)
                        {
                            // read 4 byte masking key
                            numberOfBytesToReadNext = 4;
                            nextTag = MASKING_KEY_TAG;
                            payloadRemainingLength = length;
                        }
                        else
                        {
                            numberOfBytesToReadNext = length;
                            nextTag = GNTP_DATA_TAG;
                            payloadRemainingLength = 0;

                            // handle zero-length payload
                            if (numberOfBytesToReadNext == 0)
                            {
                                numberOfBytesToReadNext = 2;
                                nextTag = BEGIN_FRAMING_TAG;
                            }
                        }
                    }

                    // read next chunk of data
                    this.Socket.Read(numberOfBytesToReadNext, TIMEOUT_FRAME, nextTag);
                }
                else if (tag == PAYLOAD_LENGTH_TAG)
                {
                    long length = 0;
                    if (readBytes.Length == 2)
                    {
                        short s = BitConverter.ToInt16(readBytes, 0);
                        s = System.Net.IPAddress.NetworkToHostOrder(s);
                        length = s;
                    }
                    else if (readBytes.Length == 8)
                    {
                        long l = BitConverter.ToInt64(readBytes, 0);
                        l = System.Net.IPAddress.NetworkToHostOrder(l);
                        length = l;
                    }

                    if (masked)
                    {
                        // read 4 byte masking key
                        numberOfBytesToReadNext = 4;
                        nextTag = MASKING_KEY_TAG;
                        payloadRemainingLength = length;
                    }
                    else
                    {
                        if (length > int.MaxValue)
                        {
                            numberOfBytesToReadNext = int.MaxValue;
                            payloadRemainingLength = length - numberOfBytesToReadNext;
                        }
                        else
                        {
                            numberOfBytesToReadNext = (int)length;
                            payloadRemainingLength = 0;
                        }
                        nextTag = GNTP_DATA_TAG;

                        // handle zero-length payload
                        if (numberOfBytesToReadNext == 0)
                        {
                            numberOfBytesToReadNext = 2;
                            nextTag = BEGIN_FRAMING_TAG;
                        }
                    }

                    // read next chunk of data
                    this.Socket.Read(numberOfBytesToReadNext, TIMEOUT_FRAME, nextTag);
                }
                else if (tag == MASKING_KEY_TAG)
                {
                    mask = readBytes;

                    if (payloadRemainingLength > int.MaxValue)
                    {
                        numberOfBytesToReadNext = int.MaxValue;
                        payloadRemainingLength = payloadRemainingLength - numberOfBytesToReadNext;
                    }
                    else
                    {
                        numberOfBytesToReadNext = (int)payloadRemainingLength;
                        payloadRemainingLength = 0;
                    }
                    nextTag = GNTP_DATA_TAG;

                    // handle zero-length payload
                    if (numberOfBytesToReadNext == 0)
                    {
                        numberOfBytesToReadNext = 2;
                        nextTag = BEGIN_FRAMING_TAG;
                    }

                    // read next chunk of data
                    this.Socket.Read(numberOfBytesToReadNext, TIMEOUT_FRAME, nextTag);
                }
                else if (tag == GNTP_DATA_TAG)
                {
                    byte[] unmaskedBytes = null;
                    if (masked)
                    {
                        unmaskedBytes = new byte[readBytes.Length];
                        for(int i=0;i<readBytes.Length;i++)
                        {
                            int b = i % 4;
                            byte unmaskedByte = (byte) (readBytes[i] ^ mask[b]);
                            unmaskedBytes[i] = unmaskedByte;
                        }
                    }
                    else
                    {
                        unmaskedBytes = readBytes;
                    }

                    parser.Parse(unmaskedBytes);

                    // normally we would want to kick off another socket.Read() here (looking for the next BEGIN_FRAME_TAG), but we currently only allow one request per socket connection
                }
                else
                {
                    // we can only get here if there was some unaccounted-for data. that is bad, so lets close the socket
                    socket.Close();
                }
            }
            catch (GrowlException gEx)
            {
                OnError(gEx.ErrorCode, gEx.Message, gEx.AdditionalInfo);
            }
            catch (Exception ex)
            {
                OnError(ErrorCode.INVALID_REQUEST, ErrorDescription.MALFORMED_REQUEST, ex.Message);
            }
        }