Example #1
0
        protected override bool OnBeforeSend(Growl.Connector.MessageBuilder mb)

        {
            //from <hostname> by <hostname> [with Growl] [id <identifier>]; <ISO 8601 date>



            foreach (Header header in this.RequestInfo.PreviousReceivedHeaders)

            {
                mb.AddHeader(header);
            }



            string received = String.Format("from {0} by {1}{2}{3}; {4}", this.RequestInfo.ReceivedFrom, this.RequestInfo.ReceivedBy, (this.RequestInfo.ReceivedWith != null ? String.Format(" with {0}", this.RequestInfo.ReceivedWith) : String.Empty), (this.RequestInfo.RequestID != null ? String.Format(" id {0}", this.RequestInfo.RequestID) : String.Empty), this.RequestInfo.TimeReceived.ToString("u"));

            Header receivedHeader = new Header("Received", received);

            mb.AddHeader(receivedHeader);



            return(base.OnBeforeSend(mb));
        }
        /// <summary>
        /// Registers the specified application and notification types and allows for additional request data.
        /// </summary>
        /// <param name="application">The <see cref="Application"/> to register.</param>
        /// <param name="notificationTypes">The <see cref="NotificationType"/>s to register.</param>
        /// <param name="requestData">The <see cref="RequestData"/> containing the additional information.</param>
        /// <param name="state">An optional state object that will be passed into the response events associated with this request</param>
        public virtual void Register(Application application, NotificationType[] notificationTypes, RequestData requestData, object state)
        {
            HeaderCollection appHeaders = application.ToHeaders();
            List<HeaderCollection> notifications = new List<HeaderCollection>();
            foreach (NotificationType notificationType in notificationTypes)
            {
                HeaderCollection notificationHeaders = notificationType.ToHeaders();
                notifications.Add(notificationHeaders);
            }

            MessageBuilder mb = new MessageBuilder(RequestType.REGISTER, this.GetKey());
            foreach(Header header in appHeaders)
            {
                mb.AddHeader(header);
            }
            mb.AddHeader(new Header(Header.NOTIFICATIONS_COUNT, notificationTypes.Length.ToString()));

            // handle any additional request data
            if (requestData != null)
            {
                HeaderCollection requestDataHeaders = requestData.ToHeaders();
                foreach (Header header in requestDataHeaders)
                {
                    mb.AddHeader(header);
                }
            }

            foreach(HeaderCollection headers in notifications)
            {
                MessageSection ms = new MessageSection();
                foreach(Header header in headers)
                {
                    ms.AddHeader(header);
                }
                mb.AddMessageSection(ms);
            }

            Send(mb, OnResponseReceived, false, state);
        }
        /// <summary>
        /// Sends a notification to Growl that specifies callback information and allows for additional request data.
        /// </summary>
        /// <param name="notification">The <see cref="Notification"/> to send.</param>
        /// <param name="callbackContext">The <see cref="CallbackContext"/> containing the callback information.</param>
        /// <param name="requestData">The <see cref="RequestData"/> containing the additional information.</param>
        /// <param name="state">An optional state object that will be passed into the response events associated with this request</param>
        public virtual void Notify(Notification notification, CallbackContext callbackContext, RequestData requestData, object state)
        {
            bool waitForCallback = false;
            HeaderCollection notificationHeaders = notification.ToHeaders();
            MessageBuilder mb = new MessageBuilder(RequestType.NOTIFY, this.GetKey());
            foreach (Header header in notificationHeaders)
            {
                mb.AddHeader(header);
            }

            if (callbackContext != null)
            {
                string url = callbackContext.CallbackUrl;
                if (!String.IsNullOrEmpty(url))
                {
                    mb.AddHeader(new Header(Header.NOTIFICATION_CALLBACK_TARGET, url));
                }
                else
                {
                    mb.AddHeader(new Header(Header.NOTIFICATION_CALLBACK_CONTEXT, callbackContext.Data));
                    mb.AddHeader(new Header(Header.NOTIFICATION_CALLBACK_CONTEXT_TYPE, callbackContext.Type.ToString()));
                    waitForCallback = true;
                }
            }

            // handle any additional request data
            if (requestData != null)
            {
                HeaderCollection requestDataHeaders = requestData.ToHeaders();
                foreach (Header header in requestDataHeaders)
                {
                    mb.AddHeader(header);
                }
            }

            Send(mb, OnResponseReceived, waitForCallback, state);
        }
