aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS.src1
-rw-r--r--capture_opts.c6
-rw-r--r--capture_opts.h2
-rw-r--r--doc/README.extcap2
-rwxr-xr-xdoc/extcap_example.py32
-rw-r--r--extcap.c55
-rw-r--r--extcap.h8
-rw-r--r--extcap_spawn.c132
-rw-r--r--extcap_spawn.h2
-rw-r--r--ui/qt/interface_toolbar.cpp15
-rw-r--r--ui/qt/interface_toolbar.h2
-rw-r--r--ui/qt/interface_toolbar_reader.cpp170
-rw-r--r--ui/qt/interface_toolbar_reader.h26
-rw-r--r--ui/qt/main_window.cpp4
-rw-r--r--ui/qt/main_window_slots.cpp4
15 files changed, 323 insertions, 138 deletions
diff --git a/AUTHORS.src b/AUTHORS.src
index 172a1a3f40..6e8bd4f44f 100644
--- a/AUTHORS.src
+++ b/AUTHORS.src
@@ -3955,6 +3955,7 @@ James Lynch <lynch007[AT]gmail.com>
Chidambaram Arunachalam <carunach[AT]cisco.com>
João Valverde <joao.valverde[AT]tecnico.ulisboa.pt>
Benoît Canet <benoit[AT]scylladb.com>
+Håkon Øye Amundsen <haakon.amundsen[AT]nordicsemi.no>
Acknowledgements
------------
diff --git a/capture_opts.c b/capture_opts.c
index 0f7a88ee3f..4d63ba4d12 100644
--- a/capture_opts.c
+++ b/capture_opts.c
@@ -70,6 +70,8 @@ capture_opts_init(capture_options *capture_opts)
capture_opts->default_options.extcap_pid = INVALID_EXTCAP_PID;
#ifdef _WIN32
capture_opts->default_options.extcap_pipe_h = INVALID_HANDLE_VALUE;
+ capture_opts->default_options.extcap_control_in_h = INVALID_HANDLE_VALUE;
+ capture_opts->default_options.extcap_control_out_h = INVALID_HANDLE_VALUE;
#endif
capture_opts->default_options.extcap_control_in = NULL;
capture_opts->default_options.extcap_control_out = NULL;
@@ -718,6 +720,8 @@ capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg_str
interface_opts.extcap_userdata = NULL;
#ifdef _WIN32
interface_opts.extcap_pipe_h = INVALID_HANDLE_VALUE;
+ interface_opts.extcap_control_in_h = INVALID_HANDLE_VALUE;
+ interface_opts.extcap_control_out_h = INVALID_HANDLE_VALUE;
#endif
interface_opts.extcap_control_in = g_strdup(capture_opts->default_options.extcap_control_in);
interface_opts.extcap_control_out = g_strdup(capture_opts->default_options.extcap_control_out);
@@ -1234,6 +1238,8 @@ collect_ifaces(capture_options *capture_opts)
interface_opts.extcap_userdata = NULL;
#ifdef _WIN32
interface_opts.extcap_pipe_h = INVALID_HANDLE_VALUE;
+ interface_opts.extcap_control_in_h = INVALID_HANDLE_VALUE;
+ interface_opts.extcap_control_out_h = INVALID_HANDLE_VALUE;
#endif
interface_opts.extcap_control_in = NULL;
interface_opts.extcap_control_out = NULL;
diff --git a/capture_opts.h b/capture_opts.h
index 22d03c8472..311cc4ac97 100644
--- a/capture_opts.h
+++ b/capture_opts.h
@@ -238,6 +238,8 @@ typedef struct interface_options_tag {
guint extcap_child_watch;
#ifdef _WIN32
HANDLE extcap_pipe_h;
+ HANDLE extcap_control_in_h;
+ HANDLE extcap_control_out_h;
#endif
gchar *extcap_control_in;
gchar *extcap_control_out;
diff --git a/doc/README.extcap b/doc/README.extcap
index f1e27ce01c..3ce07aa161 100644
--- a/doc/README.extcap
+++ b/doc/README.extcap
@@ -356,7 +356,7 @@ Control packet:
The common sync pipe indication. This protocol uses the value 'T'.
Message Length:
- Payload length + 2 bytes for argument number and command.
+ Payload length + 2 bytes for control number and command.
Control Number:
Unique number to identify the control. This number also gives the order of
diff --git a/doc/extcap_example.py b/doc/extcap_example.py
index e984b374aa..9c14ddeae7 100755
--- a/doc/extcap_example.py
+++ b/doc/extcap_example.py
@@ -340,28 +340,22 @@ def extcap_capture(interface, fifo, control_in, control_out, in_delay, in_verify
message = in_message
verify = in_verify
counter = 1
-
- if not os.path.exists(fifo):
- print ( "Fifo does not exist, exiting!", file=sys.stderr )
- sys.exit(1)
-
fn_out = None
- if control_out != None:
- fn_out = open(control_out, 'wb', 0)
- control_write(fn_out, CTRL_ARG_LOGGER, CTRL_CMD_SET, "Log started at " + time.strftime("%c") + "\n")
+ with open(fifo, 'wb', 0 ) as fh:
+ fh.write (pcap_fake_header())
- if control_in != None:
- # Start reading thread
- thread = Thread(target = control_read_thread, args = (control_in, fn_out))
- thread.start()
+ if control_out != None:
+ fn_out = open(control_out, 'wb', 0)
+ control_write(fn_out, CTRL_ARG_LOGGER, CTRL_CMD_SET, "Log started at " + time.strftime("%c") + "\n")
+ if control_in != None:
+ # Start reading thread
+ thread = Thread(target = control_read_thread, args = (control_in, fn_out))
+ thread.start()
- if fn_out != None:
- control_write_defaults(fn_out)
-
- with open(fifo, 'wb', 0 ) as fh:
- fh.write (pcap_fake_header())
+ if fn_out != None:
+ control_write_defaults(fn_out)
while True:
if fn_out != None:
@@ -383,10 +377,6 @@ def extcap_capture(interface, fifo, control_in, control_out, in_delay, in_verify
fn_out.close()
def extcap_close_fifo(fifo):
- if not os.path.exists(fifo):
- print ( "Fifo does not exist!", file=sys.stderr )
- return
-
# This is apparently needed to workaround an issue on Windows/macOS
# where the message cannot be read. (really?)
fh = open(fifo, 'wb', 0 )
diff --git a/extcap.c b/extcap.c
index d025c9fe25..e88edc8dbc 100644
--- a/extcap.c
+++ b/extcap.c
@@ -1041,6 +1041,24 @@ void extcap_if_cleanup(capture_options *capture_opts, gchar **errormsg)
CloseHandle(interface_opts.extcap_pipe_h);
interface_opts.extcap_pipe_h = INVALID_HANDLE_VALUE;
}
+ if (interface_opts.extcap_control_in_h != INVALID_HANDLE_VALUE)
+ {
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
+ "Extcap [%s] - Closing control_in pipe", interface_opts.name);
+ FlushFileBuffers(interface_opts.extcap_control_in_h);
+ DisconnectNamedPipe(interface_opts.extcap_control_in_h);
+ CloseHandle(interface_opts.extcap_control_in_h);
+ interface_opts.extcap_control_in_h = INVALID_HANDLE_VALUE;
+ }
+ if (interface_opts.extcap_control_out_h != INVALID_HANDLE_VALUE)
+ {
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
+ "Extcap [%s] - Closing control_out pipe", interface_opts.name);
+ FlushFileBuffers(interface_opts.extcap_control_out_h);
+ DisconnectNamedPipe(interface_opts.extcap_control_out_h);
+ CloseHandle(interface_opts.extcap_control_out_h);
+ interface_opts.extcap_control_out_h = INVALID_HANDLE_VALUE;
+ }
#else
if (interface_opts.extcap_fifo != NULL && file_exists(interface_opts.extcap_fifo))
{
@@ -1355,14 +1373,20 @@ extcap_init_interfaces(capture_options *capture_opts)
if (extcap_has_toolbar(interface_opts.name))
{
extcap_create_pipe(interface_opts.name, &interface_opts.extcap_control_in,
- EXTCAP_CONTROL_IN_PREFIX);
+ EXTCAP_CONTROL_IN_PREFIX, FALSE);
+#ifdef _WIN32
+ interface_opts.extcap_control_in_h = pipe_h;
+#endif
extcap_create_pipe(interface_opts.name, &interface_opts.extcap_control_out,
- EXTCAP_CONTROL_OUT_PREFIX);
+ EXTCAP_CONTROL_OUT_PREFIX, FALSE);
+#ifdef _WIN32
+ interface_opts.extcap_control_out_h = pipe_h;
+#endif
}
/* create pipe for fifo */
if (!extcap_create_pipe(interface_opts.name, &interface_opts.extcap_fifo,
- EXTCAP_PIPE_PREFIX))
+ EXTCAP_PIPE_PREFIX, TRUE))
{
return FALSE;
}
@@ -1403,7 +1427,18 @@ extcap_init_interfaces(capture_options *capture_opts)
*/
if (pid != INVALID_EXTCAP_PID)
{
- extcap_wait_for_pipe(interface_opts.extcap_pipe_h, pid);
+ HANDLE pipe_handles[3];
+ int num_pipe_handles = 1;
+ pipe_handles[0] = interface_opts.extcap_pipe_h;
+
+ if (extcap_has_toolbar(interface_opts.name))
+ {
+ pipe_handles[1] = interface_opts.extcap_control_in_h;
+ pipe_handles[2] = interface_opts.extcap_control_out_h;
+ num_pipe_handles += 2;
+ }
+
+ extcap_wait_for_pipe(pipe_handles, num_pipe_handles, pid);
}
#endif
@@ -1416,15 +1451,14 @@ extcap_init_interfaces(capture_options *capture_opts)
return TRUE;
}
-gboolean extcap_create_pipe(const gchar *ifname, gchar **fifo, const gchar *pipe_prefix)
+gboolean extcap_create_pipe(const gchar *ifname, gchar **fifo, const gchar *pipe_prefix, gboolean byte_mode _U_)
{
#ifdef _WIN32
gchar timestr[ 14 + 1 ];
time_t current_time;
-
gchar *pipename = NULL;
-
SECURITY_ATTRIBUTES security;
+
/* create pipename */
current_time = time(NULL);
/*
@@ -1440,18 +1474,19 @@ gboolean extcap_create_pipe(const gchar *ifname, gchar **fifo, const gchar *pipe
security.bInheritHandle = TRUE;
security.lpSecurityDescriptor = NULL;
- /* create a namedPipe*/
+ /* create a namedPipe */
pipe_h = CreateNamedPipe(
utf_8to16(pipename),
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
- PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
- 5, 65536, 65536,
+ byte_mode ? PIPE_TYPE_BYTE : PIPE_TYPE_MESSAGE | byte_mode ? PIPE_READMODE_BYTE : PIPE_READMODE_MESSAGE | PIPE_WAIT,
+ 1, 65536, 65536,
300,
&security);
if (pipe_h == INVALID_HANDLE_VALUE)
{
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "\nError creating pipe => (%d)", GetLastError());
+ g_free (pipename);
return FALSE;
}
else
diff --git a/extcap.h b/extcap.h
index 2e6739fa00..013ccdb4fd 100644
--- a/extcap.h
+++ b/extcap.h
@@ -40,8 +40,8 @@
/* Prefix for the pipe interfaces */
#define EXTCAP_PIPE_PREFIX "wireshark_extcap"
-#define EXTCAP_CONTROL_IN_PREFIX "wireshark_control_in"
-#define EXTCAP_CONTROL_OUT_PREFIX "wireshark_control_out"
+#define EXTCAP_CONTROL_IN_PREFIX "wireshark_control_ext_to_ws"
+#define EXTCAP_CONTROL_OUT_PREFIX "wireshark_control_ws_to_ext"
#define EXTCAP_ARGUMENT_CONFIG "--extcap-config"
#define EXTCAP_ARGUMENT_LIST_INTERFACES "--extcap-interfaces"
@@ -143,11 +143,11 @@ gboolean
extcap_init_interfaces(capture_options * capture_opts);
gboolean
-extcap_create_pipe(const gchar *ifname, gchar **fifo, const gchar *pipe_prefix);
+extcap_create_pipe(const gchar *ifname, gchar **fifo, const gchar *pipe_prefix, gboolean byte_mode);
/* Clean up all if related stuff */
void
-extcap_if_cleanup(capture_options * capture_opts _U_, gchar ** errormsg);
+extcap_if_cleanup(capture_options * capture_opts, gchar ** errormsg);
struct preference *
extcap_pref_for_argument(const gchar *ifname, struct _extcap_arg * arg);
diff --git a/extcap_spawn.c b/extcap_spawn.c
index 8b9b5988bf..d88c3945d0 100644
--- a/extcap_spawn.c
+++ b/extcap_spawn.c
@@ -287,67 +287,117 @@ GPid extcap_spawn_async(extcap_userdata *userdata, GPtrArray *args)
}
#ifdef _WIN32
+
+typedef struct
+{
+ HANDLE pipeHandle;
+ OVERLAPPED ol;
+ BOOL pendingIO;
+} PIPEINTS;
+
gboolean
-extcap_wait_for_pipe(HANDLE pipe_h, HANDLE pid)
+extcap_wait_for_pipe(HANDLE * pipe_handles, int num_pipe_handles, HANDLE pid)
{
- DWORD dw;
- HANDLE handles[2];
- OVERLAPPED ov;
- gboolean success = FALSE;
- ov.Pointer = 0;
- ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- ConnectNamedPipe(pipe_h, &ov);
- handles[0] = ov.hEvent;
- handles[1] = pid;
-
- if (GetLastError() == ERROR_PIPE_CONNECTED)
+ PIPEINTS pipeinsts[3];
+ DWORD dw, cbRet;
+ HANDLE handles[4];
+ int error_code;
+ int num_waiting_to_connect = 0;
+ int num_handles = num_pipe_handles + 1; // PID handle is also added to list of handles.
+
+ if (num_pipe_handles == 0 || num_pipe_handles > 3)
{
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap connected to pipe");
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Invalid number of pipes given as argument.");
+ return FALSE;
}
- else
+
+ for (int i = 0; i < num_pipe_handles; ++i)
{
- dw = WaitForMultipleObjects(2, handles, FALSE, 30000);
- if (dw == WAIT_OBJECT_0)
+ pipeinsts[i].pipeHandle = pipe_handles[i];
+ pipeinsts[i].ol.Pointer = 0;
+ pipeinsts[i].ol.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ pipeinsts[i].pendingIO = FALSE;
+ handles[i] = pipeinsts[i].ol.hEvent;
+ BOOL connected = ConnectNamedPipe(pipeinsts[i].pipeHandle, &pipeinsts[i].ol);
+ if (connected)
+ {
+ error_code = GetLastError();
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe failed with %d \n.", error_code);
+ return FALSE;
+ }
+
+ switch (GetLastError())
{
- /* ConnectNamedPipe finished. */
- DWORD code;
+ case ERROR_IO_PENDING:
+ num_waiting_to_connect++;
+ pipeinsts[i].pendingIO = TRUE;
+ break;
- code = GetLastError();
- if (code == ERROR_IO_PENDING)
+ case ERROR_PIPE_CONNECTED:
+ if (SetEvent(pipeinsts[i].ol.hEvent))
{
- DWORD dummy;
- if (!GetOverlappedResult(ov.hEvent, &ov, &dummy, TRUE))
- {
- code = GetLastError();
- }
- else
- {
- code = ERROR_SUCCESS;
- success = TRUE;
- }
- }
+ break;
+ } // Fallthrough if this fails.
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe code: %d", code);
+ default:
+ error_code = GetLastError();
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe failed with %d \n.", error_code);
+ return FALSE;
}
- else if (dw == (WAIT_OBJECT_0 + 1))
+ }
+
+ // Store pid of extcap process so it can be monitored in case it fails before the pipes has connceted.
+ handles[num_pipe_handles] = pid;
+
+ while(num_waiting_to_connect > 0)
+ {
+ dw = WaitForMultipleObjects(num_handles, handles, FALSE, 30000);
+ int idx = dw - WAIT_OBJECT_0;
+ if (dw == WAIT_TIMEOUT)
{
- /* extcap process terminated. */
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap terminated without connecting to pipe.");
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap didn't connect to pipe within 30 seconds.");
+ return FALSE;
}
- else if (dw == WAIT_TIMEOUT)
+ // If index points to our handles array
+ else if (idx >= 0 && idx < num_handles)
{
- g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap didn't connect to pipe within 30 seconds.");
+ if (idx < num_pipe_handles) // Index of pipe handle
+ {
+ if (pipeinsts[idx].pendingIO)
+ {
+ BOOL success = GetOverlappedResult(
+ pipeinsts[idx].pipeHandle, // handle to pipe
+ &pipeinsts[idx].ol, // OVERLAPPED structure
+ &cbRet, // bytes transferred
+ FALSE); // do not wait
+
+ if (!success)
+ {
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Error %d \n.", GetLastError());
+ return FALSE;
+ }
+ else
+ {
+ pipeinsts[idx].pendingIO = FALSE;
+ num_waiting_to_connect--;
+ }
+ }
+ }
+ else // Index of PID
+ {
+ // Fail since index of 'pid' indicates that the pid of the extcap process has terminated.
+ g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap terminated without connecting to pipe.");
+ return FALSE;
+ }
}
else
{
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "WaitForMultipleObjects returned 0x%08X. Error %d", dw, GetLastError());
+ return FALSE;
}
}
- CloseHandle(ov.hEvent);
-
- return success;
+ return TRUE;
}
#endif
diff --git a/extcap_spawn.h b/extcap_spawn.h
index 16d8a97a58..858671865a 100644
--- a/extcap_spawn.h
+++ b/extcap_spawn.h
@@ -47,7 +47,7 @@ gboolean extcap_spawn_sync ( gchar * dirname, gchar * command, gint argc, gchar
GPid extcap_spawn_async ( extcap_userdata * userdata, GPtrArray * args );
#ifdef _WIN32
-gboolean extcap_wait_for_pipe(HANDLE pipe_h, HANDLE pid);
+gboolean extcap_wait_for_pipe(HANDLE * pipe_handles, int num_pipe_handles, HANDLE pid);
void win32_readfrompipe(HANDLE read_pipe, gint32 max_buffer, gchar * buffer);
#endif
diff --git a/ui/qt/interface_toolbar.cpp b/ui/qt/interface_toolbar.cpp
index b28fee9abe..ffddf28f50 100644
--- a/ui/qt/interface_toolbar.cpp
+++ b/ui/qt/interface_toolbar.cpp
@@ -710,7 +710,8 @@ void InterfaceToolbar::closeLog()
}
}
-void InterfaceToolbar::startReaderThread(QString ifname, QString control_in)
+
+void InterfaceToolbar::startReaderThread(QString ifname, void *control_in)
{
QThread *thread = new QThread;
InterfaceToolbarReader *reader = new InterfaceToolbarReader(ifname, control_in);
@@ -757,12 +758,14 @@ void InterfaceToolbar::startCapture(GArray *ifaces)
// Already have control channels for this interface
continue;
- // The reader thread will open control in channel
- startReaderThread(ifname, interface_opts.extcap_control_in);
-
// Open control out channel
+#ifdef _WIN32
+ startReaderThread(ifname, interface_opts.extcap_control_in_h);
+ interface_[ifname].out_fd = _open_osfhandle((intptr_t)interface_opts.extcap_control_out_h, O_APPEND | O_BINARY);
+#else
+ startReaderThread(ifname, interface_opts.extcap_control_in);
interface_[ifname].out_fd = ws_open(interface_opts.extcap_control_out, O_WRONLY | O_BINARY, 0);
-
+#endif
sendChangedValues(ifname);
controlSend(ifname, 0, commandControlInitialized);
}
@@ -800,7 +803,9 @@ void InterfaceToolbar::stopCapture()
if (interface_[ifname].out_fd != -1)
{
+#ifndef _WIN32
ws_close (interface_[ifname].out_fd);
+#endif
interface_[ifname].out_fd = -1;
}
diff --git a/ui/qt/interface_toolbar.h b/ui/qt/interface_toolbar.h
index cdbfb57906..404dc1ccdb 100644
--- a/ui/qt/interface_toolbar.h
+++ b/ui/qt/interface_toolbar.h
@@ -70,7 +70,7 @@ signals:
void closeReader();
private slots:
- void startReaderThread(QString ifname, QString control_in);
+ void startReaderThread(QString ifname, void *control_in);
void updateWidgets();
void onControlButtonPressed();
diff --git a/ui/qt/interface_toolbar_reader.cpp b/ui/qt/interface_toolbar_reader.cpp
index f4565fe6c3..99b15a47b3 100644
--- a/ui/qt/interface_toolbar_reader.cpp
+++ b/ui/qt/interface_toolbar_reader.cpp
@@ -39,37 +39,125 @@
const int header_size = 6;
-// To do:
-// - Add support for WIN32
+#ifdef _WIN32
+int InterfaceToolbarReader::async_pipe_read(void *data, int nbyte)
+{
+ BOOL success;
+ DWORD nof_bytes_read, last_err;
+ OVERLAPPED overlap;
+
+ overlap.Pointer = 0;
+ overlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (overlap.hEvent == NULL)
+ {
+ // CreateEvent failed with error code GetLastError()
+ return -1;
+ }
+
+ success = ReadFile(control_in_, data, nbyte, &nof_bytes_read, &overlap);
+
+ if (success && nof_bytes_read != 0)
+ {
+ // The read operation completed successfully.
+ return nof_bytes_read;
+ }
+
+ last_err = GetLastError();
+
+ if (!success && last_err == ERROR_IO_PENDING)
+ {
+ // The operation is still pending, wait for a signal.
+ DWORD wait = WaitForMultipleObjects(1, &overlap.hEvent, TRUE, INFINITE);
+
+ if (wait - WAIT_OBJECT_0 == 0)
+ {
+ // The wait operation has completed.
+ success = GetOverlappedResult(control_in_, &overlap, &nof_bytes_read, FALSE);
+
+ if (success && nof_bytes_read != 0)
+ {
+ // The get result operation completed successfully.
+ return nof_bytes_read;
+ }
+ }
+ }
+
+ // The pipe is closed or an unknown error occured.
+ return -1;
+}
+#endif
+
+int InterfaceToolbarReader::pipe_read(char *data, int nbyte)
+{
+ int total_len = 0;
+
+ while (total_len < nbyte)
+ {
+ char *data_ptr = data + total_len;
+ int data_len = nbyte - total_len;
+
+#ifdef _WIN32
+ int read_len = async_pipe_read(data_ptr, data_len);
+#else
+ int read_len = (int)ws_read(fd_in_, data_ptr, data_len);
+#endif
+ if (read_len == -1)
+ {
+ if (errno != EAGAIN)
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ total_len += read_len;
+ }
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
+ if (QThread::currentThread()->isInterruptionRequested())
+ {
+ return -1;
+ }
+#endif
+ }
+
+ return total_len;
+}
void InterfaceToolbarReader::loop()
{
-#ifndef _WIN32
- struct timeval timeout;
QByteArray header;
QByteArray payload;
+
+#ifndef _WIN32
+ struct timeval timeout;
fd_set readfds;
+ fd_in_ = ws_open(control_in_.toUtf8(), O_RDONLY | O_BINARY | O_NONBLOCK, 0);
- int fd = ws_open(control_in_.toUtf8(), O_RDONLY | O_BINARY | O_NONBLOCK, 0);
- if (fd == -1)
+ if (fd_in_ == -1)
{
emit finished();
return;
}
+#endif
+
+ header.resize(header_size);
forever
{
+#ifndef _WIN32
FD_ZERO(&readfds);
- FD_SET(fd, &readfds);
+ FD_SET(fd_in_, &readfds);
timeout.tv_sec = 2;
timeout.tv_usec = 0;
- int ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
+ int ret = select(fd_in_ + 1, &readfds, NULL, NULL, &timeout);
if (ret == -1)
{
break;
}
+
#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
if (QThread::currentThread()->isInterruptionRequested())
{
@@ -77,52 +165,40 @@ void InterfaceToolbarReader::loop()
}
#endif
- if (ret > 0 && FD_ISSET(fd, &readfds))
+ if (ret == 0 || !FD_ISSET(fd_in_, &readfds))
{
- header.resize(header_size);
- if (ws_read(fd, header.data(), header_size) != header_size)
- {
- break;
- }
+ continue;
+ }
+#endif
- unsigned char high_nibble = header[1] & 0xFF;
- unsigned char mid_nibble = header[2] & 0xFF;
- unsigned char low_nibble = header[3] & 0xFF;
- ssize_t payload_len = (ssize_t)((high_nibble << 16) + (mid_nibble << 8) + low_nibble) - 2;
+ // Read the header from the pipe.
+ if (pipe_read(header.data(), header_size) != header_size)
+ {
+ break;
+ }
- payload.resize((int)payload_len);
- if (payload_len > 0)
- {
- ssize_t total_len = 0;
- while (total_len < payload_len)
- {
- ssize_t read_len = ws_read(fd, payload.data() + total_len, payload_len - total_len);
- if (read_len == -1)
- {
- if (errno != EAGAIN)
- {
- break;
- }
- }
- else
- {
- total_len += read_len;
- }
- }
- if (total_len != payload_len)
- {
- break;
- }
- }
- if (header[0] == SP_TOOLBAR_CTRL)
- {
- emit received(ifname_, (unsigned char)header[4], (unsigned char)header[5], payload);
- }
+ unsigned char high_nibble = header[1] & 0xFF;
+ unsigned char mid_nibble = header[2] & 0xFF;
+ unsigned char low_nibble = header[3] & 0xFF;
+ int payload_len = (int)((high_nibble << 16) + (mid_nibble << 8) + low_nibble) - 2;
+
+ payload.resize(payload_len);
+ // Read the payload from the pipe.
+ if (pipe_read(payload.data(), payload_len) != payload_len)
+ {
+ break;
+ }
+
+ if (header[0] == SP_TOOLBAR_CTRL)
+ {
+ emit received(ifname_, (unsigned char)header[4], (unsigned char)header[5], payload);
}
}
- ws_close(fd);
+#ifndef _WIN32
+ ws_close(fd_in_);
#endif
+
emit finished();
}
diff --git a/ui/qt/interface_toolbar_reader.h b/ui/qt/interface_toolbar_reader.h
index 1b34db4fb0..75fc7cbea9 100644
--- a/ui/qt/interface_toolbar_reader.h
+++ b/ui/qt/interface_toolbar_reader.h
@@ -25,6 +25,10 @@
#include <QObject>
#include <QByteArray>
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
namespace Ui {
class InterfaceToolbarReader;
}
@@ -34,8 +38,16 @@ class InterfaceToolbarReader : public QObject
Q_OBJECT
public:
- InterfaceToolbarReader(QString ifname, QString control_in, QObject *parent = 0) :
- QObject(parent), ifname_(ifname), control_in_(control_in) {}
+ InterfaceToolbarReader(QString ifname, void *control_in, QObject *parent = 0) :
+ QObject(parent), ifname_(ifname)
+ {
+#ifdef _WIN32
+ control_in_ = (HANDLE)control_in;
+#else
+ control_in_ = (char *)control_in;
+ fd_in_ = -1;
+#endif
+ }
public slots:
void loop();
@@ -45,8 +57,18 @@ signals:
void finished();
private:
+#ifdef _WIN32
+ int async_pipe_read(void *data, int nbyte);
+#endif
+ int pipe_read(char *data, int nbyte);
+
QString ifname_;
+#ifdef _WIN32
+ HANDLE control_in_;
+#else
QString control_in_;
+ int fd_in_;
+#endif
};
#endif // INTERFACE_TOOLBAR_READER_H
diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp
index 653ff4cf4f..cd5a2ca53e 100644
--- a/ui/qt/main_window.cpp
+++ b/ui/qt/main_window.cpp
@@ -714,14 +714,12 @@ MainWindow::MainWindow(QWidget *parent) :
#endif
plugin_if_register_gui_cb(PLUGIN_IF_REMOVE_TOOLBAR, plugin_if_mainwindow_update_toolbars);
-#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) && !defined(_WIN32)
+#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
// Register Interface Toolbar callbacks
//
// Qt version must be 5.2 or higher because the use of
// QThread::requestInterruption() in interface_toolbar.cpp and
// QThread::isInterruptionRequested() in interface_toolbar_reader.cpp
- //
- // The toolbar in/out control pipes are not supported on WIN32 yet.
iface_toolbar_register_cb(mainwindow_add_toolbar, mainwindow_remove_toolbar);
#endif
diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp
index 0c6dcbf710..c6d30c9a6a 100644
--- a/ui/qt/main_window_slots.cpp
+++ b/ui/qt/main_window_slots.cpp
@@ -657,7 +657,7 @@ void MainWindow::queuedFilterAction(QString action_filter, FilterAction::Action
// Capture callbacks
-void MainWindow::captureCapturePrepared(capture_session *session) {
+void MainWindow::captureCapturePrepared(capture_session *) {
#ifdef HAVE_LIBPCAP
setTitlebarForCaptureInProgress();
@@ -665,7 +665,7 @@ void MainWindow::captureCapturePrepared(capture_session *session) {
/* Disable menu items that make no sense if you're currently running
a capture. */
- setForCaptureInProgress(true, session->capture_opts->ifaces);
+ setForCaptureInProgress(true);
// set_capture_if_dialog_for_capture_in_progress(TRUE);
// /* Don't set up main window for a capture file. */