summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore8
-rw-r--r--Makefile.am4
-rw-r--r--configure.in5
-rw-r--r--lrtp.pc.in13
-rw-r--r--src/Makefile.am19
-rw-r--r--src/asc2bin.cc64
-rw-r--r--src/asc2bin.h50
-rw-r--r--src/compat.h37
-rw-r--r--src/lrtp.cc273
-rw-r--r--src/lrtp.h104
-rw-r--r--src/lrtp_profiles.h72
-rw-r--r--src/rtp.cc262
-rw-r--r--src/rtp.h116
-rw-r--r--src/rtp_profile.h86
-rw-r--r--src/rtp_profile_amrwb.cc307
-rw-r--r--src/rtp_profile_amrwb.h39
-rw-r--r--src/rtp_profile_opus.cc188
-rw-r--r--src/rtp_profile_opus.h39
-rw-r--r--src/rtp_profile_raw.cc123
-rw-r--r--src/rtp_profile_raw.h39
-rw-r--r--src/srtp.cc230
-rw-r--r--src/srtp.h54
-rw-r--r--test/Makefile29
-rw-r--r--test/test_amrwb.cc155
-rw-r--r--test/test_connectivity.cc122
-rw-r--r--test/test_init.cc63
-rw-r--r--test/test_opus.cc272
-rw-r--r--test/test_raw.cc78
-rw-r--r--test/test_rtp.cc112
-rw-r--r--test/test_srtp.cc87
30 files changed, 3032 insertions, 18 deletions
diff --git a/.gitignore b/.gitignore
index bb23159..6ffe871 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,11 @@ Makefile.in
*.la
*.lo
*.o
+lrtp.pc
+test_amrwb
+test_connectivity
+test_init
+test_opus
+test_raw
+test_rtp
+test_srtp
diff --git a/Makefile.am b/Makefile.am
index 86e2080..d22e1ba 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,9 @@
AUTOMAKE_OPTIONS = gnu
SUBDIRS = src
DISTDIRS = src
+EXTRA_DIST = lrtp.pc.in
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = lrtp.pc
.PHONY:
diff --git a/configure.in b/configure.in
index ddf76b9..537aa37 100644
--- a/configure.in
+++ b/configure.in
@@ -1,6 +1,6 @@
# Filename: configure.in
-AC_INIT([lrtp], [1.0.0])
+AC_INIT([lrtp], [0.0.1])
AC_CONFIG_SRCDIR([src/lrtp.cc])
AM_INIT_AUTOMAKE
@@ -69,5 +69,6 @@ AC_STDC_HEADERS
AC_OUTPUT(
Makefile
- src/Makefile)
+ src/Makefile
+ lrtp.pc)
diff --git a/lrtp.pc.in b/lrtp.pc.in
new file mode 100644
index 0000000..568b498
--- /dev/null
+++ b/lrtp.pc.in
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: liblrtp
+Description: LiteRTP: A (lite) library for handling sRTP transmissions.
+Version: @VERSION@
+Requires:
+Conflicts:
+Libs: -L${libdir} -llrtp
+Libs.private:
+Cflags: -I${includedir}
diff --git a/src/Makefile.am b/src/Makefile.am
index 594b257..15a201f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,10 +5,23 @@ liblrtp_la_LIBADD = $(SRTP_LIBS)
liblrtp_la_CXXFLAGS = $(SRTP_CXXFLAGS)
liblrtp_la_SOURCES = \
- lrtp.cc
+ lrtp.cc \
+ rtp.cc \
+ srtp.cc \
+ rtp_profile_amrwb.cc \
+ rtp_profile_opus.cc \
+ rtp_profile_raw.cc \
+ asc2bin.cc
include_HEADERS = \
- lrtp.h
+ lrtp.h \
+ lrtp_profiles.h
-EXTRA_DIST =
+EXTRA_DIST = \
+ rtp_profile_amrwb.h \
+ rtp_profile_opus.h \
+ rtp_profile_raw.h \
+ rtp.h \
+ srtp.h \
+ asc2bin.h
diff --git a/src/asc2bin.cc b/src/asc2bin.cc
new file mode 100644
index 0000000..65efc31
--- /dev/null
+++ b/src/asc2bin.cc
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * asc2bin.cc
+ *
+ * Thu Sep 5 11:12:50 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "asc2bin.h"
+
+static int asc2nibble(unsigned char c)
+{
+ if(c >= '0' && c <= '9') return c - '0';
+ if(c >= 'a' && c <= 'f') return c - 'a' + 0xa;
+ if(c >= 'A' && c <= 'F') return c - 'A' + 0xa;
+ return -1;
+}
+
+ssize_t asc2bin(char *raw, size_t rawsz, const char *hex, size_t hexlen)
+{
+ if(hexlen % 2 != 0) return -1;
+ if(rawsz < hexlen / 2) return -1;
+
+ unsigned char val;
+ int nibble;
+ size_t size = 0;
+
+ while(size < hexlen / 2) {
+ nibble = asc2nibble(hex[0]);
+ if(nibble == -1) return -1;
+ val = (nibble << 4);
+
+ nibble = asc2nibble(hex[1]);
+ if(nibble == -1) return -1;
+ val |= (nibble & 0xff);
+
+ *raw = val;
+ raw++;
+ size++;
+
+ hex += 2;
+ }
+
+ return (ssize_t)size;
+}
diff --git a/src/asc2bin.h b/src/asc2bin.h
new file mode 100644
index 0000000..42c3b54
--- /dev/null
+++ b/src/asc2bin.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * asc2bin.h
+ *
+ * Thu Sep 5 11:12:50 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __LRTP_ASC2BIN_H__
+#define __LRTP_ASC2BIN_H__
+
+#include <stdlib.h>
+
+#include "compat.h"
+
+/**
+ * asc2bin converts a hexadecimal string to a raw octet string.
+ * @param raw The char buffer that will contain the result.
+ * @param rawsz The size of the output buffer 'raw'. This size must be at
+ * least hexlen / 2.
+ * @param hex The input hex string.
+ * @param hexlen The length of the hex string.
+ * @return The length of the resulting raw data. -1 on error.
+ * Errors are one of the following:
+ * - Hex string contains invalid hex character (0-9, a-f and A-F allowed).
+ * - rawsz is less than hexlen / 2.
+ * - hexlen is not a multiplum of 2 (odd hex string lengths not supported).
+ */
+ssize_t asc2bin(char *raw, size_t rawsz, const char *hex, size_t hexlen);
+
+#endif/*__LRTP_ASC2BIN_H__*/
diff --git a/src/compat.h b/src/compat.h
new file mode 100644
index 0000000..70a6286
--- /dev/null
+++ b/src/compat.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * compat.h
+ *
+ * Thu Sep 5 11:14:38 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __LRTP_COMPAT_H__
+#define __LRTP_COMPAT_H__
+
+#ifdef WIN32
+typedef signed int ssize_t;
+#else
+
+#endif
+
+#endif/*__LRTP_COMPAT_H__*/
diff --git a/src/lrtp.cc b/src/lrtp.cc
index 36da6f0..1f0b11d 100644
--- a/src/lrtp.cc
+++ b/src/lrtp.cc
@@ -27,20 +27,267 @@
*/
#include "lrtp.h"
-#ifdef TEST_LRTP
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
-#include "test.h"
+#include <string>
+#include <string.h>
+#include <map>
+#include <stdio.h>
-TEST_BEGIN;
+#include "rtp_profile.h"
+#include "rtp_profile_amrwb.h"
+#include "rtp_profile_opus.h"
+#include "rtp_profile_raw.h"
-// TODO: Put some testcode here (see test.h for usable macros).
-TEST_TRUE(false, "No tests yet!");
+#include "srtp.h"
-TEST_END;
+#ifdef __cplusplus
+extern "C" {
+#endif
-#endif/*TEST_LRTP*/
+typedef std::map<csrc_t, lrtp_profile_t *> profile_map_t;
+
+struct lrtp_t {
+ SRTP *srtp;
+ csrc_t ssrc;
+ unsigned short seq;
+ profile_map_t profiles;
+
+ csrc_t next_csrc; // for frame iterator (see get_next_frame)
+
+ std::list<outputframe_t *> framelist;
+};
+
+typedef struct {
+ lrtp_profile_id_t id;
+ struct lrtp_profile_t *(*create)(struct lrtp_t *lrtp, unsigned int csrc,
+ va_list ap);
+} profile_class_t;
+
+static const profile_class_t registered_profiles[] = {
+ { PROFILE_AMRWB, profile_amrwb_create },
+ { PROFILE_OPUS, profile_opus_create },
+ { PROFILE_RAW, profile_raw_create },
+ { }
+};
+
+EXPORT
+struct lrtp_t *lrtp_init(const char *key, unsigned int ssrc)
+{
+ struct lrtp_t *lrtp = new struct lrtp_t;
+
+ lrtp->srtp = new SRTP(key, ssrc);
+ lrtp->ssrc = ssrc;
+ lrtp->seq = 0;
+
+ return lrtp;
+}
+
+EXPORT
+void lrtp_close(struct lrtp_t *lrtp)
+{
+ delete lrtp->srtp;
+ delete lrtp;
+}
+
+EXPORT
+struct lrtp_profile_t *lrtp_create_profile(struct lrtp_t *lrtp,
+ lrtp_profile_id_t profile_id,
+ unsigned int csrc, ...)
+{
+ struct lrtp_profile_t *profile = NULL;
+
+ if(lrtp->profiles.find(csrc) != lrtp->profiles.end()) {
+ // TODO: CSRC already active
+ printf("ERROR: CSRC already active\n");
+ return NULL;
+ }
+
+ va_list ap;
+ va_start(ap, csrc);
+
+ const profile_class_t *p = registered_profiles;
+ while(p->create) {
+ if(p->id == profile_id) {
+ profile = p->create(lrtp, csrc, ap);
+ profile->process_finished = NULL; // TODO: Figure out a way to set non-profile specific options.
+ break;
+ }
+ p++;
+ }
+
+ va_end(ap);
+
+ if(profile) {
+ profile->id = PROFILE_RAW;
+ profile->lrtp = lrtp;
+ profile->csrc = csrc;
+
+ lrtp->profiles[csrc] = profile;
+ }
+
+ return profile;
+}
+
+EXPORT
+void lrtp_destroy_profile(struct lrtp_t *lrtp, unsigned int csrc)
+{
+ if(lrtp->profiles.find(csrc) == lrtp->profiles.end()) {
+ // TODO: CSRC not found
+ printf("ERROR: CSRC not found\n");
+ return;
+ }
+
+ struct lrtp_profile_t *profile = lrtp->profiles[csrc];
+ profile->destroy(profile);
+ lrtp->profiles.erase(csrc);
+}
+
+EXPORT
+int lrtp_enqueue_frame(struct lrtp_profile_t *profile,
+ const char *data, size_t size)
+{
+ inputframe_t *frame = new inputframe_t();
+ frame->data = data;
+ frame->size = size;
+ frame->offset = 0;
+
+ profile->framelist.push_back(frame);
+
+ return 0;
+}
+
+static lrtp_profile_t *get_next_profile(struct lrtp_t *lrtp)
+{
+ // TODO: This function /should/ return the next profile containing frame data,
+ // not just the next profile in the list (regardless of it's framequeue being
+ // empty!).
+
+ if(lrtp->profiles.size() == 0) return NULL; // No profiles
+
+ profile_map_t::iterator i = lrtp->profiles.find(lrtp->next_csrc);
+
+ if(i == lrtp->profiles.end()) {
+ i = lrtp->profiles.begin();
+ }
+
+ struct lrtp_profile_t *profile = i->second;
+
+ i++;
+
+ if(i == lrtp->profiles.end()) {
+ i = lrtp->profiles.begin();
+ }
+
+ lrtp->next_csrc = i->second->csrc;
+
+ return profile;
+}
+
+EXPORT
+int lrtp_pack(struct lrtp_t *lrtp, char *packet, size_t maxsize)
+{
+ //if(!profile) return PACK_MISSING_PROFILE;
+
+ // TODO: Check profile magic word
+
+ struct lrtp_profile_t *profile = get_next_profile(lrtp);
+
+ if(profile == NULL || profile->framelist.size() == 0) return 0;
+
+ inputframe_t *frame = profile->framelist.front();
+
+ RTP rtp;
+ rtp.setSSrc(lrtp->ssrc);
+ //rtp.setTimestamp(ts); // TODO...
+ rtp.setSeq(lrtp->seq);
+ rtp.addCSrc(profile->csrc);
+
+ int ret = profile->pack(profile,
+ frame->data + frame->offset,
+ frame->size - frame->offset,
+ rtp);
+
+ if(ret < 0) return ret;
+
+ frame->offset += ret;
+
+ if(frame->size == frame->offset) {
+ if(profile->process_finished) {
+ profile->process_finished(profile, frame->data,
+ profile->process_finished_ptr);
+ }
+
+ profile->framelist.pop_front();
+ delete frame;
+ }
+
+ if(rtp.isValid()) {
+ size_t size = rtp.packet(packet, maxsize);
+ size = lrtp->srtp->encrypt(packet, size);
+ lrtp->seq++;
+ return size;
+ }
+
+ return 0;
+}
+
+EXPORT
+int lrtp_dequeue_frame(struct lrtp_t *lrtp,
+ char *frame, size_t maxsize,
+ unsigned int *csrc, unsigned int *ts)
+{
+ if(lrtp->framelist.size() == 0) return 0;
+
+ outputframe_t *f = lrtp->framelist.front();
+
+ if(f->size > maxsize) {
+ printf("Buffer is too small\n");
+ return -1; // Buffer too small.
+ }
+
+ memcpy(frame, f->data, f->size);
+
+ lrtp->framelist.pop_front();
+
+ free(f->data);
+ delete f;
+
+ return f->size;
+}
+
+EXPORT
+int lrtp_unpack(struct lrtp_t *lrtp, const char *packet, size_t size)
+{
+ if(!lrtp) return UNPACK_MISSING_HANDLE;
+
+ // TODO: Check lrtp magic word
+
+ char pkg[16*1024];
+ memcpy(pkg, packet, size);
+
+ size = lrtp->srtp->decrypt(pkg, size);
+
+ RTP rtp;
+ rtp.fromPacket(pkg, size);
+ std::list<csrc_t> csrcs = rtp.getCSrcs();
+ if(csrcs.size() == 0) return UNPACK_MISSING_CSRC;
+ if(csrcs.size() > 1) return UNPACK_TOO_MANY_CSRCS;
+
+ csrc_t csrc = *csrcs.begin();
+
+ struct lrtp_profile_t *profile = NULL;
+ if(lrtp->profiles.find(csrc) == lrtp->profiles.end()) {
+ return UNPACK_MISSING_PROFILE;
+ }
+
+ profile = lrtp->profiles[csrc];
+
+ std::list<outputframe_t*> framelist;
+ int ret = profile->unpack(profile, rtp, framelist);
+ lrtp->framelist.splice(lrtp->framelist.end(), framelist);
+
+ return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/lrtp.h b/src/lrtp.h
index 7428997..ce6b0e2 100644
--- a/src/lrtp.h
+++ b/src/lrtp.h
@@ -27,4 +27,108 @@
*/
#ifndef __LRTP_LRTP_H__
#define __LRTP_LRTP_H__
+
+#ifdef WIN32
+#ifdef BUILD_DLL
+/* DLL export */
+#define EXPORT __declspec(dllexport)
+#else
+/* EXE import */
+#define EXPORT __declspec(dllimport)
+#endif
+#else
+#define EXPORT
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+
+#include "lrtp_profiles.h"
+
+struct lrtp_t;
+
+EXPORT
+struct lrtp_t *lrtp_init(const char *key, unsigned int ssrc);
+
+EXPORT
+void lrtp_close(struct lrtp_t *lrtp);
+
+struct lrtp_profile_t;
+
+/**
+ * @param ...
+ */
+EXPORT
+struct lrtp_profile_t *lrtp_create_profile(struct lrtp_t *lrtp,
+ lrtp_profile_id_t profile_id,
+ unsigned int csrc, ...);
+
+EXPORT
+void lrtp_destroy_profile(struct lrtp_t *lrtp, unsigned int csrc);
+
+typedef enum {
+ // Errors:
+ PACK_ERROR = 1000, // Error...
+ PACK_BUFFER_TOO_SMALL = 1001, // Packet buffer needs to be bigger.
+ PACK_UNKNOWN_PROFILE = 1002, // Illegal profile id
+ PACK_MISSING_PROFILE = 1003, // Profile pointer NULL or not valid.
+} lrtp_pack_status_t;
+
+/**
+ * Enqueue a media frame for the packetiser.
+ * @param profile A pointer to profile needed for processing the frame type.
+ * @param framedate The frame data that needs encapsulation.
+ * @param framesize The size in bytes of the frame data.
+ * @return 0 on success, or a negative error code on error.
+ * NOTE: The frame pointer cannot be freed or overwritten until all frame data
+ * has been handled by lrtp_pack(). Either call lrtp_pack() until it returns 0
+ * after each call to lrtp_enqueue_frame or use the
+ * OPTION_SET_PROCESS_FINISHED_HANDLER option to set a process finished handler.
+ * See lrtp_profiles.h for further details.
+ */
+EXPORT
+int lrtp_enqueue_frame(struct lrtp_profile_t *profile,
+ const char *framedate, size_t framesize);
+
+/**
+ * Handle frame data from the frame queue and create at most a single sRTP
+ * packet.
+ * @param lrtp The lrtp context handle.
+ * @param packet A char buffer which will contain the resulting RTP data.
+ * @param maxsize the maximum number of bytes that can be contained within
+ * packet.
+ * @return Returns the number of bytes written in packet, if any (can be zero
+ * if no packet is available) or a negative error code on error.
+ */
+EXPORT int lrtp_pack(struct lrtp_t *lrtp, char *packet, size_t maxsize);
+
+typedef enum {
+ // Errors:
+ UNPACK_ERROR = 1000, // Error...
+ UNPACK_BUFFER_TOO_SMALL = 1001, // Frame buffer needs to be bigger.
+ UNPACK_MISSING_HANDLE = 1002, // Handle pointer NULL or not valid.
+ UNPACK_MISSING_CSRC = 1003, // Exactly one csrc must be present.
+ UNPACK_TOO_MANY_CSRCS = 1004, // Exactly one csrc must be present.
+ UNPACK_MISSING_PROFILE = 1005, // CSrc from packet could not be connected with a preofile..
+} lrtp_unpack_status_t;
+
+/**
+ */
+EXPORT
+int lrtp_dequeue_frame(struct lrtp_t *lrtp,
+ char *frame, size_t maxsize,
+ unsigned int *csrc, unsigned int *ts);
+
+/**
+ */
+EXPORT
+int lrtp_unpack(struct lrtp_t *lrtp, const char *packet, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif/*__LRTP_LRTP_H__*/
diff --git a/src/lrtp_profiles.h b/src/lrtp_profiles.h
new file mode 100644
index 0000000..a3d6db1
--- /dev/null
+++ b/src/lrtp_profiles.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * lrtp_profiles.h
+ *
+ * Mon Sep 9 13:29:04 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __LRTP_LRTP_PROFILES_H__
+#define __LRTP_LRTP_PROFILES_H__
+
+// List of known RTP profiles:
+typedef enum {
+ PROFILE_RAW = 0, // Dummy profile, for test
+ PROFILE_L16 = 1,
+ PROFILE_AMRWB = 2,
+ PROFILE_OPUS = 3,
+ PROFILE_JPEG = 4,
+} lrtp_profile_id_t;
+
+// No more options.
+#define OPTION_END 0
+
+// Options relating to all profiles:
+/**
+ * This option is used to set the custom processFinishedHandler
+ * It takes two arguments, the first being a function pointer of the type:
+ * void (*process_finished)(struct lrtp_profile_t *profile,
+ * const char *frame, size_t framesize,
+ * void *ptr);
+ *
+ * the second argument is the value of ptr, passed on to the callback function.
+ * See rtp_profile.h for further details.
+ */
+#define OPTION_SET_PROCESS_FINISHED_HANDLER 1000
+
+// Raw profile options:
+#define OPTION_RAW_PKG_SIZE 2000 // Integer argument.
+ // Number of bytes per rtp packet.
+ // Default is 100
+
+// AMR-WB profile options:
+#define OPTION_AMRWB_FRAME_TYPE_INDEX 3000 // Integer argument.
+ // Frame type index according to
+ // Table 1a in "3GPP TS 26.201"
+ // Default is 8: AMR-WB 23.85 kbit/s
+
+// Opus profile options:
+// None
+
+// Jpeg profile options:
+
+#endif/*__LRTP_LRTP_PROFILES_H__*/
diff --git a/src/rtp.cc b/src/rtp.cc
new file mode 100644
index 0000000..28a9203
--- /dev/null
+++ b/src/rtp.cc
@@ -0,0 +1,262 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * rtp.cc
+ *
+ * Mon Sep 2 15:24:09 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "rtp.h"
+
+#include <string.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+
+RTP::RTP()
+{
+ memset(&header, 0, sizeof(header));
+ pads = 0;
+
+ header.version = 2;
+
+ memset(pload, 0, sizeof(pload));
+ pload_size = 0;
+
+ is_valid = false;
+}
+
+void RTP::setPadding(unsigned char padding)
+{
+ if(padding == 0) {
+ header.p = 0;
+ pads = 0;
+ return;
+ }
+ header.p = 1;
+ pads = padding;
+}
+
+unsigned char RTP::padding() const
+{
+ return pads;
+}
+
+void RTP::setPayloadType(unsigned char pt)
+{
+ header.pt = pt;
+}
+
+unsigned char RTP::payloadType() const
+{
+ return header.pt;
+}
+
+void RTP::setMarker(bool bit)
+{
+ header.m = bit?1:0;
+}
+
+bool RTP::marker() const
+{
+ return header.m;
+}
+
+void RTP::setSeq(uint16_t seq)
+{
+ header.seq = htons(seq);
+}
+
+uint16_t RTP::seq() const
+{
+ return ntohs(header.seq);
+}
+
+void RTP::setTimestamp(uint32_t ts)
+{
+ header.ts = htonl(ts);
+}
+
+uint32_t RTP::timestamp() const
+{
+ return ntohl(header.ts);
+}
+
+void RTP::setSSrc(uint32_t ssrc)
+{
+ header.ssrc = htonl(ssrc);
+}
+
+uint32_t RTP::SSrc() const
+{
+ return ntohl(header.ssrc);
+}
+
+void RTP::addCSrc(csrc_t csrc)
+{
+ if(csrcs.size() == 15) {
+ printf("ERROR: Too many CSRCs (max 15).\n");
+ return; // TODO: Report error!
+ }
+ csrcs.push_back(csrc);
+ header.cc = csrcs.size();
+}
+
+std::list<csrc_t> RTP::getCSrcs() const
+{
+ return csrcs;
+}
+
+void RTP::removeCSrc(csrc_t csrc)
+{
+ csrcs.remove(csrc);
+ header.cc = csrcs.size();
+}
+
+void RTP::clearCSrcs()
+{
+ csrcs.clear();
+ header.cc = csrcs.size();
+}
+
+void RTP::setPayload(const char *pl, size_t size)
+{
+ if(size > MAX_RTP_PAYLOAD_SIZE) {
+ printf("ERROR: Payload is too big for RTP pakcet.\n");
+ // TODO: Report error.
+ }
+
+ memcpy(pload, pl, size);
+ pload_size = size;
+
+ setValid(true);
+}
+
+size_t RTP::payload(char *payload, size_t maxsize) const
+{
+ if(pload_size > maxsize) {
+ printf("ERROR: Payload is too big for the buffer.\n");
+ return 0; // TODO: Report error.
+ }
+
+ memcpy(payload, pload, pload_size);
+ return pload_size;
+}
+
+size_t RTP::payloadSize() const
+{
+ return pload_size;
+}
+
+const char *RTP::payloadData() const
+{
+ return pload;
+}
+
+size_t RTP::packet(char *packet, size_t maxsize) const
+{
+ memset(packet, 0, maxsize);
+
+ size_t total_packet_size =
+ sizeof(header) + sizeof(csrc_t) * csrcs.size() + pload_size + pads;
+
+ if(total_packet_size > maxsize) {
+ printf("ERROR: Packet is too big for the buffer.\n");
+ return 0; // TODO: Report error.
+ }
+
+ char *p = packet;
+
+ // Copy header fields.
+ memcpy(p, &header, sizeof(header));
+
+ p += sizeof(header);
+
+ // Write CSrcs to packet
+ csrc_t *pcsrc = (csrc_t*)p;
+ std::list<csrc_t>::const_iterator i = csrcs.begin();
+ while(i != csrcs.end()) {
+ *pcsrc++ = htonl(*i);
+ i++;
+ }
+
+ p += sizeof(csrc_t) * csrcs.size();
+
+ // TODO: Insert header extension here (if it exists)
+
+ // Write payload to body.
+ memcpy(p, pload, pload_size);
+
+ p += pload_size;
+
+ if(pads) {
+ for(int i = 0; i < pads - 1; i++) *p++ = '\0';
+ *p++ = (unsigned char)pads;
+ }
+
+ return p - packet;
+}
+
+void RTP::fromPacket(const char *packet, size_t size)
+{
+ rtp_header_t *hdr = (rtp_header_t *)packet;
+
+ if(hdr->version != 2) {
+ printf("ERROR: Wrong RTP header version.\n");
+ return; // TODO: Invalid RTP version error
+ }
+
+ setMarker(hdr->m);
+ setPayloadType(hdr->pt);
+ setSeq(ntohs(hdr->seq));
+ setTimestamp(ntohl(hdr->ts));
+ setSSrc(ntohl(hdr->ssrc));
+
+ if(hdr->p) {
+ setPadding(*(unsigned char*)&packet[size - 1]);
+ }
+
+ // TODO: Use header extension flag: hdr->x
+
+ // Read out CSrc's:
+ csrc_t *pcsrc = (csrc_t*)(packet + sizeof(rtp_header_t));
+ for(int i = 0; i < hdr->cc; i++) {
+ addCSrc(ntohl(*pcsrc));
+ pcsrc++;
+ }
+
+ // Read out payload
+ size_t plsz = size - (sizeof(rtp_header_t) + hdr->cc*sizeof(csrc_t) + pads);
+ char *pl = (char*)pcsrc;
+ setPayload(pl, plsz);
+
+ setValid(true);
+}
+
+bool RTP::isValid()
+{
+ return is_valid;
+}
+
+void RTP::setValid(bool valid)
+{
+ is_valid = valid;
+}
diff --git a/src/rtp.h b/src/rtp.h
new file mode 100644
index 0000000..b7aa8b4
--- /dev/null
+++ b/src/rtp.h
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * rtp.h
+ *
+ * Mon Sep 2 15:24:09 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __LRTP_RTP_H__
+#define __LRTP_RTP_H__
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <list>
+
+typedef struct {
+ uint16_t cc:4; // CSRC count
+ uint16_t x:1; // Header extension flag
+ uint16_t p:1; // Padding flag
+ uint16_t version:2; // Protocol version
+
+ uint16_t m:1; // Marker bit
+ uint16_t pt:7; // Payload type
+
+ uint16_t seq; // Sequence number
+
+ uint32_t ts; // Timestamp
+ uint32_t ssrc; // Synchronization source
+} rtp_header_t;
+
+#define MAX_RTP_PACKET_SIZE (16 * 1024)
+#define MAX_RTP_PAYLOAD_SIZE ( MAX_RTP_PACKET_SIZE - sizeof(rtp_header_t) )
+
+typedef struct {
+ rtp_header_t header;
+ char body[MAX_RTP_PAYLOAD_SIZE];
+} rtp_t;
+
+typedef unsigned int csrc_t;
+
+class RTP {
+public:
+ RTP();
+
+ /* // Not implemented
+ void setHeaderExtension();
+ int headerExtension();
+ */
+
+ void setPadding(unsigned char padding);
+ unsigned char padding() const;
+
+ void setPayloadType(unsigned char pt);
+ unsigned char payloadType() const;
+
+ void setMarker(bool bit);
+ bool marker() const;
+
+ void setSeq(uint16_t seq);
+ uint16_t seq() const;
+
+ void setTimestamp(uint32_t seq);
+ uint32_t timestamp() const;
+
+ void setSSrc(uint32_t ssrc);
+ uint32_t SSrc() const;
+
+ void addCSrc(csrc_t csrc);
+ std::list<csrc_t> getCSrcs() const;
+ void removeCSrc(csrc_t csrc);
+ void clearCSrcs();
+
+ void setPayload(const char *payload, size_t size);
+ size_t payload(char *payload, size_t maxsize) const;
+ size_t payloadSize() const;
+ const char *payloadData() const;
+
+ size_t packet(char *packet, size_t maxsize) const;
+ void fromPacket(const char *packet, size_t size);
+
+ bool isValid();
+ void setValid(bool valid);
+
+private:
+ std::list<csrc_t> csrcs;
+
+ rtp_header_t header;
+
+ unsigned char pads;
+
+ char pload[MAX_RTP_PAYLOAD_SIZE];
+ size_t pload_size;
+
+ bool is_valid;
+};
+
+#endif/*__LRTP_RTP_H__*/
diff --git a/src/rtp_profile.h b/src/rtp_profile.h
new file mode 100644
index 0000000..96dc9eb
--- /dev/null
+++ b/src/rtp_profile.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * rtp_profile.h
+ *
+ * Wed Sep 11 08:40:11 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __LRTP_RTP_PROFILE_H__
+#define __LRTP_RTP_PROFILE_H__
+
+#include <stdint.h>
+#include <list>
+
+#include "rtp.h"
+
+struct lrtp_t;
+
+typedef struct {
+ const char *data;
+ size_t size;
+ size_t offset;
+} inputframe_t;
+
+typedef struct {
+ char *data;
+ size_t size;
+
+ csrc_t csrc;
+ unsigned int ts;
+ // TODO: Add other metadata ...
+
+} outputframe_t;
+
+struct lrtp_profile_t {
+ struct lrtp_t *lrtp;
+ lrtp_profile_id_t id;
+ unsigned int csrc;
+
+ // Frames ready for packing with this profile:
+ std::list<inputframe_t *> framelist;
+
+ // Profile functions:
+ /**
+ * Custom callback used when a frame has been processed.
+ * This could be the place to call free(3), decrease a reference counter or
+ * re-add to a memory pool.
+ * Use ptr to pass custom parameters to the callback.
+ * If NULL, no call is performed.
+ */
+ void (*process_finished)(struct lrtp_profile_t *profile,
+ const char *frame, void *ptr);
+ void *process_finished_ptr;
+
+ int (*pack)(struct lrtp_profile_t *profile,
+ const char *frame, size_t framesize,
+ RTP &rtp);
+
+ int (*unpack)(struct lrtp_profile_t *profile,
+ const RTP &rtp,
+ std::list<outputframe_t *> &framelist);
+
+ void (*destroy)(struct lrtp_profile_t *profile);
+
+};
+
+#endif/*__LRTP_RTP_PROFILE_H__*/
diff --git a/src/rtp_profile_amrwb.cc b/src/rtp_profile_amrwb.cc
new file mode 100644
index 0000000..f83b3c3
--- /dev/null
+++ b/src/rtp_profile_amrwb.cc
@@ -0,0 +1,307 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * rtp_profile_amrwb.cc
+ *
+ * Wed Oct 2 14:43:05 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "rtp_profile_amrwb.h"
+
+#include "rtp_profile.h"
+#include "rtp.h"
+
+#include <stdio.h>
+#include <string.h>
+
+/*
+The timestamp clock frequency is the same as the sampling frequency, so the
+timestamp unit is in samples.
+
+The duration of one speech frame-block is 20 ms for both AMR and AMR-WB. For
+AMR, the sampling frequency is 8 kHz, corresponding to 160 encoded speech
+samples per frame from each channel. For AMR-WB, the sampling frequency is
+16 kHz, corresponding to 320 samples per frame from each channel. Thus, the
+timestamp is increased by 160 for AMR and 320 for AMR-WB for each consecutive
+frame-block.
+
+QUESTION: Should we use 16kHz or 19351Hz?
+ANSWER: The encoder and decoder respectively should use 19531Hz, the rest of
+the system can assume 16kHz without loss of quality.
+ */
+
+struct lrtp_profile_amrwb_t {
+ struct lrtp_profile_t profile; // 'Inherit' lrtp_profile_t
+
+ int frame_type_index;
+};
+
+// Frame sizes based on frame type index:
+static const int wb_frame_size[16] = {
+ 17, 23, 32, 36, 40, 46, 50, 58,
+ 60, 5, -1, -1, -1, -1, -1, 0
+};
+
+/*
+ * 0 1 2 3 4 5 6 7
+ * +-+-+-+-+-+-+-+-+
+ * |F| FT |Q|P|P|
+ * +-+-+-+-+-+-+-+-+
+ */
+
+/*
+ * F (1 bit): If set to 1, indicates that this frame is followed by
+ * another speech frame in this payload; if set to 0, indicates that
+ * this frame is the last frame in this payload.
+ */
+static int is_last_frame(const char *frame_header)
+{
+ return ( (*frame_header >> 7) & 0x1 ) == 0;
+}
+
+static void set_is_last_frame(char *frame_header, int last)
+{
+ last = 1 - last; // Invert 'last': 0 means last, 1 means more
+ *frame_header = (*frame_header & 0x7f) | ( (last & 0x1) << 7);
+}
+
+/*
+ * FT (4 bits): Frame type index, indicating either the AMR or AMR-WB
+ * speech coding mode or comfort noise (SID) mode of the
+ * corresponding frame carried in this payload.
+ */
+static int frame_type_index(const char *frame_header)
+{
+ return (*frame_header >> 3) & 0xf;
+}
+
+static int set_frame_type_index(char *frame_header, int index)
+{
+ *frame_header = (*frame_header & 0x87) | ( (index & 0xf) << 3);
+}
+
+/*
+ * Q (1 bit): Frame quality indicator. If set to 0, indicates the
+ * corresponding frame is severely damaged and the receiver should
+ * set the RX_TYPE (see [6]) to either SPEECH_BAD or SID_BAD
+ * depending on the frame type (FT).
+ */
+static int quality_indicator(const char *frame_header)
+{
+ return (*frame_header >> 2) & 0x1;
+}
+
+static int set_quality_indicator(char *frame_header, int quality)
+{
+ *frame_header = (*frame_header & 0xf8) | ( (quality & 0x1) << 2);
+}
+
+
+// http://tools.ietf.org/html/rfc3267#section-4.4
+int profile_amrwb_pack(struct lrtp_profile_t *profile,
+ const char *input, size_t inputsize,
+ RTP &rtp)
+{
+ // NOTE: This implementation does not support frame interleaving...
+
+ struct lrtp_profile_amrwb_t *p = (struct lrtp_profile_amrwb_t *)profile;
+
+ size_t frameheader_size = 1;
+ size_t cmr_size = 1;
+
+ // Frame size based on frame_type_index,
+ size_t frame_size = wb_frame_size[p->frame_type_index];
+
+ // This is the maximum number of frames we have room for in a single RTP
+ // payload.
+ size_t max_num_frames =
+ (MAX_RTP_PAYLOAD_SIZE - cmr_size) / (frame_size + frameheader_size);
+
+ size_t cpsz = inputsize;
+
+ printf("cpsz: %d\n", cpsz);
+
+ size_t num_frames = cpsz / frame_size;
+
+ if(num_frames == 0) {
+ printf("Garbage at the end of the buffer\n");
+ rtp.setValid(false);
+ return -1;
+ }
+
+ if(num_frames > max_num_frames) num_frames = max_num_frames;
+
+ char *payload = (char*)malloc(MAX_RTP_PAYLOAD_SIZE);
+
+ /* 0 1
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ * +-+-+-+-+-+-+-+-+- - - - - - - -
+ * | CMR |R|R|R|R| ILL | ILP |
+ * +-+-+-+-+-+-+-+-+- - - - - - - -
+ */
+ // If a terminal has no preference in which mode to receive, it SHOULD set
+ // CMR=15 in all its outbound payloads.
+ char *CMR = payload;
+ *CMR = 15;
+
+ // The ILL and ILP fields are not used (see note above).
+
+ char *frame_header = CMR + cmr_size;
+ for(size_t i = 0; i < num_frames; i++) {
+ // 0 if this is the last frame.
+ set_is_last_frame(frame_header, i == (num_frames - 1) );
+
+ // Frame type index (4 bits):
+ set_frame_type_index(frame_header, p->frame_type_index);
+
+ // Frame quality indicator (1 bit): Set to 0 to indicate damaged frame.
+ set_quality_indicator(frame_header, 1);
+
+ frame_header += frameheader_size;
+ }
+
+ char *frame_data = frame_header;
+
+ size_t payload_size = cmr_size;
+ const char *frame_offset = input;
+ for(size_t i = 0; i < num_frames; i++) {
+ memcpy(frame_data, frame_offset, frame_size);
+ frame_data += frame_size;
+ frame_offset += frame_size;
+ payload_size += frameheader_size + frame_size;
+ }
+
+ //size_t payload_size = cmr_size + num_frames*(frame_size + frameheader_size);
+ rtp.setPayload(payload, payload_size);
+ rtp.setValid(true);
+
+ printf("payload (pack):\n");
+ for(int i = 0; i < payload_size; i++) {
+ printf("%02x ", (unsigned char)payload[i]);
+ }
+ printf("\n");
+
+ free(payload);
+
+ return cpsz;
+}
+
+int profile_amrwb_unpack(struct lrtp_profile_t *profile,
+ const RTP &rtp,
+ std::list<outputframe_t *> &framelist)
+{
+ struct lrtp_profile_amrwb_t *p = (struct lrtp_profile_amrwb_t *)profile;
+
+ size_t size = rtp.payloadSize();
+ const char *payload = rtp.payloadData();
+
+ printf("---------------------------------------- New packet:\n");
+ printf("payload (unpack):\n");
+ for(int i = 0; i < size; i++) {
+ printf("%02x ", (unsigned char)payload[i]);
+ }
+ printf("\n");
+
+ // Read CMR:
+ size_t cmr_size = 1;
+ char CMR = payload[0];
+ if(CMR != 15) {
+ printf("CMR not 15\n");
+ return UNPACK_ERROR;
+ }
+
+ // TODO: What to do if there are 0 frames (and therefore no header to set the
+ // 'last frame' bit in....)
+
+ // Read ToC:
+ size_t frameheader_size = 1;
+ const char *frame_toc;
+ frame_toc = payload + cmr_size;
+
+ size_t frame_num = 0;
+ const char *frame_data = frame_toc;
+ while(!is_last_frame(frame_data)) {
+ frame_num++;
+ frame_data += frameheader_size;
+ }
+ frame_num++;
+ frame_data += frameheader_size;
+
+ while(frame_num) {
+ size_t frame_size_idx = frame_type_index(frame_toc);
+ size_t frame_size = wb_frame_size[frame_size_idx];
+
+ outputframe_t *of = new outputframe_t();
+ of->size = frame_size;
+ char *buf = (char*)malloc(of->size);
+ memcpy(buf, frame_data, frame_size);
+ of->data = buf;
+
+ framelist.push_back(of);
+
+ if(is_last_frame(frame_toc)) return 0;
+
+ frame_toc += frameheader_size;
+ frame_data += frame_size;
+
+ frame_num--;
+ }
+
+ printf("Error, missed the last_frame bit\n");
+
+ return 1; // Error, missed the last_frame bit
+}
+
+void profile_amrwb_destroy(struct lrtp_profile_t *profile)
+{
+ struct lrtp_profile_amrwb_t *p = (struct lrtp_profile_amrwb_t *)profile;
+ delete p;
+}
+
+struct lrtp_profile_t *profile_amrwb_create(struct lrtp_t *lrtp,
+ unsigned int csrc,
+ va_list vp)
+{
+ struct lrtp_profile_amrwb_t *p = new struct lrtp_profile_amrwb_t;
+
+ p->profile.pack = profile_amrwb_pack;
+ p->profile.unpack = profile_amrwb_unpack;
+ p->profile.destroy = profile_amrwb_destroy;
+
+ p->frame_type_index = 8; // Default: AMR-WB 23.85 kbit/s
+
+ while(true) {
+ int type = va_arg(vp, int);
+ if(type == OPTION_END) break;
+
+ switch(type) {
+ case OPTION_AMRWB_FRAME_TYPE_INDEX:
+ p->frame_type_index = va_arg(vp, int);
+ break;
+ default:
+ // TODO: Unknown arg type
+ break;
+ }
+ }
+
+ return (struct lrtp_profile_t *)p;
+}
diff --git a/src/rtp_profile_amrwb.h b/src/rtp_profile_amrwb.h
new file mode 100644
index 0000000..38b20c1
--- /dev/null
+++ b/src/rtp_profile_amrwb.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * rtp_profile_amrwb.h
+ *
+ * Wed Oct 2 14:43:05 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __LRTP_RTP_PROFILE_AMRWB_H__
+#define __LRTP_RTP_PROFILE_AMRWB_H__
+
+#include <stdarg.h>
+
+#include "lrtp.h"
+
+struct lrtp_profile_t *profile_amrwb_create(struct lrtp_t *lrtp,
+ unsigned int csrc,
+ va_list ap);
+
+#endif/*__LRTP_RTP_PROFILE_AMRWB_H__*/
diff --git a/src/rtp_profile_opus.cc b/src/rtp_profile_opus.cc
new file mode 100644
index 0000000..102d175
--- /dev/null
+++ b/src/rtp_profile_opus.cc
@@ -0,0 +1,188 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * rtp_profile_opus.cc
+ *
+ * Tue Sep 10 13:53:24 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Part of this code is an adaptation of the GStreamer RTP profile code for Celt
+ * by Wim Taymans <wim.taymans@gmail.com>
+ * The original code can be found in the gst-plugins-good package version 1.1.3:
+ * http://gstreamer.freedesktop.org/src/gst-plugins-good
+ */
+#include "rtp_profile_opus.h"
+
+/*
+ +--------------+----------------+-----------+----------+
+ | Abbreviation | Name | Bandwidth | Sampling |
+ +--------------+----------------+-----------+----------+
+ | nb | Narrowband | 0 - 4000 | 8000 |
+ | | | | |
+ | mb | Mediumband | 0 - 6000 | 12000 |
+ | | | | |
+ | wb | Wideband | 0 - 8000 | 16000 |
+ | | | | |
+ | swb | Super-wideband | 0 - 12000 | 24000 |
+ | | | | |
+ | fb | Fullband | 0 - 20000 | 48000 |
+ +--------------+----------------+-----------+----------+
+
+ Audio bandwidth naming
+
+ Table 1
+*/
+/*
+Recommended Bitrate
+
+ For a frame size of 20 ms, these are the bitrate "sweet spots" for
+ Opus in various configurations:
+ o 8-12 kb/s for NB speech,
+ o 16-20 kb/s for WB speech,
+ o 28-40 kb/s for FB speech,
+ o 48-64 kb/s for FB mono music, and
+ o 64-128 kb/s for FB stereo music.
+*/
+
+/*
+Forward Error Correction (FEC)
+
+ The voice mode of Opus allows for "in-band" forward error correction
+ (FEC) data to be embedded into the bit stream of Opus.
+*/
+
+/*
+RTP Header Usage
+
+ The format of the RTP header is specified in [RFC3550]. The Opus
+ payload format uses the fields of the RTP header consistent with this
+ specification.
+
+ The payload length of Opus is a multiple number of octets and
+ therefore no padding is required. The payload MAY be padded by an
+ integer number of octets according to [RFC3550].
+
+ The marker bit (M) of the RTP header is used in accordance with
+ Section 4.1 of [RFC3551].
+
+ The RTP payload type for Opus has not been assigned statically and is
+ expected to be assigned dynamically.
+
+ The receiving side MUST be prepared to receive duplicates of RTP
+ packets. Only one of those payloads MUST be provided to the Opus
+ decoder for decoding and others MUST be discarded.
+
+ Opus supports 5 different audio bandwidths which may be adjusted
+ during the duration of a call. The RTP timestamp clock frequency is
+ defined as the highest supported sampling frequency of Opus, i.e.
+ 48000 Hz, for all modes and sampling rates of Opus. The unit for the
+ timestamp is samples per single (mono) channel. The RTP timestamp
+ corresponds to the sample time of the first encoded sample in the
+ encoded frame. For sampling rates lower than 48000 Hz the number of
+ samples has to be multiplied with a multiplier according to Table 2
+ to determine the RTP timestamp.
+
+ +---------+------------+
+ | fs (Hz) | Multiplier |
+ +---------+------------+
+ | 8000 | 6 |
+ | | |
+ | 12000 | 4 |
+ | | |
+ | 16000 | 3 |
+ | | |
+ | 24000 | 2 |
+ | | |
+ | 48000 | 1 |
+ +---------+------------+
+
+ Table 2: Timestamp multiplier
+*/
+
+#include "rtp_profile.h"
+
+#include <stdio.h>
+#include <string.h>
+
+struct lrtp_profile_opus_t {
+ struct lrtp_profile_t profile; // 'Inherit' lrtp_profile_t
+};
+
+int profile_opus_pack(struct lrtp_profile_t *profile,
+ const char *frame, size_t framesize,
+ RTP &rtp)
+{
+ //struct lrtp_profile_opus_t *p = (struct lrtp_profile_opus_t *)profile;
+ (void)profile;
+
+ rtp.setPayload(frame, framesize);
+ rtp.setValid(true);
+
+ return framesize;
+}
+
+int profile_opus_unpack(struct lrtp_profile_t *profile,
+ const RTP &rtp,
+ std::list<outputframe_t *> &framelist)
+{
+ struct lrtp_profile_opus_t *p = (struct lrtp_profile_opus_t *)profile;
+
+ outputframe_t *of = new outputframe_t();
+ of->size = rtp.payloadSize();
+ char *buf = (char*)malloc(of->size);
+ of->size = rtp.payload(buf, of->size);
+ of->data = buf;
+
+ framelist.push_back(of);
+
+ return 0;
+}
+
+void profile_opus_destroy(struct lrtp_profile_t *profile)
+{
+ struct lrtp_profile_opus_t *p = (struct lrtp_profile_opus_t *)profile;
+ delete p;
+}
+
+struct lrtp_profile_t *profile_opus_create(struct lrtp_t *lrtp,
+ unsigned int csrc,
+ va_list vp)
+{
+ struct lrtp_profile_opus_t *p = new struct lrtp_profile_opus_t;
+
+ p->profile.pack = profile_opus_pack;
+ p->profile.unpack = profile_opus_unpack;
+ p->profile.destroy = profile_opus_destroy;
+
+ while(true) {
+ int type = va_arg(vp, int);
+ if(type == OPTION_END) break;
+
+ switch(type) {
+ default:
+ // TODO: Unknown arg type
+ break;
+ }
+ }
+
+ return &p->profile;
+}
diff --git a/src/rtp_profile_opus.h b/src/rtp_profile_opus.h
new file mode 100644
index 0000000..23002d3
--- /dev/null
+++ b/src/rtp_profile_opus.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * rtp_profile_opus.h
+ *
+ * Tue Sep 10 13:53:24 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __LRTP_RTP_PROFILE_OPUS_H__
+#define __LRTP_RTP_PROFILE_OPUS_H__
+
+#include <stdarg.h>
+
+#include "lrtp.h"
+
+struct lrtp_profile_t *profile_opus_create(struct lrtp_t *lrtp,
+ unsigned int csrc,
+ va_list ap);
+
+#endif/*__LRTP_RTP_PROFILE_OPUS_H__*/
diff --git a/src/rtp_profile_raw.cc b/src/rtp_profile_raw.cc
new file mode 100644
index 0000000..cf34186
--- /dev/null
+++ b/src/rtp_profile_raw.cc
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * rtp_profile_raw.cc
+ *
+ * Mon Sep 2 14:30:56 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "rtp_profile_raw.h"
+
+#include "rtp_profile.h"
+
+#include <stdio.h>
+#include <string.h>
+
+struct lrtp_profile_raw_t {
+ struct lrtp_profile_t profile; // 'Inherit' lrtp_profile_t
+
+ unsigned short int pkg_size;
+
+ // Cache
+ char *pkg_cache;
+ int pkg_cache_size;
+};
+
+int profile_raw_pack(struct lrtp_profile_t *profile,
+ const char *frame, size_t framesize,
+ RTP &rtp)
+{
+ struct lrtp_profile_raw_t *p = (struct lrtp_profile_raw_t *)profile;
+
+ size_t cpsz = p->pkg_size - p->pkg_cache_size;
+
+ if(cpsz > framesize) cpsz = framesize;
+
+ if(cpsz != 0) {
+ memcpy(p->pkg_cache, frame, cpsz);
+ p->pkg_cache_size += cpsz;
+ }
+
+ if(p->pkg_cache_size == p->pkg_size) {
+ rtp.setPayload(p->pkg_cache, p->pkg_cache_size);
+ p->pkg_cache_size = 0;
+ }
+
+ return cpsz;
+}
+
+int profile_raw_unpack(struct lrtp_profile_t *profile,
+ const RTP &rtp,
+ std::list<outputframe_t *> &framelist)
+{
+ struct lrtp_profile_raw_t *p = (struct lrtp_profile_raw_t *)profile;
+
+ outputframe_t *of = new outputframe_t();
+ of->size = rtp.payloadSize();
+ char *buf = (char*)malloc(of->size);
+ of->size = rtp.payload(buf, of->size);
+ of->data = buf;
+
+ framelist.push_back(of);
+
+ return 0;
+}
+
+void profile_raw_destroy(struct lrtp_profile_t *profile)
+{
+ struct lrtp_profile_raw_t *p = (struct lrtp_profile_raw_t *)profile;
+ delete p->pkg_cache;
+ delete p;
+}
+
+struct lrtp_profile_t *profile_raw_create(struct lrtp_t *lrtp,
+ unsigned int csrc,
+ va_list vp)
+{
+ struct lrtp_profile_raw_t *p = new struct lrtp_profile_raw_t;
+
+ p->profile.pack = profile_raw_pack;
+ p->profile.unpack = profile_raw_unpack;
+ p->profile.destroy = profile_raw_destroy;
+
+ p->pkg_size = 100;
+
+ while(true) {
+ int type = va_arg(vp, int);
+ if(type == OPTION_END) break;
+
+ switch(type) {
+ case OPTION_RAW_PKG_SIZE:
+ p->pkg_size = va_arg(vp, int);
+ break;
+ default:
+ // TODO: Unknown arg type
+ break;
+ }
+ }
+
+ p->pkg_cache = new char[p->pkg_size];
+ p->pkg_cache_size = 0;
+
+ return &p->profile;
+}
+
diff --git a/src/rtp_profile_raw.h b/src/rtp_profile_raw.h
new file mode 100644
index 0000000..febae5d
--- /dev/null
+++ b/src/rtp_profile_raw.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * rtp_profile_raw.h
+ *
+ * Mon Sep 2 14:30:56 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __LRTP_RTP_PROFILE_RAW_H__
+#define __LRTP_RTP_PROFILE_RAW_H__
+
+#include <stdarg.h>
+
+#include "lrtp.h"
+
+struct lrtp_profile_t *profile_raw_create(struct lrtp_t *lrtp,
+ unsigned int csrc,
+ va_list ap);
+
+#endif/*__LRTP_RTP_PROFILE_RAW_H__*/
diff --git a/src/srtp.cc b/src/srtp.cc
new file mode 100644
index 0000000..98c4002
--- /dev/null
+++ b/src/srtp.cc
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * srtp.cc
+ *
+ * Thu Sep 5 10:46:10 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "srtp.h"
+
+#ifdef WIN32
+#include <srtp/crypto/include/datatypes.h>
+#include <srtp/include/srtp.h>
+#include <srtp/include/rtp_priv.h>
+#else
+#include <srtp/datatypes.h>
+#include <srtp/srtp.h>
+#include <srtp/rtp_priv.h>
+#endif
+
+#include "asc2bin.h"
+
+struct SRTP::prv {
+ char *key;
+ size_t key_len;
+
+ unsigned int ssrc;
+
+ srtp_t session;
+ srtp_policy_t policy;
+};
+
+static bool is_initialised = false;
+
+SRTP::SRTP(std::string key, unsigned int ssrc)
+{
+ prv = NULL;
+
+ err_status_t status;
+
+ if(!is_initialised) {
+ status = srtp_init();
+ if(status != err_status_ok) {
+ // TODO: Error handling
+ printf("srtp_init failed %d\n", status);
+ }
+ is_initialised = true;
+ }
+
+ prv = new struct prv;
+
+ prv->ssrc = ssrc;
+
+ setupKey(key);
+ setupPolicy(true, true);
+
+ status = srtp_create(&prv->session, &prv->policy);
+ if(status != err_status_ok) {
+ // TODO: Error handling
+ printf("srtp_create %d\n", status);
+ }
+
+ status = srtp_add_stream(prv->session, &prv->policy);
+ if(status != err_status_ok) {
+ // TODO: Error handling
+ printf("srtp_add_stream %d\n", status);
+ }
+}
+
+SRTP::~SRTP()
+{
+ err_status_t status = srtp_remove_stream(prv->session, htonl(prv->ssrc));
+ if(status != err_status_ok) {
+ // TODO: Error handling
+ printf("srtp_remove_stream failed %d\n", status);
+ }
+
+ status = srtp_dealloc(prv->session);
+ if(status != err_status_ok) {
+ // TODO: Error handling
+ printf("srtp_dealloc failed %d\n", status);
+ }
+
+ status = srtp_shutdown();
+ if(status != err_status_ok) {
+ // TODO: Error handling
+ printf("srtp_shutdown failed %d\n", status);
+ }
+
+ is_initialised = false;
+
+ if(prv) {
+ free(prv->key);
+ delete prv;
+ }
+}
+
+void SRTP::setupKey(const std::string &key)
+{
+ prv->key = (char *)calloc(MASTER_KEY_LEN, 1);
+ prv->key_len = MASTER_KEY_LEN;
+
+ if(key.length() > MASTER_KEY_LEN * 2) printf("KeyTooLong\n"); // TODO
+
+ // Read key from hexadecimal on command line into an octet string
+ ssize_t len = asc2bin(prv->key, prv->key_len, key.c_str(), key.size());
+
+ if(len == -1) printf("InvalidHexKeyString\n"); // TODO
+ prv->key_len = len;
+
+ // check that hex string is the right length.
+ if(len < MASTER_KEY_LEN) printf("KeyTooShort\n"); // TODO
+}
+
+void SRTP::setupPolicy(bool confidentiality, bool authentication)
+{
+#ifndef USE_CRYPTO
+ confidentiality = authentication = false;
+ printf("No crypto!\n")
+#endif
+
+ /*
+ * create policy structure, using the default mechanisms but
+ * with only the security services requested on the command line,
+ * using the right SSRC value
+ */
+ if(confidentiality && authentication) {
+ crypto_policy_set_aes_cm_128_hmac_sha1_80(&prv->policy.rtp);
+ prv->policy.rtp.sec_serv = sec_serv_conf_and_auth;
+ } else if(confidentiality && !authentication) {
+ crypto_policy_set_aes_cm_128_null_auth(&prv->policy.rtp);
+ prv->policy.rtp.sec_serv = sec_serv_conf;
+ } else if(!confidentiality && authentication) {
+ crypto_policy_set_null_cipher_hmac_sha1_80(&prv->policy.rtp);
+ prv->policy.rtp.sec_serv = sec_serv_auth;
+ } else {
+ /*
+ * we're not providing security services, so set the policy to the
+ * null policy
+ *
+ * Note that this policy does not conform to the SRTP
+ * specification, since RTCP authentication is required. However,
+ * the effect of this policy is to turn off SRTP, so that this
+ * application is now a vanilla-flavored RTP application.
+ */
+ prv->policy.rtp.cipher_type = NULL_CIPHER;
+ prv->policy.rtp.cipher_key_len = 0;
+ prv->policy.rtp.auth_type = NULL_AUTH;
+ prv->policy.rtp.auth_key_len = 0;
+ prv->policy.rtp.auth_tag_len = 0;
+ prv->policy.rtp.sec_serv = sec_serv_none;
+ }
+
+ crypto_policy_set_rtcp_default(&prv->policy.rtcp);
+ prv->policy.rtcp.sec_serv = sec_serv_none; // No need for RTCP
+
+ prv->policy.key = (uint8_t *)prv->key;
+ prv->policy.ssrc.type = ssrc_specific;
+ prv->policy.ssrc.value = prv->ssrc;
+ prv->policy.next = NULL;
+}
+
+int SRTP::encrypt(char *packet, size_t size)
+{
+ int sz = size;
+ err_status_t status = srtp_protect(prv->session, packet, &sz);
+ if(status != err_status_ok) {
+ // TODO: throw SRTP::UnprotectException();
+ printf("srtp_protect failed %d\n", status);
+ }
+
+ return sz;
+}
+
+int SRTP::decrypt(char *packet, size_t size)
+{
+ int sz = size;
+ err_status_t status = srtp_unprotect(prv->session, packet, &sz);
+ switch(status) {
+ case err_status_ok:
+ // No errors.
+ break;
+ case err_status_replay_fail:
+ // TODO: throw SRTP::ReplayException();// (replay check failed)
+ printf("srtp_unprotect failed replay %d\n", status);
+ break;
+ case err_status_replay_old:
+ // TODO: throw SRTP::ReplayOldException();// (replay check failed)
+ printf("srtp_unprotect failed replay_old %d\n", status);
+ break;
+ case err_status_auth_fail:
+ // TODO: throw SRTP::AuthCheckException();// (auth check failed)
+ printf("srtp_unprotect failed auth %d\n", status);
+ break;
+ default:
+ // TODO: throw SRTP::UnprotectException();
+ printf("srtp_unprotect failed %d\n", status);
+ break;
+ }
+
+ /*
+ if(octets_recvd - RTP_HEADER_LEN > (ssize_t)size) {
+ printf("BufferSize %d\n", status);
+ }
+ */
+
+ // TODO: rtp.fromBuffer(packet, size);
+ //memcpy(buf, prv->receiver->message.body, octets_recvd - RTP_HEADER_LEN);
+
+ return sz;
+}
diff --git a/src/srtp.h b/src/srtp.h
new file mode 100644
index 0000000..3d8b697
--- /dev/null
+++ b/src/srtp.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * srtp.h
+ *
+ * Thu Sep 5 10:46:10 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __LRTP_SRTP_H__
+#define __LRTP_SRTP_H__
+
+#include <string>
+
+#include "rtp.h"
+
+#define MAX_KEY_LEN 64
+#define MASTER_KEY_LEN 30
+
+class SRTP {
+public:
+ SRTP(std::string key, unsigned int ssrc);
+ ~SRTP();
+
+ int encrypt(char *packet, size_t size);
+ int decrypt(char *packet, size_t size);
+
+private:
+ struct prv;
+ struct prv *prv;
+
+ void setupKey(const std::string &key);
+ void setupPolicy(bool confidentiality, bool authentication);
+};
+
+#endif/*__LRTP_SRTP_H__*/
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..49bcf0d
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,29 @@
+all: connectivity amrwb init rtp srtp opus raw
+
+connectivity:
+ g++ -g test_$@.cc -L../src/.libs -llrtp -I../src -o test_$@
+ LD_LIBRARY_PATH=../src/.libs ./test_$@
+
+amrwb:
+ g++ -g test_$@.cc -L../src/.libs -llrtp -lm -I../src -o test_$@
+ LD_LIBRARY_PATH=../src/.libs ./test_$@
+
+opus:
+ g++ -g test_$@.cc -L../src/.libs -llrtp -lm -I../src -lopus -lao -o test_$@
+ LD_LIBRARY_PATH=../src/.libs ./test_$@
+
+init:
+ g++ -g test_$@.cc -L../src/.libs -llrtp -I../src -o test_$@
+ LD_LIBRARY_PATH=../src/.libs ./test_$@
+
+raw:
+ g++ -g test_$@.cc -L../src/.libs -llrtp -I../src -o test_$@
+ LD_LIBRARY_PATH=../src/.libs ./test_$@
+
+rtp:
+ g++ -g test_$@.cc ../src/rtp.cc -o test_$@
+ ./test_$@
+
+srtp:
+ g++ -g -DUSE_CRYPTO test_$@.cc ../src/rtp.cc ../src/srtp.cc ../src/asc2bin.cc -lsrtp -o test_$@
+ ./test_$@
diff --git a/test/test_amrwb.cc b/test/test_amrwb.cc
new file mode 100644
index 0000000..cf5a5a6
--- /dev/null
+++ b/test/test_amrwb.cc
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * test_init.cc
+ *
+ * Mon Sep 2 14:02:16 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <lrtp.h>
+
+#include <stdio.h>
+
+#include <string>
+#include <vector>
+
+#include <math.h>
+#include <opus/opus.h>
+#include <limits.h>
+#include <ao/ao.h>
+
+#define KEY "123456789012345678901234567890123456789012345678901234567890"
+#define SSRC 1234567890
+
+#define FS 8000
+
+#define F1 440
+#define AF1 0.3
+
+#define F2 500
+#define AF2 0.7
+
+void dump(const char *title, const char *buf, size_t size)
+{
+ printf("%12s: ", title);
+ for(int i = 0; i < size; i++) {
+ if(i % 8 == 0) printf(" ");
+ printf("%02x ", (unsigned char)*buf++);
+ }
+ printf("\n");
+}
+
+// Frame sizes based on frame type index:
+static const int wb_frame_size[16] = {
+ 17, 23, 32, 36, 40, 46, 50, 58,
+ 60, 5, -1, -1, -1, -1, -1, 0
+};
+
+int main()
+{
+ std::vector<std::string> packets;
+ unsigned int csrc = 42;
+
+ int frame_type_index = 8;
+
+ printf("========== Encode ==========\n");
+
+ { // Encode
+ struct lrtp_t *lrtp = lrtp_init(KEY, SSRC);
+
+ struct lrtp_profile_t *profile =
+ lrtp_create_profile(lrtp, PROFILE_AMRWB, csrc,
+ OPTION_AMRWB_FRAME_TYPE_INDEX, frame_type_index,
+ OPTION_END);
+
+ char packet[16*1024];
+ size_t packetsize = sizeof(packet);
+
+ int cnt = 0;
+
+ for(int i = 0; i < 10; i++) {
+
+ size_t num_frames = 10;
+ char frame[wb_frame_size[frame_type_index] * num_frames];
+ size_t framesize = wb_frame_size[frame_type_index] * num_frames;
+
+ for(int i = 0; i < framesize; i++) frame[i] = cnt++;
+
+ int timestamp = 0;
+
+ int ret = lrtp_enqueue_frame(profile, frame, framesize);
+ while( (ret = lrtp_pack(lrtp, packet, sizeof(packet))) != 0) {
+ std::string p;
+ p.append(packet, ret);
+ packets.push_back(p);
+ }
+ }
+
+ lrtp_destroy_profile(lrtp, csrc);
+ lrtp_close(lrtp);
+ }
+
+ printf("========== Decode ==========\n");
+
+ { // Decode
+ struct lrtp_t *lrtp = lrtp_init(KEY, SSRC);
+
+ struct lrtp_profile_t *profile =
+ lrtp_create_profile(lrtp, PROFILE_AMRWB, csrc,
+ OPTION_AMRWB_FRAME_TYPE_INDEX, frame_type_index,
+ OPTION_END);
+
+ char frame[16*1024];
+ size_t framesize = sizeof(frame);
+
+ int cnt = 0;
+
+ std::vector<std::string>::iterator i = packets.begin();
+ while(i != packets.end()) {
+ size_t packetsize = i->size();
+ printf("unpack sz: %d\n", packetsize);
+ const char *packet = i->data();
+ unsigned int ts;
+
+ framesize = sizeof(frame);
+
+ lrtp_unpack(lrtp, packet, packetsize);
+ int ret;
+ while((ret = lrtp_dequeue_frame(lrtp, frame, framesize, &csrc, &ts)) != 0) {
+ printf("Got %d bytes, csrc %d, ts: %d\n", ret, csrc, ts);
+
+ printf("cnt:\n");
+ for(int i = 0; i < ret; i++) {
+ printf("%02x ", (unsigned char)frame[i]);
+ }
+ printf("\n");
+ }
+
+ i++;
+ }
+
+ lrtp_destroy_profile(lrtp, csrc);
+ lrtp_close(lrtp);
+ }
+
+ return 0;
+}
diff --git a/test/test_connectivity.cc b/test/test_connectivity.cc
new file mode 100644
index 0000000..e115748
--- /dev/null
+++ b/test/test_connectivity.cc
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * test_init.cc
+ *
+ * Mon Sep 2 14:02:16 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <lrtp.h>
+
+#include <stdio.h>
+
+#include <string>
+#include <vector>
+
+#define KEY "123456789012345678901234567890123456789012345678901234567890"
+#define SSRC 1234567890
+
+void dump(const char *title, const char *buf, size_t size)
+{
+ printf("%12s: ", title);
+ for(int i = 0; i < size; i++) {
+ if(i % 8 == 0) printf(" ");
+ printf("%02x ", (unsigned char)*buf++);
+ }
+ printf("\n");
+}
+
+int main()
+{
+ char frame[5];
+ int pkg_size = 4;
+
+ std::vector<std::string> packets;
+ unsigned int csrc = 42;
+
+ { // Encode
+ struct lrtp_t *lrtp = lrtp_init(KEY, SSRC);
+
+ struct lrtp_profile_t *profile =
+ lrtp_create_profile(lrtp, PROFILE_RAW, csrc,
+ OPTION_RAW_PKG_SIZE, pkg_size,
+ OPTION_END);
+
+ char packet[16*1024];
+ size_t size = sizeof(packet);
+
+ for(unsigned int ts = 0; ts < 8; ts++) {
+ int ret = 0;
+ ret = lrtp_enqueue_frame(profile, frame, sizeof(frame));
+ while( (ret = lrtp_pack(lrtp, packet, sizeof(packet))) != 0) {
+ std::string p;
+ p.append(packet, ret);
+ packets.push_back(p);
+ dump("pkg", packet, ret);
+ }
+ }
+
+ lrtp_destroy_profile(lrtp, csrc);
+
+ lrtp_close(lrtp);
+ }
+
+ { // Decode
+ struct lrtp_t *lrtp = lrtp_init(KEY, SSRC);
+
+ struct lrtp_profile_t *profile =
+ lrtp_create_profile(lrtp, PROFILE_RAW, csrc,
+ OPTION_RAW_PKG_SIZE, pkg_size,
+ OPTION_END);
+
+ char frame[16*1024];
+ size_t framesize = sizeof(frame);
+
+ int cnt = 0;
+
+ std::vector<std::string>::iterator i = packets.begin();
+ while(i != packets.end()) {
+ size_t packetsize = i->size();
+ printf("unpack sz: %d\n", packetsize);
+ const char *packet = i->data();
+ unsigned int ts;
+
+ framesize = sizeof(frame);
+
+ lrtp_unpack(lrtp, packet, packetsize);
+ int ret;
+ while((ret = lrtp_dequeue_frame(lrtp, frame, framesize, &csrc, &ts))
+ != 0) {
+ printf("Got %d bytes, csrc %d, ts: %d\n", ret, csrc, ts);
+ dump("pkg", frame, ret);
+ }
+
+ i++;
+ }
+
+ lrtp_destroy_profile(lrtp, csrc);
+ lrtp_close(lrtp);
+ }
+
+ return 0;
+}
+
diff --git a/test/test_init.cc b/test/test_init.cc
new file mode 100644
index 0000000..97ecd30
--- /dev/null
+++ b/test/test_init.cc
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * test_init.cc
+ *
+ * Mon Sep 2 14:02:16 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <lrtp.h>
+
+#include <stdio.h>
+
+#define KEY "123456789012345678901234567890123456789012345678901234567890"
+#define SSRC 1234567890
+
+void dump(const char *title, const char *buf, size_t size)
+{
+ printf("%12s: ", title);
+ for(int i = 0; i < size; i++) {
+ if(i % 8 == 0) printf(" ");
+ printf("%02x ", (unsigned char)*buf++);
+ }
+ printf("\n");
+}
+
+int main()
+{
+ char frame[] = "foo";
+
+ struct lrtp_t *lrtp = lrtp_init(KEY, SSRC);
+
+ unsigned int csrc = 42;
+ struct lrtp_profile_t *profile =
+ lrtp_create_profile(lrtp, PROFILE_RAW, csrc,
+ OPTION_RAW_PKG_SIZE, sizeof(frame),
+ OPTION_END);
+
+ lrtp_destroy_profile(lrtp, csrc);
+
+ lrtp_close(lrtp);
+
+ return 0;
+}
+
diff --git a/test/test_opus.cc b/test/test_opus.cc
new file mode 100644
index 0000000..68ea0f4
--- /dev/null
+++ b/test/test_opus.cc
@@ -0,0 +1,272 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * test_init.cc
+ *
+ * Mon Sep 2 14:02:16 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <lrtp.h>
+
+#include <stdio.h>
+
+#include <string>
+#include <vector>
+
+#include <math.h>
+#include <opus/opus.h>
+#include <limits.h>
+#include <ao/ao.h>
+
+#define KEY "123456789012345678901234567890123456789012345678901234567890"
+#define SSRC 1234567890
+
+#define FS 8000
+
+#define F1 440
+#define AF1 0.3
+
+#define F2 500
+#define AF2 0.7
+
+void dump(const char *title, const char *buf, size_t size)
+{
+ printf("%12s: ", title);
+ for(int i = 0; i < size; i++) {
+ if(i % 8 == 0) printf(" ");
+ printf("%02x ", (unsigned char)*buf++);
+ }
+ printf("\n");
+}
+
+class Audio {
+public:
+ Audio() {
+ ao_initialize();
+
+ device = NULL;
+ ao_sample_format format;
+
+ int default_driver = ao_default_driver_id();
+ if(default_driver == -1) {
+ printf("Error could not default driver.\n");
+ return;
+ }
+ printf("Default driver: %d\n", default_driver);
+
+ format.bits = 16;
+ format.channels = 2;
+ format.rate = FS;
+ format.byte_format = AO_FMT_LITTLE;
+
+ device = ao_open_live(default_driver, &format, NULL);
+ if(device == NULL) {
+ printf("Error opening device.\n");
+ return;
+ }
+ }
+
+ ~Audio() {
+ if(device) ao_close(device);
+ ao_shutdown();
+ }
+
+ void play(char *pcm, size_t size) {
+ ao_play(device, pcm, size);
+ }
+
+private:
+ ao_device *device;
+};
+
+int main()
+{
+ size_t channels = 2;
+ size_t ms[] = { 120, 240, 480, 960, 1920, 2880 };
+
+ std::vector<std::string> packets;
+ unsigned int csrc = 42;
+
+ double sin_x = 0;
+ size_t ts = 0;
+
+ printf("========== Encode ==========\n");
+
+ { // Encode
+ struct lrtp_t *lrtp = lrtp_init(KEY, SSRC);
+
+ struct lrtp_profile_t *profile =
+ lrtp_create_profile(lrtp, PROFILE_OPUS, csrc,
+ //OPTION_RAW_PKG_SIZE, pkg_size,
+ OPTION_END);
+
+ char packet[16*1024];
+ size_t packetsize = sizeof(packet);
+
+ int err;
+ OpusEncoder *opus = opus_encoder_create(FS, channels,
+ OPUS_APPLICATION_AUDIO, &err);
+ printf("Opus create err: %d\n", err);
+
+ opus_encoder_ctl(opus, OPUS_SET_BITRATE(64000));// [500;512000]
+ opus_encoder_ctl(opus, OPUS_SET_COMPLEXITY(10)); // [0;10]
+ opus_encoder_ctl(opus, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC));
+
+ int cnt = 0;
+ size_t timestamp = 0;
+ for(unsigned int ts = 0; ts < 120; ts++) {
+ printf("packet #%d\n", ts);
+
+ size_t idx = rand() % (sizeof(ms)/sizeof(size_t));
+ printf("idx: %d\n", idx);
+ size_t pcmsize = ms[idx] / (48000.0 / FS); // Number of samples pr channel
+ short *pcm = new short[100000/*pcmsize * channels*/];
+ for(int i = 0 ; i < pcmsize; i++) {
+ sin_x++;
+
+ double amp1 = sin((2*M_PI/(double)FS)*(double)sin_x * AF1) * SHRT_MAX;
+ double amp2 = sin((2*M_PI/(double)FS)*(double)sin_x * AF2) * SHRT_MAX;
+
+ pcm[i*2] = (short)(sin(2*M_PI/FS*(double)sin_x * F1) * amp1);
+ pcm[i*2+1] = (short)(sin(2*M_PI/FS*(double)sin_x * F2) * amp2);
+ }
+
+ // Master timestamp is sample number in 48kHz (Opus RFC states this)
+ timestamp += pcmsize * 48000 / FS;
+
+ // size_t pcmsize = pcmsize * channels * sizeof(short);
+
+ char frame[pcmsize];
+ int framesize = sizeof(frame);
+ framesize = opus_encode(opus, pcm, pcmsize,
+ (unsigned char*)frame, framesize);
+
+ if(framesize < 0) {
+ printf("Opus error: %s\n", opus_strerror(framesize));
+ }
+
+ printf("Opus Packet: %d bytes from %d bytes\n", pcmsize, framesize);
+
+ int ret = lrtp_enqueue_frame(profile, frame, framesize);
+ while( (ret = lrtp_pack(lrtp, packet, sizeof(packet))) != 0) {
+ std::string p;
+ p.append(packet, ret);
+ packets.push_back(p);
+ }
+
+ delete[] pcm;
+ }
+
+ opus_encoder_destroy(opus);
+ lrtp_destroy_profile(lrtp, csrc);
+ lrtp_close(lrtp);
+ }
+
+ printf("========== Decode ==========\n");
+
+ { // Decode
+ struct lrtp_t *lrtp = lrtp_init(KEY, SSRC);
+
+ struct lrtp_profile_t *profile =
+ lrtp_create_profile(lrtp, PROFILE_OPUS, csrc,
+ //OPTION_RAW_PKG_SIZE, pkg_size,
+ OPTION_END);
+
+ int err;
+ OpusDecoder *opus = opus_decoder_create(FS, channels, &err);
+ printf("Opus create err: %d\n", err);
+
+ int idx = (sizeof(ms)/sizeof(size_t)) - 1;
+ printf("idx: %d\n", idx);
+
+ Audio audio;
+
+ char frame[16*1024];
+
+ int cnt = 0;
+ std::vector<std::string>::iterator i = packets.begin();
+ while(i != packets.end()) {
+ size_t packetsize = i->size();
+ const char *packet = i->data();
+ unsigned int ts;
+
+ printf("unpack sz: %d - %p\n", packetsize, packet);
+
+ lrtp_unpack(lrtp, packet, packetsize);
+ int ret;
+ while((ret = lrtp_dequeue_frame(lrtp, frame, sizeof(frame), &csrc, &ts))
+ != 0) {
+ size_t pcmsize = 16*1024;//ms[idx] / (48000 / FS);
+ short *pcm = new short[pcmsize * channels];
+ printf("pcmsize %d\n", pcmsize); fflush(stdout);
+ int res = opus_decode(opus, (const unsigned char*)frame, ret,
+ pcm, pcmsize, 0);
+
+ printf("Decompressed %d bytes\n", res);
+ // pcmsize = res * channels * sizeof(short);
+
+ audio.play((char *)pcm, res * channels * sizeof(short));
+
+ delete[] pcm;
+ }
+
+ i++;
+ }
+
+
+ /*
+
+ std::vector<std::string>::iterator i = packets.begin();
+ while(i != packets.end()) {
+ size_t packetsize = i->size();
+ printf("unpack sz: %d\n", packetsize);
+ const char *packet = i->data();
+ unsigned int ts;
+
+ framesize = sizeof(frame);
+
+ lrtp_unpack(lrtp, packet, packetsize, frame, &framesize, &csrc, &ts);
+ printf("Got %d bytes, csrc %d, ts: %d\n", framesize, csrc, ts);
+
+ size_t pcmsize = 16*1024;//ms[idx] / (48000 / FS);
+ short *pcm = new short[pcmsize * channels];
+ printf("pcmsize %d\n", pcmsize); fflush(stdout);
+ int res = opus_decode(opus, (const unsigned char*)frame, framesize,
+ pcm, pcmsize, 0);
+ framesize = sizeof(frame);
+
+ printf("Decompressed %d bytes\n", res);
+ // pcmsize = res * channels * sizeof(short);
+
+ audio.play((char *)pcm, res * channels * sizeof(short));
+
+ delete[] pcm;
+ i++;
+ }
+ */
+ opus_decoder_destroy(opus);
+ lrtp_destroy_profile(lrtp, csrc);
+ lrtp_close(lrtp);
+ }
+
+ return 0;
+}
diff --git a/test/test_raw.cc b/test/test_raw.cc
new file mode 100644
index 0000000..c3dcb71
--- /dev/null
+++ b/test/test_raw.cc
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * test_raw.cc
+ *
+ * Mon Sep 2 14:02:16 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <lrtp.h>
+
+#include <stdio.h>
+
+#define KEY "123456789012345678901234567890123456789012345678901234567890"
+#define SSRC 1234567890
+
+void dump(const char *title, const char *buf, size_t size)
+{
+ printf("%12s: ", title);
+ for(int i = 0; i < size; i++) {
+ if(i % 8 == 0) printf(" ");
+ printf("%02x ", (unsigned char)*buf++);
+ }
+ printf("\n");
+}
+
+int main()
+{
+ const char frame[] = "foo";
+
+ struct lrtp_t *lrtp = lrtp_init(KEY, SSRC);
+
+ unsigned int csrc = 42;
+ struct lrtp_profile_t *profile =
+ lrtp_create_profile(lrtp, PROFILE_RAW, csrc,
+ OPTION_RAW_PKG_SIZE, 4,
+ OPTION_END);
+ if(profile == NULL) {
+ printf("Could not create profile!\n");
+ return 1;
+ }
+
+ char packet[16*1024];
+ size_t size = sizeof(packet);
+
+ for(unsigned int ts = 0; ts < 8; ts++) {
+ int ret = 0;
+ ret = lrtp_enqueue_frame(profile, frame, sizeof(frame));
+ while( (ret = lrtp_pack(lrtp, packet, sizeof(packet))) != 0) {
+ dump("pkg", packet, ret);
+ }
+ }
+
+ lrtp_destroy_profile(lrtp, csrc);
+
+ lrtp_close(lrtp);
+
+ return 0;
+}
+
diff --git a/test/test_rtp.cc b/test/test_rtp.cc
new file mode 100644
index 0000000..b3ef80d
--- /dev/null
+++ b/test/test_rtp.cc
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * test_rtp.cc
+ *
+ * Mon Sep 2 14:02:16 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "../src/rtp.h"
+
+#include <stdio.h>
+
+void dump(RTP &rtp, const char *title)
+{
+ char buf[16 * 1024];
+
+ unsigned char *p = (unsigned char *)buf;
+ size_t s = rtp.packet(buf, sizeof(buf));
+
+ printf("%12s: ", title);
+ for(int i = 0; i < s; i++) {
+ if(i % 8 == 0) printf(" ");
+ printf("%02x ", *p++);
+ }
+ printf("\n");
+}
+
+int main()
+{
+ RTP rtp;
+ dump(rtp, "Clean");
+
+ rtp.setMarker(true);
+ dump(rtp, "mark");
+
+ char payload[] = { 0xff, 0xff, 0xff };
+ rtp.setPayload(payload, sizeof(payload));
+ dump(rtp, "Payload[6*f]");
+
+ rtp.setPadding(5);
+ dump(rtp, "Padding(5)");
+
+ rtp.setPadding(0);
+ dump(rtp, "Padding(0)");
+
+ rtp.setPadding(3);
+ dump(rtp, "Padding(3)");
+
+ rtp.setMarker(true);
+ dump(rtp, "mark");
+
+ rtp.setPayloadType(1);
+ dump(rtp, "pt(1)");
+
+ rtp.setPayloadType(0x7f);
+ dump(rtp, "pt(7f)");
+
+ rtp.setPayloadType(2);
+ dump(rtp, "pt(2)");
+
+ rtp.addCSrc(1);
+ dump(rtp, "CSrc[1]");
+
+ rtp.removeCSrc(1);
+ dump(rtp, "CSrc[-]");
+
+ rtp.addCSrc(2);
+ rtp.addCSrc(4);
+ dump(rtp, "CSrc[2,4]");
+
+ rtp.removeCSrc(2);
+ dump(rtp, "CSrc[2]");
+
+ rtp.setSeq(0x0102);
+ dump(rtp, "seq");
+
+ rtp.setTimestamp(0x03040506);
+ dump(rtp, "ts");
+
+ rtp.setSSrc(0x0708090a);
+ dump(rtp, "ssrc");
+
+ char buf[MAX_RTP_PACKET_SIZE];
+ size_t sz = rtp.packet(buf, sizeof(buf));
+
+ RTP rtp2;
+ rtp2.fromPacket(buf, sz);
+
+ dump(rtp2, "fromPacket");
+
+ return 0;
+}
+
diff --git a/test/test_srtp.cc b/test/test_srtp.cc
new file mode 100644
index 0000000..962c18f
--- /dev/null
+++ b/test/test_srtp.cc
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * test_srtp.cc
+ *
+ * Mon Sep 2 14:02:16 CEST 2013
+ * Copyright 2013 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of lrtp.
+ *
+ * lrtp is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * lrtp 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with lrtp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <stdio.h>
+
+#include "../src/rtp.h"
+#include "../src/srtp.h"
+
+#define KEY "123456789012345678901234567890123456789012345678901234567890"
+#define SSRC 1234567890
+
+void dump(const char *title, const char *buf, size_t size)
+{
+ printf("%12s: ", title);
+ for(int i = 0; i < size; i++) {
+ if(i % 8 == 0) printf(" ");
+ printf("%02x ", (unsigned char)*buf++);
+ }
+ printf("\n");
+}
+
+int main()
+{
+ RTP rtp;
+ rtp.setSSrc(SSRC);
+
+ char payload[] = { 0xde, 0xad, 0xbe, 0xef };
+ rtp.setPayload(payload, sizeof(payload));
+
+ char buf[MAX_RTP_PACKET_SIZE];
+ size_t sz = rtp.packet(buf, sizeof(buf));
+
+ dump("Vanilla", buf, sz);
+
+ {
+ SRTP srtp(KEY, rtp.SSrc());
+ sz = srtp.encrypt(buf, sz);
+ }
+
+ dump("Encrypted", buf, sz);
+
+ {
+ SRTP srtp(KEY, rtp.SSrc());
+ sz = srtp.decrypt(buf, sz);
+ }
+
+
+ dump("Decrypted", buf, sz);
+
+ printf("Compare:\n");
+ char buf0[MAX_RTP_PACKET_SIZE];
+ size_t sz0 = rtp.packet(buf0, sizeof(buf0));
+ if(sz0 != sz) printf("Sizes differ (%d %d)...\n", sz0, sz);
+ unsigned int sum = 0;
+ for(int i = 0; i < sz0; i++) {
+ sum += abs(buf0[i] - buf[i]);
+ }
+ if(sum) printf("NOT EQUAL! diff = %d\n", sum);
+ else printf("Vanilla == Decrypted\n");
+
+ return 0;
+}
+