blob: 88ba9729a45b8be809e8e21296263dd95b002dbf [file] [log] [blame]
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include "hdhomerun_http.h"
#define HOST "google.com"
#define PAGE "/"
#define PORT 80
#define USERAGENT "SAGETV 1.0"
#define _MIN_(x, y) ((x) > (y) ? (y) : (x))
static char *get_ip(char *host, char *buf, int size)
{
struct hostent *hent;
char *ip = buf;
memset(ip, 0, size);
if ((hent = gethostbyname(host)) == NULL) {
herror("Can't get IP");
exit(1);
}
if (inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, size) == NULL) {
perror("Can't resolve host");
exit(1);
}
return ip;
}
static char *build_get_query(char *host, char *page)
{
char *query;
char *getpage = page;
char *tpl = "GET /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: %s\r\n\r\n";
if (getpage[0] == '/') {
getpage = getpage + 1;
}
// -5 is to consider the %s %s %s in tpl and the ending \0
query = (char *)malloc(strlen(host) + strlen(getpage) + strlen(USERAGENT) +
strlen(tpl) - 5);
sprintf(query, tpl, getpage, host, USERAGENT);
return query;
}
int parse_http_page(char *host, char *page, parser_f parser, void *context)
{
struct sockaddr_in *remote;
int ret;
char buf[BUFSIZ + 1];
int sock;
char *get;
char ip[32];
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("Can't create TCP socket");
return -1;
}
get_ip(host, ip, sizeof(ip));
remote = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in *));
remote->sin_family = AF_INET;
ret = inet_pton(AF_INET, ip, (void *)(&(remote->sin_addr.s_addr)));
if (ret < 0) {
perror("Can't set remote->sin_addr.s_addr");
goto exit_free_rem;
} else if (ret == 0) {
fprintf(stderr, "%s is not a valid IP address\n", ip);
ret = -1;
goto exit_free_rem;
}
remote->sin_port = htons(PORT);
if (connect(sock, (struct sockaddr *)remote, sizeof(struct sockaddr)) < 0) {
perror("Could not connect");
ret = -1;
goto exit_free_rem;
}
get = build_get_query(host, page);
// send the query to the server
int sent = 0;
while (sent < strlen(get)) {
ret = send(sock, get + sent, strlen(get) - sent, 0);
if (ret == -1) {
perror("Can't send query");
goto exit_free_get;
}
sent += ret;
}
// receive page
int remain = 0;
while ((ret = recv(sock, buf + remain, BUFSIZ - remain, 0)) > 0) {
int used_bytes = 0;
if (parser != NULL && ret >= 0) {
*(buf + remain + ret) = 0x0;
used_bytes = parser(context, buf, ret + remain);
remain = ret + remain - used_bytes;
if (remain > 0)
memcpy(buf, buf + used_bytes, remain);
}
if (used_bytes < 0)
break;
}
exit_free_get:
free(get);
exit_free_rem:
free(remote);
close(sock);
return (ret < 0) ? -1 : 1;
}
#ifdef HTTP_GET_APP
static void usage(void)
{
fprintf(stderr,
"USAGE: htmlget host [page]\n"
"\thost: the website hostname. ex: coding.debuntu.org\n"
"\tpage: the page to retrieve. ex: index.html, default: /\n");
}
static int noop_parser(void *context, char *buf, int bytes)
{
printf("%s", buf);
return bytes;
}
int main(int argc, char **argv)
{
char *host;
char *page;
if (argc == 1) {
usage();
exit(2);
}
host = argv[1];
if (argc > 2) {
page = argv[2];
} else {
page = PAGE;
}
parse_http_page(host, page, noop_parser, NULL);
return 0;
}
#endif