]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Extract a useful routine from the softmix bridge technology.
authorRichard Mudgett <rmudgett@digium.com>
Fri, 21 Jun 2013 22:39:27 +0000 (22:39 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Fri, 21 Jun 2013 22:39:27 +0000 (22:39 +0000)
* Extract a useful routine from the softmix bridge technology for other
technologies.  Make other technologies use it if they can.

* Made native and 1-1 bridges write to all parties if the bridge channel
writing the frame into the bridge is NULL.  Softmix will also do the same
for frame types that make sense.

* Tweak the bridge write routine return value meaning and adjust the
bridge technologies to match.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@392514 65c4cc65-6c06-0410-ace0-fbb531ad65f3

bridges/bridge_holding.c
bridges/bridge_native_rtp.c
bridges/bridge_simple.c
bridges/bridge_softmix.c
include/asterisk/bridging.h
include/asterisk/bridging_technology.h
main/bridging.c

index fe0a7303fc2a478a15c571bb7280a4f0a10c38e1..bd288c9bd1e82fc2a6c820419e2cfc7f92ff622e 100644 (file)
@@ -255,27 +255,25 @@ static void holding_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_ch
 
 static int holding_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 {
-       struct ast_bridge_channel *cur;
-       struct holding_channel *hc = bridge_channel->tech_pvt;
+       struct holding_channel *hc = bridge_channel ? bridge_channel->tech_pvt : NULL;
 
        /* If there is no tech_pvt, then the channel failed to allocate one when it joined and is borked. Don't listen to him. */
        if (!hc) {
-               return -1;
+               /* "Accept" the frame and discard it. */
+               return 0;
        }
 
        /* If we aren't an announcer, we never have any business writing anything. */
        if (!ast_test_flag(&hc->holding_roles, HOLDING_ROLE_ANNOUNCER)) {
-               return -1;
+               /* "Accept" the frame and discard it. */
+               return 0;
        }
 
-       /* Ok, so we are the announcer and there are one or more people available to receive our writes. Let's do it. */
-       AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
-               if (bridge_channel == cur || !cur->tech_pvt) {
-                       continue;
-               }
-
-               ast_bridge_channel_queue_frame(cur, frame);
-       }
+       /*
+        * Ok, so we are the announcer.  Write the frame to all other
+        * channels if any.
+        */
+       ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
 
        return 0;
 }
