diff options
author | Håkon Øye Amundsen <haakon.amundsen@nordicsemi.no> | 2017-08-25 11:28:34 +0200 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2017-08-28 08:13:04 +0000 |
commit | 78d30d687b17cff81395013a5bf55f21232fac95 (patch) | |
tree | 719532fa2ff96f0b560617744ae0499f472b46a2 | |
parent | af90b3190673f547a64e1c86748819acb3c322e4 (diff) | |
download | wireshark-78d30d687b17cff81395013a5bf55f21232fac95.tar.gz wireshark-78d30d687b17cff81395013a5bf55f21232fac95.tar.bz2 wireshark-78d30d687b17cff81395013a5bf55f21232fac95.zip |
extcap: Interface Toolbar support on Windows
Add support for extcap control pipes on Windows.
Improved read loop in InterfaceToolbarReader.
Delay opening control pipes until extcap has opened the fifo pipe.
Make extcap_example.py work on Windows.
Bug: 13833
Change-Id: I4b47d25452637759b8a3be53be48eee5365bc0e4
Reviewed-on: https://code.wireshark.org/review/23211
Petri-Dish: Stig Bjørlykke <stig@bjorlykke.org>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
(cherry picked from commit 018f6bff18785a1c3971a1ccfe3b1b5243d4d154)
Reviewed-on: https://code.wireshark.org/review/23250
-rw-r--r-- | AUTHORS.src | 1 | ||||
-rw-r--r-- | capture_opts.c | 6 | ||||
-rw-r--r-- | capture_opts.h | 2 | ||||
-rw-r--r-- | doc/README.extcap | 2 | ||||
-rwxr-xr-x | doc/extcap_example.py | 32 | ||||
-rw-r--r-- | extcap.c | 55 | ||||
-rw-r--r-- | extcap.h | 8 | ||||
-rw-r--r-- | extcap_spawn.c | 132 | ||||
-rw-r--r-- | extcap_spawn.h | 2 | ||||
-rw-r--r-- | ui/qt/interface_toolbar.cpp | 15 | ||||
-rw-r--r-- | ui/qt/interface_toolbar.h | 2 | ||||
-rw-r--r-- | ui/qt/interface_toolbar_reader.cpp | 170 | ||||
-rw-r--r-- | ui/qt/interface_toolbar_reader.h | 26 | ||||
-rw-r--r-- | ui/qt/main_window.cpp | 4 | ||||
-rw-r--r-- | ui/qt/main_window_slots.cpp | 4 |
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 f72b886216..1276154daa 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; @@ -709,6 +711,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); @@ -1194,6 +1198,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 49b087e7e7..7b16e09a06 100644 --- a/capture_opts.h +++ b/capture_opts.h @@ -232,6 +232,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 ) @@ -1040,6 +1040,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)) { @@ -1364,14 +1382,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; } @@ -1412,7 +1436,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 @@ -1425,15 +1460,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); /* @@ -1449,18 +1483,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 @@ -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 fd63c3dec6..3f1538578e 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 6aa5243b33..2f64d3eb5d 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -700,14 +700,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 ac9fc777ac..553b118a38 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -655,7 +655,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(); @@ -663,7 +663,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. */ |