summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2014-05-29 14:20:50 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2014-05-29 14:20:50 +0200
commit7b6e7703cdeeecae28552f589f249a6ab7f6c4d2 (patch)
tree2443c4b3f2e1cd0cb6cf5350b745b60e11eaf87f
parent1caa03670f91309e4237a37368c4df696d56a47d (diff)
Make typedef for framelists. Add some error handling in SRTP class. Make new instance protection mechanism for SRTP. Make some error handling in lrtp public API.
-rw-r--r--src/Makefile.am2
-rw-r--r--src/compat.h3
-rw-r--r--src/lrtp.cc134
-rw-r--r--src/lrtp.h102
-rw-r--r--src/rtp_profile.h8
-rw-r--r--src/rtp_profile_amrwb.cc4
-rw-r--r--src/rtp_profile_jpeg.cc2
-rw-r--r--src/rtp_profile_l16.cc2
-rw-r--r--src/rtp_profile_opus.cc2
-rw-r--r--src/rtp_profile_raw.cc2
-rw-r--r--src/srtp.cc95
-rw-r--r--src/srtp.h21
12 files changed, 264 insertions, 113 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 8dfcf71..ef3cfdb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,6 +6,7 @@ liblrtp_la_CXXFLAGS = $(SRTP_CXXFLAGS)
liblrtp_la_SOURCES = \
lrtp.cc \
+ error.cc \
rtp.cc \
srtp.cc \
rtp_profile_amrwb.cc \
@@ -21,6 +22,7 @@ include_HEADERS = \
EXTRA_DIST = \
compat.h \
+ error.h \
rtp_profile.h \
rtp_profile_amrwb.h \
rtp_profile_opus.h \
diff --git a/src/compat.h b/src/compat.h
index 70a6286..f4a7f20 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -29,9 +29,10 @@
#define __LRTP_COMPAT_H__
#ifdef WIN32
+#define _throw(...)
typedef signed int ssize_t;
#else
-
+#define _throw(fmt...) throw(fmt)
#endif
#endif/*__LRTP_COMPAT_H__*/
diff --git a/src/lrtp.cc b/src/lrtp.cc
index b627c95..71854f0 100644
--- a/src/lrtp.cc
+++ b/src/lrtp.cc
@@ -45,9 +45,21 @@
extern "C" {
#endif
+#define MAGIC 0x726c7074
+
+// Check if 'h' is a valid smtl handle and report/return error if not.
+#define CHECK_HANDLE(h) \
+ do { \
+ if(!h || h->magic != MAGIC) { \
+ return LRTP_MISSING_HANDLE; \
+ } \
+ } while(0)
+
typedef std::map<csrc_t, lrtp_profile_t *> profile_map_t;
struct lrtp_t {
+ unsigned int magic;
+
SRTP *srtp;
csrc_t ssrc;
unsigned short seq;
@@ -55,7 +67,7 @@ struct lrtp_t {
csrc_t next_csrc; // for frame iterator (see get_next_frame)
- std::list<outputframe_t *> framelist;
+ oframelist_t framelist;
};
typedef struct {
@@ -74,35 +86,71 @@ static const profile_class_t registered_profiles[] = {
};
EXPORT
-struct lrtp_t *lrtp_init(const char *key, unsigned int ssrc)
+struct lrtp_t *lrtp_init(enum lrtp_status_t *status,
+ const char *key, unsigned int ssrc)
{
- struct lrtp_t *lrtp = new struct lrtp_t;
+ if(status == NULL) return NULL;
- lrtp->srtp = new SRTP(key, ssrc);
+ struct lrtp_t *lrtp = new (std::nothrow) struct lrtp_t;
+ if(!lrtp) {
+ *status = LRTP_OUT_OF_MEMORY;
+ return NULL;
+ }
+
+ try {
+ lrtp->srtp = new SRTP(key, ssrc);
+ } catch(enum lrtp_status_t s) {
+ *status = s;
+ delete lrtp;
+ return NULL;
+ }
+
lrtp->ssrc = ssrc;
lrtp->seq = 0;
+ lrtp->magic = MAGIC;
+
return lrtp;
}
EXPORT
-void lrtp_close(struct lrtp_t *lrtp)
+enum lrtp_status_t lrtp_close(struct lrtp_t *lrtp)
{
- delete lrtp->srtp;
- delete lrtp;
+ CHECK_HANDLE(lrtp);
+
+ enum lrtp_status_t status = LRTP_OK;
+
+ try {
+ if(lrtp->srtp) delete lrtp->srtp;
+ lrtp->srtp = NULL;
+ } catch(enum lrtp_status_t s) {
+ status = s;
+ }
+
+ lrtp->magic = 0;
+
+ try {
+ delete lrtp;
+ } catch(enum lrtp_status_t s) {
+ status = s;
+ }
+
+ return status;
}
EXPORT
-int lrtp_create_profile(struct lrtp_t *lrtp,
- lrtp_profile_id_t profile_id,
- unsigned int csrc, ...)
+enum lrtp_status_t lrtp_create_profile(struct lrtp_t *lrtp,
+ lrtp_profile_id_t profile_id,
+ unsigned int csrc, ...)
{
+ CHECK_HANDLE(lrtp);
+
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 1;
+ return LRTP_CSRC_ALREADY_ACTIVE;
}
va_list ap;
@@ -122,7 +170,7 @@ int lrtp_create_profile(struct lrtp_t *lrtp,
if(!profile) {
printf("ERROR: Could not find profile [%d]\n", profile_id);
- return 1;
+ return LRTP_MISSING_PROFILE;
}
profile->id = profile_id;
@@ -131,32 +179,34 @@ int lrtp_create_profile(struct lrtp_t *lrtp,
lrtp->profiles[csrc] = profile;
- return 0;
+ return LRTP_OK;
}
EXPORT
-void lrtp_destroy_profile(struct lrtp_t *lrtp, unsigned int csrc)
+enum lrtp_status_t lrtp_destroy_profile(struct lrtp_t *lrtp, unsigned int csrc)
{
+ CHECK_HANDLE(lrtp);
+
if(lrtp->profiles.find(csrc) == lrtp->profiles.end()) {
- // TODO: CSRC not found
- printf("ERROR: CSRC not found\n");
- return;
+ return LRTP_MISSING_CSRC;
}
struct lrtp_profile_t *profile = lrtp->profiles[csrc];
profile->destroy(profile);
lrtp->profiles.erase(csrc);
+
+ return LRTP_OK;
}
EXPORT
-int lrtp_enqueue_frame(struct lrtp_t *lrtp, unsigned int csrc,
- char *data, size_t size,
- unsigned long int timestamp)
+enum lrtp_status_t lrtp_enqueue_frame(struct lrtp_t *lrtp, unsigned int csrc,
+ char *data, size_t size,
+ unsigned long int timestamp)
{
+ CHECK_HANDLE(lrtp);
+
if(lrtp->profiles.find(csrc) == lrtp->profiles.end()) {
- // TODO: CSRC not found
- printf("ERROR: CSRC not found\n");
- return 1;
+ return LRTP_MISSING_CSRC;
}
struct lrtp_profile_t *profile = lrtp->profiles[csrc];
@@ -171,7 +221,7 @@ int lrtp_enqueue_frame(struct lrtp_t *lrtp, unsigned int csrc,
profile->framelist.push_back(frame);
- return 0;
+ return LRTP_OK;
}
// Assume we have at least one csrc in the list
@@ -219,6 +269,8 @@ static lrtp_profile_t *get_next_profile(struct lrtp_t *lrtp)
EXPORT
int lrtp_pack(struct lrtp_t *lrtp, char *packet, size_t maxsize)
{
+ CHECK_HANDLE(lrtp);
+
//if(!profile) return PACK_MISSING_PROFILE;
// TODO: Check profile magic word
@@ -271,6 +323,8 @@ int lrtp_dequeue_frame(struct lrtp_t *lrtp,
char *frame, size_t maxsize,
unsigned int *csrc, unsigned int *ts)
{
+ CHECK_HANDLE(lrtp);
+
if(lrtp->framelist.size() == 0) return 0;
outputframe_t *f = lrtp->framelist.front();
@@ -297,11 +351,10 @@ int lrtp_dequeue_frame(struct lrtp_t *lrtp,
}
EXPORT
-int lrtp_unpack(struct lrtp_t *lrtp, const char *packet, size_t size)
+enum lrtp_status_t lrtp_unpack(struct lrtp_t *lrtp,
+ const char *packet, size_t size)
{
- if(!lrtp) return -UNPACK_MISSING_HANDLE;
-
- // TODO: Check lrtp magic word
+ CHECK_HANDLE(lrtp);
char *pkg = (char*)malloc(size);
memcpy(pkg, packet, size);
@@ -309,12 +362,11 @@ int lrtp_unpack(struct lrtp_t *lrtp, const char *packet, size_t size)
int ret = 0;
#ifndef SKIP_SRTP
- ret = lrtp->srtp->decrypt(pkg, size);
-
- if(ret < 0) {
- printf("lrtp_unpack::decrypt error: %d\n", ret);
+ try {
+ ret = lrtp->srtp->decrypt(pkg, size);
+ } catch(enum lrtp_status_t s) {
free(pkg);
- return -1;
+ return s;
}
size = ret;
@@ -325,11 +377,11 @@ int lrtp_unpack(struct lrtp_t *lrtp, const char *packet, size_t size)
std::list<csrc_t> csrcs = rtp.getCSrcs();
if(csrcs.size() == 0) {
free(pkg);
- return -UNPACK_MISSING_CSRC;
+ return LRTP_MISSING_CSRC;
}
if(csrcs.size() > 1) {
free(pkg);
- return -UNPACK_TOO_MANY_CSRCS;
+ return LRTP_TOO_MANY_CSRCS;
}
csrc_t csrc = *csrcs.begin();
@@ -337,22 +389,22 @@ int lrtp_unpack(struct lrtp_t *lrtp, const char *packet, size_t size)
struct lrtp_profile_t *profile = NULL;
if(lrtp->profiles.find(csrc) == lrtp->profiles.end()) {
free(pkg);
- return -UNPACK_MISSING_PROFILE;
+ return LRTP_MISSING_PROFILE;
}
profile = lrtp->profiles[csrc];
- std::list<outputframe_t*> framelist;
+ oframelist_t framelist;
ret = profile->unpack(profile, rtp, framelist);
if(ret < 0) {
printf("lrtp_unpack::Profile unpack failed: %d\n", ret);
free(pkg);
- return -1;
+ return (enum lrtp_status_t)ret;
}
// Make sure all frames in the list have the correct csrc.
- std::list<outputframe_t*>::iterator fi = framelist.begin();
+ oframelist_t::iterator fi = framelist.begin();
while(fi != framelist.end()) {
(*fi)->csrc = csrc;
fi++;
@@ -362,9 +414,11 @@ int lrtp_unpack(struct lrtp_t *lrtp, const char *packet, size_t size)
free(pkg);
- return ret;
+ return LRTP_OK;
}
+// NOTE: lrtp_strerror implemented in error.cc
+
#ifdef __cplusplus
}
#endif
diff --git a/src/lrtp.h b/src/lrtp.h
index b68205a..ec654b9 100644
--- a/src/lrtp.h
+++ b/src/lrtp.h
@@ -48,23 +48,76 @@ extern "C" {
#include "lrtp_profiles.h"
+/**
+ * Status return codes. Note that all of these values (except @ref ERROR_OK)
+ * are negative. The reason for this is that many functions return a size or
+ * a negative integer (one of these values) in case of error.
+ */
+enum lrtp_status_t {
+ LRTP_OK = 0, ///< All went well.
+ LRTP_UNKNOWN = -1, ///< An unknown error occurred.
+ LRTP_MISSING_HANDLE = -2, ///< The handle is corrupted or NULL.
+ LRTP_OUT_OF_MEMORY = -3, ///< Out of memory error.
+
+ // SRTP errors
+ LRTP_SRTP_FAIL = -4, ///< unspecified failure
+ LRTP_SRTP_BAD_PARAM = -5, ///< unsupported parameter
+ LRTP_SRTP_ALLOC_FAIL = -6, ///< couldn't allocate memory
+ LRTP_SRTP_DEALLOC_FAIL = -7, ///< couldn't deallocate properly
+ LRTP_SRTP_INIT_FAIL = -8, ///< couldn't initialize
+ LRTP_SRTP_TERMINUS = -9, ///< can't process as much data as requested
+ LRTP_SRTP_AUTH_FAIL = -10, ///< authentication failure
+ LRTP_SRTP_CIPHER_FAIL = -11, ///< cipher failure
+ LRTP_SRTP_REPLAY_FAIL = -12, ///< replay check failed (bad index)
+ LRTP_SRTP_REPLAY_OLD = -13, ///< replay check failed (index too old)
+ LRTP_SRTP_ALGO_FAIL = -14, ///< algorithm failed test routine
+ LRTP_SRTP_NO_SUCH_OP = -15, ///< unsupported operation
+ LRTP_SRTP_NO_CTX = -16, ///< no appropriate context found
+ LRTP_SRTP_CANT_CHECK = -17, ///< unable to perform desired validation
+ LRTP_SRTP_KEY_EXPIRED = -18, ///< can't use key any more
+ LRTP_SRTP_SOCKET_ERR = -19, ///< error in use of socket
+ LRTP_SRTP_SIGNAL_ERR = -20, ///< error in use POSIX signals
+ LRTP_SRTP_NONCE_BAD = -21, ///< nonce check failed
+ LRTP_SRTP_READ_FAIL = -22, ///< couldn't read data
+ LRTP_SRTP_WRITE_FAIL = -23, ///< couldn't write data
+ LRTP_SRTP_PARSE_ERR = -24, ///< error pasring data
+ LRTP_SRTP_ENCODE_ERR = -25, ///< error encoding data
+ LRTP_SRTP_SEMAPHORE_ERR = -26, ///< error while using semaphores
+ LRTP_SRTP_PFKEY_ERR = -27, ///< error while using pfkey
+
+ LRTP_MISSING_CSRC = -28, ///< Invalid CSrc
+
+ LRTP_TOO_MANY_CSRCS = -29, ///< Exactly one csrc must be present.
+ LRTP_MISSING_PROFILE = -30, ///< CSrc from packet could not be connected with a profile..
+ LRTP_UNPACK_ERROR = -31, ///< Error unpacking RTP pakcet.
+ LRTP_BUFFER_TOO_SMALL = -32, ///< Supplied buffer was not big enough.
+
+ LRTP_CSRC_ALREADY_ACTIVE= -33, ///< CSrc already in session list.
+};
+
struct lrtp_t;
/**
* Initialise lrtp.
+ * @param status A pointer to the function status code. If the function returns
+ * NULL this status code will indicate what went wrong. If status is NULL it
+ * will simply be ignored.
* @param key The key to be use in this session.
* @param ssrc The secure source to be used in the session.
* @return Returns the handle to the newly created session.
*/
EXPORT
-struct lrtp_t *lrtp_init(const char *key, unsigned int ssrc);
+struct lrtp_t *lrtp_init(enum lrtp_status_t *status,
+ const char *key, unsigned int ssrc);
/**
* Close session.
* @param lrtp The lrtp context handle to be closed.
+ * @return LRTP_OK on success, or LRTP_MISSING_HANDLE if handle was broken or
+ * NULL.
*/
EXPORT
-void lrtp_close(struct lrtp_t *lrtp);
+enum lrtp_status_t lrtp_close(struct lrtp_t *lrtp);
/**
* Create a new profile to be used in the lrtp_enqueue_frame and
@@ -75,34 +128,28 @@ void lrtp_close(struct lrtp_t *lrtp);
* @param profile_id See lrtp_profiles.h for possible values.
* @param csrc The csrc to be connected with this profile.
* @param ... Options for the profile. See lrtp_profiles.h for possible values.
- * @return 0 on success, 1 on error.
+ * @return TODO: TBD
*/
EXPORT
-int lrtp_create_profile(struct lrtp_t *lrtp,
- lrtp_profile_id_t profile_id,
- unsigned int csrc, ...);
-
+enum lrtp_status_t lrtp_create_profile(struct lrtp_t *lrtp,
+ lrtp_profile_id_t profile_id,
+ unsigned int csrc, ...);
+
/**
* Free all resources connected with a profile.
* @param lrtp The lrtp context handle.
* @param csrc The csrc of the profile to be freed.
+ * @return TODO: TBD
*/
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;
+enum lrtp_status_t lrtp_destroy_profile(struct lrtp_t *lrtp, unsigned int csrc);
/**
* 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 TODO: TBD
* @return 0 on success, or a negative error code on error.
* WARNING: The frame pointer cannot be freed or overwritten until all frame
* data has been handled by lrtp_pack(). Either call lrtp_pack() until it
@@ -111,9 +158,9 @@ typedef enum {
* See lrtp_profiles.h for further details.
*/
EXPORT
-int lrtp_enqueue_frame(struct lrtp_t *lrtp, unsigned int csrc,
- char *framedate, size_t framesize,
- unsigned long int timestamp);
+enum lrtp_status_t lrtp_enqueue_frame(struct lrtp_t *lrtp, unsigned int csrc,
+ char *framedate, size_t framesize,
+ unsigned long int timestamp);
/**
* Handle frame data from the frame queue and create at most a single sRTP
@@ -127,16 +174,6 @@ int lrtp_enqueue_frame(struct lrtp_t *lrtp, unsigned int csrc,
*/
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 profile..
-} lrtp_unpack_status_t;
-
/**
* Dequeue a frame from the frame queue.
* @param lrtp The lrtp context handle.
@@ -144,7 +181,7 @@ typedef enum {
* @param maxsize The size of the char buffer stored in 'frame'.
* @param csrc The csrc of the dequeued frame is returned in this pointer.
* @param ts The timestamp of the dequeued frame is returned in this pointer.
- * @return The size of the returned frame. -1 on error.
+ * @return The size of the returned frame or a negative error code on error.
*/
EXPORT
int lrtp_dequeue_frame(struct lrtp_t *lrtp,
@@ -157,10 +194,11 @@ int lrtp_dequeue_frame(struct lrtp_t *lrtp,
* @param lrtp The lrtp context handle.
* @param packet The packet data.
* @param size The size of the packet.
- * @return 0 on success, error code (negative integer) on error.
+ * @return TODO: TBD
*/
EXPORT
-int lrtp_unpack(struct lrtp_t *lrtp, const char *packet, size_t size);
+enum lrtp_status_t lrtp_unpack(struct lrtp_t *lrtp,
+ const char *packet, size_t size);
#ifdef __cplusplus
}
diff --git a/src/rtp_profile.h b/src/rtp_profile.h
index bfb7572..6865adb 100644
--- a/src/rtp_profile.h
+++ b/src/rtp_profile.h
@@ -42,6 +42,8 @@ typedef struct {
unsigned long int timestamp;
} inputframe_t;
+typedef std::list<inputframe_t *> iframelist_t;
+
typedef struct {
char *data;
size_t size;
@@ -52,13 +54,15 @@ typedef struct {
} outputframe_t;
+typedef std::list<outputframe_t *> oframelist_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;
+ iframelist_t framelist;
// Profile functions:
/**
@@ -78,7 +82,7 @@ struct lrtp_profile_t {
int (*unpack)(struct lrtp_profile_t *profile,
const RTP &rtp,
- std::list<outputframe_t *> &framelist);
+ oframelist_t &framelist);
void (*destroy)(struct lrtp_profile_t *profile);
diff --git a/src/rtp_profile_amrwb.cc b/src/rtp_profile_amrwb.cc
index 94084cf..7b02c11 100644
--- a/src/rtp_profile_amrwb.cc
+++ b/src/rtp_profile_amrwb.cc
@@ -222,7 +222,7 @@ int profile_amrwb_pack(struct lrtp_profile_t *profile,
int profile_amrwb_unpack(struct lrtp_profile_t *profile,
const RTP &rtp,
- std::list<outputframe_t *> &framelist)
+ oframelist_t &framelist)
{
//struct lrtp_profile_amrwb_t *p = (struct lrtp_profile_amrwb_t *)profile;
@@ -244,7 +244,7 @@ int profile_amrwb_unpack(struct lrtp_profile_t *profile,
char CMR = payload[0];
if(CMR != 15) {
printf("CMR not 15\n");
- return UNPACK_ERROR;
+ return LRTP_UNPACK_ERROR;
}
// TODO: What to do if there are 0 frames (and therefore no header to set the
diff --git a/src/rtp_profile_jpeg.cc b/src/rtp_profile_jpeg.cc
index 9ce667f..c597fe6 100644
--- a/src/rtp_profile_jpeg.cc
+++ b/src/rtp_profile_jpeg.cc
@@ -1587,7 +1587,7 @@ int profile_jpeg_pack(struct lrtp_profile_t *profile,
int profile_jpeg_unpack(struct lrtp_profile_t *profile,
const RTP &rtp,
- std::list<outputframe_t *> &framelist)
+ oframelist_t &framelist)
{
struct lrtp_profile_jpeg_t *p = (struct lrtp_profile_jpeg_t *)profile;
diff --git a/src/rtp_profile_l16.cc b/src/rtp_profile_l16.cc
index 379df1c..f57ba4b 100644
--- a/src/rtp_profile_l16.cc
+++ b/src/rtp_profile_l16.cc
@@ -79,7 +79,7 @@ int profile_l16_pack(struct lrtp_profile_t *profile,
int profile_l16_unpack(struct lrtp_profile_t *profile,
const RTP &rtp,
- std::list<outputframe_t *> &framelist)
+ oframelist_t &framelist)
{
struct lrtp_profile_l16_t *p = (struct lrtp_profile_l16_t *)profile;
diff --git a/src/rtp_profile_opus.cc b/src/rtp_profile_opus.cc
index 3fc0de9..af0b2cc 100644
--- a/src/rtp_profile_opus.cc
+++ b/src/rtp_profile_opus.cc
@@ -142,7 +142,7 @@ int profile_opus_pack(struct lrtp_profile_t *profile,
int profile_opus_unpack(struct lrtp_profile_t *profile,
const RTP &rtp,
- std::list<outputframe_t *> &framelist)
+ oframelist_t &framelist)
{
//struct lrtp_profile_opus_t *p = (struct lrtp_profile_opus_t *)profile;
diff --git a/src/rtp_profile_raw.cc b/src/rtp_profile_raw.cc
index 25cc297..0a36c79 100644
--- a/src/rtp_profile_raw.cc
+++ b/src/rtp_profile_raw.cc
@@ -55,7 +55,7 @@ int profile_raw_pack(struct lrtp_profile_t *profile,
int profile_raw_unpack(struct lrtp_profile_t *profile,
const RTP &rtp,
- std::list<outputframe_t *> &framelist)
+ oframelist_t &framelist)
{
//struct lrtp_profile_raw_t *p = (struct lrtp_profile_raw_t *)profile;
diff --git a/src/srtp.cc b/src/srtp.cc
index 596949d..36f3148 100644
--- a/src/srtp.cc
+++ b/src/srtp.cc
@@ -35,6 +35,38 @@
#include "asc2bin.h"
+// This macro translates srtp status codes into exceptions:
+#define SRTP_THROW(s) \
+ do { \
+ switch(s) { \
+ case err_status_fail: throw LRTP_SRTP_FAIL; \
+ case err_status_bad_param: throw LRTP_SRTP_BAD_PARAM; \
+ case err_status_alloc_fail: throw LRTP_SRTP_ALLOC_FAIL; \
+ case err_status_dealloc_fail: throw LRTP_SRTP_DEALLOC_FAIL; \
+ case err_status_init_fail: throw LRTP_SRTP_INIT_FAIL; \
+ case err_status_terminus: throw LRTP_SRTP_TERMINUS; \
+ case err_status_auth_fail: throw LRTP_SRTP_AUTH_FAIL; \
+ case err_status_cipher_fail: throw LRTP_SRTP_CIPHER_FAIL; \
+ case err_status_replay_fail: throw LRTP_SRTP_REPLAY_FAIL; \
+ case err_status_replay_old: throw LRTP_SRTP_REPLAY_OLD; \
+ case err_status_algo_fail: throw LRTP_SRTP_ALGO_FAIL; \
+ case err_status_no_such_op: throw LRTP_SRTP_NO_SUCH_OP; \
+ case err_status_no_ctx: throw LRTP_SRTP_NO_CTX; \
+ case err_status_cant_check: throw LRTP_SRTP_CANT_CHECK; \
+ case err_status_key_expired: throw LRTP_SRTP_KEY_EXPIRED; \
+ case err_status_socket_err: throw LRTP_SRTP_SOCKET_ERR; \
+ case err_status_signal_err: throw LRTP_SRTP_SIGNAL_ERR; \
+ case err_status_nonce_bad: throw LRTP_SRTP_NONCE_BAD; \
+ case err_status_read_fail: throw LRTP_SRTP_READ_FAIL; \
+ case err_status_write_fail: throw LRTP_SRTP_WRITE_FAIL; \
+ case err_status_parse_err: throw LRTP_SRTP_PARSE_ERR; \
+ case err_status_encode_err: throw LRTP_SRTP_ENCODE_ERR; \
+ case err_status_semaphore_err: throw LRTP_SRTP_SEMAPHORE_ERR; \
+ case err_status_pfkey_err: throw LRTP_SRTP_PFKEY_ERR; \
+ default: throw LRTP_SRTP_FAIL; \
+ } \
+ } while(0)
+
struct SRTP::prv {
char *key;
size_t key_len;
@@ -45,24 +77,15 @@ struct SRTP::prv {
srtp_policy_t policy;
};
-static bool is_initialised = false;
-
SRTP::SRTP(std::string key, unsigned int ssrc)
+ _throw(enum lrtp_status_t)
{
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;
+ if(!prv) throw LRTP_OUT_OF_MEMORY;
prv->ssrc = ssrc;
@@ -70,16 +93,10 @@ SRTP::SRTP(std::string key, unsigned int ssrc)
setupPolicy(true, true);
status = srtp_create(&prv->session, &prv->policy);
- if(status != err_status_ok) {
- // TODO: Error handling
- printf("srtp_create %d\n", status);
- }
+ if(status != err_status_ok) SRTP_THROW(status);
status = srtp_add_stream(prv->session, &prv->policy);
- if(status != err_status_ok) {
- // TODO: Error handling
- printf("srtp_add_stream %d\n", status);
- }
+ if(status != err_status_ok) SRTP_THROW(status);
}
SRTP::~SRTP()
@@ -96,14 +113,6 @@ SRTP::~SRTP()
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;
@@ -111,6 +120,7 @@ SRTP::~SRTP()
}
void SRTP::setupKey(const std::string &key)
+ _throw(enum lrtp_status_t)
{
prv->key = (char *)calloc(MASTER_KEY_LEN, 1);
prv->key_len = MASTER_KEY_LEN;
@@ -128,6 +138,7 @@ void SRTP::setupKey(const std::string &key)
}
void SRTP::setupPolicy(bool confidentiality, bool authentication)
+ _throw(enum lrtp_status_t)
{
#ifndef USE_CRYPTO
confidentiality = authentication = false;
@@ -176,6 +187,7 @@ void SRTP::setupPolicy(bool confidentiality, bool authentication)
}
int SRTP::encrypt(char *packet, size_t size)
+ _throw(enum lrtp_status_t)
{
int sz = size;
err_status_t status = srtp_protect(prv->session, packet, &sz);
@@ -188,6 +200,7 @@ int SRTP::encrypt(char *packet, size_t size)
}
int SRTP::decrypt(char *packet, size_t size)
+ _throw(enum lrtp_status_t)
{
int sz = size;
err_status_t status = srtp_unprotect(prv->session, packet, &sz);
@@ -228,3 +241,31 @@ int SRTP::decrypt(char *packet, size_t size)
return sz;
}
+
+// Global SRTP instance reference counter
+static int active_srtp_instances = 0;
+
+SRTP::SRTPInstance::SRTPInstance()
+ _throw(enum lrtp_status_t)
+{
+ err_status_t status;
+
+ if(active_srtp_instances == 0) {
+ status = srtp_init();
+ active_srtp_instances++;
+ if(status != err_status_ok) SRTP_THROW(status);
+ }
+}
+
+SRTP::SRTPInstance::~SRTPInstance()
+ _throw(enum lrtp_status_t)
+{
+ err_status_t status;
+
+ active_srtp_instances--;
+
+ if(active_srtp_instances == 0) {
+ status = srtp_shutdown();
+ if(status != err_status_ok) SRTP_THROW(status);
+ }
+}
diff --git a/src/srtp.h b/src/srtp.h
index 3d8b697..66197bb 100644
--- a/src/srtp.h
+++ b/src/srtp.h
@@ -30,25 +30,36 @@
#include <string>
+#include "lrtp.h"
#include "rtp.h"
+#include "compat.h"
#define MAX_KEY_LEN 64
#define MASTER_KEY_LEN 30
class SRTP {
public:
- SRTP(std::string key, unsigned int ssrc);
+ SRTP(std::string key, unsigned int ssrc) _throw(enum lrtp_status_t);
~SRTP();
- int encrypt(char *packet, size_t size);
- int decrypt(char *packet, size_t size);
+ int encrypt(char *packet, size_t size) _throw(enum lrtp_status_t);
+ int decrypt(char *packet, size_t size) _throw(enum lrtp_status_t);
private:
+ class SRTPInstance {
+ public:
+ SRTPInstance() _throw(enum lrtp_status_t);
+ ~SRTPInstance() _throw(enum lrtp_status_t);
+ };
+
+ SRTPInstance instance;
+
struct prv;
struct prv *prv;
- void setupKey(const std::string &key);
- void setupPolicy(bool confidentiality, bool authentication);
+ void setupKey(const std::string &key) _throw(enum lrtp_status_t);
+ void setupPolicy(bool confidentiality, bool authentication)
+ _throw(enum lrtp_status_t);
};
#endif/*__LRTP_SRTP_H__*/