/*
* Copyright (C) 2012 Doubango Telecom <http://www.doubango.org>
* License: BSD
* This file is part of Open Source sipML5 solution <http://www.sipml5.org>
*/
// Check if we have ",CRLF" ==> See WWW-Authenticate header
// As :>CRLF is preceded by any+ ==> p will be at least (start + 1)
// p point to CR
// #define prev_not_comma(p) !(p && p[-1] == ',')
function prev_not_comma(o_ragel_state, i_p){
	return (o_ragel_state.i_pe <= i_p) || (o_ragel_state.o_data[i_p - 1] != ',');
}

%%{
	machine tsip_machine_parser_headers;


	# /*== Accept: ==*/
	action parse_header_Accept
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Accept-Contact: ==*/
	action parse_header_Accept_Contact 
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Accept-Encoding: ==*/
	action parse_header_Accept_Encoding
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Accept-Language: ==*/
	action parse_header_Accept_Language
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Accept-Resource-Priority : ==*/
	action parse_header_Accept_Resource_Priority 
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Alert-Info: ==*/
	action parse_header_Alert_Info
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Allow: ==*/
	action parse_header_Allow
	{
		var header = tsip_header_Allow.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Allow-Events: ==*/
	action parse_header_Allow_Events
	{
		var header = tsip_header_Allow_Events.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Authentication-Info: ==*/
	action parse_header_Authentication_Info 
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Authorization: ==*/
	action parse_header_Authorization 
	{
	    var header = tsip_header_Authorization.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Call-ID: ==*/
	action parse_header_Call_ID
	{
	    var header = tsip_header_Call_ID.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Call-Info: ==*/
	action parse_header_Call_Info
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Contact: ==*/
	action parse_header_Contact 
	{
	    var headers = tsip_header_Contact.prototype.Parse(s_str);
	    for(var i = 0; i < headers.length; ++i){
		    o_msg.add_header(headers[i]);
		}
	}

	# /*== Content-Disposition: ==*/
	action parse_header_Content_Disposition
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Content-Encoding: ==*/
	action parse_header_Content_Encoding
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Content-Language: ==*/
	action parse_header_Content_Language
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Content-Length: ==*/
	action parse_header_Content_Length
	{
	    var header = tsip_header_Content_Length.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Content-Type: ==*/
	action parse_header_Content_Type
	{
	    var header = tsip_header_Content_Type.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== CSeq: ==*/
	action parse_header_CSeq
	{
	    var header = tsip_header_CSeq.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Date: ==*/
	action parse_header_Date
	{
	    var header = tsip_header_Date.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Error-Info: ==*/
	action parse_header_Error_Info
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Event: ==*/
	action parse_header_Event
	{
	    var header = tsip_header_Event.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Expires: ==*/
	action parse_header_Expires
	{
	    var header = tsip_header_Expires.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== From: ==*/
	action parse_header_From
	{
	    var header = tsip_header_From.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== History-Info: ==*/
	action parse_header_History_Info 
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Identity: ==*/
	action parse_header_Identity
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Identity-Info: ==*/
	action parse_header_Identity_Info
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== In_Reply-To: ==*/
	action parse_header_In_Reply_To
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Join: ==*/
	action parse_header_Join
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Max-Forwards: ==*/
	action parse_header_Max_Forwards
	{
	    var header = tsip_header_Max_Forwards.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== MIME-Version: ==*/
	action parse_header_MIME_Version
	{
	    var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Min-Expires: ==*/
	action parse_header_Min_Expires
	{
	    var header = tsip_header_Min_Expires.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Min-SE: ==*/
	action parse_header_Min_SE
	{
	    var header = tsip_header_Min_SE.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Organization: ==*/
	action parse_header_Organization 
	{
		var header = tsip_header_Organization.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P-Access-Network-Info: ==*/
	action parse_header_P_Access_Network_Info 
	{
	    var header = tsip_header_P_Access_Network_Info.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P-Answer-State: ==*/
	action parse_header_P_Answer_State
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P-Asserted-Identity: ==*/
	action parse_header_P_Asserted_Identity 
	{
	    var headers = tsip_header_P_Asserted_Identity.prototype.Parse(s_str);
		if(headers){
			for(var i = 0; i < headers.length; ++i){
				o_msg.add_header(headers[i]);
			}
		}
	}

	# /*== P-Associated-URI: ==*/
	action parse_header_P_Associated_URI
	{
	    var headers = tsip_header_P_Associated_URI.prototype.Parse(s_str);
		if(headers){
			for(var i = 0; i < headers.length; ++i){
				o_msg.add_header(headers[i]);
			}
		}
	}

	# /*== P-Called-Party-ID: ==*/
	action parse_header_P_Called_Party_ID
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P-Charging-Function-Addresses : ==*/
	action parse_header_P_Charging_Function_Addresses 
	{
		var header = tsip_header_P_Charging_Function_Addresses.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P_Charging_Vector: ==*/
	action parse_header_P_Charging_Vector
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P-DCS-Billing-Info: ==*/
	action parse_header_P_DCS_Billing_Info
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P-DCS-LAES: ==*/
	action parse_header_P_DCS_LAES
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P-DCS-OSPS: ==*/
	action parse_header_P_DCS_OSPS
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P-DCS-Redirect: ==*/
	action parse_header_P_DCS_Redirect
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P-DCS-Trace-Party-ID: ==*/
	action parse_header_P_DCS_Trace_Party_ID
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P-Early-Media: ==*/
	action parse_header_P_Early_Media
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P-Media-Authorization: ==*/
	action parse_header_P_Media_Authorization
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P-Preferred-Identity: ==*/
	action parse_header_P_Preferred_Identity
	{
		var headers = tsip_header_P_Preferred_Identity.prototype.Parse(s_str);
		if(headers){
			for(var i = 0; i < headers.length; ++i){
				o_msg.add_header(headers[i]);
			}
		}
	}

	# /*== P-Profile-Key: ==*/
	action parse_header_P_Profile_Key
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P-User-Database: ==*/
	action parse_header_P_User_Database
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== P-Visited-Network-ID: ==*/
	action parse_header_P_Visited_Network_ID
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Path: ==*/
	action parse_header_Path
	{
	    var headers = tsip_header_Path.prototype.Parse(s_str);
		if(headers){
			for(var i = 0; i < headers.length; ++i){
				o_msg.add_header(headers[i]);
			}
		}
	}

	# /* == Priority: ==*/
	action parse_header_Priority
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Privacy: ==*/
	action parse_header_Privacy
	{
	    var header = tsip_header_Privacy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Authenticate: ==*/
	action parse_header_Proxy_Authenticate
	{
	    var header = tsip_header_WWW_Authenticate.prototype.Parse(s_str);
		o_msg.add_headers(header);
		p = (pe - 1); // hack: Ragel "when" clause not supported in javascript
	}

	# /*== Proxy-Authorization: ==*/
	action parse_header_Proxy_Authorization
	{
	    var header = tsip_header_Authorization.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Proxy-Require: ==*/
	action parse_header_Proxy_Require 
	{
	    var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== RAck: ==*/
	action parse_header_RAck
	{
	    var header = tsip_header_RAck.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Reason: ==*/
	action parse_header_Reason 
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Record-Route: ==*/
	action parse_header_Record_Route 
	{
	    var headers = tsip_header_Record_Route.prototype.Parse(s_str);
		if(headers){
			for(var i = 0; i < headers.length; ++i){
				o_msg.add_header(headers[i]);
			}
		}
	}

	# /*== Refer-Sub: ==*/
	action parse_header_Refer_Sub 
	{
	    var header = tsip_header_Refer_Sub.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Refer-To: ==*/
	action parse_header_Refer_To
	{
	    var header = tsip_header_Refer_To.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Referred-By: ==*/
	action parse_header_Referred_By
	{
	    var header = tsip_header_Referred_By.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Reject-Contact: ==*/
	action parse_header_Reject_Contact
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Replaces: ==*/
	action parse_header_Replaces
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Reply-To: ==*/
	action parse_header_Reply_To
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Request-Disposition: ==*/
	action parse_header_Request_Disposition
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Require: ==*/
	action parse_header_Require
	{
	    var header = tsip_header_Require.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Resource-Priority: ==*/
	action parse_header_Resource_Priority
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Retry-After: ==*/
	action parse_header_Retry_After
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Route: ==*/
	action parse_header_Route
	{
	    var headers = tsip_header_Route.prototype.Parse(s_str);
		if(headers){
			for(var i = 0; i < headers.length; ++i){
				o_msg.add_header(headers[i]);
			}
		}
	}

	# /*== RSeq: ==*/
	action parse_header_RSeq
	{
	    var header = tsip_header_RSeq.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Security_Client: ==*/
	action parse_header_Security_Client
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Security-Server: ==*/
	action parse_header_Security_Server
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Security-Verify: ==*/
	action parse_header_Security_Verify
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Server: ==*/
	action parse_header_Server
	{
	    var header = tsip_header_Server.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Service-Route: ==*/
	action parse_header_Service_Route
	{
	    var headers = tsip_header_Service_Route.prototype.Parse(s_str);
		if(headers){
			for(var i = 0; i < headers.length; ++i){
				o_msg.add_header(headers[i]);
			}
		}
	}

	# /*== Session-Expires: ==*/
	action parse_header_Session_Expires
	{
	    var header = tsip_header_Session_Expires.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== SIP-ETag: ==*/
	action parse_header_SIP_ETag
	{
	    var header = tsip_header_SIP_ETag.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== SIP-If-Match: ==*/
	action parse_header_SIP_If_Match
	{
	    var header = tsip_header_SIP_If_Match.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Subject: ==*/
	action parse_header_Subject
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Subscription-State: ==*/
	action parse_header_Subscription_State
	{
	    var header = tsip_header_Subscription_State.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Supported: ==*/
	action parse_header_Supported
	{
	    var header = tsip_header_Supported.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Target-Dialog: ==*/
	action parse_header_Target_Dialog
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Timestamp: ==*/
	action parse_header_Timestamp
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== To: ==*/
	action parse_header_To
	{
	    var header = tsip_header_To.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Unsupported: ==*/
	action parse_header_Unsupported
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== User-Agent: ==*/
	action parse_header_User_Agent
	{
	    var header = tsip_header_User_Agent.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== Via: ==*/
	action parse_header_Via
	{	
	    var headers = tsip_header_Via.prototype.Parse(s_str);
		if(headers){
			for(var i = 0; i < headers.length; ++i){
				o_msg.add_header(headers[i]);
			}
		}
	}

	# /*== Warning: ==*/
	action parse_header_Warning 
	{
	    var header = tsip_header_Warning.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	# /*== WWW-Authenticate: ==*/
	action parse_header_WWW_Authenticate
	{
		var header = tsip_header_WWW_Authenticate.prototype.Parse(s_str);
		o_msg.add_headers(header);
		p = (pe - 1); // hack: Ragel "when" clause not supported in javascript
	}
		
	# /*== extension_header: ==*/
	action parse_header_extension_header
	{
		var header = tsip_header_Dummy.prototype.Parse(s_str);
		o_msg.add_headers(header);
	}

	action prev_not_comma{
		prev_not_comma(o_ragel_state, p)
	}

	# Includes
	include tsip_machine_utils "./tsip_machine_utils.jrl";
	include tsip_machine_header "./tsip_machine_header.jrl";

	# Entry point
	main := HEADER;
}%%

%%write data;

function tsip_header_parse(o_ragel_state, o_msg){
	var cs = 0;
	var p = o_ragel_state.i_tag_start;
	var pe = o_ragel_state.i_tag_end;
	var eof = pe;
	var data = o_ragel_state.o_data;
	var s_str = o_ragel_state.s_data.substring(o_ragel_state.i_tag_start, o_ragel_state.i_tag_start + (o_ragel_state.i_tag_end - o_ragel_state.i_tag_start));
	
	%%write init;
	%%write exec;
	
	if( cs < %%{ write first_final; }%% ){
	    tsk_utils_log_error("Failed to parse header: " + s_str);
	    return -2;
	}
	return 0;
}