|
reSIProcate/DialogUsageManager
9694
|
00001 #include "resip/stack/KeepAliveMessage.hxx" 00002 #include "resip/stack/InteropHelper.hxx" 00003 #include "resip/dum/KeepAliveManager.hxx" 00004 #include "resip/dum/KeepAliveTimeout.hxx" 00005 #include "resip/dum/DialogUsageManager.hxx" 00006 #include "resip/stack/Helper.hxx" 00007 #include "rutil/Logger.hxx" 00008 #include "resip/stack/SipStack.hxx" 00009 00010 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM 00011 00012 using namespace resip; 00013 using namespace std; 00014 00015 int KeepAliveManager::mKeepAlivePongTimeoutMs = 10000; // Defaults to 10000ms (10s) as specified in RFC5626 section 4.4.1 00016 00017 void 00018 KeepAliveManager::add(const Tuple& target, int keepAliveInterval, bool targetSupportsOutbound) 00019 { 00020 assert(mDum); 00021 NetworkAssociationMap::iterator it = mNetworkAssociations.find(target); 00022 if (it == mNetworkAssociations.end()) 00023 { 00024 DebugLog(<< "First keep alive for id=" << mCurrentId << ": " << target << ", interval=" 00025 << keepAliveInterval << "s, supportsOutbound=" << (targetSupportsOutbound ? "true" : "false")); 00026 00027 NetworkAssociationInfo info; 00028 info.refCount = 1; 00029 info.keepAliveInterval = keepAliveInterval; 00030 info.id = mCurrentId; 00031 info.supportsOutbound = targetSupportsOutbound; 00032 info.pongReceivedForLastPing = false; 00033 mNetworkAssociations.insert(NetworkAssociationMap::value_type(target, info)); 00034 KeepAliveTimeout t(target, mCurrentId); 00035 SipStack &stack = mDum->getSipStack(); 00036 if(targetSupportsOutbound) 00037 { 00038 // Used randomized timeout between 80% and 100% of keepalivetime 00039 stack.post(t, Helper::jitterValue(keepAliveInterval, 80, 100), mDum); 00040 } 00041 else 00042 { 00043 stack.post(t, keepAliveInterval, mDum); 00044 } 00045 ++mCurrentId; 00046 } 00047 else 00048 { 00049 it->second.refCount++; 00050 if(keepAliveInterval < it->second.keepAliveInterval || targetSupportsOutbound) // if targetSupportsOutbound, then always update the interval, as value may be from Flow-Timer header 00051 { 00052 // ?slg? only allow value to be shortened??? What if 2 different profiles 00053 // with different keepAliveTime settings are sharing this network association? 00054 it->second.keepAliveInterval = keepAliveInterval; 00055 } 00056 if(targetSupportsOutbound) 00057 { 00058 // allow this to be updated to true only. If any usage get's an indication of 00059 // outbound support on this flow, then we accept it 00060 it->second.supportsOutbound = targetSupportsOutbound; 00061 } 00062 DebugLog(<< "Association added for keep alive id=" << it->second.id << ": " << target 00063 << ", interval=" << it->second.keepAliveInterval << "s, supportsOutbound=" 00064 << (it->second.supportsOutbound ? "true" : "false") 00065 << ", refCount=" << it->second.refCount); 00066 } 00067 } 00068 00069 void 00070 KeepAliveManager::remove(const Tuple& target) 00071 { 00072 NetworkAssociationMap::iterator it = mNetworkAssociations.find(target); 00073 if (it != mNetworkAssociations.end()) 00074 { 00075 if (0 == --it->second.refCount) 00076 { 00077 DebugLog(<< "Last association removed for keep alive id=" << it->second.id << ": " << target); 00078 mNetworkAssociations.erase(it); 00079 } 00080 else 00081 { 00082 DebugLog(<< "Association removed for keep alive id=" << it->second.id << ": " << target << ", refCount=" << it->second.refCount); 00083 } 00084 } 00085 } 00086 00087 void 00088 KeepAliveManager::process(KeepAliveTimeout& timeout) 00089 { 00090 assert(mDum); 00091 static KeepAliveMessage msg; 00092 NetworkAssociationMap::iterator it = mNetworkAssociations.find(timeout.target()); 00093 if (it != mNetworkAssociations.end() && timeout.id() == it->second.id) 00094 { 00095 SipStack &stack = mDum->getSipStack(); 00096 DebugLog(<< "Refreshing keepalive for id=" << it->second.id << ": " << it->first 00097 << ", interval=" << it->second.keepAliveInterval << "s, supportsOutbound=" 00098 << (it->second.supportsOutbound ? "true" : "false") 00099 << ", refCount=" << it->second.refCount); 00100 00101 if(InteropHelper::getOutboundVersion()>=8 && it->second.supportsOutbound && mKeepAlivePongTimeoutMs > 0) 00102 { 00103 // Assert if keep alive interval is too short in order to properly detect 00104 // missing pong responses - ie. interval must be greater than 10s 00105 assert((it->second.keepAliveInterval*1000) > mKeepAlivePongTimeoutMs); 00106 00107 // Start pong timeout if transport is TCP based (note: pong processing of Stun messaging is currently not implemented) 00108 if(it->first.getType() == TCP || it->first.getType() == TLS) 00109 { 00110 DebugLog( << "Starting pong timeout for keepalive id " << it->second.id); 00111 KeepAlivePongTimeout t(it->first, it->second.id); 00112 stack.postMS(t, mKeepAlivePongTimeoutMs, mDum); 00113 } 00114 } 00115 it->second.pongReceivedForLastPing = false; // reset flag 00116 00117 stack.sendTo(msg, timeout.target(), mDum); 00118 KeepAliveTimeout t(it->first, it->second.id); 00119 if(it->second.supportsOutbound) 00120 { 00121 // Used randomized timeout between 80% and 100% of keepalivetime 00122 stack.post(t, Helper::jitterValue(it->second.keepAliveInterval, 80, 100), mDum); 00123 } 00124 else 00125 { 00126 stack.post(t, it->second.keepAliveInterval, mDum); 00127 } 00128 } 00129 } 00130 00131 void 00132 KeepAliveManager::process(KeepAlivePongTimeout& timeout) 00133 { 00134 assert(mDum); 00135 NetworkAssociationMap::iterator it = mNetworkAssociations.find(timeout.target()); 00136 if (it != mNetworkAssociations.end() && timeout.id() == it->second.id) 00137 { 00138 if(!it->second.pongReceivedForLastPing) 00139 { 00140 // Timeout expecting pong response 00141 InfoLog(<< "Timed out expecting pong response for keep alive id=" << it->second.id << ": " << it->first); 00142 mDum->getSipStack().terminateFlow(it->first); 00143 } 00144 } 00145 } 00146 00147 void 00148 KeepAliveManager::receivedPong(const Tuple& flow) 00149 { 00150 NetworkAssociationMap::iterator it = mNetworkAssociations.find(flow); 00151 if (it != mNetworkAssociations.end()) 00152 { 00153 DebugLog(<< "Received pong response for keep alive id=" << it->second.id << ": " << it->first); 00154 it->second.pongReceivedForLastPing = true; 00155 } 00156 } 00157 00158 00159 /* ==================================================================== 00160 * The Vovida Software License, Version 1.0 00161 * 00162 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00163 * 00164 * Redistribution and use in source and binary forms, with or without 00165 * modification, are permitted provided that the following conditions 00166 * are met: 00167 * 00168 * 1. Redistributions of source code must retain the above copyright 00169 * notice, this list of conditions and the following disclaimer. 00170 * 00171 * 2. Redistributions in binary form must reproduce the above copyright 00172 * notice, this list of conditions and the following disclaimer in 00173 * the documentation and/or other materials provided with the 00174 * distribution. 00175 * 00176 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00177 * and "Vovida Open Communication Application Library (VOCAL)" must 00178 * not be used to endorse or promote products derived from this 00179 * software without prior written permission. For written 00180 * permission, please contact vocal@vovida.org. 00181 * 00182 * 4. Products derived from this software may not be called "VOCAL", nor 00183 * may "VOCAL" appear in their name, without prior written 00184 * permission of Vovida Networks, Inc. 00185 * 00186 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00187 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00188 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00189 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00190 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00191 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00192 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00193 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00194 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00195 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00196 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00197 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00198 * DAMAGE. 00199 * 00200 * ==================================================================== 00201 * 00202 * This software consists of voluntary contributions made by Vovida 00203 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00204 * Inc. For more information on Vovida Networks, Inc., please see 00205 * <http://www.vovida.org/>. 00206 * 00207 */
1.7.5.1