~ubuntu-branches/ubuntu/saucy/resiprocate/saucy-proposed

« back to all changes in this revision

Viewing changes to resip/recon/MOHParkServer/MOHManager.cxx

  • Committer: Package Import Robot
  • Author(s): Daniel Pocock
  • Date: 2012-05-17 19:29:59 UTC
  • Revision ID: package-import@ubuntu.com-20120517192959-vv00m77isztdy64q
Tags: upstream-1.8.2
ImportĀ upstreamĀ versionĀ 1.8.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "AppSubsystem.hxx"
 
2
#include "MOHManager.hxx"
 
3
#include "Server.hxx"
 
4
#include "../UserAgent.hxx"
 
5
 
 
6
#include <resip/stack/ExtensionParameter.hxx>
 
7
#include <rutil/Log.hxx>
 
8
#include <rutil/Logger.hxx>
 
9
#include <rutil/WinLeakCheck.hxx>
 
10
 
 
11
using namespace recon;
 
12
using namespace resip;
 
13
using namespace std;
 
14
 
 
15
#define RESIPROCATE_SUBSYSTEM AppSubsystem::MOHPARKSERVER
 
16
 
 
17
static const resip::ExtensionParameter p_automaton("automaton");
 
18
static const resip::ExtensionParameter p_byeless("+sip.byeless");
 
19
static const resip::ExtensionParameter p_rendering("+sip.rendering");
 
20
 
 
21
namespace mohparkserver 
 
