;/*
gcc -noixemul -Wall -O2 httpget.c -o httpget
quit
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#include <proto/exec.h>
#ifdef __SASC
#include <proto/socket.h>
#endif
#include <clib/alib_protos.h>
#define RECV_BUFSIZE 16384
struct MinList *http_get(const char *host, int port, const char *path);
struct MinList *dorecv(int s);
void dumplist(struct MinList *list);
void freelist(struct MinList *list);
struct datanode
{
struct MinNode node;
int len;
};
int main(void)
{
struct MinList *res;
res = http_get("www.amiga.org", 80, "/");
if (res)
{
dumplist(res);
freelist(res);
}
else
{
fprintf(stderr, "http_get failed\n");
}
return 0;
}
/*
FUNCTION
http_get - HTTP GET a location off a web server
struct MinList *http_get(const char *host, int port, const char *path)
INPUT
The http-request must be split into valid components for this function.
host: hostname
port: port number
path: the path of object to http get. spaces and special chars should
be encoded to %<hex>
RESULT
struct MinList *
NULL if error, else list filled with 'struct datanode' nodes. Note
that the output includes the full header returned by the server, and
it's left for the caller to parse it (separate header and actual
data).
NOTE
This function blocks, and it can potentially take hours to complete;
for example if the file is long, or the connection is very slow.
*/
struct MinList *http_get(const char *host, int port, const char *path)
{
struct MinList *list = NULL;
int s;
if (host && host[0] && port > 0 && path)
{
struct sockaddr_in saddr;
struct hostent *he;
bzero(&saddr, sizeof(saddr));
he = gethostbyname(host);
if (he)
{
memcpy(&saddr.sin_addr, he->h_addr, he->h_length);
saddr.sin_family = he->h_addrtype;
}
else
{
saddr.sin_addr.s_addr = inet_addr(host);
saddr.sin_family = AF_INET;
}
if (saddr.sin_addr.s_addr != INADDR_NONE)
{
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s != -1)
{
saddr.sin_port = htons(port);
if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr)) != -1)
{
const char *fmt =
"GET %s HTTP/1.0\r\n"
"Host: %s\r\n"
"User-Agent: httpget_test_app/1.0\r\n"
"\r\n";
char *req;
if (path[0] == '\0')
{
path = "/";
}
req = malloc(strlen(fmt) +
strlen(path) - 2 +
strlen(host) - 2 + 1);
if (req)
{
int reqlen;
sprintf(req, fmt, path, host);
reqlen = strlen(req);
if (send(s, req, reqlen, 0) == reqlen)
{
list = dorecv(s);
}
free(req);
}
close(s);
}
}
}
}
return list;
}
struct MinList *dorecv(int s)
{
struct MinList *list = NULL;
UBYTE *buf;
buf = malloc(RECV_BUFSIZE);
if (buf)
{
int ok = 0;
for (;;)
{
int actual;
actual = recv(s, buf, RECV_BUFSIZE, 0);
if (actual == -1)
{
/* error */
break;
}
else if (actual == 0)
{
/* eof */
ok = 1;
break;
}
else
{
struct datanode *node;
if (!list)
{
list = malloc(sizeof(*list));
if (!list)
{
break;
}
NewList((struct List *) list);
}
node = malloc(sizeof(*node) + actual);
if (!node)
{
break;
}
node->len = actual;
memcpy(node + 1, buf, actual);
AddTail((struct List *) list, (struct Node *) node);
}
}
if (!ok)
{
freelist(list);
list = NULL;
}
free(buf);
}
return list;
}
void dumplist(struct MinList *list)
{
if (list)
{
struct datanode *node;
fflush(stdout);
for (node = (APTR) list->mlh_Head;
node->node.mln_Succ;
node = (APTR) node->node.mln_Succ)
{
write(STDOUT_FILENO, node + 1, node->len);
}
fflush(stdout);
}
}
void freelist(struct MinList *list)
{
if (list)
{
struct datanode *node, *nextnode;
for (node = (APTR) list->mlh_Head;
(nextnode = (APTR) node->node.mln_Succ);
node = nextnode)
{
free(node);
}
free(list);
}
}