blob: 9be2e3fd7f6c70bf861cdeca35ec2e481db26758 [file] [log] [blame]
#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;
}