/*
 * Some SDP file parsing...
 *
 * (C) 2009-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
 * (C) 2009-2014 by On-Waves
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <openbsc/mgcp.h>
#include <openbsc/mgcp_internal.h>

#include <errno.h>

struct sdp_rtp_map {
	/* the type */
	int payload_type;
	/* null, static or later dynamic codec name */
	char *codec_name;
	/* A pointer to the original line for later parsing */
	char *map_line;

	int rate;
	int channels;
};

int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
			int payload_type, const char *audio_name)
{
	int rate = codec->rate;
	int channels = codec->channels;
	char audio_codec[64];

	talloc_free(codec->subtype_name);
	codec->subtype_name = NULL;
	talloc_free(codec->audio_name);
	codec->audio_name = NULL;

	if (payload_type != PTYPE_UNDEFINED)
		codec->payload_type = payload_type;

	if (!audio_name) {
		switch (payload_type) {
		case 3: audio_name = "GSM/8000/1"; break;
		case 8: audio_name = "PCMA/8000/1"; break;
		case 18: audio_name = "G729/8000/1"; break;
		default:
			 /* Payload type is unknown, don't change rate and
			  * channels. */
			 /* TODO: return value? */
			 return 0;
		}
	}

	if (sscanf(audio_name, "%63[^/]/%d/%d",
		   audio_codec, &rate, &channels) < 1)
		return -EINVAL;

	codec->rate = rate;
	codec->channels = channels;
	codec->subtype_name = talloc_strdup(ctx, audio_codec);
	codec->audio_name = talloc_strdup(ctx, audio_name);

	if (!strcmp(audio_codec, "G729")) {
		codec->frame_duration_num = 10;
		codec->frame_duration_den = 1000;
	} else {
		codec->frame_duration_num = DEFAULT_RTP_AUDIO_FRAME_DUR_NUM;
		codec->frame_duration_den = DEFAULT_RTP_AUDIO_FRAME_DUR_DEN;
	}

	if (payload_type < 0) {
		payload_type = 96;
		if (rate == 8000 && channels == 1) {
			if (!strcmp(audio_codec, "GSM"))
				payload_type = 3;
			else if (!strcmp(audio_codec, "PCMA"))
				payload_type = 8;
			else if (!strcmp(audio_codec, "G729"))
				payload_type = 18;
		}

		codec->payload_type = payload_type;
	}

	if (channels != 1)
		LOGP(DMGCP, LOGL_NOTICE,
		     "Channels != 1 in SDP: '%s'\n", audio_name);

	return 0;
}

void codecs_initialize(void *ctx, struct sdp_rtp_map *codecs, int used)
{
	int i;

	for (i = 0; i < used; ++i) {
		switch (codecs[i].payload_type) {
		case 3:
			codecs[i].codec_name = "GSM";
			codecs[i].rate = 8000;
			codecs[i].channels = 1;
			break;
		case 8:
			codecs[i].codec_name = "PCMA";
			codecs[i].rate = 8000;
			codecs[i].channels = 1;
			break;
		case 18:
			codecs[i].codec_name = "G729";
			codecs[i].rate = 8000;
			codecs[i].channels = 1;
			break;
		}
	}
}

void codecs_update(void *ctx, struct sdp_rtp_map *codecs, int used, int payload, char *audio_name)
{
	int i;

	for (i = 0; i < used; ++i) {
		char audio_codec[64];
		int rate = -1;
		int channels = -1;
		if (codecs[i].payload_type != payload)
			continue;
		if (sscanf(audio_name, "%63[^/]/%d/%d",
				audio_codec, &rate, &channels) < 1) {
			LOGP(DMGCP, LOGL_ERROR, "Failed to parse '%s'\n", audio_name);
			continue;
		}

		codecs[i].map_line = talloc_strdup(ctx, audio_name);
		codecs[i].codec_name = talloc_strdup(ctx, audio_codec);
		codecs[i].rate = rate;
		codecs[i].channels = channels;
		return;
	}

	LOGP(DMGCP, LOGL_ERROR, "Unconfigured PT(%d) with %s\n", payload, audio_name);
}

