Permalink
Browse files

Allow connections over tcp sockets too (wait command)

Using general streams API for handling TCP/UNIX domain sockets etc.
Now phpdbg.path ini setting needs to be in form of unix:///path/to/phpdbg.sock
For Windows, there's now tcp://localhost:12000 for example.
  • Loading branch information...
1 parent 69565c5 commit 5b8b6e3df4819293dd94d9a7b56c88e3d2ac018b @bwoebi bwoebi committed Nov 4, 2014
Showing with 106 additions and 69 deletions.
  1. +13 −4 phpdbg.c
  2. +3 −2 phpdbg.h
  3. +3 −3 phpdbg_prompt.c
  4. +20 −25 phpdbg_rinit_hook.c
  5. +67 −35 phpdbg_wait.c
View
@@ -90,8 +90,8 @@ static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */
memset(pg->io, 0, sizeof(pg->io));
pg->frame.num = 0;
pg->sapi_name_ptr = NULL;
- pg->socket_fd = -1;
- pg->socket_server_fd = -1;
+ pg->socket_client_stream = NULL;
+ pg->socket_server_stream = NULL;
pg->req_id = 0;
pg->err_buf.active = 0;
@@ -614,8 +614,8 @@ static void php_sapi_phpdbg_register_vars(zval *track_vars_array TSRMLS_DC) /* {
static inline int php_sapi_phpdbg_ub_write(const char *message, unsigned int length TSRMLS_DC) /* {{{ */
{
- if (PHPDBG_G(socket_fd) != -1 && !(PHPDBG_G(flags) & PHPDBG_IS_INTERACTIVE)) {
- send(PHPDBG_G(socket_fd), message, length, 0);
+ if (PHPDBG_G(socket_client_stream) != NULL && !(PHPDBG_G(flags) & PHPDBG_IS_INTERACTIVE)) {
+ php_stream_write(PHPDBG_G(socket_client_stream), message, length);
}
return phpdbg_script(P_STDOUT, "%.*s", length, message);
} /* }}} */
@@ -1583,6 +1583,15 @@ int main(int argc, char **argv) /* {{{ */
}
#endif
+ if (PHPDBG_G(socket_client_stream)) {
+ php_stream_close(PHPDBG_G(socket_client_stream));
+ PHPDBG_G(socket_client_stream) = NULL;
+ }
+ if (PHPDBG_G(socket_server_stream)) {
+ php_stream_close(PHPDBG_G(socket_server_stream));
+ PHPDBG_G(socket_server_stream) = NULL;
+ }
+
if (cleaning <= 0) {
PHPDBG_G(flags) &= ~PHPDBG_IS_CLEANING;
cleaning = -1;
View
@@ -283,8 +283,9 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg)
char *socket_path; /* phpdbg.path ini setting */
char *sapi_name_ptr; /* store sapi name to free it if necessary to not leak memory */
- int socket_fd; /* file descriptor to socket (wait command) (-1 if unused) */
- int socket_server_fd; /* file descriptor to master socket (wait command) (-1 if unused) */
+ php_stream *socket_client_stream; /* client stream (wait command) (NULL if unused) */
+ php_stream *socket_server_stream; /* server stream (wait command) (NULL if unused) */
+
#ifdef PHP_WIN32
HANDLE sigio_watcher_thread; /* sigio watcher thread handle */
struct win32_sigio_watcher_data swd;
View
@@ -693,9 +693,9 @@ PHPDBG_COMMAND(run) /* {{{ */
}
} zend_end_try();
- if (PHPDBG_G(socket_fd) != -1) {
- close(PHPDBG_G(socket_fd));
- PHPDBG_G(socket_fd) = -1;
+ if (PHPDBG_G(socket_client_stream)) {
+ php_stream_close(PHPDBG_G(socket_client_stream));
+ PHPDBG_G(socket_client_stream) = NULL;
}
if (restore) {
View
@@ -18,7 +18,7 @@
#include "phpdbg_rinit_hook.h"
#include "php_ini.h"
-#include <errno.h>
+#include "ext/standard/file.h"
ZEND_DECLARE_MODULE_GLOBALS(phpdbg_webhelper);
@@ -52,43 +52,38 @@ static PHP_RINIT_FUNCTION(phpdbg_webhelper) /* {{{ */
return SUCCESS;
}
-#ifndef _WIN32
{
- struct sockaddr_un sock;
- int s = socket(AF_UNIX, SOCK_STREAM, 0);
- int len = strlen(PHPDBG_WG(path)) + sizeof(sock.sun_family);
- char buf[(1 << 8) + 1];
- int buflen;
- sock.sun_family = AF_UNIX;
- strcpy(sock.sun_path, PHPDBG_WG(path));
-
- if (connect(s, (struct sockaddr *)&sock, len) == -1) {
-/* zend_error(E_ERROR, "Unable to connect to UNIX domain socket at %s defined by phpdbg.path ini setting. Reason: %s", PHPDBG_WG(path), strerror(errno)); */
- free(sock.sun_path);
- close(s);
-
- return SUCCESS;
- }
+ char *host = PHPDBG_WG(path);
+ int host_len = strlen(host);
+ struct timeval tv;
+ php_stream *stream;
+ int err;
+ char *errstr = NULL;
char *msg = NULL;
char msglen[5] = {0};
- phpdbg_webdata_compress(&msg, (int *)msglen TSRMLS_CC);
- send(s, msglen, 4, 0);
- send(s, msg, *(int *) msglen, 0);
+ tv.tv_sec = 60;
+ tv.tv_usec = 0;
+
+ stream = php_stream_xport_create(host, host_len, REPORT_ERRORS, STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, NULL, &tv, NULL, &errstr, &err);
- while ((buflen = recv(s, buf, sizeof(buf) - 1, 0)) > 0) {
- php_write(buf, buflen TSRMLS_CC);
+ if (stream == NULL) {
+/* zend_error(E_ERROR, "Unable to connect to UNIX domain socket at %s defined by phpdbg.path ini setting. Reason: %s", PHPDBG_WG(path), strerror(errno)); */
+ return SUCCESS;
}
- close(s);
+ phpdbg_webdata_compress(&msg, (int *) msglen TSRMLS_CC);
- free(sock.sun_path);
+ php_stream_write(stream, msglen, 4);
+ php_stream_write(stream, msg, *(int *) msglen);
+
+ php_stream_passthru(stream);
+ php_stream_close(stream);
php_output_flush_all(TSRMLS_C);
zend_bailout();
}
-#endif
return SUCCESS;
} /* }}} */
View
@@ -369,55 +369,87 @@ void phpdbg_webdata_decompress(char *msg, int len TSRMLS_DC) {
PHPDBG_COMMAND(wait) /* {{{ */
{
- struct sockaddr_un local, remote;
- int rlen, sr, sl;
- unlink(PHPDBG_G(socket_path));
- if (PHPDBG_G(socket_server_fd) == -1) {
- int len;
- PHPDBG_G(socket_server_fd) = sl = socket(AF_UNIX, SOCK_STREAM, 0);
-
- local.sun_family = AF_UNIX;
- strcpy(local.sun_path, PHPDBG_G(socket_path));
- len = strlen(local.sun_path) + sizeof(local.sun_family);
- if (bind(sl, (struct sockaddr *)&local, len) == -1) {
- phpdbg_error("wait", "type=\"nosocket\" import=\"fail\"", "Unable to connect to UNIX domain socket at %s defined by phpdbg.path ini setting", PHPDBG_G(socket_path));
- return FAILURE;
+ char *errstr = NULL;
+ struct timeval tv;
+
+ tv.tv_sec = 60;
+ tv.tv_usec = 0;
+
+ if (PHPDBG_G(socket_server_stream) == NULL) {
+ int err = 0;
+#ifndef _WIN32
+ zend_bool is_unix = strlen(PHPDBG_G(socket_path)) > 7 && !memcmp("unix://", PHPDBG_G(socket_path), 7);
+
+ /* Try to avoid address already in use style errors on UNIX domain sockets */
+ if (is_unix) {
+ unlink(PHPDBG_G(socket_path) + 7);
}
+#endif
- chmod(PHPDBG_G(socket_path), 0666);
+ PHPDBG_G(socket_server_stream) = php_stream_xport_create(PHPDBG_G(socket_path), strlen(PHPDBG_G(socket_path)), REPORT_ERRORS, STREAM_XPORT_BIND | STREAM_XPORT_LISTEN | STREAM_XPORT_SERVER, NULL, &tv, NULL, &errstr, &err);
- listen(sl, 2);
- } else {
- sl = PHPDBG_G(socket_server_fd);
+ if (PHPDBG_G(socket_server_stream) == NULL) {
+ phpdbg_error("wait", "type=\"nosocket\" import=\"fail\" socket=\"%s\" reason=\"%s\"", "Unable to connect to %s defined by phpdbg.path ini setting (%s)", PHPDBG_G(socket_path), errstr == NULL ? errno ? strerror(errno) : "Unknown error" : errstr);
+
+ if (errstr) {
+ efree(errstr);
+ }
+
+ return SUCCESS;
+ }
+
+#ifndef _WIN32
+ if (is_unix) {
+ chmod(PHPDBG_G(socket_path) + 7, 0666);
+ }
+#endif
+ }
+
+ if (PHPDBG_G(socket_client_stream)) {
+ php_stream_close(PHPDBG_G(socket_client_stream));
+ PHPDBG_G(socket_client_stream) = NULL;
}
- rlen = sizeof(remote);
- sr = accept(sl, (struct sockaddr *) &remote, (socklen_t *) &rlen);
+ if (php_stream_xport_accept(PHPDBG_G(socket_server_stream), &PHPDBG_G(socket_client_stream), NULL, NULL, NULL, NULL, &tv, &errstr TSRMLS_CC) && PHPDBG_G(socket_client_stream)) {
+ phpdbg_error("wait", "type=\"nosocket\" import=\"fail\" socket=\"%s\" reason=\"%s\"", "Unable to connect to %s defined by phpdbg.path ini setting (%s)", PHPDBG_G(socket_path), errstr == NULL ? errno ? strerror(errno) : "Unknown error" : errstr);
+ } else {
+ char msglen[5], *data;
+ int rcvd = 4;
+
+ if (php_stream_read(PHPDBG_G(socket_client_stream), msglen, rcvd) != 4) {
+ goto read_error;
+ }
- char msglen[5];
- int recvd = 4;
+ rcvd = *(size_t *) msglen;
+ data = emalloc(rcvd);
- do {
- recvd -= recv(sr, &(msglen[4 - recvd]), recvd, 0);
- } while (recvd > 0);
+ do {
+ int oldrcvd = rcvd;
+ rcvd -= php_stream_read(PHPDBG_G(socket_client_stream), &(data[(*(int *) msglen) - rcvd]), rcvd);
- recvd = *(size_t *) msglen;
- char *data = emalloc(recvd);
+ if (oldrcvd == rcvd) {
+ efree(data);
+ goto read_error;
+ }
+ } while (rcvd > 0);
- do {
- recvd -= recv(sr, &(data[(*(int *) msglen) - recvd]), recvd, 0);
- } while (recvd > 0);
+ phpdbg_webdata_decompress(data, *(int *) msglen TSRMLS_CC);
- phpdbg_webdata_decompress(data, *(int *) msglen TSRMLS_CC);
+ efree(data);
- if (PHPDBG_G(socket_fd) != -1) {
- close(PHPDBG_G(socket_fd));
+ phpdbg_notice("wait", "import=\"success\"", "Successfully imported request data, stopped before executing");
}
- PHPDBG_G(socket_fd) = sr;
- efree(data);
+ if (0) {
+read_error:
+ php_stream_close(PHPDBG_G(socket_client_stream));
+ PHPDBG_G(socket_client_stream) = NULL;
+ phpdbg_error("wait", "type=\"nosocket\" import=\"fail\" socket=\"%s\" reason=\"%s\"", "Unable to read from %s (%s)", PHPDBG_G(socket_path), "Connection was aborted by client");
+ }
- phpdbg_notice("wait", "import=\"success\"", "Successfully imported request data, stopped before executing");
+ if (errstr) {
+ efree(errstr);
+ }
return SUCCESS;
} /* }}} */

0 comments on commit 5b8b6e3

Please sign in to comment.