GME
13
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one or more 00003 * contributor license agreements. See the NOTICE file distributed with 00004 * this work for additional information regarding copyright ownership. 00005 * The ASF licenses this file to You under the Apache License, Version 2.0 00006 * (the "License"); you may not use this file except in compliance with 00007 * the License. You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /* 00019 * $Id: UnixHTTPURLInputStream.cpp 936316 2010-04-21 14:19:58Z borisk $ 00020 */ 00021 00022 #if HAVE_CONFIG_H 00023 # include <config.h> 00024 #endif 00025 00026 #include <string.h> 00027 00028 #if HAVE_UNISTD_H 00029 # include <unistd.h> 00030 #endif 00031 #if HAVE_SYS_TYPES_H 00032 # include <sys/types.h> 00033 #endif 00034 #if HAVE_SYS_SOCKET_H 00035 # include <sys/socket.h> 00036 #endif 00037 #if HAVE_NETINET_IN_H 00038 # include <netinet/in.h> 00039 #endif 00040 #if HAVE_ARPA_INET_H 00041 # include <arpa/inet.h> 00042 #endif 00043 #if HAVE_NETDB_H 00044 # include <netdb.h> 00045 #endif 00046 #include <errno.h> 00047 00048 #include <xercesc/util/NetAccessors/Socket/UnixHTTPURLInputStream.hpp> 00049 #include <xercesc/util/XMLString.hpp> 00050 #include <xercesc/util/XMLExceptMsgs.hpp> 00051 #include <xercesc/util/Janitor.hpp> 00052 00053 XERCES_CPP_NAMESPACE_BEGIN 00054 00055 class SocketJanitor 00056 { 00057 public: 00058 // ----------------------------------------------------------------------- 00059 // Constructors and Destructor 00060 // ----------------------------------------------------------------------- 00061 SocketJanitor(int* toDelete) : fData(toDelete) {} 00062 ~SocketJanitor() { reset(); } 00063 00064 int* get() const { return fData; } 00065 int* release() { int* p = fData; fData = 0; return p; } 00066 00067 void reset(int* p = 0) 00068 { 00069 if(fData) { 00070 shutdown(*fData, 2); 00071 close(*fData); 00072 } 00073 fData = p; 00074 } 00075 bool isDataNull() { return (fData == 0); } 00076 00077 private : 00078 // ----------------------------------------------------------------------- 00079 // Unimplemented constructors and operators 00080 // ----------------------------------------------------------------------- 00081 SocketJanitor(); 00082 SocketJanitor(const SocketJanitor&); 00083 SocketJanitor& operator=(const SocketJanitor&); 00084 00085 // ----------------------------------------------------------------------- 00086 // Private data members 00087 // 00088 // fData 00089 // This is the pointer to the socket that must be closed when 00090 // this object is destroyed. 00091 // ----------------------------------------------------------------------- 00092 int* fData; 00093 }; 00094 00095 UnixHTTPURLInputStream::UnixHTTPURLInputStream(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo/*=0*/) 00096 : BinHTTPInputStreamCommon(urlSource.getMemoryManager()), 00097 fSocket(0) 00098 { 00099 // 00100 // Convert the hostName to the platform's code page for gethostbyname and 00101 // inet_addr functions. 00102 // 00103 00104 MemoryManager *memoryManager = urlSource.getMemoryManager(); 00105 00106 const XMLCh* hostName = urlSource.getHost(); 00107 00108 if (hostName == 0) 00109 ThrowXMLwithMemMgr1(NetAccessorException, 00110 XMLExcepts::File_CouldNotOpenFile, 00111 urlSource.getURLText(), 00112 memoryManager); 00113 00114 char* hostNameAsCharStar = XMLString::transcode(hostName, memoryManager); 00115 ArrayJanitor<char> janHostNameAsCharStar(hostNameAsCharStar, memoryManager); 00116 00117 XMLURL url(urlSource); 00118 int redirectCount = 0; 00119 SocketJanitor janSock(0); 00120 00121 do { 00122 // 00123 // Set up a socket. 00124 // 00125 00126 #if HAVE_GETADDRINFO 00127 struct addrinfo hints, *res, *ai; 00128 00129 CharBuffer portBuffer(10, memoryManager); 00130 portBuffer.appendDecimalNumber(url.getPortNum()); 00131 00132 memset(&hints, 0, sizeof(struct addrinfo)); 00133 hints.ai_family = PF_UNSPEC; 00134 hints.ai_socktype = SOCK_STREAM; 00135 int n = getaddrinfo(hostNameAsCharStar,portBuffer.getRawBuffer(),&hints, &res); 00136 if(n != 0) 00137 { 00138 hints.ai_flags = AI_NUMERICHOST; 00139 n = getaddrinfo(hostNameAsCharStar,portBuffer.getRawBuffer(),&hints, &res); 00140 if(n != 0) 00141 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_TargetResolution, hostName, memoryManager); 00142 } 00143 janSock.reset(); 00144 for (ai = res; ai != NULL; ai = ai->ai_next) { 00145 // Open a socket with the correct address family for this address. 00146 fSocket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); 00147 if (fSocket < 0) 00148 continue; 00149 janSock.reset(&fSocket); 00150 if (connect(fSocket, ai->ai_addr, ai->ai_addrlen) < 0) 00151 { 00152 freeaddrinfo(res); 00153 ThrowXMLwithMemMgr1(NetAccessorException, 00154 XMLExcepts::NetAcc_ConnSocket, url.getURLText(), memoryManager); 00155 } 00156 break; 00157 } 00158 freeaddrinfo(res); 00159 if (fSocket < 0) 00160 { 00161 ThrowXMLwithMemMgr1(NetAccessorException, 00162 XMLExcepts::NetAcc_CreateSocket, url.getURLText(), memoryManager); 00163 } 00164 #else 00165 struct hostent *hostEntPtr = 0; 00166 struct sockaddr_in sa; 00167 00168 // Use the hostName in the local code page .... 00169 if((hostEntPtr = gethostbyname(hostNameAsCharStar)) == NULL) 00170 { 00171 unsigned long numAddress = inet_addr(hostNameAsCharStar); 00172 if ((hostEntPtr = 00173 gethostbyaddr((char *) &numAddress, 00174 sizeof(unsigned long), AF_INET)) == NULL) 00175 { 00176 ThrowXMLwithMemMgr1(NetAccessorException, 00177 XMLExcepts::NetAcc_TargetResolution, hostName, memoryManager); 00178 } 00179 } 00180 00181 memset(&sa, '\0', sizeof(sockaddr_in)); // iSeries fix ?? 00182 memcpy((void *) &sa.sin_addr, 00183 (const void *) hostEntPtr->h_addr, hostEntPtr->h_length); 00184 sa.sin_family = hostEntPtr->h_addrtype; 00185 sa.sin_port = htons((unsigned short)url.getPortNum()); 00186 00187 janSock.reset(); 00188 fSocket = socket(hostEntPtr->h_addrtype, SOCK_STREAM, 0); 00189 if(fSocket < 0) 00190 { 00191 ThrowXMLwithMemMgr1(NetAccessorException, 00192 XMLExcepts::NetAcc_CreateSocket, url.getURLText(), memoryManager); 00193 } 00194 janSock.reset(&fSocket); 00195 00196 if(connect(fSocket, (struct sockaddr *) &sa, sizeof(sa)) < 0) 00197 { 00198 ThrowXMLwithMemMgr1(NetAccessorException, 00199 XMLExcepts::NetAcc_ConnSocket, url.getURLText(), memoryManager); 00200 } 00201 #endif 00202 00203 int status = sendRequest(url, httpInfo); 00204 00205 if(status == 200) { 00206 // HTTP 200 OK response means we're done. 00207 break; 00208 } 00209 // a 3xx response means there was an HTTP redirect 00210 else if(status >= 300 && status <= 307) { 00211 redirectCount++; 00212 00213 XMLCh *newURLString = findHeader("Location"); 00214 ArrayJanitor<XMLCh> janNewURLString(newURLString, memoryManager); 00215 00216 if(newURLString == 0 || *newURLString == 0) { 00217 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, url.getURLText(), memoryManager); 00218 } 00219 00220 XMLURL newURL(memoryManager); 00221 newURL.setURL(url, newURLString); 00222 if(newURL.getProtocol() != XMLURL::HTTP) { 00223 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, newURL.getURLText(), memoryManager); 00224 } 00225 00226 url = newURL; 00227 hostName = newURL.getHost(); 00228 00229 if (hostName == 0) 00230 ThrowXMLwithMemMgr1(NetAccessorException, 00231 XMLExcepts::File_CouldNotOpenFile, 00232 newURL.getURLText(), 00233 memoryManager); 00234 00235 janHostNameAsCharStar.release(); 00236 hostNameAsCharStar = XMLString::transcode(hostName, memoryManager); 00237 janHostNameAsCharStar.reset(hostNameAsCharStar, memoryManager); 00238 } 00239 else { 00240 // Most likely a 404 Not Found error. 00241 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, url.getURLText(), memoryManager); 00242 } 00243 } while(redirectCount < 6); 00244 00245 janSock.release(); 00246 } 00247 00248 00249 UnixHTTPURLInputStream::~UnixHTTPURLInputStream() 00250 { 00251 shutdown(fSocket, 2); 00252 close(fSocket); 00253 } 00254 00255 bool UnixHTTPURLInputStream::send(const char *buf, XMLSize_t len) 00256 { 00257 XMLSize_t done = 0; 00258 int ret; 00259 00260 while(done < len) { 00261 ret = ::send(fSocket, buf + done, len - done, 0); 00262 if(ret == -1) return false; 00263 done += ret; 00264 } 00265 00266 return true; 00267 } 00268 00269 int UnixHTTPURLInputStream::receive(char *buf, XMLSize_t len) 00270 { 00271 return ::recv(fSocket, buf, len, 0); 00272 } 00273 00274 XERCES_CPP_NAMESPACE_END