Added Xerces-C++ 3.1.2
This commit is contained in:
@@ -0,0 +1,495 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: BinHTTPURLInputStream.cpp 936316 2010-04-21 14:19:58Z borisk $
|
||||
*/
|
||||
|
||||
|
||||
#include <xercesc/util/NetAccessors/WinSock/BinHTTPURLInputStream.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef WITH_IPV6
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <xercesc/util/PlatformUtils.hpp>
|
||||
#include <xercesc/util/XMLNetAccessor.hpp>
|
||||
#include <xercesc/util/XMLString.hpp>
|
||||
#include <xercesc/util/XMLExceptMsgs.hpp>
|
||||
#include <xercesc/util/Janitor.hpp>
|
||||
#include <xercesc/util/XMLUniDefs.hpp>
|
||||
#include <xercesc/util/Mutexes.hpp>
|
||||
|
||||
XERCES_CPP_NAMESPACE_BEGIN
|
||||
|
||||
typedef u_short (WSAAPI * LPFN_HTONS)(u_short hostshort);
|
||||
typedef SOCKET (WSAAPI * LPFN_SOCKET)(int af, int type, int protocol);
|
||||
typedef int (WSAAPI * LPFN_CONNECT)(SOCKET s, const struct sockaddr* name, int namelen);
|
||||
typedef int (WSAAPI * LPFN_SEND)(SOCKET s, const char* buf, int len, int flags);
|
||||
typedef int (WSAAPI * LPFN_RECV)(SOCKET s, char* buf, int len, int flags);
|
||||
typedef int (WSAAPI * LPFN_SHUTDOWN)(SOCKET s, int how);
|
||||
typedef int (WSAAPI * LPFN_CLOSESOCKET)(SOCKET s);
|
||||
typedef int (WSAAPI * LPFN_WSACLEANUP)();
|
||||
typedef int (WSAAPI * LPFN_WSASTARTUP)(WORD wVersionRequested, LPWSADATA lpWSAData);
|
||||
#ifdef WITH_IPV6
|
||||
typedef int (WSAAPI * LPFN_GETADDRINFO)(const char* nodename, const char * servname, const struct addrinfo * hints, struct addrinfo ** res);
|
||||
typedef void (WSAAPI * LPFN_FREEADDRINFO)(struct addrinfo * ai);
|
||||
#else
|
||||
typedef struct hostent *(WSAAPI * LPFN_GETHOSTBYNAME)(const char* name);
|
||||
typedef struct hostent *(WSAAPI * LPFN_GETHOSTBYADDR)(const char* addr, int len, int type);
|
||||
typedef unsigned long (WSAAPI * LPFN_INET_ADDR)(const char* cp);
|
||||
#endif
|
||||
|
||||
static HMODULE gWinsockLib = NULL;
|
||||
static LPFN_HTONS gWShtons = NULL;
|
||||
static LPFN_SOCKET gWSsocket = NULL;
|
||||
static LPFN_CONNECT gWSconnect = NULL;
|
||||
static LPFN_SEND gWSsend = NULL;
|
||||
static LPFN_RECV gWSrecv = NULL;
|
||||
static LPFN_SHUTDOWN gWSshutdown = NULL;
|
||||
static LPFN_CLOSESOCKET gWSclosesocket = NULL;
|
||||
static LPFN_WSACLEANUP gWSACleanup = NULL;
|
||||
#ifdef WITH_IPV6
|
||||
static LPFN_GETADDRINFO gWSgetaddrinfo = NULL;
|
||||
static LPFN_FREEADDRINFO gWSfreeaddrinfo = NULL;
|
||||
#else
|
||||
static LPFN_GETHOSTBYNAME gWSgethostbyname = NULL;
|
||||
static LPFN_GETHOSTBYADDR gWSgethostbyaddr = NULL;
|
||||
static LPFN_INET_ADDR gWSinet_addr = NULL;
|
||||
#endif
|
||||
|
||||
static u_short wrap_htons(u_short hostshort)
|
||||
{
|
||||
return (*gWShtons)(hostshort);
|
||||
}
|
||||
|
||||
static SOCKET wrap_socket(int af,int type,int protocol)
|
||||
{
|
||||
return (*gWSsocket)(af,type,protocol);
|
||||
}
|
||||
|
||||
static int wrap_connect(SOCKET s,const struct sockaddr* name,int namelen)
|
||||
{
|
||||
return (*gWSconnect)(s,name,namelen);
|
||||
}
|
||||
|
||||
static int wrap_send(SOCKET s,const char* buf,int len,int flags)
|
||||
{
|
||||
return (*gWSsend)(s,buf,len,flags);
|
||||
}
|
||||
|
||||
static int wrap_recv(SOCKET s,char* buf,int len,int flags)
|
||||
{
|
||||
return (*gWSrecv)(s,buf,len,flags);
|
||||
}
|
||||
|
||||
static int wrap_shutdown(SOCKET s,int how)
|
||||
{
|
||||
return (*gWSshutdown)(s,how);
|
||||
}
|
||||
|
||||
static int wrap_closesocket(SOCKET socket)
|
||||
{
|
||||
return (*gWSclosesocket)(socket);
|
||||
}
|
||||
|
||||
#ifdef WITH_IPV6
|
||||
static int wrap_getaddrinfo(const char* nodename,const char* servname,const struct addrinfo* hints,struct addrinfo** res)
|
||||
{
|
||||
return (*gWSgetaddrinfo)(nodename,servname,hints,res);
|
||||
}
|
||||
|
||||
static void wrap_freeaddrinfo(struct addrinfo* ai)
|
||||
{
|
||||
(*gWSfreeaddrinfo)(ai);
|
||||
}
|
||||
#else
|
||||
static struct hostent* wrap_gethostbyname(const char* name)
|
||||
{
|
||||
return (*gWSgethostbyname)(name);
|
||||
}
|
||||
|
||||
static struct hostent* wrap_gethostbyaddr(const char* addr,int len,int type)
|
||||
{
|
||||
return (*gWSgethostbyaddr)(addr,len,type);
|
||||
}
|
||||
|
||||
static unsigned long wrap_inet_addr(const char* cp)
|
||||
{
|
||||
return (*gWSinet_addr)(cp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
class SocketJanitor
|
||||
{
|
||||
public:
|
||||
// -----------------------------------------------------------------------
|
||||
// Constructors and Destructor
|
||||
// -----------------------------------------------------------------------
|
||||
SocketJanitor(SOCKET* toDelete) : fData(toDelete) {}
|
||||
~SocketJanitor() { reset(); }
|
||||
|
||||
SOCKET* get() const { return fData; }
|
||||
SOCKET* release() { SOCKET* p = fData; fData = 0; return p; }
|
||||
|
||||
void reset(SOCKET* p = 0)
|
||||
{
|
||||
if(fData) {
|
||||
wrap_shutdown(*fData, SD_BOTH);
|
||||
wrap_closesocket(*fData);
|
||||
}
|
||||
fData = p;
|
||||
}
|
||||
bool isDataNull() { return (fData == 0); }
|
||||
|
||||
private :
|
||||
// -----------------------------------------------------------------------
|
||||
// Unimplemented constructors and operators
|
||||
// -----------------------------------------------------------------------
|
||||
SocketJanitor();
|
||||
SocketJanitor(const SocketJanitor&);
|
||||
SocketJanitor& operator=(const SocketJanitor&);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Private data members
|
||||
//
|
||||
// fData
|
||||
// This is the pointer to the socket that must be closed when
|
||||
// this object is destroyed.
|
||||
// -----------------------------------------------------------------------
|
||||
SOCKET* fData;
|
||||
};
|
||||
|
||||
bool BinHTTPURLInputStream::fInitialized = false;
|
||||
|
||||
void BinHTTPURLInputStream::Initialize(MemoryManager* const manager)
|
||||
{
|
||||
//
|
||||
// Initialize the WinSock library here.
|
||||
//
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
|
||||
LPFN_WSASTARTUP startup = NULL;
|
||||
if(gWinsockLib == NULL)
|
||||
{
|
||||
#ifdef WITH_IPV6
|
||||
gWinsockLib = LoadLibraryA("WS2_32");
|
||||
#else
|
||||
gWinsockLib = LoadLibraryA("WSOCK32");
|
||||
#endif
|
||||
if(gWinsockLib == NULL)
|
||||
{
|
||||
ThrowXMLwithMemMgr(NetAccessorException, XMLExcepts::NetAcc_InitFailed, manager);
|
||||
}
|
||||
else
|
||||
{
|
||||
startup = (LPFN_WSASTARTUP) GetProcAddress(gWinsockLib,"WSAStartup");
|
||||
gWSACleanup = (LPFN_WSACLEANUP) GetProcAddress(gWinsockLib,"WSACleanup");
|
||||
gWShtons = (LPFN_HTONS) GetProcAddress(gWinsockLib,"htons");
|
||||
gWSsocket = (LPFN_SOCKET) GetProcAddress(gWinsockLib,"socket");
|
||||
gWSconnect = (LPFN_CONNECT) GetProcAddress(gWinsockLib,"connect");
|
||||
gWSsend = (LPFN_SEND) GetProcAddress(gWinsockLib,"send");
|
||||
gWSrecv = (LPFN_RECV) GetProcAddress(gWinsockLib,"recv");
|
||||
gWSshutdown = (LPFN_SHUTDOWN) GetProcAddress(gWinsockLib,"shutdown");
|
||||
gWSclosesocket = (LPFN_CLOSESOCKET) GetProcAddress(gWinsockLib,"closesocket");
|
||||
#ifdef WITH_IPV6
|
||||
gWSgetaddrinfo = (LPFN_GETADDRINFO) GetProcAddress(gWinsockLib,"getaddrinfo");
|
||||
gWSfreeaddrinfo = (LPFN_FREEADDRINFO) GetProcAddress(gWinsockLib,"freeaddrinfo");
|
||||
#else
|
||||
gWSgethostbyname = (LPFN_GETHOSTBYNAME) GetProcAddress(gWinsockLib,"gethostbyname");
|
||||
gWSgethostbyaddr = (LPFN_GETHOSTBYADDR) GetProcAddress(gWinsockLib,"gethostbyaddr");
|
||||
gWSinet_addr = (LPFN_INET_ADDR) GetProcAddress(gWinsockLib,"inet_addr");
|
||||
#endif
|
||||
|
||||
if(startup == NULL
|
||||
|| gWSACleanup == NULL
|
||||
|| gWShtons == NULL
|
||||
|| gWSsocket == NULL
|
||||
|| gWSconnect == NULL
|
||||
|| gWSsend == NULL
|
||||
|| gWSrecv == NULL
|
||||
|| gWSshutdown == NULL
|
||||
|| gWSclosesocket == NULL
|
||||
#ifdef WITH_IPV6
|
||||
|| gWSgetaddrinfo == NULL
|
||||
|| gWSfreeaddrinfo == NULL
|
||||
#else
|
||||
|| gWSgethostbyname == NULL
|
||||
|| gWSgethostbyaddr == NULL
|
||||
|| gWSinet_addr == NULL
|
||||
#endif
|
||||
)
|
||||
{
|
||||
gWSACleanup = NULL;
|
||||
Cleanup();
|
||||
ThrowXMLwithMemMgr(NetAccessorException, XMLExcepts::NetAcc_InitFailed, manager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wVersionRequested = MAKEWORD( 2, 2 );
|
||||
|
||||
int err = (*startup)(wVersionRequested, &wsaData);
|
||||
if (err != 0)
|
||||
{
|
||||
// Call WSAGetLastError() to get the last error.
|
||||
ThrowXMLwithMemMgr(NetAccessorException, XMLExcepts::NetAcc_InitFailed, manager);
|
||||
}
|
||||
fInitialized = true;
|
||||
}
|
||||
|
||||
void BinHTTPURLInputStream::Cleanup()
|
||||
{
|
||||
XMLMutexLock lock(XMLPlatformUtils::fgAtomicMutex);
|
||||
|
||||
if(fInitialized)
|
||||
{
|
||||
if(gWSACleanup) (*gWSACleanup)();
|
||||
gWSACleanup = NULL;
|
||||
FreeLibrary(gWinsockLib);
|
||||
gWinsockLib = NULL;
|
||||
gWShtons = NULL;
|
||||
gWSsocket = NULL;
|
||||
gWSconnect = NULL;
|
||||
gWSsend = NULL;
|
||||
gWSrecv = NULL;
|
||||
gWSshutdown = NULL;
|
||||
gWSclosesocket = NULL;
|
||||
#ifdef WITH_IPV6
|
||||
gWSgetaddrinfo = NULL;
|
||||
gWSfreeaddrinfo = NULL;
|
||||
#else
|
||||
gWSgethostbyname = NULL;
|
||||
gWSgethostbyaddr = NULL;
|
||||
gWSinet_addr = NULL;
|
||||
#endif
|
||||
|
||||
fInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
BinHTTPURLInputStream::BinHTTPURLInputStream(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo /*=0*/)
|
||||
: BinHTTPInputStreamCommon(urlSource.getMemoryManager())
|
||||
, fSocketHandle(0)
|
||||
{
|
||||
MemoryManager *memoryManager = urlSource.getMemoryManager();
|
||||
|
||||
// Check if we need to load the winsock library. While locking the
|
||||
// mutex every time may be somewhat slow, we don't care in this
|
||||
// particular case since the next operation will most likely be
|
||||
// the network access which is a lot slower.
|
||||
//
|
||||
{
|
||||
XMLMutexLock lock(XMLPlatformUtils::fgAtomicMutex);
|
||||
|
||||
if (!fInitialized)
|
||||
Initialize(memoryManager);
|
||||
}
|
||||
|
||||
//
|
||||
// Pull all of the parts of the URL out of th urlSource object, and transcode them
|
||||
// and transcode them back to ASCII.
|
||||
//
|
||||
const XMLCh* hostName = urlSource.getHost();
|
||||
|
||||
if (hostName == 0)
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::File_CouldNotOpenFile,
|
||||
urlSource.getURLText(),
|
||||
memoryManager);
|
||||
|
||||
char* hostNameAsCharStar = XMLString::transcode(hostName, memoryManager);
|
||||
ArrayJanitor<char> janHostNameAsCharStar(hostNameAsCharStar, memoryManager);
|
||||
|
||||
XMLURL url(urlSource);
|
||||
int redirectCount = 0;
|
||||
SocketJanitor janSock(0);
|
||||
|
||||
do {
|
||||
//
|
||||
// Set up a socket.
|
||||
//
|
||||
|
||||
#ifdef WITH_IPV6
|
||||
struct addrinfo hints, *res, *ai;
|
||||
|
||||
CharBuffer portBuffer(10, memoryManager);
|
||||
portBuffer.appendDecimalNumber(url.getPortNum());
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
int n = wrap_getaddrinfo(hostNameAsCharStar,portBuffer.getRawBuffer(),&hints, &res);
|
||||
if(n != 0)
|
||||
{
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
n = wrap_getaddrinfo(hostNameAsCharStar,(const char*)tempbuf,&hints, &res);
|
||||
if(n != 0)
|
||||
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_TargetResolution, hostName, memoryManager);
|
||||
}
|
||||
janSock.reset();
|
||||
for (ai = res; ai != NULL; ai = ai->ai_next) {
|
||||
// Open a socket with the correct address family for this address.
|
||||
fSocketHandle = wrap_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
if (fSocketHandle == INVALID_SOCKET)
|
||||
continue;
|
||||
janSock.reset(&fSocketHandle);
|
||||
if (wrap_connect(fSocketHandle, ai->ai_addr, (int)ai->ai_addrlen) == SOCKET_ERROR)
|
||||
{
|
||||
wrap_freeaddrinfo(res);
|
||||
// Call WSAGetLastError() to get the error number.
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::NetAcc_ConnSocket, url.getURLText(), memoryManager);
|
||||
}
|
||||
break;
|
||||
}
|
||||
wrap_freeaddrinfo(res);
|
||||
if (fSocketHandle == INVALID_SOCKET)
|
||||
{
|
||||
// Call WSAGetLastError() to get the error number.
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::NetAcc_CreateSocket, url.getURLText(), memoryManager);
|
||||
}
|
||||
#else
|
||||
struct hostent* hostEntPtr = 0;
|
||||
struct sockaddr_in sa;
|
||||
|
||||
|
||||
if ((hostEntPtr = wrap_gethostbyname(hostNameAsCharStar)) == NULL)
|
||||
{
|
||||
unsigned long numAddress = wrap_inet_addr(hostNameAsCharStar);
|
||||
if (numAddress == INADDR_NONE)
|
||||
{
|
||||
// Call WSAGetLastError() to get the error number.
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::NetAcc_TargetResolution, hostName, memoryManager);
|
||||
}
|
||||
if ((hostEntPtr =
|
||||
wrap_gethostbyaddr((const char *) &numAddress,
|
||||
sizeof(unsigned long), AF_INET)) == NULL)
|
||||
{
|
||||
// Call WSAGetLastError() to get the error number.
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::NetAcc_TargetResolution, hostName, memoryManager);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy((void *) &sa.sin_addr,
|
||||
(const void *) hostEntPtr->h_addr, hostEntPtr->h_length);
|
||||
sa.sin_family = hostEntPtr->h_addrtype;
|
||||
sa.sin_port = wrap_htons((unsigned short)url.getPortNum());
|
||||
|
||||
janSock.reset();
|
||||
fSocketHandle = wrap_socket(hostEntPtr->h_addrtype, SOCK_STREAM, 0);
|
||||
if (fSocketHandle == INVALID_SOCKET)
|
||||
{
|
||||
// Call WSAGetLastError() to get the error number.
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::NetAcc_CreateSocket, url.getURLText(), memoryManager);
|
||||
}
|
||||
janSock.reset(&fSocketHandle);
|
||||
|
||||
if (wrap_connect(fSocketHandle, (struct sockaddr *) &sa, sizeof(sa)) == SOCKET_ERROR)
|
||||
{
|
||||
// Call WSAGetLastError() to get the error number.
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::NetAcc_ConnSocket, url.getURLText(), memoryManager);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int status = sendRequest(url, httpInfo);
|
||||
|
||||
if(status == 200) {
|
||||
// HTTP 200 OK response means we're done.
|
||||
// We're done
|
||||
break;
|
||||
}
|
||||
// a 3xx response means there was an HTTP redirect
|
||||
else if(status >= 300 && status <= 307) {
|
||||
redirectCount++;
|
||||
|
||||
XMLCh *newURLString = findHeader("Location");
|
||||
ArrayJanitor<XMLCh> janNewURLString(newURLString, memoryManager);
|
||||
|
||||
if(newURLString == 0 || *newURLString == 0) {
|
||||
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, url.getURLText(), memoryManager);
|
||||
}
|
||||
|
||||
XMLURL newURL(memoryManager);
|
||||
newURL.setURL(url, newURLString);
|
||||
if(newURL.getProtocol() != XMLURL::HTTP) {
|
||||
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, newURL.getURLText(), memoryManager);
|
||||
}
|
||||
|
||||
url = newURL;
|
||||
hostName = newURL.getHost();
|
||||
|
||||
if (hostName == 0)
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::File_CouldNotOpenFile,
|
||||
newURL.getURLText(),
|
||||
memoryManager);
|
||||
|
||||
janHostNameAsCharStar.release();
|
||||
hostNameAsCharStar = XMLString::transcode(hostName, memoryManager);
|
||||
janHostNameAsCharStar.reset(hostNameAsCharStar, memoryManager);
|
||||
}
|
||||
else {
|
||||
// Most likely a 404 Not Found error.
|
||||
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, url.getURLText(), memoryManager);
|
||||
}
|
||||
} while(redirectCount < 6);
|
||||
|
||||
janSock.release();
|
||||
}
|
||||
|
||||
BinHTTPURLInputStream::~BinHTTPURLInputStream()
|
||||
{
|
||||
wrap_shutdown(fSocketHandle, SD_BOTH);
|
||||
wrap_closesocket(fSocketHandle);
|
||||
}
|
||||
|
||||
bool BinHTTPURLInputStream::send(const char *buf, XMLSize_t len)
|
||||
{
|
||||
XMLSize_t done = 0;
|
||||
int ret;
|
||||
|
||||
while(done < len) {
|
||||
ret = wrap_send(fSocketHandle, buf + done, (int)(len - done), 0);
|
||||
if(ret == SOCKET_ERROR) return false;
|
||||
done += ret;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int BinHTTPURLInputStream::receive(char *buf, XMLSize_t len)
|
||||
{
|
||||
int iLen = wrap_recv(fSocketHandle, buf, (int)len, 0);
|
||||
if (iLen == SOCKET_ERROR) return -1;
|
||||
return iLen;
|
||||
}
|
||||
|
||||
XERCES_CPP_NAMESPACE_END
|
||||
Reference in New Issue
Block a user