index 120a509c1cefbb7e598b4881189eb46d94849fb1..4436f706af0ddb9daf918ae3145e781c9bcdcb2f 100644 (file)
@@ -389,16 +389,7 @@ static void native_rtp_bridge_leave(struct ast_bridge *bridge, struct ast_bridge
 
 static int native_rtp_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 {
-       struct ast_bridge_channel *other = ast_bridge_channel_peer(bridge_channel);
-
-       if (!other) {
-               return -1;
-       }
-
-       /* The bridging core takes care of freeing the passed in frame. */
-       ast_bridge_channel_queue_frame(other, frame);
-
-       return 0;
+       return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
 }
 
 static struct ast_bridge_technology native_rtp_bridge = {
index 3e53b31c0e1849b7f361927228954c54e6e8d921..49e3a35ace1bfe5e72a204b0fd718f6b0caab00e 100644 (file)
@@ -68,18 +68,7 @@ static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_chann
 
 static int simple_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 {
-       struct ast_bridge_channel *other;
-
-       /* Find the channel we actually want to write to */
-       other = ast_bridge_channel_peer(bridge_channel);
-       if (!other) {
-               return -1;
-       }
-
-       /* The bridging core takes care of freeing the passed in frame. */
-       ast_bridge_channel_queue_frame(other, frame);
-
-       return 0;
+       return ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
 }
 
 static struct ast_bridge_technology simple_bridge = {
index 8698ff4511d41648da8ebd6b20aa3e863a4ddfe9..cf891c6687bbe5c92675dac22e3131f19b7fade5 100644 (file)
@@ -445,29 +445,6 @@ static void softmix_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_ch
        ast_free(sc);
 }
 
-/*!
- * \internal
- * \brief Pass the given frame to everyone else.
- * \since 12.0.0
- *
- * \param bridge What bridge to distribute frame.
- * \param bridge_channel Channel to optionally not pass frame to. (NULL to pass to everyone)
- * \param frame Frame to pass.
- *
- * \return Nothing
- */
-static void softmix_pass_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
-{
-       struct ast_bridge_channel *cur;
-
-       AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
-               if (cur == bridge_channel) {
-                       continue;
-               }
-               ast_bridge_channel_queue_frame(cur, frame);
-       }
-}
-
 static void softmix_pass_video_top_priority(struct ast_bridge *bridge, struct ast_frame *frame)
 {
        struct ast_bridge_channel *cur;
@@ -507,7 +484,7 @@ static void softmix_bridge_write_video(struct ast_bridge *bridge, struct ast_bri
                video_src_priority = ast_bridge_is_video_src(bridge, bridge_channel->chan);
                if (video_src_priority == 1) {
                        /* Pass to me and everyone else. */
-                       softmix_pass_everyone_else(bridge, NULL, frame);
+                       ast_bridge_queue_everyone_else(bridge, NULL, frame);
                }
                break;
        case AST_BRIDGE_VIDEO_MODE_TALKER_SRC:
@@ -522,7 +499,7 @@ static void softmix_bridge_write_video(struct ast_bridge *bridge, struct ast_bri
                        int num_src = ast_bridge_number_video_src(bridge);
                        int echo = num_src > 1 ? 0 : 1;
 
-                       softmix_pass_everyone_else(bridge, echo ? NULL : bridge_channel, frame);
+                       ast_bridge_queue_everyone_else(bridge, echo ? NULL : bridge_channel, frame);
                } else if (video_src_priority == 2) {
                        softmix_pass_video_top_priority(bridge, frame);
                }
@@ -612,12 +589,14 @@ static void softmix_bridge_write_voice(struct ast_bridge *bridge, struct ast_bri
  * \param bridge_channel Which channel is writing the frame.
  * \param frame What is being written.
  *
- * \return Nothing
+ * \retval 0 Frame accepted into the bridge.
+ * \retval -1 Frame needs to be deferred.
  */
-static void softmix_bridge_write_control(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
+static int softmix_bridge_write_control(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
 {
 /* BUGBUG need to look at channel roles to determine what to do with control frame. */
        /*! \todo BUGBUG softmix_bridge_write_control() not written */
+       return 0;
 }
 
 /*!
@@ -629,8 +608,8 @@ static void softmix_bridge_write_control(struct ast_bridge *bridge, struct ast_b
  * \param bridge_channel Which channel is writing the frame.
  * \param frame What is being written.
  *
- * \retval 0 on success
- * \retval -1 on failure
+ * \retval 0 Frame accepted into the bridge.
+ * \retval -1 Frame needs to be deferred.
  *
  * \note On entry, bridge is already locked.
  */
@@ -638,30 +617,35 @@ static int softmix_bridge_write(struct ast_bridge *bridge, struct ast_bridge_cha
 {
        int res = 0;
 
-       if (!bridge->tech_pvt || !bridge_channel->tech_pvt) {
-               return -1;
+       if (!bridge->tech_pvt || (bridge_channel && !bridge_channel->tech_pvt)) {
+               /* "Accept" the frame and discard it. */
+               return 0;
        }
 
        switch (frame->frametype) {
        case AST_FRAME_DTMF_BEGIN:
        case AST_FRAME_DTMF_END:
-               softmix_pass_everyone_else(bridge, bridge_channel, frame);
+               res = ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
                break;
        case AST_FRAME_VOICE:
-               softmix_bridge_write_voice(bridge, bridge_channel, frame);
+               if (bridge_channel) {
+                       softmix_bridge_write_voice(bridge, bridge_channel, frame);
+               }
                break;
        case AST_FRAME_VIDEO:
-               softmix_bridge_write_video(bridge, bridge_channel, frame);
+               if (bridge_channel) {
+                       softmix_bridge_write_video(bridge, bridge_channel, frame);
+               }
                break;
        case AST_FRAME_CONTROL:
-               softmix_bridge_write_control(bridge, bridge_channel, frame);
+               res = softmix_bridge_write_control(bridge, bridge_channel, frame);
                break;
        case AST_FRAME_BRIDGE_ACTION:
-               softmix_pass_everyone_else(bridge, bridge_channel, frame);
+               res = ast_bridge_queue_everyone_else(bridge, bridge_channel, frame);
                break;
        default:
                ast_debug(3, "Frame type %d unsupported\n", frame->frametype);
-               res = -1;
+               /* "Accept" the frame and discard it. */
                break;
        }
 
index 3f817f4f1de35110a86a1dc28921e14c6cbf3fbf..850245827103758e30d14b8e0b73f386a994f9ec 100644 (file)
@@ -1064,6 +1064,22 @@ void ast_bridge_update_linkedids(struct ast_bridge *bridge, struct ast_bridge_ch
  */
 void ast_bridge_update_accountcodes(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
 
+/*!
+ * \brief Queue the given frame to everyone else.
+ * \since 12.0.0
+ *
+ * \param bridge What bridge to distribute frame.
+ * \param bridge_channel Channel to optionally not pass frame to. (NULL to pass to everyone)
+ * \param frame Frame to pass.
+ *
+ * \note This is intended to be called by bridge hooks and
+ * bridge technologies.
+ *
+ * \retval 0 Frame written to at least one channel.
+ * \retval -1 Frame written to no channels.
+ */
+int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame);
+
 /*!
  * \brief Write a frame to the specified bridge_channel.
  * \since 12.0.0
index 33bdf258453afd1c48c085c9ee6750f0cc336b5a..bc432638427b0014ef9c6c094199e1b33c22a96d 100644 (file)
@@ -124,8 +124,10 @@ struct ast_bridge_technology {
        /*!
         * \brief Write a frame into the bridging technology instance for a bridge.
         *
-        * \retval 0 on success
-        * \retval -1 on failure
+        * \note The bridge must be tolerant of bridge_channel being NULL.
+        *
+        * \retval 0 Frame accepted into the bridge.
+        * \retval -1 Frame needs to be deferred.
         *
         * \note On entry, bridge is already locked.
         */
index 98a72f379bb95b5759965e472bc1815557a7d2a9..0530424ff181916d89530e20acee1b1abf167c19 100644 (file)
@@ -421,6 +421,22 @@ int ast_bridge_channel_queue_control_data(struct ast_bridge_channel *bridge_chan
        return ast_bridge_channel_queue_frame(bridge_channel, &frame);
 }
 
+int ast_bridge_queue_everyone_else(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
+{
+       struct ast_bridge_channel *cur;
+       int not_written = -1;
+
+       AST_LIST_TRAVERSE(&bridge->channels, cur, entry) {
+               if (cur == bridge_channel) {
+                       continue;
+               }
+               if (!ast_bridge_channel_queue_frame(cur, frame)) {
+                       not_written = 0;
+               }
+       }
+       return not_written;
+}
+
 void ast_bridge_channel_restore_formats(struct ast_bridge_channel *bridge_channel)
 {
        /* Restore original formats of the channel as they came in */