reSIProcate/repro  9694
LocationServer.cxx
Go to the documentation of this file.
00001 #if defined(HAVE_CONFIG_H)
00002 #include "config.h"
00003 #endif
00004 
00005 #include <algorithm>
00006 
00007 #include "resip/stack/SipMessage.hxx"
00008 #include "resip/stack/Helper.hxx"
00009 #include "resip/stack/ExtensionParameter.hxx"
00010 #include "repro/monkeys/LocationServer.hxx"
00011 #include "repro/RequestContext.hxx"
00012 #include "repro/UserInfoMessage.hxx"
00013 #include "repro/OutboundTarget.hxx"
00014 #include "repro/QValueTarget.hxx"
00015 #include "repro/Proxy.hxx"
00016 #include "resip/stack/SipStack.hxx"
00017 
00018 #include "rutil/WinLeakCheck.hxx"
00019 
00020 
00021 #include "rutil/Logger.hxx"
00022 #define RESIPROCATE_SUBSYSTEM resip::Subsystem::REPRO
00023 
00024 using namespace resip;
00025 using namespace repro;
00026 using namespace std;
00027 
00028 
00029 Processor::processor_action_t
00030 LocationServer::process(RequestContext& context)
00031 {
00032    DebugLog(<< "Monkey handling request: " << *this << "; reqcontext = " << context);
00033 
00034    // UserInfoMessage is used to look for existence of user if we cannot find
00035    // them in the Regisration Database.  This code handles the asynchronous
00036    // lookup.
00037    UserInfoMessage *userInfo = dynamic_cast<UserInfoMessage*>(context.getCurrentEvent());
00038    if(userInfo && userInfo->getOriginatorAddress() == getAddress())  // Ensure we generated the UserInfo - it could be from the Digest Authenticator
00039    {
00040       // If A1 is empty, then user does not exist - return 404
00041       if(userInfo->A1().empty())
00042       {
00043          resip::SipMessage response;
00044          Helper::makeResponse(response, context.getOriginalRequest(), 404); 
00045          context.sendResponse(response);
00046          return Processor::SkipThisChain;
00047       }
00048       else
00049       {
00050          // User exists, but is just not registered - continue processing
00051          return Processor::Continue;
00052       }
00053    }
00054 
00055    resip::Uri inputUri = context.getOriginalRequest().header(h_RequestLine).uri().getAorAsUri(context.getOriginalRequest().getSource().getType());
00056 
00057    //!RjS! This doesn't look exception safe - need guards
00058    mStore.lockRecord(inputUri);
00059 
00060    resip::ContactList contacts;
00061    mStore.getContacts(inputUri,contacts);
00062    
00063    if(contacts.size() > 0)
00064    {
00065       TargetPtrList batch;
00066       std::map<resip::Data,resip::ContactList> outboundBatch;
00067       UInt64 now = Timer::getTimeSecs();
00068       for(resip::ContactList::iterator i  = contacts.begin(); i != contacts.end(); ++i)
00069       {
00070          resip::ContactInstanceRecord contact = *i;
00071          if (contact.mRegExpires > now)
00072          {
00073             InfoLog (<< *this << " adding target " << contact.mContact <<
00074                   " with tuple " << contact.mReceivedFrom);
00075             if(contact.mInstance.empty() || contact.mRegId==0)
00076             {
00077                QValueTarget* target = new QValueTarget(contact);
00078                batch.push_back(target);
00079             }
00080             else
00081             {
00082                outboundBatch[contact.mInstance].push_back(contact);
00083             }
00084          }
00085          else
00086          {
00087             // remove expired contact 
00088             mStore.removeContact(inputUri, contact);
00089          }
00090       }
00091 
00092       mStore.unlockRecord(inputUri);
00093 
00094       std::map<resip::Data,resip::ContactList>::iterator o;
00095       
00096       for(o=outboundBatch.begin(); o!=outboundBatch.end(); ++o)
00097       {
00098          o->second.sort(OutboundTarget::instanceCompare);  // Orders records by lastUpdate time
00099          OutboundTarget* ot = new OutboundTarget(o->first, o->second);
00100          batch.push_back(ot);
00101       }
00102       
00103       if(!batch.empty())
00104       {
00105          // Note: some elements of list are already in a sorted order (see outbound bactch sorting
00106          // above), however list::sort is stable, so it's safe to sort twice, as relative order 
00107          // of equal elements is preserved
00108 #ifdef __SUNPRO_CC
00109          sort(batch.begin(), batch.end(), Target::priorityMetricCompare);
00110 #else
00111          batch.sort(Target::priorityMetricCompare);
00112 #endif
00113          context.getResponseContext().addTargetBatch(batch, false /* high priority */);
00114          //ResponseContext should be consuming the vector
00115          assert(batch.empty());
00116       }
00117    }
00118    else
00119    {
00120       mStore.unlockRecord(inputUri);
00121 
00122       if(mUserInfoDispatcher)
00123       {
00124          // User does not have an active registration - check if they even exist or not
00125          // so we know if should send a 404 vs a 480.
00126          // Since users are not kept in memory we need to go to the database asynchrounously 
00127          // to look for existance.  We will use the existing mechanism in place for asynhcronous 
00128          // authentication lookups in order to check for existance - we don't need the returned 
00129          // A1 hash, but the efficiency of this request is more than adequate for this purpose.
00130          // Currently repro authentication treats authentication realm the same as users aor domain,
00131          // if this changes in the future we may need to add a different mechanism to check for
00132          // existance.
00133          // Note:  repro authentication must be enabled in order for mUserInfoDispatcher to be
00134          //        defined and for 404 responses to work
00135          UserInfoMessage* async = new UserInfoMessage(*this, context.getTransactionId(), &(context.getProxy()));
00136          async->user() = inputUri.user();
00137          async->realm() = inputUri.host();
00138          async->domain() = inputUri.host();
00139          std::auto_ptr<ApplicationMessage> app(async);
00140          mUserInfoDispatcher->post(app);
00141          return WaitingForEvent;
00142       }
00143    }
00144 
00145    return Processor::Continue;
00146 }
00147 
00148 
00149 /* ====================================================================
00150  * The Vovida Software License, Version 1.0 
00151  * 
00152  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00153  * 
00154  * Redistribution and use in source and binary forms, with or without
00155  * modification, are permitted provided that the following conditions
00156  * are met:
00157  * 
00158  * 1. Redistributions of source code must retain the above copyright
00159  *    notice, this list of conditions and the following disclaimer.
00160  * 
00161  * 2. Redistributions in binary form must reproduce the above copyright
00162  *    notice, this list of conditions and the following disclaimer in
00163  *    the documentation and/or other materials provided with the
00164  *    distribution.
00165  * 
00166  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00167  *    and "Vovida Open Communication Application Library (VOCAL)" must
00168  *    not be used to endorse or promote products derived from this
00169  *    software without prior written permission. For written
00170  *    permission, please contact vocal@vovida.org.
00171  *
00172  * 4. Products derived from this software may not be called "VOCAL", nor
00173  *    may "VOCAL" appear in their name, without prior written
00174  *    permission of Vovida Networks, Inc.
00175  * 
00176  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00177  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00178  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00179  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00180  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00181  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00182  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00183  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00184  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00185  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00186  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00187  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00188  * DAMAGE.
00189  * 
00190  * ====================================================================
00191  * 
00192  * This software consists of voluntary contributions made by Vovida
00193  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00194  * Inc.  For more information on Vovida Networks, Inc., please see
00195  * <http://www.vovida.org/>.
00196  *
00197  */