1#!/usr/bin/env python
2#
3# Copyright (c) 2014 Sippy Software, Inc. All rights reserved.
4#
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without modification,
8# are permitted provided that the following conditions are met:
9#
10# 1. Redistributions of source code must retain the above copyright notice, this
11# list of conditions and the following disclaimer.
12#
13# 2. Redistributions in binary form must reproduce the above copyright notice,
14# this list of conditions and the following disclaimer in the documentation and/or
15# other materials provided with the distribution.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
21# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28NCMDS = 100000
29CMD_TEMPLATE_U = 'U %s 127.0.0.2 %d %s'
30CMD_TEMPLATE_L = 'L %s 127.0.0.3 %d %s %s'
31CMD_TEMPLATE_D_C = 'D %s %s'
32CMD_TEMPLATE_D_B = 'D %s %s %s'
33
34from twisted.internet import reactor
35from random import random
36
37import sys
38sys.path.append('../../sippy.git')
39
40from sippy.Rtp_proxy_client_local import Rtp_proxy_client_local
41from sippy.Rtp_proxy_client_udp import Rtp_proxy_client_udp
42from sippy.Timeout import Timeout
43
44sys.path.append('../../sip_test_data/python')
45
46from pickrandom import pickrandom
47
48class sess_data(object):
49    command_u = None
50    command_l = None
51    command_d_c = None
52    command_d_b1 = None
53    command_d_b2 = None
54
55class res(object):
56    rcodes = None
57    rremain = None
58    nsent = None
59    rtppc = None
60    prand_cid = None
61    prand_tags = None
62
63    def __init__(self, rremain):
64        self.rcodes = []
65        self.rremain = rremain
66        self.nsent = 0
67        global_config = {}
68        self.prand_cid = pickrandom(kind = 'call_id')
69        self.prand_tags = pickrandom(kind = 'to_from_tags')
70        self.rtppc = Rtp_proxy_client_local(global_config, \
71          address = '/var/run/rtpproxy.sock', nworkers = 2)
72        #self.rtppc = Rtp_proxy_client_udp(global_config, \
73        #  address = ('127.0.0.1', 1234), nworkers = 2)
74
75    def issue_command(self):
76        call_id = self.prand_cid.get()
77        ftag = self.prand_tags.get()
78        ttag = self.prand_tags.get()
79        sd = sess_data()
80        sd.command_u = CMD_TEMPLATE_U % (call_id, self.nsent + 1000, ftag)
81        sd.command_l = CMD_TEMPLATE_L % (call_id, self.nsent + 2000, ftag, ttag)
82        sd.command_d_c = CMD_TEMPLATE_D_C % (call_id, ftag)
83        sd.command_d_b1 = CMD_TEMPLATE_D_B % (call_id, ftag, ttag)
84        sd.command_d_b2 = CMD_TEMPLATE_D_B % (call_id, ttag, ftag)
85        self.rtppc.send_command(sd.command_u, self.rtpp_reply_u, sd)
86        #print command
87
88    def rtpp_reply_u(self, rval, sdata):
89        #print 'rtpp_reply'
90        if rval == 'E72':
91            print 'bingo 1'
92            Timeout(self.issue_command, 3 * random())
93            return
94        if rval == None or rval.startswith('E'):
95            print ('rtpp_reply_u: error: %s, original command: %s' % \
96              (str(rval), sdata.command_u))
97            reactor.stop()
98            return
99
100        self.rcodes.append(rval)
101
102        if random() < 0.1:
103             Timeout(self.issue_command_d, 10 * random(), 1, sdata.command_d_c)
104             self.issue_command()
105        else:
106             self.issue_command_l(sdata)
107
108    def issue_command_l(self, sdata):
109        self.rtppc.send_command(sdata.command_l, self.rtpp_reply_l, sdata)
110        #print command
111        self.nsent += 1
112
113    def rtpp_reply_l(self, rval, sdata):
114        #print 'rtpp_reply', sdata
115        if rval == 'E71':
116            print 'bingo 2'
117            Timeout(self.issue_command_l, 2 * random(), 1, sdata)
118            return
119        if rval == None or rval.startswith('E'):
120            print ('rtpp_reply_l: error: %s, original command: %s' % \
121              (str(rval), sdata.command_l))
122            reactor.stop()
123            return
124
125        if random() > 0.5:
126            # let 50% of the sessions timeout, disconnect the rest after
127            # 8.5-58.5 seconds explicitly
128            tout = 8.5 + (50.0 * random())
129            if random() > 0.5:
130                Timeout(self.issue_command_d, tout, 1, sdata.command_d_b1)
131            else:
132                Timeout(self.issue_command_d, tout, 1, sdata.command_d_b2)
133        self.rcodes.append(rval)
134        self.rremain -= 1
135        if self.rremain == 0:
136            reactor.stop()
137        self.issue_command()
138
139    def issue_command_d(self, command_d):
140        self.rtppc.send_command(command_d, self.rtpp_reply_d, command_d)
141
142    def rtpp_reply_d(self, rval, command_d):
143        if rval != '0':
144            print ('rtpp_reply_d: error: %s, original command: %s' % \
145              (str(rval), command_d))
146            reactor.stop()
147            return
148
149rres = res(NCMDS)
150rres.issue_command()
151
152reactor.run()
153#print 'main:', rres.rcodes
154rres.rtppc.shutdown()
155