Click here to Skip to main content
15,891,633 members
Articles / Programming Languages / XML

XMLFoundation

Rate me:
Please Sign up or sign in to vote.
4.82/5 (12 votes)
2 Jul 20029 min read 75.2K   1.4K   34  
Obtaining data marked up in XML creates the need for Application Layer tools to easily and efficiently work with XML data.
// --------------------------------------------------------------------------
//					www.UnitedBusinessTechnologies.com
//			  Copyright (c) 1998 - 2002  All Rights Reserved.
//
// Source in this file is released to the public under the following license:
// --------------------------------------------------------------------------
// This toolkit may be used free of charge for any purpose including corporate
// and academic use.  For profit, and Non-Profit uses are permitted.
//
// This source code and any work derived from this source code must retain 
// this copyright at the top of each source file.
// 
// UBT welcomes any suggestions, improvements or new platform ports.
// email to: XMLFoundation@UnitedBusinessTechnologies.com
// --------------------------------------------------------------------------

#include "SocketHTTPDataSource.h"
#include "GString.h"
#include "GException.h"
#include "GProfile.h"


#include <stdio.h> // for: sprintf()
#include <string.h> // for: strlen() memcpy(), memset() strcat()
#ifndef _WIN32
#include <errno.h> // for global errno an all OS's except MSFT
#endif


#include <sys/types.h>
#ifdef _WIN32
	// NT only
	#include <winsock.h>
#else 
	// _LINUX && __sun &&  _HPUX
	#include <netinet/in.h>
	#include <sys/socket.h>
	#include <netdb.h> // for gethostbyname() and hostent structure definition
	#include <arpa/inet.h>	// for inet_addr struct
#endif

#ifdef __sun 
	#include <unistd.h>		// for close()
#endif
#ifdef _LINUX
	#include <unistd.h>		// for close()
#endif


CSocketHTTPDataSource::CSocketHTTPDataSource(const char **ppQueryAttributes/* = 0*/) : 
	CFileDataSource(ppQueryAttributes)
{
}

CSocketHTTPDataSource::~CSocketHTTPDataSource()
{
}

