#include "websocket_common.h"
#include
#include
#include // 使用 malloc, calloc等动态分配内存方法
#include // 获取系统时间
#include
#include // 非阻塞
#include
#include // inet_addr()
#include // close()
#include // 文件IO操作
#include //
#include
#include
#include
#include // gethostbyname, gethostbyname2, gethostbyname_r, gethostbyname_r2
#include
#include
#include
#include
#include // SIOCSIFADDR
//==============================================================================================
//======================================== 设置和工具部分 =======================================
//==============================================================================================
// 连接服务器
#define WEBSOCKET_LOGIN_CONNECT_TIMEOUT 1000 // 登录连接超时设置 1000ms
#define WEBSOCKET_LOGIN_RESPOND_TIMEOUT (1000 + WEBSOCKET_LOGIN_CONNECT_TIMEOUT) // 登录等待回应超时设置 1000ms
// 发收
// 生成握手key的长度
#define WEBSOCKET_SHAKE_KEY_LEN 16
//==================== delay ms ====================
void webSocket_delayms(unsigned int ms)
{
struct timeval tim;
tim.tv_sec = ms/1000;
tim.tv_usec = (ms%1000)*1000;
select(0, NULL, NULL, NULL, &tim);
}
//-------------------- IP控制 --------------------
int netCheck_setIP(char *devName, char *ip)
{
struct ifreq temp;
struct sockaddr_in *addr;
int fd, ret;
//
strcpy(temp.ifr_name, devName);
if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return -1;
//
addr = (struct sockaddr_in *)&(temp.ifr_addr);
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = inet_addr(ip);
ret = ioctl(fd, SIOCSIFADDR, &temp);
//
close(fd);
if(ret < 0)
return -1;
return 0;
}
void netCheck_getIP(char *devName, char *ip)
{
struct ifreq temp;
struct sockaddr_in *addr;
int fd, ret;
//
strcpy(temp.ifr_name, devName);
if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return;
ret = ioctl(fd, SIOCGIFADDR, &temp);
close(fd);
if(ret < 0)
return;
//
addr = (struct sockaddr_in *)&(temp.ifr_addr);
strcpy(ip, inet_ntoa(addr->sin_addr));
//
// return ip;
}
//==================== 域名转IP ====================
typedef struct{
pthread_t thread_id;
char ip[256];
bool result;
bool actionEnd;
}GetHostName_Struct;
//
void *websocket_getHost_fun(void *arge)
{
int ret;
//int i;
char buf[1024];
struct hostent host_body, *host = NULL;
struct in_addr **addr_list;
GetHostName_Struct *gs = (GetHostName_Struct *)arge;
/* 此类方法不可重入! 即使关闭线程
if((host = gethostbyname(gs->ip)) == NULL)
//if((host = gethostbyname2(gs->ip, AF_INET)) == NULL)
{
gs->actionEnd = true;
return NULL;
}*/
if(gethostbyname_r(gs->ip, &host_body, buf, sizeof(buf), &host, &ret))
{
gs->actionEnd = true;
return NULL;
}
if(host == NULL)
{
gs->actionEnd = true;
return NULL;
}
addr_list = (struct in_addr **)host->h_addr_list;
//printf("ip name : %s\r\nip list : ", host->h_name);
//for(i = 0; addr_list[i] != NULL; i++) printf("%s, ", inet_ntoa(*addr_list[i])); printf("\r\n");
if(addr_list[0] == NULL)
{
gs->actionEnd = true;
return NULL;
}
memset(gs->ip, 0, sizeof(gs->ip));
strcpy(gs->ip, (char *)(inet_ntoa(*addr_list[0])));
gs->result = true;
gs->actionEnd = true;
return NULL;
}
//
int websocket_getIpByHostName(char *hostName, char *backIp)
{
int i, timeOut = 1;
GetHostName_Struct gs;
if(hostName == NULL)
return -1;
else if(strlen(hostName) < 1)
return -1;
//----- 开线程从域名获取IP -----
memset(&gs, 0, sizeof(GetHostName_Struct));
strcpy(gs.ip, hostName);
gs.result = false;
gs.actionEnd = false;
if (pthread_create(&gs.thread_id, NULL, (void *)websocket_getHost_fun, &gs) < 0)
return -1;
i = 0;
while(!gs.actionEnd)
{
if(++i > 10)
{
i = 0;
if(++timeOut > 1000)
break;
}
webSocket_delayms(1000);// 1ms延时
}
// pthread_cancel(gs.thread_id);
pthread_join(gs.thread_id, NULL);
if(!gs.result)
return -timeOut;
//----- 开线程从域名获取IP -----
memset(backIp, 0, strlen(backIp));
strcpy(backIp, gs.ip);
return timeOut;
}
//==================== 加密方法BASE64 ====================
//base64编/解码用的基础字符集
const char websocket_base64char[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/*******************************************************************************
* 名称: websocket_base64_encode
* 功能: ascii编码为base64格式
* 形参: bindata : ascii字符串输入
* base64 : base64字符串输出
* binlength : bindata的长度
* 返回: base64字符串长度
* 说明: 无
******************************************************************************/
int websocket_base64_encode( const unsigned char *bindata, char *base64, int binlength)
{
int i, j;
unsigned char current;
for ( i = 0, j = 0 ; i < binlength ; i += 3 )
{
current = (bindata[i] >> 2) ;
current &= (unsigned char)0x3F;
base64[j++] = websocket_base64char[(int)current];
current = ( (unsigned char)(bindata[i] << 4 ) ) & ( (unsigned char)0x30 ) ;
if ( i + 1 >= binlength )
{
base64[j++] = websocket_base64char[(int)current];
base64[j++] = '=';
base64[j++] = '=';
break;
}
current |= ( (unsigned char)(bindata[i+1] >> 4) ) & ( (unsigned char) 0x0F );
base64[j++] = websocket_base64char[(int)current];
current = ( (unsigned char)(bindata[i+1] << 2) ) & ( (unsigned char)0x3C ) ;
if ( i + 2 >= binlength )
{
base64[j++] = websocket_base64char[(int)current];
base64[j++] = '=';
break;
}
current |= ( (unsigned char)(bindata[i+2] >> 6) ) & ( (unsigned char) 0x03 );
base64[j++] = websocket_base64char[(int)current];
current = ( (unsigned char)bindata[i+2] ) & ( (unsigned char)0x3F ) ;
base64[j++] = websocket_base64char[(int)current];
}
base64[j] = '\0';
return j;
}
/*******************************************************************************
* 名称: websocket_base64_decode
* 功能: base64格式解码为ascii
* 形参: base64 : base64字符串输入
* bindata : ascii字符串输出
* 返回: 解码出来的ascii字符串长度
* 说明: 无
******************************************************************************/
int websocket_base64_decode( const char *base64, unsigned char *bindata)
{
int i, j;
unsigned char k;
unsigned char temp[4];
for ( i = 0, j = 0; base64[i] != '\0' ; i += 4 )
{
memset( temp, 0xFF, sizeof(temp) );
for ( k = 0 ; k < 64 ; k ++ )
{
if ( websocket_base64char[k] == base64[i] )
temp[0]= k;
}
for ( k = 0 ; k < 64 ; k ++ )
{
if ( websocket_base64char[k] == base64[i+1] )
temp[1]= k;
}
for ( k = 0 ; k < 64 ; k ++ )
{
if ( websocket_base64char[k] == base64[i+2] )
temp[2]= k;
}
for ( k = 0 ; k < 64 ; k ++ )
{
if ( websocket_base64char[k] == base64[i+3] )
temp[3]= k;
}
bindata[j++] = ((unsigned char)(((unsigned char)(temp[0] << 2))&0xFC)) | \
((unsigned char)((unsigned char)(temp[1]>>4)&0x03));
if ( base64[i+2] == '=' )
break;
bindata[j++] = ((unsigned char)(((unsigned char)(temp[1] << 4))&0xF0)) | \
((unsigned char)((unsigned char)(temp[2]>>2)&0x0F));
if ( base64[i+3] == '=' )
break;
bindata[j++] = ((unsigned char)(((unsigned char)(temp[2] << 6))&0xF0)) | \
((unsigned char)(temp[3]&0x3F));
}
return j;
}
//==================== 加密方法 sha1哈希 ====================
typedef struct SHA1Context{
unsigned Message_Digest[5];
unsigned Length_L