/* * Torsocks call for close(2). */ LIBC_CLOSE_RET_TYPE tsocks_close(LIBC_CLOSE_SIG) { struct connection *conn; DBG("[close] Close caught for fd %d", fd); connection_registry_lock(); conn = connection_find(fd); if (conn) { /* * Remove from the registry so it's not visible anymore and thus using * it without lock. */ connection_remove(conn); } connection_registry_unlock(); /* * Put back the connection reference. If the refcount get to 0, the * connection pointer is destroyed. */ if (conn) { DBG("[close] Close connection putting back ref"); connection_put_ref(conn); } /* * Let the log system detect when the log file fd is about to be * closed and clean up. */ log_fd_close_notify(fd); /* Return the original libc close. */ return tsocks_libc_close(fd); }
static void connection_remove(struct fetion_account_data *sip, int fd) { struct sip_connection *conn = connection_find(sip, fd); sip->openconns = g_slist_remove(sip->openconns, conn); if (conn->inputhandler) purple_input_remove(conn->inputhandler); g_free(conn->inbuf); g_free(conn); }
static gint tcp_send_out(PurpleConnection *gc, guint8 *data, gint data_len) { qq_data *qd; qq_connection *conn; gint ret; g_return_val_if_fail(data != NULL && data_len > 0, -1); g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); qd = (qq_data *) gc->proto_data; conn = connection_find(qd, qd->fd); g_return_val_if_fail(conn, -1); #if 0 purple_debug_info("TCP_SEND_OUT", "Send %d bytes to socket %d\n", data_len, qd->fd); #endif if (conn->can_write_handler == 0) { ret = write(qd->fd, data, data_len); } else { ret = -1; errno = EAGAIN; } /* purple_debug_info("TCP_SEND_OUT", "Socket %d, total %d bytes is sent %d\n", qd->fd, data_len, ret); */ if (ret < 0 && errno == EAGAIN) { /* socket is busy, send later */ purple_debug_info("TCP_SEND_OUT", "Socket is busy and send later\n"); ret = 0; } else if (ret <= 0) { /* TODO: what to do here - do we really have to disconnect? */ gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); purple_debug_error("TCP_SEND_OUT", "Send to socket %d failed: %d, %s\n", qd->fd, errno, g_strerror(errno)); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return ret; } if (ret < data_len) { purple_debug_info("TCP_SEND_OUT", "Add %d bytes to buffer\n", data_len - ret); if (conn->can_write_handler == 0) { conn->can_write_handler = purple_input_add(qd->fd, PURPLE_INPUT_WRITE, tcp_can_write, gc); } if (conn->tcp_txbuf == NULL) { conn->tcp_txbuf = purple_circ_buffer_new(4096); } purple_circ_buffer_append(conn->tcp_txbuf, data + ret, data_len - ret); } return ret; }
/* This function is the "key store" for tinyDTLS. It is called to * retrieve a key for the given identity within this particular * session. */ static int get_psk_info(struct dtls_context_t *ctx, const session_t *session, dtls_credentials_type_t type, const unsigned char *id, size_t id_len, unsigned char *result, size_t result_length) { // find connection dtls_connection_t* cnx = connection_find((dtls_connection_t *) ctx->app, &(session->addr.st),session->size); if (cnx == NULL) { printf("GET PSK session not found\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } switch (type) { case DTLS_PSK_IDENTITY: { int idLen; char * id; id = security_get_public_id(cnx->securityObj, cnx->securityInstId, &idLen); if (result_length < idLen) { printf("cannot set psk_identity -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } memcpy(result, id,idLen); lwm2m_free(id); return idLen; } case DTLS_PSK_KEY: { int keyLen; char * key; key = security_get_secret_key(cnx->securityObj, cnx->securityInstId, &keyLen); if (result_length < keyLen) { printf("cannot set psk -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } memcpy(result, key,keyLen); lwm2m_free(key); return keyLen; } default: printf("unsupported request type: %d\n", type); } return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); }
static int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { // find connection dtls_connection_t * connP = (dtls_connection_t *) ctx->app; dtls_connection_t* cnx = connection_find((dtls_connection_t *) ctx->app, &(session->addr.st),session->size); if (cnx != NULL) { lwm2m_handle_packet(cnx->lwm2mH, (uint8_t*)data, len, (void*)cnx); return 0; } return -1; }
static void connection_remove(qq_data *qd, int fd) { qq_connection *conn = connection_find(qd, fd); qd->openconns = g_slist_remove(qd->openconns, conn); g_return_if_fail( conn != NULL ); purple_debug_info("QQ", "Close socket %d\n", conn->fd); if(conn->input_handler > 0) purple_input_remove(conn->input_handler); if(conn->can_write_handler > 0) purple_input_remove(conn->can_write_handler); if (conn->fd >= 0) close(conn->fd); if(conn->tcp_txbuf != NULL) purple_circ_buffer_destroy(conn->tcp_txbuf); if (conn->tcp_rxqueue != NULL) g_free(conn->tcp_rxqueue); g_free(conn); }
static int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { // find connection dtls_connection_t * connP = (dtls_connection_t *) ctx->app; dtls_connection_t* cnx = connection_find((dtls_connection_t *) ctx->app, &(session->addr.st),session->size); if (cnx != NULL) { // send data to peer int err = send_data(connP,data,len); if (COAP_NO_ERROR != err) { return -1; } return 0; } return -1; }
/* * Torsocks call for getpeername(2). */ LIBC_GETPEERNAME_RET_TYPE tsocks_getpeername(LIBC_GETPEERNAME_SIG) { int ret = 0; struct connection *conn; DBG("[getpeername] Requesting address on socket %d", __sockfd); connection_registry_lock(); conn = connection_find(__sockfd); if (!conn) { errno = ENOTCONN; ret = -1; goto end; } connection_registry_unlock(); errno = 0; end: return ret; }
static void tcp_can_write(gpointer data, gint source, PurpleInputCondition cond) { PurpleConnection *gc = (PurpleConnection *) data; qq_data *qd; qq_connection *conn; int ret, writelen; g_return_if_fail(gc != NULL && gc->proto_data != NULL); qd = (qq_data *) gc->proto_data; conn = connection_find(qd, source); g_return_if_fail(conn != NULL); writelen = purple_circ_buffer_get_max_read(conn->tcp_txbuf); if (writelen == 0) { purple_input_remove(conn->can_write_handler); conn->can_write_handler = 0; return; } ret = write(source, conn->tcp_txbuf->outptr, writelen); purple_debug_info("TCP_CAN_WRITE", "total %d bytes is sent %d\n", writelen, ret); if (ret < 0 && errno == EAGAIN) return; else if (ret < 0) { /* TODO: what to do here - do we really have to disconnect? */ gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); g_free(tmp); return; } purple_circ_buffer_mark_read(conn->tcp_txbuf, ret); }
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; }
static void tcp_pending(gpointer data, gint source, PurpleInputCondition cond) { PurpleConnection *gc = (PurpleConnection *) data; qq_data *qd; qq_connection *conn; guint8 buf[1024]; /* set to 16 when test tcp_rxqueue */ gint buf_len; gint bytes; guint8 *pkt; guint16 pkt_len; gchar *error_msg; guint8 *jump; gint jump_len; g_return_if_fail(gc != NULL && gc->proto_data != NULL); qd = (qq_data *) gc->proto_data; if(cond != PURPLE_INPUT_READ) { purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Socket error")); return; } conn = connection_find(qd, source); g_return_if_fail(conn != NULL); /* test code, not using tcp_rxqueue memset(pkt,0, sizeof(pkt)); buf_len = read(qd->fd, pkt, sizeof(pkt)); if (buf_len > 2) { packet_process(gc, pkt + 2, buf_len - 2); } return; */ buf_len = read(source, buf, sizeof(buf)); if (buf_len < 0) { if (errno == EAGAIN) /* No worries */ return; error_msg = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_msg); g_free(error_msg); return; } else if (buf_len == 0) { purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Server closed the connection")); return; } /* keep alive will be sent in 30 seconds since last_receive * QQ need a keep alive packet in every 60 seconds gc->last_received = time(NULL); */ #if 1 purple_debug_info("TCP_PENDING", "Read %d bytes, tcp_rxlen is %d\n", buf_len, conn->tcp_rxlen); #endif conn->tcp_rxqueue = g_realloc(conn->tcp_rxqueue, buf_len + conn->tcp_rxlen); memcpy(conn->tcp_rxqueue + conn->tcp_rxlen, buf, buf_len); conn->tcp_rxlen += buf_len; pkt = g_newa(guint8, MAX_PACKET_SIZE); while (PURPLE_CONNECTION_IS_VALID(gc)) { if (qd->openconns == NULL) { break; } if (conn->tcp_rxqueue == NULL) { conn->tcp_rxlen = 0; break; } if (conn->tcp_rxlen < QQ_TCP_HEADER_LENGTH) { break; } bytes = 0; bytes += qq_get16(&pkt_len, conn->tcp_rxqueue + bytes); if (conn->tcp_rxlen < pkt_len) { break; } #if 1 qq_show_packet("tcp_pending", conn->tcp_rxqueue, pkt_len); #endif /* purple_debug_info("TCP_PENDING", "Packet len=%d, rxlen=%d\n", pkt_len, conn->tcp_rxlen); */ if ( pkt_len < QQ_TCP_HEADER_LENGTH || *(conn->tcp_rxqueue + bytes) != QQ_PACKET_TAG || *(conn->tcp_rxqueue + pkt_len - 1) != QQ_PACKET_TAIL) { /* HEY! This isn't even a QQ. What are you trying to pull? */ purple_debug_warning("TCP_PENDING", "Packet error, no header or tail tag\n"); jump = memchr(conn->tcp_rxqueue + 1, QQ_PACKET_TAIL, conn->tcp_rxlen - 1); if ( !jump ) { purple_debug_warning("TCP_PENDING", "Failed to find next tail, clear receive buffer\n"); g_free(conn->tcp_rxqueue); conn->tcp_rxqueue = NULL; conn->tcp_rxlen = 0; return; } /* jump and over QQ_PACKET_TAIL */ jump_len = (jump - conn->tcp_rxqueue) + 1; purple_debug_warning("TCP_PENDING", "Find next tail at %d, jump %d\n", jump_len, jump_len + 1); g_memmove(conn->tcp_rxqueue, jump, conn->tcp_rxlen - jump_len); conn->tcp_rxlen -= jump_len; continue; } /* get packet */ memset(pkt, 0, MAX_PACKET_SIZE); g_memmove(pkt, conn->tcp_rxqueue + bytes, pkt_len - bytes); /* jump to next packet */ conn->tcp_rxlen -= pkt_len; if (conn->tcp_rxlen) { /* purple_debug_info("TCP_PENDING", "shrink tcp_rxqueue to %d\n", conn->tcp_rxlen); */ jump = g_memdup(conn->tcp_rxqueue + pkt_len, conn->tcp_rxlen); g_free(conn->tcp_rxqueue); conn->tcp_rxqueue = jump; } else { /* purple_debug_info("TCP_PENDING", "free tcp_rxqueue\n"); */ g_free(conn->tcp_rxqueue); conn->tcp_rxqueue = NULL; } /* packet_process may call disconnect and destory data like conn * do not call packet_process before jump, * break if packet_process return FALSE */ if (packet_process(gc, pkt, pkt_len - bytes) == FALSE) { purple_debug_info("TCP_PENDING", "Connection has been destory\n"); break; } } }
int main(int argc, char *argv[]) { client_data_t data; int result; lwm2m_context_t * lwm2mH = NULL; int i; const char * localPort = "56830"; const char * server = NULL; const char * serverPort = LWM2M_STANDARD_PORT_STR; char * name = "testlwm2mclient"; int lifetime = 300; int batterylevelchanging = 0; time_t reboot_time = 0; int opt; bool bootstrapRequested = false; bool serverPortChanged = false; #ifdef LWM2M_BOOTSTRAP lwm2m_client_state_t previousState = STATE_INITIAL; #endif char * pskId = NULL; char * psk = NULL; uint16_t pskLen = -1; char * pskBuffer = NULL; /* * The function start by setting up the command line interface (which may or not be useful depending on your project) * * This is an array of commands describes as { name, description, long description, callback, userdata }. * The firsts tree are easy to understand, the callback is the function that will be called when this command is typed * and in the last one will be stored the lwm2m context (allowing access to the server settings and the objects). */ command_desc_t commands[] = { {"list", "List known servers.", NULL, prv_output_servers, NULL}, {"change", "Change the value of resource.", " change URI [DATA]\r\n" " URI: uri of the resource such as /3/0, /3/0/2\r\n" " DATA: (optional) new value\r\n", prv_change, NULL}, {"update", "Trigger a registration update", " update SERVER\r\n" " SERVER: short server id such as 123\r\n", prv_update, NULL}, #ifdef LWM2M_BOOTSTRAP {"bootstrap", "Initiate a DI bootstrap process", NULL, prv_initiate_bootstrap, NULL}, {"dispb", "Display current backup of objects/instances/resources\r\n" "\t(only security and server objects are backupped)", NULL, prv_display_backup, NULL}, #endif {"ls", "List Objects and Instances", NULL, prv_object_list, NULL}, {"disp", "Display current objects/instances/resources", NULL, prv_display_objects, NULL}, {"dump", "Dump an Object", "dump URI" "URI: uri of the Object or Instance such as /3/0, /1\r\n", prv_object_dump, NULL}, {"add", "Add support of object 1024", NULL, prv_add, NULL}, {"rm", "Remove support of object 1024", NULL, prv_remove, NULL}, {"quit", "Quit the client gracefully.", NULL, prv_quit, NULL}, {"^C", "Quit the client abruptly (without sending a de-register message).", NULL, NULL, NULL}, COMMAND_END_LIST }; memset(&data, 0, sizeof(client_data_t)); data.addressFamily = AF_INET6; opt = 1; while (opt < argc) { if (argv[opt] == NULL || argv[opt][0] != '-' || argv[opt][2] != 0) { print_usage(); return 0; } switch (argv[opt][1]) { case 'b': bootstrapRequested = true; if (!serverPortChanged) serverPort = LWM2M_BSSERVER_PORT_STR; break; case 'c': batterylevelchanging = 1; break; case 't': opt++; if (opt >= argc) { print_usage(); return 0; } if (1 != sscanf(argv[opt], "%d", &lifetime)) { print_usage(); return 0; } break; #ifdef WITH_TINYDTLS case 'i': opt++; if (opt >= argc) { print_usage(); return 0; } pskId = argv[opt]; break; case 's': opt++; if (opt >= argc) { print_usage(); return 0; } psk = argv[opt]; break; #endif case 'n': opt++; if (opt >= argc) { print_usage(); return 0; } name = argv[opt]; break; case 'l': opt++; if (opt >= argc) { print_usage(); return 0; } localPort = argv[opt]; break; case 'h': opt++; if (opt >= argc) { print_usage(); return 0; } server = argv[opt]; break; case 'p': opt++; if (opt >= argc) { print_usage(); return 0; } serverPort = argv[opt]; serverPortChanged = true; break; case '4': data.addressFamily = AF_INET; break; default: print_usage(); return 0; } opt += 1; } if (!server) { server = (AF_INET == data.addressFamily ? DEFAULT_SERVER_IPV4 : DEFAULT_SERVER_IPV6); } /* *This call an internal function that create an IPV6 socket on the port 5683. */ fprintf(stderr, "Trying to bind LWM2M Client to port %s\r\n", localPort); data.sock = create_socket(localPort, data.addressFamily); if (data.sock < 0) { fprintf(stderr, "Failed to open socket: %d %s\r\n", errno, strerror(errno)); return -1; } /* * Now the main function fill an array with each object, this list will be later passed to liblwm2m. * Those functions are located in their respective object file. */ #ifdef WITH_TINYDTLS if (psk != NULL) { pskLen = strlen(psk) / 2; pskBuffer = malloc(pskLen); if (NULL == pskBuffer) { fprintf(stderr, "Failed to create PSK binary buffer\r\n"); return -1; } // Hex string to binary char *h = psk; char *b = pskBuffer; char xlate[] = "0123456789ABCDEF"; for ( ; *h; h += 2, ++b) { char *l = strchr(xlate, toupper(*h)); char *r = strchr(xlate, toupper(*(h+1))); if (!r || !l) { fprintf(stderr, "Failed to parse Pre-Shared-Key HEXSTRING\r\n"); return -1; } *b = ((l - xlate) << 4) + (r - xlate); } } #endif char serverUri[50]; int serverId = 123; sprintf (serverUri, "coap://%s:%s", server, serverPort); #ifdef LWM2M_BOOTSTRAP objArray[0] = get_security_object(serverId, serverUri, pskId, pskBuffer, pskLen, bootstrapRequested); #else objArray[0] = get_security_object(serverId, serverUri, pskId, pskBuffer, pskLen, false); #endif if (NULL == objArray[0]) { fprintf(stderr, "Failed to create security object\r\n"); return -1; } data.securityObjP = objArray[0]; objArray[1] = get_server_object(serverId, "U", lifetime, false); if (NULL == objArray[1]) { fprintf(stderr, "Failed to create server object\r\n"); return -1; } objArray[2] = get_object_device(); if (NULL == objArray[2]) { fprintf(stderr, "Failed to create Device object\r\n"); return -1; } objArray[3] = get_object_firmware(); if (NULL == objArray[3]) { fprintf(stderr, "Failed to create Firmware object\r\n"); return -1; } objArray[4] = get_object_location(); if (NULL == objArray[4]) { fprintf(stderr, "Failed to create location object\r\n"); return -1; } objArray[5] = get_test_object(); if (NULL == objArray[5]) { fprintf(stderr, "Failed to create test object\r\n"); return -1; } objArray[6] = get_object_conn_m(); if (NULL == objArray[6]) { fprintf(stderr, "Failed to create connectivity monitoring object\r\n"); return -1; } objArray[7] = get_object_conn_s(); if (NULL == objArray[7]) { fprintf(stderr, "Failed to create connectivity statistics object\r\n"); return -1; } int instId = 0; objArray[8] = acc_ctrl_create_object(); if (NULL == objArray[8]) { fprintf(stderr, "Failed to create Access Control object\r\n"); return -1; } else if (acc_ctrl_obj_add_inst(objArray[8], instId, 3, 0, serverId)==false) { fprintf(stderr, "Failed to create Access Control object instance\r\n"); return -1; } else if (acc_ctrl_oi_add_ac_val(objArray[8], instId, 0, 0b000000000001111)==false) { fprintf(stderr, "Failed to create Access Control ACL default resource\r\n"); return -1; } else if (acc_ctrl_oi_add_ac_val(objArray[8], instId, 999, 0b000000000000001)==false) { fprintf(stderr, "Failed to create Access Control ACL resource for serverId: 999\r\n"); return -1; } /* * The liblwm2m library is now initialized with the functions that will be in * charge of communication */ lwm2mH = lwm2m_init(&data); if (NULL == lwm2mH) { fprintf(stderr, "lwm2m_init() failed\r\n"); return -1; } #ifdef WITH_TINYDTLS data.lwm2mH = lwm2mH; #endif /* * We configure the liblwm2m library with the name of the client - which shall be unique for each client - * the number of objects we will be passing through and the objects array */ result = lwm2m_configure(lwm2mH, name, NULL, NULL, OBJ_COUNT, objArray); if (result != 0) { fprintf(stderr, "lwm2m_configure() failed: 0x%X\r\n", result); return -1; } signal(SIGINT, handle_sigint); /** * Initialize value changed callback. */ init_value_change(lwm2mH); /* * As you now have your lwm2m context complete you can pass it as an argument to all the command line functions * precedently viewed (first point) */ for (i = 0 ; commands[i].name != NULL ; i++) { commands[i].userData = (void *)lwm2mH; } fprintf(stdout, "LWM2M Client \"%s\" started on port %s\r\n", name, localPort); fprintf(stdout, "> "); fflush(stdout); /* * We now enter in a while loop that will handle the communications from the server */ while (0 == g_quit) { struct timeval tv; fd_set readfds; if (g_reboot) { time_t tv_sec; tv_sec = lwm2m_gettime(); if (0 == reboot_time) { reboot_time = tv_sec + 5; } if (reboot_time < tv_sec) { /* * Message should normally be lost with reboot ... */ fprintf(stderr, "reboot time expired, rebooting ..."); system_reboot(); } else { tv.tv_sec = reboot_time - tv_sec; } } else if (batterylevelchanging) { update_battery_level(lwm2mH); tv.tv_sec = 5; } else { tv.tv_sec = 60; } tv.tv_usec = 0; FD_ZERO(&readfds); FD_SET(data.sock, &readfds); FD_SET(STDIN_FILENO, &readfds); /* * This function does two things: * - first it does the work needed by liblwm2m (eg. (re)sending some packets). * - Secondly it adjusts the timeout value (default 60s) depending on the state of the transaction * (eg. retransmission) and the time between the next operation */ result = lwm2m_step(lwm2mH, &(tv.tv_sec)); if (result != 0) { fprintf(stderr, "lwm2m_step() failed: 0x%X\r\n", result); if(previousState == STATE_BOOTSTRAPPING) { #ifdef WITH_LOGS fprintf(stdout, "[BOOTSTRAP] restore security and server objects\r\n"); #endif prv_connections_free(lwm2mH); prv_restore_objects(lwm2mH); lwm2mH->state = STATE_INITIAL; } else return -1; } #ifdef LWM2M_BOOTSTRAP update_bootstrap_info(&previousState, lwm2mH); #endif /* * This part will set up an interruption until an event happen on SDTIN or the socket until "tv" timed out (set * with the precedent function) */ result = select(FD_SETSIZE, &readfds, NULL, NULL, &tv); if (result < 0) { if (errno != EINTR) { fprintf(stderr, "Error in select(): %d %s\r\n", errno, strerror(errno)); } } else if (result > 0) { uint8_t buffer[MAX_PACKET_SIZE]; int numBytes; /* * If an event happens on the socket */ if (FD_ISSET(data.sock, &readfds)) { struct sockaddr_storage addr; socklen_t addrLen; addrLen = sizeof(addr); /* * We retrieve the data received */ numBytes = recvfrom(data.sock, buffer, MAX_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrLen); if (0 > numBytes) { fprintf(stderr, "Error in recvfrom(): %d %s\r\n", errno, strerror(errno)); } else if (0 < numBytes) { char s[INET6_ADDRSTRLEN]; in_port_t port; #ifdef WITH_TINYDTLS dtls_connection_t * connP; #else connection_t * connP; #endif 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)); /* * Display it in the STDERR */ output_buffer(stderr, buffer, numBytes, 0); connP = connection_find(data.connList, &addr, addrLen); if (connP != NULL) { /* * Let liblwm2m respond to the query depending on the context */ #ifdef WITH_TINYDTLS int result = connection_handle_packet(connP, buffer, numBytes); if (0 != result) { printf("error handling message %d\n",result); } #else lwm2m_handle_packet(lwm2mH, buffer, numBytes, connP); #endif conn_s_updateRxStatistic(objArray[7], numBytes, false); } else { fprintf(stderr, "received bytes ignored!\r\n"); } } } /* * If the event happened on the SDTIN */ else if (FD_ISSET(STDIN_FILENO, &readfds)) { numBytes = read(STDIN_FILENO, buffer, MAX_PACKET_SIZE - 1); if (numBytes > 1) { buffer[numBytes] = 0; /* * We call the corresponding callback of the typed command passing it the buffer for further arguments */ handle_command(commands, (char*)buffer); } if (g_quit == 0) { fprintf(stdout, "\r\n> "); fflush(stdout); } else { fprintf(stdout, "\r\n"); } } } } /* * Finally when the loop is left smoothly - asked by user in the command line interface - we unregister our client from it */ if (g_quit == 1) { #ifdef LWM2M_BOOTSTRAP close_backup_object(); #endif lwm2m_close(lwm2mH); } close(data.sock); connection_free(data.connList); clean_security_object(objArray[0]); lwm2m_free(objArray[0]); clean_server_object(objArray[1]); lwm2m_free(objArray[1]); free_object_device(objArray[2]); free_object_firmware(objArray[3]); free_object_location(objArray[4]); free_test_object(objArray[5]); free_object_conn_m(objArray[6]); free_object_conn_s(objArray[7]); acl_ctrl_free_object(objArray[8]); #ifdef MEMORY_TRACE if (g_quit == 1) { trace_print(0, 1); } #endif return 0; }
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; }
/* * Torsocks call for connect(2). */ LIBC_CONNECT_RET_TYPE tsocks_connect(LIBC_CONNECT_SIG) { int ret, ret_errno; struct connection *new_conn; struct onion_entry *on_entry; DBG("Connect caught on fd %d", sockfd); /* * Validate socket values in order to see if we can handle this connect * through Tor. */ ret = tsocks_validate_socket(sockfd, addr); if (ret == 1) { /* Tor can't handle it so send it to the libc. */ goto libc_connect; } else if (ret == -1) { /* Validation failed. Stop right now. */ goto error; } /* Implicit else statement meaning we continue processing the connect. */ assert(!ret); /* * Lock registry to get the connection reference if one. In this code path, * if a connection object is found, it will not be used since a double * connect() on the same file descriptor is an error so the registry is * quickly unlocked and no reference is needed. */ connection_registry_lock(); new_conn = connection_find(sockfd); connection_registry_unlock(); if (new_conn) { /* Double connect() for the same fd. */ errno = EISCONN; goto error; } /* * See if the IP being connected is an onion IP cookie mapping to an * existing .onion address. */ onion_pool_lock(&tsocks_onion_pool); on_entry = onion_entry_find_by_addr(addr, &tsocks_onion_pool); onion_pool_unlock(&tsocks_onion_pool); if (on_entry) { /* * Create a connection with the onion IP cookie since getpeername() * might need it, and set connection domain and hostname to use * the onion address name found before. */ new_conn = connection_create(sockfd, addr); if (!new_conn) { errno = ENOMEM; goto error; } new_conn->dest_addr.domain = CONNECTION_DOMAIN_NAME; new_conn->dest_addr.hostname.port = utils_get_port_from_addr(addr); new_conn->dest_addr.hostname.addr = strdup(on_entry->hostname); if (!new_conn->dest_addr.hostname.addr) { ret_errno = ENOMEM; goto error_free; } } else { /* * Check if address is localhost. At this point, we are sure it's not a * .onion cookie address that is by default in the loopback network * thus this check is done after the onion entry lookup. */ if (utils_sockaddr_is_localhost(addr)) { /* * Certain setups need to be able to reach localhost, despite * running torsocks. If they enabled the config option, allow such * connections. */ if (tsocks_config.allow_outbound_localhost) { goto libc_connect; } WARN("[connect] Connection to a local address are denied since it " "might be a TCP DNS query to a local DNS server. " "Rejecting it for safety reasons."); errno = EPERM; goto error; } new_conn = connection_create(sockfd, addr); if (!new_conn) { errno = ENOMEM; goto error; } } /* Connect the socket to the Tor network. */ ret = tsocks_connect_to_tor(new_conn); if (ret < 0) { ret_errno = -ret; goto error_free; } connection_registry_lock(); /* This can't fail since a lookup was done previously. */ connection_insert(new_conn); connection_registry_unlock(); /* Flag errno for success */ ret = errno = 0; return ret; libc_connect: return tsocks_libc_connect(LIBC_CONNECT_ARGS); error_free: /* * Put back reference of newly created connection. Will be freed if * refcount goes down to 0. */ connection_put_ref(new_conn); errno = ret_errno; error: /* At this point, errno MUST be set to a valid connect() error value. */ return -1; }
/* * Torsocks call for connect(2). */ LIBC_CONNECT_RET_TYPE tsocks_connect(LIBC_CONNECT_SIG) { int ret, sock_type; socklen_t optlen; struct connection *new_conn; struct onion_entry *on_entry; struct sockaddr_in *inet_addr; DBG("Connect catched on fd %d", __sockfd); optlen = sizeof(sock_type); ret = getsockopt(__sockfd, SOL_SOCKET, SO_TYPE, &sock_type, &optlen); if (ret < 0) { /* Use the getsockopt() errno value. */ goto error; } /* We can't handle a non inet socket. */ if (__addr->sa_family != AF_INET && __addr->sa_family != AF_INET6) { DBG("[conect] Connection is not IPv4/v6. Ignoring."); goto libc_connect; } /* * Refuse non stream socket. There is a chance that this might be a DNS * request that we can't pass through Tor using raw UDP packet. */ if (sock_type != SOCK_STREAM) { WARN("[connect] UDP or ICMP stream can't be handled. Rejecting."); errno = EBADF; goto error; } DBG("[connect] Socket family %s and type %d", __addr->sa_family == AF_INET ? "AF_INET" : "AF_INET6", sock_type); inet_addr = (struct sockaddr_in *) __addr; /* * Lock registry to get the connection reference if one. In this code path, * if a connection object is found, it will not be used since a double * connect() on the same file descriptor is an error so the registry is * quickly unlocked and no reference is needed. */ connection_registry_lock(); new_conn = connection_find(__sockfd); connection_registry_unlock(); if (new_conn) { /* Double connect() for the same fd. */ errno = EISCONN; goto error; } /* * See if the IP being connected is an onion IP cookie mapping to an * existing .onion address. */ onion_pool_lock(&tsocks_onion_pool); on_entry = onion_entry_find_by_ip(inet_addr->sin_addr.s_addr, &tsocks_onion_pool); onion_pool_unlock(&tsocks_onion_pool); if (on_entry) { /* * Create a connection without a destination address since we will set * the onion address name found before. */ new_conn = connection_create(__sockfd, NULL); if (!new_conn) { errno = ENOMEM; goto error; } new_conn->dest_addr.domain = CONNECTION_DOMAIN_NAME; new_conn->dest_addr.hostname.addr = strdup(on_entry->hostname); new_conn->dest_addr.hostname.port = inet_addr->sin_port; } else { /* * Check if address is local IPv4. At this point, we are sure it's not * a .onion cookie address that is by default in the loopback network. */ if (__addr->sa_family == AF_INET && utils_is_ipv4_local(inet_addr->sin_addr.s_addr)) { WARN("[connect] Connection to a local address are denied since it " "might be a TCP DNS query to a local DNS server. " "Rejecting it for safety reasons."); errno = EPERM; goto error; } new_conn = connection_create(__sockfd, __addr); if (!new_conn) { errno = ENOMEM; goto error; } } /* Connect the socket to the Tor network. */ ret = tsocks_connect_to_tor(new_conn); if (ret < 0) { errno = -ret; goto error; } connection_registry_lock(); /* This can't fail since a lookup was done previously. */ connection_insert(new_conn); connection_registry_unlock(); /* Flag errno for success */ ret = errno = 0; return ret; libc_connect: return tsocks_libc_connect(LIBC_CONNECT_ARGS); error: /* At this point, errno MUST be set to a valid connect() error value. */ return -1; }
int lwm2mclient_main() { client_data_t data; int result; lwm2m_context_t * lwm2mH = NULL; int i; const char * localPort = "56830"; //const char * server = "beta-devices.zatar.com"; const char * server = "leshan.eclipse.org"; //const char * server = "5.39.83.206"; const char * serverPort = LWM2M_STANDARD_PORT_STR; char * name = "ZebraBlr"; int lifetime = 300; int batterylevelchanging = 0; time_t reboot_time = 0; int opt; bool bootstrapRequested = false; #ifdef LWM2M_BOOTSTRAP lwm2m_bootstrap_state_t previousBootstrapState = NOT_BOOTSTRAPPED; #endif /* * The function start by setting up the command line interface (which may or not be useful depending on your project) * * This is an array of commands describes as { name, description, long description, callback, userdata }. * The firsts tree are easy to understand, the callback is the function that will be called when this command is typed * and in the last one will be stored the lwm2m context (allowing access to the server settings and the objects). */ command_desc_t commands[] = { {"list", "List known servers.", NULL, prv_output_servers, NULL}, {"change", "Change the value of resource.", " change URI [DATA]\r\n" " URI: uri of the resource such as /3/0, /3/0/2\r\n" " DATA: (optional) new value\r\n", prv_change, NULL}, {"update", "Trigger a registration update", " update SERVER\r\n" " SERVER: short server id such as 123\r\n", prv_update, NULL}, #ifdef LWM2M_BOOTSTRAP {"bootstrap", "Initiate a DI bootstrap process", NULL, prv_initiate_bootstrap, NULL}, {"disp", "Display current objects/instances/resources", NULL, prv_display_objects, NULL}, {"dispb", "Display current backup of objects/instances/resources\r\n" "\t(only security and server objects are backupped)", NULL, prv_display_backup, NULL}, #endif {"ls", "List Objects and Instances", NULL, prv_object_list, NULL}, {"dump", "Dump an Object", "dump URI" "URI: uri of the Object or Instance such as /3/0, /1\r\n", prv_object_dump, NULL}, {"quit", "Quit the client gracefully.", NULL, prv_quit, NULL}, {"^C", "Quit the client abruptly (without sending a de-register message).", NULL, NULL, NULL}, COMMAND_END_LIST }; memset(&data, 0, sizeof(client_data_t)); /* Zebra change: Reddy while ((opt = getopt(argc, argv, "bcl:n:p:t:h:")) != -1) { switch (opt) { case 'b': bootstrapRequested = true; break; case 'c': batterylevelchanging = 1; break; case 't': sscanf(optarg, "%d", &lifetime); break; case 'n': name = optarg; break; case 'l': localPort = optarg; break; case 'h': server = optarg; break; case 'p': serverPort = optarg; break; default: print_usage(); return 0; } } */ /* *This call an internal function that create an IPV6 socket on the port 5683. */ fprintf(stderr, "Trying to bind LWM2M Client to port %s\r\n", localPort); data.sock = create_socket(localPort); if (data.sock < 0) { fprintf(stderr, "Failed to open socket: %d\r\n", errno); return -1; } /* * Now the main function fill an array with each object, this list will be later passed to liblwm2m. * Those functions are located in their respective object file. */ char serverUri[50]; int serverId = 123; sprintf (serverUri, "coap://%s:%s", server, serverPort); fprintf(stderr, " LWM2M serverUri %s\r\n", serverUri); #ifdef LWM2M_BOOTSTRAP objArray[0] = get_security_object(serverId, serverUri, bootstrapRequested); #else objArray[0] = get_security_object(serverId, serverUri, false); #endif if (NULL == objArray[0]) { fprintf(stderr, "Failed to create security object\r\n"); return -1; } data.securityObjP = objArray[0]; objArray[1] = get_server_object(serverId, "U", lifetime, false); if (NULL == objArray[1]) { fprintf(stderr, "Failed to create server object\r\n"); return -1; } objArray[2] = get_object_device(); if (NULL == objArray[2]) { fprintf(stderr, "Failed to create Device object\r\n"); return -1; } objArray[3] = get_object_firmware(); if (NULL == objArray[3]) { fprintf(stderr, "Failed to create Firmware object\r\n"); return -1; } objArray[4] = get_object_location(); if (NULL == objArray[4]) { fprintf(stderr, "Failed to create location object\r\n"); return -1; } objArray[5] = get_test_object(); if (NULL == objArray[5]) { fprintf(stderr, "Failed to create test object\r\n"); return -1; } objArray[6] = get_object_conn_m(); if (NULL == objArray[6]) { fprintf(stderr, "Failed to create connectivity monitoring object\r\n"); return -1; } objArray[7] = get_object_conn_s(); if (NULL == objArray[7]) { fprintf(stderr, "Failed to create connectivity statistics object\r\n"); return -1; } int instId = 0; objArray[8] = acc_ctrl_create_object(); if (NULL == objArray[8]) { fprintf(stderr, "Failed to create Access Control object\r\n"); return -1; } else if (acc_ctrl_obj_add_inst(objArray[8], instId, 3, 0, serverId)==false) { fprintf(stderr, "Failed to create Access Control object instance\r\n"); return -1; } else if (acc_ctrl_oi_add_ac_val(objArray[8], instId, 0, 0b000000000001111)==false) { fprintf(stderr, "Failed to create Access Control ACL default resource\r\n"); return -1; } else if (acc_ctrl_oi_add_ac_val(objArray[8], instId, 999, 0b000000000000001)==false) { fprintf(stderr, "Failed to create Access Control ACL resource for serverId: 999\r\n"); return -1; } /* * The liblwm2m library is now initialized with the functions that will be in * charge of communication */ lwm2mH = lwm2m_init(prv_connect_server, prv_buffer_send, &data); if (NULL == lwm2mH) { fprintf(stderr, "lwm2m_init() failed\r\n"); return -1; } #ifdef LWM2M_BOOTSTRAP /* * Bootstrap state initialization */ if (bootstrapRequested) { lwm2mH->bsState = BOOTSTRAP_REQUESTED; } else { lwm2mH->bsState = NOT_BOOTSTRAPPED; } #endif /* * We configure the liblwm2m library with the name of the client - which shall be unique for each client - * the number of objects we will be passing through and the objects array */ result = lwm2m_configure(lwm2mH, name, NULL, NULL, OBJ_COUNT, objArray); if (result != 0) { fprintf(stderr, "lwm2m_configure() failed: 0x%X\r\n", result); return -1; } signal(SIGINT, handle_sigint); /* * This function start your client to the LWM2M servers */ result = lwm2m_start(lwm2mH); if (result != 0) { fprintf(stderr, "lwm2m_start() failed: 0x%X\r\n", result); return -1; } /** * Initialize value changed callback. */ init_value_change(lwm2mH); /* * As you now have your lwm2m context complete you can pass it as an argument to all the command line functions * precedently viewed (first point) */ for (i = 0 ; commands[i].name != NULL ; i++) { commands[i].userData = (void *)lwm2mH; } fprintf(stdout, "LWM2M Client \"%s\" started on port %s\r\n", name, localPort); fprintf(stdout, "> "); fflush(stdout); /* * We now enter in a while loop that will handle the communications from the server */ while (0 == g_quit) { struct timeval tv; fd_set readfds; if (g_reboot) { time_t tv_sec; tv_sec = lwm2m_gettime(); if (0 == reboot_time) { reboot_time = tv_sec + 5; } if (reboot_time < tv_sec) { /* * Message should normally be lost with reboot ... */ fprintf(stderr, "reboot time expired, rebooting ..."); system_reboot(); } else { tv.tv_sec = reboot_time - tv_sec; } } else if (batterylevelchanging) { update_battery_level(lwm2mH); tv.tv_sec = 5; } else { tv.tv_sec = 60; } tv.tv_usec = 0; FD_ZERO(&readfds); FD_SET(data.sock, &readfds); FD_SET(STDIN_FILENO, &readfds); /* * This function does two things: * - first it does the work needed by liblwm2m (eg. (re)sending some packets). * - Secondly it adjusts the timeout value (default 60s) depending on the state of the transaction * (eg. retransmission) and the time between the next operation */ result = lwm2m_step(lwm2mH, &(tv.tv_sec)); if (result != 0) { fprintf(stderr, "lwm2m_step() failed: 0x%X\r\n", result); return -1; } #ifdef LWM2M_BOOTSTRAP update_bootstrap_info(&previousBootstrapState, lwm2mH); #endif /* * This part will set up an interruption until an event happen on SDTIN or the socket until "tv" timed out (set * with the precedent function) */ //result = select(FD_SETSIZE, &readfds, NULL, NULL, &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 an event happens on the socket */ if (FD_ISSET(data.sock, &readfds)) { //struct sockaddr_storage addr; struct sockaddr addr; uint32 addrLen; addrLen = sizeof(addr); /* * We retrieve the data received */ //numBytes = recvfrom(data.sock, buffer, MAX_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrLen); numBytes = recvfrom(data.sock, buffer, MAX_PACKET_SIZE,0); if (0 > numBytes) { fprintf(stderr, "Error in recvfrom(): %d\r\n", errno); } else if (0 < numBytes) { char s[INET6_ADDRSTRLEN]; uint16 port; connection_t * connP; if (AF_INET == addr.sa_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)); /* * Display it in the STDERR */ output_buffer(stderr, buffer, numBytes, 0); connP = connection_find(data.connList, &addr, addrLen); if (connP != NULL) { /* * Let liblwm2m respond to the query depending on the context */ lwm2m_handle_packet(lwm2mH, buffer, numBytes, connP); conn_s_updateRxStatistic(objArray[7], numBytes, false); } else { fprintf(stderr, "received bytes ignored!\r\n"); } } } /* * If the event happened on the SDTIN */ else if (FD_ISSET(STDIN_FILENO, &readfds)) { numBytes = read(STDIN_FILENO, buffer, MAX_PACKET_SIZE - 1); if (numBytes > 1) { buffer[numBytes] = 0; fprintf(stderr, "STDIN %d bytes '%s'\r\n> ", numBytes, buffer); /* * We call the corresponding callback of the typed command passing it the buffer for further arguments */ handle_command(commands, (char*)buffer); } if (g_quit == 0) { fprintf(stdout, "\r\n> "); fflush(stdout); } else { fprintf(stdout, "\r\n"); } } } } /* * Finally when the loop is left smoothly - asked by user in the command line interface - we unregister our client from it */ if (g_quit == 1) { #ifdef LWM2M_BOOTSTRAP close_backup_object(); #endif lwm2m_close(lwm2mH); } close(data.sock); connection_free(data.connList); return 0; }