diff --git a/AUTHORS.src b/AUTHORS.src index 172a1a3f40..6e8bd4f44f 100644 --- a/AUTHORS.src +++ b/AUTHORS.src @@ -3955,6 +3955,7 @@ James Lynch Chidambaram Arunachalam João Valverde Benoît Canet +Håkon Øye Amundsen 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,29 +340,23 @@ 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") - - - 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 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) + while True: if fn_out != None: log = "Received packet #" + str(counter) + "\n" @@ -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 -gboolean -extcap_wait_for_pipe(HANDLE pipe_h, HANDLE pid) + +typedef struct { - DWORD dw; - HANDLE handles[2]; - OVERLAPPED ov; - gboolean success = FALSE; - ov.Pointer = 0; - ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + HANDLE pipeHandle; + OVERLAPPED ol; + BOOL pendingIO; +} PIPEINTS; - ConnectNamedPipe(pipe_h, &ov); - handles[0] = ov.hEvent; - handles[1] = pid; +gboolean +extcap_wait_for_pipe(HANDLE * pipe_handles, int num_pipe_handles, HANDLE pid) +{ + 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 (GetLastError() == ERROR_PIPE_CONNECTED) + 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) { - /* ConnectNamedPipe finished. */ - DWORD code; + error_code = GetLastError(); + g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe failed with %d \n.", error_code); + return FALSE; + } - code = GetLastError(); - if (code == ERROR_IO_PENDING) + switch (GetLastError()) + { + case ERROR_IO_PENDING: + num_waiting_to_connect++; + pipeinsts[i].pendingIO = TRUE; + break; + + 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)) - { - /* extcap process terminated. */ - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap terminated without connecting to pipe."); - } - else if (dw == WAIT_TIMEOUT) + } + + // 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) { g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap didn't connect to pipe within 30 seconds."); + return FALSE; + } + // If index points to our handles array + else if (idx >= 0 && idx < num_handles) + { + 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; - fd_set readfds; - int fd = ws_open(control_in_.toUtf8(), O_RDONLY | O_BINARY | O_NONBLOCK, 0); - if (fd == -1) +#ifndef _WIN32 + struct timeval timeout; + fd_set readfds; + fd_in_ = ws_open(control_in_.toUtf8(), O_RDONLY | O_BINARY | O_NONBLOCK, 0); + + 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 #include +#ifdef _WIN32 +#include +#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. */