1
2 /* H461_base.cxx
3 *
4 * Copyright (c) 2013 Spranto Int'l Pte Ltd. All Rights Reserved.
5 *
6 * The contents of this file are subject to the Mozilla Public License
7 * Version 1.1 (the "License"); you may not use this file except in
8 * compliance with the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Alternatively, the contents of this file may be used under the terms
12 * of the General Public License (the "GNU License"), in which case the
13 * provisions of GNU License are applicable instead of those
14 * above. If you wish to allow use of your version of this file only
15 * under the terms of the GNU License and not to allow others to use
16 * your version of this file under the MPL, indicate your decision by
17 * deleting the provisions above and replace them with the notice and
18 * other provisions required by the GNU License. If you do not delete
19 * the provisions above, a recipient may use your version of this file
20 * under either the MPL or the GNU License."
21 *
22 * Software distributed under the License is distributed on an "AS IS"
23 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
24 * the License for the specific language governing rights and limitations
25 * under the License.
26 *
27 * The Original Code is derived from and used in conjunction with the
28 * H323plus Project (www.h323plus.org/)
29 *
30 * The Initial Developer of the Original Code is ISVO (Asia) Pte Ltd.
31 *
32 *
33 * Contributor(s): ______________________________________.
34 *
35 * $Id$
36 *
37 */
38
39 #include <ptlib.h>
40 #include <openh323buildopts.h>
41
42 #ifdef H323_H461
43
44 #include "h460/h461_base.h"
45 #include <h460/h460.h>
46 #include "h323ep.h"
47 #include "h323pdu.h"
48
49 #ifdef _MSC_VER
50 #pragma warning(disable:4127)
51 #endif
52
53 #define DEFAULT_ASSOCIATE_TTL 43200 // 30 days
54 #define DEFAULT_STATUS_INTERVAL 180 // 3 hours
55
56 // Must Declare for Factory Loader.
57 H460_FEATURE(X1);
58
59 #define baseOID "0.0.8.461.0"
60 #define ASSETAssociate "0"
61 #define ASSETApplication "1"
62
H460_FeatureX1()63 H460_FeatureX1::H460_FeatureX1()
64 : H460_FeatureOID(baseOID),
65 m_ep(NULL), m_con(NULL), m_handler(NULL), m_endpointmode(0),
66 m_enabled(false), m_supported(false)
67 {
68 PTRACE(6,"X1\tInstance Created");
69 FeatureCategory = FeatureSupported;
70 }
71
~H460_FeatureX1()72 H460_FeatureX1::~H460_FeatureX1()
73 {
74 delete m_handler;
75 }
76
77
AttachEndPoint(H323EndPoint * _ep)78 void H460_FeatureX1::AttachEndPoint(H323EndPoint * _ep)
79 {
80 m_ep = _ep;
81 m_enabled = m_ep->IsASSETEnabled();
82 if (!m_enabled)
83 return;
84
85 m_endpointmode = m_ep->GetEndPointASSETMode();
86 switch (m_endpointmode) {
87 case H323EndPoint::e_H461EndPoint: FeatureCategory = FeatureSupported; break;
88 case H323EndPoint::e_H461ASSET: FeatureCategory = FeatureNeeded; break;
89 }
90 }
91
AttachConnection(H323Connection * _con)92 void H460_FeatureX1::AttachConnection(H323Connection * _con)
93 {
94 m_con = _con;
95 m_handler = new H461Handler(*this);
96 }
97
GetIdentifier()98 PStringArray H460_FeatureX1::GetIdentifier()
99 {
100 return PStringArray(baseOID);
101 }
102
FeatureAdvertised(int mtype)103 PBoolean H460_FeatureX1::FeatureAdvertised(int mtype)
104 {
105 if (m_con->GetH461Mode() == H323Connection::e_h461EndpointCall) {
106 switch (mtype) {
107 case H460_MessageType::e_setup:
108 case H460_MessageType::e_connect:
109 return true;
110 default:
111 return false;
112 }
113 } else
114 return false;
115 }
116
CommonFeature()117 PBoolean H460_FeatureX1::CommonFeature()
118 {
119 if (!m_supported)
120 m_con->SetH461Mode(H323Connection::e_h461NormalCall);
121
122 return m_supported;
123 }
124
OnSendSetup_UUIE(H225_FeatureDescriptor & pdu)125 PBoolean H460_FeatureX1::OnSendSetup_UUIE(H225_FeatureDescriptor & pdu)
126 {
127 if (!m_enabled)
128 return false;
129
130 PTRACE(6,"X1\tSending Setup");
131 PASN_OctetString xpdu;
132 if (m_handler->BuildPDU(xpdu)) {
133 H460_FeatureOID feat = H460_FeatureOID(OpalOID(baseOID));
134 feat.Add(ASSETApplication,H460_FeatureContent(xpdu));
135 pdu = feat;
136 return true;
137 }
138 return false;
139 }
140
OnReceiveSetup_UUIE(const H225_FeatureDescriptor & pdu)141 void H460_FeatureX1::OnReceiveSetup_UUIE(const H225_FeatureDescriptor & pdu)
142 {
143 if (!m_enabled)
144 return;
145
146 m_supported = true;
147 H460_FeatureOID & feat = (H460_FeatureOID &)pdu;
148 if (feat.Contains(ASSETApplication)) {
149 PTRACE(6,"X1\tReceive Setup");
150 PASN_OctetString & xpdu = feat.Value(ASSETApplication);
151 m_handler->HandlePDU(xpdu);
152 }
153 }
154
OnSendCallConnect_UUIE(H225_FeatureDescriptor & pdu)155 PBoolean H460_FeatureX1::OnSendCallConnect_UUIE(H225_FeatureDescriptor & pdu)
156 {
157 if (!m_enabled)
158 return false;
159
160 PTRACE(6,"X1\tSending Connect");
161 PASN_OctetString xpdu;
162 if (m_handler->BuildPDU(xpdu)) {
163 H460_FeatureOID feat = H460_FeatureOID(OpalOID(baseOID));
164 feat.Add(ASSETApplication,H460_FeatureContent(xpdu));
165 pdu = feat;
166 return true;
167 }
168 return false;
169 }
170
OnReceiveCallConnect_UUIE(const H225_FeatureDescriptor & pdu)171 void H460_FeatureX1::OnReceiveCallConnect_UUIE(const H225_FeatureDescriptor & pdu)
172 {
173 if (!m_enabled)
174 return;
175
176 m_supported = true;
177 H460_FeatureOID & feat = (H460_FeatureOID &)pdu;
178 if (feat.Contains(ASSETApplication)) {
179 PTRACE(6,"X1\tReading Connect");
180 PASN_OctetString & xpdu = feat.Value(ASSETApplication);
181 m_handler->HandlePDU(xpdu);
182 }
183 }
184
OnSendFacility_UUIE(H225_FeatureDescriptor & pdu)185 PBoolean H460_FeatureX1::OnSendFacility_UUIE(H225_FeatureDescriptor & pdu)
186 {
187 if (!m_enabled || !m_supported)
188 return false;
189
190 PTRACE(6,"X1\tSending Facility");
191 PASN_OctetString xpdu;
192 if (m_handler->BuildPDU(xpdu)) {
193 H460_FeatureOID feat = H460_FeatureOID(OpalOID(baseOID));
194 feat.Add(ASSETApplication,H460_FeatureContent(xpdu));
195 pdu = feat;
196 return true;
197 }
198 return false;
199 }
200
OnReceiveFacility_UUIE(const H225_FeatureDescriptor & pdu)201 void H460_FeatureX1::OnReceiveFacility_UUIE(const H225_FeatureDescriptor & pdu)
202 {
203 if (!m_enabled || !m_supported)
204 return;
205
206 H460_FeatureOID & feat = (H460_FeatureOID &)pdu;
207 if (feat.Contains(ASSETApplication)) {
208 PTRACE(6,"X1\tReading facility");
209 PASN_OctetString & xpdu = feat.Value(ASSETApplication);
210 m_handler->HandlePDU(xpdu);
211 }
212 }
213
GetMode()214 int H460_FeatureX1::GetMode()
215 {
216 return m_endpointmode;
217 }
218
GetConnection()219 H323Connection * H460_FeatureX1::GetConnection()
220 {
221 return m_con;
222 }
GetDataStore()223 H461DataStore * H460_FeatureX1::GetDataStore()
224 {
225 return m_ep ? m_ep->GetASSETDataStore() : NULL;
226 }
227
228 //////////////////////////////////////////////////////////////////////////////////
229 // Handler
230
H461Handler(H460_FeatureX1 & feature)231 H461Handler::H461Handler(H460_FeatureX1 & feature)
232 : m_feature(feature), m_connection(feature.GetConnection()),
233 m_mode(feature.GetMode()), m_dataStore(feature.GetDataStore())
234 {
235
236 }
237
BuildPDU(PASN_OctetString & pdu)238 PBoolean H461Handler::BuildPDU(PASN_OctetString & pdu)
239 {
240 PBoolean success = true;
241 H461AssetPDU element;
242 H461_ASSETPDU msg;
243 msg.SetSize(1);
244 msg[0] = element.BuildMessage(this, success);
245 if (success)
246 pdu.EncodeSubType(msg);
247
248 return success;
249 }
250
HandlePDU(const PASN_OctetString & msg)251 PBoolean H461Handler::HandlePDU(const PASN_OctetString & msg)
252 {
253 H461_ASSETPDU element;
254 PPER_Stream raw(msg);
255 if (!element.Decode(raw) || element.GetSize() == 0) {
256 PTRACE(2,"X1\tError Decoding Element. Malformed or no messages.");
257 return false;
258 }
259 return ProcessPDU(element);
260 }
261
ProcessPDU(H461_ASSETPDU & pdu)262 PBoolean H461Handler::ProcessPDU(H461_ASSETPDU & pdu)
263 {
264 for (PINDEX i=0; i<pdu.GetSize(); ++i) {
265 H461AssetPDU msg(pdu[i]);
266 ProcessMessage(msg);
267 }
268 return true;
269 }
270
ProcessMessage(H461AssetPDU & msg)271 PBoolean H461Handler::ProcessMessage(H461AssetPDU & msg)
272 {
273 return msg.ProcessMessage(this);
274 }
275
276 ///////////////////////////////////////////////////////////////////////////////////
277 // Utilities
278
279 #define opt_NONE 0
280 #define opt_ASSOC 1
281 #define opt_CALL 2
282 #define opt_BOTH 3
283 #define opt_DEPEND 4
284
285 #define chk_associateRequest opt_NONE
286 #define chk_associateResponse opt_ASSOC
287 #define chk_statusRequest opt_ASSOC
288 #define chk_statusResponse opt_ASSOC
289 #define chk_listRequest opt_CALL
290 #define chk_listResponse opt_CALL
291 #define chk_callApplist opt_BOTH
292 #define chk_preInvokeRequest opt_BOTH
293 #define chk_preInvokeResponse opt_BOTH
294 #define chk_invokeRequest opt_DEPEND
295 #define chk_invokeResponse opt_DEPEND
296 #define chk_invoke opt_BOTH
297 #define chk_invokeStartList opt_CALL
298 #define chk_invokeNotify opt_CALL
299 #define chk_stopRequest opt_BOTH
300 #define chk_stopNotify opt_CALL
301 #define chk_callRelease opt_BOTH
302
H323GetGUIDString(const H225_GloballyUniqueID & guid)303 PString H323GetGUIDString(const H225_GloballyUniqueID & guid) {
304 return OpalGloballyUniqueID(guid).AsString();
305 }
306
H323GetCallIdentifier(const H225_CallIdentifier & callid)307 PString H323GetCallIdentifier(const H225_CallIdentifier & callid) {
308 return H323GetGUIDString(callid.m_guid);
309 }
310
H323SetGUIDString(const PString & val,H225_GloballyUniqueID & guid)311 void H323SetGUIDString(const PString & val, H225_GloballyUniqueID & guid) {
312 OpalGloballyUniqueID id(val);
313 return guid.SetValue(id);
314 }
315
H323SetCallIdentifier(const PString & val,H225_CallIdentifier & callid)316 void H323SetCallIdentifier(const PString & val ,H225_CallIdentifier & callid) {
317 H323SetGUIDString(val, callid.m_guid);
318 }
319
GetToken(PString & token,const H461_ASSETMessage & pdu)320 void GetToken(PString & token, const H461_ASSETMessage & pdu) {
321 if (pdu.HasOptionalField(H461_ASSETMessage::e_associateToken))
322 token = H323GetGUIDString(pdu.m_associateToken);
323 }
324
SetToken(const PString & val,H461_ASSETMessage & pdu)325 void SetToken(const PString & val, H461_ASSETMessage & pdu) {
326 pdu.IncludeOptionalField(H461_ASSETMessage::e_associateToken);
327 H323SetGUIDString(val,pdu.m_associateToken);
328 }
329
GetCallID(PString & callid,const H461_ASSETMessage & pdu)330 void GetCallID(PString & callid, const H461_ASSETMessage & pdu) {
331 if (pdu.HasOptionalField(H461_ASSETMessage::e_callIdentifier))
332 callid = H323GetCallIdentifier(pdu.m_callIdentifier);
333 }
334
SetCallID(const PString & val,H461_ASSETMessage & pdu)335 void SetCallID(const PString & val, H461_ASSETMessage & pdu) {
336 pdu.IncludeOptionalField(H461_ASSETMessage::e_callIdentifier);
337 H323SetCallIdentifier(val,pdu.m_callIdentifier);
338 }
339
340
341 #define CHECKTOKEN(name) \
342 if (m_token.IsEmpty()) { \
343 PTRACE(2,"H461\tMessage " << #name << " missing Association Token"); \
344 return false; } \
345
346 #define CHECKCALLID(name) \
347 if (m_callid.IsEmpty()) { \
348 PTRACE(2,"H461\tMessage " << #name << " missing Call Identifier"); \
349 return false; } \
350
351
352 #define CHECKPARAMETERS(name) \
353 if (chk_##name != opt_NONE) { \
354 if (chk_##name == opt_ASSOC || chk_##name == opt_BOTH) { CHECKTOKEN(name) } \
355 if (chk_##name == opt_CALL || chk_##name == opt_BOTH || chk_##name == opt_DEPEND) { CHECKCALLID(name) } \
356 }
357
358
359 #define BUILDPARAMETERS(name) \
360 if (chk_##name == opt_ASSOC || chk_##name == opt_BOTH) SetToken(m_token,*this); \
361 if (chk_##name == opt_CALL || chk_##name == opt_BOTH || chk_##name == opt_DEPEND) SetCallID(m_callid,*this); \
362 if (chk_##name == opt_DEPEND && !m_token) SetToken(m_token,*this); \
363 PTRACE(6,"H461\tPDU to send " << *this);
364
365 #define H461HANDLECASE(name) \
366 case H461_ApplicationIE::e_##name : return Handle_##name(m_connection);
367
368 #define H461BUILDCASE(name) \
369 case H461_ApplicationIE::e_##name : return Build_##name(m_connection);
370
371 #define H461HANDLE(name) \
372 PBoolean H461AssetPDU::Handle_##name(H323Connection* m_connection) { \
373 CHECKPARAMETERS(name) \
374 return m_dataStore->Received_##name(m_connection, m_token, m_callid, m_application); }
375
376 #define H461BUILD(name) \
377 H461_ASSETMessage & H461AssetPDU::Build_##name(H323Connection* m_connection) { \
378 m_dataStore->Build_##name(m_connection, m_token, m_callid, m_appID, m_invokeToken, m_aliasAddress, m_approved, m_application); \
379 BUILDPARAMETERS(name) \
380 return *this; }
381
382
H461AssetPDU()383 H461AssetPDU::H461AssetPDU()
384 : m_handler(NULL), m_connection(NULL), m_dataStore(NULL), m_token(PString()), m_callid(PString()), m_appID(-1),
385 m_invokeToken(PString()), m_aliasAddress(PString()), m_approved(false)
386 {
387
388 }
389
H461AssetPDU(H461_ASSETMessage & msg)390 H461AssetPDU::H461AssetPDU(H461_ASSETMessage & msg)
391 : m_handler(NULL), m_connection(NULL), m_dataStore(NULL), m_token(PString()), m_callid(PString()), m_appID(-1),
392 m_invokeToken(PString()), m_aliasAddress(PString()), m_approved(false)
393 {
394 m_application = msg.m_application;
395 if (msg.HasOptionalField(H461_ASSETMessage::e_associateToken)) {
396 IncludeOptionalField(H461_ASSETMessage::e_associateToken);
397 m_associateToken = msg.m_associateToken;
398 }
399 if (msg.HasOptionalField(H461_ASSETMessage::e_callIdentifier)) {
400 IncludeOptionalField(H461_ASSETMessage::e_callIdentifier);
401 m_callIdentifier = msg.m_callIdentifier;
402 }
403 }
404
~H461AssetPDU()405 H461AssetPDU::~H461AssetPDU()
406 {
407
408 }
409
BuildParameters(H323Connection * connection)410 PBoolean H461AssetPDU::BuildParameters(H323Connection* connection)
411 {
412 H323Connection::H461MessageInfo & m_info = connection->GetH461MessageInfo();
413
414 if (m_info.m_message < 0)
415 return false;
416
417 m_application.SetTag(m_info.m_message);
418 m_token = m_info.m_assocToken;
419 m_callid = m_info.m_callToken;
420 m_appID = m_info.m_applicationID;
421 m_invokeToken = m_info.m_invokeToken;
422 m_aliasAddress = m_info.m_aliasAddress;
423 m_approved = m_info.m_approved;
424 return true;
425 }
426
ProcessMessage(H461Handler * handler)427 PBoolean H461AssetPDU::ProcessMessage(H461Handler * handler)
428 {
429 m_handler = handler;
430 m_connection = handler->GetConnection();
431 m_dataStore = handler->GetDataStore();
432
433 GetToken(m_token, *this);
434 GetCallID(m_callid, *this);
435
436 PTRACE(6,"H461\tPDU Received " << *this);
437
438 switch (m_application.GetTag()) {
439 H461HANDLECASE(associateRequest)
440 H461HANDLECASE(associateResponse)
441 H461HANDLECASE(statusRequest)
442 H461HANDLECASE(statusResponse)
443 H461HANDLECASE(listRequest)
444 H461HANDLECASE(listResponse)
445 H461HANDLECASE(callApplist)
446 H461HANDLECASE(preInvokeRequest)
447 H461HANDLECASE(preInvokeResponse)
448 H461HANDLECASE(invokeRequest)
449 H461HANDLECASE(invokeResponse)
450 H461HANDLECASE(invoke)
451 H461HANDLECASE(invokeStartList)
452 H461HANDLECASE(invokeNotify)
453 H461HANDLECASE(stopRequest)
454 H461HANDLECASE(stopNotify)
455 H461HANDLECASE(callRelease)
456 default: break;
457 }
458 return false;
459 }
460
BuildMessage(H461Handler * handler,PBoolean & success)461 H461_ASSETMessage & H461AssetPDU::BuildMessage(H461Handler * handler, PBoolean & success)
462 {
463 m_handler = handler;
464 m_connection = handler->GetConnection();
465 if (!BuildParameters(m_connection)) {
466 success = false;
467 return *this;
468 }
469 m_dataStore = handler->GetDataStore();
470
471 switch (m_application.GetTag()) {
472 H461BUILDCASE(associateRequest)
473 H461BUILDCASE(associateResponse)
474 H461BUILDCASE(statusRequest)
475 H461BUILDCASE(statusResponse)
476 H461BUILDCASE(listRequest)
477 H461BUILDCASE(listResponse)
478 H461BUILDCASE(callApplist)
479 H461BUILDCASE(preInvokeRequest)
480 H461BUILDCASE(preInvokeResponse)
481 H461BUILDCASE(invokeRequest)
482 H461BUILDCASE(invokeResponse)
483 H461BUILDCASE(invoke)
484 H461BUILDCASE(invokeStartList)
485 H461BUILDCASE(invokeNotify)
486 H461BUILDCASE(stopRequest)
487 H461BUILDCASE(stopNotify)
488 H461BUILDCASE(callRelease)
489 default: break;
490 }
491 success = true;
492 return *this;
493 }
494
ValidateToken(const PString & token)495 PBoolean H461AssetPDU::ValidateToken(const PString & token)
496 {
497 return false;
498 }
499
500 H461HANDLE(associateRequest)
H461HANDLE(associateResponse)501 H461HANDLE(associateResponse)
502 H461HANDLE(statusRequest)
503 H461HANDLE(statusResponse)
504 H461HANDLE(listRequest)
505 H461HANDLE(listResponse)
506 H461HANDLE(callApplist)
507 H461HANDLE(preInvokeRequest)
508 H461HANDLE(preInvokeResponse)
509 H461HANDLE(invokeRequest)
510 H461HANDLE(invokeResponse)
511 H461HANDLE(invoke)
512 H461HANDLE(invokeStartList)
513 H461HANDLE(invokeNotify)
514 H461HANDLE(stopRequest)
515 H461HANDLE(stopNotify)
516 H461HANDLE(callRelease)
517
518
519 H461BUILD(associateRequest)
520 H461BUILD(associateResponse)
521 H461BUILD(statusRequest)
522 H461BUILD(statusResponse)
523 H461BUILD(listRequest)
524 H461BUILD(listResponse)
525 H461BUILD(callApplist)
526 H461BUILD(preInvokeRequest)
527 H461BUILD(preInvokeResponse)
528 H461BUILD(invokeRequest)
529 H461BUILD(invokeResponse)
530 H461BUILD(invoke)
531 H461BUILD(invokeStartList)
532 H461BUILD(invokeNotify)
533 H461BUILD(stopRequest)
534 H461BUILD(stopNotify)
535 H461BUILD(callRelease)
536
537
538 //////////////////////////////////////////////////////////////////////////////////
539
540 PString GetGenericIdentifier(const H225_GenericIdentifier & gid)
541 {
542 if (gid.GetTag() == H225_GenericIdentifier::e_oid) {
543 const PASN_ObjectId & val = gid;
544 return val.AsString();
545 }
546 return PString();
547 }
548
SetGenericIdentifier(const PString & id,H225_GenericIdentifier & gid)549 void SetGenericIdentifier(const PString & id, H225_GenericIdentifier & gid)
550 {
551 gid.SetTag(H225_GenericIdentifier::e_oid);
552 PASN_ObjectId & val = gid;
553 val.SetValue(id);
554 }
555
GetDisplay(const H461_ArrayOf_ApplicationDisplay & display)556 PString GetDisplay(const H461_ArrayOf_ApplicationDisplay & display)
557 {
558 if (display.GetSize() > 0)
559 return display[0].m_display.GetValue();
560 return PString();
561 }
562
SetDisplay(const PString & id,H461_ArrayOf_ApplicationDisplay & display)563 void SetDisplay(const PString & id, H461_ArrayOf_ApplicationDisplay & display)
564 {
565 display.SetSize(1);
566 display[0].m_display.SetValue(id);
567 }
568
GetApplicationStatus(H461DataStore::Application & app,int associate,const H461_ApplicationStatus & application)569 void GetApplicationStatus(H461DataStore::Application & app, int associate, const H461_ApplicationStatus & application)
570 {
571 app.associate = associate;
572 app.id = GetGenericIdentifier(application.m_applicationId);
573 if (application.HasOptionalField(H461_ApplicationStatus::e_display))
574 app.displayName = GetDisplay(application.m_display);
575 if (application.HasOptionalField(H461_ApplicationStatus::e_avatar))
576 app.avatar = application.m_avatar.GetValue();
577 if (application.HasOptionalField(H461_ApplicationStatus::e_state))
578 app.state = (H461DataStore::ApplicationStates)application.m_state.GetTag();
579 }
580
581
SetApplicationStatus(const H461DataStore::Application & app,H461_ApplicationStatus & application)582 void SetApplicationStatus(const H461DataStore::Application & app, H461_ApplicationStatus & application)
583 {
584 SetGenericIdentifier(app.id, application.m_applicationId);
585
586 if (!app.displayName) {
587 application.IncludeOptionalField(H461_ApplicationStatus::e_display);
588 SetDisplay(app.displayName, application.m_display);
589 }
590
591 if (!app.avatar) {
592 application.IncludeOptionalField(H461_ApplicationStatus::e_avatar);
593 application.m_avatar.SetValue(app.avatar);
594 }
595
596 application.IncludeOptionalField(H461_ApplicationStatus::e_state);
597 application.m_state.SetTag(app.state);
598 }
599
SetApplicationStatus(const H461DataStore::ApplicationMap & apps,H461_ArrayOf_ApplicationStatus & applications)600 void SetApplicationStatus(const H461DataStore::ApplicationMap & apps, H461_ArrayOf_ApplicationStatus & applications)
601 {
602 applications.SetSize(apps.size());
603 int j = 0;
604 H461DataStore::ApplicationMap::const_iterator i = apps.begin();
605 while (i != apps.end()) {
606 SetApplicationStatus(i->second,applications[j]);
607 ++j;
608 ++i;
609 }
610 }
611
SetApplicationStatus(const std::list<int> & id,H461DataStore::ApplicationMap & apps,H461_ArrayOf_ApplicationStatus & applications)612 void SetApplicationStatus(const std::list<int> & id, H461DataStore::ApplicationMap & apps, H461_ArrayOf_ApplicationStatus & applications)
613 {
614 applications.SetSize(id.size());
615 int j = 0;
616 std::list<int>::const_iterator i = id.begin();
617 while (i != id.end()) {
618 SetApplicationStatus(apps[*i],applications[j]);
619 ++j;
620 ++i;
621 }
622 }
623
GetApplicationStatus(const H461_ArrayOf_ApplicationStatus & applications,H461DataStore::ApplicationList & id)624 void GetApplicationStatus(const H461_ArrayOf_ApplicationStatus & applications, H461DataStore::ApplicationList & id)
625 {
626 for (PINDEX j=0; j < applications.GetSize(); ++j) {
627 H461DataStore::Application app;
628 GetApplicationStatus(app,-1,applications[j]);
629 id.push_back(app);
630 }
631 }
632
BuildCallApplicationList(const H461DataStore::ApplicationMap & apps,std::list<int> & applist)633 void BuildCallApplicationList(const H461DataStore::ApplicationMap & apps, std::list<int> & applist)
634 {
635 H461DataStore::ApplicationMap::const_iterator i = apps.begin();
636 while(i != apps.end()) {
637 if (i->second.availableForCall)
638 applist.push_back(i->first);
639 ++i;
640 }
641 }
642
MergeCallApplicationList(const H461DataStore::ApplicationList & remote,H461DataStore::ApplicationMap & apps,std::list<int> & applist)643 void MergeCallApplicationList(const H461DataStore::ApplicationList & remote, H461DataStore::ApplicationMap & apps, std::list<int> & applist)
644 {
645 H461DataStore::ApplicationList::const_iterator i;
646 std::list<int>::iterator j = applist.begin();
647 while (j != applist.end()) {
648 bool found = false;
649 for (i = remote.begin(); i != remote.end(); ++i) {
650 if ((*i).id == apps[*j].id) {
651 found = true;
652 break;
653 }
654 }
655 if (!found)
656 j = applist.erase(j);
657 else
658 ++j;
659 }
660 }
661
H461DataStore()662 H461DataStore::H461DataStore()
663 : m_timeToLive(DEFAULT_ASSOCIATE_TTL), m_statusInterval(DEFAULT_STATUS_INTERVAL)
664 {
665
666 }
667
Application()668 H461DataStore::Application::Application()
669 : associate(-1), id(PString()), displayName(PString()), avatar(PString()), state(e_stateAvailable),
670 availableForCall(true), nextUpdate(0)
671 {
672
673 }
674
CallData()675 H461DataStore::CallData::CallData()
676 : callId(PString()), associate(-1), remote(PString())
677 {
678
679 }
680
MessageAsString(Messages msg)681 PString H461DataStore::MessageAsString(Messages msg) {
682 switch (msg) {
683 case e_id_associateRequest: return "AssociateRequest";
684 case e_id_associateResponse: return "AssociateResponse";
685 case e_id_statusRequest: return "StatusRequest";
686 case e_id_statusResponse: return "StatusResponse";
687 case e_id_listRequest: return "ListRequest";
688 case e_id_listResponse: return "listResponse";
689 case e_id_callApplist: return "CallAppList";
690 case e_id_preInvokeRequest: return "PreInvokeRequest";
691 case e_id_preInvokeResponse: return "PreInvokeResponse";
692 case e_id_invokeRequest: return "InvokeRequest";
693 case e_id_invokeResponse: return "InvokeResponse";
694 case e_id_invoke: return "Invoke";
695 case e_id_invokeStartList: return "InvokeStartList";
696 case e_id_invokeNotify: return "InvokeNotify";
697 case e_id_stopRequest: return "StopRequest";
698 case e_id_stopNotify: return "StopNotify";
699 case e_id_callRelease: return "CallRelease";
700 }
701 return "Unknown Msg";
702 }
703
704
705 /////////////////////////////////////
706 //Utilities
707
FindAssociateID(const PString & token)708 int H461DataStore::FindAssociateID(const PString & token)
709 {
710 if (token.IsEmpty()) return -1;
711
712 AssociateMap::const_iterator i = m_associates.begin();
713 while (i != m_associates.end()) {
714 if (i->second.token == token)
715 return i->first;
716 ++i;
717 }
718 return -1;
719 }
720
FindAssociateAddress(int id,PString & address,PString & token)721 void H461DataStore::FindAssociateAddress(int id, PString & address, PString & token)
722 {
723 AssociateMap::const_iterator i = m_associates.begin();
724 while (i != m_associates.end()) {
725 if (i->first == id) {
726 address = i->second.alias;
727 token = i->second.token;
728 break;
729 }
730 ++i;
731 }
732 }
733
FindApplicationID(const PString & id)734 int H461DataStore::FindApplicationID(const PString & id)
735 {
736 if (id.IsEmpty()) return -1;
737
738 ApplicationMap::const_iterator i = m_applications.begin();
739 while (i != m_applications.end()) {
740 if (i->second.id == id)
741 return i->first;
742 ++i;
743 }
744 return -1;
745 }
746
FindApplicationID(const PString & token,const PString & id)747 int H461DataStore::FindApplicationID(const PString & token, const PString & id)
748 {
749 if (token.IsEmpty()) return -1;
750
751 int assoc = FindAssociateID(token);
752 if (assoc < 0) return -1;
753
754 return FindApplicationID(assoc, id);
755 }
756
FindApplicationID(int assoc,const PString & id)757 int H461DataStore::FindApplicationID(int assoc, const PString & id)
758 {
759 ApplicationMap::const_iterator i = m_applications.begin();
760 while (i != m_applications.end()) {
761 if (i->second.associate == assoc && i->second.id == id)
762 return i->first;
763 ++i;
764 }
765 return -1;
766 }
767
FindCallData(const PString & callIdentifier)768 int H461DataStore::FindCallData(const PString & callIdentifier)
769 {
770 if (callIdentifier.IsEmpty()) return -1;
771
772 CallApplicationMap::const_iterator i = m_callapplications.begin();
773 while (i != m_callapplications.end()) {
774 if (i->second.callId == callIdentifier)
775 return i->first;
776 ++i;
777 }
778 return -1;
779 }
780
FindCall(int id)781 PString H461DataStore::FindCall(int id)
782 {
783 CallApplicationMap::const_iterator i = m_callapplications.begin();
784 while (i != m_callapplications.end()) {
785 if (i->first == id)
786 return i->second.callId;
787 ++i;
788 }
789 return PString();
790 }
791
FindApplications(DataType type,const PString & key,std::list<int> & id)792 PBoolean H461DataStore::FindApplications(DataType type, const PString & key, std::list<int> & id)
793 {
794 int idx = -1;
795 if (type == H461DataStore::e_associate) {
796 idx = FindAssociateID(key);
797 if (idx < 0) return false;
798 }
799
800 ApplicationMap::const_iterator i = m_applications.begin();
801 while (i != m_applications.end()) {
802 if ((type == H461DataStore::e_associate && i->second.associate == idx) ||
803 (type == H461DataStore::e_application && i->second.id == key))
804 id.push_back(i->first);
805 ++i;
806 }
807 return (!id.empty());
808 }
809
810
811 ////////////////////////////////////////
812
813 template <typename mapType>
H461ASSIGN(const mapType & map)814 int H461ASSIGN(const mapType & map) {
815 if (map.size() == 0)
816 return 0;
817 return map.rbegin()->first+1;
818 }
819
820 #define H461BUILDPDU(name) \
821 void H461DataStore::Build_##name(H323Connection* connection, const PString & token, PString & callid, int appID, \
822 const PString & invokeToken, const PString & aliasAddress, bool approved, msg_##name & pdu) { \
823 int assocID = FindAssociateID(token); int callID = FindCallData(callid); \
824 OnBuildIE(e_id_##name, connection, assocID, callID, appID, invokeToken, aliasAddress, approved); \
825
826
827 #define H461RECEIVEDPDU_HEAD(name) \
828 PBoolean H461DataStore::Received_##name(H323Connection* connection, const PString & token, PString & callid, const msg_##name & pdu) { \
829 int assocID = FindAssociateID(token); int callID = FindCallData(callid); int appID = -1; \
830 PString invokeToken = PString(); PString aliasAddress = PString(); bool approved = false;
831
832 #define H461RECEIVEDPDU_TAIL(name) \
833 return OnReceiveIE(e_id_##name, connection, assocID, callID, appID, invokeToken, aliasAddress, approved); }
834
835
UpdateApplication(int assoc,const H461_ApplicationStatus & application)836 void H461DataStore::UpdateApplication(int assoc, const H461_ApplicationStatus & application)
837 {
838 H461DataStore::Application app;
839 GetApplicationStatus(app, assoc, application);
840 app.associate = assoc;
841 int appID = FindApplicationID(assoc,app.id);
842 bool newEntry = false;
843 if (appID < 0) {
844 // New Application
845 appID = H461ASSIGN<ApplicationMap>(m_applications);
846 m_applications.insert(ApplicationMap::value_type(appID,app));
847 newEntry = true;
848 } else {
849 m_applications[appID].state = app.state;
850 m_applications[appID].nextUpdate += m_timeToLive;
851 }
852 OnUpdateApplication(appID, m_applications[appID], newEntry);
853 }
854
UpdateApplications(int assoc,const H461_ArrayOf_ApplicationStatus & applications)855 void H461DataStore::UpdateApplications(int assoc, const H461_ArrayOf_ApplicationStatus & applications)
856 {
857 for (PINDEX i=0; i<applications.GetSize(); ++i)
858 UpdateApplication(assoc, applications[i]);
859 }
860
BuildApplicationAvailable(int assocID,int callID,const PString & display,H461_ArrayOf_ApplicationAvailable & pdu)861 void H461DataStore::BuildApplicationAvailable(int assocID, int callID, const PString & display, H461_ArrayOf_ApplicationAvailable & pdu)
862 {
863 pdu.SetSize(0);
864
865 CallData c = m_callapplications[callID];
866 std::list<int>::const_iterator i = c.applications.begin();
867 while (i != c.applications.end()) {
868 if (m_applications[*i].associate == assocID) {
869 int sz = pdu.GetSize();
870 pdu.SetSize(sz+1);
871 pdu[sz].m_aliasAddress.SetSize(1);
872 H323SetAliasAddress(display, pdu[sz].m_aliasAddress[0]);
873 SetGenericIdentifier(m_applications[*i].id, pdu[sz].m_applicationId);
874
875 }
876 ++i;
877 }
878 }
879
SetApplicationAvailable(int assocID,const PString & callidentifier,const H461_ArrayOf_ApplicationAvailable & pdu)880 int H461DataStore::SetApplicationAvailable(int assocID, const PString & callidentifier, const H461_ArrayOf_ApplicationAvailable & pdu)
881 {
882 if (pdu.GetSize() == 0)
883 return -1;
884
885 CallData cData;
886 cData.callId = callidentifier;
887 cData.associate = assocID;
888 cData.remote = H323GetAliasAddressString(pdu[0].m_aliasAddress[0]);
889
890 for (PINDEX i=0; i< pdu.GetSize(); ++i) {
891 int appID = FindApplicationID(GetGenericIdentifier(pdu[i].m_applicationId));
892 if (appID > -1)
893 cData.applications.push_back(appID);
894 }
895
896 int callID = H461ASSIGN<CallApplicationMap>(m_callapplications);
897 m_callapplications.insert(CallApplicationMap::value_type(callID,cData));
898 return callID;
899 }
900
FindCallAssociates(int callID,std::list<int> & assoc)901 bool H461DataStore::FindCallAssociates(int callID, std::list<int> & assoc)
902 {
903 std::list<int> & apps = m_callapplications[callID].applications;
904 std::list<int>::const_iterator i = apps.begin();
905 while (i != apps.end()) {
906 assoc.push_back(m_applications[*i].associate);
907 ++i;
908 }
909 assoc.unique();
910 return (!assoc.empty());
911 }
912
GetCallApplicationList(const PString & call)913 void H461DataStore::GetCallApplicationList(const PString & call)
914 {
915 int callid = FindCallData(call);
916 if (callid > -1) {
917 std::list<int> apps = m_callapplications[callid].applications;
918 std::list<int>::const_iterator i = apps.begin();
919 while (i != apps.end()) {
920 Application app = m_applications[*i];
921 OnCallApplicationList(*i,app.displayName, app.avatar, (app.state == e_stateAvailable));
922 ++i;
923 }
924 }
925 }
926
GetApplicationCallList(int appid)927 void H461DataStore::GetApplicationCallList(int appid)
928 {
929 CallApplicationMap::const_iterator i = m_callapplications.begin();
930 while (i != m_callapplications.end()) {
931 std::list<int> apps = i->second.applications;
932 std::list<int>::const_iterator j = apps.begin();
933 while (j != apps.end()) {
934 if (*j == appid) {
935 OnApplicationCallList(appid, i->first, i->second.remote);
936 }
937 ++j;
938 }
939 ++i;
940 }
941 }
942
943 ////////////////////////////////////////
944
OnReceiveIE(Messages id,H323Connection * connection,int assoc,int callid,int appid,const PString & invokeToken,const PString & aliasAddress,bool approval)945 PBoolean H461DataStore::OnReceiveIE(Messages id, H323Connection* connection, int assoc, int callid, int appid, const PString & invokeToken, const PString & aliasAddress, bool approval)
946 {
947 PTRACE(2,"H461\tReceived " << MessageAsString(id) << " message.");
948
949 H323Connection::H461MessageInfo & info = connection->GetH461MessageInfo();
950 info.m_message = id;
951 if (assoc > -1) info.m_assocToken = m_associates[assoc].token;
952 if (callid > -1) info.m_callToken = m_callapplications[callid].callId;
953 if (appid > -1) info.m_applicationID = appid;
954
955 PBoolean endCall = false;
956 PBoolean reply = false;
957 PBoolean facilityMsg = false;
958
959 switch (id) {
960 case H461DataStore::e_id_associateRequest:
961 if (OnAssociateRequest(connection->GetRemotePartyAliases()[0], connection->GetRemotePartyName())) {
962 int Id = FindValidAssociate(connection->GetRemotePartyAliases()[0]);
963 int newId = (Id > -1) ? Id : CreateNewAssociation();
964 m_associates[newId].alias = connection->GetRemotePartyAliases()[0];
965 m_associates[newId].displayName = connection->GetRemotePartyName();
966 info.m_assocToken = m_associates[newId].token;
967 reply = true;
968 } else
969 endCall = true;
970 break;
971 case H461DataStore::e_id_associateResponse:
972 facilityMsg=true;
973 reply = true;
974 break;
975 case H461DataStore::e_id_statusRequest:
976 reply = true;
977 break;
978 case H461DataStore::e_id_listRequest:
979 reply = true;
980 break;
981 case H461DataStore::e_id_preInvokeRequest:
982 reply = true;
983 break;
984 case H461DataStore::e_id_invokeRequest:
985 if (OnInvokeRequest(connection->GetRemotePartyAliases()[0], connection->GetRemotePartyName(), appid)) {
986 if (connection->GetEndPoint().GetEndPointASSETMode() == H323EndPoint::e_H461ASSET) {
987 info.m_aliasAddress = connection->GetEndPoint().GetAliasNames()[0];
988 info.m_invokeToken = GenerateApplicationToken();
989 info.m_approved = true;
990 reply = true;
991 } else {
992 StartApplication(callid,appid,true);
993 info.m_message = -1;
994 }
995 } else {
996 info.m_approved = false;
997 reply = true;
998 }
999 break;
1000 case H461DataStore::e_id_invokeResponse:
1001 if (assoc > -1) {
1002 SendFacility(info.m_callToken, H461DataStore::e_id_invokeResponse,info.m_applicationID, invokeToken, aliasAddress, approval);
1003 endCall = true;
1004 } else {
1005 InvokeApplication(callid,appid,invokeToken,aliasAddress,approval);
1006 info.m_message = -1;
1007 }
1008 break;
1009
1010 case H461DataStore::e_id_invokeStartList:
1011 info.m_message = -1;
1012 break;
1013 case H461DataStore::e_id_listResponse:
1014 UpdateAssociateCall(callid, true);
1015 info.m_message = -1;
1016 break;
1017 case H461DataStore::e_id_invoke:
1018 MakeApplicationCall(appid, info.m_callToken, invokeToken, aliasAddress);
1019 info.m_message = -1;
1020 break;
1021 case H461DataStore::e_id_callApplist:
1022 OnAssociateCallStart(callid);
1023 info.m_message = -1;
1024 break;
1025 // End the connection
1026 case H461DataStore::e_id_callRelease:
1027 OnAssociateCallEnd(callid);
1028 Call_Terminate(callid);
1029 endCall = true;
1030 break;
1031 case H461DataStore::e_id_preInvokeResponse:
1032 SendFacility(info.m_callToken, H461DataStore::e_id_invokeRequest,info.m_applicationID);
1033 endCall = true;
1034 break;
1035 case H461DataStore::e_id_statusResponse:
1036 case H461DataStore::e_id_invokeNotify:
1037 case H461DataStore::e_id_stopNotify:
1038 case H461DataStore::e_id_stopRequest:
1039 endCall = true;
1040 break;
1041 };
1042
1043 if (reply) {
1044 if (connection->IsConnected() || facilityMsg)
1045 SendInternalFacility(connection,id+1);
1046 else
1047 info.m_message=id+1;
1048 }
1049 else if (endCall) {
1050 connection->ClearCall();
1051 }
1052
1053 return true;
1054 }
1055
SendInternalFacility(H323Connection * connection,int id)1056 void H461DataStore::SendInternalFacility(H323Connection * connection, int id)
1057 {
1058 H323Connection::H461MessageInfo & info = connection->GetH461MessageInfo();
1059 info.m_message=id;
1060
1061 H323SignalPDU facilityPDU;
1062 facilityPDU.BuildFacility(*connection, TRUE,8);
1063 H225_FeatureSet fs;
1064 if (connection->OnSendFeatureSet(H460_MessageType::e_facility, fs, false)) {
1065 facilityPDU.m_h323_uu_pdu.IncludeOptionalField(H225_H323_UU_PDU::e_genericData);
1066 H225_ArrayOf_FeatureDescriptor & fsn = fs.m_supportedFeatures;
1067 H225_ArrayOf_GenericData & data = facilityPDU.m_h323_uu_pdu.m_genericData;
1068 for (PINDEX i=0; i < fsn.GetSize(); i++) {
1069 PINDEX lastPos = data.GetSize();
1070 data.SetSize(lastPos+1);
1071 data[lastPos] = fsn[i];
1072 }
1073 }
1074 connection->WriteSignalPDU(facilityPDU);
1075 }
1076
OnBuildIE(Messages id,H323Connection * connection,int assoc,int callid,int appid,const PString & invokeToken,const PString & aliasAddress,bool approval)1077 void H461DataStore::OnBuildIE(Messages id, H323Connection* connection, int assoc, int callid, int appid, const PString & invokeToken, const PString & aliasAddress, bool approval)
1078 {
1079 PTRACE(2,"H461\tBuild " << MessageAsString(id) << " message.");
1080
1081 switch (id) {
1082 case H461DataStore::e_id_listResponse:
1083 m_callapplications[callid].remote = connection->GetRemotePartyAliases()[0];
1084 UpdateAssociateCall(callid, true);
1085 break;
1086 case H461DataStore::e_id_associateRequest:
1087 case H461DataStore::e_id_associateResponse:
1088 case H461DataStore::e_id_statusRequest:
1089 case H461DataStore::e_id_listRequest:
1090 case H461DataStore::e_id_preInvokeRequest:
1091 case H461DataStore::e_id_invokeRequest:
1092 case H461DataStore::e_id_invokeStartList:
1093 case H461DataStore::e_id_invokeResponse:
1094 case H461DataStore::e_id_invoke:
1095 case H461DataStore::e_id_statusResponse:
1096 case H461DataStore::e_id_callApplist:
1097 case H461DataStore::e_id_preInvokeResponse:
1098 case H461DataStore::e_id_invokeNotify:
1099 case H461DataStore::e_id_stopNotify:
1100 case H461DataStore::e_id_stopRequest:
1101 case H461DataStore::e_id_callRelease:
1102 break;
1103 };
1104 }
1105
LoadDataStoreAssociate(int id,const PString & alias,const PString & displayName,const PString & token,PInt64 expire,PBoolean alert)1106 void H461DataStore::LoadDataStoreAssociate(int id, const PString & alias, const PString & displayName, const PString & token, PInt64 expire, PBoolean alert)
1107 {
1108 Associate associate;
1109 associate.token = token;
1110 associate.expire = expire;
1111 associate.alias = alias;
1112 associate.displayName = displayName;
1113 m_associates.insert(AssociateMap::value_type(id,associate));
1114 }
1115
LoadDataStoreApplication(int id,int associate,const PString & appID,const PString & displayName,const PString & avatar,int state,PBoolean availableForCall)1116 void H461DataStore::LoadDataStoreApplication(int id, int associate, const PString & appID, const PString & displayName, const PString & avatar, int state, PBoolean availableForCall)
1117 {
1118 Application cApp;
1119 cApp.associate = associate;
1120 cApp.avatar = avatar;
1121 cApp.displayName = displayName;
1122 cApp.id = appID;
1123 cApp.state = (H461DataStore::ApplicationStates)state;
1124 cApp.availableForCall = availableForCall;
1125 m_applications.insert(ApplicationMap::value_type(id,cApp));
1126 }
1127
Call_Initiate(const PString & callid,int assoc)1128 int H461DataStore::Call_Initiate(const PString & callid, int assoc)
1129 {
1130 int callID = FindCallData(callid);
1131 if (callID > -1)
1132 return callID;
1133
1134 CallData cData;
1135 cData.callId = callid;
1136 cData.associate = assoc;
1137 BuildCallApplicationList(m_applications,cData.applications);
1138
1139 callID = H461ASSIGN<CallApplicationMap>(m_callapplications);
1140 m_callapplications.insert(CallApplicationMap::value_type(callID,cData));
1141 return callID;
1142 }
1143
Call_Terminate(int callID)1144 void H461DataStore::Call_Terminate(int callID)
1145 {
1146 CallApplicationMap::iterator i = m_callapplications.find(callID);
1147 if (i != m_callapplications.end()) {
1148 m_callapplications.erase(i);
1149 }
1150 }
1151
CreateNewAssociation()1152 int H461DataStore::CreateNewAssociation()
1153 {
1154 Associate associate;
1155 OpalGloballyUniqueID guid;
1156 associate.token = guid.AsString();
1157 associate.expire = PTimer::Tick().GetSeconds() + DEFAULT_ASSOCIATE_TTL;
1158 int id = H461ASSIGN<AssociateMap>(m_associates);
1159 m_associates.insert(AssociateMap::value_type(id,associate));
1160 return id;
1161 }
1162
FindValidAssociate(const PString & alias)1163 int H461DataStore::FindValidAssociate(const PString & alias)
1164 {
1165 AssociateMap::const_iterator i = m_associates.begin();
1166 while (i != m_associates.end()) {
1167 if (i->second.alias == alias) {
1168 return i->first;
1169 }
1170 ++i;
1171 }
1172 return -1;
1173 }
1174
GenerateApplicationToken()1175 PString H461DataStore::GenerateApplicationToken()
1176 {
1177 OpalGloballyUniqueID guid;
1178 return guid.AsString();
1179 }
1180
UpdateAssociateCall(const PString & call,PBoolean startCall)1181 void H461DataStore::UpdateAssociateCall(const PString & call, PBoolean startCall) {
1182 int callid = FindCallData(call);
1183 UpdateAssociateCall(callid, startCall);
1184 }
1185
UpdateAssociateCall(int callid,PBoolean startCall)1186 void H461DataStore::UpdateAssociateCall(int callid, PBoolean startCall)
1187 {
1188 std::list<int> assoc;
1189 if (FindCallAssociates(callid,assoc)) {
1190 std::list<int>::const_iterator i = assoc.begin();
1191 while (i != assoc.end()) {
1192 if (startCall)
1193 MakeAssociateCall(H461DataStore::e_id_callApplist, *i ,callid);
1194 else
1195 MakeAssociateCall(H461DataStore::e_id_callRelease, *i ,callid);
1196 ++i;
1197 }
1198 }
1199 }
1200
StartApplication(const PString & callToken,int i)1201 void H461DataStore::StartApplication(const PString & callToken, int i)
1202 {
1203 int callid = FindCallData(callToken);
1204 StartApplication(callid, i);
1205 }
1206
StartApplication(int callid,int i,bool remote)1207 void H461DataStore::StartApplication(int callid, int i, bool remote)
1208 {
1209 CallData & data = m_callapplications[callid];
1210 std::list<int> app = data.applications;
1211 std::list<int>::const_iterator j = app.begin();
1212 while (j != app.end()) {
1213 if (*j == i) {
1214 Application & app = m_applications[i];
1215 if (remote)
1216 MakeAssociateCall(H461DataStore::e_id_invokeRequest,app.associate,callid,i);
1217 else
1218 MakeAssociateCall(H461DataStore::e_id_preInvokeRequest,app.associate,callid,i);
1219 return;
1220 }
1221 ++j;
1222 }
1223 }
1224
StartASSETApplication(int callid,int i)1225 void H461DataStore::StartASSETApplication(int callid, int i)
1226 {
1227 CallData & data = m_callapplications[callid];
1228 std::list<int> app = data.applications;
1229 std::list<int>::const_iterator j = app.begin();
1230 while (j != app.end()) {
1231 if (*j == i)
1232 MakeAssociateCall(H461DataStore::e_id_preInvokeResponse,data.associate,callid,i);
1233 ++j;
1234 }
1235 }
1236
1237
InvokeApplication(int callid,int i,const PString & invokeToken,const PString & aliasAddress,bool approval)1238 void H461DataStore::InvokeApplication(int callid, int i, const PString & invokeToken, const PString & aliasAddress, bool approval)
1239 {
1240 CallData & data = m_callapplications[callid];
1241 std::list<int> app = data.applications;
1242 std::list<int>::const_iterator j = app.begin();
1243 while (j != app.end()) {
1244 if (*j == i) {
1245 Application & app = m_applications[i];
1246 MakeAssociateCall(H461DataStore::e_id_invoke,app.associate,callid,i,invokeToken,aliasAddress,approval);
1247 return;
1248 }
1249 ++j;
1250 }
1251 }
1252
1253
1254
1255 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1256
1257 H461BUILDPDU(associateRequest)
1258 H225_TimeToLive & ttl = pdu.m_timeToLive;
1259 ttl = (unsigned)m_timeToLive;
1260 }
1261
1262 H461BUILDPDU(associateResponse)
1263 H323SetGUIDString(m_associates[assocID].token,pdu.m_associateToken);
1264 H225_TimeToLive & ttl = pdu.m_timeToLive;
1265 ttl = (unsigned)m_timeToLive;
1266 pdu.IncludeOptionalField(msg_associateResponse::e_statusInterval);
1267 H225_TimeToLive & stat = pdu.m_statusInterval;
1268 stat = (unsigned)m_statusInterval;
1269 OnUpdateAssociate(assocID, m_associates[assocID], true);
1270 }
1271
1272 H461BUILDPDU(statusRequest)
1273 // Nothing to do.
1274 }
1275
1276 H461BUILDPDU(statusResponse)
1277 SetApplicationStatus(m_applications,pdu);
1278 }
1279
1280 H461BUILDPDU(listRequest)
1281 callid = connection->GetCallIdentifier().AsString();
1282 callID = Call_Initiate(callid);
1283 SetApplicationStatus(m_callapplications[callID].applications,m_applications,pdu);
1284 }
1285
1286 H461BUILDPDU(listResponse)
1287 SetApplicationStatus(m_callapplications[callID].applications,m_applications,pdu);
1288 }
1289
1290 H461BUILDPDU(callApplist)
1291 BuildApplicationAvailable(assocID, callID, m_callapplications[callID].remote, pdu);
1292 }
1293
1294 H461BUILDPDU(preInvokeRequest)
1295 if (appID > -1) {
1296 SetGenericIdentifier(m_applications[appID].id,pdu.m_applicationId);
1297 }
1298 }
1299
1300 H461BUILDPDU(preInvokeResponse)
1301 if (appID > -1)
1302 SetApplicationStatus(m_applications[appID], pdu);
1303 }
1304
1305 H461BUILDPDU(invokeRequest)
1306 if (appID > -1) {
1307 pdu.SetTag(msg_invokeRequest::e_applicationId);
1308 H225_GenericIdentifier & id = pdu;
1309 SetGenericIdentifier(m_applications[appID].id,id);
1310 }
1311 }
1312
1313 H461BUILDPDU(invokeResponse)
1314 if (!approved) {
1315 pdu.SetTag(msg_invokeResponse::e_declined);
1316 H461_InvokeFailReason & reason = pdu;
1317 reason.SetTag(H461_InvokeFailReason::e_declined);
1318 } else {
1319 pdu.SetTag(msg_invokeResponse::e_approved);
1320 H461_ApplicationInvoke & invoke = pdu;
1321 SetGenericIdentifier(m_applications[appID].id,invoke.m_applicationId);
1322 H323SetGUIDString(invokeToken,invoke.m_invokeToken);
1323 invoke.m_aliasAddress.SetSize(1);
1324 H323SetAliasAddress(aliasAddress, invoke.m_aliasAddress[0]);
1325 }
1326 }
1327
1328 H461BUILDPDU(invoke)
1329 SetGenericIdentifier(m_applications[appID].id,pdu.m_applicationId);
1330 H323SetGUIDString(invokeToken,pdu.m_invokeToken);
1331 pdu.m_aliasAddress.SetSize(1);
1332 H323SetAliasAddress(aliasAddress, pdu.m_aliasAddress[0]);
1333 }
1334
1335 H461BUILDPDU(invokeStartList)
1336 pdu.SetSize(1);
1337 SetGenericIdentifier(m_applications[appID].id,pdu[0].m_applicationId);
1338 H323SetGUIDString(invokeToken,pdu[0].m_invokeToken);
1339 }
1340
1341 H461BUILDPDU(invokeNotify)
1342 SetApplicationStatus(m_applications[appID],pdu);
1343 }
1344
1345 H461BUILDPDU(stopRequest)
1346 pdu.SetSize(1);
1347 SetGenericIdentifier(m_applications[appID].id,pdu[0].m_applicationId);
1348 }
1349
1350 H461BUILDPDU(stopNotify)
1351 pdu.SetSize(1);
1352 SetGenericIdentifier(m_applications[appID].id,pdu[0].m_applicationId);
1353 }
1354
1355 H461BUILDPDU(callRelease)
1356 // Nothing to do
1357 }
1358
1359 H461RECEIVEDPDU_HEAD(associateRequest)
1360 long ttl = pdu.m_timeToLive;
1361 invokeToken = PString(ttl);
1362 H461RECEIVEDPDU_TAIL(associateRequest)
1363
1364
1365 H461RECEIVEDPDU_HEAD(associateResponse)
1366 Associate associate;
1367 associate.token = H323GetGUIDString(pdu.m_associateToken);
1368 associate.expire = PTimer::Tick().GetSeconds() + pdu.m_timeToLive.GetValue();
1369 associate.alias = connection->GetRemotePartyAliases()[0];
1370 associate.displayName = connection->GetRemotePartyName();
1371 assocID = H461ASSIGN<AssociateMap>(m_associates);
1372 m_associates.insert(AssociateMap::value_type(assocID,associate));
1373 OnUpdateAssociate(assocID, associate, true);
1374 H461RECEIVEDPDU_TAIL(associateResponse)
1375
1376
1377 H461RECEIVEDPDU_HEAD(statusRequest)
1378 // nothing to do
1379 H461RECEIVEDPDU_TAIL(statusRequest)
1380
1381
1382 H461RECEIVEDPDU_HEAD(statusResponse)
1383 UpdateApplications(assocID, pdu);
1384 H461RECEIVEDPDU_TAIL(statusResponse)
1385
1386
1387 H461RECEIVEDPDU_HEAD(listRequest)
1388 callid = connection->GetCallIdentifier().AsString();
1389 callID = Call_Initiate(callid);
1390 H461DataStore::ApplicationList remote;
1391 GetApplicationStatus(pdu,remote);
1392 MergeCallApplicationList(remote, m_applications, m_callapplications[callID].applications);
1393 remote.clear();
1394 H461RECEIVEDPDU_TAIL(listRequest)
1395
1396
1397 H461RECEIVEDPDU_HEAD(listResponse)
1398 H461DataStore::ApplicationList remote;
1399 GetApplicationStatus(pdu,remote);
1400 m_callapplications[callID].remote = connection->GetRemotePartyAliases()[0];
1401 MergeCallApplicationList(remote, m_applications, m_callapplications[callID].applications);
1402 remote.clear();
1403 H461RECEIVEDPDU_TAIL(listResponse)
1404
1405
1406 H461RECEIVEDPDU_HEAD(callApplist)
1407 callID = SetApplicationAvailable(assocID, callid, pdu);
1408 H461RECEIVEDPDU_TAIL(callApplist)
1409
1410
1411 H461RECEIVEDPDU_HEAD(preInvokeRequest)
1412 appID = FindApplicationID(GetGenericIdentifier(pdu.m_applicationId));
1413 H461RECEIVEDPDU_TAIL(preInvokeRequest)
1414
1415
1416 H461RECEIVEDPDU_HEAD(preInvokeResponse)
1417 appID = FindApplicationID(assocID, GetGenericIdentifier(pdu.m_applicationId));
1418 UpdateApplication(assocID, pdu);
1419 H461RECEIVEDPDU_TAIL(preInvokeResponse)
1420
1421
1422 H461RECEIVEDPDU_HEAD(invokeRequest)
1423 if (pdu.GetTag() == msg_invokeRequest::e_applicationId) {
1424 const H225_GenericIdentifier & id = pdu;
1425 appID = FindApplicationID(GetGenericIdentifier(id));
1426 }
1427 H461RECEIVEDPDU_TAIL(invokeRequest)
1428
1429
1430 H461RECEIVEDPDU_HEAD(invokeResponse)
1431 if (pdu.GetTag() == msg_invokeResponse::e_declined) {
1432 approved = false;
1433 const H461_InvokeFailReason & reason = pdu;
1434 invokeToken = reason.GetTag();
1435 } else {
1436 approved = true;
1437 const H461_ApplicationInvoke & invoke = pdu;
1438 appID = FindApplicationID(GetGenericIdentifier(invoke.m_applicationId));
1439 invokeToken = H323GetGUIDString(invoke.m_invokeToken);
1440 if (invoke.m_aliasAddress.GetSize() > 0)
1441 aliasAddress = H323GetAliasAddressString(invoke.m_aliasAddress[0]);
1442 }
1443 H461RECEIVEDPDU_TAIL(invokeResponse)
1444
1445
1446 H461RECEIVEDPDU_HEAD(invoke)
1447 appID = FindApplicationID(GetGenericIdentifier(pdu.m_applicationId));
1448 invokeToken = H323GetGUIDString(pdu.m_invokeToken);
1449 if (pdu.m_aliasAddress.GetSize() > 0)
1450 aliasAddress = H323GetAliasAddressString(pdu.m_aliasAddress[0]);
1451 H461RECEIVEDPDU_TAIL(invoke)
1452
1453
1454 H461RECEIVEDPDU_HEAD(invokeStartList)
1455 if (pdu.GetSize() > 0) {
1456 appID = FindApplicationID(GetGenericIdentifier(pdu[0].m_applicationId));
1457 invokeToken = H323GetGUIDString(pdu[0].m_invokeToken);
1458 }
1459 H461RECEIVEDPDU_TAIL(invokeStartList)
1460
1461
1462 H461RECEIVEDPDU_HEAD(invokeNotify)
1463 UpdateApplication(assocID, pdu);
1464 H461RECEIVEDPDU_TAIL(invokeNotify)
1465
1466
1467 H461RECEIVEDPDU_HEAD(stopRequest)
1468 if (pdu.GetSize() > 0)
1469 appID = FindApplicationID(GetGenericIdentifier(pdu[0].m_applicationId));
1470 H461RECEIVEDPDU_TAIL(stopRequest)
1471
1472
1473 H461RECEIVEDPDU_HEAD(stopNotify)
1474 if (pdu.GetSize() > 0)
1475 appID = FindApplicationID(GetGenericIdentifier(pdu[0].m_applicationId));
1476 H461RECEIVEDPDU_TAIL(stopNotify)
1477
1478
1479 H461RECEIVEDPDU_HEAD(callRelease)
1480 // TODO: Release all current calls
1481 H461RECEIVEDPDU_TAIL(callRelease)
1482
1483 #endif
1484
1485
1486