reSIProcate/repro  9694
RegSyncServer.cxx
Go to the documentation of this file.
00001 #include <cassert>
00002 #include <sstream>
00003 
00004 #include <resip/stack/Symbols.hxx>
00005 #include <resip/stack/Tuple.hxx>
00006 #include <rutil/Data.hxx>
00007 #include <rutil/DnsUtil.hxx>
00008 #include <rutil/Logger.hxx>
00009 #include <rutil/ParseBuffer.hxx>
00010 #include <rutil/Socket.hxx>
00011 #include <rutil/TransportType.hxx>
00012 #include <rutil/Timer.hxx>
00013 
00014 #include "repro/XmlRpcServerBase.hxx"
00015 #include "repro/XmlRpcConnection.hxx"
00016 #include "repro/RegSyncServer.hxx"
00017 
00018 using namespace repro;
00019 using namespace resip;
00020 using namespace std;
00021 
00022 #define RESIPROCATE_SUBSYSTEM Subsystem::REPRO
00023 
00024 
00025 RegSyncServer::RegSyncServer(resip::InMemorySyncRegDb* regDb,
00026                              int port, 
00027                              IpVersion version) :
00028    XmlRpcServerBase(port, version),
00029    mRegDb(regDb)
00030 {
00031    assert(mRegDb);
00032    mRegDb->setHandler(this);
00033 }
00034 
00035 RegSyncServer::~RegSyncServer()
00036 {
00037    mRegDb->setHandler(0);
00038 }
00039 
00040 void 
00041 RegSyncServer::sendResponse(unsigned int connectionId, 
00042                            unsigned int requestId, 
00043                            const Data& responseData, 
00044                            unsigned int resultCode, 
00045                            const Data& resultText)
00046 {
00047    std::stringstream ss;
00048    ss << Symbols::CRLF << responseData << "    <Result Code=\"" << resultCode << "\"";
00049    ss << ">" << resultText.xmlCharDataEncode() << "</Result>" << Symbols::CRLF;
00050    XmlRpcServerBase::sendResponse(connectionId, requestId, ss.str().c_str(), resultCode >= 200 /* isFinal */);
00051 }
00052 
00053 void 
00054 RegSyncServer::sendRegistrationModifiedEvent(unsigned int connectionId, const resip::Uri& aor)
00055 {
00056    ContactList contacts;
00057 
00058    mRegDb->getContacts(aor, contacts);
00059    sendRegistrationModifiedEvent(connectionId, aor, contacts);
00060 }
00061 
00062 void 
00063 RegSyncServer::sendRegistrationModifiedEvent(unsigned int connectionId, const resip::Uri& aor, const ContactList& contacts)
00064 {
00065    std::stringstream ss;
00066    bool infoFound = false;
00067 
00068    ss << "<reginfo>" << Symbols::CRLF;
00069    ss << "   <aor>" << Data::from(aor).xmlCharDataEncode() << "</aor>" << Symbols::CRLF;
00070    ContactList::const_iterator cit = contacts.begin();
00071    for(; cit != contacts.end(); cit++)
00072    {
00073       const ContactInstanceRecord& rec = *cit;
00074       if(!rec.mReceivedFrom.onlyUseExistingConnection)
00075       {
00076           streamContactInstanceRecord(ss, rec);
00077           infoFound = true;
00078       }
00079    }
00080    ss << "</reginfo>" << Symbols::CRLF;
00081 
00082    if(infoFound)
00083    {
00084       sendEvent(connectionId, ss.str().c_str());
00085    }
00086 }
00087 
00088 void 
00089 RegSyncServer::handleRequest(unsigned int connectionId, unsigned int requestId, const resip::Data& request)
00090 {
00091    DebugLog (<< "RegSyncServer::handleRequest:  connectionId=" << connectionId << ", requestId=" << requestId << ", request=" << request);
00092 
00093    try
00094    {
00095       ParseBuffer pb(request);
00096       XMLCursor xml(pb);
00097 
00098       if(isEqualNoCase(xml.getTag(), "InitialSync"))
00099       {
00100          handleInitialSyncRequest(connectionId, requestId, xml);
00101       }
00102       else 
00103       {
00104          WarningLog(<< "RegSyncServer::handleRequest: Received XML message with unknown method: " << xml.getTag());
00105          sendResponse(connectionId, requestId, Data::Empty, 400, "Unknown method");
00106       }
00107    }
00108    catch(resip::BaseException& e)
00109    {
00110       WarningLog(<< "RegSyncServer::handleRequest: ParseException: " << e);
00111       sendResponse(connectionId, requestId, Data::Empty, 400, "Parse error");
00112    }
00113 }
00114   
00115 void 
00116 RegSyncServer::handleInitialSyncRequest(unsigned int connectionId, unsigned int requestId, XMLCursor& xml)
00117 {
00118    InfoLog(<< "RegSyncServer::handleInitialSyncRequest");
00119 
00120    // Check for correct Version
00121    unsigned int version = 0;
00122    if(xml.firstChild())
00123    {
00124       if(isEqualNoCase(xml.getTag(), "request"))
00125       {
00126          if(xml.firstChild())
00127          {
00128             if(isEqualNoCase(xml.getTag(), "version"))
00129             {
00130                if(xml.firstChild())
00131                {
00132                   version = xml.getValue().convertUnsignedLong();
00133                   xml.parent();
00134                }
00135             }
00136             xml.parent();
00137          }
00138       }
00139       xml.parent();
00140    }
00141 
00142    if(version == REGSYNC_VERSION)
00143    {
00144       mRegDb->initialSync(connectionId);
00145       sendResponse(connectionId, requestId, Data::Empty, 200, "Initial Sync Completed.");
00146    }
00147    else
00148    {
00149       sendResponse(connectionId, requestId, Data::Empty, 505, "Version not supported.");
00150    }
00151 }
00152 
00153 void 
00154 RegSyncServer::streamContactInstanceRecord(std::stringstream& ss, const ContactInstanceRecord& rec)
00155 {
00156     UInt64 now = Timer::getTimeSecs();
00157 
00158     ss << "   <contactinfo>" << Symbols::CRLF;
00159     ss << "      <contacturi>" << Data::from(rec.mContact.uri()).xmlCharDataEncode() << "</contacturi>" << Symbols::CRLF;
00160     // If contact is expired or removed, then pass expires time as 0, otherwise send number of seconds until expirey
00161     ss << "      <expires>" << (((rec.mRegExpires == 0) || (rec.mRegExpires <= now)) ? 0 : (rec.mRegExpires-now)) << "</expires>" << Symbols::CRLF;
00162     ss << "      <lastupdate>" << now-rec.mLastUpdated << "</lastupdate>" << Symbols::CRLF;
00163     if(rec.mReceivedFrom.getPort() != 0)
00164     {
00165         resip::Data binaryFlowToken;
00166         Tuple::writeBinaryToken(rec.mReceivedFrom,binaryFlowToken);            
00167         ss << "      <receivedfrom>" << binaryFlowToken.base64encode() << "</receivedfrom>" << Symbols::CRLF;
00168     }
00169     if(rec.mPublicAddress.getType() != UNKNOWN_TRANSPORT)
00170     {
00171         resip::Data binaryFlowToken;
00172         Tuple::writeBinaryToken(rec.mPublicAddress,binaryFlowToken);            
00173         ss << "      <publicaddress>" << binaryFlowToken.base64encode() << "</publicaddress>" << Symbols::CRLF;
00174     }
00175     NameAddrs::const_iterator naIt = rec.mSipPath.begin();
00176     for(; naIt != rec.mSipPath.end(); naIt++)
00177     {
00178         ss << "      <sippath>" << Data::from(naIt->uri()).xmlCharDataEncode() << "</sippath>" << Symbols::CRLF;
00179     }
00180     if(!rec.mInstance.empty())
00181     {
00182         ss << "      <instance>" << rec.mInstance.xmlCharDataEncode() << "</instance>" << Symbols::CRLF;
00183     }
00184     if(rec.mRegId != 0)
00185     {
00186         ss << "      <regid>" << rec.mRegId << "</regid>" << Symbols::CRLF;
00187     }
00188     ss << "   </contactinfo>" << Symbols::CRLF;
00189 }
00190 
00191 void 
00192 RegSyncServer::onAorModified(const resip::Uri& aor, const ContactList& contacts)
00193 {
00194    sendRegistrationModifiedEvent(0, aor, contacts);
00195 }
00196 
00197 void 
00198 RegSyncServer::onInitialSyncAor(unsigned int connectionId, const resip::Uri& aor, const ContactList& contacts)
00199 {
00200    sendRegistrationModifiedEvent(connectionId, aor, contacts);
00201 }
00202 
00203 /* ====================================================================
00204  * The Vovida Software License, Version 1.0 
00205  * 
00206  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00207  * Copyright (c) 2010 SIP Spectrum, Inc.  All rights reserved.
00208  * 
00209  * Redistribution and use in source and binary forms, with or without
00210  * modification, are permitted provided that the following conditions
00211  * are met:
00212  * 
00213  * 1. Redistributions of source code must retain the above copyright
00214  *    notice, this list of conditions and the following disclaimer.
00215  * 
00216  * 2. Redistributions in binary form must reproduce the above copyright
00217  *    notice, this list of conditions and the following disclaimer in
00218  *    the documentation and/or other materials provided with the
00219  *    distribution.
00220  * 
00221  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00222  *    and "Vovida Open Communication Application Library (VOCAL)" must
00223  *    not be used to endorse or promote products derived from this
00224  *    software without prior written permission. For written
00225  *    permission, please contact vocal@vovida.org.
00226  *
00227  * 4. Products derived from this software may not be called "VOCAL", nor
00228  *    may "VOCAL" appear in their name, without prior written
00229  *    permission of Vovida Networks, Inc.
00230  * 
00231  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00232  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00233  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00234  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00235  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00236  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00237  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00238  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00239  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00240  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00241  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00242  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00243  * DAMAGE.
00244  * 
00245  * ====================================================================
00246  * 
00247  * This software consists of voluntary contributions made by Vovida
00248  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00249  * Inc.  For more information on Vovida Networks, Inc., please see
00250  * <http://www.vovida.org/>.
00251  *
00252  */