|
reSIProcate/stack
9359
|
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 */
1.7.5.1