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: BinHTTPURLInputStream.cpp 936316 2010-04-21 14:19:58Z borisk $ 00020 */ 00021 00022 00023 #include <xercesc/util/NetAccessors/WinSock/BinHTTPURLInputStream.hpp> 00024 #include <windows.h> 00025 00026 #ifdef WITH_IPV6 00027 #include <ws2tcpip.h> 00028 #endif 00029 00030 #include <stdio.h> 00031 #include <string.h> 00032 00033 #include <xercesc/util/PlatformUtils.hpp> 00034 #include <xercesc/util/XMLNetAccessor.hpp> 00035 #include <xercesc/util/XMLString.hpp> 00036 #include <xercesc/util/XMLExceptMsgs.hpp> 00037 #include <xercesc/util/Janitor.hpp> 00038 #include <xercesc/util/XMLUniDefs.hpp> 00039 #include <xercesc/util/Mutexes.hpp> 00040 00041 XERCES_CPP_NAMESPACE_BEGIN 00042 00043 typedef u_short (WSAAPI * LPFN_HTONS)(u_short hostshort); 00044 typedef SOCKET (WSAAPI * LPFN_SOCKET)(int af, int type, int protocol); 00045 typedef int (WSAAPI * LPFN_CONNECT)(SOCKET s, const struct sockaddr* name, int namelen); 00046 typedef int (WSAAPI * LPFN_SEND)(SOCKET s, const char* buf, int len, int flags); 00047 typedef int (WSAAPI * LPFN_RECV)(SOCKET s, char* buf, int len, int flags); 00048 typedef int (WSAAPI * LPFN_SHUTDOWN)(SOCKET s, int how); 00049 typedef int (WSAAPI * LPFN_CLOSESOCKET)(SOCKET s); 00050 typedef int (WSAAPI * LPFN_WSACLEANUP)(); 00051 typedef int (WSAAPI * LPFN_WSASTARTUP)(WORD wVersionRequested, LPWSADATA lpWSAData); 00052 #ifdef WITH_IPV6 00053 typedef int (WSAAPI * LPFN_GETADDRINFO)(const char* nodename, const char * servname, const struct addrinfo * hints, struct addrinfo ** res); 00054 typedef void (WSAAPI * LPFN_FREEADDRINFO)(struct addrinfo * ai); 00055 #else 00056 typedef struct hostent *(WSAAPI * LPFN_GETHOSTBYNAME)(const char* name); 00057 typedef struct hostent *(WSAAPI * LPFN_GETHOSTBYADDR)(const char* addr, int len, int type); 00058 typedef unsigned long (WSAAPI * LPFN_INET_ADDR)(const char* cp); 00059 #endif 00060 00061 static HMODULE gWinsockLib = NULL; 00062 static LPFN_HTONS gWShtons = NULL; 00063 static LPFN_SOCKET gWSsocket = NULL; 00064 static LPFN_CONNECT gWSconnect = NULL; 00065 static LPFN_SEND gWSsend = NULL; 00066 static LPFN_RECV gWSrecv = NULL; 00067 static LPFN_SHUTDOWN gWSshutdown = NULL; 00068 static LPFN_CLOSESOCKET gWSclosesocket = NULL; 00069 static LPFN_WSACLEANUP gWSACleanup = NULL; 00070 #ifdef WITH_IPV6 00071 static LPFN_GETADDRINFO gWSgetaddrinfo = NULL; 00072 static LPFN_FREEADDRINFO gWSfreeaddrinfo = NULL; 00073 #else 00074 static LPFN_GETHOSTBYNAME gWSgethostbyname = NULL; 00075 static LPFN_GETHOSTBYADDR gWSgethostbyaddr = NULL; 00076 static LPFN_INET_ADDR gWSinet_addr = NULL; 00077 #endif 00078 00079 static u_short wrap_htons(u_short hostshort) 00080 { 00081 return (*gWShtons)(hostshort); 00082 } 00083 00084 static SOCKET wrap_socket(int af,int type,int protocol) 00085 { 00086 return (*gWSsocket)(af,type,protocol); 00087 } 00088 00089 static int wrap_connect(SOCKET s,const struct sockaddr* name,int namelen) 00090 { 00091 return (*gWSconnect)(s,name,namelen); 00092 } 00093 00094 static int wrap_send(SOCKET s,const char* buf,int len,int flags) 00095 { 00096 return (*gWSsend)(s,buf,len,flags); 00097 } 00098 00099 static int wrap_recv(SOCKET s,char* buf,int len,int flags) 00100 { 00101 return (*gWSrecv)(s,buf,len,flags); 00102 } 00103 00104 static int wrap_shutdown(SOCKET s,int how) 00105 { 00106 return (*gWSshutdown)(s,how); 00107 } 00108 00109 static int wrap_closesocket(SOCKET socket) 00110 { 00111 return (*gWSclosesocket)(socket); 00112 } 00113 00114 #ifdef WITH_IPV6 00115 static int wrap_getaddrinfo(const char* nodename,const char* servname,const struct addrinfo* hints,struct addrinfo** res) 00116 { 00117 return (*gWSgetaddrinfo)(nodename,servname,hints,res); 00118 } 00119 00120 static void wrap_freeaddrinfo(struct addrinfo* ai) 00121 { 00122 (*gWSfreeaddrinfo)(ai); 00123 } 00124 #else 00125 static struct hostent* wrap_gethostbyname(const char* name) 00126 { 00127 return (*gWSgethostbyname)(name); 00128 } 00129 00130 static struct hostent* wrap_gethostbyaddr(const char* addr,int len,int type) 00131 { 00132 return (*gWSgethostbyaddr)(addr,len,type); 00133 } 00134 00135 static unsigned long wrap_inet_addr(const char* cp) 00136 { 00137 return (*gWSinet_addr)(cp); 00138 } 00139 00140 #endif 00141 00142 00143 class SocketJanitor 00144 { 00145 public: 00146 // ----------------------------------------------------------------------- 00147 // Constructors and Destructor 00148 // ----------------------------------------------------------------------- 00149 SocketJanitor(SOCKET* toDelete) : fData(toDelete) {} 00150 ~SocketJanitor() { reset(); } 00151 00152 SOCKET* get() const { return fData; } 00153 SOCKET* release() { SOCKET* p = fData; fData = 0; return p; } 00154 00155 void reset(SOCKET* p = 0) 00156 { 00157 if(fData) { 00158 wrap_shutdown(*fData, SD_BOTH); 00159 wrap_closesocket(*fData); 00160 } 00161 fData = p; 00162 } 00163 bool isDataNull() { return (fData == 0); } 00164 00165 private : 00166 // ----------------------------------------------------------------------- 00167 // Unimplemented constructors and operators 00168 // ----------------------------------------------------------------------- 00169 SocketJanitor(); 00170 SocketJanitor(const SocketJanitor&); 00171 SocketJanitor& operator=(const SocketJanitor&); 00172 00173 // ----------------------------------------------------------------------- 00174 // Private data members 00175 // 00176 // fData 00177 // This is the pointer to the socket that must be closed when 00178 // this object is destroyed. 00179 // ----------------------------------------------------------------------- 00180 SOCKET* fData; 00181 }; 00182 00183 bool BinHTTPURLInputStream::fInitialized = false; 00184 00185 void BinHTTPURLInputStream::Initialize(MemoryManager* const manager) 00186 { 00187 // 00188 // Initialize the WinSock library here. 00189 // 00190 WORD wVersionRequested; 00191 WSADATA wsaData; 00192 00193 LPFN_WSASTARTUP startup = NULL; 00194 if(gWinsockLib == NULL) 00195 { 00196 #ifdef WITH_IPV6 00197 gWinsockLib = LoadLibraryA("WS2_32"); 00198 #else 00199 gWinsockLib = LoadLibraryA("WSOCK32"); 00200 #endif 00201 if(gWinsockLib == NULL) 00202 { 00203 ThrowXMLwithMemMgr(NetAccessorException, XMLExcepts::NetAcc_InitFailed, manager); 00204 } 00205 else 00206 { 00207 startup = (LPFN_WSASTARTUP) GetProcAddress(gWinsockLib,"WSAStartup"); 00208 gWSACleanup = (LPFN_WSACLEANUP) GetProcAddress(gWinsockLib,"WSACleanup"); 00209 gWShtons = (LPFN_HTONS) GetProcAddress(gWinsockLib,"htons"); 00210 gWSsocket = (LPFN_SOCKET) GetProcAddress(gWinsockLib,"socket"); 00211 gWSconnect = (LPFN_CONNECT) GetProcAddress(gWinsockLib,"connect"); 00212 gWSsend = (LPFN_SEND) GetProcAddress(gWinsockLib,"send"); 00213 gWSrecv = (LPFN_RECV) GetProcAddress(gWinsockLib,"recv"); 00214 gWSshutdown = (LPFN_SHUTDOWN) GetProcAddress(gWinsockLib,"shutdown"); 00215 gWSclosesocket = (LPFN_CLOSESOCKET) GetProcAddress(gWinsockLib,"closesocket"); 00216 #ifdef WITH_IPV6 00217 gWSgetaddrinfo = (LPFN_GETADDRINFO) GetProcAddress(gWinsockLib,"getaddrinfo"); 00218 gWSfreeaddrinfo = (LPFN_FREEADDRINFO) GetProcAddress(gWinsockLib,"freeaddrinfo"); 00219 #else 00220 gWSgethostbyname = (LPFN_GETHOSTBYNAME) GetProcAddress(gWinsockLib,"gethostbyname"); 00221 gWSgethostbyaddr = (LPFN_GETHOSTBYADDR) GetProcAddress(gWinsockLib,"gethostbyaddr"); 00222 gWSinet_addr = (LPFN_INET_ADDR) GetProcAddress(gWinsockLib,"inet_addr"); 00223 #endif 00224 00225 if(startup == NULL 00226 || gWSACleanup == NULL 00227 || gWShtons == NULL 00228 || gWSsocket == NULL 00229 || gWSconnect == NULL 00230 || gWSsend == NULL 00231 || gWSrecv == NULL 00232 || gWSshutdown == NULL 00233 || gWSclosesocket == NULL 00234 #ifdef WITH_IPV6 00235 || gWSgetaddrinfo == NULL 00236 || gWSfreeaddrinfo == NULL 00237 #else 00238 || gWSgethostbyname == NULL 00239 || gWSgethostbyaddr == NULL 00240 || gWSinet_addr == NULL 00241 #endif 00242 ) 00243 { 00244 gWSACleanup = NULL; 00245 Cleanup(); 00246 ThrowXMLwithMemMgr(NetAccessorException, XMLExcepts::NetAcc_InitFailed, manager); 00247 } 00248 } 00249 } 00250 00251 wVersionRequested = MAKEWORD( 2, 2 ); 00252 00253 int err = (*startup)(wVersionRequested, &wsaData); 00254 if (err != 0) 00255 { 00256 // Call WSAGetLastError() to get the last error. 00257 ThrowXMLwithMemMgr(NetAccessorException, XMLExcepts::NetAcc_InitFailed, manager); 00258 } 00259 fInitialized = true; 00260 } 00261 00262 void BinHTTPURLInputStream::Cleanup() 00263 { 00264 XMLMutexLock lock(XMLPlatformUtils::fgAtomicMutex); 00265 00266 if(fInitialized) 00267 { 00268 if(gWSACleanup) (*gWSACleanup)(); 00269 gWSACleanup = NULL; 00270 FreeLibrary(gWinsockLib); 00271 gWinsockLib = NULL; 00272 gWShtons = NULL; 00273 gWSsocket = NULL; 00274 gWSconnect = NULL; 00275 gWSsend = NULL; 00276 gWSrecv = NULL; 00277 gWSshutdown = NULL; 00278 gWSclosesocket = NULL; 00279 #ifdef WITH_IPV6 00280 gWSgetaddrinfo = NULL; 00281 gWSfreeaddrinfo = NULL; 00282 #else 00283 gWSgethostbyname = NULL; 00284 gWSgethostbyaddr = NULL; 00285 gWSinet_addr = NULL; 00286 #endif 00287 00288 fInitialized = false; 00289 } 00290 } 00291 00292 BinHTTPURLInputStream::BinHTTPURLInputStream(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo /*=0*/) 00293 : BinHTTPInputStreamCommon(urlSource.getMemoryManager()) 00294 , fSocketHandle(0) 00295 { 00296 MemoryManager *memoryManager = urlSource.getMemoryManager(); 00297 00298 // Check if we need to load the winsock library. While locking the 00299 // mutex every time may be somewhat slow, we don't care in this 00300 // particular case since the next operation will most likely be 00301 // the network access which is a lot slower. 00302 // 00303 { 00304 XMLMutexLock lock(XMLPlatformUtils::fgAtomicMutex); 00305 00306 if (!fInitialized) 00307 Initialize(memoryManager); 00308 } 00309 00310 // 00311 // Pull all of the parts of the URL out of th urlSource object, and transcode them 00312 // and transcode them back to ASCII. 00313 // 00314 const XMLCh* hostName = urlSource.getHost(); 00315 00316 if (hostName == 0) 00317 ThrowXMLwithMemMgr1(NetAccessorException, 00318 XMLExcepts::File_CouldNotOpenFile, 00319 urlSource.getURLText(), 00320 memoryManager); 00321 00322 char* hostNameAsCharStar = XMLString::transcode(hostName, memoryManager); 00323 ArrayJanitor<char> janHostNameAsCharStar(hostNameAsCharStar, memoryManager); 00324 00325 XMLURL url(urlSource); 00326 int redirectCount = 0; 00327 SocketJanitor janSock(0); 00328 00329 do { 00330 // 00331 // Set up a socket. 00332 // 00333 00334 #ifdef WITH_IPV6 00335 struct addrinfo hints, *res, *ai; 00336 00337 CharBuffer portBuffer(10, memoryManager); 00338 portBuffer.appendDecimalNumber(url.getPortNum()); 00339 00340 memset(&hints, 0, sizeof(struct addrinfo)); 00341 hints.ai_family = PF_UNSPEC; 00342 hints.ai_socktype = SOCK_STREAM; 00343 int n = wrap_getaddrinfo(hostNameAsCharStar,portBuffer.getRawBuffer(),&hints, &res); 00344 if(n != 0) 00345 { 00346 hints.ai_flags = AI_NUMERICHOST; 00347 n = wrap_getaddrinfo(hostNameAsCharStar,(const char*)tempbuf,&hints, &res); 00348 if(n != 0) 00349 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_TargetResolution, hostName, memoryManager); 00350 } 00351 janSock.reset(); 00352 for (ai = res; ai != NULL; ai = ai->ai_next) { 00353 // Open a socket with the correct address family for this address. 00354 fSocketHandle = wrap_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); 00355 if (fSocketHandle == INVALID_SOCKET) 00356 continue; 00357 janSock.reset(&fSocketHandle); 00358 if (wrap_connect(fSocketHandle, ai->ai_addr, (int)ai->ai_addrlen) == SOCKET_ERROR) 00359 { 00360 wrap_freeaddrinfo(res); 00361 // Call WSAGetLastError() to get the error number. 00362 ThrowXMLwithMemMgr1(NetAccessorException, 00363 XMLExcepts::NetAcc_ConnSocket, url.getURLText(), memoryManager); 00364 } 00365 break; 00366 } 00367 wrap_freeaddrinfo(res); 00368 if (fSocketHandle == INVALID_SOCKET) 00369 { 00370 // Call WSAGetLastError() to get the error number. 00371 ThrowXMLwithMemMgr1(NetAccessorException, 00372 XMLExcepts::NetAcc_CreateSocket, url.getURLText(), memoryManager); 00373 } 00374 #else 00375 struct hostent* hostEntPtr = 0; 00376 struct sockaddr_in sa; 00377 00378 00379 if ((hostEntPtr = wrap_gethostbyname(hostNameAsCharStar)) == NULL) 00380 { 00381 unsigned long numAddress = wrap_inet_addr(hostNameAsCharStar); 00382 if (numAddress == INADDR_NONE) 00383 { 00384 // Call WSAGetLastError() to get the error number. 00385 ThrowXMLwithMemMgr1(NetAccessorException, 00386 XMLExcepts::NetAcc_TargetResolution, hostName, memoryManager); 00387 } 00388 if ((hostEntPtr = 00389 wrap_gethostbyaddr((const char *) &numAddress, 00390 sizeof(unsigned long), AF_INET)) == NULL) 00391 { 00392 // Call WSAGetLastError() to get the error number. 00393 ThrowXMLwithMemMgr1(NetAccessorException, 00394 XMLExcepts::NetAcc_TargetResolution, hostName, memoryManager); 00395 } 00396 } 00397 00398 memcpy((void *) &sa.sin_addr, 00399 (const void *) hostEntPtr->h_addr, hostEntPtr->h_length); 00400 sa.sin_family = hostEntPtr->h_addrtype; 00401 sa.sin_port = wrap_htons((unsigned short)url.getPortNum()); 00402 00403 janSock.reset(); 00404 fSocketHandle = wrap_socket(hostEntPtr->h_addrtype, SOCK_STREAM, 0); 00405 if (fSocketHandle == INVALID_SOCKET) 00406 { 00407 // Call WSAGetLastError() to get the error number. 00408 ThrowXMLwithMemMgr1(NetAccessorException, 00409 XMLExcepts::NetAcc_CreateSocket, url.getURLText(), memoryManager); 00410 } 00411 janSock.reset(&fSocketHandle); 00412 00413 if (wrap_connect(fSocketHandle, (struct sockaddr *) &sa, sizeof(sa)) == SOCKET_ERROR) 00414 { 00415 // Call WSAGetLastError() to get the error number. 00416 ThrowXMLwithMemMgr1(NetAccessorException, 00417 XMLExcepts::NetAcc_ConnSocket, url.getURLText(), memoryManager); 00418 } 00419 00420 #endif 00421 00422 int status = sendRequest(url, httpInfo); 00423 00424 if(status == 200) { 00425 // HTTP 200 OK response means we're done. 00426 // We're done 00427 break; 00428 } 00429 // a 3xx response means there was an HTTP redirect 00430 else if(status >= 300 && status <= 307) { 00431 redirectCount++; 00432 00433 XMLCh *newURLString = findHeader("Location"); 00434 ArrayJanitor<XMLCh> janNewURLString(newURLString, memoryManager); 00435 00436 if(newURLString == 0 || *newURLString == 0) { 00437 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, url.getURLText(), memoryManager); 00438 } 00439 00440 XMLURL newURL(memoryManager); 00441 newURL.setURL(url, newURLString); 00442 if(newURL.getProtocol() != XMLURL::HTTP) { 00443 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, newURL.getURLText(), memoryManager); 00444 } 00445 00446 url = newURL; 00447 hostName = newURL.getHost(); 00448 00449 if (hostName == 0) 00450 ThrowXMLwithMemMgr1(NetAccessorException, 00451 XMLExcepts::File_CouldNotOpenFile, 00452 newURL.getURLText(), 00453 memoryManager); 00454 00455 janHostNameAsCharStar.release(); 00456 hostNameAsCharStar = XMLString::transcode(hostName, memoryManager); 00457 janHostNameAsCharStar.reset(hostNameAsCharStar, memoryManager); 00458 } 00459 else { 00460 // Most likely a 404 Not Found error. 00461 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, url.getURLText(), memoryManager); 00462 } 00463 } while(redirectCount < 6); 00464 00465 janSock.release(); 00466 } 00467 00468 BinHTTPURLInputStream::~BinHTTPURLInputStream() 00469 { 00470 wrap_shutdown(fSocketHandle, SD_BOTH); 00471 wrap_closesocket(fSocketHandle); 00472 } 00473 00474 bool BinHTTPURLInputStream::send(const char *buf, XMLSize_t len) 00475 { 00476 XMLSize_t done = 0; 00477 int ret; 00478 00479 while(done < len) { 00480 ret = wrap_send(fSocketHandle, buf + done, (int)(len - done), 0); 00481 if(ret == SOCKET_ERROR) return false; 00482 done += ret; 00483 } 00484 00485 return true; 00486 } 00487 00488 int BinHTTPURLInputStream::receive(char *buf, XMLSize_t len) 00489 { 00490 int iLen = wrap_recv(fSocketHandle, buf, (int)len, 0); 00491 if (iLen == SOCKET_ERROR) return -1; 00492 return iLen; 00493 } 00494 00495 XERCES_CPP_NAMESPACE_END