From 6dd85029b826d58a826f562f04f8046997be436a Mon Sep 17 00:00:00 2001 From: gumartinm Date: Sun, 29 Jan 2012 06:04:56 +0100 Subject: [PATCH] New modifications in Java TCP fork --- JavaFork/Daemon/Makefile | 2 +- JavaFork/Daemon/javafork.c | 111 ++++++++++++--------- JavaFork/Daemon/javafork.h | 4 +- .../src/main/java/de/fork/java/RemoteForkMain.java | 4 +- .../src/main/java/de/fork/java/TCPForkDaemon.java | 6 -- 5 files changed, 68 insertions(+), 59 deletions(-) diff --git a/JavaFork/Daemon/Makefile b/JavaFork/Daemon/Makefile index 7c28c45..d785678 100644 --- a/JavaFork/Daemon/Makefile +++ b/JavaFork/Daemon/Makefile @@ -1,7 +1,7 @@ all: javafork javafork: javafork.c javafork.h - gcc -Wall -g -o javafork javafork.c -lpthread + gcc -Wall -g -o javafork javafork.c -lpthread -D_GNU_SOURCE clean: rm -f javafork diff --git a/JavaFork/Daemon/javafork.c b/JavaFork/Daemon/javafork.c index fd1d03a..c92cd38 100644 --- a/JavaFork/Daemon/javafork.c +++ b/JavaFork/Daemon/javafork.c @@ -215,7 +215,7 @@ int daemonize(const char *pname, int facility, int option) return -1; } - if((fd = TEMP_FAILURE_RETRY(open( "/dev/null", O_RDWR, 0))) == -1) { + if ((fd = TEMP_FAILURE_RETRY(open( "/dev/null", O_RDWR, 0))) == -1) { closeSafely(fd); return -1; } @@ -237,8 +237,8 @@ int daemonize(const char *pname, int facility, int option) void *serverThread (void * arg) { int socket = -1; /*Open socket by the Java client*/ - struct timeval ptime; /*Variable used by the select function, timeout control*/ - int nLeft; /*Control parameter used while receiving data from the client*/ + long timeout, utimeout; /*Timeout for reading data from client: secs and usecs respectively*/ + int len; /*Control parameter used while receiving data from the client*/ char buffer[1025]; /*This buffer is intended to store the data received from the client*/ char *command = NULL; /*The command sent by the client, to be executed by this process*/ uint32_t *commandLength = NULL; /*Store the command length*/ @@ -265,6 +265,11 @@ void *serverThread (void * arg) /* */ /************************************************************************************************************/ + /*Wait max 2 seconds for data coming from client, otherwise exits with error.*/ + timeout = 2; + utimeout = 0; + + /*COMMAND LENGTH*/ /*First of all we receive the command size as a Java integer (4 bytes primitive type)*/ @@ -274,15 +279,10 @@ void *serverThread (void * arg) } bzero(buffer, sizeof(buffer)); - nLeft = sizeof(uint32_t); - /*Wait max 2 seconds for data coming from client, otherwise exits with error.*/ - ptime.tv_sec=2; - ptime.tv_usec=0; - if (receive_from_socket (socket, buffer, &nLeft, &ptime) < 0) - goto err; + len = sizeof(uint32_t); - if (nLeft < 0) - syslog (LOG_INFO, "command length excessive data received, expected: 4, received: %d", (-nLeft + sizeof(uint32_t)) ); + if (receive_from_socket (socket, buffer, len, timeout, utimeout) < 0) + goto err; /*Retrieve integer (4 bytes) from buffer*/ memcpy (commandLength, buffer, sizeof(uint32_t)); @@ -290,6 +290,7 @@ void *serverThread (void * arg) *commandLength = be32toh (*commandLength); + /*COMMAND*/ /*Reserving commandLength + 1 because of the string end character*/ @@ -299,21 +300,20 @@ void *serverThread (void * arg) } bzero(command, ((*commandLength) + 1)); - nLeft = *commandLength; + len = *commandLength; /*Wait max 2 seconds for data coming from client, otherwise exits with error.*/ - ptime.tv_sec=2; - ptime.tv_usec=0; - if (receive_from_socket (socket, command, &nLeft, &ptime) < 0) + if (receive_from_socket (socket, command, len, timeout, utimeout) < 0) goto err; - if (nLeft < 0) - syslog (LOG_INFO, "execessive command length, expected: %d, received: %d", *commandLength, (-nLeft + *commandLength)); + /*RESULTS*/ pre_fork_system(socket, command); + + /*CLOSE CONNECTION AND FINISH*/ err: @@ -324,6 +324,8 @@ err: pthread_exit(0); } + + int required_sock_options (int socket) { int optval, flags; @@ -335,7 +337,7 @@ int required_sock_options (int socket) return -1; } - if(TEMP_FAILURE_RETRY(fcntl(socket, F_SETFL, O_NONBLOCK|flags)) < 0){ + if (TEMP_FAILURE_RETRY(fcntl(socket, F_SETFL, O_NONBLOCK|flags)) < 0){ syslog (LOG_ERR, "set socket status flags failed: %m"); return -1; } @@ -343,14 +345,14 @@ int required_sock_options (int socket) /*Portable programs should not rely on inheritance or noninheritance of file status flags and */ /*always explicitly set all required flags*/ optval = 1; - if(setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) { + if (setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) { syslog (LOG_ERR, "setsockopt SO_REUSEADDR failed: %m"); return -1; } /*Enable keepalive for this socket*/ optval = 1; - if(setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) < 0) { + if (setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) < 0) { syslog (LOG_ERR, "setsockopt SO_KEEPALIVE failed: %m"); return -1; } @@ -359,51 +361,64 @@ int required_sock_options (int socket) /* apparently it just works while the handshake phase. See: */ /* http://stackoverflow.com/questions/4345415/socket-detect-connection-is-lost */ /* I have to implement an echo/ping messages protocol (application layer) */ - /* In the meanwhile this application should just be used in the localhost interface :( */ return 0; } -int timeout (int fd, long timeout) + +int readable_timeout (int fd, long timeout, long utimeout) { - struct timeval ptime; - fd_set fd_read; + struct timeval ptime; /*Timeout, secs and usecs*/ + fd_set fd_read; /*Values for select function.*/ ptime.tv_sec = timeout; - ptime.tv_usec = 0; - for (;;) { - - } + ptime.tv_usec = utimeout; + FD_ZERO(&fd_read); + FD_SET(fd, &fd_read); + + return TEMP_FAILURE_RETRY(select(fd+1, &fd_read, NULL, NULL, &ptime)); } -int receive_from_socket (int socket, char *store, int *nLeft, struct timeval *ptime) + + +int receive_from_socket (int socket, char *data, int len, long timeout, long utimeout) { int nData, iPos; /*Control variables.*/ int ret; /*Store return value from select.*/ - fd_set fd_read; /*Values for select function.*/ nData = iPos = 0; - do { - FD_ZERO(&fd_read); - FD_SET(socket, &fd_read); - ret = select(socket+1, &fd_read, NULL, NULL, ptime); - if(ret == 0) { - syslog(LOG_INFO, "receiving timeout error"); - return -1; - } - if(ret == -1) { - syslog(LOG_ERR, "receiving select error: %m"); - return -1; - } - if((nData = recv(socket, &store[iPos], *nLeft, 0)) <= 0) { - syslog (LOG_ERR, "read TCP socket failed: %m"); - return -1; - } - *nLeft -= nData; + ret = readable_timeout(socket, timeout, utimeout); + + if (ret == 0) { + syslog(LOG_INFO, "receiving timeout error"); + return -1; + } else if (ret == -1) { + syslog(LOG_ERR, "receiving error: %m"); + return -1; + } + + nData = TEMP_FAILURE_RETRY(recv(socket, &data[iPos], len, 0)); + + if (nData < 0) { + if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) { + syslog (LOG_ERR, "read TCP socket failed: %m"); + return -1; + } else { + /*see spurious readiness man select(2) BUGS section*/ + nData = 0; + syslog (LOG_INFO, "read TCP socket spurious readiness"); + } + } else if (nData == 0) { + /*if nData is 0, client closed connection but we wanted to receive more data, this is an error */ + syslog (LOG_ERR, "expected more data from client"); + return -1; + } + + len -= nData; iPos += nData; - } while (*nLeft > 0); + } while (len > 0); return 0; } diff --git a/JavaFork/Daemon/javafork.h b/JavaFork/Daemon/javafork.h index d8fbf14..3264e51 100644 --- a/JavaFork/Daemon/javafork.h +++ b/JavaFork/Daemon/javafork.h @@ -9,7 +9,6 @@ - /**************************************************************************************** * This method is used by pthread_create * * * @@ -74,4 +73,5 @@ void sigint_handler(); int required_sock_options (int socket); -int receive_from_socket (int socket, char *store, int *Left, struct timeval *ptime); +int receive_from_socket (int socket, char *data, int len, long timeout, long utimeout); +int readable_timeout (int fd, long timeout, long utimeout); diff --git a/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/RemoteForkMain.java b/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/RemoteForkMain.java index ac0a312..5b9c57d 100644 --- a/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/RemoteForkMain.java +++ b/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/RemoteForkMain.java @@ -22,12 +22,12 @@ public class RemoteForkMain { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final PrintStream stdout = new PrintStream(baos); - final String command = "ls -lah ~/.ssh; ls -lah * bbbb aaa"; + final String command = "ls -lah ~/Desktop; ls -lah * bbbb aaa"; final ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); final PrintStream stderr = new PrintStream(baos2); int result; - result = LauncherProcesses.exec(command,stdout, stderr, "gumartinm.name", 5193); + result = LauncherProcesses.exec(command,stdout, stderr, "127.0.0.1", 5193); System.out.println(result); System.out.println("Stdout: " + baos.toString()); System.out.println("Stderr: " + baos2.toString()); diff --git a/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/TCPForkDaemon.java b/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/TCPForkDaemon.java index 89141c5..c9da0cb 100644 --- a/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/TCPForkDaemon.java +++ b/JavaFork/JavaExample/javafork-example/src/main/java/de/fork/java/TCPForkDaemon.java @@ -144,12 +144,6 @@ public class TCPForkDaemon { inputSource.setEncoding("UTF-8"); parser.setStream(socket.getInputStream()); - DataInputStream receiveData = new DataInputStream(socket.getInputStream()); - - - // 2. ACK - int ack = receiveData.readInt(); - // 4. SERVER CLOSED CONNECTION } finally { -- 2.1.4