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
198 lines
4.1 KiB
C
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;
|
|
}
|