void CSocketHTTPDataSource::SendHelper(const char *pzRequest, int nRequestLen, GString &destinationStream, const char *pzNamespace)
{
	int fd, numbytes;  
#ifdef _WIN32
	WSADATA wsaData;
	WSAStartup(MAKEWORD( 1, 0 ), &wsaData);
#endif

	int nNamespaceLen = strlen(pzNamespace);


	struct sockaddr_in their_addr; 
	their_addr.sin_family = AF_INET;      
	their_addr.sin_port = htons(m_nPort); 
	their_addr.sin_addr.s_addr = inet_addr (GetServerAddress());
	if (their_addr.sin_addr.s_addr == -1)
	{
		// resolve a DNS server name if inet_addr() came up empty.
		struct hostent *pHE = (struct hostent *)gethostbyname(GetServerAddress());
		if (pHE == 0)
		{ 
			GString strError;
			strError.Format("gethostbyname() failed to resolve[%s]",GetServerAddress());
			throw CSocketError(errno,(const char *)strError);
		}
		memcpy((char *)&(their_addr.sin_addr), pHE->h_addr,pHE->h_length); 
	}
	memset(&(their_addr.sin_zero),0, 8);//zero the rest of the struct


	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
	{	
		throw CSocketError(0,"socket");
	}
	CSocketWrap sockfd(fd); 


	// local bind() is not required on WIN32 platform
	struct sockaddr_in localAddr; 
	localAddr.sin_family = AF_INET;
	localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	localAddr.sin_port = htons(0);
	int rc = bind(fd, (struct sockaddr *) &localAddr, sizeof(localAddr));
	if(rc<0) 
	{
		GString strError;
		strError.Format("failed to bind([%s]:%d)",GetServerAddress(),m_nPort);
		throw CSocketError(errno,(const char *)strError);
	}


	if (connect(fd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) 
	{
		GString strError;
		strError.Format("failed to connect([%s]:%d)",GetServerAddress(),m_nPort);
		throw CSocketError(errno,(const char *)strError);
	}

	// 200 bytes in excess
	char *pSendBuf = new char[200 + nRequestLen + nNamespaceLen];
	sprintf(pSendBuf,"POST /XMLServer/UBT.dll?%s HTTP/1.1\r\nUser-Agent: XML_Object_Framework_DataSource\r\nHost: 100.100.100.100\r\nContent-Length:  ",pzNamespace);
	
	GString strTemp;
	strTemp.Format("%d\r\n\r\n%s",nNamespaceLen + nRequestLen,pzNamespace);
	strcat(&pSendBuf[120],(const char *)strTemp);
	int nHeaderLen = strlen(&pSendBuf[120]) + 120;
	strcat(&pSendBuf[120],pzRequest);


	int nTotalMessageLength = nHeaderLen + nRequestLen;


	if ((numbytes=sendto(sockfd, pSendBuf, nTotalMessageLength, 0, 
		 (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) 
	{
		delete pSendBuf;
		throw CSocketError(sockfd,"sendto");
	}
	delete pSendBuf;

	int nCumulativeBytes = 0;
	numbytes = 0;
	do
	{
		if ((numbytes=recv(sockfd, m_winsockBuffer, sizeof(m_winsockBuffer), 0)) == -1) 
		{
			continue;
		}
		destinationStream.write(m_winsockBuffer,numbytes);
		nCumulativeBytes += numbytes;
	}while( numbytes != 0 );
}


const char *CSocketHTTPDataSource::send(const char *pzProcedureName, 
								  const char *xml, 
								  int nXMLLen, 
								  void *PooledConnection,
								  void **ppUserData,
								  const char *pzNamespace)
{
	// service the request locally if conf'd by txml.txt or SetConnectionInfo()
	const char *pXML = CFileDataSource::send(pzProcedureName,xml,nXMLLen,PooledConnection,ppUserData,pzNamespace);
	if (pXML)
		return pXML;

	char *pHTTP = 0;
	
	GString *XMLResults = new GString(100000);
	GString **pp = (GString **)ppUserData;
	GString *p = *pp;
	p = XMLResults;

	// go to the server for the response
	int nAttempts = 0;
	for (int i = 0; i < 1; i++)
	{
		try
		{
			SendHelper( xml, nXMLLen, *XMLResults, pzNamespace );
			nAttempts = 0;
			pHTTP = (char *)(const char *)*XMLResults;
			// XML starts after HTTP 1.1 headers
			pXML = pHTTP;
			while(memcmp(pXML,"HTTP",4)==0)
			{
				// advance past the HTTP header(s)
				pXML = strstr(pXML,"\r\n\r\n") + 4;
			}
		}catch( CSocketError &rErr )
		{
			nAttempts++;
			i--;
			if (nAttempts > 3)
			{
				throw GenericException("Socket data soruce", 2001, rErr.m_nErrorCode, rErr.m_pzOperation);
			}
		}
	}
	return pXML;
}


int CSocketHTTPDataSource::release(const char *resultFromSend, void *PooledConnection, void *ppUserData)
{
	// if the base class can't delete it
	if (!CFileDataSource::release(resultFromSend,PooledConnection,ppUserData))
	{
		// then do it here
		delete (GString *)ppUserData;
	}
	return 1;
}



CSocketError::CSocketError(int nSocketHandle, const char *pzOperation)
{
	strcpy(m_pzOperation,pzOperation);
	m_nErrorCode = 0;
#ifdef _WIN32		
	m_nErrorCode = WSAGetLastError();
#endif
	if (!m_nErrorCode)
	{
		int size = sizeof(m_nErrorCode);
#ifdef WIN32
		int status = getsockopt(nSocketHandle, SOL_SOCKET, SO_ERROR, (char *) &m_nErrorCode, &size);
#else
		int status = getsockopt(nSocketHandle, SOL_SOCKET, SO_ERROR, (char *) &m_nErrorCode, (socklen_t *)&size);
#endif

		if (!m_nErrorCode)
			m_nErrorCode = errno;
		if (!m_nErrorCode)
			m_nErrorCode = -1;
	}

}

CSocketWrap::CSocketWrap(int nSocketHandle)
{
	m_nSocketHandle = nSocketHandle;
}

CSocketWrap::~CSocketWrap()
{
#ifdef _WIN32    
	closesocket(m_nSocketHandle);
	WSACleanup();
#elif _HPUX
	shutdown(m_nSocketHandle,2);
#else
	close(m_nSocketHandle);
#endif
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Founder United Business Technologies
United States United States
http://about.me/brian.aberle
https://www.linkedin.com/in/brianaberle
http://SyrianRue.org/Brian

Comments and Discussions