reSIProcate/DialogUsageManager  9694
testSMIMEInvite.cxx
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include "config.h"
00003 #endif
00004 
00005 #include "resip/dum/DialogUsageManager.hxx"
00006 #include "resip/dum/ClientRegistration.hxx"
00007 #include "resip/dum/ClientInviteSession.hxx"
00008 #include "resip/dum/ServerInviteSession.hxx"
00009 #include "resip/dum/ClientAuthManager.hxx"
00010 
00011 #include "resip/dum/RegistrationHandler.hxx"
00012 #include "resip/dum/InviteSessionHandler.hxx"
00013 #include "resip/dum/DumShutdownHandler.hxx"
00014 
00015 #include "resip/dum/MasterProfile.hxx"
00016 #include "resip/stack/ShutdownMessage.hxx"
00017 
00018 #include "resip/stack/SdpContents.hxx"
00019 #include "resip/stack/Pkcs7Contents.hxx"
00020 #include "resip/stack/MultipartSignedContents.hxx"
00021 #include "resip/stack/MultipartAlternativeContents.hxx"
00022 #include "resip/stack/Mime.hxx"
00023 
00024 #include "resip/stack/SecurityAttributes.hxx"
00025 #include "resip/stack/Helper.hxx"
00026 
00027 #include "rutil/FdPoll.hxx"
00028 #include "rutil/Log.hxx"
00029 #include "rutil/Logger.hxx"
00030 
00031 #ifdef WIN32
00032 #include "resip/stack/ssl/WinSecurity.hxx"
00033 #else
00034 #include "resip/stack/ssl/Security.hxx"
00035 #endif
00036 
00037 #include "TestDumHandlers.hxx"
00038 
00039 #include <time.h>
00040 #include <sstream>
00041 
00042 using namespace std;
00043 using namespace resip;
00044 
00045 #define RESIPROCATE_SUBSYSTEM Subsystem::TEST
00046 
00047 
00048 class TestSMIMEInviteHandler : public TestClientRegistrationHandler,
00049                                public TestInviteSessionHandler,
00050                                public TestDumShutdownHandler
00051 {
00052    public:
00053       
00054       TestSMIMEInviteHandler(Security *sec) : handles(0), security(sec), registered(0), done(0), dumShutDown(0), connected(0), callFailed(false)
00055       {
00056       }
00057 
00058       virtual ~TestSMIMEInviteHandler()
00059       {
00060       }
00061 
00062       void resetRegistered(void)
00063       {
00064          registered = 0;
00065       }
00066 
00067       bool isConnected(void)
00068       {
00069          return (connected == 2);
00070       }
00071       
00072       bool isDumShutDown(void)
00073       {
00074          return (dumShutDown == 2);
00075       }
00076 
00077       bool isRegistered(void)
00078       {
00079          return (registered == 2);
00080       }
00081       
00082       bool isDone(void)
00083       {
00084          return (done == 2);
00085          
00086       }
00087 
00088       bool isCallFailed(void)
00089       {
00090          return callFailed;
00091       }
00092 
00093       SdpContents* generateBody()
00094       {
00095          Data* txt = new Data("v=0\r\n"
00096                               "o=1900 369696545 369696545 IN IP4 192.168.2.15\r\n"
00097                               "s=X-Lite\r\n"
00098                               "c=IN IP4 192.168.2.15\r\n"
00099                               "t=0 0\r\n"
00100                               "m=audio 8000 RTP/AVP 8 3 101\r\n"
00101                               "a=rtpmap:8 pcma/8000\r\n"
00102                               "a=rtpmap:3 gsm/8000\r\n"
00103                               "a=rtpmap:101 telephone-event/8000\r\n"
00104                               "a=fmtp:101 0-15\r\n");
00105          
00106          HeaderFieldValue hfv(txt->data(), txt->size());
00107          SdpContents *sdp = new SdpContents(hfv, Mime("application", "sdp"));
00108          return sdp;
00109       }
00110    
00111 
00112       virtual void onSuccess(ClientRegistrationHandle r,
00113                              const SipMessage& response)
00114       {
00115          InfoLog( << "ClientRegistrationHandler::onSuccess" );
00116          handles.push_back(r);
00117          registered++;
00118       }
00119 
00120       virtual void onConnected(ClientInviteSessionHandle,
00121                                const SipMessage& msg)
00122       {
00123          InfoLog( << "ClientInviteSessionHandler::onConnected" );
00124          connected++;
00125       }
00126 
00127       using TestClientRegistrationHandler::onFailure;
00128       virtual void onFailure(ClientInviteSessionHandle,
00129                              const SipMessage& msg)
00130       {
00131          InfoLog( << "TestInviteSessionHander::onFailure" );
00132          callFailed = true;
00133       }
00134 
00135       using TestInviteSessionHandler::onNewSession;
00136       virtual void onNewSession(ServerInviteSessionHandle is,
00137                                 InviteSession::OfferAnswerType oat,
00138                                 const SipMessage& msg)
00139       {
00140          InfoLog( << "ServerInviteSessionHandler::onNewSession" );
00141          sis = is;
00142          is->provisional(180);
00143       }
00144 
00145       virtual void onConnected(InviteSessionHandle,
00146                                const SipMessage& msg)
00147       {
00148          InfoLog( << "InviteSessionHandler::onConnected()" );
00149          connected++;
00150       }
00151 
00152       virtual void onTerminated(InviteSessionHandle,
00153                                 InviteSessionHandler::TerminatedReason reason,
00154                                 const SipMessage* msg)
00155       {
00156          InfoLog( << "InviteSessionHandler::onTerminated");
00157          done++;
00158       }
00159 
00160       virtual void onOffer(InviteSessionHandle is,
00161                            const SipMessage& msg,
00162                            const SdpContents& sdp)
00163       {
00164          InfoLog( << "InviteSessionHandler::onOffer" );
00165          InfoLog( << "Server received SDP: " << sdp );
00166 
00167          const SecurityAttributes *attr = msg.getSecurityAttributes();
00168          if (attr)
00169          {
00170             InfoLog( << *attr );
00171          }
00172          else
00173          {
00174             InfoLog( << "no Security Attributes" );
00175          }
00176 
00177          if (sis.isValid())
00178          {
00179             NameAddr fromAor(msg.header(h_From).uri());
00180             NameAddr toAor(msg.header(h_To).uri());
00181             is->provideAnswer(*generateBody());
00182             sis->accept();
00183          }
00184       }
00185       
00186       virtual void onAnswer(InviteSessionHandle,
00187                             const SipMessage& msg,
00188                             const SdpContents& sdp)
00189       {
00190          InfoLog( << "InviteSessionHandler::onAnswer");
00191          InfoLog( << "Client received SDP: " << sdp );
00192 
00193          const SecurityAttributes *attr = msg.getSecurityAttributes();
00194          if (attr)
00195          {
00196             InfoLog( << *attr );
00197          }
00198          else
00199          {
00200             InfoLog( << "no Security Attributes" );
00201          }
00202          
00203       }
00204 
00205       virtual void onDumCanBeDeleted() 
00206       {
00207          InfoLog( << "DumShutDownHandler::onDumCanBeDeleted" );
00208          dumShutDown++;
00209       }
00210 
00211       virtual void onReferNoSub(InviteSessionHandle, const SipMessage& msg)
00212       {
00213          InfoLog(<< "InviteSessionHandler::onReferNoSub(): " << msg.brief());
00214       }
00215 
00216    public:
00217       std::vector<ClientRegistrationHandle> handles;
00218       ServerInviteSessionHandle sis;
00219 
00220    private:
00221       Security *security;
00222       int registered;
00223       int done;
00224       int dumShutDown;
00225       int connected;
00226       bool callFailed;
00227       
00228 };
00229 
00230 
00231 int 
00232 main (int argc, char** argv)
00233 {
00234    if ( argc < 5 ) {
00235       cout << "usage: " << argv[0] << " sip:user1 passwd1 sip:user2 passwd2" << endl;
00236       return 1;
00237    }
00238 
00239    Log::initialize(Log::Cout, Log::Debug, argv[0]);
00240 
00241    NameAddr clientAor(argv[1]);
00242    Data clientPasswd(argv[2]);
00243    NameAddr serverAor(argv[3]);
00244    Data serverPasswd(argv[4]);
00245 
00246 #ifdef WIN32
00247    Security* security = new WinSecurity;
00248 #else
00249    Security* security = new Security;
00250 #endif
00251 
00252    TestSMIMEInviteHandler handler(security);
00253 
00254    // Shared FdPollGrp
00255    std::auto_ptr<FdPollGrp> pollGrp(FdPollGrp::create());
00256 
00257    // set up UAC
00258    SipStack clientStack(security,
00259                         DnsStub::EmptyNameserverList,
00260                         0,
00261                         false,
00262                         0,
00263                         0,
00264                         pollGrp.get());
00265    DialogUsageManager clientDum(clientStack);
00266    srand(time(NULL));
00267    clientDum.addTransport(UDP, 0, V4);
00268    clientDum.addTransport(TCP, 0, V4);
00269    clientDum.addTransport(TLS, 0, V4);
00270 #ifdef USE_IPV6
00271    clientDum.addTransport(UDP, 0, V6);
00272    clientDum.addTransport(TCP, 0, V6);
00273    clientDum.addTransport(TLS, 0, V6);
00274 #endif
00275 
00276    SharedPtr<MasterProfile> clientProfile(new MasterProfile);   
00277    auto_ptr<ClientAuthManager> clientAuth(new ClientAuthManager());   
00278 
00279    clientDum.setClientAuthManager(clientAuth);
00280    clientDum.setClientRegistrationHandler(&handler);
00281    clientDum.setInviteSessionHandler(&handler);
00282 
00283    clientProfile->setDefaultFrom(clientAor);
00284    clientProfile->setDigestCredential(clientAor.uri().host(),clientAor.uri().user(),clientPasswd);
00285    clientProfile->setDefaultRegistrationTime(60);
00286    clientProfile->addSupportedMethod(INVITE);
00287    clientProfile->addSupportedMimeType(INVITE, Mime("application", "pkcs7-mime"));
00288    clientProfile->addSupportedMimeType(INVITE, Mime("multipart", "signed"));
00289    clientProfile->addSupportedMimeType(INVITE, Mime("multipart", "alternative"));
00290    clientDum.setMasterProfile(clientProfile);
00291 
00292    //set up UAS
00293    SipStack serverStack(security,
00294                         DnsStub::EmptyNameserverList,
00295                         0,
00296                         false,
00297                         0,
00298                         0,
00299                         pollGrp.get());
00300    DialogUsageManager serverDum(serverStack);
00301    //serverDum.addTransport(UDP, 0, V4);
00302    serverDum.addTransport(TCP, 0, V4);
00303    //serverDum.addTransport(TLS, 0, V4);
00304 
00305    SharedPtr<MasterProfile> serverProfile(new MasterProfile);
00306    std::auto_ptr<ClientAuthManager> serverAuth(new ClientAuthManager);
00307 
00308    serverDum.setClientAuthManager(serverAuth);
00309    serverDum.setClientRegistrationHandler(&handler);
00310    serverDum.setInviteSessionHandler(&handler);
00311 
00312    serverProfile->setDefaultFrom(serverAor);
00313    serverProfile->setDigestCredential(serverAor.uri().host(),serverAor.uri().user(),serverPasswd);
00314    serverProfile->setDefaultRegistrationTime(60);
00315    serverProfile->addSupportedMethod(INVITE);
00316    serverProfile->addSupportedMimeType(INVITE, Mime("application", "pkcs7-mime"));
00317    serverProfile->addSupportedMimeType(INVITE, Mime("multipart", "signed"));
00318    serverProfile->addSupportedMimeType(INVITE, Mime("multipart", "alternative"));
00319    serverDum.setMasterProfile(serverProfile);
00320 
00321    enum
00322       {
00323          Registering,
00324          Inviting,
00325          Waiting,
00326          HangingUp,
00327          Unregistering,
00328          ShuttingDown,
00329          Finished
00330       } state;
00331    time_t endTime=0;
00332 
00333    // register client and server
00334    SharedPtr<SipMessage> clientRegMessage = clientDum.makeRegistration(clientAor);
00335    clientDum.send(clientRegMessage);
00336    SharedPtr<SipMessage> serverRegMessage = serverDum.makeRegistration(serverAor);
00337    serverDum.send(serverRegMessage);
00338    state = Registering;
00339 
00340    while (state != Finished)
00341    {
00342       // This waits on IO for both stacks; this is the canonical way to drive
00343       // multiple stacks with the same thread. We could make two calls to 
00344       // process(), but this requires more calls to epoll_wait/select.
00345       pollGrp->waitAndProcess(resipMin(clientStack.getTimeTillNextProcessMS(),
00346                                        serverStack.getTimeTillNextProcessMS()));
00347       clientStack.processTimers();
00348       serverStack.processTimers();
00349 
00350       while(clientDum.process() || serverDum.process());
00351 
00352       switch (state)
00353       {
00354          case Registering:
00355          {
00356             if (handler.isRegistered())
00357             {
00358                InfoLog( << "Sending INVITE request" );
00359                clientDum.send(clientDum.makeInviteSession(serverAor,
00360                                                           handler.generateBody()));
00361                state = Inviting;
00362             }
00363             break;
00364          }
00365          
00366          case Inviting:
00367          {
00368             if (handler.isConnected())
00369             {
00370                InfoLog( << "Starting timer, waiting for 5 seconds" );
00371                endTime = time(NULL) + 5;
00372                state = Waiting;
00373             }
00374             break;
00375          }
00376          
00377          case Waiting:
00378          {
00379             if (handler.isCallFailed())
00380             {
00381                InfoLog( << "Call Failed" );
00382                for (std::vector<ClientRegistrationHandle>::iterator it = handler.handles.begin();
00383                     it != handler.handles.end(); it++)
00384                {
00385                   (*it)->end();
00386                }
00387                state = Unregistering;
00388             }
00389 
00390             if (time(NULL) > endTime)
00391             {
00392                InfoLog( << "Timer expired, hanging up" );
00393                handler.sis->end();
00394                state = HangingUp;
00395             }
00396             break;
00397          }
00398 
00399          case HangingUp:
00400          {
00401             if (handler.isDone())
00402             {
00403                for (std::vector<ClientRegistrationHandle>::iterator it = handler.handles.begin();
00404                        it != handler.handles.end(); it++)
00405                {
00406                   (*it)->end();
00407                }
00408                state = Unregistering;
00409             }
00410             break;
00411          }
00412          
00413          case Unregistering:
00414          {
00415             if (handler.isRegistered())
00416             {
00417                InfoLog( << "Shutting down" );
00418                serverDum.shutdown(&handler);
00419                clientDum.shutdown(&handler);
00420                state = ShuttingDown;
00421             }
00422             break;
00423          }
00424          
00425          case ShuttingDown:
00426          {
00427             if (handler.isDumShutDown()) 
00428             {
00429                InfoLog( << "Finished" );
00430                state = Finished;
00431             }
00432             
00433             break;
00434          }
00435 
00436          default:
00437          {
00438             InfoLog( << "Unrecognised state" );
00439             assert(0);
00440          }
00441       }
00442       
00443    }
00444 
00445    return 0;
00446 
00447 }
00448 
00449 /* ====================================================================
00450  * The Vovida Software License, Version 1.0 
00451  * 
00452  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00453  * 
00454  * Redistribution and use in source and binary forms, with or without
00455  * modification, are permitted provided that the following conditions
00456  * are met:
00457  * 
00458  * 1. Redistributions of source code must retain the above copyright
00459  *    notice, this list of conditions and the following disclaimer.
00460  * 
00461  * 2. Redistributions in binary form must reproduce the above copyright
00462  *    notice, this list of conditions and the following disclaimer in
00463  *    the documentation and/or other materials provided with the
00464  *    distribution.
00465  * 
00466  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00467  *    and "Vovida Open Communication Application Library (VOCAL)" must
00468  *    not be used to endorse or promote products derived from this
00469  *    software without prior written permission. For written
00470  *    permission, please contact vocal@vovida.org.
00471  *
00472  * 4. Products derived from this software may not be called "VOCAL", nor
00473  *    may "VOCAL" appear in their name, without prior written
00474  *    permission of Vovida Networks, Inc.
00475  * 
00476  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00477  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00478  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00479  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00480  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00481  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00482  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00483  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00484  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00485  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00486  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00487  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00488  * DAMAGE.
00489  * 
00490  * ====================================================================
00491  * 
00492  * This software consists of voluntary contributions made by Vovida
00493  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00494  * Inc.  For more information on Vovida Networks, Inc., please see
00495  * <http://www.vovida.org/>.
00496  *
00497  */