/// <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> /// Converts the Response to a list of headers /// </summary> /// <returns><see cref="HeaderCollection"/></returns> public override HeaderCollection ToHeaders() { HeaderCollection headers = new HeaderCollection(); if (this.IsOK && !this.IsCallback) { Header hResponseAction = new Header(Header.RESPONSE_ACTION, this.InResponseTo); headers.AddHeader(hResponseAction); } if (this.IsError) { Header hErrorCode = new Header(Header.ERROR_CODE, this.ErrorCode.ToString()); Header hDescription = new Header(Header.ERROR_DESCRIPTION, this.ErrorDescription); headers.AddHeader(hErrorCode); headers.AddHeader(hDescription); } if (this.IsCallback) { Header hNotificationID = new Header(Header.NOTIFICATION_ID, this.callbackData.NotificationID); Header hCallbackResult = new Header(Header.NOTIFICATION_CALLBACK_RESULT, Enum.GetName(typeof(CallbackResult), this.callbackData.Result)); Header hCallbackContext = new Header(Header.NOTIFICATION_CALLBACK_CONTEXT, this.callbackData.Data); Header hCallbackContextType = new Header(Header.NOTIFICATION_CALLBACK_CONTEXT_TYPE, this.callbackData.Type); //Header hCallbackTimestamp = new Header(Header.NOTIFICATION_CALLBACK_TIMESTAMP, DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ")); Header hCallbackTimestamp = new Header(Header.NOTIFICATION_CALLBACK_TIMESTAMP, DateTime.UtcNow.ToString("u")); headers.AddHeader(hNotificationID); headers.AddHeader(hCallbackResult); headers.AddHeader(hCallbackContext); headers.AddHeader(hCallbackContextType); headers.AddHeader(hCallbackTimestamp); } this.AddInheritedAttributesToHeaders(headers); return(headers); }
/// <summary> /// Adds any inherited headers to the end of the header collection /// </summary> /// <param name="headers">The <see cref="HeaderCollection"/> to append the headers to</param> /// <remarks> /// This method should only be called from a derived class' .ToHeaders() method. /// It takes care of adding the Origin-* headers as well as any X-* custom headers. /// /// This method is the same as calling both AddCommonAttributesToHeaders and /// AddCustomAttributesToHeaders. /// </remarks> protected void AddInheritedAttributesToHeaders(HeaderCollection headers) { AddCommonAttributesToHeaders(headers); AddCustomAttributesToHeaders(headers); }
/// <summary> /// Sets the object's base class properties from the supplied header list /// </summary> /// <param name="obj">The <see cref="ExtensibleObject"/> being rehydrated</param> /// <param name="headers">The <see cref="HeaderCollection"/> containing the parsed header values</param> /// <remarks> /// This method should only be called from a derived class' .FromHeaders() method. /// It takes care of setting the Origin-* related properties, as well as any custom attributes. /// /// This method is the same as calling both SetCommonAttributesFromHeaders and /// SetCustomAttributesFromHeaders. /// </remarks> protected static void SetInhertiedAttributesFromHeaders(ExtensibleObject obj, HeaderCollection headers) { SetCommonAttributesFromHeaders(obj, headers); SetCustomAttributesFromHeaders(obj, headers); }
/// <summary> /// Parses a response message and returns the corresponding <see cref="Response"/> object /// </summary> /// <param name="message">The entire GNTP response message</param> /// <param name="headers">The <see cref="HeaderCollection"/> of parsed header values</param> /// <returns><see cref="Response"/></returns> private Response Parse(string message, out HeaderCollection headers) { ResponseType responseType = ResponseType.ERROR; Response response = null; headers = new HeaderCollection(); byte[] bytes = System.Text.Encoding.UTF8.GetBytes(message); System.IO.MemoryStream stream = new System.IO.MemoryStream(bytes); using (stream) { GNTPStreamReader reader = new GNTPStreamReader(stream); using (reader) { bool isError = false; bool isFirstLine = true; while (!reader.EndOfStream) { string line = reader.ReadLine(); if (isFirstLine) { Match match = ParseGNTPHeaderLine(line); if (match.Success) { this.version = match.Groups["Version"].Value; this.directive = match.Groups["Directive"].Value; if (this.directive.StartsWith("-", StringComparison.InvariantCulture)) { this.directive = this.directive.Remove(0, 1); } if (version == GNTP_SUPPORTED_VERSION) { if (Enum.IsDefined(typeof(ResponseType), this.directive)) { responseType = (ResponseType)Enum.Parse(typeof(ResponseType), this.directive, false); response = new Response(); if (responseType == ResponseType.ERROR) { isError = true; } isFirstLine = false; } else { // invalid directive response = new Response(ErrorCode.INVALID_REQUEST, "Unrecognized response type"); break; } } else { // invalid version response = new Response(ErrorCode.UNKNOWN_PROTOCOL_VERSION, "Unsupported version"); break; } } else { // invalid message header response = new Response(ErrorCode.UNKNOWN_PROTOCOL, "Unrecognized response"); break; } } else { Header header = Header.ParseHeader(line); headers.AddHeader(header); } } if (response != null) { if (isError) { int errorCode = headers.GetHeaderIntValue(Header.ERROR_CODE, false); string errorDescription = headers.GetHeaderStringValue(Header.ERROR_DESCRIPTION, false); if (errorCode > 0 && errorDescription != null) { response = new Response(errorCode, errorDescription); } else { response = new Response(ErrorCode.INTERNAL_SERVER_ERROR, ErrorDescription.INTERNAL_SERVER_ERROR); } } else { string inResponseTo = headers.GetHeaderStringValue(Header.RESPONSE_ACTION, false); response.InResponseTo = inResponseTo; } response.SetAttributesFromHeaders(headers, (responseType == ResponseType.CALLBACK)); } else { // if we got here, that is bad. response = new Response(ErrorCode.INTERNAL_SERVER_ERROR, ErrorDescription.INTERNAL_SERVER_ERROR); } } } return(response); }