1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
#include <signal.h>
#include <stdio.h>
#include <malloc.h>
#include <netdb.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include "iobroker.c"
#include "t-utils.h"
static iobroker_set *iobs;
static char *msg[] = {
"Welcome to the echo service!\n",
"test msg nr 2",
"random piece of string\nwith\nlots\nof\nnewlines\n\n\n\n\0",
"another totally random message\n",
"and this one's from emma. She's alright, really",
NULL,
};
static int echo_service(int fd, int events, void *arg)
{
char buf[1024];
int len;
len = read(fd, buf, sizeof(buf));
if (len < 0) {
perror("read");
iobroker_close(iobs, fd);
ok_int(iobroker_is_registered(iobs, fd), 0, "Closing must deregister");
return 0;
}
/* zero read means we're disconnected */
if (!len) {
iobroker_close(iobs, fd);
ok_int(iobroker_is_registered(iobs, fd), 0, "Closing must deregister");
return 0;
}
write(fd, buf, len);
return 0;
}
static int connected_handler(int fd, int events, void *arg)
{
int *counter = (int *)arg;
int i;
i = *counter;
if (events == IOBROKER_POLLIN) {
char buf[1024];
int len = read(fd, buf, sizeof(buf));
buf[len] = 0;
test(len == (int)strlen(msg[i]), "len match for message %d", i);
test(!memcmp(buf, msg[i], len), "data match for message %d", i);
}
i++;
if (i < 0 || i >= (int)ARRAY_SIZE(msg)) {
fprintf(stderr, "i = %d in connected_handler(). What's up with that?\n", i);
return 0;
}
if (!msg[i]) {
iobroker_close(iobs, fd);
return 0;
}
write(fd, msg[i], strlen(msg[i]));
*counter = i;
return 0;
}
static int listen_handler(int fd, int events, void *arg)
{
int sock;
struct sockaddr_in sain;
socklen_t addrlen;
if (!arg || arg != iobs) {
printf("Argument passing seems to fail spectacularly\n");
}
addrlen = sizeof(sain);
//printf("listen_handler(%d, %d, %p) called\n", fd, events, arg);
sock = accept(fd, (struct sockaddr *)&sain, &addrlen);
if (sock < 0) {
perror("accept");
return -1;
}
write(sock, msg[0], strlen(msg[0]));
iobroker_register(iobs, sock, iobs, echo_service);
ok_int(iobroker_is_registered(iobs, sock), 1, "is_registered must be true");
return 0;
}
void sighandler(int sig)
{
/* test failed */
t_fail("Caught signal %d", sig);
exit(t_end());
}
#define NUM_PROCS 500
static int proc_counter[NUM_PROCS];
static int conn_spam(struct sockaddr_in *sain)
{
int i;
#ifdef HAVE_SIGACTION
struct sigaction sig_action;
sig_action.sa_sigaction = NULL;
sig_action.sa_handler = SIG_IGN;
sigemptyset(&sig_action.sa_mask);
sig_action.sa_flags = 0;
sigaction(SIGPIPE, &sig_action, NULL);
sig_action.sa_handler = sighandler;
sigfillset(&sig_action.sa_mask);
sig_action.sa_flags = SA_NODEFER|SA_RESTART;
sigaction(SIGQUIT, &sig_action, NULL);
sigaction(SIGINT, &sig_action, NULL);
#else /* HAVE_SIGACTION */
signal(SIGALRM, sighandler);
signal(SIGINT, sighandler);
signal(SIGPIPE, SIG_IGN);
#endif /* HAVE_SIGACTION */
alarm(20);
for (i = 0; i < NUM_PROCS; i++) {
int fd, sockopt = 1;
fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
(void)setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
proc_counter[i] = 0;
iobroker_register(iobs, fd, (void *)&proc_counter[i], connected_handler);
if (connect(fd, (struct sockaddr *)sain, sizeof(*sain))) {
perror("connect");
}
iobroker_poll(iobs, -1);
}
return 0;
}
int main(int argc, char **argv)
{
int listen_fd, flags, sockopt = 1;
struct sockaddr_in sain;
int error;
const char *err_msg;
t_set_colors(0);
t_start("iobroker ipc test");
error = iobroker_get_max_fds(NULL);
ok_int(error, IOBROKER_ENOSET, "test errors when passing null");
err_msg = iobroker_strerror(error);
test(err_msg && !strcmp(err_msg, iobroker_errors[(~error) + 1].string), "iobroker_strerror() returns the right string");
iobs = iobroker_create();
error = iobroker_get_max_fds(iobs);
test(iobs && error >= 0, "max fd's for real iobroker set must be > 0");
listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
flags = fcntl(listen_fd, F_GETFD);
flags |= FD_CLOEXEC;
fcntl(listen_fd, F_SETFD, flags);
(void)setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
memset(&sain, 0, sizeof(sain));
sain.sin_port = ntohs(9123);
sain.sin_family = AF_INET;
bind(listen_fd, (struct sockaddr *)&sain, sizeof(sain));
listen(listen_fd, 128);
iobroker_register(iobs, listen_fd, iobs, listen_handler);
if (argc == 1)
conn_spam(&sain);
for (;;) {
iobroker_poll(iobs, -1);
if (iobroker_get_num_fds(iobs) <= 1) {
break;
}
}
iobroker_close(iobs, listen_fd);
iobroker_destroy(iobs, 0);
t_end();
return 0;
}
|