Example #4
0
 /// <summary>
 /// Adds any application-specific headers to the message
 /// </summary>
 /// <param name="mb">The <see cref="MessageBuilder"/> used to construct the message</param>
 /// <param name="requestData">The <see cref="RequestData"/> that contains the application-specific data</param>
 private void AddRequestData(MessageBuilder mb, RequestData requestData)
 {
     if (requestData != null)
     {
         HeaderCollection headers = requestData.ToHeaders();
         foreach (Header header in headers)
         {
             mb.AddHeader(header);
         }
     }
 }
Example #5
0
        /// <summary>
        /// Writes back the GNTP response to the requesting application
        /// </summary>
        /// <param name="cbInfo">The <see cref="CallbackInfo"/> associated with the response</param>
        /// <param name="response">The <see cref="Response"/> to be written back</param>
        public void WriteResponse(CallbackInfo cbInfo, Response response)
        {
            if (!cbInfo.AlreadyResponded)
            {
                cbInfo.AlreadyResponded = true;
                MessageHandler mh = cbInfo.MessageHandler;
                GNTPRequest request = mh.Request;
                ResponseType responseType = ResponseType.ERROR;
                if (response != null)
                {
                    if (response.IsCallback) responseType = ResponseType.CALLBACK;
                    else if (response.IsOK) responseType = ResponseType.OK;
                }
                else
                {
                    response = new Response(ErrorCode.INTERNAL_SERVER_ERROR, ErrorDescription.INTERNAL_SERVER_ERROR);
                }

                if (cbInfo.AdditionalInfo != null)
                {
                    foreach (KeyValuePair<string, string> item in cbInfo.AdditionalInfo)
                    {
                        response.CustomTextAttributes.Add(item.Key, item.Value);
                    }
                }

                AddServerHeaders(response);
                MessageBuilder mb = new MessageBuilder(responseType);
                HeaderCollection responseHeaders = response.ToHeaders();
                foreach (Header header in responseHeaders)
                {
                    mb.AddHeader(header);
                }
                // return any application-specific data headers that were received
                RequestData rd = RequestData.FromHeaders(request.Headers);
                AddRequestData(mb, rd);

                mh.WriteResponse(mb, true);
            }
         }