22
{
 
23
 
 
24
MOHManager::MOHManager(Server& server) :
 
25
   mServer(server),
 
26
   mConversationProfileHandle(0),
 
27
   mMusicFilenameChanged(false)
 
28
{
 
29
}
 
30
 
 
31
MOHManager::~MOHManager()
 
32
{
 
33
}
 
34
 
 
35
void
 
36
MOHManager::startup()
 
37
{
 
38
   // Initialize settings
 
39
   initializeSettings(mServer.mConfig.mMOHFilenameUrl);
 
40
 
 
41
   // Setup ConversationProfile
 
42
   initializeConversationProfile(mServer.mConfig.mMOHUri, mServer.mConfig.mMOHPassword, mServer.mConfig.mMOHRegistrationTime, mServer.mConfig.mOutboundProxy);
 
43
 
 
44
   // Create an initial conversation and start music
 
45
   ConversationHandle convHandle = mServer.createConversation(true /* broadcast only*/);   
 
46
   mServer.createMediaResourceParticipant(convHandle, mServer.mConfig.mMOHFilenameUrl);  // Play Music
 
47
   mConversations[convHandle];
 
48
   mMusicFilenameChanged = false;
 
49
}
 
50
 
 
51
void 
 
52
MOHManager::initializeConversationProfile(const NameAddr& uri, const Data& password, unsigned long registrationTime, const resip::NameAddr& outboundProxy)
 
53
{
 
54
   if(mConversationProfileHandle)
 
55
   {
 
56
       mServer.mMyUserAgent->destroyConversationProfile(mConversationProfileHandle);
 
57
       mConversationProfileHandle = 0;
 
58
   }
 
59
 
 
60
   // Setup ConversationProfile
 
61
   SharedPtr<ConversationProfile> mohConversationProfile = SharedPtr<ConversationProfile>(new ConversationProfile(mServer.mUserAgentMasterProfile));
 
62
   mohConversationProfile->setDefaultRegistrationTime(registrationTime);  
 
63
   mohConversationProfile->setDefaultRegistrationRetryTime(120);  // 2 mins
 
64
   mohConversationProfile->setDefaultFrom(uri);
 
65
   mohConversationProfile->setDigestCredential(uri.uri().host(), uri.uri().user(), password);  
 
66
   if(!outboundProxy.uri().host().empty())
 
67
   {
 
68
      mohConversationProfile->setOutboundProxy(outboundProxy.uri());
 
69
   }
 
70
   mohConversationProfile->challengeOODReferRequests() = false;
 
71
   mohConversationProfile->setExtraHeadersInReferNotifySipFragEnabled(true);  // Enable dialog identifying headers in SipFrag bodies of Refer Notifies - required for a music on hold server
 
72
   NameAddr capabilities;
 
73
   capabilities.param(p_automaton);
 
74
   capabilities.param(p_byeless);
 
75
   capabilities.param(p_rendering) = "\"no\"";
 
76
   mohConversationProfile->setUserAgentCapabilities(capabilities);
 
77
   mohConversationProfile->natTraversalMode() = ConversationProfile::NoNatTraversal;
 
78
   mohConversationProfile->secureMediaMode() = ConversationProfile::NoSecureMedia;
 
79
   mServer.buildSessionCapabilities(mohConversationProfile->sessionCaps());
 
80
   mConversationProfileHandle = mServer.mMyUserAgent->addConversationProfile(mohConversationProfile);
 
81
}
 
82
 
 
83
void 
 
84
MOHManager::initializeSettings(const resip::Uri& musicFilename)
 
85
{
 
86
   Lock lock(mMutex);
 
87
   mMusicFilename = musicFilename;
 
88
   // If there is a single conversation with no participants, then there are no 
 
89
   // current parties on hold - re-create the conversation with new music
 
90
   if(mConversations.size() == 1 && mConversations.begin()->second.size() == 0)
 
91
   {
 
92
      mServer.destroyConversation(mConversations.begin()->first);
 
93
      mConversations.clear();
 
94
 
 
95
      // re-create an initial conversation and start music
 
96
      ConversationHandle convHandle = mServer.createConversation(true /* broadcast only*/);      
 
97
      mServer.createMediaResourceParticipant(convHandle, mMusicFilename);  // Play Music
 
98
      mConversations[convHandle];
 
99
   }
 
100
   else
 
101
   {
 
102
      mMusicFilenameChanged = true;
 
103
   }
 
104
}
 
105
 
 
106
void
 
107
MOHManager::shutdown(bool shuttingDownServer)
 
108
{
 
109
   Lock lock(mMutex);
 
110
   // Destroy all conversations
 
111
   ConversationMap::iterator it = mConversations.begin();
 
112
   for(; it != mConversations.end(); it++)
 
113
   {
 
114
      // Clean up participant memory
 
115
      ParticipantMap::iterator partIt = it->second.begin();
 
116
      for(;partIt!= it->second.end(); partIt++)
 
117
      {
 
118
         delete partIt->second;
 
119
      }
 
120
      it->second.clear();
 
121
 
 
122
       mServer.destroyConversation(it->first);
 
123
   }
 
124
   mConversations.clear();
 
125
 
 
126
   // If shutting down server, then we shouldn't remove the conversation profiles here
 
127
   // shutting down the ConversationManager will take care of this.  We need to be sure
 
128
   // we don't remove all conversation profiles when we are still processing SipMessages,
 
129
   // since recon requires at least one to be present for inbound processing.
 
130
   if(mConversationProfileHandle && !shuttingDownServer)
 
131
   {
 
132
       mServer.mMyUserAgent->destroyConversationProfile(mConversationProfileHandle);
 
133
       mConversationProfileHandle = 0;
 
134
   }
 
135
}
 
136
 
 
137
bool 
 
138
MOHManager::isMyProfile(recon::ConversationProfile& profile)
 
139
{
 
140
   Lock lock(mMutex);
 
141
   return profile.getHandle() == mConversationProfileHandle;
 
142
}
 
143
 
 
144
void 
 
145
MOHManager::addParticipant(ParticipantHandle participantHandle, const Uri& heldUri, const Uri& holdingUri)
 
146
{
 
147
   Lock lock(mMutex);
 
148
   ConversationHandle conversationToUse = 0;
 
149
   // Check if we have an existing conversation with room to add this party
 
150
   ConversationMap::iterator it = mConversations.begin();
 
151
   for(; it != mConversations.end(); it++)
 
152
   {
 
153
      if(it->second.size() < DEFAULT_BRIDGE_MAX_IN_OUTPUTS-3)
 
154
      {
 
155
         // Found an existing conversation with room - add the participant here
 
156
         conversationToUse = it->first;
 
157
         break;
 
158
      }
 
159
   }
 
160
 
 
161
   // No conversation found that we can use - create a new one
 
162
   if(!conversationToUse)
 
163
   {
 
164
      conversationToUse = mServer.createConversation(true /* broadcast only*/);
 
165
      InfoLog(<< "MOHManager::addParticipant created new conversation for music on hold, id=" << conversationToUse);
 
166
 
 
167
      // Play Music
 
168
      mServer.createMediaResourceParticipant(conversationToUse, mMusicFilename);
 
169
   }
 
170
 
 
171
   assert(conversationToUse);
 
172
 
 
173
   mServer.addParticipant(conversationToUse, participantHandle);
 
174
   mServer.modifyParticipantContribution(conversationToUse, participantHandle, 100, 0 /* Mute participant */);
 
175
   mServer.answerParticipant(participantHandle);
 
176
   mConversations[conversationToUse].insert(std::make_pair(participantHandle, new ParticipantMOHInfo(participantHandle, heldUri, holdingUri)));
 
177
}
 
178
 
 
179
bool
 
180
MOHManager::removeParticipant(ParticipantHandle participantHandle)
 
181
{
 
182
   Lock lock(mMutex);
 
183
   // Find Conversation that participant is in
 
184
   ConversationMap::iterator it = mConversations.begin();
 
185
   for(; it != mConversations.end(); it++)
 
186
   {
 
187
      ParticipantMap::iterator partIt = it->second.find(participantHandle);
 
188
      if(partIt != it->second.end())
 
189
      {
 
190
         InfoLog(<< "MOHManager::removeParticipant found in conversation id=" << it->first << ", size=" << it->second.size());
 
191
 
 
192
         // Found! Remove from conversation
 
193
         delete partIt->second;
 
194
         it->second.erase(partIt);
 
195
 
 
196
         // Check if conversation is now empty, and it's not the last conversation
 
197
         if(it->second.size() == 0)
 
198
         {    
 
199
            if(mConversations.size() > 1)
 
200
            {
 
201
               // Destroy conversation (and containing media participant)
 
202
               mServer.destroyConversation(it->first);
 
203
 
 
204
               // Remove Conversation from Map
 
205
               mConversations.erase(it);
 
206
 
 
207
               InfoLog(<< "MOHManager::removeParticipant last participant in conversation, destroying conversation, num conversations now=" << mConversations.size());
 
208
            }
 
209
            else if(mConversations.size() == 1 && mMusicFilenameChanged)  // If the initial conversation is empty, and the music filename setting changed, then restart it
 
210
            {
 
211
               mServer.destroyConversation(mConversations.begin()->first);
 
212
               mConversations.clear();
 
213
 
 
214
               // re-create an initial conversation and start music
 
215
               ConversationHandle convHandle = mServer.createConversation(true /* broadcast only*/);      
 
216
               mServer.createMediaResourceParticipant(convHandle, mMusicFilename);  // Play Music
 
217
               mConversations[convHandle];
 
218
               mMusicFilenameChanged = false;
 
219
            }
 
220
         }
 
221
         return true;
 
222
      }
 
223
   }
 
224
   return false;
 
225
}
 
226
 
 
227
void 
 
228
MOHManager::getActiveCallsInfo(CallInfoList& callInfos)
 
229
{
 
230
   Lock lock(mMutex);
 
231
   // Find Conversation that participant is in
 
232
   ConversationMap::iterator it = mConversations.begin();
 
233
   for(; it != mConversations.end(); it++)
 
234
   {
 
235
      ParticipantMap::iterator partIt = it->second.begin();
 
236
      for(; partIt != it->second.end(); partIt++)
 
237
      {
 
238
         callInfos.push_back(ActiveCallInfo(partIt->second->mHeldUri, partIt->second->mHoldingUri, "MOH", partIt->first, it->first));
 
239
      }
 
240
   }
 
241
}
 
242
 
 
243
}
 
244
 
 
245
/* ====================================================================
 
246
 
 
247
 Copyright (c) 2010, SIP Spectrum, Inc.
 
248
 All rights reserved.
 
249
 
 
250
 Redistribution and use in source and binary forms, with or without
 
251
 modification, are permitted provided that the following conditions are 
 
252
 met:
 
253
 
 
254
 1. Redistributions of source code must retain the above copyright 
 
255
    notice, this list of conditions and the following disclaimer. 
 
256
 
 
257
 2. Redistributions in binary form must reproduce the above copyright
 
258
    notice, this list of conditions and the following disclaimer in the
 
259
    documentation and/or other materials provided with the distribution. 
 
260
 
 
261
 3. Neither the name of SIP Spectrum nor the names of its contributors 
 
262
    may be used to endorse or promote products derived from this 
 
263
    software without specific prior written permission. 
 
264
 
 
265
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 
266
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 
267
 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
 
268
 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 
269
 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 
270
 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
 
271
 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 
272
 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 
273
 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 
274
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 
275
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
276
 
 
277
 ==================================================================== */
 
278