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