reSIProcate/stack  9694
Transceiver.cxx
Go to the documentation of this file.
00001 #include <sys/time.h>
00002 #include <sys/types.h>
00003 #include <unistd.h>
00004 #include <iostream>
00005 
00006 #include <sys/socket.h>
00007 #include <netinet/in.h>
00008 #include <arpa/inet.h>
00009 
00010 #include "Transceiver.hxx"
00011 #include "rutil/Logger.hxx"
00012 #include "rutil/DataStream.hxx"
00013 #include "rutil/DnsUtil.hxx"
00014 #include "rutil/Timer.hxx"
00015 
00016 
00017 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP
00018 
00019 using namespace std;
00020 using namespace resip;
00021 using namespace Loadgen;
00022 
00023 Transceiver::Transceiver(int port)
00024    : mUdp(mReceived, port)
00025 {
00026    mContactUri.host() = DnsUtil::getLocalHostName();
00027    mContactUri.port() = mUdp.port();
00028    mContactUri.param(p_transport) = Transport::toData(mUdp.transport());
00029 }
00030 
00031 void
00032 Transceiver::send(SipMessage& message)
00033 {
00034    Uri target;
00035    if (message.isRequest())
00036    {
00037       if (message.header(h_Routes).size() && !message.header(h_Routes).front().exists(p_lr))
00038       {
00039          target = message.header(h_Routes).front().uri();
00040       }
00041       else
00042       {
00043          target = message.header(h_RequestLine).uri();         
00044       }
00045    }
00046    else if (message.isResponse())
00047    {
00048       assert (!message.header(h_Vias).empty());
00049       const Via& via = message.header(h_Vias).front();
00050       
00051       // should look at via.transport()
00052       target.param(p_transport) = Symbols::UDP; // !jf!
00053       target.host() = via.sentHost();
00054       target.port() = via.sentPort();
00055       
00056       if (via.exists(p_received))
00057       {
00058          target.host() = via.param(p_received);
00059       }
00060       if (via.exists(p_rport))
00061       {
00062          target.port() = via.param(p_rport).port();
00063       }
00064    }
00065    else
00066    {
00067       assert(0);
00068    }
00069    
00070    // do a dns lookup !jf!
00071    // should only do this once and store in the SipMessage (or somewhere)
00072    DebugLog(<<"Trying to resolve target: " << target);
00073    Resolver resolver(target);
00074 
00075    send(target, message);
00076 }
00077 
00078 
00079 void 
00080 Transceiver::send(const Resolver& target,  
00081                   SipMessage& message)
00082 {
00083    DebugLog(<< message.header(h_Vias).size() );
00084  
00085    if (message.isRequest())
00086    {
00087       assert(!message.header(h_Vias).empty());
00088       message.header(h_Vias).front().transport() = Transport::toData(mUdp.transport()); 
00089       message.header(h_Vias).front().sentHost() =  DnsUtil::getLocalHostName();
00090       message.header(h_Vias).front().sentPort() = mUdp.port();
00091    }
00092    
00093    Data& encoded = message.getEncoded();
00094    DataStream strm(encoded);
00095    message.encode(strm);
00096    strm.flush();
00097    mUdp.send(target.mNextHops.front(), encoded, "bogus"); 
00098    mUdp.process(mFdset);
00099 }
00100 
00101 SipMessage*
00102 Transceiver::receive(int waitMs)
00103 {
00104    UInt64 startTime = Timer::getTimeMs();
00105 
00106    UInt64 currentTime = Timer::getTimeMs();
00107    
00108    while( UInt64(waitMs) > currentTime - startTime)
00109    {
00110       int timeLeft = waitMs - (currentTime - startTime);
00111       if (!mReceived.messageAvailable())
00112       {
00113          mUdp.buildFdSet(mFdset);
00114          
00115          int  err = mFdset.selectMilliSeconds(timeLeft);
00116          int e = errno;
00117          if ( err == -1 )
00118          {
00119             InfoLog(<< "Error " << e << " " << strerror(e) << " in select");
00120          }
00121          
00122          DebugLog(<<"Calling process in Transceiver::receive");
00123          mUdp.process(mFdset);
00124       }
00125 
00126       if (mReceived.messageAvailable())
00127       {
00128          Message* msg = mReceived.getNext();
00129          DebugLog(<<"Received a message in the transceiver, " << msg);
00130          
00131          SipMessage* next = dynamic_cast<SipMessage*>(msg);
00132          DebugLog(<<"Dynamic cast resulted in: " << next);
00133          if (next)
00134          {
00135             DebugLog(<<"Received a sip message in the transceiver.");
00136             return next;
00137          }
00138          else
00139          {
00140             DebugLog(<<"Which was apparently not a sip message.");
00141             delete msg;
00142          }
00143       }
00144       currentTime = Timer::getTimeMs();
00145    }
00146    return 0;
00147 }
00148 /* ====================================================================
00149  * The Vovida Software License, Version 1.0 
00150  * 
00151  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00152  * 
00153  * Redistribution and use in source and binary forms, with or without
00154  * modification, are permitted provided that the following conditions
00155  * are met:
00156  * 
00157  * 1. Redistributions of source code must retain the above copyright
00158  *    notice, this list of conditions and the following disclaimer.
00159  * 
00160  * 2. Redistributions in binary form must reproduce the above copyright
00161  *    notice, this list of conditions and the following disclaimer in
00162  *    the documentation and/or other materials provided with the
00163  *    distribution.
00164  * 
00165  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00166  *    and "Vovida Open Communication Application Library (VOCAL)" must
00167  *    not be used to endorse or promote products derived from this
00168  *    software without prior written permission. For written
00169  *    permission, please contact vocal@vovida.org.
00170  *
00171  * 4. Products derived from this software may not be called "VOCAL", nor
00172  *    may "VOCAL" appear in their name, without prior written
00173  *    permission of Vovida Networks, Inc.
00174  * 
00175  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00176  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00177  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00178  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00179  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00180  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00181  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00182  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00183  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00184  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00185  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00186  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00187  * DAMAGE.
00188  * 
00189  * ====================================================================
00190  * 
00191  * This software consists of voluntary contributions made by Vovida
00192  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00193  * Inc.  For more information on Vovida Networks, Inc., please see
00194  * <http://www.vovida.org/>.
00195  *
00196  */