]> sjero.net Git - linphone/commitdiff
Allow random selection of media ports without configured ranges.
authorGhislain MARY <ghislain.mary@belledonne-communications.com>
Thu, 11 Oct 2012 13:35:52 +0000 (15:35 +0200)
committerGhislain MARY <ghislain.mary@belledonne-communications.com>
Thu, 11 Oct 2012 13:39:12 +0000 (15:39 +0200)
coreapi/linphonecall.c
coreapi/linphonecore.c
coreapi/linphonecore.h
coreapi/private.h

index d0667251d9b6a4c754fb455b0ebe0afb718aea57..a930b1bed6bd8d5b7e78b4c00bbbb9ef03721d9c 100644 (file)
@@ -298,17 +298,35 @@ SalMediaDescription *create_local_media_description(LinphoneCore *lc, LinphoneCa
        return _create_local_media_description(lc,call,id,id);
 }
 
-static int find_port_offset(LinphoneCore *lc){
+static int find_port_offset(LinphoneCore *lc, SalStreamType type){
        int offset;
        MSList *elem;
-       int audio_port;
+       int tried_port;
+       int existing_port;
        bool_t already_used=FALSE;
        for(offset=0;offset<100;offset+=2){
-               audio_port=linphone_core_get_audio_port (lc)+offset;
+               switch (type) {
+                       default:
+                       case SalAudio:
+                               tried_port=linphone_core_get_audio_port (lc)+offset;
+                               break;
+                       case SalVideo:
+                               tried_port=linphone_core_get_video_port (lc)+offset;
+                               break;
+               }
                already_used=FALSE;
                for(elem=lc->calls;elem!=NULL;elem=elem->next){
                        LinphoneCall *call=(LinphoneCall*)elem->data;
-                       if (call->audio_port==audio_port) {
+                       switch (type) {
+                               default:
+                               case SalAudio:
+                                       existing_port = call->audio_port;
+                                       break;
+                               case SalVideo:
+                                       existing_port = call->video_port;
+                                       break;
+                       }
+                       if (existing_port==tried_port) {
                                already_used=TRUE;
                                break;
                        }
@@ -322,8 +340,54 @@ static int find_port_offset(LinphoneCore *lc){
        return offset;
 }
 
+static int select_random_port(LinphoneCore *lc, SalStreamType type) {
+       MSList *elem;
+       int nb_tries;
+       int tried_port = 0;
+       int existing_port = 0;
+       int min_port = 0, max_port = 0;
+       bool_t already_used = FALSE;
+
+       switch (type) {
+               default:
+               case SalAudio:
+                       linphone_core_get_audio_port_range(lc, &min_port, &max_port);
+                       break;
+               case SalVideo:
+                       linphone_core_get_video_port_range(lc, &min_port, &max_port);
+                       break;
+       }
+       tried_port = (rand() % (max_port - min_port) + min_port) & ~0x1;
+       if (tried_port < min_port) tried_port = min_port + 2;
+       for (nb_tries = 0; nb_tries < 100; nb_tries++) {
+               for (elem = lc->calls; elem != NULL; elem = elem->next) {
+                       LinphoneCall *call = (LinphoneCall *)elem->data;
+                       switch (type) {
+                               default:
+                               case SalAudio:
+                                       existing_port = call->audio_port;
+                                       break;
+                               case SalVideo:
+                                       existing_port = call->video_port;
+                                       break;
+                       }
+                       if (existing_port == tried_port) {
+                               already_used = TRUE;
+                               break;
+                       }
+               }
+               if (!already_used) break;
+       }
+       if (nb_tries == 100) {
+               ms_error("Could not find any free port!");
+               return -1;
+       }
+       return tried_port;
+}
+
 static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
        int port_offset;
+       int min_port, max_port;
        call->magic=linphone_call_magic;
        call->refcnt=1;
        call->state=LinphoneCallIdle;
@@ -333,10 +397,26 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from,
        call->log=linphone_call_log_new(call, from, to);
        call->owns_call_log=TRUE;
        linphone_core_notify_all_friends(call->core,LinphoneStatusOnThePhone);
-       port_offset=find_port_offset (call->core);
-       if (port_offset==-1) return;
-       call->audio_port=linphone_core_get_audio_port(call->core)+port_offset;
-       call->video_port=linphone_core_get_video_port(call->core)+port_offset;
+       linphone_core_get_audio_port_range(call->core, &min_port, &max_port);
+       if (min_port == max_port) {
+               /* Used fixed RTP audio port. */
+               port_offset=find_port_offset (call->core, SalAudio);
+               if (port_offset==-1) return;
+               call->audio_port=linphone_core_get_audio_port(call->core)+port_offset;
+       } else {
+               /* Select random RTP audio port in the specified range. */
+               call->audio_port = select_random_port(call->core, SalAudio);
+       }
+       linphone_core_get_video_port_range(call->core, &min_port, &max_port);
+       if (min_port == max_port) {
+               /* Used fixed RTP video port. */
+               port_offset=find_port_offset (call->core, SalVideo);
+               if (port_offset==-1) return;
+               call->video_port=linphone_core_get_video_port(call->core)+port_offset;
+       } else {
+               /* Select random RTP video port in the specified range. */
+               call->video_port = select_random_port(call->core, SalVideo);
+       }
        linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO], LINPHONE_CALL_STATS_AUDIO);
        linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO], LINPHONE_CALL_STATS_VIDEO);
 }
