TI's mqtt.
platform/cc31xx_sl_net.cpp
- Committer:
- dflet
- Date:
- 2015-06-06
- Revision:
- 1:673880ad39ad
- Parent:
- 0:698866e331b2
File content as of revision 1:673880ad39ad:
/****************************************************************************** * * Copyright (C) 2014 Texas Instruments Incorporated * * All rights reserved. Property of Texas Instruments Incorporated. * Restricted rights to use, duplicate or disclose this code are * granted through contract. * * The program may not be used without the written permission of * Texas Instruments Incorporated or against the terms and conditions * stipulated in the agreement under which this program has been supplied, * and under no circumstances can it be used with non-TI connectivity device. * ******************************************************************************/ //#include "mbed.h" #include "cc3100_simplelink.h" #include "cc3100_sl_common.h" #include "cc31xx_sl_net.h" #include "sl_mqtt_client.h" #include "mqtt_client.h" #include "cc3200_platform.h" #include "cc3100.h" #include "fPtr_func.h" #include "myBoardInit.h" #include "cli_uart.h" #define PRINT_BUF_LEN 128 extern int8_t print_buf[PRINT_BUF_LEN]; using namespace mbed_cc3100; #if (THIS_BOARD == MBED_BOARD_LPC1768) cc3100 _cc3100_module_(p16, p17, p9, p10, p8, SPI(p5, p6, p7));//LPC1768 irq, nHib, cs, mosi, miso, sck //cc3100 _cc3100_module_(p9, p10, p8, SPI(p11, p12, p13));//LPC1768 irq, nHib, cs, mosi, miso, sck #elif (THIS_BOARD == Seeed_Arch_Max) class cc3100 _cc3100_module_(PE_5, PE_4, PE_6, SPI(PB_5, PB_4, PB_3)); #elif (THIS_BOARD == ST_MBED_NUCLEOF103) class cc3100 _cc3100_module_(PA_9, PC_7, PB_6, SPI(PA_7, PA_6, PA_5));//nucleoF103 irq, nHib, cs, mosi, miso, sck #elif (THIS_BOARD == ST_MBED_NUCLEOF411) class cc3100 _cc3100_module_(PA_9, PC_7, PB_6, SPI(PA_7, PA_6, PA_5));//nucleoF411 irq, nHib, cs, mosi, miso, sck #elif (THIS_BOARD == ST_MBED_NUCLEOF401) class cc3100 _cc3100_module_(PA_8, PA_9, PC_7, PB_6, SPI(PA_7, PA_6, PA_5));//nucleoF401 irq, nHib, cs, mosi, miso, sck #elif (THIS_BOARD == EA_MBED_LPC4088) class cc3100 _cc3100_module_(p14, p15, p9, p10, p8, SPI(p5, p6, p7));//LPC4088 irq, nHib, cs, mosi, miso, sck #elif (THIS_BOARD == LPCXpresso4337) class cc3100 _cc3100_module_(P2_2, P3_5, P1_2, SPI(P1_4, P1_3, PF_4));//LPCXpresso4337 irq, nHib, cs, mosi, miso, sck #endif namespace mbed_mqtt { #ifdef DEBUG_NET_DEV extern int32_t (*debug_printf)(const char *fmt, ...); #define PRINTF(x,...) debug_printf(x,##__VA_ARGS__) #else #define PRINTF(x,...) #endif /* 3200 Devices specific Network Services Implementation */ #define LISTEN_QUE_SIZE 2 //***************************************************************************** // GLOBAL VARIABLES //***************************************************************************** //***************************************************************************** // STATIC FUNCTIONS //***************************************************************************** #ifdef DEBUG_NET_DEV static int32_t buf_printf(const uint8_t *buf, uint32_t len, uint32_t idt) { int32_t i = 0; for(i = 0; i < len; i++) { memset(print_buf, 0x00, PRINT_BUF_LEN); sprintf((char*) print_buf, "%02x ", *buf++); Uart_Write((uint8_t *) print_buf); if(0x03 == (i & 0x03)) Uart_Write((uint8_t *)" "); if(0x0F == (i & 0x0F)) { int32_t j = 0; Uart_Write((uint8_t *)"\n\r"); for(j = 0; j < idt; j++) Uart_Write((uint8_t *)" "); } } Uart_Write((uint8_t *)"\n\r"); return len; } #endif /*----------------------------------------------------------------------------- Open a TCP socket and modify its properties i.e security options if req. Socket properties modified in this function are based on the options set outside the scope of this function. Returns a valid handle on success, otherwise a negative number. -----------------------------------------------------------------------------*/ static int32_t create_socket(uint32_t nwconn_opts, struct secure_conn *nw_security_opts) { int32_t MqttSocketFd, Status; //local variables for creating secure socket uint8_t SecurityMethod; uint32_t SecurityCypher; int8_t i; //If TLS is required if ((nwconn_opts & DEV_NETCONN_OPT_SEC) != 0) // bit was set to 1 { MqttSocketFd = _cc3100_module_._socket.sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_SEC_SOCKET); if (MqttSocketFd < 0) { memset(print_buf, 0x00, PRINT_BUF_LEN); sprintf((char*) print_buf, "MqttSocketFd fail %i\r\n",MqttSocketFd); Uart_Write((uint8_t *) print_buf); return (MqttSocketFd); } SecurityMethod = *((uint8_t *) (nw_security_opts->method)); SecurityCypher = *((uint32_t *) (nw_security_opts->cipher)); if (nw_security_opts->n_file < 1 || nw_security_opts->n_file > 4 ) { Uart_Write((uint8_t*)"\n\r ERROR: security files missing or wrong number of security files\n\r"); Uart_Write((uint8_t*)"\n\r ERROR: Did not create socket\n\r"); return (-1); } //Set Socket Options that were just defined Status = _cc3100_module_._socket.sl_SetSockOpt(MqttSocketFd, SL_SOL_SOCKET, SL_SO_SECMETHOD, &SecurityMethod, sizeof(SecurityMethod)); if (Status < 0) { memset(print_buf, 0x00, PRINT_BUF_LEN); sprintf((char*) print_buf, "Status error %i socket closed\n\r",Status); Uart_Write((uint8_t *) print_buf); _cc3100_module_._socket.sl_Close(MqttSocketFd); return (Status); } Status = _cc3100_module_._socket.sl_SetSockOpt(MqttSocketFd, SL_SOL_SOCKET, SL_SO_SECURE_MASK, &SecurityCypher, sizeof(SecurityCypher)); if (Status < 0) { memset(print_buf, 0x00, PRINT_BUF_LEN); sprintf((char*) print_buf, "Status error %i socket closed\n\r",Status); Uart_Write((uint8_t *) print_buf); _cc3100_module_._socket.sl_Close(MqttSocketFd); return (Status); } if(nw_security_opts->n_file == 1){ Status = _cc3100_module_._socket.sl_SetSockOpt(MqttSocketFd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CA_FILE_NAME, nw_security_opts->files[0], strlen(nw_security_opts->files[0])); if (Status < 0) { memset(print_buf, 0x00, PRINT_BUF_LEN); sprintf((char*) print_buf, "Status error %i socket closed\n\r",Status); Uart_Write((uint8_t *) print_buf); _cc3100_module_._socket.sl_Close(MqttSocketFd); return (Status); } }else{ for(i=0; i<nw_security_opts->n_file;i++){ if(NULL != nw_security_opts->files[i]){ Status = _cc3100_module_._socket.sl_SetSockOpt(MqttSocketFd, SL_SOL_SOCKET, (SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME+i), nw_security_opts->files[i], strlen(nw_security_opts->files[i])); if (Status < 0) { memset(print_buf, 0x00, PRINT_BUF_LEN); sprintf((char*) print_buf, "Status error %i socket closed\n\r",Status); Uart_Write((uint8_t *) print_buf); _cc3100_module_._socket.sl_Close(MqttSocketFd); return (Status); } } } } } // If no TLS required else { // check to create a udp or tcp socket if ((nwconn_opts & DEV_NETCONN_OPT_UDP) != 0) // bit is set ; create a udp socket { MqttSocketFd = _cc3100_module_._socket.sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, SL_IPPROTO_UDP); } else // socket for tcp { MqttSocketFd = _cc3100_module_._socket.sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_IPPROTO_TCP); // consider putting 0 in place of SL_IPPROTO_TCP } } return (MqttSocketFd); } // end of function /*----------------------------------------------------------------------------- This function takes an ipv4 address in dot format i.e "a.b.c.d" and returns the ip address in Network byte Order, which can be used in connect call It returns 0, if a valid ip address is not detected. -----------------------------------------------------------------------------*/ static uint32_t svr_addr_NB_order_IPV4(char *svr_addr_str) { uint8_t addr[4]; int8_t i = 0; char *token; uint32_t svr_addr; int32_t temp; /*take a temporary copy of the string. strtok modifies the input string*/ int8_t svr_addr_size = strlen(svr_addr_str); char *svr_addr_cpy = (char*)malloc(svr_addr_size + 1); //1 for null if(NULL == svr_addr_cpy) return 0; strcpy(svr_addr_cpy, svr_addr_str); memset(print_buf, 0x00, PRINT_BUF_LEN); sprintf((char*) print_buf, "\n\r server address = %s\n\r", svr_addr_cpy); Uart_Write((uint8_t *) print_buf); memset(print_buf, 0x00, PRINT_BUF_LEN); sprintf((char*) print_buf, "\n\r server address string length = %d\n\r", strlen(svr_addr_cpy)); Uart_Write((uint8_t *) print_buf); /* get the first token */ token = strtok((char*)svr_addr_cpy, "."); /* walk through other tokens */ while (token != NULL) { temp = atoi((const char*)token); //check for invalid tokens or if already 4 tokens were obtained if ((temp < 0) || (temp > 255) || (i >= 4)) { free(svr_addr_cpy); return (0); } addr[i++] = (uint8_t) temp; token = strtok(NULL, "."); } // check if exactly 4 valid tokens are available or not if (i != 4) { free(svr_addr_cpy); return (0); } //form address if above test passed svr_addr = *((uint32_t *) &addr); free(svr_addr_cpy); return (svr_addr); } // end of function //***************************************************************************** // Network Services functions //***************************************************************************** /*----------------------------------------------------------------------------- Open a TCP socket with required properties Also connect to the server. Returns a valid handle on success, NULL on failure. -----------------------------------------------------------------------------*/ int32_t comm_open(uint32_t nwconn_opts, const char *server_addr, uint16_t port_number, const struct secure_conn *nw_security) { int32_t Status, MqttSocketFd; SlSockAddrIn_t LocalAddr; //address of the server to connect to int32_t LocalAddrSize; uint32_t uiIP; // create socket MqttSocketFd = create_socket(nwconn_opts, (struct secure_conn*) nw_security); if (MqttSocketFd < 0) { Uart_Write((uint8_t*)"\n\r ERROR: Could not create a socket.\n\r"); return -1; } if ((nwconn_opts & DEV_NETCONN_OPT_UDP) != 0) // bit is set ; create a udp socket { //filling the UDP server socket address LocalAddr.sin_family = SL_AF_INET; LocalAddr.sin_port = _cc3100_module_._socket.sl_Htons((unsigned short) port_number); LocalAddr.sin_addr.s_addr = 0; LocalAddrSize = sizeof(SlSockAddrIn_t); Status = _cc3100_module_._socket.sl_Bind(MqttSocketFd, (SlSockAddr_t *) &LocalAddr, LocalAddrSize); if (Status < 0) { // error Uart_Write((uint8_t*)"\n\r ERROR: Could not bind socket.\n\r"); _cc3100_module_._socket.sl_Close(MqttSocketFd); return -1; } } else // do tcp connection { // get the ip address of server to do tcp connect if ((nwconn_opts & DEV_NETCONN_OPT_URL) != 0) // server address is a URL { Status = _cc3100_module_._netapp.sl_NetAppDnsGetHostByName((uint8_t*) server_addr, strlen(server_addr), (uint32_t*) &uiIP, SL_AF_INET); if (Status < 0) { Uart_Write((uint8_t*)"\n\r ERROR: Could not resolve the ip address of the server \n\r"); return (-1); } // convert the address to network byte order as the function returns in host byte order uiIP = _cc3100_module_._socket.sl_Htonl(uiIP); } else // server address is a string in dot notation { if ((nwconn_opts & DEV_NETCONN_OPT_IP6) != 0) // server address is an IPV6 address string { Uart_Write((uint8_t*)"\n\r ERROR: Currently do not support IPV6 addresses \n\r"); return (-1); } else // address is an IPv4 string { // get the server ip address in Network Byte order uiIP = svr_addr_NB_order_IPV4((char*) server_addr); if (0 == uiIP) { Uart_Write((uint8_t*)"\n\r ERROR: Could not resolve the ip address of the server \n\r"); return (-1); } } } LocalAddr.sin_family = SL_AF_INET; LocalAddr.sin_addr.s_addr = uiIP; LocalAddr.sin_port = _cc3100_module_._socket.sl_Htons(port_number); LocalAddrSize = sizeof(SlSockAddrIn_t); // do tcp connect Status = _cc3100_module_._socket.sl_Connect(MqttSocketFd, (SlSockAddr_t *) &LocalAddr, LocalAddrSize); if (Status < 0) { if (SL_ESECSNOVERIFY != Status) { Uart_Write((uint8_t*)" \n\r ERROR: Could not establish connection to server.\n\r");Uart_Write((uint8_t*)" \n\r ERROR: Closing the socket.\n\r"); _cc3100_module_._socket.sl_Close(MqttSocketFd); return (-1); } else // SL_ESECSNOVERIFY == Status { Uart_Write((uint8_t*)" \n\r ERROR: Could not establish secure connection to server.\n\r");Uart_Write((uint8_t*)" \n\r Continuing with unsecure connection to server...\n\r"); } } // Success Uart_Write((uint8_t*)"\n\r Connected to server ....\n\r"); } // end of doing binding port to udp socket or doing tcp connect // set Timer for host processor platform_timer_init(); return (MqttSocketFd); } // end of function int32_t tcp_send(int32_t comm, const uint8_t *buf, uint32_t len, void *ctx) { int32_t Status; PRINTF("\n\r TCP send invoked for data with len %d\n\r", len);PRINTF("\n\r Sent Data : "); #ifdef DEBUG_NET_DEV buf_printf(buf, len, 0); #endif Status = _cc3100_module_._socket.sl_Send(comm, buf, len, 0); return (Status); } // end of function int32_t tcp_recv(int32_t comm, uint8_t *buf, uint32_t len, uint32_t wait_secs, bool *timed_out, void *ctx) { int32_t Status; int32_t MqttSocketFd = comm; #ifdef SOC_RCV_TIMEOUT_OPT // socket receive time out options SlTimeval_t timeVal; // recv time out options timeVal.tv_sec = wait_secs; // Seconds timeVal.tv_usec = 0; // Microseconds. 10000 microseconds resoultion /*------------------- setting receive timeout option on socket ---------------------*/ Status = _cc3100_module_._socket.sl_SetSockOpt(MqttSocketFd, SOL_SOCKET, SL_SO_RCVTIMEO, &timeVal, sizeof(timeVal)); if (Status == 0) { } else if (Status < 0) { Uart_Write((uint8_t*)"\n\r ERROR: setting socket recv_timeout_option unsuccessfull! \n\r"); } /*--------------end of setting receive timeout option on socket ---------------------*/ #endif // printf("\n\r TCP recv invoked ...\n\r"); *timed_out = 0; Status = _cc3100_module_._socket.sl_Recv(MqttSocketFd, buf, len, 0); if (Status > 0) { #ifdef DEBUG_NET_DEV buf_printf(buf, Status, 0); #endif } if (0 == Status) { Uart_Write((uint8_t*)"\n\r Connection Closed by peer....\n\r"); } if (SL_EAGAIN == Status) { Uart_Write((uint8_t*)"\n\r ERROR: Recv Time out error on server socket \n\r"); *timed_out = 1; } return (Status); } // end of function int32_t comm_close(int32_t comm) { int32_t Status; Status = _cc3100_module_._socket.sl_Close(comm); return (Status); } // end of function uint32_t rtc_secs(void) { return(platform_get_time_in_secs()); } // end of function //--------------------------- adding functions for server functionalities --------------------------- int32_t tcp_listen(uint32_t nwconn_info, uint16_t port_number, const struct secure_conn *nw_security) { SlSockAddrIn_t sLocalAddr; int32_t iSockID, iAddrSize; int32_t iStatus; //filling the TCP server socket address sLocalAddr.sin_family = SL_AF_INET; sLocalAddr.sin_port = _cc3100_module_._socket.sl_Htons(port_number); sLocalAddr.sin_addr.s_addr = 0; iAddrSize = sizeof(SlSockAddrIn_t); // creating a TCP socket iSockID = _cc3100_module_._socket.sl_Socket(SL_AF_INET, SL_SOCK_STREAM, 0); if (iSockID < 0) { // error return (-1); } // binding the TCP socket to the TCP server address iStatus = _cc3100_module_._socket.sl_Bind(iSockID, (SlSockAddr_t *) &sLocalAddr, iAddrSize); if (iStatus < 0) { // error _cc3100_module_._socket.sl_Close(iSockID); return (-1); } // putting the socket for listening to the incoming TCP connection iStatus = _cc3100_module_._socket.sl_Listen(iSockID, LISTEN_QUE_SIZE); if (iStatus < 0) { _cc3100_module_._socket.sl_Close(iSockID); return (-1); } memset(print_buf, 0x00, PRINT_BUF_LEN); sprintf((char*) print_buf, "\n\r\t Server Socket created and listening on port number: %d! \n\r", port_number); Uart_Write((uint8_t *) print_buf); return (iSockID); } // end of function int32_t tcp_select(int32_t *recv_cvec, int32_t *send_cvec, int32_t *rsvd_cvec, uint32_t wait_secs) { SlTimeval_t tv, *p_tv; SlFdSet_t rdfds; int32_t rd_idx = 0, wr_idx = 0, max_fd = 0; int32_t rv = 0; tv.tv_sec = wait_secs; tv.tv_usec = 0; p_tv = (0xFFFFFFFF != wait_secs) ? &tv : NULL; _cc3100_module_._socket.SL_FD_ZERO(&rdfds); while (-1 != recv_cvec[rd_idx]) { int32_t fd = recv_cvec[rd_idx++]; _cc3100_module_._socket.SL_FD_SET(fd, &rdfds); if (max_fd < fd){ max_fd = fd; } } // printf("Blocking network for (%s) %u secs to monitor %d fd(s)\n\r", // p_tv? "finite" : "forever", wait_secs, rd_idx); rv = _cc3100_module_._socket.sl_Select(max_fd + 1, &rdfds, NULL, NULL, p_tv); if (rv <= 0) { // printf("Select Failed %i\n\r",rv); return rv; } rd_idx = 0; while (-1 != recv_cvec[rd_idx]) { int32_t fd = recv_cvec[rd_idx++]; if (_cc3100_module_._socket.SL_FD_ISSET(fd, &rdfds)) recv_cvec[wr_idx++] = fd; } recv_cvec[wr_idx] = NULL; // printf("Number of sockets on which activity is observed = %d \n\r", wr_idx); return (wr_idx); } // end of function int32_t tcp_accept(int32_t listen_hnd, uint8_t *client_ip, uint32_t *ip_length) { int32_t new_fd; SlSockAddrIn_t client_addr = {0}; // client address SlSocklen_t cl_addr_size; cl_addr_size = sizeof(client_addr); new_fd = _cc3100_module_._socket.sl_Accept(listen_hnd, (SlSockAddr_t *) &client_addr, &cl_addr_size); if (new_fd < 0) { Uart_Write((uint8_t*)"\n\r ERROR: in accept \n\r"); return (NULL); } client_ip[0] = (client_addr.sin_addr.s_addr & 0xFF000000) >> 24; client_ip[1] = (client_addr.sin_addr.s_addr & 0x00FF0000) >> 16; client_ip[2] = (client_addr.sin_addr.s_addr & 0x0000FF00) >> 8; client_ip[3] = (client_addr.sin_addr.s_addr & 0x000000FF); *ip_length = 4; return new_fd; } // end of function //--------------------------- adding functions for udp functionalities --------------------------- int32_t send_dest(int32_t comm, const uint8_t *buf, uint32_t len, uint16_t dest_port, const uint8_t *dest_ip, uint32_t ip_len) { int32_t iSockID = (int32_t) comm; int32_t iStatus, iAddrSize; SlSockAddrIn_t sAddr; uint32_t uiDestIp; //get destination ip #if 0 uiDestIp = svr_addr_NB_order_IPV4((uint8_t*)dest_ip); //assuming a IPV4 address is passed in dot notation. if( 0 == uiDestIp ) { Uart_Write((uint8_t*)"\n\r ERROR: Could not resolve the ip address of the destination \n\r"); return(-1); } #else uiDestIp = (((uint32_t) dest_ip[0] << 24) | ((uint32_t) dest_ip[1] << 16) | (dest_ip[2] << 8) | (dest_ip[3])); // printf("Writing to %d, %08x\r\n", (int32_t)comm, uiDestIp); #endif //filling the UDP server socket address sAddr.sin_family = SL_AF_INET; sAddr.sin_port = _cc3100_module_._socket.sl_Htons((unsigned short) dest_port); sAddr.sin_addr.s_addr = _cc3100_module_._socket.sl_Htonl(uiDestIp); iAddrSize = sizeof(SlSockAddrIn_t); // sending packet iStatus = _cc3100_module_._socket.sl_SendTo(iSockID, buf, len, 0, (SlSockAddr_t *) &sAddr, iAddrSize); if (iStatus <= 0) { // error _cc3100_module_._socket.sl_Close(iSockID); Uart_Write((uint8_t*)"Error: Closed the UDP socket\n\r"); } return (iStatus); } // end of function int32_t recv_from(int32_t comm, uint8_t *buf, uint32_t len, uint16_t *from_port, uint8_t *from_ip, uint32_t *ip_len) { int32_t iSockID = (int32_t) comm; int32_t iStatus, iAddrSize; SlSockAddrIn_t fromAddr = {0}; iAddrSize = sizeof(SlSockAddrIn_t); iStatus = _cc3100_module_._socket.sl_RecvFrom(iSockID, buf, len, 0, (SlSockAddr_t *) &fromAddr, (SlSocklen_t*) &iAddrSize); if (iStatus < 0) { // error _cc3100_module_._socket.sl_Close(iSockID); Uart_Write((uint8_t*)"Error: Closed the UDP socket\n\r"); return (iStatus); } //else populate from ip, from_port and ip_len parameters // refer to comments in .h if (from_port) *from_port = fromAddr.sin_port; if (from_ip) { from_ip[0] = (fromAddr.sin_addr.s_addr & 0xFF000000) >> 24; from_ip[1] = (fromAddr.sin_addr.s_addr & 0x00FF0000) >> 16; from_ip[2] = (fromAddr.sin_addr.s_addr & 0x0000FF00) >> 8; from_ip[3] = (fromAddr.sin_addr.s_addr & 0x000000FF); *ip_len = 4; } return (iStatus); } // end of function }//namespace mbed_mqtt