reSIProcate/stack  9359
SelectInterruptor.cxx
Go to the documentation of this file.
00001 #include "resip/stack/SelectInterruptor.hxx"
00002 
00003 #include <cassert>
00004 #include "rutil/Logger.hxx"
00005 
00006 #ifndef WIN32
00007 #include <unistd.h>
00008 #endif
00009 
00010 using namespace resip;
00011 
00012 #define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
00013 
00014 SelectInterruptor::SelectInterruptor()
00015 {
00016 #ifdef WIN32
00017    mSocket = ::socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
00018 
00019    sockaddr_in loopback;
00020    memset(&loopback, 0, sizeof(loopback));
00021    loopback.sin_family = AF_INET;
00022    loopback.sin_port = 0;
00023    loopback.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
00024    makeSocketNonBlocking(mSocket); //win32 woes
00025    ::bind( mSocket, reinterpret_cast<sockaddr*>(&loopback), sizeof(loopback));
00026    memset(&mWakeupAddr, 0, sizeof(mWakeupAddr));
00027    int len = sizeof(mWakeupAddr);
00028    int error = getsockname(mSocket, (sockaddr *)&mWakeupAddr, &len);
00029    assert(error == 0);
00030    error= connect(mSocket, &mWakeupAddr, sizeof(mWakeupAddr));
00031    assert(error == 0);
00032    mReadThing = mSocket;
00033 #else
00034    int x = pipe(mPipe);
00035    (void)x;
00036    assert( x != -1 );
00037    // make write-side non-blocking to avoid deadlock
00038    makeSocketNonBlocking(mPipe[1]);
00039    // make read-side non-blocking so safe to read out entire pipe
00040    // all in one go (also just safer)
00041    makeSocketNonBlocking(mPipe[0]);
00042    mReadThing = mPipe[0];
00043 #endif
00044 }
00045 
00046 SelectInterruptor::~SelectInterruptor()
00047 {
00048 #ifdef WIN32
00049    closesocket(mSocket);
00050 #else
00051    close(mPipe[0]);
00052    close(mPipe[1]);
00053 #endif
00054 }
00055 
00056 void
00057 SelectInterruptor::handleProcessNotification()
00058 {
00059    interrupt();
00060 }
00061 
00062 void
00063 SelectInterruptor::buildFdSet(FdSet& fdset)
00064 {
00065 #ifdef WIN32
00066         fdset.setRead(mSocket);
00067 #else
00068    fdset.setRead(mPipe[0]);
00069 #endif
00070 }
00071 
00072 void
00073 SelectInterruptor::processCleanup()
00074 {
00075 #ifdef WIN32
00076    {
00077       char rdBuf[16];
00078       recv(mSocket, rdBuf, sizeof(rdBuf), 0);
00079    }
00080 #else
00081    {
00082       char rdBuf[16];
00083       int x;
00084       while ( (x=read(mPipe[0], rdBuf, sizeof(rdBuf))) == sizeof(rdBuf) )
00085          ;
00086       // WATCHOUT: EWOULDBLOCK *will* happen above when the pending
00087       // number of bytes is exactly size of rdBuf
00088       // XXX: should check for certain errors (like fd closed) and die?
00089    }
00090 #endif
00091 }
00092 
00093 void
00094 SelectInterruptor::process(FdSet& fdset)
00095 {
00096    if (fdset.readyToRead(mReadThing))
00097       processCleanup();
00098 }
00099 
00100 void
00101 SelectInterruptor::interrupt()
00102 {
00103    static char wakeUp[] = "w";
00104 #ifdef WIN32
00105    int count = send(mSocket, wakeUp, sizeof(wakeUp), 0);
00106    assert(count == sizeof(wakeUp));
00107 #else
00108    ssize_t res = write(mPipe[1], wakeUp, sizeof(wakeUp));
00109    if ( res == -1 && errno==EAGAIN )
00110    {
00111       ; // this can happen when SipStack thread gets behind.
00112       // no need to block since our only purpose is to wake up the thread
00113       // also, this write can occur within the SipStack thread, in which
00114       // case we get dead-lock if this blocks
00115    } else {
00116       assert(res == sizeof(wakeUp));
00117    }
00118 #endif
00119 }
00120 
00121 /* ====================================================================
00122  * The Vovida Software License, Version 1.0
00123  *
00124  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00125  *
00126  * Redistribution and use in source and binary forms, with or without
00127  * modification, are permitted provided that the following conditions
00128  * are met:
00129  *
00130  * 1. Redistributions of source code must retain the above copyright
00131  *    notice, this list of conditions and the following disclaimer.
00132  *
00133  * 2. Redistributions in binary form must reproduce the above copyright
00134  *    notice, this list of conditions and the following disclaimer in
00135  *    the documentation and/or other materials provided with the
00136  *    distribution.
00137  *
00138  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00139  *    and "Vovida Open Communication Application Library (VOCAL)" must
00140  *    not be used to endorse or promote products derived from this
00141  *    software without prior written permission. For written
00142  *    permission, please contact vocal@vovida.org.
00143  *
00144  * 4. Products derived from this software may not be called "VOCAL", nor
00145  *    may "VOCAL" appear in their name, without prior written
00146  *    permission of Vovida Networks, Inc.
00147  *
00148  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00149  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00150  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00151  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00152  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00153  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00154  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00155  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00156  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00157  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00158  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00159  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00160  * DAMAGE.
00161  *
00162  * ====================================================================
00163  *
00164  * This software consists of voluntary contributions made by Vovida
00165  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00166  * Inc.  For more information on Vovida Networks, Inc., please see
00167  * <http://www.vovida.org/>.
00168  *
00169  * vi: set shiftwidth=3 expandtab:
00170  */