int is_codec_compatible(struct mgcp_endpoint *endp, struct sdp_rtp_map *codec)
{
	char *bts_codec;
	char audio_codec[64];

	/*
	 * GSM, GSM/8000 and GSM/8000/1 should all be compatible.. let's go
	 * by name first.
	 */
	bts_codec = endp->tcfg->audio_name;
	if (sscanf(bts_codec, "%63[^/]/%*d/%*d", audio_codec) < 1)
		return 0;

	return strcasecmp(audio_codec, codec->codec_name) == 0;
}

int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
{
	struct sdp_rtp_map codecs[10];
	int codecs_used = 0;
	char *line;
	int maxptime = -1;
	int i;
	int codecs_assigned = 0;
	void *tmp_ctx = talloc_new(NULL);

	memset(&codecs, 0, sizeof(codecs));

	for_each_line(line, p->save) {
		switch (line[0]) {
		case 'o':
		case 's':
		case 't':
		case 'v':
			/* skip these SDP attributes */
			break;
		case 'a': {
			int payload;
			int ptime, ptime2 = 0;
			char audio_name[64];


			if (sscanf(line, "a=rtpmap:%d %63s",
				   &payload, audio_name) == 2) {
				codecs_update(tmp_ctx, codecs, codecs_used, payload, audio_name);
			} else if (sscanf(line, "a=ptime:%d-%d",
					  &ptime, &ptime2) >= 1) {
				if (ptime2 > 0 && ptime2 != ptime)
					rtp->packet_duration_ms = 0;
				else
					rtp->packet_duration_ms = ptime;
			} else if (sscanf(line, "a=maxptime:%d", &ptime2) == 1) {
				maxptime = ptime2;
			}
			break;
		}
		case 'm': {
			int port, rc;

			rc = sscanf(line, "m=audio %d RTP/AVP %d %d %d %d %d %d %d %d %d %d",
					&port,
					&codecs[0].payload_type,
					&codecs[1].payload_type,
					&codecs[2].payload_type,
					&codecs[3].payload_type,
					&codecs[4].payload_type,
					&codecs[5].payload_type,
					&codecs[6].payload_type,
					&codecs[7].payload_type,
					&codecs[8].payload_type,
					&codecs[9].payload_type);
			if (rc >= 2) {
				rtp->rtp_port = htons(port);
				rtp->rtcp_port = htons(port + 1);
				codecs_used = rc - 1;
				codecs_initialize(tmp_ctx, codecs, codecs_used);
			}
			break;
		}
		case 'c': {
			char ipv4[16];

			if (sscanf(line, "c=IN IP4 %15s", ipv4) == 1) {
				inet_aton(ipv4, &rtp->addr);
			}
			break;
		}
		default:
			if (p->endp)
				LOGP(DMGCP, LOGL_NOTICE,
				     "Unhandled SDP option: '%c'/%d on 0x%x\n",
				     line[0], line[0], ENDPOINT_NUMBER(p->endp));
			else
				LOGP(DMGCP, LOGL_NOTICE,
				     "Unhandled SDP option: '%c'/%d\n",
				     line[0], line[0]);
			break;
		}
	}

	/* Now select the primary and alt_codec */
	for (i = 0; i < codecs_used && codecs_assigned < 2; ++i) {
		struct mgcp_rtp_codec *codec = codecs_assigned == 0 ?
					&rtp->codec : &rtp->alt_codec;

		if (endp->tcfg->no_audio_transcoding &&
			!is_codec_compatible(endp, &codecs[i])) {
			LOGP(DMGCP, LOGL_NOTICE, "Skipping codec %s\n",
				codecs[i].codec_name);
			continue;
		}

		mgcp_set_audio_info(p->cfg, codec,
					codecs[i].payload_type,
					codecs[i].map_line);
		codecs_assigned += 1;
	}

	if (codecs_assigned > 0) {
		/* TODO/XXX: Store this per codec and derive it on use */
		if (maxptime >= 0 && maxptime * rtp->codec.frame_duration_den >
				rtp->codec.frame_duration_num * 1500) {
			/* more than 1 frame */
			rtp->packet_duration_ms = 0;
		}

		LOGP(DMGCP, LOGL_NOTICE,
		     "Got media info via SDP: port %d, payload %d (%s), "
		     "duration %d, addr %s\n",
		     ntohs(rtp->rtp_port), rtp->codec.payload_type,
		     rtp->codec.subtype_name ? rtp->codec.subtype_name : "unknown",
		     rtp->packet_duration_ms, inet_ntoa(rtp->addr));
	}

	talloc_free(tmp_ctx);
	return codecs_assigned > 0;
}

