#pragma once
#include "libobsensor/h/ObTypes.h"
#include "ethernet/socket/SocketTypes.hpp"
#include <vector>
#include <string>
#include <mutex>
#include <set>
namespace libobsensor {
#define GVCP_VERSION 0x42
#define GVCP_DISCOVERY_FLAGS 0x11
#define GVCP_FORCEIP_FLAGS 0x11
#define GVCP_PORT 3956
#define GVCP_REQUEST_ID 0x0001
#define GEV_STATUS_SUCCESS 0x0000
#define GVCP_DISCOVERY_CMD 0x0002
#define GVCP_DISCOVERY_ACK 0x0003
#define GVCP_FORCEIP_CMD 0x0004
#define GVCP_FORCEIP_ACK 0x0005
#pragma pack(push, 1)
struct gvcp_cmd_header {
uint8_t cMsgKeyCode; uint8_t cFlag; uint16_t wCmd; uint16_t wLen; uint16_t wReqID; };
struct gvcp_forceip_payload {
uint8_t Mac[8]; uint8_t CurIP[16]; uint8_t SubMask[16]; uint8_t Gateway[16]; };
struct gvcp_ack_header {
uint16_t wStatus; uint16_t wAck; uint16_t wLen;
uint16_t wReqID;
};
struct gvcp_ack_payload {
uint32_t dwSpecVer;
uint32_t dwDevMode;
uint8_t Mac[8]; uint32_t dwSupIpSet;
uint32_t dwCurIpSet;
uint8_t CurIP[16]; uint8_t SubMask[16]; uint8_t Gateway[16]; char szFacName[32]; char szModelName[28]; uint32_t dwPID;
char szDevVer[32];
char szFacInfo[48];
char szSerial[16];
char szUserName[16];
};
struct gvcp_discover_cmd {
struct gvcp_cmd_header header;
};
struct gvcp_discover_ack {
struct gvcp_ack_header header;
struct gvcp_ack_payload payload;
};
struct gvcp_forceip_cmd {
struct gvcp_cmd_header header;
struct gvcp_forceip_payload payload;
};
struct gvcp_forceip_ack {
struct gvcp_ack_header header;
};
#pragma pack(pop)
struct GVCPDeviceInfo {
std::string netInterfaceName = "unknown";
std::string localIp = "unknown";
std::string localMac = "unknown";
std::string localGateway = "unknown";
uint8_t localSubnetLength = 0;
std::string mac = "unknown";
std::string ip = "unknown";
std::string mask = "unknown";
std::string gateway = "unknown";
std::string sn = "unknown";
std::string name = "unknown";
uint32_t pid = 0;
virtual bool operator==(const GVCPDeviceInfo &other) const {
return other.mac == mac && other.sn == sn && other.ip == ip;
}
virtual ~GVCPDeviceInfo() {}
};
struct GVCPSocketInfo {
std::string mac = "unknown";
std::string address = "unknown";
std::string netInterfaceName = "unknown";
std::string gateway = "unknown";
uint8_t subnetLength = 0;
SOCKET sock = 0;
SOCKET sockRecv = 0;
};
#define MAX_SOCKETS 32
class GVCPClient {
public:
~GVCPClient();
std::vector<GVCPDeviceInfo> queryNetDeviceList();
bool forceIpConfig(std::string macAddress, const OBNetIpConfig &config);
static GVCPClient &instance() {
static GVCPClient instance;
return instance;
}
private:
GVCPClient();
int openClientSockets();
void closeClientSockets();
SOCKET openClientSocket(SOCKADDR_IN addr);
int recvAndParseGVCPResponse(SOCKET sock, const GVCPSocketInfo &socketInfo);
void sendGVCPDiscovery(GVCPSocketInfo socketInfo);
bool sendGVCPForceIP(GVCPSocketInfo socketInfo, std::string mac, const OBNetIpConfig &config);
#if defined(__APPLE__)
const uint8_t *getMACAddress(struct ifaddrs *ifap, const char *interface_name);
#endif
void checkAndUpdateSockets();
SOCKET openClientRecvSocket(SOCKET srcSock);
private:
SOCKET socks_[MAX_SOCKETS];
GVCPSocketInfo socketInfos_[MAX_SOCKETS];
int sockCount_ = 0;
std::vector<GVCPDeviceInfo> devInfoList_;
std::mutex queryMtx_;
std::mutex devInfoListMtx_;
#ifndef WIN32
std::set<std::string> ipAddressStrSet_;
#endif
};
}