SipSubscribeServer* SipSubscribeServer::buildBasicServer(SipUserAgent& userAgent, const char* eventType) { // Create a default publisher container SipPublishContentMgr* publishContent = new SipPublishContentMgr(); // Create a default event handler SipSubscribeServerEventHandler* eventHandler = new SipSubscribeServerEventHandler(); // Create a default subscription mgr SipSubscriptionMgr* subscriptionMgr = new SipSubscriptionMgr(); SipSubscribeServer* newServer = new SipSubscribeServer(SipSubscribeServer::terminationReasonNone, userAgent, *publishContent, *subscriptionMgr, *eventHandler); if (eventType && *eventType) { // Enable the server to accept the given SIP event package newServer->enableEventType(eventType, &userAgent, publishContent, eventHandler, subscriptionMgr, SipSubscribeServer::standardVersionCallback ); } return newServer; }
SipSubscribeServer* SipSubscribeServer::buildBasicServer(SipUserAgent& userAgent, const char* eventType) { SipSubscribeServer* newServer = NULL; // Create a default publisher container SipPublishContentMgr* publishContent = new SipPublishContentMgr(); // Create a default event handler SipSubscribeServerEventHandler* eventHandler = new SipSubscribeServerEventHandler(); // Create a default subscription mgr SipSubscriptionMgr* subscriptionMgr = new SipSubscriptionMgr(); newServer = new SipSubscribeServer(userAgent, *publishContent, *subscriptionMgr, *eventHandler); if(eventType && *eventType) { // Enable the server to accept the given SIP event package newServer->enableEventType(eventType, &userAgent, publishContent, eventHandler, subscriptionMgr); } return(newServer); }
void setUp() { hostIp = "127.0.0.1"; eventName = SIP_EVENT_MESSAGE_SUMMARY; mwiMimeType = CONTENT_TYPE_SIMPLE_MESSAGE_SUMMARY;; // Construct a user agent that will function both as the subscriber // and the notfier. // Construct the URI of the notifier, which is also the URI of // the subscriber. // Also construct the name-addr version of the URI, which may be // different if it has a "transport" parameter. // And the resource-id to use, which is the AOR with any // parameters stripped off. createTestSipUserAgent(hostIp, "111", userAgentp, aor, aor_name_addr, aor_contact_name_addr, resource_id); subServerp = SipSubscribeServer::buildBasicServer(*userAgentp, eventName); subServerp->start(); // Get pointers to the Subscription Manager and Dialog Manager. subMgrp = subServerp->getSubscriptionMgr(eventName); CPPUNIT_ASSERT(subMgrp); dialogMgrp = subMgrp->getDialogMgr(); CPPUNIT_ASSERT(dialogMgrp); // Create a simple Subscription client // Register an interest in SUBSCRIBE responses and NOTIFY requests // for this event type userAgentp->addMessageObserver(incomingClientMsgQueue, SIP_SUBSCRIBE_METHOD, FALSE, // no requests TRUE, // reponses TRUE, // incoming FALSE, // no outgoing eventName, NULL, NULL); userAgentp->addMessageObserver(incomingClientMsgQueue, SIP_NOTIFY_METHOD, TRUE, // requests FALSE, // not reponses TRUE, // incoming FALSE, // no outgoing eventName, NULL, NULL); }
void SipSubscribeServer::contentChangeCallback(void* applicationData, const char* resourceId, const char* eventTypeKey, const char* eventType, UtlBoolean isDefaultContent) { SipSubscribeServer* subServer = (SipSubscribeServer*)applicationData; subServer->notifySubscribers(resourceId, eventTypeKey, eventType, isDefaultContent); }
void SipSubscribeServer::contentChangeCallback(void* applicationData, const char* resourceId, const char* eventTypeKey, const char* eventType, const char* reason) { SipSubscribeServer* subServer = (SipSubscribeServer*) applicationData; subServer->notifySubscribers(resourceId, eventTypeKey, eventType, reason); }
int main(int argc, char* argv[]) { bool bError = true ; int iSipPort, iRtpPort ; bool bLoopback ; char* szIdentity ; char* szUsername ; char* szPassword ; char* szRealm ; char* szStunServer ; char* szProxy ; bool bDialogEvents ; // The default run time is 2^31-1 seconds, which is over 68 years. long int runTime = LONG_MAX; SIPX_INST hInst ; SIPX_LINE hLine ; // Support for the dialog event notifier. // Component for holding the subscription data SipSubscriptionMgr* pSubscriptionMgr; // Component for granting the subscription rights SipSubscribeServerEventHandler* pPolicyHolder; // Component for publishing the event contents SipPublishContentMgr* pPublisher; SipSubscribeServer* pSubscribeServer; // The dialog event publisher DialogEventPublisher* pDialogEvents; // Parse Arguments if (parseArgs(argc, argv, &iDuration, &iSipPort, &iRtpPort, &g_szPlayTones, &g_szFile, &bLoopback, &szIdentity, &szUsername, &szPassword, &szRealm, &szStunServer, &szProxy, &bDialogEvents, &g_callAnswerDelay, &g_timestamp, &runTime) && (iDuration > 0) && (portIsValid(iSipPort)) && (portIsValid(iRtpPort))) { if (bLoopback) { initLoopback() ; } // initialize sipx TAPI-like API sipxConfigSetLogLevel(LOG_LEVEL_DEBUG) ; sipxConfigSetLogFile("ReceiveCall.log"); if (sipxInitialize(&hInst, iSipPort, iSipPort, 5061, iRtpPort, 16, szIdentity) == SIPX_RESULT_SUCCESS) { // Start dialog event notifier if requested. if (bDialogEvents) { // Get pointer to the call manager. CallManager* pCallManager = ((SIPX_INSTANCE_DATA*) hInst)->pCallManager; SipUserAgent* pUserAgent = ((SIPX_INSTANCE_DATA*) hInst)->pSipUserAgent; // Start the SIP Subscribe Server pSubscriptionMgr = new SipSubscriptionMgr(); pPolicyHolder = new SipSubscribeServerEventHandler; pPublisher = new SipPublishContentMgr; pSubscribeServer = new SipSubscribeServer(*pUserAgent, *pPublisher, *pSubscriptionMgr, *pPolicyHolder); pSubscribeServer->enableEventType(DIALOG_EVENT_TYPE, NULL, NULL, NULL, NULL, SipSubscribeServer::standardVersionCallback); pSubscribeServer->start(); // Create the dialog event publisher pDialogEvents = new DialogEventPublisher(pCallManager, pPublisher); pCallManager->addTaoListener(pDialogEvents); pDialogEvents->start(); } if (szProxy) { sipxConfigSetOutboundProxy(hInst, szProxy); } sipxConfigEnableRport(hInst, true) ; if (szStunServer) { sipxConfigEnableStun(hInst, szStunServer, 28) ; } sipxEventListenerAdd(hInst, EventCallBack, NULL) ; hLine = lineInit(hInst, szIdentity, szUsername, szPassword, szRealm) ; dumpLocalContacts(hInst) ; // Run as long as requested. for (long int i = 0; i < runTime; i++) { SLEEP(1000) ; } lineShutdown(hInst, hLine); // Wait a bit, so that we can re-send the REGISTER if it needs // authorization. SLEEP(5000); } else { printf("unable to initialize sipXtapi layer\n") ; } } else { usage(argv[0]) ; } return (int) bError ; }
void subscribeMwiClientTest() { smClientExpiration = -1; smNumClientNotifiesReceived = 0; smLastClientNotifyReceived = NULL; smNumClientSubResponsesReceived = 0; smLastClientSubResponseReceived = NULL; UtlString resourceId("[email protected]:"); UtlString eventTypeKey("message-summary"); UtlString eventType(eventTypeKey); UtlString from("Frida<sip:111@localhost:"); UtlString to("Tia<sip:222@localhost:"); UtlString contact("sip:[email protected]:"); char portString[20]; sprintf(portString, "%d", UNIT_TEST_SIP_PORT); resourceId.append(portString); from.append(portString); from.append('>'); to.append(portString); to.append('>'); contact.append(portString); SipUserAgent* userAgent = new SipUserAgent(UNIT_TEST_SIP_PORT, UNIT_TEST_SIP_PORT); userAgent->start(); // Set up the subscribe client SipDialogMgr* clientDialogMgr = new SipDialogMgr(); SipRefreshManager* refreshMgr = new SipRefreshManager(*userAgent, *clientDialogMgr); refreshMgr->start(); SipSubscribeClient* subClient = new SipSubscribeClient(*userAgent, *clientDialogMgr, *refreshMgr); subClient->start(); // Set up the subscribe server SipSubscribeServer* subServer = SipSubscribeServer::buildBasicServer(*userAgent, eventType); SipSubscriptionMgr* subMgr = subServer->getSubscriptionMgr(eventType); SipDialogMgr* serverDialogMgr = subMgr->getDialogMgr(); SipPublishContentMgr* contentMgr = subServer->getPublishMgr(eventType); HttpBody* preexistingBodyPtr = NULL; UtlBoolean isDefaultContent; subServer->start(); // Enable the handler for the MWI server subServer->enableEventType(eventType, userAgent); //CPPUNIT_ASSERT(TRUE); //ASSERT_STR_EQUAL("a", "a"); // Create a crude Subscription server/observer OsMsgQ incomingServerMsgQueue; // Register an interest in SUBSCRIBE requests // for this event type userAgent->addMessageObserver(incomingServerMsgQueue, SIP_SUBSCRIBE_METHOD, TRUE, // requests FALSE, // no reponses TRUE, // incoming FALSE, // no outgoing eventType, NULL, NULL); OsMsgQ incomingClientMsgQueue; userAgent->addMessageObserver(incomingClientMsgQueue, SIP_SUBSCRIBE_METHOD, FALSE, // no requests TRUE, // reponses TRUE, // incoming FALSE, // no outgoing eventType, NULL, NULL); // Should not be any pre-existing content CPPUNIT_ASSERT(!contentMgr->getContent(resourceId, eventTypeKey, NULL, preexistingBodyPtr, isDefaultContent)); int numDefaultContent = -1; int numResourceSpecificContent = -1; int numCallbacksRegistered = -1; contentMgr->getStats(numDefaultContent, numResourceSpecificContent, numCallbacksRegistered); CPPUNIT_ASSERT(numDefaultContent == 0); CPPUNIT_ASSERT(numResourceSpecificContent == 0); CPPUNIT_ASSERT(numCallbacksRegistered == 1); // Create a subscribe request, send it and keep it refreshed UtlString earlyDialogHandle; CPPUNIT_ASSERT(subClient->addSubscription(resourceId, eventType, from, to, contact, 60, // seconds expiration this, subStateCallback, notifyCallback, earlyDialogHandle)); contentMgr->getStats(numDefaultContent, numResourceSpecificContent, numCallbacksRegistered); CPPUNIT_ASSERT(numDefaultContent == 0); CPPUNIT_ASSERT(numResourceSpecificContent == 0); CPPUNIT_ASSERT(numCallbacksRegistered == 1); // See if a subscribe was sent and received /*OsTime messageTimeout(5, 0); // 5 seconds OsMsg* osMessage = NULL; const SipMessage* subscribeResponse = NULL; const SipMessage* notifyRequest = NULL; incomingServerMsgQueue.receive(osMessage, messageTimeout); CPPUNIT_ASSERT(osMessage); int msgType = osMessage->getMsgType(); int msgSubType = osMessage->getMsgSubType(); CPPUNIT_ASSERT(msgType == OsMsg::PHONE_APP); CPPUNIT_ASSERT(msgSubType == SipMessage::NET_SIP_MESSAGE); const SipMessage* sipMessage = ((SipMessageEvent*)osMessage)->getMessage(); int messageType = ((SipMessageEvent*)osMessage)->getMessageStatus(); CPPUNIT_ASSERT(sipMessage); CPPUNIT_ASSERT(messageType == SipMessageEvent::APPLICATION);*/ const SipMessage* serverSideSubRequest = NULL; CPPUNIT_ASSERT(removeMessage(incomingServerMsgQueue, 5000, // milliseconds serverSideSubRequest)); CPPUNIT_ASSERT(serverSideSubRequest); // Sub request got to server const SipMessage* clientSideSubResponse = NULL; CPPUNIT_ASSERT(removeMessage(incomingClientMsgQueue, 5000, // milliseconds clientSideSubResponse)); CPPUNIT_ASSERT(clientSideSubResponse); //UtlString clientStateString; //subClient->dumpStates(clientStateString); //printf("client states:\n%s\n", clientStateString.data()); int waitIterations = 0; while(smLastClientNotifyReceived == NULL || smLastClientSubResponseReceived == NULL) { OsTask::delay(100); waitIterations++; if(waitIterations >= 100) { break; } } CPPUNIT_ASSERT(smLastClientSubResponseReceived); CPPUNIT_ASSERT(smLastClientNotifyReceived); SipMessage* firstSubResponse = smLastClientSubResponseReceived; smLastClientSubResponseReceived = NULL; int firstSubCseq; firstSubResponse->getCSeqField(&firstSubCseq, NULL); SipMessage* firstNotifyRequest = smLastClientNotifyReceived; smLastClientNotifyReceived = NULL; int firstNotifyCseq; firstNotifyRequest->getCSeqField(&firstNotifyCseq, NULL); CPPUNIT_ASSERT(firstSubCseq == 1); CPPUNIT_ASSERT(firstNotifyCseq == 0); //subClient->dumpStates(clientStateString); //printf("client states:\n%s\n", clientStateString.data()); //UtlString dialogMgrDumpString; //clientDialogMgr.toString(dialogMgrDumpString); //printf("Client Dialog manager dump 1:\n%s\n", // dialogMgrDumpString.data()); // The refresh manager should re-SUBSCRIBE // Wait for the next notify request and subscribe response int secondMessageWait = 60; int resendTimeout = 0.55 * secondMessageWait; if(resendTimeout < 40) { resendTimeout = 40; } for(int i = 0; i < secondMessageWait - 1; i++) { if(i == resendTimeout - 1) { printf("v"); } else { printf("="); } } printf("v\n"); SipMessage* secondSubResponse = NULL; SipMessage* secondNotifyRequest = NULL; while(secondNotifyRequest == NULL || secondSubResponse == NULL) { OsTask::delay(1000); if(smLastClientSubResponseReceived) { secondSubResponse = smLastClientSubResponseReceived; smLastClientSubResponseReceived = NULL; } if(smLastClientNotifyReceived) { secondNotifyRequest = smLastClientNotifyReceived; smLastClientNotifyReceived = NULL; } printf("."); waitIterations++; if(waitIterations >= secondMessageWait) { printf("\n"); break; } } //subClient->dumpStates(clientStateString); //printf("client states:\n%s\n", clientStateString.data()); //clientDialogMgr.toString(dialogMgrDumpString); //printf("Client Dialog manager dump 2:\n%s\n", // dialogMgrDumpString.data()); CPPUNIT_ASSERT(removeMessage(incomingServerMsgQueue, 5000, // milliseconds serverSideSubRequest)); CPPUNIT_ASSERT(serverSideSubRequest); // Sub request got to server //UtlString subRequestDump; //int len; //serverSideSubRequest->getBytes(&subRequestDump, &len); //printf("server side sub request:\n%s\n", // subRequestDump.data()); CPPUNIT_ASSERT(removeMessage(incomingClientMsgQueue, 5000, // milliseconds clientSideSubResponse)); CPPUNIT_ASSERT(clientSideSubResponse); // Sub respon got to client //UtlString subResponseDump; //clientSideSubResponse->getBytes(&subResponseDump, &len); //printf("client side sub response:\n%s\n", // subResponseDump.data()); CPPUNIT_ASSERT(secondNotifyRequest); CPPUNIT_ASSERT(secondSubResponse); int secondSubCseq = -1; int secondNotifyCseq = -1; smLastClientSubResponseReceived = NULL; secondSubResponse->getCSeqField(&secondSubCseq, NULL); smLastClientNotifyReceived = NULL; secondNotifyRequest->getCSeqField(&secondNotifyCseq, NULL); CPPUNIT_ASSERT(firstSubCseq < secondSubCseq); CPPUNIT_ASSERT(firstNotifyCseq < secondNotifyCseq); // Unregister the queues so we stop receiving messages on them userAgent->removeMessageObserver(incomingServerMsgQueue); userAgent->removeMessageObserver(incomingClientMsgQueue); refreshMgr->requestShutdown(); subClient->requestShutdown(); }
// Basic server functionality test. // Checks that server answers SUBSCRIBES, sends NOTIFY, sends NOTIFY // when content changes. void basicSubscriptionTest() { // Verify that authentication and authorization are // disabled by default. { SipSubscribeServerEventHandler* eventHandler = subServerp->getEventHandler(eventName); CPPUNIT_ASSERT(eventHandler); SipMessage bogusSubscribeRequest; SipMessage bogusSubscribeResponse; CPPUNIT_ASSERT(eventHandler->isAuthenticated(bogusSubscribeRequest, bogusSubscribeResponse)); CPPUNIT_ASSERT(eventHandler->isAuthorized(bogusSubscribeRequest, bogusSubscribeResponse)); } // Send a SUBSCRIBE to the notifier. SipMessage mwiSubscribeRequest; { UtlString c; CallId::getNewCallId(c); mwiSubscribeRequest.setSubscribeData(notifier_aor, // request URI subscriber_name_addr, // From notifier_name_addr, // To c, // Call-Id 0, // CSeq eventName, // Event mwiMimeType, // Accept NULL, // Event id subscriber_name_addr, // Contact NULL, // Route 3600 // Expires ); } CPPUNIT_ASSERT(subscriberUserAgentp->send(mwiSubscribeRequest)); // We should get a 202 response and a NOTIFY request in the queue OsTime messageTimeout(1, 0); // 1 second { const SipMessage* subscribeResponse; const SipMessage* notifyRequest; runListener(incomingClientMsgQueue, *subscriberUserAgentp, messageTimeout, messageTimeout, notifyRequest, subscribeResponse, SIP_OK_CODE, FALSE, 0, NULL); // We should have received a SUBSCRIBE response and a NOTIFY request. CPPUNIT_ASSERT(subscribeResponse); CPPUNIT_ASSERT(notifyRequest); // Check that the response code and CSeq method in the // subscribe response are OK. { CPPUNIT_ASSERT(subscribeResponse->getResponseStatusCode() == SIP_ACCEPTED_CODE); UtlString subscribeMethod; subscribeResponse->getCSeqField(NULL, &subscribeMethod); ASSERT_STR_EQUAL(SIP_SUBSCRIBE_METHOD, subscribeMethod.data()); } // Check that the method in the notify request is OK. { UtlString notifyMethod; notifyRequest->getRequestMethod(¬ifyMethod); ASSERT_STR_EQUAL(SIP_NOTIFY_METHOD, notifyMethod.data()); } // Check that the Event header in the NOTIFY is the same as the // one in the SUBSCRIBE. { UtlString notifyEventHeader; UtlString subscribeEventHeader; notifyRequest->getEventField(notifyEventHeader); mwiSubscribeRequest.getEventField(subscribeEventHeader); ASSERT_STR_EQUAL(subscribeEventHeader, notifyEventHeader); } // The NOTIFY should have no body because none has been published yet. { const HttpBody* bodyPtr = notifyRequest->getBody(); CPPUNIT_ASSERT(bodyPtr == NULL); } // The Contact in the subscribe response should be the notifier. ASSERT_STR_EQUAL(notifier_contact_name_addr, subscribeResponse-> getHeaderValue(0, SIP_CONTACT_FIELD)); // The Contact in the NOTIFY should be the notifier. CPPUNIT_ASSERT(notifyRequest-> getHeaderValue(0, SIP_CONTACT_FIELD)); ASSERT_STR_EQUAL(notifier_contact_name_addr, notifyRequest-> getHeaderValue(0, SIP_CONTACT_FIELD)); } // Publish some content (mwiStateString) for this resourceID { HttpBody* newMwiBodyPtr = new HttpBody(mwiStateString, strlen(mwiStateString), mwiMimeType); SipPublishContentMgr* publishMgr = subServerp->getPublishMgr(eventName); CPPUNIT_ASSERT(publishMgr); publishMgr->publish(notifier_resource_id, eventName, eventName, 1, &newMwiBodyPtr); } // Should get a NOTIFY queued up { const SipMessage* subscribeResponse; const SipMessage* secondNotify; runListener(incomingClientMsgQueue, *subscriberUserAgentp, messageTimeout, messageTimeout, secondNotify, subscribeResponse, SIP_OK_CODE, FALSE, 0, NULL); CPPUNIT_ASSERT(secondNotify); CPPUNIT_ASSERT(subscribeResponse == NULL); // Check that the body of the NOTIFY is what we expect (mwiStateString). { const HttpBody* secondNotifyBody = secondNotify->getBody(); CPPUNIT_ASSERT(secondNotifyBody); ssize_t notifyBodySize; const char* notifyBodyBytes; secondNotifyBody->getBytes(¬ifyBodyBytes, ¬ifyBodySize); CPPUNIT_ASSERT(notifyBodyBytes); ASSERT_STR_EQUAL(mwiStateString, notifyBodyBytes); } // Check that the Dialog Manager reports that the dialog handle is OK. { UtlString secondNotifyDialogHandle; secondNotify->getDialogHandle(secondNotifyDialogHandle); CPPUNIT_ASSERT(!secondNotifyDialogHandle.isNull()); CPPUNIT_ASSERT(dialogMgrp->dialogExists(secondNotifyDialogHandle)); CPPUNIT_ASSERT(dialogMgrp->countDialogs() == 1); } } // Create a new one-time SUBSCRIBE SipMessage oneTimeMwiSubscribeRequest; { UtlString c; CallId::getNewCallId(c); oneTimeMwiSubscribeRequest. setSubscribeData(notifier_aor, // request URI subscriber_name_addr, // From notifier_name_addr, // To c, // Call-Id 0, // CSeq eventName, // Event mwiMimeType, // Accept NULL, // Event id subscriber_name_addr, // Contact NULL, // Route 0 // Expires ); } CPPUNIT_ASSERT(subscriberUserAgentp->send(oneTimeMwiSubscribeRequest)); { const SipMessage* oneTimeNotifyRequest; const SipMessage* oneTimeSubscribeResponse; runListener(incomingClientMsgQueue, *subscriberUserAgentp, messageTimeout, messageTimeout, oneTimeNotifyRequest, oneTimeSubscribeResponse, SIP_OK_CODE, FALSE, 0, NULL); // Validate the one time subscribe response and notify request CPPUNIT_ASSERT(oneTimeSubscribeResponse); CPPUNIT_ASSERT(oneTimeNotifyRequest); { CPPUNIT_ASSERT(oneTimeSubscribeResponse->getResponseStatusCode() == SIP_ACCEPTED_CODE); UtlString oneTimeSubscribeMethod; oneTimeSubscribeResponse->getCSeqField(NULL, &oneTimeSubscribeMethod); ASSERT_STR_EQUAL(SIP_SUBSCRIBE_METHOD, oneTimeSubscribeMethod.data()); UtlString oneTimeSubscribeEventHeader; oneTimeSubscribeResponse->getEventField(oneTimeSubscribeEventHeader); // The Event: header never appears in responses -- see RFC 3265 section 7.2. // The "R" in the "where" column means that "Event" appears only in // requests -- see RFC 3261 table 2 and page 160. ASSERT_STR_EQUAL("", oneTimeSubscribeEventHeader); } { UtlString oneTimeNotifyMethod; oneTimeNotifyRequest->getRequestMethod(&oneTimeNotifyMethod); ASSERT_STR_EQUAL(SIP_NOTIFY_METHOD, oneTimeNotifyMethod.data()); UtlString oneTimeNotifyEventHeader; oneTimeNotifyRequest->getEventField(oneTimeNotifyEventHeader); // The Event: header should appear in the NOTIFY. ASSERT_STR_EQUAL(SIP_EVENT_MESSAGE_SUMMARY, oneTimeNotifyEventHeader); } { const HttpBody* oneTimeBodyPtr = oneTimeNotifyRequest->getBody(); CPPUNIT_ASSERT(oneTimeBodyPtr != NULL); const char* oneTimeBodyString; ssize_t oneTimeNotifyBodySize; oneTimeBodyPtr->getBytes(&oneTimeBodyString, &oneTimeNotifyBodySize); ASSERT_STR_EQUAL(mwiStateString, oneTimeBodyString); } { UtlString oneTimeNotifyDialogHandle; oneTimeNotifyRequest->getDialogHandle(oneTimeNotifyDialogHandle); CPPUNIT_ASSERT(!oneTimeNotifyDialogHandle.isNull()); CPPUNIT_ASSERT(dialogMgrp->dialogExists(oneTimeNotifyDialogHandle)); CPPUNIT_ASSERT(dialogMgrp->countDialogs() == 2); long now = OsDateTime::getSecsSinceEpoch(); subMgrp->removeOldSubscriptions(now + 1); // The one time subscription should get garbage collected // leaving only the persistant 3600 second subscription CPPUNIT_ASSERT(dialogMgrp->countDialogs() == 1); } } }