1 /*
2 * Copyright (c) 2004-2006 Maxim Sobolev <sobomax@FreeBSD.org>
3 * Copyright (c) 2006-2016 Sippy Software, Inc., http://www.sippysoft.com
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <stdint.h>
32 #include <string.h>
33
34 #include "rtpp_defines.h"
35 #include "rtpp_cfg_stable.h"
36 #include "rtpp_log.h"
37 #include "rtpp_command_private.h"
38 #include "rtpp_types.h"
39 #include "rtpp_hash_table.h"
40 #include "rtpp_log_obj.h"
41 #include "rtpp_pipe.h"
42 #include "rtpp_session.h"
43 #include "rtpp_stream.h"
44 #include "rtpp_weakref.h"
45
46 struct delete_ematch_arg {
47 int ndeleted;
48 const char *from_tag;
49 const char *to_tag;
50 int weak;
51 struct rtpp_weakref_obj *sessions_wrt;
52 };
53
54 static int
rtpp_cmd_delete_ematch(void * dp,void * ap)55 rtpp_cmd_delete_ematch(void *dp, void *ap)
56 {
57 unsigned int medianum;
58 struct rtpp_session *spa;
59 int cmpr, cmpr1, idx;
60 struct delete_ematch_arg *dep;
61
62 spa = (struct rtpp_session *)dp;
63 dep = (struct delete_ematch_arg *)ap;
64
65 medianum = 0;
66 if ((cmpr1 = compare_session_tags(spa->tag, dep->from_tag, &medianum)) != 0) {
67 idx = 1;
68 cmpr = cmpr1;
69 } else if (dep->to_tag != NULL &&
70 (cmpr1 = compare_session_tags(spa->tag, dep->to_tag, &medianum)) != 0) {
71 idx = 0;
72 cmpr = cmpr1;
73 } else {
74 return (RTPP_HT_MATCH_CONT);
75 }
76
77 if (dep->weak)
78 spa->rtp->stream[idx]->weak = 0;
79 else
80 spa->strong = 0;
81
82 /*
83 * This seems to be stable from reiterations, the only side
84 * effect is less efficient work.
85 */
86 if (spa->strong || spa->rtp->stream[0]->weak || spa->rtp->stream[1]->weak) {
87 RTPP_LOG(spa->log, RTPP_LOG_INFO,
88 "delete: medianum=%u: removing %s flag, seeing flags to"
89 " continue session (strong=%d, weak=%d/%d)",
90 medianum,
91 dep->weak ? ( idx ? "weak[1]" : "weak[0]" ) : "strong",
92 spa->strong, spa->rtp->stream[0]->weak, spa->rtp->stream[1]->weak);
93 /* Skipping to next possible stream for this call */
94 dep->ndeleted++;
95 return (RTPP_HT_MATCH_CONT);
96 }
97 RTPP_LOG(spa->log, RTPP_LOG_INFO,
98 "forcefully deleting session %u on ports %d/%d",
99 medianum, spa->rtp->stream[0]->port, spa->rtp->stream[1]->port);
100 if (CALL_METHOD(dep->sessions_wrt, unreg, spa->seuid) != NULL) {
101 dep->ndeleted++;
102 }
103 if (cmpr != 2) {
104 return (RTPP_HT_MATCH_DEL | RTPP_HT_MATCH_BRK);
105 }
106 return (RTPP_HT_MATCH_DEL);
107 }
108
109 int
handle_delete(struct cfg * cf,struct common_cmd_args * ccap,int weak)110 handle_delete(struct cfg *cf, struct common_cmd_args *ccap, int weak)
111 {
112 struct delete_ematch_arg dea;
113
114 memset(&dea, '\0', sizeof(dea));
115 dea.from_tag = ccap->from_tag;
116 dea.to_tag = ccap->to_tag;
117 dea.weak = weak;
118 dea.sessions_wrt = cf->stable->sessions_wrt;
119 CALL_METHOD(cf->stable->sessions_ht, foreach_key, ccap->call_id,
120 rtpp_cmd_delete_ematch, &dea);
121 if (dea.ndeleted == 0) {
122 return -1;
123 }
124 return 0;
125 }
126