Browse code

sbc: filter for filtering out media lines

Václav Kubart authored on 06/08/2013 08:37:43
Showing 8 changed files
... ...
@@ -416,7 +416,10 @@ int SBCCallLeg::relayEvent(AmEvent* ev)
416 416
           // todo: handle filtering errors
417 417
 
418 418
           int res = filterSdp(req_ev->req.body, req_ev->req.method);
419
-          if (res < 0) return res;
419
+          if (res < 0) {
420
+            delete ev; // failed relayEvent should destroy the event
421
+            return res;
422
+          }
420 423
         }
421 424
         break;
422 425
 
... ...
@@ -1359,6 +1362,18 @@ int SBCCallLeg::filterSdp(AmMimeBody &body, const string &method)
1359 1362
     changed = true;
1360 1363
   }
1361 1364
 
1365
+  if (!call_profile.mediafilter.empty()) {
1366
+    res = filterMedia(sdp, call_profile.mediafilter);
1367
+    if (res < 0) {
1368
+      // result may be ignored, we need to set the SDP
1369
+      string n_body;
1370
+      sdp.print(n_body);
1371
+      sdp_body->setPayload((const unsigned char*)n_body.c_str(), n_body.length());
1372
+      return res;
1373
+    }
1374
+    changed = true;
1375
+  }
1376
+
1362 1377
   if (prefer_existing_codecs) {
1363 1378
     // We have to order payloads before adding transcoder codecs to leave
1364 1379
     // transcoding as the last chance (existing codecs are preferred thus
... ...
@@ -176,6 +176,9 @@ bool SBCCallProfile::readFromConfiguration(const string& name,
176 176
   if (!readFilter(cfg, "sdp_filter", "sdpfilter_list", sdpfilter, true))
177 177
     return false;
178 178
 
179
+  if (!readFilter(cfg, "media_filter", "mediafilter_list", mediafilter, true))
180
+    return false;
181
+
179 182
   anonymize_sdp = cfg.getParameter("sdp_anonymize", "no") == "yes";
180 183
 
181 184
   // SDP alines filter
... ...
@@ -440,6 +443,12 @@ bool SBCCallProfile::readFromConfiguration(const string& name,
440 443
     filter_elems = sdpalinesfilter.size() ? sdpalinesfilter.back().filter_list.size() : 0;
441 444
     INFO("SBC:      SDP alines-filter is %sabled, %s, %zd items in list\n",
442 445
 	 sdpalinesfilter.size()?"en":"dis", filter_type.c_str(), filter_elems);
446
+    
447
+    filter_type = mediafilter.size() ?
448
+      FilterType2String(mediafilter.back().filter_type) : "disabled";
449
+    filter_elems = mediafilter.size() ? mediafilter.back().filter_list.size() : 0;
450
+    INFO("SBC:      SDP filter is %sabled, %s, %zd items in list\n",
451
+	 mediafilter.size()?"en":"dis", filter_type.c_str(), filter_elems);
443 452
 
444 453
     INFO("SBC:      RTP relay %sabled\n", rtprelay_enabled?"en":"dis");
445 454
     if (rtprelay_enabled) {
... ...
@@ -565,6 +574,7 @@ bool SBCCallProfile::operator==(const SBCCallProfile& rhs) const {
565 574
     //messagefilter_list == rhs.messagefilter_list &&
566 575
     //sdpfilter_enabled == rhs.sdpfilter_enabled &&
567 576
     sdpfilter == rhs.sdpfilter &&
577
+    mediafilter == rhs.mediafilter &&
568 578
     sst_enabled == rhs.sst_enabled &&
569 579
     sst_aleg_enabled == rhs.sst_aleg_enabled &&
570 580
     auth_enabled == rhs.auth_enabled &&
... ...
@@ -128,6 +128,7 @@ struct SBCCallProfile
128 128
   bool anonymize_sdp;
129 129
   vector<FilterEntry> sdpfilter;
130 130
   vector<FilterEntry> sdpalinesfilter;
131
+  vector<FilterEntry> mediafilter;
131 132
 
132 133
   string sst_enabled;
133 134
   bool sst_enabled_value;
... ...
@@ -53,7 +53,7 @@ int filterSDP(AmSdp& sdp, const vector<FilterEntry>& filter_list) {
53 53
       
54 54
 	string c = p_it->encoding_name;
55 55
 	std::transform(c.begin(), c.end(), c.begin(), ::tolower);
56
-      
56
+
57 57
 	bool is_filtered =  (sdpfilter == Whitelist) ^
58 58
 	  (sdpfilter_list.find(c) != sdpfilter_list.end());
59 59
 
... ...
@@ -84,6 +84,42 @@ int filterSDP(AmSdp& sdp, const vector<FilterEntry>& filter_list) {
84 84
   return 0;
85 85
 }
86 86
 
87
+int filterMedia(AmSdp& sdp, const vector<FilterEntry>& filter_list)
88
+{
89
+  unsigned filtered_out = 0;
90
+
91
+  DBG("filtering media types\n");
92
+  for (vector<FilterEntry>::const_iterator i = filter_list.begin(); i !=filter_list.end(); ++i) {
93
+
94
+    const FilterType& filter = i->filter_type;
95
+    const std::set<string>& media_list = i->filter_list;
96
+
97
+    if (!isActiveFilter(filter)) continue;
98
+
99
+    for (std::vector<SdpMedia>::iterator m = sdp.media.begin(); m != sdp.media.end(); ++m) {
100
+      if (m->port == 0) continue; // already inactive
101
+
102
+      string type(SdpMedia::type2str(m->type));
103
+      DBG("checking whether to filter out '%s'\n", type.c_str());
104
+
105
+      bool is_filtered = (filter == Whitelist) ^ (media_list.find(type) != media_list.end());
106
+      if (is_filtered) {
107
+        m->port = 0;
108
+        filtered_out++;
109
+      }
110
+    }
111
+  }
112
+
113
+  if (filtered_out > 0 && filtered_out == sdp.media.size()) {
114
+    // we filtered out all media lines (if there was an inactive stream before
115
+    // it was probably intendend)
116
+    DBG("all streams were marked as inactive\n");
117
+    return -488;
118
+  }
119
+
120
+  return 0;
121
+}
122
+
87 123
 void fix_missing_encodings(SdpMedia& m) {
88 124
   for (std::vector<SdpPayload>::iterator p_it=
89 125
 	 m.payloads.begin(); p_it!=m.payloads.end(); p_it++) {
... ...
@@ -37,6 +37,7 @@ using std::string;
37 37
 
38 38
 int filterSDP(AmSdp& sdp, const vector<FilterEntry>& filter_list);
39 39
 int filterSDPalines(AmSdp& sdp, const vector<FilterEntry>& filter_list);
40
+int filterMedia(AmSdp& sdp, const vector<FilterEntry>& filter_list);
40 41
 
41 42
 /** normalize SDP, fixing some common issues and anonymize (IP addresses
42 43
  * replaced in such case by advertised_ip) */
... ...
@@ -353,7 +353,7 @@ void AmB2BSession::onSipRequest(const AmSipRequest& req)
353 353
     }
354 354
     else {
355 355
       // relay failed, generate error reply
356
-      ERROR("relay failed, replying error\n");
356
+      DBG("relay failed, replying error\n");
357 357
       AmSipReply n_reply;
358 358
       errCode2RelayedReply(n_reply, res, 500);
359 359
       dlg->reply(req, n_reply.code, n_reply.reason);
... ...
@@ -133,6 +133,11 @@ string SdpMedia::debugPrint() const {
133 133
   return "port "+int2str(port) + ", payloads: "+payload_list;
134 134
 }
135 135
 
136
+string SdpMedia::type2str(int type)
137
+{
138
+  return media_t_2_str(type);
139
+}
140
+
136 141
 bool SdpPayload::operator == (int r)
137 142
 {
138 143
   DBG("pl == r: payload_type = %i; r = %i\n", payload_type, r);
... ...
@@ -194,6 +194,8 @@ struct SdpMedia
194 194
   /** pretty print */
195 195
   string debugPrint() const;
196 196
 
197
+  static string type2str(int type);
198
+
197 199
   /**
198 200
    * Checks which payloads are compatible with the payload provider,
199 201
    * inserts them into the answer, compute send/recv attributes