index 2936ca0bad98b79333712d391bea2c6c4a97ba91..db7a8ea7c9598b8e63083308df52a7b97b2b4ca2 100644 (file)
@@ -624,18 +624,29 @@ static void sip_config_read(LinphoneCore *lc)
 
 static void rtp_config_read(LinphoneCore *lc)
 {
-       int port;
+       int min_port, max_port;
        int jitt_comp;
        int nortp_timeout;
        bool_t rtp_no_xmit_on_audio_mute;
        bool_t adaptive_jitt_comp_enabled;
 
-       port=lp_config_get_int(lc->config,"rtp","audio_rtp_port",7078);
-       linphone_core_set_audio_port(lc,port);
+       if (lp_config_get_range(lc->config, "rtp", "audio_rtp_port", &min_port, &max_port, 7078, 7078) == TRUE) {
+               if (min_port <= 0) min_port = 1;
+               if (max_port > 65535) max_port = 65535;
+               linphone_core_set_audio_port_range(lc, min_port, max_port);
+       } else {
+               min_port = lp_config_get_int(lc->config, "rtp", "audio_rtp_port", 7078);
+               linphone_core_set_audio_port(lc, min_port);
+       }
 
-       port=lp_config_get_int(lc->config,"rtp","video_rtp_port",9078);
-       if (port==0) port=9078;
-       linphone_core_set_video_port(lc,port);
+       if (lp_config_get_range(lc->config, "rtp", "video_rtp_port", &min_port, &max_port, 9078, 9078) == TRUE) {
+               if (min_port <= 0) min_port = 1;
+               if (max_port > 65535) max_port = 65535;
+               linphone_core_set_video_port_range(lc, min_port, max_port);
+       } else {
+               min_port = lp_config_get_int(lc->config, "rtp", "video_rtp_port", 9078);
+               linphone_core_set_video_port(lc, min_port);
+       }
 
        jitt_comp=lp_config_get_int(lc->config,"rtp","audio_jitt_comp",60);
        linphone_core_set_audio_jittcomp(lc,jitt_comp);
@@ -1440,7 +1451,18 @@ int linphone_core_get_video_jittcomp(LinphoneCore *lc)
 **/
 int linphone_core_get_audio_port(const LinphoneCore *lc)
 {
-       return lc->rtp_conf.audio_rtp_port;
+       return lc->rtp_conf.audio_rtp_min_port;
+}
+
+/**
+ * Get the audio port range from which is randomly chosen the UDP port used for audio streaming.
+ *
+ * @ingroup network_parameters
+ */
+void linphone_core_get_audio_port_range(const LinphoneCore *lc, int *min_port, int *max_port)
+{
+       *min_port = lc->rtp_conf.audio_rtp_min_port;
+       *max_port = lc->rtp_conf.audio_rtp_max_port;
 }
 
 /**
@@ -1449,7 +1471,18 @@ int linphone_core_get_audio_port(const LinphoneCore *lc)
  * @ingroup network_parameters
 **/
 int linphone_core_get_video_port(const LinphoneCore *lc){
-       return lc->rtp_conf.video_rtp_port;
+       return lc->rtp_conf.video_rtp_min_port;
+}
+
+/**
+ * Get the video port range from which is randomly chosen the UDP port used for video streaming.
+ *
+ * @ingroup network_parameters
+ */
+void linphone_core_get_video_port_range(const LinphoneCore *lc, int *min_port, int *max_port)
+{
+       *min_port = lc->rtp_conf.video_rtp_min_port;
+       *max_port = lc->rtp_conf.video_rtp_max_port;
 }
 
 
@@ -1501,7 +1534,16 @@ void linphone_core_set_rtp_no_xmit_on_audio_mute(LinphoneCore *lc,bool_t rtp_no_
 **/
 void linphone_core_set_audio_port(LinphoneCore *lc, int port)
 {
-       lc->rtp_conf.audio_rtp_port=port;
+       lc->rtp_conf.audio_rtp_min_port=lc->rtp_conf.audio_rtp_max_port=port;
+}
+
+/**
+ * Sets the UDP port range from which to randomly select the port used for audio streaming.
+ */
+void linphone_core_set_audio_port_range(LinphoneCore *lc, int min_port, int max_port)
+{
+       lc->rtp_conf.audio_rtp_min_port=min_port;
+       lc->rtp_conf.audio_rtp_max_port=max_port;
 }
 
 /**
@@ -1510,7 +1552,16 @@ void linphone_core_set_audio_port(LinphoneCore *lc, int port)
  * @ingroup network_parameters
 **/
 void linphone_core_set_video_port(LinphoneCore *lc, int port){
-       lc->rtp_conf.video_rtp_port=port;
+       lc->rtp_conf.video_rtp_min_port=lc->rtp_conf.video_rtp_max_port=port;
+}
+
+/**
+ * Sets the UDP port range from which to randomly select the port used for video streaming.
+ */
+void linphone_core_set_video_port_range(LinphoneCore *lc, int min_port, int max_port)
+{
+       lc->rtp_conf.video_rtp_min_port=min_port;
+       lc->rtp_conf.video_rtp_max_port=max_port;
 }
 
 /**
@@ -4556,8 +4607,16 @@ void sip_config_uninit(LinphoneCore *lc)
 void rtp_config_uninit(LinphoneCore *lc)
 {
        rtp_config_t *config=&lc->rtp_conf;
-       lp_config_set_int(lc->config,"rtp","audio_rtp_port",config->audio_rtp_port);
-       lp_config_set_int(lc->config,"rtp","video_rtp_port",config->video_rtp_port);
+       if (config->audio_rtp_min_port == config->audio_rtp_max_port) {
+               lp_config_set_int(lc->config, "rtp", "audio_rtp_port", config->audio_rtp_min_port);
+       } else {
+               lp_config_set_range(lc->config, "rtp", "audio_rtp_port", config->audio_rtp_min_port, config->audio_rtp_max_port);
+       }
+       if (config->video_rtp_min_port == config->video_rtp_max_port) {
+               lp_config_set_int(lc->config, "rtp", "video_rtp_port", config->video_rtp_min_port);
+       } else {
+               lp_config_set_range(lc->config, "rtp", "video_rtp_port", config->video_rtp_min_port, config->video_rtp_max_port);
+       }
        lp_config_set_int(lc->config,"rtp","audio_jitt_comp",config->audio_jitt_comp);
        lp_config_set_int(lc->config,"rtp","video_jitt_comp",config->video_jitt_comp);
        lp_config_set_int(lc->config,"rtp","nortp_timeout",config->nortp_timeout);
index 0209a37745f230ebf5eb17bc192dc902f5081df9..1849c083b8d3de35845aa9e2259c5642b433617f 100644 (file)
@@ -1115,14 +1115,22 @@ void linphone_core_set_video_jittcomp(LinphoneCore *lc, int value);
 
 int linphone_core_get_audio_port(const LinphoneCore *lc);
 
+void linphone_core_get_audio_port_range(const LinphoneCore *lc, int *min_port, int *max_port);
+
 int linphone_core_get_video_port(const LinphoneCore *lc);
 
+void linphone_core_get_video_port_range(const LinphoneCore *lc, int *min_port, int *max_port);
+
 int linphone_core_get_nortp_timeout(const LinphoneCore *lc);
 
 void linphone_core_set_audio_port(LinphoneCore *lc, int port);
 
+void linphone_core_set_audio_port_range(LinphoneCore *lc, int min_port, int max_port);
+
 void linphone_core_set_video_port(LinphoneCore *lc, int port);
 
+void linphone_core_set_video_port_range(LinphoneCore *lc, int min_port, int max_port);
+
 void linphone_core_set_nortp_timeout(LinphoneCore *lc, int port);
 
 void linphone_core_set_use_info_for_dtmf(LinphoneCore *lc, bool_t use_info);
index 82ebf3633c468ea0fdd4929150cf07d16502557e..028b408f820a756d70d4a8a32f861fb26caa530a 100644 (file)
@@ -398,8 +398,10 @@ typedef struct sip_config
 
 typedef struct rtp_config
 {
-       int audio_rtp_port;
-       int video_rtp_port;
+       int audio_rtp_min_port;
+       int audio_rtp_max_port;
+       int video_rtp_min_port;
+       int video_rtp_max_port;
        int audio_jitt_comp;  /*jitter compensation*/
        int video_jitt_comp;  /*jitter compensation*/
        int nortp_timeout;