Files
pip/libs/main/io_devices/piethernet.h
2026-03-12 14:46:57 +03:00

707 lines
33 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! \~\file piethernet.h
//! \~\ingroup IO
//! \~\brief
//! \~english Ethernet-backed UDP and TCP device
//! \~russian Устройство UDP и TCP поверх Ethernet
/*
PIP - Platform Independent Primitives
Ethernet, UDP/TCP Broadcast/Multicast
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIETHERNET_H
#define PIETHERNET_H
#include "piiodevice.h"
#include "pinetworkaddress.h"
#ifdef ANDROID
struct
#else
class
#endif
sockaddr;
//! \~\ingroup IO
//! \~\brief
//! \~english %PIIODevice implementation for UDP sockets, TCP clients and TCP servers.
//! \~russian Реализация %PIIODevice для UDP-сокетов, TCP-клиентов и TCP-серверов.
class PIP_EXPORT PIEthernet: public PIIODevice {
PIIODEVICE(PIEthernet, "eth");
friend class PIPeer;
public:
//! \~english Constructs a UDP device with an empty read address.
//! \~russian Создает UDP-устройство с пустым адресом чтения.
explicit PIEthernet();
//! \~english Operating mode of %PIEthernet.
//! \~russian Режим работы %PIEthernet.
enum Type {
UDP /** \~english UDP datagram socket \~russian UDP-сокет датаграмм */,
TCP_Client /** \~english TCP client socket \~russian TCP-клиент */,
TCP_Server /** \~english TCP server socket \~russian TCP-сервер */
};
//! \~english Extra socket parameters for %PIEthernet.
//! \~russian Дополнительные параметры сокета %PIEthernet.
enum Parameters {
ReuseAddress = 0x1 /** \~english Allow rebinding an already bound address; enabled by default \~russian Разрешает повторную привязку
уже занятого адреса; включено по умолчанию */
,
Broadcast = 0x2 /** \~english Enable broadcast sending; disabled by default \~russian Включает отправку broadcast-пакетов; выключено
по умолчанию */
,
SeparateSockets = 0x4 /** \~english Use separate sockets for receiving and sending instead of a single one; disabled by default
\~russian Использует отдельные сокеты для приема и передачи вместо одного общего; выключено по умолчанию */
,
MulticastLoop = 0x8 /** \~english Receive multicast packets sent by the same host; enabled by default \~russian Разрешает получать
multicast-пакеты от того же хоста; включено по умолчанию */
,
KeepConnection = 0x10 /** \~english Reconnect TCP connection automatically after disconnect; enabled by default \~russian
Автоматически переподключает TCP-соединение после разрыва; включено по умолчанию */
,
DisonnectOnTimeout = 0x20 /** \~english Disconnect TCP connection when read timeout expires; disabled by default \~russian Разрывает
TCP-соединение при истечении таймаута чтения; выключено по умолчанию */
,
NoDelay = 0x40 /** \~english Enable the TCP no-delay option; disabled by default \~russian Включает опцию TCP no-delay; выключено по
умолчанию */
};
//! \~english Deprecated alias for \a PINetworkAddress.
//! \~russian Устаревший псевдоним для \a PINetworkAddress.
typedef ::PINetworkAddress Address DEPRECATEDM("use PINetworkAddress instead");
//! \~english Constructs a device with mode "type", read address "ip_port" and socket "params".
//! \~russian Создает устройство с режимом "type", адресом чтения "ip_port" и параметрами сокета "params".
explicit PIEthernet(Type type,
const PIString & ip_port = PIString(),
const PIFlags<Parameters> params = PIEthernet::ReuseAddress | PIEthernet::MulticastLoop |
PIEthernet::KeepConnection);
//! \~english Destroys the ethernet device.
//! \~russian Уничтожает ethernet-устройство.
virtual ~PIEthernet();
//! \~english Sets the read address from IP and port.
//! \~russian Устанавливает адрес чтения по IP и порту.
void setReadAddress(const PIString & ip, int port) {
addr_r.set(ip, port);
setPath(addr_r.toString());
}
//! \~english Sets the read address from string "i.i.i.i:p".
//! \~russian Устанавливает адрес чтения из строки "i.i.i.i:p".
void setReadAddress(const PIString & ip_port) {
addr_r.set(ip_port);
setPath(addr_r.toString());
}
//! \~english Sets the read address from \a PINetworkAddress.
//! \~russian Устанавливает адрес чтения из \a PINetworkAddress.
void setReadAddress(const PINetworkAddress & addr) {
addr_r = addr;
setPath(addr_r.toString());
}
//! \~english Sets only the read IP.
//! \~russian Устанавливает только IP-адрес чтения.
void setReadIP(const PIString & ip) {
addr_r.setIP(ip);
setPath(addr_r.toString());
}
//! \~english Sets only the read port.
//! \~russian Устанавливает только порт чтения.
void setReadPort(int port) {
addr_r.setPort(port);
setPath(addr_r.toString());
}
//! \~english Sets the send address from IP and port.
//! \~russian Устанавливает адрес отправки по IP и порту.
void setSendAddress(const PIString & ip, int port) { addr_s.set(ip, port); }
//! \~english Sets the send address from string "i.i.i.i:p".
//! \~russian Устанавливает адрес отправки из строки "i.i.i.i:p".
void setSendAddress(const PIString & ip_port) { addr_s.set(ip_port); }
//! \~english Sets the send address from \a PINetworkAddress.
//! \~russian Устанавливает адрес отправки из \a PINetworkAddress.
void setSendAddress(const PINetworkAddress & addr) { addr_s = addr; }
//! \~english Sets only the send IP.
//! \~russian Устанавливает только IP-адрес отправки.
void setSendIP(const PIString & ip) { addr_s.setIP(ip); }
//! \~english Sets only the send port.
//! \~russian Устанавливает только порт отправки.
void setSendPort(int port) { addr_s.setPort(port); }
//! \~english Returns the current read address.
//! \~russian Возвращает текущий адрес чтения.
PINetworkAddress readAddress() const { return addr_r; }
//! \~english Returns the current read IP.
//! \~russian Возвращает текущий IP-адрес чтения.
PIString readIP() const { return addr_r.ipString(); }
//! \~english Returns the current read port.
//! \~russian Возвращает текущий порт чтения.
int readPort() const { return addr_r.port(); }
//! \~english Returns the current send address.
//! \~russian Возвращает текущий адрес отправки.
PINetworkAddress sendAddress() const { return addr_s; }
//! \~english Returns the current send IP.
//! \~russian Возвращает текущий IP-адрес отправки.
PIString sendIP() const { return addr_s.ipString(); }
//! \~english Returns the current send port.
//! \~russian Возвращает текущий порт отправки.
int sendPort() const { return addr_s.port(); }
//! \~english Returns the source address of the last received UDP packet.
//! \~russian Возвращает адрес источника последнего принятого UDP-пакета.
PINetworkAddress lastReadAddress() const { return addr_lr; }
//! \~english Returns the IP of the last received UDP packet.
//! \~russian Возвращает IP-адрес последнего принятого UDP-пакета.
PIString lastReadIP() const { return addr_lr.ipString(); }
//! \~english Returns the port of the last received UDP packet.
//! \~russian Возвращает порт последнего принятого UDP-пакета.
int lastReadPort() const { return addr_lr.port(); }
//! \~english Replaces all socket parameters with "parameters_".
//! \~russian Полностью заменяет параметры сокета на "parameters_".
//! \~english Some parameters may require reopening the device to take full effect.
//! \~russian Для полного применения некоторых параметров может потребоваться переоткрытие устройства.
void setParameters(PIFlags<PIEthernet::Parameters> parameters_) {
params = parameters_;
applyParameters();
}
//! \~english Sets socket parameter "parameter" to state "on".
//! \~russian Устанавливает параметр сокета "parameter" в состояние "on".
//! \~english Some parameters may require reopening the device to take full effect.
//! \~russian Для полного применения некоторых параметров может потребоваться переоткрытие устройства.
void setParameter(PIEthernet::Parameters parameter, bool on = true) {
params.setFlag(parameter, on);
applyParameters();
}
//! \~english Returns whether parameter "parameter" is enabled.
//! \~russian Возвращает, включен ли параметр "parameter".
bool isParameterSet(PIEthernet::Parameters parameter) const { return params[parameter]; }
//! \~english Returns current socket parameters.
//! \~russian Возвращает текущие параметры сокета.
PIFlags<PIEthernet::Parameters> parameters() const { return params; }
//! \~english Returns the current ethernet mode.
//! \~russian Возвращает текущий режим ethernet-устройства.
Type type() const { return eth_type; }
//! \~english Returns the configured read timeout.
//! \~russian Возвращает настроенный таймаут чтения.
PISystemTime readTimeout() const { return property("readTimeout").toSystemTime(); }
//! \~english Returns the configured write timeout.
//! \~russian Возвращает настроенный таймаут записи.
PISystemTime writeTimeout() const { return property("writeTimeout").toSystemTime(); }
//! \~english Sets the read timeout.
//! \~russian Устанавливает таймаут чтения.
void setReadTimeout(PISystemTime tm);
//! \~english Sets the write timeout.
//! \~russian Устанавливает таймаут записи.
void setWriteTimeout(PISystemTime tm);
//! \~english Sets the socket receive buffer size in bytes.
//! \~russian Устанавливает размер приемного буфера сокета в байтах.
void setReadBufferSize(int bytes);
//! \~english Sets the socket send buffer size in bytes.
//! \~russian Устанавливает размер буфера передачи сокета в байтах.
void setWriteBufferSize(int bytes);
//! \~english Returns the IP packet TTL.
//! \~russian Возвращает TTL IP-пакетов.
int TTL() const { return property("TTL").toInt(); }
//! \~english Returns the multicast TTL.
//! \~russian Возвращает TTL multicast-пакетов.
int multicastTTL() const { return property("MulticastTTL").toInt(); }
//! \~english Sets the IP packet TTL, default is 64.
//! \~russian Устанавливает TTL IP-пакетов, по умолчанию 64.
void setTTL(int ttl) { setProperty("TTL", ttl); }
//! \~english Sets the multicast TTL, default is 1.
//! \~russian Устанавливает TTL multicast-пакетов, по умолчанию 1.
void setMulticastTTL(int ttl) { setProperty("MulticastTTL", ttl); }
//! \~english Joins multicast group "group". Use only with \a UDP.
//! \~russian Подключается к multicast-группе "group". Используйте только с \a UDP.
bool joinMulticastGroup(const PIString & group);
//! \~english Leaves multicast group "group". Use only with \a UDP.
//! \~russian Покидает multicast-группу "group". Используйте только с \a UDP.
bool leaveMulticastGroup(const PIString & group);
//! \~english Returns joined multicast groups. Use only with \a UDP.
//! \~russian Возвращает список подключенных multicast-групп. Используйте только с \a UDP.
const PIStringList & multicastGroups() const { return mcast_groups; }
//! \~english Connects to the TCP server at \a readAddress().
//! \~russian Подключается к TCP-серверу по адресу \a readAddress().
//! \~\details
//! \~english If "threaded" is true, connection is queued and completed from subsequent \a read() or \a write() calls.
//! \~russian Если "threaded" равно true, подключение ставится в очередь и завершается из последующих вызовов \a read() или \a write().
bool connect(bool threaded = true);
//! \~english Connects to the TCP server at "ip":"port".
//! \~russian Подключается к TCP-серверу по адресу "ip":"port".
bool connect(const PIString & ip, int port, bool threaded = true) {
setPath(ip + PIStringAscii(":") + PIString::fromNumber(port));
return connect(threaded);
}
//! \~english Connects to the TCP server at "ip_port".
//! \~russian Подключается к TCP-серверу по адресу "ip_port".
bool connect(const PIString & ip_port, bool threaded = true) {
setPath(ip_port);
return connect(threaded);
}
//! \~english Connects to the TCP server at "addr". Use only for TCP_Client
//! \~russian Подключается к TCP-серверу по адресу "addr". Только для TCP_Client
bool connect(const PINetworkAddress & addr, bool threaded = true) {
setPath(addr.toString());
return connect(threaded);
}
//! \~english Returns whether the TCP client is connected. Use only for TCP_Client
//! \~russian Возвращает, подключен ли TCP-клиент. Только для TCP_Client
bool isConnected() const { return connected_; }
//! \~english Returns whether the TCP client is currently connecting. Use only for TCP_Client
//! \~russian Возвращает, выполняется ли сейчас подключение TCP-клиента. Только для TCP_Client
bool isConnecting() const { return connecting_; }
//! \~english Starts listen for incoming TCP connections on address \a readAddress(). Use only for TCP_Server
//! \~russian Начинает прослушивание входящих TCP подключений на адресе \a readAddress(). Только для TCP_Server
bool listen(bool threaded = false);
//! \~english Starts listen for incoming TCP connections on address "ip":"port". Use only for TCP_Server
//! \~russian Начинает прослушивание входящих TCP подключений на адресе "ip":"port". Только для TCP_Server
bool listen(const PIString & ip, int port, bool threaded = false) { return listen(PINetworkAddress(ip, port), threaded); }
//! \~english Starts listen for incoming TCP connections on address "ip_port". Use only for TCP_Server
//! \~russian Начинает прослушивание входящих TCP подключений на адресе "ip_port". Только для TCP_Server
bool listen(const PIString & ip_port, bool threaded = false) { return listen(PINetworkAddress(ip_port), threaded); }
//! \~english Starts listen for incoming TCP connections on address "addr". Use only for TCP_Server
//! \~russian Начинает прослушивание входящих TCP подключений на адресе "addr". Только для TCP_Server
bool listen(const PINetworkAddress & addr, bool threaded = false);
//! \~english Stops the background listen loop started with threaded listening.
//! \~russian Останавливает фоновый цикл прослушивания, запущенный в потоковом режиме.
void stopThreadedListen();
//! \~english Returns accepted TCP client by index.
//! \~russian Возвращает принятый TCP-клиент по индексу.
PIEthernet * client(int index);
//! \~english Returns the number of accepted TCP clients.
//! \~russian Возвращает количество принятых TCP-клиентов.
int clientsCount() const;
//! \~english Returns all accepted TCP clients.
//! \~russian Возвращает всех принятых TCP-клиентов.
PIVector<PIEthernet *> clients() const;
//! \~english Sends raw buffer "data" of size "size".
//! \~russian Отправляет сырой буфер "data" размером "size".
//! \~\details
//! \~english For \a UDP it uses \a sendAddress(), for \a TCP_Client it sends through the connected peer.
//! \~russian Для \a UDP использует \a sendAddress(), для \a TCP_Client отправляет данные через подключенного пира.
bool send(const void * data, int size, bool threaded = false);
//! \~english Sends raw buffer "data" to address "ip":"port".
//! \~russian Отправляет сырой буфер "data" по адресу "ip":"port".
bool send(const PIString & ip, int port, const void * data, int size, bool threaded = false) {
return send(PINetworkAddress(ip, port), data, size, threaded);
}
//! \~english Sends raw buffer "data" to address "ip_port".
//! \~russian Отправляет сырой буфер "data" по адресу "ip_port".
bool send(const PIString & ip_port, const void * data, int size, bool threaded = false) {
return send(PINetworkAddress(ip_port), data, size, threaded);
}
//! \~english Sends raw buffer "data" to address "addr".
//! \~russian Отправляет сырой буфер "data" по адресу "addr".
bool send(const PINetworkAddress & addr, const void * data, int size, bool threaded = false);
//! \~english Sends byte array "data" using the default destination.
//! \~russian Отправляет массив байт "data" по адресу назначения по умолчанию.
bool send(const PIByteArray & data, bool threaded = false);
//! \~english Sends byte array "data" to address "ip":"port".
//! \~russian Отправляет массив байт "data" по адресу "ip":"port".
bool send(const PIString & ip, int port, const PIByteArray & data, bool threaded = false) {
return send(PINetworkAddress(ip, port), data, threaded);
}
//! \~english Sends byte array "data" to address "ip_port".
//! \~russian Отправляет массив байт "data" по адресу "ip_port".
bool send(const PIString & ip_port, const PIByteArray & data, bool threaded = false) {
return send(PINetworkAddress(ip_port), data, threaded);
}
//! \~english Sends byte array "data" to address "addr".
//! \~russian Отправляет массив байт "data" по адресу "addr".
bool send(const PINetworkAddress & addr, const PIByteArray & data, bool threaded = false);
//! \~english Returns whether writing is currently allowed.
//! \~russian Возвращает, разрешена ли сейчас запись.
bool canWrite() const override { return mode() & WriteOnly; }
//! \~english Interrupts a blocking socket operation.
//! \~russian Прерывает блокирующую операцию сокета.
void interrupt() override;
//! \~english Returns the underlying native socket descriptor.
//! \~russian Возвращает дескриптор нативного сокета.
int socket() const { return sock; }
//! \~english Flags describing a network interface.
//! \~russian Флаги, описывающие сетевой интерфейс.
enum InterfaceFlag {
ifActive = 0x1 /** \~english Interface is active \~russian Интерфейс активен */,
ifRunning = 0x2 /** \~english Interface is running \~russian Интерфейс работает */,
ifBroadcast = 0x4 /** \~english Interface supports broadcast \~russian Интерфейс поддерживает broadcast */,
ifMulticast = 0x8 /** \~english Interface supports multicast \~russian Интерфейс поддерживает multicast */,
ifLoopback = 0x10 /** \~english Interface is loopback \~russian Интерфейс является loopback */,
ifPTP = 0x20 /** \~english Interface is point-to-point \~russian Интерфейс работает в режиме point-to-point */
};
//! \~english Bitmask of \a InterfaceFlag values.
//! \~russian Битовая маска значений \a InterfaceFlag.
typedef PIFlags<InterfaceFlag> InterfaceFlags;
//! \~\ingroup IO
//! \~\brief
//! \~english Public descriptor of a system network interface.
//! \~russian Публичное описание системного сетевого интерфейса.
struct PIP_EXPORT Interface {
//! \~english System interface index.
//! \~russian Системный индекс интерфейса.
int index = -1;
//! \~english Interface MTU.
//! \~russian MTU интерфейса.
int mtu = 0;
//! \~english System interface name.
//! \~russian Системное имя интерфейса.
PIString name;
//! \~english MAC address in format "hh:hh:hh:hh:hh:hh", or empty if unavailable.
//! \~russian MAC-адрес в формате "hh:hh:hh:hh:hh:hh", либо пустая строка если он недоступен.
PIString mac;
//! \~english IPv4 address in format "i.i.i.i", or empty if unavailable.
//! \~russian IPv4-адрес в формате "i.i.i.i", либо пустая строка если он недоступен.
PIString address;
//! \~english Netmask in format "i.i.i.i", or empty if unavailable.
//! \~russian Маска сети в формате "i.i.i.i", либо пустая строка если она недоступна.
PIString netmask;
//! \~english Broadcast address in format "i.i.i.i", or empty if unavailable.
//! \~russian Broadcast-адрес в формате "i.i.i.i", либо пустая строка если он недоступен.
PIString broadcast;
//! \~english Point-to-point peer address, or empty if unavailable.
//! \~russian Адрес point-to-point-пира, либо пустая строка если он недоступен.
PIString ptp;
//! \~english Interface capability flags.
//! \~russian Флаги возможностей интерфейса.
InterfaceFlags flags;
//! \~english Returns whether the descriptor contains a valid interface.
//! \~russian Возвращает, содержит ли описание валидный интерфейс.
bool isValid() const { return name.isNotEmpty(); }
//! \~english Returns whether the interface is active.
//! \~russian Возвращает, активен ли интерфейс.
bool isActive() const { return flags[PIEthernet::ifActive]; }
//! \~english Returns whether the interface is running.
//! \~russian Возвращает, работает ли интерфейс.
bool isRunning() const { return flags[PIEthernet::ifRunning]; }
//! \~english Returns whether broadcast is supported.
//! \~russian Возвращает, поддерживается ли broadcast.
bool isBroadcast() const { return flags[PIEthernet::ifBroadcast]; }
//! \~english Returns whether multicast is supported.
//! \~russian Возвращает, поддерживается ли multicast.
bool isMulticast() const { return flags[PIEthernet::ifMulticast]; }
//! \~english Returns whether the interface is loopback.
//! \~russian Возвращает, является ли интерфейс loopback.
bool isLoopback() const { return flags[PIEthernet::ifLoopback]; }
//! \~english Returns whether the interface is point-to-point.
//! \~russian Возвращает, работает ли интерфейс в режиме point-to-point.
bool isPTP() const { return flags[PIEthernet::ifPTP]; }
};
//! \~\ingroup IO
//! \~\brief
//! \~english Collection of \a Interface descriptors with lookup helpers.
//! \~russian Коллекция описаний \a Interface с методами поиска.
class PIP_EXPORT InterfaceList: public PIVector<PIEthernet::Interface> {
public:
InterfaceList(): PIVector<PIEthernet::Interface>() {}
//! \~english Returns interface with system index "index", or 0 if absent.
//! \~russian Возвращает интерфейс с системным индексом "index", либо 0 если он не найден.
const Interface * getByIndex(int index) const {
for (int i = 0; i < size_s(); ++i)
if ((*this)[i].index == index) return &((*this)[i]);
return 0;
}
//! \~english Returns interface with system name "name", or 0 if absent.
//! \~russian Возвращает интерфейс с системным именем "name", либо 0 если он не найден.
const Interface * getByName(const PIString & name) const {
for (int i = 0; i < size_s(); ++i)
if ((*this)[i].name == name) return &((*this)[i]);
return 0;
}
//! \~english Returns interface with IP address "address", or 0 if absent.
//! \~russian Возвращает интерфейс с IP-адресом "address", либо 0 если он не найден.
const Interface * getByAddress(const PIString & address) const {
for (int i = 0; i < size_s(); ++i)
if ((*this)[i].address == address) return &((*this)[i]);
return 0;
}
//! \~english Returns the loopback interface, or 0 if absent.
//! \~russian Возвращает loopback-интерфейс, либо 0 если он не найден.
const Interface * getLoopback() const {
for (int i = 0; i < size_s(); ++i)
if ((*this)[i].isLoopback()) return &((*this)[i]);
return 0;
}
};
//! \~english Returns all detected system network interfaces.
//! \~russian Возвращает все обнаруженные системные сетевые интерфейсы.
static InterfaceList interfaces();
//! \~english Returns the address currently assigned to interface "interface_".
//! \~russian Возвращает адрес, назначенный интерфейсу "interface_".
static PINetworkAddress interfaceAddress(const PIString & interface_);
//! \~english Returns all detected system IP addresses.
//! \~russian Возвращает все обнаруженные системные IP-адреса.
static PIVector<PINetworkAddress> allAddresses();
//! \~english Converts a MAC address byte array to text form.
//! \~russian Преобразует массив байт MAC-адреса в текстовый вид.
static PIString macFromBytes(const PIByteArray & mac);
//! \~english Converts a textual MAC address to bytes.
//! \~russian Преобразует текстовый MAC-адрес в массив байт.
static PIByteArray macToBytes(const PIString & mac);
//! \~english Applies network mask "mask" to IPv4 string "ip".
//! \~russian Применяет сетевую маску "mask" к строковому IPv4-адресу "ip".
static PIString applyMask(const PIString & ip, const PIString & mask);
//! \~english Applies network mask "mask" to address "ip".
//! \~russian Применяет сетевую маску "mask" к адресу "ip".
static PINetworkAddress applyMask(const PINetworkAddress & ip, const PINetworkAddress & mask);
//! \~english Calculates broadcast address from IPv4 string and mask.
//! \~russian Вычисляет broadcast-адрес по строковому IPv4-адресу и маске.
static PIString getBroadcast(const PIString & ip, const PIString & mask);
//! \~english Calculates broadcast address from address and mask.
//! \~russian Вычисляет broadcast-адрес по адресу и маске.
static PINetworkAddress getBroadcast(const PINetworkAddress & ip, const PINetworkAddress & mask);
//! \events
//! \{
//! \fn void newConnection(PIEthernet * client)
//! \~english Raised when a new TCP client connection is accepted.
//! \~russian Вызывается при принятии нового TCP-клиентского соединения.
EVENT1(newConnection, PIEthernet *, client);
//! \fn void connected()
//! \~english Raised after a successful TCP client connection.
//! \~russian Вызывается после успешного подключения TCP-клиента.
EVENT0(connected);
//! \fn void disconnected(bool withError)
//! \~english Raised when the TCP connection is closed.
//! \~russian Вызывается при закрытии TCP-соединения.
EVENT1(disconnected, bool, withError);
//! \}
//! \ioparams
//! \{
#ifdef DOXYGEN
//! \~english Read IP address, default ""
//! \~russian IP-адрес чтения, по умолчанию ""
string ip;
//! \~english Read port, default 0
//! \~russian Порт чтения, по умолчанию 0
int port;
//! \~english Bitmask of \a Parameters values
//! \~russian Битовая маска значений \a Parameters
int parameters;
//! \~english Read timeout, default 10 s
//! \~russian Таймаут чтения, по умолчанию 10 с
PISystemTime readTimeout;
//! \~english Write timeout, default 10 s
//! \~russian Таймаут записи, по умолчанию 10 с
PISystemTime writeTimeout;
//! \~english IP packet TTL, default 64
//! \~russian TTL IP-пакетов, по умолчанию 64
int TTL;
//! \~english Multicast TTL, default 1
//! \~russian TTL multicast-пакетов, по умолчанию 1
int multicastTTL;
#endif
//! \}
protected:
explicit PIEthernet(int sock, PIString ip_port);
void propertyChanged(const char * name) override;
PIString constructFullPathDevice() const override;
void configureFromFullPathDevice(const PIString & full_path) override;
PIPropertyStorage constructVariantDevice() const override;
void configureFromVariantDevice(const PIPropertyStorage & d) override;
bool configureDevice(const void * e_main, const void * e_parent = 0) override;
ssize_t readDevice(void * read_to, ssize_t max_size) override;
ssize_t writeDevice(const void * data, ssize_t max_size) override;
DeviceInfoFlags deviceInfoFlags() const override;
void applyParameters();
//! \~english Called after any successful receive operation.
//! \~russian Вызывается после любой успешной операции приема.
//! \~\details
//! \~english Default implementation does nothing.
//! \~russian Реализация по умолчанию ничего не делает.
virtual void received(const void * data, int size) { ; }
void construct();
void init();
bool openDevice() override;
bool closeDevice() override;
void closeSocket(int & sd);
void applyTimeouts();
void applyBuffers();
void applyTimeout(int fd, int opt, PISystemTime tm);
void applyOptInt(int level, int opt, int val);
PRIVATE_DECLARATION(PIP_EXPORT)
int sock = -1, sock_s = -1, rcv_buf = 0, snd_buf = 0;
std::atomic_bool connected_ = {false}, connecting_ = {false}, listen_threaded = {false}, server_bounded = {false};
bool is_server_client = false;
mutable PINetworkAddress addr_r, addr_s, addr_lr;
Type eth_type;
PIThread server_thread_;
mutable PIMutex clients_mutex;
PIVector<PIEthernet *> clients_;
PIQueue<PIString> mcast_queue;
PIStringList mcast_groups;
PIFlags<PIEthernet::Parameters> params;
private:
EVENT_HANDLER1(void, clientDeleted, PIObject *, o);
static void server_func(void * eth);
void setType(Type t, bool reopen = true);
bool connectTCP();
#ifdef WINDOWS
long waitForEvent(PIWaitEvent & event, long mask);
#endif
static int ethErrorCore();
static PIString ethErrorString();
static int ethRecv(int sock, void * buf, int size, int flags = 0);
static int ethRecvfrom(int sock, void * buf, int size, int flags, sockaddr * addr);
static int ethSendto(int sock, const void * buf, int size, int flags, sockaddr * addr, int addr_len);
static void ethClosesocket(int sock, bool shutdown);
static int ethSetsockopt(int sock, int level, int optname, const void * optval, int optlen);
static int ethSetsockoptInt(int sock, int level, int optname, int value = 1);
static int ethSetsockoptBool(int sock, int level, int optname, bool value = true);
static void ethNonblocking(int sock);
static bool ethIsWriteable(int sock);
};
inline bool operator<(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {
return (v0.name < v1.name);
}
inline bool operator==(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {
return (v0.name == v1.name && v0.address == v1.address && v0.netmask == v1.netmask);
}
inline bool operator!=(const PIEthernet::Interface & v0, const PIEthernet::Interface & v1) {
return (v0.name != v1.name || v0.address != v1.address || v0.netmask != v1.netmask);
}
#endif // PIETHERNET_H