diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/compat.h | 3 | ||||
| -rw-r--r-- | src/lrtp.cc | 134 | ||||
| -rw-r--r-- | src/lrtp.h | 102 | ||||
| -rw-r--r-- | src/rtp_profile.h | 8 | ||||
| -rw-r--r-- | src/rtp_profile_amrwb.cc | 4 | ||||
| -rw-r--r-- | src/rtp_profile_jpeg.cc | 2 | ||||
| -rw-r--r-- | src/rtp_profile_l16.cc | 2 | ||||
| -rw-r--r-- | src/rtp_profile_opus.cc | 2 | ||||
| -rw-r--r-- | src/rtp_profile_raw.cc | 2 | ||||
| -rw-r--r-- | src/srtp.cc | 95 | ||||
| -rw-r--r-- | 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<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 @@ -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); +  } +} @@ -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__*/ | 
