#define _GNU_SOURCE
#include <errno.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <time.h>
#include <arpa/inet.h>
#include <stdarg.h>
#include <Conn.h>
/* Global variables */
static unsigned short debug = 1;
static FILE *Logf = NULL;
static char *log_file = "c.log";
static int port = 9000;
static unsigned int answers = 0;
struct priv
{
unsigned int dummy;
};
static void Log(unsigned short level, char *format, ...)
{
va_list ap;
if (level > debug)
return;
va_start(ap, format);
vfprintf(Logf, format, ap);
va_end(ap);
}
static void c_connected(struct Conn *C)
{
struct priv *p;
Log(4, "%s(A connection was estabilished on slot %d)\n",
__FUNCTION__, C->slot);
C->private = malloc(sizeof(struct priv));
if (C->private == NULL) {
Log(0, "cannot alloc memory!\n");
exit(1);
}
p = (struct priv *) C->private;
p->dummy = 0;
}
static void c_close(struct Conn *C)
{
Log(5, "%s(Slot %d will close)\n",
__FUNCTION__, C->slot);
free(C->private);
}
static void c_data(struct Conn *C)
{
struct priv *p;
char *dump;
if (debug >= 8) {
dump = Conn_dump(C->ibuf + C->ibuf_head, C->ibuf_tail - C->ibuf_head);
Log(8, "data: recv: %s\n", dump);
free(dump);
}
p = (struct priv *) C->private;
p->dummy = 1;
answers++;
Conn_close(C);
Conn_eatall(C);
}
static void c_error(struct Conn *C)
{
Log(0, "%s Slot=%d C=%p [%s]\n",
__FUNCTION__, C ? C->slot : -1, (void *) C, Conn_strerror());
}
int main(void)
{
char *stat;
int i, ret;
struct timeval start, end;
unsigned int elap;
unsigned int ipv4conns = 10000, ipv6conns = 0;
struct Conn *C4, *C6;
Logf = fopen(log_file, "a+");
if (!Logf) {
fprintf(stderr, "Cannot open log file [%s] [%s]\n",
log_file, strerror(errno));
return 1;
}
if (debug > 0)
setlinebuf(Logf);
Log(0, "Starting...\n");
Log(0, "\tPort=%d\n", port);
Log(0, "\tLogFile=%s Debug=%d\n", log_file, debug);
Conn_debug(Logf, debug);
ret = Conn_init(0);
if (ret == -1) {
Log(0, "%s", Conn_strerror());
return 1;
}
Conn_connected_cb = c_connected;
Conn_data_cb = c_data;
Conn_close_cb = c_close;
Conn_error_cb = c_error;
gettimeofday(&start, NULL);
answers = 0;
/* ipv4 */
for (i = 0; i < ipv4conns; i++) {
C4 = Conn_connect(PF_INET, SOCK_STREAM, "82.79.23.14", port);
if (C4 == NULL) {
Log(0, "Error calling Conn_connect [%s]!\n",
Conn_strerror());
return 1;
}
}
/* ipv6 */
for (i = 0; i < ipv6conns; i++) {
C6 = Conn_connect(PF_INET6, SOCK_STREAM, "::1", port);
if (C6 == NULL) {
Log(0, "Error calling Conn_connect6 [%s]!\n",
Conn_strerror());
return 1;
}
}
while (1) {
ret = Conn_poll(1000);
if (ret == -1) {
Log(0, "Error in poll [%s]!\n",
Conn_strerror());
break;
}
if (ret == 0) {
Log(0, "Finish work!\n");
break;
}
if (debug >= 9) {
stat = Conn_status(0);
Log(9, "%s\n", stat);
free(stat);
}
if (answers % 10 == 0)
printf(".");
if (answers == ipv4conns + ipv6conns)
break;
}
gettimeofday(&end, NULL);
elap = 1000000 * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec;
Log(0, "Finish in %ld.%06ld. ipv4conns=%d. ipv6conns=%d. Total=%d. answers=%d"
" Conns per sec = %d\n",
elap / 1000000, elap % 1000000,
ipv4conns, ipv6conns, ipv4conns + ipv6conns,
answers, (ipv4conns + ipv6conns) / (elap / 1000000 + 1));
return 0;
}