Example #6
0
        /// <summary>
        /// Handles the parsed message after it is received
        /// </summary>
        /// <param name="obj">The <see cref="MessageHandler"/> object that parsed the message</param>
        private void HandleParsedMessage(object obj)
        {
            MessageHandler mh = (MessageHandler)obj;
            GNTPRequest request = mh.Request;

            try
            {
                Response response = null;
                switch (request.Directive)
                {
                    case RequestType.REGISTER:
                        Application application = Application.FromHeaders(request.Headers);
                        List<NotificationType> notificationTypes = new List<NotificationType>();
                        for (int i = 0; i < request.NotificationsToBeRegistered.Count; i++)
                        {
                            HeaderCollection headers = request.NotificationsToBeRegistered[i];
                            notificationTypes.Add(NotificationType.FromHeaders(headers));
                        }
                        response = this.OnRegisterReceived(application, notificationTypes, mh.RequestInfo);
                        break;
                    case RequestType.NOTIFY:
                        Notification notification = Notification.FromHeaders(request.Headers);
                        mh.CallbackInfo.NotificationID = notification.ID;
                        response = this.OnNotifyReceived(notification, mh.CallbackInfo, mh.RequestInfo);
                        break;
                    case RequestType.SUBSCRIBE:
                        Subscriber subscriber = Subscriber.FromHeaders(request.Headers);
                        subscriber.IPAddress = mh.Socket.RemoteAddress.ToString();
                        subscriber.Key = new SubscriberKey(request.Key, subscriber.ID, request.Key.HashAlgorithm, request.Key.EncryptionAlgorithm);
                        response = this.OnSubscribeReceived(subscriber, mh.RequestInfo);
                        break;
                }


                ResponseType responseType = ResponseType.ERROR;
                if (response != null && response.IsOK)
                {
                    responseType = ResponseType.OK;
                    response.InResponseTo = request.Directive.ToString();
                }

                // no response
                if (response == null)
                    response = new Response(ErrorCode.INTERNAL_SERVER_ERROR, ErrorDescription.INTERNAL_SERVER_ERROR);

                AddServerHeaders(response);
                MessageBuilder mb = new MessageBuilder(responseType);
                HeaderCollection responseHeaders = response.ToHeaders();
                foreach (Header header in responseHeaders)
                {
                    mb.AddHeader(header);
                }
                // return any application-specific data headers that were received
                RequestData rd = RequestData.FromHeaders(request.Headers);
                AddRequestData(mb, rd);

                bool requestComplete = !mh.CallbackInfo.ShouldKeepConnectionOpen();
                mh.WriteResponse(mb, requestComplete);
            }
            catch (GrowlException gEx)
            {
                mh.WriteError(gEx.ErrorCode, gEx.Message, gEx.AdditionalInfo);
            }
            catch(Exception ex)
            {
                mh.WriteError(ErrorCode.INTERNAL_SERVER_ERROR, ex.Message);
            }
        }
        /// <summary>
        /// Writes data to the specified socket.
        /// </summary>
        /// <param name="socket">The <see cref="AsyncSocket"/> to write the data to</param>
        /// <param name="mb">The <see cref="MessageBuilder"/> containing the data to write</param>
        /// <param name="timeout">The socket write timeout value</param>
        /// <param name="tag">The tag that will identify the write operation (can be referenced in the socket's DidWrite event)</param>
        /// <param name="disconnectAfterWriting">Indicates if the server should disconnect the socket after writing the data</param>
        /// <param name="requestComplete">Indicates if the request is complete once the data is written</param>
        protected virtual void Write(AsyncSocket socket, MessageBuilder mb, int timeout, long tag, bool disconnectAfterWriting, bool requestComplete)
        {
            //Console.WriteLine(alreadyReceived.ToString());

            byte[] bytes = mb.GetBytes();
            mb = null;
            FinalWrite(socket, bytes, timeout, tag, disconnectAfterWriting, requestComplete);
        }
        /// <summary>
        /// Writes an error response back to the original sender.
        /// </summary>
        /// <param name="socket">The <see cref="AsyncSocket"/> used to write the response</param>
        /// <param name="error">The error</param>
        private void WriteError(AsyncSocket socket, Error error)
        {
            if (this.Error != null)
            {
                this.Error(error);
            }

            HeaderCollection headers = error.ToHeaders();
            MessageBuilder mb = new MessageBuilder(ResponseType.ERROR);
            foreach (Header header in headers)
            {
                mb.AddHeader(header);
            }

            Write(socket, mb, TIMEOUT_ERROR_RESPONSE, RESPONSE_ERROR_TAG, true, true);
        }
 /// <summary>
 /// Writes the response back to the original sender.
 /// </summary>
 /// <param name="mb">The <see cref="MessageBuilder"/> containing the data to write</param>
 /// <param name="requestComplete">Indicates if this completes the transaction (all responses and callbacks have been written)</param>
 public void WriteResponse(MessageBuilder mb, bool requestComplete)
 {
     Write(socket, mb, TIMEOUT_ERROR_RESPONSE, RESPONSE_SUCCESS_TAG, false, requestComplete);
 }
        /// <summary>
        /// Renews the callers subscription to the server to avoid being timed-out.
        /// </summary>
        /// <remarks>
        /// By default, the renewal interval is equal to (Server TTL - 30 seconds).
        /// </remarks>
        private void RenewSubscription()
        {
            HeaderCollection headers = this.subscriber.ToHeaders();

            MessageBuilder mb = new MessageBuilder(RequestType.SUBSCRIBE, this.GetKey());
            foreach (Header header in headers)
            {
                mb.AddHeader(header);
            }

            Send(mb, OnResponseReceived, false, null);
        }
Example #11
0
        /// <summary>
        /// Sends the request and handles any responses
        /// </summary>
        /// <param name="mb">The <see cref="MessageBuilder"/> used to contruct the request</param>
        /// <param name="del">The <see cref="ResponseReceivedEventHandler"/> for handling the response</param>
        /// <param name="waitForCallback"><c>true</c> to wait for a callback;<c>false</c> otherwise</param>
        /// <param name="state">An optional state object that will be passed into the response events associated with this request</param>
        protected void Send(MessageBuilder mb, ResponseReceivedEventHandler del, bool waitForCallback, object state)
        {
            // do some of this *before* we spin up a new thread so we can just throw an exception if the error occurs
            // *before* we even send the request (like when generating the message bytes)
            bool doSend = this.OnBeforeSend(mb);
            if (doSend)
            {
                byte[] bytes = mb.GetBytes();
                mb = null;

                // start a new thread for the network connection stuff
                ConnectionState cs = new ConnectionState(bytes, del, waitForCallback, state);
                ParameterizedThreadStart pts = new ParameterizedThreadStart(SendAsync);
                Thread t = new Thread(pts);
                t.Start(cs);
            }
        }
Example #12
0
 /// <summary>
 /// Fired immediately before the message is constructed and set.
 /// Allows adding any additional headers to the outgoing request or
 /// to cancel the request.
 /// </summary>
 /// <param name="mb">The <see cref="MessageBuilder"/> used to construct the message</param>
 /// <returns>
 /// <c>true</c> to allow the request to be sent;
 /// <c>false</c> to cancel the request
 /// </returns>
 protected virtual bool OnBeforeSend(MessageBuilder mb)
 {
     return true;
 }