genode/repos/libports/src/test/lwip/http_srv_connect/main.c
Norman Feske ca971bbfd8 Move repositories to 'repos/' subdirectory
This patch changes the top-level directory layout as a preparatory
step for improving the tools for managing 3rd-party source codes.
The rationale is described in the issue referenced below.

Issue #1082
2014-05-14 16:08:00 +02:00

198 lines
4.1 KiB
C

/*
* \brief Simple http_srv client
* \author Josef Soentgen
* \date 2012-8-30
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
/* prototypes for net.c functions */
extern int dial(struct addrinfo*);
extern struct addrinfo *lookup(const char*, const char*, const char*);
/* pthread error handling */
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
/* send request, currently hardcoded and works with httpsrv test only */
const char req[] = "GET /";
/* thread arguments */
struct args {
struct addrinfo* ai;
int flags;
int count;
int verbose;
};
/* receive flag */
enum { F_NONE, F_RECV };
/* pthread start function */
void *
run(void *arg)
{
char buf[1 << 20]; /* 1 MiB should be enough */
struct args *ap = (struct args *) arg;
int count = ap->count;
int flags = ap->flags;
int verbose = ap->verbose;
int i, s, nbytes, sum_nbytes;
for (i = 0; i < count; i++) {
s = dial(ap->ai); /* create socket and connect */
if (s == -1)
break;
/* only send/receive if flag is set { */
if (flags & F_RECV) {
/* first send request and second get header */
write(s, req, sizeof(req));
nbytes = read(s, buf, sizeof (buf));
/* get data */
sum_nbytes = 0;
#if UGLY_MEASURE_TIME
struct timeval start, end;
gettimeofday(&start, NULL);
#endif
do {
/**
* override buffer because we don't care about
* the actual data.
*/
nbytes = read(s, buf, sizeof (buf));
sum_nbytes += nbytes;
} while (nbytes > 0 && nbytes != -1);
if (nbytes == -1)
perror("read");
#if UGLY_MEASURE_TIME
gettimeofday(&end, NULL);
int sec = end.tv_sec - start.tv_sec;
int usec = end.tv_usec - start.tv_usec;
if (usec < 0) {
usec += 1000000;
sec--;
}
printf("time: %d ms\n",
((sec) * 1000) + ((usec) / 1000));
#endif
if (verbose)
printf("bytes read: %d\n", sum_nbytes);
}
/* } */
close(s);
}
/* XXX s == -1 handling */
return NULL;
}
int
main(int argc, char *argv[])
{
struct args a;
struct addrinfo *ai;
const char *proto = "tcp", *host, *port;
int i, err, verbose = 0, flags = F_NONE, count = 1, threads = 1;
pthread_t *thread;
if (argc < 3) {
fprintf(stderr, "usage: %s [-vr] [-c count] [-t threads] "
"[-p protocol] <host> <port>\n", argv[0]);
exit(1);
}
/* argument parsing { */
while ((i = getopt(argc, argv, "c:p:t:rv")) != -1) {
switch (i) {
case 'c': count = atoi(optarg); break;
/**
* valid values are only 'tcp' and 'udp'
*/
case 'p': proto = optarg; break;
case 't': threads = atoi(optarg); break;
/**
* If receive is specified we will read from the socket,
* just connect to the host otherwise.
*/
case 'r': flags |= F_RECV; break;
case 'v': verbose = 1; break;
default: break;
}
}
if ((argc - optind) != 2) {
fprintf(stderr, "missing host and/or port\n");
exit(1);
}
host = argv[optind++];
port = argv[optind];
/* } */
/* main { */
thread = (pthread_t *) calloc(threads, sizeof (pthread_t));
if (thread == NULL) {
perror("calloc");
exit(-1);
}
/* get addrinfo once and use it for all threads */
ai = lookup(proto, host, port);
if (ai == NULL) {
exit(-1);
}
/* fill thread argument structure */
a.ai = ai;
a.count = count / threads; /* XXX check if -c > -t */
a.flags = flags;
a.verbose = verbose;
printf("connect to '%s!%s!%s' roughly %d times, %d per thread\n",
proto, host, port, count, a.count);
for (i = 0; i < threads; i++) {
err = pthread_create(&thread[i], NULL, run, (void*)&a);
if (err != 0)
handle_error_en(err, "pthread_create");
}
for (i = 0; i < threads; i++) {
err = pthread_join(thread[i], NULL);
if (err != 0)
handle_error_en(err, "pthread_create");
}
freeaddrinfo(ai);
free(thread);
/* } */
return 0;
}