#include "../ciscore/cis_if_net.h" | |
#include "../ciscore/cis_list.h" | |
#include "../ciscore/cis_log.h" | |
#include "../ciscore/cis_if_sys.h" | |
#include "../ciscore/cis_internals.h" | |
#include "cis_sample_entry.h" | |
#include "netdb.h" | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <pthread.h> | |
#include <arpa/inet.h> | |
#define MAX_PACKET_SIZE (1024) | |
struct st_cisnet_context | |
{ | |
int sock; | |
char host[128]; | |
uint16_t port; | |
int state; | |
void* context; | |
int8_t quit; | |
struct st_net_packet* g_packetlist; | |
struct sockaddr_in saddr; | |
}; | |
struct st_net_packet | |
{ | |
struct st_net_packet * next; | |
uint8_t* buffer; | |
uint32_t length; | |
}; | |
static int prvCreateSocket(uint16_t localPort,int ai_family); | |
void *lwm2m_recv_thread(void* argv); | |
uint8_t cisnet_attached_state(void * ctx) | |
{ | |
return ((struct st_cis_context *)(ctx))->netAttached; | |
} | |
extern int dialer_Check_NW(UINT32 AT_channel); | |
cis_ret_t cisnet_init(void *context,const cisnet_config_t* config,cisnet_callback_t cb) | |
{ | |
int NW_status= 0 ; | |
lwm2m_printf("fall in cisnet_init\r\n"); | |
memcpy(&((struct st_cis_context *)context)->netConfig,config,sizeof(cisnet_config_t)); | |
((struct st_cis_context *)context)->netCallback.onEvent = cb.onEvent; | |
//NW_status = dialer_Check_NW(TEL_AT_CMD_ATP_6);/*get NW status*/ | |
if(NW_status==0){ | |
lwm2m_printf("gAttached 2/3g\r\n"); | |
((struct st_cis_context *)context)->netAttached = true; | |
}else if(NW_status==1){ | |
lwm2m_printf("gAttached 4g\r\n"); | |
((struct st_cis_context *)context)->netAttached = true; | |
}else{ | |
lwm2m_printf("dialer_Check_NW %d\r\n",NW_status); | |
((struct st_cis_context *)context)->netAttached = false; | |
} | |
return CIS_RET_OK; | |
} | |
cis_ret_t cisnet_create(cisnet_t* netctx,const char* host,void* context) | |
{ | |
int NW_status= 0 ; | |
if(((struct st_cis_context *)context)->netAttached != true){ | |
//NW_status = dialer_Check_NW(TEL_AT_CMD_ATP_6);/*get NW status*/ | |
if(NW_status==0){ | |
lwm2m_printf("gAttached 2/3g\r\n"); | |
((struct st_cis_context *)context)->netAttached = true; | |
}else if(NW_status==1){ | |
lwm2m_printf("gAttached 4g\r\n"); | |
((struct st_cis_context *)context)->netAttached = true; | |
}else{ | |
lwm2m_printf("dialer_Check_NW %d\r\n",NW_status); | |
((struct st_cis_context *)context)->netAttached = false; | |
return CIS_RET_ERROR; | |
} | |
} | |
(*netctx) = (cisnet_t)cis_malloc(sizeof(struct st_cisnet_context)); | |
memset((*netctx),0,sizeof(struct st_cisnet_context)); | |
(*netctx)->sock = 0; | |
(*netctx)->port = 5683; | |
(*netctx)->state = 0; | |
(*netctx)->quit = 0; | |
(*netctx)->g_packetlist=NULL; | |
(*netctx)->context = context; | |
strcpy((*netctx)->host,host); | |
return CIS_RET_OK; | |
} | |
void cisnet_destroy(cisnet_t netctx) | |
{ | |
lwm2m_printf("enter %s\r\n",__FUNCTION__); | |
close(netctx->sock); | |
if(netctx!=NULL){ | |
cis_free(netctx); | |
} | |
} | |
cis_ret_t cisnet_connect(cisnet_t netctx) | |
{ | |
struct hostent* host_entry; | |
int sock=-1; | |
int ret; | |
//int result; | |
lwm2m_printf("enter %s,host:%s\r\n",__FUNCTION__,netctx->host); | |
host_entry = gethostbyname(netctx->host); | |
if (host_entry == NULL) { | |
lwm2m_printf("%s,DNS gethostbyname failed: %s\r\n",__FUNCTION__,netctx->host); | |
return CIS_RET_ERROR; | |
} | |
lwm2m_printf("%s,DNS gethostbyname,Get %s ip %d.%d.%d.%d\r\n", __FUNCTION__,netctx->host, host_entry->h_addr_list[0][0] & 0xff, | |
host_entry->h_addr_list[0][1] & 0xff, host_entry->h_addr_list[0][2] & 0xff, host_entry->h_addr_list[0][3] & 0xff); | |
sock = prvCreateSocket(0,AF_INET); | |
if (sock < 0) | |
{ | |
lwm2m_printf("Failed to open socket\r\n"); | |
return CIS_RET_ERROR; | |
} | |
netctx->sock = sock; | |
netctx->state = 1; | |
netctx->saddr.sin_family = AF_INET; | |
netctx->saddr.sin_port = htons(netctx->port); | |
netctx->saddr.sin_addr.s_addr= * (UINT32 *) host_entry->h_addr_list[0]; | |
((struct st_cis_context *)(netctx->context))->netCallback.onEvent(netctx,cisnet_event_connected,NULL,netctx->context); | |
static pthread_t s_tid_lwm2mRecvTask; | |
pthread_attr_t attr; | |
pthread_attr_init(&attr); | |
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); | |
ret = pthread_create(&s_tid_lwm2mRecvTask, &attr, (void *)lwm2m_recv_thread, (void *)netctx); | |
if(ret < 0){ | |
lwm2m_printf("Failed to create lwm2m recv thread, ret:%d\r\n",ret); | |
return -1; | |
} | |
return CIS_RET_OK; | |
} | |
cis_ret_t cisnet_disconnect(cisnet_t netctx) | |
{ | |
lwm2m_printf("enter %s\r\n",__FUNCTION__); | |
netctx->state = 0; | |
((struct st_cis_context *)(netctx->context))->netCallback.onEvent(netctx,cisnet_event_disconnect,NULL,netctx->context); | |
return 1; | |
} | |
cis_ret_t cisnet_write(cisnet_t netctx,const uint8_t * buffer,uint32_t length) | |
{ | |
int nbSent; | |
size_t offset; | |
struct sockaddr_in saddr; | |
uint32_t g_addrlen; | |
memcpy(&saddr,(struct sockaddr_in *)&(netctx->saddr),sizeof(struct sockaddr_in)); | |
g_addrlen=sizeof(saddr); | |
offset = 0; | |
while (offset != length) | |
{ | |
nbSent = sendto(netctx->sock, (const char*)buffer + offset, length - offset, 0, (struct sockaddr *)&saddr, g_addrlen); | |
if (nbSent == -1){ | |
int value; | |
socklen_t len; | |
len = sizeof(value); | |
//get so_error to check connect be RST or not | |
getsockopt(netctx->sock, SOL_SOCKET, SO_ERROR, &value, &len); | |
lwm2m_printf("get SO_ERROR= %d\r\n",value); | |
lwm2m_printf("socket sendto [%s:%d] failed.\r\n",inet_ntoa(*(struct in_addr*)&saddr.sin_addr.s_addr),ntohs(saddr.sin_port)); | |
return -1; | |
}else{ | |
lwm2m_printf("socket sendto [%s:%d] %d bytes\r\n",inet_ntoa(*(struct in_addr*)&saddr.sin_addr.s_addr),ntohs(saddr.sin_port),nbSent); | |
} | |
offset += nbSent; | |
} | |
return CIS_RET_OK; | |
} | |
cis_ret_t cisnet_read(cisnet_t netctx,uint8_t** buffer,uint32_t *length) | |
{ | |
Lwm2mMutexLock(); | |
if(netctx->g_packetlist != NULL){ | |
struct st_net_packet* delNode; | |
*buffer = netctx->g_packetlist->buffer; | |
*length = netctx->g_packetlist->length; | |
delNode =netctx->g_packetlist; | |
netctx->g_packetlist = netctx->g_packetlist->next; | |
cis_free(delNode); | |
Lwm2mMutexUnlock(); | |
return CIS_RET_OK; | |
} | |
Lwm2mMutexUnlock(); | |
return CIS_RET_ERROR; | |
} | |
cis_ret_t cisnet_free(cisnet_t netctx,uint8_t* buffer,uint32_t length) | |
{ | |
UNUSED(netctx); | |
UNUSED(length); | |
cis_free(buffer); | |
return CIS_RET_ERROR; | |
} | |
static int prvCreateSocket(uint16_t localPort,int ai_family) | |
{ | |
struct sockaddr_in addr; | |
int sock; | |
sock = socket(AF_INET, SOCK_DGRAM, 0); | |
if (sock < 0){ | |
return -1; | |
} | |
if(localPort>0){ | |
addr.sin_family = ai_family; | |
addr.sin_port = htons(localPort); | |
addr.sin_addr.s_addr = htonl(INADDR_ANY); | |
if(bind(sock,(struct sockaddr*)&addr,sizeof(struct sockaddr)) != 0){ | |
close(sock); | |
lwm2m_printf("socket bind failed\r\n"); | |
return -1; | |
} | |
} | |
return sock; | |
} | |
extern struct miplContext lwm2m_context; | |
void *lwm2m_recv_thread(void* argv) | |
{ | |
cisnet_t netctx=(cisnet_t)argv; | |
char *buf=NULL; | |
int fdmax, bytes; | |
fd_set read_fds; | |
struct sockaddr_in addr; | |
socklen_t addrlen; | |
int result; | |
int sock = -1; | |
sock = netctx->sock; | |
fdmax = sock+1; | |
//struct timeval tv = {5,0}; | |
lwm2m_printf("%s, trigger recv data, get sock %d\r\n",__func__,netctx->sock); | |
if(netctx->sock <= 0){ | |
lwm2m_printf("%s, trigger recv data failed: sock is invalid\r\n",__func__); | |
return NULL; | |
} | |
buf = (char *)cis_malloc(MAX_PACKET_SIZE); | |
if(buf == NULL){ | |
lwm2m_assert(0); | |
} | |
while (0 == netctx->quit && netctx->state == 1) { | |
FD_ZERO(&read_fds); | |
FD_SET(sock, &read_fds); | |
//result = select(fdmax, &read_fds, NULL, NULL, &tv); | |
result = select(fdmax, &read_fds, NULL, NULL, NULL); | |
lwm2m_printf("%s, select result: %d, g_sock=%d\r\n", __FUNCTION__,result,sock); | |
if (result <0) { | |
lwm2m_printf("%s, select error\r\n", __FUNCTION__); | |
//OSATaskSleep(200); | |
}else if(result >0){ | |
//if (FD_ISSET(sock, &read_fds) && (g_sock>0)){ | |
if (FD_ISSET(sock, &read_fds)){ | |
addrlen = sizeof(addr); | |
bytes = recvfrom(sock, buf, MAX_PACKET_SIZE, 0, (struct sockaddr*)&addr, &addrlen); | |
if (bytes < 0) | |
{ | |
lwm2m_printf("Error in recvfrom():\r\n"); | |
pthread_mutex_lock(&lwm2m_context.mutex); | |
pthread_cond_signal(&lwm2m_context.cond); | |
pthread_mutex_unlock(&lwm2m_context.mutex); | |
continue; | |
} | |
else if (bytes > 0) | |
{ | |
uint8_t* data = (uint8_t*)cis_malloc(bytes); | |
memcpy(data,buf,bytes); | |
struct st_net_packet *packet = (struct st_net_packet*)cis_malloc(sizeof(struct st_net_packet)); | |
packet->next = NULL; | |
packet->buffer = data; | |
packet->length = bytes; | |
Lwm2mMutexLock(); | |
netctx->g_packetlist = (struct st_net_packet*)CIS_LIST_ADD_new(netctx->g_packetlist,packet); | |
Lwm2mMutexUnlock(); | |
lwm2m_printf("%d bytes received from [%s]:%d\r\n", bytes, inet_ntoa(*(struct in_addr*)&addr.sin_addr.s_addr), ntohs(addr.sin_port)); | |
pthread_mutex_lock(&lwm2m_context.mutex); | |
pthread_cond_signal(&lwm2m_context.cond); | |
pthread_mutex_unlock(&lwm2m_context.mutex); | |
} | |
} | |
} | |
} | |
cis_free(buf); | |
return NULL; | |
} | |