#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
using namespace std;
#define BROADCAST_PORT 8186
#define MAX_IPC_NUM 100
#define MAX_TIMEOUT 1
#define M_DBG(fmt, ...) \
do\
{\
printf("%s:%d: "fmt"\n", __FILE__, __LINE__, ##__VA_ARGS__);\
}while(0)
#define M_RETURN(exr, ret, fmt, ...) \
do\
{\
if (!(exr))\
{\
M_DBG(fmt, ##__VA_ARGS__);\
return ret;\
}\
}while(0)
#define M_PRINTF(exr, fmt, ...) \
do\
{\
if (!(exr))\
{\
M_DBG(fmt, ##__VA_ARGS__);\
}\
}while(0)
#define _ArraySize(a) (sizeof(a)/sizeof(a[0]))
typedef struct
{
bool valid;
char szWorkNic[24];
char szId[24];
char szServer[24];
char szMAC[24];
char szIp[24];
char szGateway[24];
char szMask[24];
char szDns0[24];
char szDns1[24];
char szSession[24];
}IPC_INFO_S;
typedef struct
{
int recv_port;
IPC_INFO_S astIpcInfo[MAX_IPC_NUM];
}RUNNING_PARAMS_S;
static bool _ShowIpcInfo(RUNNING_PARAMS_S* _pstRunParams)
{
int i = 0;
printf("| %-8s | %-17s | %-16s | %-16s | %-20s | %-5s |\n",
"IPC-ID", "IPC-MAC", "IPC-IP", "IPC-GATEWAY", "IPC-SERVER", "NIC");
for (i = 0; i < _ArraySize(_pstRunParams->astIpcInfo); i++)
{
if (!_pstRunParams->astIpcInfo[i].valid)
{
continue;
}
IPC_INFO_S* pstTmp = &_pstRunParams->astIpcInfo[i];
printf("| %-8s | %-17s | %-16s | %-16s | %-20s | %-5s |\n", pstTmp->szId, pstTmp->szMAC, pstTmp->szIp,
pstTmp->szGateway,pstTmp->szServer, pstTmp->szWorkNic);
}
printf("\n\n\n\n\n\n");
return true;
}
static bool _ShowIpcInfo1(RUNNING_PARAMS_S* _pstRunParams)
{
int i = 0;
printf("| %-8s | %-17s | %-16s | %-16s | %-16s | %-16s | %-16s | %-20s | %-5s |\n",
"IPC-ID", "IPC-MAC", "IPC-IP", "IPC-GATEWAY", "IPC-MASK","IPC-DNS0","IPC-DNS1","IPC-SERVER", "NIC");
for (i = 0; i < _ArraySize(_pstRunParams->astIpcInfo); i++)
{
if (!_pstRunParams->astIpcInfo[i].valid)
{
continue;
}
IPC_INFO_S* pstTmp = &_pstRunParams->astIpcInfo[i];
printf("| %-8s | %-17s | %-16s | %-16s | %-16s | %-16s | %-16s | %-20s | %-5s |\n", pstTmp->szId, pstTmp->szMAC, pstTmp->szIp,
pstTmp->szGateway, pstTmp->szMask,pstTmp->szDns0,pstTmp->szDns1,pstTmp->szServer, pstTmp->szWorkNic);
}
printf("\n\n\n\n\n\n");
return true;
}
static bool _FindStr(char* _szInput, const char* _szKey)
{
bool bRet = false;
char* szValue = NULL;
szValue = strstr(_szInput, _szKey);
if(szValue != NULL)
{
bRet = true;
}
return bRet;
}
static int _SetupBroadCastSock(int _port)
{
M_RETURN(_port > 0 && _port < 65536, false, "invalid port[%d]", _port);
// 绑定地址
struct sockaddr_in addrto;
bzero(&addrto, sizeof(struct sockaddr_in));
addrto.sin_family = AF_INET;
addrto.sin_addr.s_addr = htonl(INADDR_ANY);
addrto.sin_port = htons(_port);
int sock = -1;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
M_DBG("socket error, %s", strerror(errno));
close(sock);
return -1;
}
const int opt = 1;
//设置该套接字为广播类型,
int nb = 0;
nb = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt));
if(nb == -1)
{
M_DBG("setsockopt broadcast error, %s", strerror(errno));
close(sock);
return -1;
}
struct timeval timeout = {MAX_TIMEOUT, 0};
nb = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(struct timeval));
if(nb == -1)
{
M_DBG("setsockopt timeout error, %s", strerror(errno));
close(sock);
return -1;
}
if(bind(sock,(struct sockaddr *)&(addrto), sizeof(struct sockaddr_in)) == -1)
{
M_DBG("setsockopt error, %s", strerror(errno));
close(sock);
return -1;
}
return sock;
}
static bool _RecvDataOverBroadCast(int _sock, char* _szTmp, int _len)
{
M_RETURN(_sock > 0, false, "invalid sock[%d]", _sock);
memset(_szTmp, 0, _len);
//int ret = recvfrom(sock, _szTmp, _len, 0, (struct sockaddr*)&from,(socklen_t*)&len);
int ret = recvfrom(_sock, _szTmp, _len, 0, NULL, NULL);
if(ret<=0)
{
if (errno == EAGAIN || errno == EINTR)
{
M_DBG("setsockopt time out, %s", strerror(errno));
//close(_sock);
return false;
}
else
{
M_DBG("setsockopt error, %s", strerror(errno));
//close(_sock);
return false;
}
}
else
{
M_DBG("recv ok[%d bytes]:\n%s", ret, _szTmp);
}
//close(_sock);
return true;
}
static bool _SendDataOverBroadCast(const char* _szTmp, int _len, int _port)
{
int sock = -1;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
M_DBG("socket error, %s", strerror(errno));
close(sock);
return false;
}
const int opt = 1;
//设置该套接字为广播类型,
int nb = 0;
nb = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt));
if(nb == -1)
{
M_DBG("setsockopt error, %s", strerror(errno));
close(sock);
return false;
}
struct timeval timeout = {MAX_TIMEOUT, 0};
nb = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(struct timeval));
if(nb == -1)
{
M_DBG("setsockopt timeout error, %s", strerror(errno));
close(sock);
return false;
}
struct sockaddr_in addrto;
bzero(&addrto, sizeof(struct sockaddr_in));
addrto.sin_family = AF_INET;
addrto.sin_addr.s_addr = htonl(INADDR_BROADCAST);
addrto.sin_port = htons(_port);
int nlen = sizeof(addrto);
int ret = sendto(sock, _szTmp, _len, 0, (struct sockaddr*)&addrto, nlen);
if(ret <= 0)
{
M_DBG("send error, %s", strerror(errno));
close(sock);
return false;
}
else
{
M_DBG("send ok[%d bytes] over broadcast port %d", ret, _port);
}
close(sock);
return true;
}
static bool _GetKeyValue(char* _szTmp, const char* _szKey, char* _szValue, int _Len)
{
bool bRet = false;
char* szValue = NULL;
char* szReturn = NULL;
memset(_szValue, 0, _Len);
szValue = strstr(_szTmp, _szKey);
if(szValue != NULL)
{
szValue += strlen(_szKey);
szReturn = strstr(szValue, "\r\n");
if(szReturn != NULL)
{
assert(szReturn - szValue <= _Len);
memcpy(_szValue, szValue, szReturn - szValue);
_szValue[szReturn - szValue] = 0;
bRet = true;
}
}
return bRet;
}
static int _GetErrCode(char* _szTmp)
{
char szStatusCode[24];
memset(szStatusCode, 0, sizeof(szStatusCode));
bool ret = _GetKeyValue(_szTmp, "AJB-IPC/1.0 ", szStatusCode, sizeof(szStatusCode));
M_RETURN(ret, -1, "get error code failed. %s", _szTmp);
return atoi(szStatusCode);
}
// FilterRepeat and find a valid node
static int _FindAvailable(const char* szMAC, IPC_INFO_S* _pstIpcInfo, int _num)
{
assert(_num <= MAX_IPC_NUM);
int i = 0;
for (i = 0; i < _num; i++)
{
if (_pstIpcInfo[i].valid)
{
if (!strcmp(_pstIpcInfo[i].szMAC, szMAC))
{
return i;
}
}
else
{
return i;
}
}
M_DBG("IpcInfo list is full[%d]", i);
return -1;
}
static bool _ParseData(char* _szTmp, int _szlen, IPC_INFO_S* _pstIpcInfo, int _num)
{
char szMAC[24];
memset(szMAC, 0, sizeof(szMAC));
char szDns[48];
memset(szDns, 0, sizeof(szDns));
bool ret = _GetKeyValue(_szTmp, "MAC: ", szMAC, sizeof(szMAC));
M_RETURN(ret, ret, "not found MAC\n%s", _szTmp);
int index = _FindAvailable(szMAC, _pstIpcInfo, _num);
M_RETURN(index != -1, false, "find available node failed");
M_DBG("index: %d", index);
memset(&_pstIpcInfo[index], 0, sizeof(IPC_INFO_S));
ret = _GetKeyValue(_szTmp, "Session: ", _pstIpcInfo[index].szSession, sizeof(_pstIpcInfo[index].szSession));
M_PRINTF(ret, "not found session, %s", _szTmp);
ret = _GetKeyValue(_szTmp, "ID: ", _pstIpcInfo[index].szId, sizeof(_pstIpcInfo[index].szId));
M_PRINTF(ret, "not found ID, %s", _szTmp);
ret = _GetKeyValue(_szTmp, "Server: ", _pstIpcInfo[index].szServer, sizeof(_pstIpcInfo[index].szServer));
M_PRINTF(ret, "not found Server, %s", _szTmp);
ret = _GetKeyValue(_szTmp, "MAC: ", _pstIpcInfo[index].szMAC, sizeof(_pstIpcInfo[index].szMAC));
M_PRINTF(ret, "not found MAC, %s", _szTmp);
ret = _GetKeyValue(_szTmp, "Ip: ", _pstIpcInfo[index].szIp, sizeof(_pstIpcInfo[index].szIp));
M_PRINTF(ret, "not found Ip, %s", _szTmp);
ret = _GetKeyValue(_szTmp, "Gateway: ", _pstIpcInfo[index].szGateway, sizeof(_pstIpcInfo[index].szGateway));
M_PRINTF(ret, "not found Gateway, %s", _szTmp);
ret = _GetKeyValue(_szTmp, "Mask: ", _pstIpcInfo[index].szMask, sizeof(_pstIpcInfo[index].szMask));
M_PRINTF(ret, "not found Mask, %s", _szTmp);
ret = _GetKeyValue(_szTmp, "WorkNic: ", _pstIpcInfo[index].szWorkNic, sizeof(_pstIpcInfo[index].szWorkNic));
M_PRINTF(ret, "not found WorkNic, %s", _szTmp);
ret = _GetKeyValue(_szTmp, "Dns: ", szDns, sizeof(szDns));
M_PRINTF(ret, "not found Dns, %s", _szTmp);
if (ret)
{
ret = _FindStr(szDns, ";");
if (ret)
{
char* Begin = szDns;
char* Found = strstr(Begin, ";");
M_RETURN(Found, false, "found ';' error, %s", Begin);
strncpy(_pstIpcInfo[index].szDns0, Begin, Found - Begin);
Found += strlen(";");
strcpy(_pstIpcInfo[index].szDns1, Found);
}
else
{
strcpy(_pstIpcInfo[index].szDns0, szDns);
}
}
_pstIpcInfo[index].valid = true;
return true;
}
static bool _SendGetRequest(RUNNING_PARAMS_S* _pstRunParams)
{
char szTmp[1024];
memset(szTmp, 0, sizeof(szTmp));
_pstRunParams->recv_port++;
const char* szTemplate =
"GET AJB-IPC/1.0\r\n"
"ClientPort: %d\r\n"
"\r\n"
;
snprintf(szTmp, sizeof(szTmp), szTemplate, _pstRunParams->recv_port);
M_DBG("ready to send[%d bytes]:\n%s", strlen(szTmp), szTmp);
bool ret = _SendDataOverBroadCast(szTmp, strlen(szTmp), BROADCAST_PORT);
return ret;
}
static bool _RecvResp(RUNNING_PARAMS_S* _pstRunParams, char* _szTmp, int _len)
{
bool ret = false;
int sock = _SetupBroadCastSock(_pstRunParams->recv_port);
M_RETURN(sock != -1, false, "invalid sock[%d]", sock);
while(1)
{
ret = _RecvDataOverBroadCast(sock, _szTmp, _len);
//M_RETURN(ret, ret, "recv all complete.");
if (!ret)
{
close(sock);
break;
}
if (200 != _GetErrCode(_szTmp))
{
M_DBG("status code is not 200, continue recv:\n%s", _szTmp);
continue;
}
if (!_FindStr(_szTmp, "\r\n\r\n"))
{
M_DBG("not found end sign, continue recv:\n%s", _szTmp);
continue;
}
ret = _ParseData(_szTmp, strlen(_szTmp), _pstRunParams->astIpcInfo, _ArraySize(_pstRunParams->astIpcInfo));
}
return ret;
}
static bool _SendPostRequest(RUNNING_PARAMS_S* _pstRunParams)
{
char szTmp[1024];
memset(szTmp, 0, sizeof(szTmp));
_pstRunParams->recv_port++;
const char* szTemplate =
"POST AJB-IPC/1.0\r\n"
"ClientPort: %d\r\n"
"Session: %s\r\n"
"ID: %x\r\n"
"Server: %s\r\n"
"MAC: %s\r\n"
"Ip: %s\r\n"
"Gateway: %s\r\n"
"Mask: %s\r\n"
"Dns: %s\r\n"
"\r\n"
;
char* szSession = NULL;
int i = 0;
for (i = 0; i < _ArraySize(_pstRunParams->astIpcInfo); i++)
{
if (!_pstRunParams->astIpcInfo[i].valid)
{
continue;
}
snprintf(szTmp, sizeof(szTmp), szTemplate, _pstRunParams->recv_port, _pstRunParams->astIpcInfo[i].szSession, 0x54325432,
"192.168.34.203", "00:00:22:26:f4:de", "192.168.34.211",
"192.168.34.254", "255.255.255.0", "5.5.5.5");
M_DBG("ready to send[%d bytes]:\n%s", strlen(szTmp), szTmp);
bool ret = _SendDataOverBroadCast(szTmp, strlen(szTmp), BROADCAST_PORT);
M_RETURN(ret, ret, "send error.");
}
return true;
}
int main()
{
char szTmp[1024];
memset(szTmp, 0, sizeof(szTmp));
RUNNING_PARAMS_S stRunParams;
memset(&stRunParams, 0, sizeof(RUNNING_PARAMS_S));
stRunParams.recv_port = 8056;// init port
while(1)
{
M_DBG("Please press ENTER to seach IPC ...");
getchar();
bool ret = _SendGetRequest(&stRunParams);
M_RETURN(ret, ret, "send error.");
ret = _RecvResp(&stRunParams, szTmp, sizeof(szTmp));
M_PRINTF(ret, "recv all complete.");
/*
ret = _SendPostRequest(&stRunParams);
M_RETURN(ret, ret, "send error.");
ret = _RecvResp(&stRunParams, szTmp, sizeof(szTmp));
M_PRINTF(ret, "recv all complete.");
*/
ret = _ShowIpcInfo(&stRunParams);
M_PRINTF(ret, "show failed.");
}
return 0;
}
局域网广播收发
最新推荐文章于 2022-07-26 23:04:18 发布