147 lines
5.2 KiB
C++
147 lines
5.2 KiB
C++
|
/***************************************************************************
|
||
|
* Copyright (C) 2005 by Christof Donat *
|
||
|
* cdonat@gmx.de *
|
||
|
* *
|
||
|
* This program is free software; you can redistribute it and/or modify *
|
||
|
* it under the terms of the GNU General Public License as published by *
|
||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||
|
* (at your option) any later version. *
|
||
|
* *
|
||
|
* This program is distributed in the hope that it will be useful, *
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||
|
* GNU General Public License for more details. *
|
||
|
* *
|
||
|
* You should have received a copy of the GNU General Public License *
|
||
|
* along with this program; if not, write to the *
|
||
|
* Free Software Foundation, Inc., *
|
||
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include "httpclient.h"
|
||
|
#include "logger.h"
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/socket.h>
|
||
|
#include <netinet/in.h>
|
||
|
#include <arpa/inet.h>
|
||
|
#include <netdb.h>
|
||
|
|
||
|
using std::string;
|
||
|
using std::streamsize;
|
||
|
using std::iostream;
|
||
|
using boost::lexical_cast;
|
||
|
using boost::bad_lexical_cast;
|
||
|
|
||
|
TCPDevice::TCPDevice(const string& address, const short int port) {
|
||
|
this->init(address.c_str(),port);
|
||
|
}
|
||
|
TCPDevice::TCPDevice(const char* address, const short int port) {
|
||
|
this->init(address,port);
|
||
|
}
|
||
|
|
||
|
void TCPDevice::init(const char* address, const short int port) {
|
||
|
struct sockaddr_in addr;
|
||
|
bzero(&addr,sizeof(addr));
|
||
|
addr.sin_family = AF_INET;
|
||
|
if( (addr.sin_addr.s_addr = inet_addr(address)) == INADDR_NONE ) {
|
||
|
struct hostent* hp = gethostbyname(address);
|
||
|
if( hp == 0 ) throw("can't resolve hostname '"+string(address)+"'");
|
||
|
bcopy(hp->h_addr, (char*) &addr.sin_addr, hp->h_length);
|
||
|
}
|
||
|
addr.sin_port = htons(port);
|
||
|
|
||
|
if( (m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0 ) throw(string("can't open socket"));
|
||
|
if( ::connect(m_socket, (struct sockaddr*) &addr, sizeof(addr)) < 0 ) {
|
||
|
::close(m_socket);
|
||
|
throw("can't connect to '"+string(address)+"' port "+(lexical_cast<string>(port)));
|
||
|
}
|
||
|
}
|
||
|
TCPDevice::TCPDevice(const int socket) : m_socket(socket) {}
|
||
|
TCPDevice::TCPDevice(const TCPDevice& other) : m_socket(other.m_socket) { }
|
||
|
|
||
|
TCPDevice::~TCPDevice() { }
|
||
|
|
||
|
void TCPDevice::closeSocket() { ::close(m_socket); }
|
||
|
|
||
|
streamsize TCPDevice::read(char* s, streamsize n) { return (streamsize)::read(m_socket,(void*)s,(size_t)n); }
|
||
|
|
||
|
streamsize TCPDevice::write(const char* s, streamsize n) { return (streamsize)::write(m_socket,(const void*)s,(size_t)n); }
|
||
|
|
||
|
GenericHttpClient::GenericHttpClient(const string &url, const unsigned short defaultPort = 80):
|
||
|
m_url(url), m_defaultPort(defaultPort) {};
|
||
|
|
||
|
string GenericHttpClient::post(string postcontent) {
|
||
|
iostream *connection;
|
||
|
try { connection = this->parseUrl(); }
|
||
|
catch(string &e) {
|
||
|
Logger::log(Logger::FATAL,"connection failed: "+e);
|
||
|
exit(-1);
|
||
|
}
|
||
|
if( connection == 0 ) return "";
|
||
|
|
||
|
string outbuf = "POST "+m_path+" HTTP/1.1\r\n";
|
||
|
outbuf += "Connection: close\r\n";
|
||
|
outbuf += "User-Agent: hsadmin CLI client\r\n";
|
||
|
outbuf += "Content-Type: text/xml\r\n";
|
||
|
outbuf += "Content-Length: "+boost::lexical_cast<string>(postcontent.length())+"\r\n";
|
||
|
outbuf += "Host: "+m_hostname+"\r\n\r\n";
|
||
|
outbuf += postcontent;
|
||
|
|
||
|
for( int i = 0; i < outbuf.length(); i++ )
|
||
|
(*connection) << outbuf[i];;
|
||
|
|
||
|
connection->flush();
|
||
|
|
||
|
string reply = "";
|
||
|
|
||
|
char buf[257];
|
||
|
do { // we simply ignore the http header in the response
|
||
|
bzero(buf,257);
|
||
|
connection->getline(buf,256);
|
||
|
} while( string(buf) != "" && string(buf) != "\r" );
|
||
|
|
||
|
string tmp;
|
||
|
do {
|
||
|
tmp = "";
|
||
|
(*connection) >> tmp;
|
||
|
reply += " "+tmp;
|
||
|
} while( tmp.length() );
|
||
|
|
||
|
this->close();
|
||
|
delete connection;
|
||
|
|
||
|
return reply;
|
||
|
};
|
||
|
|
||
|
iostream * GenericHttpClient::parseUrl() {
|
||
|
int protocolend = m_url.find("://");
|
||
|
m_protocol = m_url.substr(0,protocolend);
|
||
|
if( ! this->checkProtocol(m_protocol) ) return (iostream *)0;
|
||
|
|
||
|
int hostnameend = m_url.find("/",protocolend+3);
|
||
|
m_hostname = m_url.substr(protocolend+3,hostnameend-(protocolend+3));
|
||
|
m_port = m_defaultPort;
|
||
|
m_path = m_url.substr(hostnameend);
|
||
|
int portstart = m_hostname.find(":");
|
||
|
if( portstart >= 0 ) {
|
||
|
string portstring = m_hostname.substr(portstart+1);
|
||
|
|
||
|
if( portstring.size() > 0 ) {
|
||
|
try {
|
||
|
m_port = lexical_cast<int>(portstring.c_str());
|
||
|
m_hostname = m_hostname.substr(0,m_hostname.find(":"));
|
||
|
} catch(bad_lexical_cast &) { }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return this->getConnection(m_hostname, m_port);
|
||
|
};
|
||
|
|
||
|
GenericHttpClient *createHttpClient(const string &url) {
|
||
|
int protocolend = url.find("://");
|
||
|
string protocol = url.substr(0,protocolend);
|
||
|
if( protocol == "http" ) return (GenericHttpClient *) new HttpClient<HTTP>(url);
|
||
|
if( protocol == "https" ) return (GenericHttpClient *) new HttpClient<HTTPS>(url);
|
||
|
return 0;
|
||
|
}
|