#include "Url.h"
#include "Network.h"
#include <stdio.h>
#ifdef UNIX
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <netdb.h>
#else
# include <winsock2.h>
struct InitWS {
InitWS() { WSADATA wsaData; WSAStartup(MAKEWORD(2,2), &wsaData); }
~InitWS() { WSACleanup(); }
} g_initWinSock;
#endif
BEGIN_NAMESPACE
static void error(const char *msg)
{
perror(msg);
exit(0);
}
static void check(bool cond, const char *msg)
{
if (!cond)
error(msg);
}
Socket::Socket()
{
m_sockfd = (SocketId)socket(AF_INET, SOCK_STREAM, 0);
check(m_sockfd >= 0, "ERROR opening socket");
}
Socket::~Socket()
{
closesocket((SOCKET)m_sockfd);
}
bool Socket::connect(const String& a_hostName, int a_port)
{
struct hostent *server = gethostbyname(a_hostName.data());
check(server != NULL, "ERROR looking up ip of server");
if (server == NULL)
return false;
struct sockaddr_in serv_addr = {};
serv_addr.sin_family = AF_INET;
memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
serv_addr.sin_port = htons(a_port);
int n = ::connect(m_sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
check(n >= 0, "ERROR connecting socket to host");
return (n >= 0);
}
int Socket::send(const String& a_string)
{
int n = ::send(m_sockfd, a_string.data(), (int)a_string.toUtf8().size(), 0);
check(n >= 0, "ERROR writing to socket");
return n;
}
String Socket::receive(int a_length)
{
int totalRecv = 0, n = 1;
std::string response;
while (n > 0)
{
char buffer[1025];
n = ::recv(m_sockfd, buffer, (a_length > totalRecv) ? (a_length - totalRecv) : 1024, 0);
if (n > 0)
{
buffer[n] = 0;
response += buffer;
totalRecv += n;
}
if (a_length >= 0 && totalRecv >= a_length)
break;
}
check(n >= 0, "ERROR reading from socket");
return response;
}
String Socket::receiveAll()
{
return receive(-1);
}
HttpRequest::HttpRequest(const Url& a_url, HttpMethod a_method)
{
switch (a_method)
{
case HM_PUT: m_request = "PUT"; break;
case HM_POST: m_request = "POST"; break;
default:
case HM_GET: m_request = "GET"; break;
}
m_request += " " + a_url.path().toUtf8() + " HTTP/1.1\r\n";
setHeader("Host", a_url.hostName());
setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36");
}
HttpRequest::~HttpRequest()
{
}
void HttpRequest::setHeader(String a_field, String a_value)
{
m_headers[a_field] = a_value;
}
String HttpRequest::data()
{
String request = m_request;
for (std::map<String, String>::iterator it = m_headers.begin(); it != m_headers.end(); it++)
request += it->first + ": " + it->second + "\r\n";
return request + "\r\n";
}
String Network::wget(const String& a_url)
{
Socket sock;
Url url(a_url);
HttpRequest request(url);
sock.connect(url.hostName(), url.port());
printf("HTTP request:\n--%s--\n", request.data().data());
sock.send(request.data());
return sock.receiveAll();
//return String(tiny_wget(url.hostName(), url.port(), url.path()));
}
#if 0
/*
Could this be turned in to a tiny_wget exe to sell with other
tiny versions of UNIX tools for windows users??????????
*/
static std::string tiny_wget(const char* hostname, int portno, const char* url)
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
check(sockfd >= 0, "ERROR opening socket");
struct hostent *server = gethostbyname(hostname);
check(server != NULL, "ERROR no such host");
struct sockaddr_in serv_addr = {};
serv_addr.sin_family = AF_INET;
memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
serv_addr.sin_port = htons(portno);
int connectRet = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
check(connectRet >= 0, "ERROR connecting");
std::string request = "GET " + std::string(url) + " HTTP/1.1\r\n";
request += "Host: " + std::string(hostname) + "\r\n";
request += "User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36\r\n";
//request += "Referer: http://www.investing.com/charts/forex-charts\r\n";
request += "\r\n";
int n = send(sockfd,request.c_str(),request.size(),0);
check(n >= 0, "ERROR writing to socket");
std::string response;
while (n > 0)
{
char buffer[1024];
n = recv(sockfd, buffer, 1024, 0);
if (n > 0)
{
buffer[n] = 0;
response += buffer;
}
}
check(n >= 0, "ERROR reading from socket");
//printf("Got response of: --%s---\n",response.c_str());
return response;
}
#endif
END_NAMESPACE