Clean up; deal with tedious error handling etc.
Still needs work; command line stuff for specifying a non-default port,
and a flag to say 'exit when # connections falls to zero.'
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1278 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/auxprogs/valgrind-listener.c b/auxprogs/valgrind-listener.c
index 15dc8e6..f4917a6 100644
--- a/auxprogs/valgrind-listener.c
+++ b/auxprogs/valgrind-listener.c
@@ -40,27 +40,62 @@
#include <stdio.h>
#include <unistd.h> /* close */
#include <string.h>
-#include <assert.h>
#include <sys/poll.h>
#include <time.h>
#include <fcntl.h>
#include <stdlib.h>
+/* For VG_CLO_DEFAULT_LOGPORT and VG_EMAIL_ADDR. */
+#include "vg_include.h"
+
+
/*---------------------------------------------------------------*/
-#define SUCCESS 0
-#define ERROR 1
+/* The maximum allowable number concurrent connections. */
+#define M_CONNECTIONS 50
-#define END_LINE '\n'
-#define SERVER_PORT 1500
-#define MAX_CONNS 50
+
+/*---------------------------------------------------------------*/
+
+__attribute__ ((noreturn))
+static void panic ( Char* str )
+{
+ fprintf(stderr,
+ "\nvalgrind-listener: the "
+ "`impossible' happened:\n %s\n", str);
+ fprintf(stderr,
+ "Please report this bug to: %s\n\n", VG_EMAIL_ADDR);
+ exit(1);
+}
+
+__attribute__ ((noreturn))
+static void my_assert_fail ( Char* expr, Char* file, Int line, Char* fn )
+{
+ fprintf(stderr,
+ "\nvalgrind-listener: %s:%d (%s): Assertion `%s' failed.\n",
+ file, line, fn, expr );
+ fprintf(stderr,
+ "Please report this bug to: %s\n\n", VG_EMAIL_ADDR);
+ exit(1);
+}
+
+#undef assert
+#undef VG__STRING
+
+#define VG__STRING(__str) #__str
+#define assert(expr) \
+ ((void) ((expr) ? 0 : \
+ (my_assert_fail (VG__STRING(expr), \
+ __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__), 0)))
+
/*---------------------------------------------------------------*/
/* holds the fds for connections; zero if slot not in use. */
int conn_count = 0;
-int conn_fd[MAX_CONNS];
-struct pollfd conn_pollfd[MAX_CONNS];
+int conn_fd[M_CONNECTIONS];
+struct pollfd conn_pollfd[M_CONNECTIONS];
void set_nonblocking ( int sd )
@@ -70,7 +105,7 @@
res = fcntl(sd, F_SETFL, res | O_NONBLOCK);
if (res != 0) {
perror("fcntl failed");
- exit(ERROR);
+ panic("set_nonblocking");
}
}
@@ -81,7 +116,7 @@
res = fcntl(sd, F_SETFL, res & ~O_NONBLOCK);
if (res != 0) {
perror("fcntl failed");
- exit(ERROR);
+ panic("set_blocking");
}
}
@@ -90,11 +125,11 @@
{
int i;
for (i = 0; i < nbuf; i++) {
- if (buf[i] == '\n') {
- fprintf(stdout, "\n(%d) ", conn_count);
- } else {
- fwrite(&buf[i], 1, 1, stdout);
- }
+ if (buf[i] == '\n') {
+ fprintf(stdout, "\n(%d) ", conn_count);
+ } else {
+ fwrite(&buf[i], 1, 1, stdout);
+ }
}
fflush(stdout);
}
@@ -120,145 +155,142 @@
void snooze ( void )
{
- struct timespec req;
- req.tv_sec = 0;
- req.tv_nsec = 200 * 1000 * 1000;
- nanosleep(&req,NULL);
+ struct timespec req;
+ req.tv_sec = 0;
+ req.tv_nsec = 200 * 1000 * 1000;
+ nanosleep(&req,NULL);
}
-/* function readline */
-int read_line();
+int main (int argc, char** argv)
+{
+ int i, j, k, res;
+ int main_sd, newSd, client_len;
-int main (int argc, char *argv[]) {
- int i, j, k, res;
- int main_sd, newSd, cliLen;
+ struct sockaddr_in client_addr, server_addr;
- struct sockaddr_in cliAddr, servAddr;
+ conn_count = 0;
+ for (i = 0; i < M_CONNECTIONS; i++)
+ conn_fd[i] = 0;
- conn_count = 0;
- for (i = 0; i < MAX_CONNS; i++)
- conn_fd[i] = 0;
-
- /* create socket */
- main_sd = socket(AF_INET, SOCK_STREAM, 0);
+ /* create socket */
+ main_sd = socket(AF_INET, SOCK_STREAM, 0);
if (main_sd < 0) {
- perror("cannot open socket ");
- return ERROR;
- }
+ perror("cannot open socket ");
+ panic("main -- create socket");
+ }
- /* bind server port */
- servAddr.sin_family = AF_INET;
- servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servAddr.sin_port = htons(SERVER_PORT);
+ /* bind server port */
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ server_addr.sin_port = htons(VG_CLO_DEFAULT_LOGPORT);
- if(bind(main_sd, (struct sockaddr *) &servAddr, sizeof(servAddr))<0) {
- perror("cannot bind port ");
- return ERROR;
- }
+ if (bind(main_sd, (struct sockaddr *) &server_addr,
+ sizeof(server_addr) ) < 0) {
+ perror("cannot bind port ");
+ panic("main -- bind port");
+ }
- res = listen(main_sd,MAX_CONNS);
- if (res != 0) {
- perror("listen failed ");
- return ERROR;
- }
+ res = listen(main_sd,M_CONNECTIONS);
+ if (res != 0) {
+ perror("listen failed ");
+ panic("main -- listen");
+ }
- while(1) {
+ while(1) {
- snooze();
+ snooze();
- /* enquire, using poll, whether there is any activity available on
- the main socket descriptor. If so, someone is trying to
- connect; get the fd and add it to our table thereof. */
- { struct pollfd ufd;
- while (1) {
- ufd.fd = main_sd;
- ufd.events = POLLIN;
- ufd.revents = 0;
- res = poll(&ufd, 1, 0);
- if (res == 0) break;
+ /* enquire, using poll, whether there is any activity available on
+ the main socket descriptor. If so, someone is trying to
+ connect; get the fd and add it to our table thereof. */
+ { struct pollfd ufd;
+ while (1) {
+ ufd.fd = main_sd;
+ ufd.events = POLLIN;
+ ufd.revents = 0;
+ res = poll(&ufd, 1, 0);
+ if (res == 0) break;
- /* ok, we have someone waiting to connect. Get the sd. */
- cliLen = sizeof(cliAddr);
- newSd = accept(main_sd, (struct sockaddr *) &cliAddr, &cliLen);
- if(newSd<0) {
- perror("cannot accept connection ");
- return ERROR;
+ /* ok, we have someone waiting to connect. Get the sd. */
+ client_len = sizeof(client_addr);
+ newSd = accept(main_sd, (struct sockaddr *) &client_addr,
+ &client_len);
+ if (newSd < 0) {
+ perror("cannot accept connection ");
+ panic("main -- accept connection");
+ }
+
+ /* find a place to put it. */
+ assert(newSd > 0);
+ for (i = 0; i < M_CONNECTIONS; i++)
+ if (conn_fd[i] == 0)
+ break;
+
+ if (i >= M_CONNECTIONS) {
+ fprintf(stderr, "Too many concurrent connections. "
+ "Increase M_CONNECTIONS and recompile.\n");
+ panic("main -- too many concurrent connections");
+ }
+
+ conn_fd[i] = newSd;
+ conn_count++;
+ printf("\n(%d) -------------------- CONNECT "
+ "--------------------\n(%d)\n(%d) ",
+ conn_count, conn_count, conn_count);
+ fflush(stdout);
+ } /* while (1) */
+ }
+
+ /* We've processed all new connect requests. Listen for changes
+ to the current set of fds. */
+ j = 0;
+ for (i = 0; i < M_CONNECTIONS; i++) {
+ if (conn_fd[i] == 0)
+ continue;
+ conn_pollfd[j].fd = conn_fd[i];
+ conn_pollfd[j].events = POLLIN /* | POLLHUP | POLLNVAL */;
+ conn_pollfd[j].revents = 0;
+ j++;
+ }
+
+ res = poll(conn_pollfd, j, 0 /* return immediately. */ );
+ if (res < 0) {
+ perror("poll(main) failed");
+ panic("poll(main) failed");
+ }
+
+ /* nothing happened. go round again. */
+ if (res == 0) {
+ continue;
+ }
+
+ /* inspect the fds. */
+ for (i = 0; i < j; i++) {
+
+ if (conn_pollfd[i].revents & POLLIN) {
+ /* data is available on this fd */
+ res = read_from_sd(conn_pollfd[i].fd);
+
+ if (res == 0) {
+ /* the connection has been closed. */
+ /* this fd has been closed or otherwise gone bad; forget
+ about it. */
+ for (k = 0; k < M_CONNECTIONS; k++)
+ if (conn_fd[k] == conn_pollfd[i].fd)
+ break;
+ assert(k < M_CONNECTIONS);
+ conn_fd[k] = 0;
+ conn_count--;
+ printf("\n(%d) ------------------- DISCONNECT "
+ "-------------------\n(%d)\n(%d) ",
+ conn_count, conn_count, conn_count);
+ fflush(stdout);
+ }
}
- /* find a place to put it. */
- assert(newSd > 0);
- for (i = 0; i < MAX_CONNS; i++)
- if (conn_fd[i] == 0)
- break;
-
- if (i >= MAX_CONNS) {
- printf("too many concurrent connections\n");
- return ERROR;
- }
- conn_fd[i] = newSd;
- conn_count++;
- printf("\n(%d) -------------------- CONNECT "
- "--------------------\n(%d)\n(%d) ",
- conn_count, conn_count, conn_count);
- fflush(stdout);
- }
- }
-
-
- /* We've processed all new connect requests. Listen for changes
- to the current set of fds. */
- j = 0;
- for (i = 0; i < MAX_CONNS; i++) {
- if (conn_fd[i] == 0)
- continue;
- conn_pollfd[j].fd = conn_fd[i];
- conn_pollfd[j].events = POLLIN | POLLHUP | POLLNVAL;
- conn_pollfd[j].revents = 0;
- j++;
- }
-
- res = poll(conn_pollfd, j, 0 /* return immediately. */ );
-
- if (res < 0) {
- perror("poll(main) failed");
- return ERROR;
- }
-
- /* nothing happened. go round again. */
- if (res == 0) {
- continue;
- }
-
- /* inspect the fds. */
- for (i = 0; i < j; i++) {
-
- if ((conn_pollfd[i].revents & POLLHUP)
- || (conn_pollfd[i].revents & POLLNVAL)) {
- /* this fd has been closed or otherwise gone bad; forget about
- it. */
- closed:
- for (k = 0; k < MAX_CONNS; k++)
- if (conn_fd[k] == conn_pollfd[i].fd) break;
- assert(k < MAX_CONNS);
- conn_fd[k] = 0;
- conn_count--;
- printf("\n(%d) ------------------- DISCONNECT "
- "-------------------\n(%d)\n(%d) ",
- conn_count, conn_count, conn_count);
- fflush(stdout);
- }
- else
- if (conn_pollfd[i].revents & POLLIN) {
- /* data is available on this fd */
- res = read_from_sd(conn_pollfd[i].fd);
- if (res == 0) goto closed;
- }
-
- } /* for (i = 0; i < j; i++) */
-
-
-
+ } /* for (i = 0; i < j; i++) */
+
} /* while (1) */
}