From 7b6e7703cdeeecae28552f589f249a6ab7f6c4d2 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 29 May 2014 14:20:50 +0200 Subject: 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. --- src/Makefile.am | 2 + src/compat.h | 3 +- src/lrtp.cc | 134 +++++++++++++++++++++++++++++++++-------------- src/lrtp.h | 102 +++++++++++++++++++++++++----------- src/rtp_profile.h | 8 ++- src/rtp_profile_amrwb.cc | 4 +- src/rtp_profile_jpeg.cc | 2 +- src/rtp_profile_l16.cc | 2 +- src/rtp_profile_opus.cc | 2 +- src/rtp_profile_raw.cc | 2 +- src/srtp.cc | 95 +++++++++++++++++++++++---------- src/srtp.h | 21 ++++++-- 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 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 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 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 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::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 iframelist_t; + typedef struct { char *data; size_t size; @@ -52,13 +54,15 @@ typedef struct { } outputframe_t; +typedef std::list 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 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 &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 &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 &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 &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 &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 &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 +#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__*/ -- cgit v1.2.3