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