wireshark/ui/qt/interface_toolbar_reader.cpp

195 lines
4.2 KiB
C++

/* interface_toolbar_reader.cpp
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <errno.h>
#include "interface_toolbar_reader.h"
#include "sync_pipe.h"
#include "wsutil/file_util.h"
#include <QThread>
const int header_size = 6;
#ifdef _WIN32
int InterfaceToolbarReader::async_pipe_read(void *data, int nbyte)
{
BOOL success;
DWORD nof_bytes_read;
OVERLAPPED overlap;
int bytes_read = -1;
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.
bytes_read = nof_bytes_read;
}
else if (!success && GetLastError() == ERROR_IO_PENDING)
{
// The operation is still pending, wait for a signal.
if (WaitForSingleObject(overlap.hEvent, INFINITE) == WAIT_OBJECT_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.
bytes_read = nof_bytes_read;
}
}
}
CloseHandle(overlap.hEvent);
return bytes_read;
}
#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 (QThread::currentThread()->isInterruptionRequested())
{
return -1;
}
}
return total_len;
}
void InterfaceToolbarReader::loop()
{
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);
if (fd_in_ == -1)
{
emit finished();
return;
}
#endif
header.resize(header_size);
forever
{
#ifndef _WIN32
FD_ZERO(&readfds);
FD_SET(fd_in_, &readfds);
timeout.tv_sec = 2;
timeout.tv_usec = 0;
int ret = select(fd_in_ + 1, &readfds, NULL, NULL, &timeout);
if (ret == -1)
{
break;
}
if (QThread::currentThread()->isInterruptionRequested())
{
break;
}
if (ret == 0 || !FD_ISSET(fd_in_, &readfds))
{
continue;
}
#endif
// Read the header from the pipe.
if (pipe_read(header.data(), header_size) != header_size)
{
break;
}
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);
}
}
#ifndef _WIN32
ws_close(fd_in_);
#endif
emit finished();
}
/*
* Editor modelines
*
* Local Variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* ex: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/