|
reSIProcate/repro
9694
|
00001 #include <cassert> 00002 00003 #include <rutil/Data.hxx> 00004 #include <rutil/Socket.hxx> 00005 #include <resip/stack/Symbols.hxx> 00006 #include <rutil/TransportType.hxx> 00007 #include <rutil/Logger.hxx> 00008 #include <resip/stack/Tuple.hxx> 00009 #include <rutil/DnsUtil.hxx> 00010 #include <rutil/ParseBuffer.hxx> 00011 00012 #include "repro/XmlRpcServerBase.hxx" 00013 #include "repro/XmlRpcConnection.hxx" 00014 00015 using namespace repro; 00016 using namespace resip; 00017 using namespace std; 00018 00019 #define RESIPROCATE_SUBSYSTEM Subsystem::REPRO 00020 00021 unsigned int XmlRpcConnection::NextConnectionId = 1; 00022 00023 00024 XmlRpcConnection::XmlRpcConnection(XmlRpcServerBase& server, resip::Socket sock): 00025 mXmlRcpServer(server), 00026 mConnectionId(NextConnectionId++), 00027 mNextRequestId(1), 00028 mSock(sock) 00029 { 00030 assert(mSock > 0); 00031 } 00032 00033 00034 XmlRpcConnection::~XmlRpcConnection() 00035 { 00036 assert(mSock > 0); 00037 #ifdef WIN32 00038 closesocket(mSock); 00039 #else 00040 close(mSock); 00041 #endif 00042 mSock=0; 00043 } 00044 00045 00046 void 00047 XmlRpcConnection::buildFdSet(FdSet& fdset) 00048 { 00049 if (!mTxBuffer.empty()) 00050 { 00051 fdset.setWrite(mSock); 00052 } 00053 fdset.setRead(mSock); 00054 } 00055 00056 00057 bool 00058 XmlRpcConnection::process(FdSet& fdset) 00059 { 00060 if (fdset.hasException(mSock)) 00061 { 00062 int errNum = 0; 00063 int errNumSize = sizeof(errNum); 00064 getsockopt(mSock,SOL_SOCKET,SO_ERROR,(char *)&errNum,(socklen_t *)&errNumSize); 00065 InfoLog (<< "XmlRpcConnection::process: Exception reading from socket " 00066 << (int)mSock << " code: " << errNum << "; closing connection"); 00067 return false; 00068 } 00069 00070 if (fdset.readyToRead(mSock)) 00071 { 00072 bool ok = processSomeReads(); 00073 if (!ok) 00074 { 00075 return false; 00076 } 00077 } 00078 if ((!mTxBuffer.empty()) && fdset.readyToWrite(mSock)) 00079 { 00080 bool ok = processSomeWrites(); 00081 if (!ok) 00082 { 00083 return false; 00084 } 00085 } 00086 00087 return true; 00088 } 00089 00090 bool 00091 XmlRpcConnection::processSomeReads() 00092 { 00093 const int bufSize = 8000; 00094 char buf[bufSize]; 00095 00096 00097 #if defined(WIN32) 00098 int bytesRead = ::recv(mSock, buf, bufSize, 0); 00099 #else 00100 int bytesRead = ::read(mSock, buf, bufSize); 00101 #endif 00102 00103 if (bytesRead == INVALID_SOCKET) 00104 { 00105 int e = getErrno(); 00106 XmlRpcServerBase::logSocketError(e); 00107 InfoLog (<< "XmlRpcConnection::processSomeReads: Failed read on " << (int)mSock); 00108 return false; 00109 } 00110 else if(bytesRead == 0) 00111 { 00112 DebugLog (<< "XmlRpcConnection::processSomeReads: Connection closed by remote"); 00113 return false; 00114 } 00115 00116 //DebugLog (<< "XmlRpcConnection::processSomeReads: read=" << bytesRead); 00117 00118 mRxBuffer += Data( buf, bytesRead ); 00119 00120 while(tryParse()); 00121 00122 return true; 00123 } 00124 00125 00126 bool 00127 XmlRpcConnection::tryParse() 00128 { 00129 ParseBuffer pb(mRxBuffer); 00130 Data initialTag; 00131 const char* start = pb.position(); 00132 pb.skipWhitespace(); 00133 pb.skipToChar('<'); 00134 if(!pb.eof()) 00135 { 00136 pb.skipChar(); 00137 const char* anchor = pb.position(); 00138 pb.skipToChar('>'); 00139 if(!pb.eof()) 00140 { 00141 initialTag = pb.data(anchor); 00142 // Find end of initial tag 00143 pb.skipToChars("</" + initialTag + ">"); 00144 if (!pb.eof()) 00145 { 00146 pb.skipN((int)initialTag.size() + 3); // Skip past </InitialTag> 00147 mRequests[mNextRequestId] = pb.data(start); 00148 mXmlRcpServer.handleRequest(mConnectionId, mNextRequestId, mRequests[mNextRequestId]); 00149 mNextRequestId++; 00150 00151 // Remove processed data from RxBuffer 00152 pb.skipWhitespace(); 00153 if(!pb.eof()) 00154 { 00155 anchor = pb.position(); 00156 pb.skipToEnd(); 00157 mRxBuffer = pb.data(anchor); 00158 return true; 00159 } 00160 else 00161 { 00162 mRxBuffer.clear(); 00163 } 00164 } 00165 } 00166 } 00167 return false; 00168 } 00169 00170 bool 00171 XmlRpcConnection::processSomeWrites() 00172 { 00173 if (mTxBuffer.empty()) 00174 { 00175 return true; 00176 } 00177 00178 //DebugLog (<< "XmlRpcConnection::processSomeWrites: Writing " << mTxBuffer ); 00179 00180 #if defined(WIN32) 00181 int bytesWritten = ::send(mSock, mTxBuffer.data(), (int)mTxBuffer.size(), 0); 00182 #else 00183 int bytesWritten = ::write(mSock, mTxBuffer.data(), mTxBuffer.size() ); 00184 #endif 00185 00186 if (bytesWritten == INVALID_SOCKET) 00187 { 00188 int e = getErrno(); 00189 XmlRpcServerBase::logSocketError(e); 00190 InfoLog (<< "XmlRpcConnection::processSomeWrites - failed write on " << mSock << " " << strerror(e)); 00191 00192 return false; 00193 } 00194 00195 if (bytesWritten == (int)mTxBuffer.size()) 00196 { 00197 DebugLog (<< "XmlRpcConnection::processSomeWrites - Wrote it all" ); 00198 mTxBuffer = Data::Empty; 00199 00200 //return false; // return false causes connection to close and clean up 00201 return true; // keep connection up 00202 } 00203 else 00204 { 00205 Data rest = mTxBuffer.substr(bytesWritten); 00206 mTxBuffer = rest; 00207 DebugLog( << "XmlRpcConnection::processSomeWrites - Wrote " << bytesWritten << " bytes - still need to do " << mTxBuffer ); 00208 } 00209 00210 return true; 00211 } 00212 00213 bool 00214 XmlRpcConnection::sendResponse(unsigned int requestId, const Data& responseData, bool isFinal) 00215 { 00216 RequestMap::iterator it = mRequests.find(requestId); 00217 if(it != mRequests.end()) 00218 { 00219 Data& request = it->second; 00220 Data response(request.size() + responseData.size() + 30, Data::Preallocate); 00221 ParseBuffer pb(request); 00222 00223 // A response is formed by starting with the request and inserting the 00224 // ResponseData between <Response> tags at the same level as the <Request> tags 00225 const char* start = pb.position(); 00226 pb.skipToChars("</Request>"); 00227 if (!pb.eof()) 00228 { 00229 pb.skipN(10); // Skip past </Request> 00230 pb.skipWhitespace(); 00231 00232 // Response starts with request message up to end of Request tag 00233 response = pb.data(start); 00234 00235 // Add in response data 00236 response += Symbols::CRLF; 00237 response += " <Response>" + responseData + " </Response>"; 00238 response += Symbols::CRLF; 00239 00240 // Add remainder of request message 00241 start = pb.position(); 00242 pb.skipToEnd(); 00243 response += pb.data(start); 00244 } 00245 else 00246 { 00247 // No Request in message - just send bare response 00248 response = "<Response>" + responseData + "</Response>"; 00249 } 00250 mTxBuffer += response; 00251 if(isFinal) 00252 { 00253 mRequests.erase(it); 00254 } 00255 return true; 00256 } 00257 return false; 00258 } 00259 00260 void 00261 XmlRpcConnection::sendEvent(const Data& eventData) 00262 { 00263 mTxBuffer += eventData; 00264 } 00265 00266 /* ==================================================================== 00267 * The Vovida Software License, Version 1.0 00268 * 00269 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00270 * Copyright (c) 2010 SIP Spectrum, Inc. All rights reserved. 00271 * 00272 * Redistribution and use in source and binary forms, with or without 00273 * modification, are permitted provided that the following conditions 00274 * are met: 00275 * 00276 * 1. Redistributions of source code must retain the above copyright 00277 * notice, this list of conditions and the following disclaimer. 00278 * 00279 * 2. Redistributions in binary form must reproduce the above copyright 00280 * notice, this list of conditions and the following disclaimer in 00281 * the documentation and/or other materials provided with the 00282 * distribution. 00283 * 00284 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00285 * and "Vovida Open Communication Application Library (VOCAL)" must 00286 * not be used to endorse or promote products derived from this 00287 * software without prior written permission. For written 00288 * permission, please contact vocal@vovida.org. 00289 * 00290 * 4. Products derived from this software may not be called "VOCAL", nor 00291 * may "VOCAL" appear in their name, without prior written 00292 * permission of Vovida Networks, Inc. 00293 * 00294 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00295 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00296 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00297 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00298 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00299 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00300 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00301 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00302 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00303 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00304 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00305 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00306 * DAMAGE. 00307 * 00308 * ==================================================================== 00309 * 00310 * This software consists of voluntary contributions made by Vovida 00311 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00312 * Inc. For more information on Vovida Networks, Inc., please see 00313 * <http://www.vovida.org/>. 00314 * 00315 */ 00316
1.7.5.1