module SDP_Templates {

/* SDP Templates, building on top of SDP_Types from Ericsson.
 *
 * (C) 2017 by Harald Welte <laforge@gnumonks.org>
 * All rights reserved.
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 */

import from SDP_Types all;

/* SDP Templates */
template SDP_Origin ts_SDP_origin(charstring addr, charstring session_id,
				  charstring session_version := "1",
				  charstring addr_type := "IP4",
				  charstring user_name := "-") := {
	user_name := user_name,
	session_id := session_id,
	session_version := session_version,
	net_type := "IN",
	addr_type := addr_type,
	addr := addr
}

template SDP_connection ts_SDP_connection_IP(charstring addr, charstring addr_type := "IP4",
					     template integer ttl := omit,
					     template integer num_of_addr := omit) :={
	net_type := "IN",
	addr_type := addr_type,
	conn_addr := {
		addr := addr,
		ttl := ttl,
		num_of_addr := num_of_addr
	}
}

template SDP_connection tr_SDP_connection_IP(template charstring addr, template charstring addr_type := ?,
					     template integer ttl := *,
					     template integer num_of_addr := *) := {
	net_type := "IN",
	addr_type := addr_type,
	conn_addr := {
		addr := addr,
		ttl := ttl,
		num_of_addr := num_of_addr
	}
}

template SDP_time ts_SDP_time(charstring beg, charstring end) := {
	time_field := {
		start_time := beg,
		stop_time := end
	},
	time_repeat := omit
}

template SDP_media_desc ts_SDP_media_desc(integer port_number, SDP_fmt_list fmts,
					  SDP_attribute_list attributes) := {
	media_field := {
		media := "audio",
		ports := {
			port_number := port_number,
			num_of_ports := omit
		},
		transport := "RTP/AVP",
		fmts := fmts
	},
	information := omit,
	connections := omit,
	bandwidth := omit,
	key := omit,
	attributes := attributes
}

template SDP_media_desc tr_SDP_media_desc(template integer port_number := ?,
					  template SDP_fmt_list fmts := ?,
					  template SDP_attribute_list attributes := ?) := {
	media_field := {
		media := "audio",
		ports := {
			port_number := port_number,
			num_of_ports := omit
		},
		transport := "RTP/AVP",
		fmts := fmts
	},
	information := *,
	connections := *,
	bandwidth := *,
	key := *,
	attributes := attributes
}

/* master template for generating SDP based in template arguments */
template SDP_Message ts_SDP(charstring local_addr, charstring remote_addr,
			    charstring session_id, charstring session_version,
			    integer rtp_port, SDP_fmt_list fmts,
			    SDP_attribute_list attributes) := {
	protocol_version := 0,
	origin := ts_SDP_origin(local_addr, session_id, session_version, f_sdp_addr2addrtype(local_addr)),
	session_name := "-",
	information := omit,
	uri := omit,
	emails := omit,
	phone_numbers := omit,
	connection := ts_SDP_connection_IP(remote_addr, f_sdp_addr2addrtype(remote_addr)),
	bandwidth := omit,
	times := { ts_SDP_time("0","0") },
	timezone_adjustments := omit,
	key := omit,
	attributes := omit,
	media_list := { ts_SDP_media_desc(rtp_port, fmts, attributes) }
}

template SDP_Message tr_SDP(template charstring remote_addr := ?, template integer rtp_port := ?) := {
	protocol_version := 0,
	origin := ?,
	session_name := ?,
	information := *,
	uri := *,
	emails := *,
	phone_numbers := *,
	connection := tr_SDP_connection_IP(remote_addr, ?),
	bandwidth := *,
	times := ?,
	timezone_adjustments := *,
	key := *,
	attributes := *,
	media_list := { tr_SDP_media_desc(rtp_port) }
}

template SDP_attribute ts_SDP_rtpmap(integer fmt, charstring val) := {
	rtpmap := {
		attr_value := int2str(fmt) & " " & val
	}
}
template SDP_attribute ts_SDP_ptime(integer p) := {
	ptime := {
		attr_value := int2str(p)
	}
}
template SDP_attribute ts_SDP_fmtp(integer fmt, charstring val) := {
	fmtp := {
		attr_value := int2str(fmt) & " " & val
	}
}

template (present) SDP_attribute tr_SDP_recvonly := {
	recvonly := {}
}

template (present) SDP_attribute tr_SDP_sendonly := {
	sendonly := {}
}

template (present) SDP_attribute tr_SDP_sendrecv := {
	sendrecv := {}
}

/* rfc3312 */
const charstring c_SDP_PRECON_TYPE_qos := "qos";
const charstring c_SDP_PRECON_STRENGTH_TAG_mandatory := "mandatory";
const charstring c_SDP_PRECON_STRENGTH_TAG_optional := "optional";
const charstring c_SDP_PRECON_STRENGTH_TAG_none := "none";
const charstring c_SDP_PRECON_STRENGTH_TAG_failure := "failure";
const charstring c_SDP_PRECON_STRENGTH_TAG_unknown := "unknown";
const charstring c_SDP_PRECON_STATUS_TYPE_e2e := "e2e";
const charstring c_SDP_PRECON_STATUS_TYPE_local := "local";
const charstring c_SDP_PRECON_STATUS_TYPE_remote := "remote";
const charstring c_SDP_PRECON_DIR_TAG_none := "none";
const charstring c_SDP_PRECON_DIR_TAG_send := "send";
const charstring c_SDP_PRECON_DIR_TAG_recv := "recv";
const charstring c_SDP_PRECON_DIR_TAG_sendrecv := "sendrecv";

template (present) SDP_attribute tr_SDP_curr(charstring status_type,
					     charstring dir_tag,
					     charstring precondition_type := c_SDP_PRECON_TYPE_qos) := {
	curr := {
		attr_value := precondition_type & " " & status_type & " " & dir_tag
	}
}
template (present) SDP_attribute tr_SDP_curr_present := {
	curr := {
		attr_value := ?
	}
}
template (value) SDP_attribute ts_SDP_curr(charstring status_type,
					   charstring dir_tag,
					   charstring precondition_type := c_SDP_PRECON_TYPE_qos) := {
	curr := {
		attr_value := precondition_type & " " & status_type & " " & dir_tag
	}
}

template (present) SDP_attribute tr_SDP_des(charstring strength_tag,
					    charstring status_type,
					    charstring dir_tag,
					    charstring precondition_type := c_SDP_PRECON_TYPE_qos) := {
	des := {
		attr_value := precondition_type & " " & strength_tag & " " & status_type & " " & dir_tag
	}
}
template (present) SDP_attribute tr_SDP_des_present := {
	des := {
		attr_value := ?
	}
}
template (value) SDP_attribute ts_SDP_des(charstring strength_tag,
					   charstring status_type,
					   charstring dir_tag,
					   charstring precondition_type := c_SDP_PRECON_TYPE_qos) := {
	des := {
		attr_value := precondition_type & " " & strength_tag & " " & status_type & " " & dir_tag
	}
}

template (present) SDP_attribute tr_SDP_conf(charstring status_type,
					     charstring dir_tag,
					     charstring precondition_type := c_SDP_PRECON_TYPE_qos) := {
	conf := {
		attr_value := precondition_type & " " & status_type & " " & dir_tag
	}
}
template (present) SDP_attribute tr_SDP_conf_present := {
	conf := {
		attr_value := ?
	}
}
template (value) SDP_attribute ts_SDP_conf(charstring status_type,
					   charstring dir_tag,
					   charstring precondition_type := c_SDP_PRECON_TYPE_qos) := {
	conf := {
		attr_value := precondition_type & " " & status_type & " " & dir_tag
	}
}

function f_sdp_addr2addrtype(charstring addr) return charstring {
	for (var integer i := 0; i < lengthof(addr); i := i + 1) {
		if (addr[i] == ":") {
			return "IP6";
		}
	}
	return "IP4";
}

}