/* * \brief Configure mesh network * */ void thread_tasklet_configure_and_connect_to_network(void) { int8_t status; link_configuration_s* temp_link_config=NULL; if (MBED_CONF_MBED_MESH_API_THREAD_DEVICE_TYPE == MESH_DEVICE_TYPE_THREAD_MINIMAL_END_DEVICE) { thread_tasklet_data_ptr->operating_mode = NET_6LOWPAN_HOST; } else if (MBED_CONF_MBED_MESH_API_THREAD_DEVICE_TYPE == MESH_DEVICE_TYPE_THREAD_SLEEPY_END_DEVICE) { thread_tasklet_data_ptr->operating_mode = NET_6LOWPAN_SLEEPY_HOST; } else { thread_tasklet_data_ptr->operating_mode = NET_6LOWPAN_ROUTER; } arm_nwk_interface_configure_6lowpan_bootstrap_set( thread_tasklet_data_ptr->nwk_if_id, thread_tasklet_data_ptr->operating_mode, NET_6LOWPAN_THREAD); thread_tasklet_data_ptr->channel_list.channel_page = (channel_page_e)MBED_CONF_MBED_MESH_API_THREAD_CONFIG_CHANNEL_PAGE; thread_tasklet_data_ptr->channel_list.channel_mask[0] = MBED_CONF_MBED_MESH_API_THREAD_CONFIG_CHANNEL_MASK; TRACE_DETAIL("channel page: %d", thread_tasklet_data_ptr->channel_list.channel_page); TRACE_DETAIL("channel mask: 0x%.8lx", thread_tasklet_data_ptr->channel_list.channel_mask[0]); // PSKd const char PSKd[] = MBED_CONF_MBED_MESH_API_THREAD_PSKD; MBED_ASSERT(sizeof(PSKd) > 5 && sizeof(PSKd) < 33); char *dyn_buf = ns_dyn_mem_alloc(sizeof(PSKd)); strcpy(dyn_buf, PSKd); ns_dyn_mem_free(device_configuration.PSKd_ptr); device_configuration.PSKd_ptr = (uint8_t*)dyn_buf; device_configuration.PSKd_len = sizeof(PSKd) - 1; if (true == MBED_CONF_MBED_MESH_API_THREAD_USE_STATIC_LINK_CONFIG) { read_link_configuration(); temp_link_config = &thread_tasklet_data_ptr->link_config; } thread_management_node_init(thread_tasklet_data_ptr->nwk_if_id, &thread_tasklet_data_ptr->channel_list, &device_configuration, temp_link_config); status = arm_nwk_interface_up(thread_tasklet_data_ptr->nwk_if_id); if (status >= 0) { thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_STARTED; tr_info("Start Thread bootstrap (%s mode)", thread_tasklet_data_ptr->operating_mode == NET_6LOWPAN_SLEEPY_HOST ? "SED" : "Router"); } else { thread_tasklet_data_ptr->tasklet_state = TASKLET_STATE_BOOTSTRAP_FAILED; tr_err("Bootstrap start failed, %d", status); thread_tasklet_network_state_changed(MESH_BOOTSTRAP_START_FAILED); } }
void CStdUtilsTestDlg::OnTestStrings() { unsigned char iUChar = 1; unsigned short iUShort=5; int iInt = 10; long lLong = 15; float fltFloat = (float) 5.3; double dblDouble = 7.5; bool bBool = true; try { // LOG_TEMP(StdLogInfo, "Test Val %d, Float: %f", 5403, dblDouble); CStdString strVal; strVal = (int) iUChar; strVal = iUShort; strVal = iInt; strVal = lLong; strVal = fltFloat; strVal = dblDouble; CStdString strUShort(iUShort), strInt(iInt), strLong(lLong); CStdString strFloat(fltFloat), strDouble(dblDouble); CStdString strTest1("The Test value is : "); CStdString strTest2(" Is the test value."); strVal = strTest1 + STR(iInt); strVal = strTest1 + STR(lLong); strVal = strTest1 + STR(fltFloat); strVal = strTest1 + STR(dblDouble); strVal = STR(iInt) + strTest2; strVal = STR(lLong) + strTest2; strVal = STR(fltFloat) + strTest2; strVal = STR(dblDouble) + strTest2; strVal = "This is a test: " + STR(iInt); strVal = "This is a test: " + STR(lLong); strVal = "This is a test: " + STR(fltFloat); strVal = "This is a test: " + STR(bBool); strVal = "This is a test: " + STR("100"); TRACE_INFO("This is a test. Test Value: " + STR(lLong)); TRACE_DETAIL("Fitness: " + STR(fltFloat)); strVal = "This is a test: " + FSTR("%5.2f", fltFloat); Test1(); } catch(CStdErrorInfo oError) { CStdString strError = oError.Log(); CString strMSError = strError.c_str(); AfxMessageBox(strMSError); } catch(...) {AfxMessageBox("Unidentified Error");} }
void read_link_configuration() { thread_tasklet_data_ptr->link_config.panId = MBED_CONF_MBED_MESH_API_THREAD_CONFIG_PANID; TRACE_DETAIL("PANID %x", thread_tasklet_data_ptr->link_config.panId); thread_tasklet_data_ptr->link_config.rfChannel = MBED_CONF_MBED_MESH_API_THREAD_CONFIG_CHANNEL; TRACE_DETAIL("channel: %d", thread_tasklet_data_ptr->link_config.rfChannel); // Mesh prefix const uint8_t mesh_local_prefix[] = MBED_CONF_MBED_MESH_API_THREAD_CONFIG_ML_PREFIX; MBED_ASSERT(sizeof(mesh_local_prefix) == 8); memcpy(thread_tasklet_data_ptr->link_config.mesh_local_ula_prefix, mesh_local_prefix, 8); TRACE_DETAIL("Mesh prefix: %s", trace_array(mesh_local_prefix, 8)); // Master Key const uint8_t master_key[] = MBED_CONF_MBED_MESH_API_THREAD_MASTER_KEY; MBED_ASSERT(sizeof(master_key) == 16); memcpy(thread_tasklet_data_ptr->link_config.master_key, master_key, 16); // PSKc const uint8_t PSKc[] = MBED_CONF_MBED_MESH_API_THREAD_CONFIG_PSKC; MBED_ASSERT(sizeof(PSKc) == 16); memcpy(thread_tasklet_data_ptr->link_config.PSKc, PSKc, 16); thread_tasklet_data_ptr->link_config.key_rotation = 3600; thread_tasklet_data_ptr->link_config.key_sequence = 0; thread_tasklet_data_ptr->link_config.securityPolicy = MBED_CONF_MBED_MESH_API_THREAD_SECURITY_POLICY; // network name MBED_ASSERT(strlen(MBED_CONF_MBED_MESH_API_THREAD_CONFIG_NETWORK_NAME) > 0 && strlen(MBED_CONF_MBED_MESH_API_THREAD_CONFIG_NETWORK_NAME) < 17); memcpy(thread_tasklet_data_ptr->link_config.name, MBED_CONF_MBED_MESH_API_THREAD_CONFIG_NETWORK_NAME, strlen(MBED_CONF_MBED_MESH_API_THREAD_CONFIG_NETWORK_NAME)); thread_tasklet_data_ptr->link_config.timestamp = MBED_CONF_MBED_MESH_API_THREAD_CONFIG_COMMISSIONING_DATASET_TIMESTAMP; // extended pan-id const uint8_t extented_panid[] = MBED_CONF_MBED_MESH_API_THREAD_CONFIG_EXTENDED_PANID; MBED_ASSERT(sizeof(extented_panid) == 8); memcpy(thread_tasklet_data_ptr->link_config.extented_pan_id, extented_panid, sizeof(extented_panid)); }
/** * @brief Closes connection on the given transport CB * * @param *tprt_cb Transport Control Block whose connection is to be closed (#HM_TRANSPORT_CB) * @return #HM_OK if successful, else #HM_ERR */ int32_t hm_tprt_close_connection(HM_TRANSPORT_CB *tprt_cb) { /***************************************************************************/ /* Variable Declarations */ /***************************************************************************/ int32_t ret_val = HM_OK; HM_MSG *msg = NULL; HM_LIST_BLOCK *block = NULL; /***************************************************************************/ /* Sanity Checks */ /***************************************************************************/ TRACE_ENTRY(); TRACE_ASSERT(tprt_cb != NULL); /***************************************************************************/ /* Main Routine */ /***************************************************************************/ /***************************************************************************/ /* Empty the outgoing buffers queue. Don't try to send them, just drop. */ /***************************************************************************/ TRACE_DETAIL(("Emptying pending queue.")); for(block = (HM_LIST_BLOCK *)HM_NEXT_IN_LIST(tprt_cb->pending); block != NULL; block = (HM_LIST_BLOCK *)HM_NEXT_IN_LIST(tprt_cb->pending)) { msg = (HM_MSG *)block->target; /***************************************************************************/ /* Remove from list. */ /***************************************************************************/ HM_REMOVE_FROM_LIST(block->node); TRACE_DETAIL(("Freeing Message!")); hm_free_buffer(msg); free(block); block = NULL; } if(tprt_cb->in_buffer != NULL) { TRACE_DETAIL(("Transport has data in its input buffers. Freeing!")); hm_free_buffer((HM_MSG *)tprt_cb->in_buffer); tprt_cb->in_buffer = NULL; } /***************************************************************************/ /* Transport Types may differ. Default is Socket Based Transport. So, we're*/ /* currently only implementing the default case. */ /***************************************************************************/ switch(tprt_cb->type) { default: /***************************************************************************/ /* It is possible that the socket connection was torn down before, or never*/ /* existed in the first place. */ /***************************************************************************/ if(tprt_cb->sock_cb != NULL) { TRACE_DETAIL(("Closing socket connections")); hm_close_sock_connection(tprt_cb->sock_cb); tprt_cb->sock_cb = NULL; } } /***************************************************************************/ /* Exit Level Checks */ /***************************************************************************/ TRACE_EXIT(); return(ret_val); }/* hm_tprt_close_connection */
/** * @brief Receives data from socket * * @param sock_fd Socket Descriptor on which to receive data * @param sock_type Type of socket to determine method of receiving * @param *msg_buffer Message Buffer into which data must be written * @param length Length of buffer * @param **src_addr A @c SOCKADDR type of structure where incoming connection * parameters will be written if connection is Datagram based. * * @return Total bytes read from the socket */ int32_t hm_tprt_recv_on_socket(uint32_t sock_fd , uint32_t sock_type, BYTE * msg_buffer, uint32_t length, SOCKADDR **src_addr) { /***************************************************************************/ /* Local variables */ /***************************************************************************/ int32_t total_bytes_rcvd=0; uint32_t bytes_rcvd=0; int32_t os_error; int32_t op_complete = FALSE; BYTE *buf = msg_buffer; SOCKADDR_IN * ip_addr = NULL; extern fd_set hm_tprt_conn_set; socklen_t len = sizeof(SOCKADDR); TRACE_ENTRY(); TRACE_ASSERT(msg_buffer != NULL); /***************************************************************************/ /* Now try to receive data */ /***************************************************************************/ if(src_addr != NULL) { *src_addr = NULL; } do { TRACE_DETAIL(("Try to receive %d bytes on Socket %d", (length - bytes_rcvd), sock_fd)); if(sock_type==HM_TRANSPORT_SOCK_TYPE_TCP) { TRACE_DETAIL(("TCP Socket")); bytes_rcvd = recv(sock_fd, buf, (length - bytes_rcvd), 0); } else if(sock_type==HM_TRANSPORT_SOCK_TYPE_UDP) { TRACE_DETAIL(("UDP Socket")); ip_addr = (SOCKADDR_IN*)malloc(sizeof(SOCKADDR_IN)); if(ip_addr == NULL) { TRACE_ERROR(("Error allocating memory for incoming Address")); op_complete = TRUE; bytes_rcvd = 0; break; } bytes_rcvd = recvfrom(sock_fd, buf, (length - bytes_rcvd), 0, (struct sockaddr *)ip_addr , &len); /***************************************************************************/ /* Do we need to fetch the sender IP information too, from the socket? */ /* or will they tell it themselves? */ /* In some upper layer structure? */ /***************************************************************************/ //FIXME: So far, they're not telling, so we need to get it here. { char net_addr[128]; int32_t length = 128; inet_ntop(AF_INET, &ip_addr->sin_addr, net_addr, length); TRACE_DETAIL(("%s:%d", net_addr, ntohs(ip_addr->sin_port))); } } if(bytes_rcvd == length) { TRACE_DETAIL(("Message received in full")); #if 0 #ifdef I_WANT_TO_DEBUG { uint32_t debug_length; TRACE_INFO(("Buffer:")); for(debug_length=0; debug_length<length; debug_length++) { TRACE_INFO(("%02X", *((unsigned char *)buf+debug_length))); } } #endif #endif buf = NULL; op_complete = TRUE; total_bytes_rcvd +=bytes_rcvd; break; } else if (bytes_rcvd == -1) { /***********************************************************************/ /* An error was returned - check for retryable socket error values. */ /***********************************************************************/ TRACE_PERROR(("Recv failed on socket")); os_error = errno; if ((os_error == EWOULDBLOCK)) { /*********************************************************************/ /* This seems to be a flow control condition - clear the bytes sent */ /* value to show that no data was written. */ /*********************************************************************/ TRACE_WARN(("Resource shortage - try again")); bytes_rcvd = 0; } else if (os_error == EINTR) { TRACE_WARN(("Receive interrupted - loop round again")); bytes_rcvd = 0; } else { /*********************************************************************/ /* Socket failed so work source needs to be unregistered. */ /*********************************************************************/ TRACE_ERROR(("Socket failed")); FD_CLR(sock_fd, &hm_tprt_conn_set); op_complete = TRUE; bytes_rcvd = 0; break; } } else if(bytes_rcvd == 0) { TRACE_WARN(("The peer has disconnected")); op_complete = TRUE; FD_CLR(sock_fd, &hm_tprt_conn_set); total_bytes_rcvd = HM_ERR; break; } else { TRACE_INFO(("%d bytes received. Returning.", bytes_rcvd)); op_complete = TRUE; break; } /***************************************************************************/ /* Advance current pointer to remaining part of data */ /***************************************************************************/ buf += bytes_rcvd; total_bytes_rcvd +=bytes_rcvd; } while(total_bytes_rcvd< length); if(op_complete == TRUE) { if(total_bytes_rcvd == length) { TRACE_DETAIL(("Message received in full")); buf = NULL; } else { TRACE_WARN(("Some error happened")); buf = NULL; total_bytes_rcvd = bytes_rcvd; } } #ifdef I_WANT_TO_DEBUG if(ip_addr != NULL) { if(src_addr== NULL) { TRACE_WARN(( "UDP/Multicast UDP port was specified but address to fill sender addr was not given" )); } TRACE_ASSERT(src_addr!=NULL); } #endif if(src_addr != NULL) { *src_addr = (SOCKADDR *)ip_addr; } TRACE_EXIT(); return (total_bytes_rcvd); } /* hm_tprt_recv_on_socket */
/** * @brief Send Message on Socket * * @param *ip a @t< struct sockaddr @t type of structure to which data must be sent. * @param sock_fd Socket Descriptor on which to send data * @param sock_type Type of socket to determine sending mechanism * @param *msg_buffer A byte buffer to be sent * @param length Length of data to be sent from @p msg_buffer * * @return Total number of bytes sent */ int32_t hm_tprt_send_on_socket(struct sockaddr* ip,int32_t sock_fd, uint32_t sock_type,BYTE *msg_buffer, uint32_t length ) { /***************************************************************************/ /* Local variables */ /***************************************************************************/ int32_t total_bytes_sent=0; int32_t bytes_sent=0; int32_t success = FALSE; BYTE *buf = NULL; int32_t os_error; #ifdef I_WANT_TO_DEBUG char temp[129]; #endif TRACE_ENTRY(); TRACE_DETAIL(("Socket type %d", sock_type)); TRACE_DETAIL(("Attempt to send %d bytes of data on socket %d", length, sock_fd)); buf = msg_buffer; do { if((sock_type== HM_TRANSPORT_TCP_IN) || (sock_type==HM_TRANSPORT_TCP_OUT)) { TRACE_DETAIL(("data to be sent on TCP connection ")); bytes_sent = send(sock_fd, buf, (length - bytes_sent), 0); } else if(sock_type==HM_TRANSPORT_UDP) { TRACE_DETAIL(("Data to be sent on UDP Ucast connection ")); bytes_sent = sendto(sock_fd, buf, (length - bytes_sent), 0, ip, sizeof(struct sockaddr)); } else if(sock_type==HM_TRANSPORT_MCAST) { TRACE_DETAIL(("Data to be sent on UDP Mcast connection ")); #ifdef I_WANT_TO_DEBUG { char address_value[128]; HM_SOCKADDR_UNION addr; socklen_t addrlen = sizeof(addr); getsockname(sock_fd, &addr.sock_addr, &addrlen); inet_ntop(addr.in_addr.sin_family, &addr.in_addr.sin_addr, address_value, sizeof(address_value)); TRACE_INFO(("Address value: %s:%d",address_value, ntohs(addr.in_addr.sin_port))); TRACE_INFO(("Family: %d", addr.in_addr.sin_family)); } TRACE_DETAIL(("Send to %s:%d", inet_ntop(((SOCKADDR_IN *)ip)->sin_family, &((SOCKADDR_IN *)ip)->sin_addr, temp, sizeof(temp)), ntohs(((SOCKADDR_IN *)ip)->sin_port))); TRACE_DETAIL(("Family: %d",((SOCKADDR_IN *)ip)->sin_family)); #endif bytes_sent = sendto(sock_fd, buf, (length - bytes_sent), 0, ip, sizeof(struct sockaddr)); } if(bytes_sent == length) { TRACE_DETAIL(("Message sent in full")); buf = NULL; success = TRUE; total_bytes_sent +=bytes_sent; break; } else if (bytes_sent == -1) { /***********************************************************************/ /* An error was returned - check for retryable socket error values. */ /***********************************************************************/ os_error = errno; TRACE_PERROR(("Send failed on socket %d.",sock_fd)); if ((os_error == EWOULDBLOCK) || (os_error == ENOMEM) || (os_error == ENOSR)) { /*********************************************************************/ /* This seems to be a flow control condition - clear the bytes sent */ /* value to show that no data was written. */ /*********************************************************************/ TRACE_WARN(("Resource shortage - try again")); bytes_sent = 0; } else if (os_error == EINTR) { TRACE_WARN(("Send interrupted - loop round again")); bytes_sent = 0; } else { /*********************************************************************/ /* Socket failed so work source needs to be unregistered. */ /*********************************************************************/ TRACE_ERROR(("Socket failed")); success = HM_ERR; break; } } /***************************************************************************/ /* Advance current pointer to remaining part of data */ /***************************************************************************/ buf += bytes_sent; total_bytes_sent +=bytes_sent; } while(total_bytes_sent< length); if(total_bytes_sent == length) { TRACE_DETAIL(("Message sent in full")); success = TRUE; } TRACE_EXIT(); return (success); } /* hm_tprt_send_on_socket */
/** * @brief Opens a Non-Blocking Socket * * @param *res a @t< struct addrinfo @t type of address structure containing parameters of connection * @param **saptr @c SOCKADDR type structure to write the @sockaddr structure into * @param *lenp Length of @p saptr structure (to distinguish @sockaddr_in from @sockaddr_in6 * * @return Descriptor of socket if successful, -1 otherwise */ static int32_t hm_open_socket(struct addrinfo *res, SOCKADDR **saptr, socklen_t *lenp) { /***************************************************************************/ /* Variable Declarations */ /***************************************************************************/ int32_t sock_fd = -1; int32_t val; int32_t option_val; /***************************************************************************/ /* Sanity Checks */ /***************************************************************************/ TRACE_ENTRY(); TRACE_ASSERT(res != NULL); /***************************************************************************/ /* Main Routine */ /***************************************************************************/ do { sock_fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sock_fd >= 0) { TRACE_DETAIL(("Got socket.")); break; } } while((res = res->ai_next) != NULL); if(res == NULL) { TRACE_PERROR(("Error opening socket!")); sock_fd = -1; goto EXIT_LABEL; } /***************************************************************************/ /* Socket Opened. Now set its options */ /***************************************************************************/ TRACE_DETAIL(("Setting the socket to non-blocking mode")); val = fcntl(sock_fd, F_GETFL, 0); val = fcntl(sock_fd, F_SETFL, val | O_NONBLOCK); if (val == -1) { TRACE_PERROR(("Error setting socket to non-blocking mode")); close(sock_fd); sock_fd = -1; goto EXIT_LABEL; } //end if val == -1 /***************************************************************************/ /* Allow the descriptors to be reusable */ /***************************************************************************/ option_val = (int)TRUE; /*************************************************************/ /* Allow socket descriptor to be reuseable */ /*************************************************************/ TRACE_DETAIL(("Setting socket descriptor as reusable")); val = setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&option_val, sizeof(option_val)); if (val < 0) { TRACE_PERROR(("Error settting socket descriptor to reusable")); close(sock_fd); sock_fd = -1; goto EXIT_LABEL; } /***************************************************************************/ /* Add the descriptor to global descriptor set */ /***************************************************************************/ if(max_fd < sock_fd) { TRACE_DETAIL(("Update maximum socket descriptor value to %d", sock_fd)); max_fd = sock_fd; } TRACE_DETAIL(("Add FD to set")); FD_SET(sock_fd, &hm_tprt_conn_set); *saptr = malloc(res->ai_addrlen); if(*saptr == NULL) { TRACE_ERROR(("Error allocating memory for address structure.")); close(sock_fd); sock_fd = -1; goto EXIT_LABEL; } memcpy(*saptr, res->ai_addr, res->ai_addrlen); *lenp = res->ai_addrlen; EXIT_LABEL: /***************************************************************************/ /* Exit Level Checks */ /***************************************************************************/ TRACE_EXIT(); return sock_fd; }/* hm_open_socket */
/** * @brief Creates a non-blocking socket and returns its descriptor. * * @param conn_type Type of connection to be opened * @param *params Structure containing paramters of request for destination. * * @return Socket CB (#HM_SOCKET_CB) of the connection opened, else @c NULL */ HM_SOCKET_CB * hm_tprt_open_connection(uint32_t conn_type, void * params ) { /***************************************************************************/ /* Descriptor of the socket created. Default value denotes error condition */ /***************************************************************************/ int32_t sock_fd = -1; int32_t val; int32_t option_val = 1; socklen_t length; HM_SOCKET_CB *sock_cb = NULL; HM_INET_ADDRESS *address = params; struct ip_mreq mreq; char mcast_addr[129]; int32_t mcast_group = HM_MCAST_BASE_ADDRESS; /* Base value */ char target[128], service[128]; int32_t ret_val = HM_OK; struct addrinfo hints, *res, *ressave; HM_SOCKADDR_UNION *mcast_cast = NULL, *addr = NULL; TRACE_ENTRY(); TRACE_ASSERT(params != NULL); /***************************************************************************/ /* Create a socket control block */ /***************************************************************************/ sock_cb = hm_alloc_sock_cb(); if(sock_cb == NULL) { TRACE_ERROR(("Resource allocation failed for socket control block")); ret_val = HM_ERR; goto EXIT_LABEL; } /***************************************************************************/ /* Depending on the connection type, determine the sockaddr strcuture */ switch(conn_type) { case HM_TRANSPORT_TCP_LISTEN: TRACE_INFO(("IPv4 Listen Socket")); hints.ai_family = AF_INET; hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; inet_ntop(hints.ai_family, &((SOCKADDR_IN *)params)->sin_addr, target, sizeof(target)); snprintf(service, sizeof(service), "%d", ntohs(((SOCKADDR_IN *)params)->sin_port)); break; case HM_TRANSPORT_TCP_OUT: TRACE_INFO(("IPv4 Outgoing Socket")); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV; inet_ntop(hints.ai_family, &((SOCKADDR_IN *)params)->sin_addr, target, sizeof(target)); snprintf(service, sizeof(service), "%d", ntohs(((SOCKADDR_IN *)params)->sin_port)); break; case HM_TRANSPORT_TCP_IN: TRACE_INFO(("IPv4 Incoming Socket")); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; break; case HM_TRANSPORT_UDP: TRACE_INFO(("IPv4 UDP Socket")); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; inet_ntop(hints.ai_family, &((SOCKADDR_IN *)params)->sin_addr, target, sizeof(target)); snprintf(service, sizeof(service), "%d", ntohs(((SOCKADDR_IN *)params)->sin_port)); break; case HM_TRANSPORT_MCAST: TRACE_INFO(("IPv4 Multicast Socket")); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; inet_ntop(hints.ai_family, &((SOCKADDR_IN *)params)->sin_addr, target, sizeof(target)); snprintf(service, sizeof(service), "%d", ntohs(((SOCKADDR_IN *)params)->sin_port)); break; case HM_TRANSPORT_SCTP: TRACE_INFO(("IPv4 SCTP Socket")); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_SCTP; inet_ntop(hints.ai_family, &((SOCKADDR_IN *)params)->sin_addr, target, sizeof(target)); snprintf(service, sizeof(service), "%d", ntohs(((SOCKADDR_IN *)params)->sin_port)); break; case HM_TRANSPORT_TCP_IPv6_LISTEN: TRACE_INFO(("IPv6 Listen Socket")); hints.ai_family = AF_INET6; hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; inet_ntop(hints.ai_family, &((SOCKADDR_IN6 *)params)->sin6_addr, target, sizeof(target)); snprintf(service, sizeof(service), "%d", ntohs(((SOCKADDR_IN6 *)params)->sin6_port)); break; case HM_TRANSPORT_TCP_IPv6_OUT: TRACE_INFO(("IPv6 I/O Socket")); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; inet_ntop(hints.ai_family, &((SOCKADDR_IN6 *)params)->sin6_addr, target, sizeof(target)); snprintf(service, sizeof(service), "%d", ntohs(((SOCKADDR_IN6 *)params)->sin6_port)); break; case HM_TRANSPORT_TCP_IPv6_IN: TRACE_INFO(("IPv6 I/O Socket")); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; break; case HM_TRANSPORT_UDP_IPv6: TRACE_INFO(("IPv6 UDP Socket")); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; inet_ntop(hints.ai_family, &((SOCKADDR_IN6 *)params)->sin6_addr, target, sizeof(target)); snprintf(service, sizeof(service), "%d", ntohs(((SOCKADDR_IN6 *)params)->sin6_port)); break; case HM_TRANSPORT_MCAST_IPv6: TRACE_INFO(("IPv6 Multicast Socket")); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; inet_ntop(hints.ai_family, &((SOCKADDR_IN6 *)params)->sin6_addr, target, sizeof(target)); snprintf(service, sizeof(service), "%d", ntohs(((SOCKADDR_IN6 *)params)->sin6_port)); break; case HM_TRANSPORT_SCTP_IPv6: TRACE_INFO(("IPv6 SCTP Socket")); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; inet_ntop(hints.ai_family, &((SOCKADDR_IN6 *)params)->sin6_addr, target, sizeof(target)); snprintf(service, sizeof(service), "%d", ntohs(((SOCKADDR_IN6 *)params)->sin6_port)); break; default: TRACE_ERROR(("Unknown connection Type %d", conn_type)); TRACE_ASSERT(0==1); goto EXIT_LABEL; } switch(conn_type) { case HM_TRANSPORT_TCP_IN: case HM_TRANSPORT_TCP_IPv6_IN: TRACE_INFO(("Accept incoming connection")); goto EXIT_LABEL; default: TRACE_INFO(("One of Outgoing Connections Type %d", conn_type)); } /***************************************************************************/ /* If unsatisfactory, this code chunk may be replaced by a more elaborate */ /* memset(0) and filling of sin_addr structures. */ /***************************************************************************/ TRACE_DETAIL(("AI_FAMILY: %d", hints.ai_family)); TRACE_DETAIL(("Target: %s:%s", target, service)); if((conn_type != HM_TRANSPORT_MCAST)&&(conn_type != HM_TRANSPORT_MCAST_IPv6)) { TRACE_DETAIL(("Unicast Address")); if((ret_val = getaddrinfo(target, service, &hints, &res)) !=0) { TRACE_GAI_ERROR(("Error getting information on target %s:%s", target, service),ret_val); ret_val = HM_ERR; goto EXIT_LABEL; } ressave = res; /***************************************************************************/ /* Right now, we are only expecting a single address in response. */ /* Set appropriate socket options depending on the type of socket. */ /***************************************************************************/ TRACE_DETAIL(("Opening Socket")); sock_fd = hm_open_socket(res, (SOCKADDR **)&addr, &length); } else { TRACE_DETAIL(("Multicast Address")); if((ret_val = getaddrinfo(NULL, service, &hints, &res)) !=0) { TRACE_GAI_ERROR(("Error getting information on target %s:%s", target, service),ret_val); ret_val = HM_ERR; goto EXIT_LABEL; } ressave = res; TRACE_DETAIL(("Opening Socket")); sock_fd = hm_open_socket(res, (SOCKADDR **)&addr, &length); } if(sock_fd == -1) { TRACE_ERROR(("Error opening socket")); ret_val = HM_ERR; goto EXIT_LABEL; } TRACE_DETAIL(("Socket opened: %d", sock_fd)); TRACE_ASSERT(addr != NULL); /***************************************************************************/ /* Other specific options and processing. */ /***************************************************************************/ switch (conn_type) { case HM_TRANSPORT_TCP_LISTEN: /***************************************************************************/ /* Set SOCKOPTS to TCP_NODELAY to disable Nagle's algorithm */ /***************************************************************************/ val = setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, &option_val, sizeof(option_val)); if(val == -1) { TRACE_PERROR(("Error Setting TCP_NODELAY")); close(sock_fd); sock_fd = -1; goto EXIT_LABEL; } /***************************************************************************/ /* Bind to address */ /***************************************************************************/ TRACE_DETAIL(("Binding to address")); if(bind(sock_fd, &addr->sock_addr, length) != 0) { TRACE_PERROR(("Error binding to port")); close(sock_fd); sock_fd = -1; goto EXIT_LABEL; } TRACE_DETAIL(("Start Listen on Port")); if(listen(sock_fd, HM_MAX_PENDING_CONNECT_REQ) != 0) { TRACE_PERROR(("Listen on socket %d failed.", sock_fd)); close(sock_fd); sock_fd = -1; goto EXIT_LABEL; } sock_cb->sock_type = HM_TRANSPORT_SOCK_TYPE_TCP; break; case HM_TRANSPORT_TCP_OUT: TRACE_INFO(("Trying to connect")); if((val = connect(sock_fd, &addr->sock_addr, length))!=0) { if(errno == EINPROGRESS) { TRACE_DETAIL(("Connect will complete asynchronously.")); FD_SET(sock_fd, &hm_tprt_write_set); sock_cb->conn_state = HM_TPRT_CONN_INIT; } else { TRACE_PERROR(("Connect failed on socket %d", sock_fd)); FD_CLR(sock_cb->sock_fd, &hm_tprt_write_set); close(sock_fd); sock_fd = -1; goto EXIT_LABEL; } } else { TRACE_DETAIL(("Connect succeeded!")); /* Directly move connection to active state */ sock_cb->conn_state = HM_TPRT_CONN_ACTIVE; } //TODO: Add socket to write_set and poll on write_set too. sock_cb->sock_type = HM_TRANSPORT_SOCK_TYPE_TCP; FD_SET(sock_fd, &hm_tprt_write_set); break; case HM_TRANSPORT_UDP: /***************************************************************************/ /* Bind to address */ /***************************************************************************/ TRACE_DETAIL(("Binding to address")); if(bind(sock_fd, &addr->sock_addr, length) != 0) { TRACE_PERROR(("Error binding to port")); close(sock_fd); sock_fd = -1; goto EXIT_LABEL; } sock_cb->sock_type = HM_TRANSPORT_SOCK_TYPE_UDP; break; case HM_TRANSPORT_MCAST: /***************************************************************************/ /* Bind to address */ /***************************************************************************/ if(bind(sock_fd, &addr->sock_addr, length) != 0) { TRACE_PERROR(("Error binding to port")); close(sock_fd); sock_fd = -1; goto EXIT_LABEL; } sock_cb->sock_type = HM_TRANSPORT_SOCK_TYPE_UDP; #ifdef I_WANT_TO_DEBUG { char address_value[128]; HM_SOCKADDR_UNION addr; socklen_t addrlen = sizeof(addr); getsockname(sock_fd, &addr.sock_addr, &addrlen); inet_ntop(addr.in_addr.sin_family, &addr.in_addr.sin_addr, address_value, sizeof(address_value)); TRACE_INFO(("Address value: %s:%d",address_value, ntohs(addr.in_addr.sin_port))); TRACE_INFO(("Family: %d", addr.in_addr.sin_family)); } #endif snprintf(mcast_addr, sizeof(mcast_addr), "224.0.0.%d", mcast_group+address->mcast_group); TRACE_DETAIL(("Multicast Group Address: %s", mcast_addr)); /***************************************************************************/ /* Convert to network representation. */ /***************************************************************************/ inet_pton(res->ai_family, mcast_addr, &mreq.imr_multiaddr.s_addr); mreq.imr_interface.s_addr = htonl(INADDR_ANY); if(setsockopt(sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) { TRACE_PERROR(("Error joining Multicast Group")); close(sock_fd); sock_fd = -1; goto EXIT_LABEL; } TRACE_INFO(("Joined Multicast Group %d.", address->mcast_group)); TRACE_INFO(("Update Global Multicast Address Destination")); /***************************************************************************/ /* Also update the Multicast sending address in LOCAL */ /* This is a quickfix. */ /* FIXME */ /***************************************************************************/ TRACE_ASSERT(LOCAL.mcast_addr != NULL); LOCAL.mcast_addr->address.mcast_group = address->mcast_group; //IPv4 Specific mcast_cast = (HM_SOCKADDR_UNION *)&LOCAL.mcast_addr->address.address; inet_pton(res->ai_family, mcast_addr, ((SOCKADDR_IN *)&mcast_cast->in_addr.sin_addr)); mcast_cast->in_addr.sin_port = ((SOCKADDR_IN*)res->ai_addr)->sin_port; mcast_cast->in_addr.sin_family = res->ai_family; #ifdef I_WANT_TO_DEBUG { char address_value[128]; inet_ntop(res->ai_family, ((SOCKADDR_IN *)&mcast_cast->in_addr.sin_addr), address_value, sizeof(address_value)); TRACE_INFO(("Multicast Address value: %s:%d",address_value, ntohs(mcast_cast->in_addr.sin_port))); TRACE_INFO(("Family: %d", res->ai_family)); } #endif /***************************************************************************/ /* Do not loopback the packets */ /***************************************************************************/ { TRACE_DETAIL(("Setting Loopback to off.")); u_char flag; flag = 0; if(setsockopt(sock_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &flag, sizeof(flag)) == -1) { TRACE_PERROR(("Error setting loopback option on Multicast socket")); } } LOCAL.mcast_addr->sock_cb = sock_cb; LOCAL.mcast_addr->location_cb = &LOCAL.local_location_cb; break; default: TRACE_WARN(("Unknown Connection type")); break; } /***************************************************************************/ /* All went well. Set the sock_fd as that of sock_cb */ /***************************************************************************/ sock_cb->sock_fd = sock_fd; memcpy(&sock_cb->addr, &address->address, sizeof(SOCKADDR)); /***************************************************************************/ /* Insert in Connection List */ /***************************************************************************/ HM_INSERT_BEFORE(LOCAL.conn_list, sock_cb->node); EXIT_LABEL: if (ret_val == HM_OK) { /***************************************************************************/ /* Free the address structures that were allocated in getaddrinfo in kernel*/ /* NOTE: We are not saving the struct sockaddr, we will fetch it later */ /* using getaddrinfo() */ /***************************************************************************/ freeaddrinfo(ressave); /***************************************************************************/ /* Add the socket descriptor to the global FD set. */ /***************************************************************************/ //FIXME } else if(ret_val == HM_ERR) { hm_free_sock_cb(sock_cb); sock_cb = NULL; } TRACE_EXIT(); return (sock_cb); } /* hm_tprt_open_connection */
/** * @brief Accepts the connection into a SOCKET_CB and returns the CB * * @param sock_fd Socket Descriptor * @return Socket Control Block (#HM_SOCKET_CB) if successful, @c NULL otherwise */ HM_SOCKET_CB * hm_tprt_accept_connection(int32_t sock_fd) { /***************************************************************************/ /* Variable Declarations */ /***************************************************************************/ HM_SOCKET_CB *sock_cb =NULL; uint32_t client_len = sizeof(SOCKADDR); #ifdef I_WANT_TO_DEBUG char address[128]; HM_SOCKADDR_UNION *addr = NULL; #endif /***************************************************************************/ /* Sanity Checks */ /***************************************************************************/ TRACE_ENTRY(); TRACE_ASSERT(sock_fd > 0); /***************************************************************************/ /* Main Routine */ /***************************************************************************/ sock_cb = hm_alloc_sock_cb(); if(sock_cb == NULL) { TRACE_ERROR(("Error allocating resources for incoming connection request")); goto EXIT_LABEL; } TRACE_DETAIL(("Socket: %d", sock_fd)); sock_cb->sock_fd = accept(sock_fd, (SOCKADDR *)&(sock_cb->addr), (socklen_t *)&client_len); if (sock_cb->sock_fd < 0) { if (errno != EWOULDBLOCK) { TRACE_PERROR(("Failed to accept local connection.")); hm_free_sock_cb(sock_cb); sock_cb = NULL; goto EXIT_LABEL; } TRACE_WARN(("No new connection requests")); } #ifdef I_WANT_TO_DEBUG /***************************************************************************/ /* Accepted Connection. Its parameters are enumerated. */ /***************************************************************************/ addr = (HM_SOCKADDR_UNION *)&sock_cb->addr; TRACE_INFO(("New Connection from %s:%d", inet_ntop(AF_INET, &addr->in_addr.sin_addr, address, client_len), ntohs(addr->in_addr.sin_port))); #endif /***************************************************************************/ /* Add the descriptor to global descriptor set */ /***************************************************************************/ TRACE_DETAIL(("Add FD to set")); FD_SET(sock_cb->sock_fd, &hm_tprt_conn_set); if(max_fd < sock_cb->sock_fd) { TRACE_DETAIL(("Update maximum socket descriptor value to %d", sock_cb->sock_fd)); max_fd = sock_cb->sock_fd; } /***************************************************************************/ /* We're going to INIT state. Connect has been received, but nothing else */ /* has happened. Chances are, it has not been mapped on to a Transport CB */ /***************************************************************************/ sock_cb->conn_state = HM_TPRT_CONN_INIT; sock_cb->sock_type = HM_TRANSPORT_SOCK_TYPE_TCP; TRACE_DETAIL(("Connection Accepted on Socket %d. Wait for Messages.", sock_cb->sock_fd)); HM_INSERT_BEFORE(LOCAL.conn_list, sock_cb->node); EXIT_LABEL: /***************************************************************************/ /* Exit Level Checks */ /***************************************************************************/ TRACE_EXIT(); return (sock_cb); }/* hm_tprt_accept_connection */