Skip to content

Instantly share code, notes, and snippets.

@aslatter
Created October 7, 2011 14:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aslatter/1270448 to your computer and use it in GitHub Desktop.
Save aslatter/1270448 to your computer and use it in GitHub Desktop.
// This flag has us build with windows sockets
// instead of cygwin sockets. Needs to be linked
// with ws2_32 as well.
// #define WINDOWS
#ifdef WINDOWS
#define WIN32_LEAN_AND_MEAN
#define NOGDI
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <strings.h>
#include <sys/types.h>
#ifndef WINDOWS
#include <sys/socket.h>
#include <netdb.h>
#endif
/* size of the socket receive buffer */
#define RECV_BUFF_LEN 8000
/* Print an error message to the user and quit. */
void error(char *msg);
/* Print an error related to address info construction
and quit. */
void addrError(char *msg, int errCode);
/* Print a windows error and quit. */
#ifdef WINDOWS
void winError(char *msg, int errCode);
#endif
/* Load/Cleanup Winsock */
void init_sockets();
void destroy_sockets();
/* returns true on success. */
int writef(int fd, size_t size, char *fmt, ...);
/* Exits on failure */
void parse_args(int argc, char** argv,
char** host_name, char** document, char** service);
int main(int argc, char** argv)
{
int ret_val;
char *host_name;
char *document;
char *service = "http";
parse_args(argc, argv, &host_name, &document, &service);
/* Setup socket */
init_sockets();
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) error("Error creating socket");
int sock_buff_size = RECV_BUFF_LEN;
ret_val = setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
(char*)&sock_buff_size, (int)sizeof(sock_buff_size));
if (ret_val != 0) error("Error setting socket options");
/* Set a linger of zero.
This can cause a harder close than turning off linger.
*/
struct linger linger_opts;
linger_opts.l_onoff = 1;
linger_opts.l_linger = 0;
ret_val = setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
(char*)&linger_opts, sizeof(linger_opts));
if (ret_val != 0) error("Error setting socket options");
// todo - set TCP_NODELAY to 1, on IPPROTO_TCP ?
/* Lookup host */
struct addrinfo *server;
ret_val = getaddrinfo(host_name, service, NULL, &server);
if (ret_val != 0)
addrError("Error constructing address info", ret_val);
/* Connect socket */
ret_val = connect(sockfd, server->ai_addr, server->ai_addrlen);
if (ret_val != 0) error("Error connecting socket");
/* Do an HTTP request */
writef(sockfd, 255, "GET %s HTTP/1.1\r\n", document);
writef(sockfd, 255, "Host: %s\r\n", host_name);
writef(sockfd, 255, "User-Agent: HappyBot\r\n");
//writef(sockfd, 255, "Range: bytes=100-5866155\r\n");
writef(sockfd, 255, "\r\n\r\n");
/* Print the first few bytes of response */
char buff[ RECV_BUFF_LEN ];
ret_val = recv(sockfd, buff, sizeof(buff), 0);
if(ret_val > 0)
{
printf("Read %d bytes:\n", ret_val);
fwrite(buff, sizeof(char), ret_val, stdout);
}
else
error("Unable to read from socket");
printf("\n\n");
raise(SIGKILL);
/*
closesocket(sockfd);
destroy_sockets();
return 0;
*/
}
void parse_args(int argc, char** argv,
char** host_name, char** document, char** service)
{
if(!(argc == 3 || argc == 4))
{
fprintf(stderr, "USAGE: %s HOST PATH [SERVICE]\n", argv[0]);
exit(1);
}
*host_name = argv[1];
*document = argv[2];
if (argc==4)
*service = argv[3];
}
int writef(int sock, size_t size, char *fmt, ...)
{
va_list ap;
int success = 0;
va_start(ap, fmt);
char buffer[ size ];
int real_size = vsnprintf(buffer, size, fmt, ap);
if (real_size <= size)
{
// also log to stdout
fwrite(buffer, sizeof(char), real_size, stdout);
ssize_t retval = 0;
size_t written = 0;
do
{
retval = send(sock, &buffer[written], real_size - written, 0);
if (retval > 0) written += retval;
} while (retval >= 0 && written < real_size);
if (retval >= 0) success = 1;
}
va_end(ap);
/* because I'm lazy */
if (!success) error("Error writing to socket");
return success;
}
void addrError(char *msg, int errCode)
{
#ifdef WINDOWS
error(msg); // WSAGetLastError works here
#else
fprintf(stdout, "%s: %s\n", msg, gai_strerror(errCode));
exit(1);
#endif
}
void error(char *msg)
{
#ifdef WINDOWS
int winErrCode = WSAGetLastError();
if(winErrCode)
winError(msg, winErrCode);
else
#endif
{
perror(msg);
exit(1);
}
}
#ifdef WINDOWS
void winError(char *msg, int errCode)
{
static char message[1024];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, errCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
message, 1024, NULL);
fprintf(stderr,"%s: %s\n", msg, message);
exit(1);
}
#endif
void init_sockets()
{
#ifdef WINDOWS
WSADATA wsaData;
int ret_val = WSAStartup(MAKEWORD(2,2), &wsaData);
if (ret_val != 0) winError("Error starting up Winsock", ret_val);
#endif
}
void destroy_sockets()
{
#ifdef WINDOWS
int ret_val = WSACleanup();
if (ret_val != 0) winError("Error shutting down Winsock", ret_val);
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment