connection_t * connection_create(connection_t * connList, int sock, char * host, uint16_t port) { char portStr[6]; struct addrinfo hints; struct addrinfo *servinfo = NULL; struct addrinfo *p; int s; struct sockaddr *sa; socklen_t sl; connection_t * connP = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; if (0 >= sprintf(portStr, "%hu", port)) return NULL; if (0 != getaddrinfo(host, portStr, &hints, &servinfo) || servinfo == NULL) return NULL; // we test the various addresses s = -1; for(p = servinfo ; p != NULL && s == -1 ; p = p->ai_next) { s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (s >= 0) { sa = p->ai_addr; sl = p->ai_addrlen; if (-1 == connect(s, p->ai_addr, p->ai_addrlen)) { close(s); s = -1; } } } if (s >= 0) { connP = connection_new_incoming(connList, sock, sa, sl); close(s); } if (NULL != servinfo) { free(servinfo); } return connP; }
int main(int argc, char *argv[]) { int sock; fd_set readfds; struct timeval tv; int result; lwm2m_context_t * lwm2mH = NULL; int i; connection_t * connList = NULL; int addressFamily = AF_INET6; int opt; command_desc_t commands[] = { {"list", "List registered clients.", NULL, prv_output_clients, NULL}, {"read", "Read from a client.", " read CLIENT# URI\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri to read such as /3, /3/0/2, /1024/11, /1024/0/1\r\n" "Result will be displayed asynchronously.", prv_read_client, NULL}, {"disc", "Discover resources of a client.", " disc CLIENT# URI\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri to discover such as /3, /3/0/2, /1024/11, /1024/0/1\r\n" "Result will be displayed asynchronously.", prv_discover_client, NULL}, {"write", "Write to a client.", " write CLIENT# URI DATA\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri to write to such as /3, /3/0/2, /1024/11, /1024/0/1\r\n" " DATA: data to write\r\n" "Result will be displayed asynchronously.", prv_write_client, NULL}, {"time", "Write time-related attributes to a client.", " time CLIENT# URI PMIN PMAX\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri to write attributes to such as /3, /3/0/2, /1024/11, /1024/0/1\r\n" " PMIN: Minimum period\r\n" " PMAX: Maximum period\r\n" "Result will be displayed asynchronously.", prv_time_client, NULL}, {"attr", "Write value-related attributes to a client.", " attr CLIENT# URI LT GT [STEP]\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri to write attributes to such as /3, /3/0/2, /1024/11, /1024/0/1\r\n" " LT: \"Less than\" value\r\n" " GT: \"Greater than\" value\r\n" " STEP: \"Step\" value\r\n" "Result will be displayed asynchronously.", prv_attr_client, NULL}, {"clear", "Clear attributes of a client.", " clear CLIENT# URI\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri to clear attributes of such as /3, /3/0/2, /1024/11, /1024/0/1\r\n" "Result will be displayed asynchronously.", prv_clear_client, NULL}, {"exec", "Execute a client resource.", " exec CLIENT# URI\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri of the resource to execute such as /3/0/2\r\n" "Result will be displayed asynchronously.", prv_exec_client, NULL}, {"del", "Delete a client Object instance.", " del CLIENT# URI\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri of the instance to delete such as /1024/11\r\n" "Result will be displayed asynchronously.", prv_delete_client, NULL}, {"create", "create an Object instance.", " create CLIENT# URI DATA\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri to which create the Object Instance such as /1024, /1024/45 \r\n" " DATA: data to initialize the new Object Instance (0-255 for object 1024) \r\n" "Result will be displayed asynchronously.", prv_create_client, NULL}, {"observe", "Observe from a client.", " observe CLIENT# URI\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri to observe such as /3, /3/0/2, /1024/11\r\n" "Result will be displayed asynchronously.", prv_observe_client, NULL}, {"cancel", "Cancel an observe.", " cancel CLIENT# URI\r\n" " CLIENT#: client number as returned by command 'list'\r\n" " URI: uri on which to cancel an observe such as /3, /3/0/2, /1024/11\r\n" "Result will be displayed asynchronously.", prv_cancel_client, NULL}, {"q", "Quit the server.", NULL, prv_quit, NULL}, COMMAND_END_LIST }; while ((opt = getopt(argc, argv, "4")) != -1) { switch (opt) { case '4': addressFamily = AF_INET; break; default: print_usage(); return 0; } } sock = create_socket(LWM2M_STANDARD_PORT_STR, addressFamily); if (sock < 0) { fprintf(stderr, "Error opening socket: %d\r\n", errno); return -1; } lwm2mH = lwm2m_init(NULL); if (NULL == lwm2mH) { fprintf(stderr, "lwm2m_init() failed\r\n"); return -1; } signal(SIGINT, handle_sigint); for (i = 0 ; commands[i].name != NULL ; i++) { commands[i].userData = (void *)lwm2mH; } fprintf(stdout, "> "); fflush(stdout); lwm2m_set_monitoring_callback(lwm2mH, prv_monitor_callback, lwm2mH); while (0 == g_quit) { FD_ZERO(&readfds); FD_SET(sock, &readfds); FD_SET(STDIN_FILENO, &readfds); tv.tv_sec = 60; tv.tv_usec = 0; result = lwm2m_step(lwm2mH, &(tv.tv_sec)); if (result != 0) { fprintf(stderr, "lwm2m_step() failed: 0x%X\r\n", result); return -1; } result = select(FD_SETSIZE, &readfds, 0, 0, &tv); if ( result < 0 ) { if (errno != EINTR) { fprintf(stderr, "Error in select(): %d\r\n", errno); } } else if (result > 0) { uint8_t buffer[MAX_PACKET_SIZE]; int numBytes; if (FD_ISSET(sock, &readfds)) { struct sockaddr_storage addr; socklen_t addrLen; addrLen = sizeof(addr); numBytes = recvfrom(sock, buffer, MAX_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrLen); if (numBytes == -1) { fprintf(stderr, "Error in recvfrom(): %d\r\n", errno); } else { char s[INET6_ADDRSTRLEN]; in_port_t port; connection_t * connP; s[0] = 0; if (AF_INET == addr.ss_family) { struct sockaddr_in *saddr = (struct sockaddr_in *)&addr; inet_ntop(saddr->sin_family, &saddr->sin_addr, s, INET6_ADDRSTRLEN); port = saddr->sin_port; } else if (AF_INET6 == addr.ss_family) { struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)&addr; inet_ntop(saddr->sin6_family, &saddr->sin6_addr, s, INET6_ADDRSTRLEN); port = saddr->sin6_port; } fprintf(stderr, "%d bytes received from [%s]:%hu\r\n", numBytes, s, ntohs(port)); output_buffer(stderr, buffer, numBytes, 0); connP = connection_find(connList, &addr, addrLen); if (connP == NULL) { connP = connection_new_incoming(connList, sock, (struct sockaddr *)&addr, addrLen); if (connP != NULL) { connList = connP; } } if (connP != NULL) { lwm2m_handle_packet(lwm2mH, buffer, numBytes, connP); } } } else if (FD_ISSET(STDIN_FILENO, &readfds)) { numBytes = read(STDIN_FILENO, buffer, MAX_PACKET_SIZE - 1); if (numBytes > 1) { buffer[numBytes] = 0; handle_command(commands, (char*)buffer); fprintf(stdout, "\r\n"); } if (g_quit == 0) { fprintf(stdout, "> "); fflush(stdout); } else { fprintf(stdout, "\r\n"); } } } } lwm2m_close(lwm2mH); close(sock); connection_free(connList); #ifdef MEMORY_TRACE if (g_quit == 1) { trace_print(0, 1); } #endif return 0; }
dtls_connection_t * connection_create(dtls_connection_t * connList, int sock, lwm2m_object_t * securityObj, int instanceId, lwm2m_context_t * lwm2mH, int addressFamily) { struct addrinfo hints; struct addrinfo *servinfo = NULL; struct addrinfo *p; int s; struct sockaddr *sa; socklen_t sl; dtls_connection_t * connP = NULL; char uriBuf[URI_LENGTH]; char * uri; char * host; char * port; memset(&hints, 0, sizeof(hints)); hints.ai_family = addressFamily; hints.ai_socktype = SOCK_DGRAM; uri = security_get_uri(securityObj, instanceId, uriBuf, URI_LENGTH); if (uri == NULL) return NULL; // parse uri in the form "coaps://[host]:[port]" char * defaultport; if (0 == strncmp(uri, "coaps://", strlen("coaps://"))) { host = uri+strlen("coaps://"); defaultport = COAPS_PORT; } else if (0 == strncmp(uri, "coap://", strlen("coap://"))) { host = uri+strlen("coap://"); defaultport = COAP_PORT; } else { return NULL; } port = strrchr(host, ':'); if (port == NULL) { port = defaultport; } else { // remove brackets if (host[0] == '[') { host++; if (*(port - 1) == ']') { *(port - 1) = 0; } return NULL; } // split strings *port = 0; port++; } if (0 != getaddrinfo(host, port, &hints, &servinfo) || servinfo == NULL) return NULL; // we test the various addresses s = -1; for(p = servinfo ; p != NULL && s == -1 ; p = p->ai_next) { s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (s >= 0) { sa = p->ai_addr; sl = p->ai_addrlen; if (-1 == connect(s, p->ai_addr, p->ai_addrlen)) { close(s); s = -1; } } } if (s >= 0) { connP = connection_new_incoming(connList, sock, sa, sl); close(s); // do we need to start tinydtls? if (connP != NULL) { connP->securityObj = securityObj; connP->securityInstId = instanceId; connP->lwm2mH = lwm2mH; if (security_get_mode(connP->securityObj,connP->securityInstId) != LWM2M_SECURITY_MODE_NONE) { connP->dtlsContext = get_dtls_context(connP); } else { // no dtls session connP->dtlsSession = NULL; } } } if (NULL != servinfo) free(servinfo); return connP; }
int main(int argc, char *argv[]) { fd_set readfds; struct timeval tv; int result; char * port = "5685"; internal_data_t data; char * filename = "bootstrap_server.ini"; int opt; FILE * fd; command_desc_t commands[] = { {"boot", "Bootstrap a client (Server Initiated).", " boot URI [NAME]\r\n" " URI: uri of the client to bootstrap\r\n" " NAME: endpoint name of the client as in the .ini file (optionnal)\r\n" "Example: boot coap://[::1]:56830 testlwm2mclient", prv_bootstrap_client, &data}, {"q", "Quit the server.", NULL, prv_quit, NULL}, COMMAND_END_LIST }; while ((opt = getopt(argc, argv, "f:p:")) != -1) { switch (opt) { case 'f': filename = optarg; break; case 'p': port = optarg; break; default: print_usage(filename, port); return 0; } } memset(&data, 0, sizeof(internal_data_t)); data.sock = create_socket(port); if (data.sock < 0) { fprintf(stderr, "Error opening socket: %d\r\n", errno); return -1; } data.lwm2mH = lwm2m_init(NULL, prv_buffer_send, NULL); if (NULL == data.lwm2mH) { fprintf(stderr, "lwm2m_init() failed\r\n"); return -1; } signal(SIGINT, handle_sigint); fd = fopen(filename, "r"); if (fd == NULL) { fprintf(stderr, "Opening file %s failed.\r\n", filename); return -1; } data.bsInfo = bs_get_info(fd); fclose(fd); if (data.bsInfo == NULL) { fprintf(stderr, "Reading Bootsrap Info from file %s failed.\r\n", filename); return -1; } lwm2m_set_bootstrap_callback(data.lwm2mH, prv_bootstrap_callback, (void *)&data); fprintf(stdout, "LWM2M Bootstrap Server now listening on port %s.\r\n\n", port); fprintf(stdout, "> "); fflush(stdout); while (0 == g_quit) { endpoint_t * endP; FD_ZERO(&readfds); FD_SET(data.sock, &readfds); FD_SET(STDIN_FILENO, &readfds); tv.tv_sec = 60; tv.tv_usec = 0; result = lwm2m_step(data.lwm2mH, &(tv.tv_sec)); if (result != 0) { fprintf(stderr, "lwm2m_step() failed: 0x%X\r\n", result); return -1; } result = select(FD_SETSIZE, &readfds, 0, 0, &tv); if ( result < 0 ) { if (errno != EINTR) { fprintf(stderr, "Error in select(): %d\r\n", errno); } } else if (result >= 0) { uint8_t buffer[MAX_PACKET_SIZE]; int numBytes; // Packet received if (FD_ISSET(data.sock, &readfds)) { struct sockaddr_storage addr; socklen_t addrLen; addrLen = sizeof(addr); numBytes = recvfrom(data.sock, buffer, MAX_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrLen); if (numBytes == -1) { fprintf(stderr, "Error in recvfrom(): %d\r\n", errno); } else { char s[INET6_ADDRSTRLEN]; in_port_t port; connection_t * connP; s[0] = 0; if (AF_INET == addr.ss_family) { struct sockaddr_in *saddr = (struct sockaddr_in *)&addr; inet_ntop(saddr->sin_family, &saddr->sin_addr, s, INET6_ADDRSTRLEN); port = saddr->sin_port; } else if (AF_INET6 == addr.ss_family) { struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)&addr; inet_ntop(saddr->sin6_family, &saddr->sin6_addr, s, INET6_ADDRSTRLEN); port = saddr->sin6_port; } fprintf(stderr, "%d bytes received from [%s]:%hu\r\n", numBytes, s, ntohs(port)); output_buffer(stderr, buffer, numBytes, 0); connP = connection_find(data.connList, &addr, addrLen); if (connP == NULL) { connP = connection_new_incoming(data.connList, data.sock, (struct sockaddr *)&addr, addrLen); if (connP != NULL) { data.connList = connP; } } if (connP != NULL) { lwm2m_handle_packet(data.lwm2mH, buffer, numBytes, connP); } } } // command line input else if (FD_ISSET(STDIN_FILENO, &readfds)) { numBytes = read(STDIN_FILENO, buffer, MAX_PACKET_SIZE - 1); if (numBytes > 1) { buffer[numBytes] = 0; handle_command(commands, (char*)buffer); } if (g_quit == 0) { fprintf(stdout, "\r\n> "); fflush(stdout); } else { fprintf(stdout, "\r\n"); } } // Do operations on endpoints prv_endpoint_clean(&data); endP = data.endpointList; while (endP != NULL) { switch(endP->status) { case CMD_STATUS_OK: endP->cmdList = endP->cmdList->next; endP->status = CMD_STATUS_NEW; // fall through case CMD_STATUS_NEW: prv_send_command(&data, endP); break; default: break; } endP = endP->next; } } } lwm2m_close(data.lwm2mH); bs_free_info(data.bsInfo); while (data.endpointList != NULL) { endpoint_t * endP; endP = data.endpointList; data.endpointList = data.endpointList->next; prv_endpoint_free(endP); } close(data.sock); connection_free(data.connList); return 0; }