void NetworkAddress_Free(NetworkAddress ** address) { // TODO - review when addresses are freed (e.g. after client bootstrap, or connection lost ?) if (address && *address) { (*address)->useCount--; if ((*address)->useCount == 0) { int index; for (index = 0; index < MAX_NETWORK_ADDRESS_CACHE; index++) { if (networkAddressCache[index].address == *address) { if (networkAddressCache[index].uri) { Lwm2m_Debug("Address free: %s\n", networkAddressCache[index].uri); free(networkAddressCache[index].uri); networkAddressCache[index].uri = NULL; } else { Lwm2m_Debug("Address free\n"); } networkAddressCache[index].address = NULL; break; } } free(*address); } *address = NULL; } }
void coap_SendNotify(AddressType * addr, const char * path, const char * token, int tokenSize, ContentType contentType, const char * payload, int payloadLen, int sequence) { coap_packet_t notify; coap_transaction_t *transaction; Lwm2m_Debug("Coap notify: %s\n", path); Lwm2m_Debug("Coap IPv6 request address: " PRINT6ADDR(&addr->Addr)); Lwm2m_Debug("Coap request port: %d\n", addr->Port); coap_init_message(¬ify, COAP_TYPE_NON, CONTENT_2_05, coap_get_mid()); if (contentType != ContentType_None) { coap_set_header_content_format(¬ify, contentType); coap_set_payload(¬ify, payload, payloadLen); } coap_set_token(¬ify, token, tokenSize); coap_set_header_observe(¬ify, sequence); if ((transaction = coap_new_transaction(notify.mid, &addr->Addr, uip_htons(addr->Port)))) { transaction->packet_len = coap_serialize_message(¬ify, transaction->packet); coap_send_transaction(transaction); // for NON confirmable messages this will call coap_clear_transaction(); } }
static void addCachedAddress(NetworkAddress * address, const char * uri, int uriLength) { if (address) { int index; for (index = 0; index < MAX_NETWORK_ADDRESS_CACHE; index++) { if (networkAddressCache[index].address == NULL) { if (uri && uriLength > 0) { networkAddressCache[index].uri = (char *)malloc(uriLength + 1); if (networkAddressCache[index].uri) { memcpy(networkAddressCache[index].uri, uri, uriLength); networkAddressCache[index].uri[uriLength] = 0; networkAddressCache[index].address = address; Lwm2m_Debug("Address add: %s\n", networkAddressCache[index].uri); } } else { networkAddressCache[index].address = address; networkAddressCache[index].uri = NULL; Lwm2m_Debug("Address add (received)\n"); // TODO - print remote address } break; } } } }
static NetworkAddress * getCachedAddress(NetworkAddress * matchAddress, const char * uri, int uriLength) { NetworkAddress * result = NULL; int index; for (index = 0; index < MAX_NETWORK_ADDRESS_CACHE; index++) { NetworkAddress * address = networkAddressCache[index].address; if (address) { if (NetworkAddress_Compare(matchAddress, address) == 0) { if (uri && uriLength > 0 && networkAddressCache[index].uri == NULL) { // Add info to cached address address->Secure = matchAddress->Secure; networkAddressCache[index].uri = (char *)malloc(uriLength + 1); if (networkAddressCache[index].uri) { memcpy(networkAddressCache[index].uri, uri, uriLength); networkAddressCache[index].uri[uriLength] = 0; Lwm2m_Debug("Address add uri: %s\n", networkAddressCache[index].uri); } } result = address; break; } } } return result; }
void coap_SendNotify(AddressType * addr, const char * path, const char * token, int tokenSize, ContentType contentType, const char * payload, int payloadLen, int sequence) { // TODO - FIXME: if path is not full uri then map addr to Network address + append path(?) coap_packet_t notify; coap_transaction_t *transaction; NetworkAddress * remoteAddress = NetworkAddress_New(path, strlen(path)); Lwm2m_Debug("Coap notify: %s\n", path); //Lwm2m_Debug("Coap IPv6 request address: " PRINT6ADDR(&addr->Addr)); //Lwm2m_Debug("Coap request port: %d\n", addr->Port); coap_init_message(¬ify, COAP_TYPE_NON, CONTENT_2_05, coap_get_mid()); if (contentType != ContentType_None) { coap_set_header_content_format(¬ify, contentType); coap_set_payload(¬ify, payload, payloadLen); } coap_set_token(¬ify, token, tokenSize); coap_set_header_observe(¬ify, sequence); if ((transaction = coap_new_transaction(networkSocket, notify.mid, remoteAddress))) { transaction->packet_len = coap_serialize_message(¬ify, transaction->packet); coap_send_transaction(transaction); // for NON confirmable messages this will call coap_clear_transaction(); } }
// Handler called when the server posts a "finished" message to /bs static int BootStrapPost(void * ctxt, AddressType * addr, const char * path, const char * query, ContentType contentType, const char * requestContent, size_t requestContentLen, char * responseContent, size_t * responseContentLen, int * responseCode) { Lwm2mContextType * context = (Lwm2mContextType *)ctxt; Lwm2mBootStrapState state = Lwm2mCore_GetBootstrapState(context); *responseContentLen = 0; // no content Lwm2m_Debug("POST to /bs\n"); if (state == Lwm2mBootStrapState_BootStrapFinishPending) { Lwm2m_Info("Bootstrap finished\n"); Lwm2mCore_SetBootstrapState(context, Lwm2mBootStrapState_BootStrapped); Lwm2mCore_UpdateAllServers(context, Lwm2mRegistrationState_Register); *responseCode = AwaResult_SuccessChanged; } else if ((state == Lwm2mBootStrapState_BootStrapPending) || (state == Lwm2mBootStrapState_ClientHoldOff)) { Lwm2m_Info("Server initiated bootstrap\n"); Lwm2mCore_SetBootstrapState(context, Lwm2mBootStrapState_BootStrapped); Lwm2mCore_UpdateAllServers(context, Lwm2mRegistrationState_Register); *responseCode = AwaResult_SuccessChanged; } else { *responseCode = AwaResult_BadRequest; } return 0; }
static bool BootStrapFromSmartCard(Lwm2mContextType * context) { // not implemented Lwm2m_Debug("Lwm2m_BootstrapFromSmartCard\n"); return false; }
static int connectivityStatisticsStartOrReset(void * context, ObjectIDType objectID, ObjectInstanceIDType objectInstanceID, ResourceIDType resourceID, uint8_t * inValueBuffer, size_t inValueBufferLen) { Lwm2m_Debug("Reset/Start Connectivity Statistics"); // Not implemented return 0; }
static int executeUpdate(void * context, ObjectIDType objectID, ObjectInstanceIDType objectInstanceID, ResourceIDType resourceID, uint8_t * inValueBuffer, size_t inValueBufferLen) { Lwm2m_Debug("Firmware Update resource executed\n"); #ifndef CONTIKI // Fire IPC notifications to any subscribers. xmlif_ExecuteResourceHandler(context, objectID, objectInstanceID, resourceID, inValueBuffer, inValueBufferLen); #endif return 0; }
uip_ipaddr_t * getHostByName(const char *hostName) { uip_ipaddr_t * result = NULL; static uip_ipaddr_t ipaddr; if (uiplib_ipaddrconv(hostName, &ipaddr) == 0) { uip_ipaddr_t *resolved_addr = NULL; resolv_status_t status = resolv_lookup(hostName, &resolved_addr); if (status == RESOLV_STATUS_UNCACHED || status == RESOLV_STATUS_EXPIRED) { Lwm2m_Debug("Attempting to look up %s\n", hostName); resolv_query(hostName); status = RESOLV_STATUS_RESOLVING; } else if (status == RESOLV_STATUS_CACHED && resolved_addr != NULL ) { Lwm2m_Debug("Lookup of \"%s\" succeeded!\n", hostName); } else if (status == RESOLV_STATUS_RESOLVING) { resolved_addr = NULL; Lwm2m_Debug("Still looking up \"%s\"...\n", hostName); } else { resolved_addr = NULL; Lwm2m_Debug("Lookup of \"%s\" failed. status = %d\n", hostName, status); } if (resolved_addr) { uip_ipaddr_copy(&ipaddr, resolved_addr); result = &ipaddr; } } else { result = &ipaddr; Lwm2m_Debug("Cache hit on look up %s\n", hostName); } return result; }
static void RegisterObjects(Lwm2mContextType * context, Options * options) { Lwm2m_Debug("Register built-in objects\n"); Lwm2m_RegisterSecurityObject(context); if (options->BootStrap != NULL) { Lwm2m_PopulateSecurityObject(context, options->BootStrap); } Lwm2m_RegisterServerObject(context); Lwm2m_RegisterACLObject(context); }
void coap_createCoapRequest(void * context, coap_method_t method, const char * uri, ContentType contentType, const char * payload, int payloadLen, TransactionCallback callback) { coap_packet_t request; uip_ipaddr_t * remote_ipaddr = coap_getIpFromURI(uri); int remote_port = coap_getPortFromURI(uri); coap_transaction_t *transaction; char path[128] = {0}; char query[128] = {0}; coap_getPathQueryFromURI(uri, path, query); Lwm2m_Debug("Coap request: %s\n", uri); Lwm2m_Debug("Coap IPv6 request address: " PRINT6ADDR(remote_ipaddr)); Lwm2m_Debug("Coap request port: %d\n", remote_port); Lwm2m_Debug("Coap request path: %s\n", path); Lwm2m_Debug("Coap request query: %s\n", query); coap_init_message(&request, COAP_TYPE_CON, method, coap_get_mid()); coap_set_header_uri_path(&request, path); coap_set_header_uri_query(&request, query); if (contentType != ContentType_None) { coap_set_header_content_format(&request, contentType); coap_set_payload(&request, payload, payloadLen); } if (CurrentTransaction[CurrentTransactionIndex].TransactionUsed && CurrentTransaction[CurrentTransactionIndex].TransactionPtr) { Lwm2m_Warning("Canceled previous transaction [%d]: %p\n", CurrentTransactionIndex, CurrentTransaction[CurrentTransactionIndex].TransactionPtr); coap_clear_transaction(CurrentTransaction[CurrentTransactionIndex].TransactionPtr); } if ((transaction = coap_new_transaction(request.mid, remote_ipaddr, uip_htons(remote_port)))) { transaction->callback = coap_CoapRequestCallback; CurrentTransaction[CurrentTransactionIndex].Callback = callback; CurrentTransaction[CurrentTransactionIndex].Context = context; CurrentTransaction[CurrentTransactionIndex].TransactionUsed = true; CurrentTransaction[CurrentTransactionIndex].TransactionPtr = transaction; memcpy(&CurrentTransaction[CurrentTransactionIndex].Address.Addr, remote_ipaddr, sizeof(uip_ipaddr_t)); CurrentTransaction[CurrentTransactionIndex].Address.Port = uip_htons(remote_port); transaction->callback_data = &CurrentTransaction[CurrentTransactionIndex]; transaction->packet_len = coap_serialize_message(&request, transaction->packet); Lwm2m_Debug("Sending transaction [%d]: %p\n", CurrentTransactionIndex, CurrentTransaction[CurrentTransactionIndex].TransactionPtr); coap_send_transaction(transaction); CurrentTransactionIndex++; if(CurrentTransactionIndex >= MAX_COAP_TRANSACTIONS) { CurrentTransactionIndex = 0; } } }
int coap_RegisterUri(const char * uri) { resource_t * temp = malloc(sizeof(resource_t)); char * uriCopy = strdup(&uri[1]); Lwm2m_Debug("register %s\n", uriCopy); memcpy(temp, &rest_resource_template, sizeof(resource_t)); rest_activate_resource(temp, uriCopy); return 0; }
int coap_ResolveAddressByURI(unsigned char * address, AddressType * addr) { int result = -1; Lwm2m_Debug("resolve address from Uri: %s\n", address); NetworkAddress * networkAddress = NetworkAddress_New(address, strlen(address)); if (networkAddress) { NetworkAddress_SetAddressType(networkAddress, addr); NetworkAddress_Free(&networkAddress); result = 0; } return result; }
Lwm2mContextType * Lwm2mCore_Init(CoapInfo * coap, ContentType contentType) { Lwm2m_Debug("Create object store\n"); Lwm2mContextType * context = &Lwm2mContext; context->Coap = coap; context->Store = ObjectStore_Create(); context->Definitions = DefinitionRegistry_Create(); context->ContentType = contentType; Lwm2mEndPoint_InitEndPointList(&context->EndPointList); coap_SetContext(context); coap_SetRequestHandler(Lwm2mCore_HandleRequest); // Initialise registration data, i.e tables for storing client information Lwm2m_RegistrationInit(context); return context; }
bool readUDP(NetworkSocket * networkSocket, uint8_t * buffer, int bufferLength, NetworkAddress ** sourceAddress, int *readLength) { bool result = true; *readLength = 0; //if (uip_newdata() && (UIP_IP_BUF->destport == networkSocket->Port) ) if (uip_newdata()) { Lwm2m_Debug("Packet from: %d %d\n", UIP_IP_BUF->destport, networkSocket->Port); if (uip_datalen() > bufferLength) *readLength = bufferLength; else *readLength = uip_datalen(); } if (*readLength > 0) { memcpy(buffer, uip_appdata, *readLength); NetworkAddress * networkAddress = NULL; NetworkAddress matchAddress; size_t size = sizeof(struct _NetworkAddress); memset(&matchAddress, 0, size); memcpy(&matchAddress.Address, &UIP_IP_BUF->srcipaddr, sizeof(uip_ipaddr_t)); matchAddress.Port = UIP_IP_BUF->srcport; //uip_ntohs(UIP_UDP_BUF->srcport); matchAddress.Secure = (networkSocket->SocketType & NetworkSocketType_Secure) == NetworkSocketType_Secure; networkAddress = getCachedAddress(&matchAddress, NULL, 0); if (networkAddress == NULL) { networkAddress = addCachedAddress(NULL, 0); if (networkAddress) { // Add new address to cache (note: uri and secure is unknown) memcpy(networkAddress, &matchAddress, size); networkAddress->useCount++; // TODO - ensure addresses are freed? (after t/o or transaction or DTLS session closed) } } if (networkAddress) { *sourceAddress = networkAddress; } } return result; }
static NetworkAddress * addCachedAddress(const char * uri, int uriLength) { NetworkAddress * result = NULL; int index; for (index = 0; index < MAX_NETWORK_ADDRESS_CACHE; index++) { if (!networkAddressCache[index].InUse) { if (uri && uriLength > 0) { memcpy(networkAddressCache[index].Uri, uri, uriLength); networkAddressCache[index].Uri[uriLength] = 0; Lwm2m_Debug("Address add: %s\n", networkAddressCache[index].Uri); } networkAddressCache[index].InUse = true; result = &networkAddressCache[index].Address; break; } } return result; }
void NetworkAddress_Free(NetworkAddress ** address) { // TODO - review when addresses are freed (e.g. after client bootstrap, or connection lost ?) if (address && *address) { (*address)->useCount--; if ((*address)->useCount == 0) { int index; for (index = 0; index < MAX_NETWORK_ADDRESS_CACHE; index++) { if (NetworkAddress_Compare(&networkAddressCache[index].Address, *address) == 0) { Lwm2m_Debug("Address free\n"); networkAddressCache[index].InUse = false; memset(&networkAddressCache[index].Address, 0, sizeof(struct _NetworkAddress)); break; } } } *address = NULL; } }
bool readUDP(NetworkSocket * networkSocket, uint8_t * buffer, int bufferLength, NetworkAddress ** sourceAddress, int *readLength) { bool result = true; *readLength = 0; //if (uip_newdata() && (UIP_IP_BUF->destport == networkSocket->Port) ) if (uip_newdata()) { Lwm2m_Debug("Packet from: %d %d\n", uip_htons(UIP_IP_BUF->destport), networkSocket->Port); if (uip_datalen() > bufferLength) *readLength = bufferLength; else *readLength = uip_datalen(); } if (*readLength > 0) { uip_ipaddr_t * address = &UIP_IP_BUF->srcipaddr; uint16_t port = uip_htons(UIP_IP_BUF->srcport); bool secure = (networkSocket->SocketType & NetworkSocketType_Secure) == NetworkSocketType_Secure; memcpy(buffer, uip_appdata, *readLength); NetworkAddress * networkAddress = getCachedAddress(address, port); if (networkAddress == NULL) { networkAddress = addCachedAddress(address, port, secure); if (networkAddress) { networkAddress->useCount++; // TODO - ensure addresses are freed? (after t/o or transaction or DTLS session closed) } } if (networkAddress) { *sourceAddress = networkAddress; } } return result; }
int Lwm2mCore_GetIPAddressFromInterface(const char * interface, int addressFamily, char * destAddress, size_t destAddressLength) { int returnCode = 0; if (addressFamily != AF_INET && addressFamily != AF_INET6) { Lwm2m_Error("Unsupported address family: %d. Only AF_INET and AF_INET6 are supported.\n", addressFamily); returnCode = 1; goto error; } struct ifaddrs *interfaceAddresses, *interfaceAddress; char host[NI_MAXHOST]; if (getifaddrs(&interfaceAddresses) == -1) { perror("getifaddrs"); returnCode = 1; goto error; } char linkLocalIpv6Address[NI_MAXHOST] = { 0 }; char globalIpv6Address[NI_MAXHOST] = { 0 }; bool found = false; int index = 0; for (interfaceAddress = interfaceAddresses; interfaceAddress != NULL; interfaceAddress = interfaceAddress->ifa_next) { if (interfaceAddress->ifa_addr == NULL) { continue; } if ((strcmp(interfaceAddress->ifa_name, interface)==0)&&(interfaceAddress->ifa_addr->sa_family==addressFamily)) { int socketAddressLength = 0; switch(addressFamily) { case AF_INET: socketAddressLength = sizeof(struct sockaddr_in); break; default: socketAddressLength = sizeof(struct sockaddr_in6); break; } returnCode = getnameinfo(interfaceAddress->ifa_addr, socketAddressLength, host, sizeof(host), NULL, 0, NI_NUMERICHOST); if (returnCode != 0) { Lwm2m_Error("getnameinfo() failed: %s\n", gai_strerror(returnCode)); goto error_free; } size_t addressLength = strlen(host); if (destAddressLength < addressLength) { Lwm2m_Error("Error: Address is longer than %zu characters\n", destAddressLength); goto error_free; } switch(addressFamily) { case AF_INET: strcpy(destAddress, host); found = true; break; default: if (strncmp(host, "fe80", 4) == 0) { Lwm2m_Debug("Address %d: %s (local)\n", index, host); strcpy(linkLocalIpv6Address, host); } else { Lwm2m_Debug("Address %d: %s (global)\n", index, host); strcpy(globalIpv6Address, host); } break; } index++; } } if (addressFamily == AF_INET6) { if (strlen(globalIpv6Address) > 0) { Lwm2m_Debug("Global IPv6 address found for interface %s: %s\n", interface, globalIpv6Address); strcpy(destAddress, globalIpv6Address); found = true; } else if (strlen(linkLocalIpv6Address) > 0) { Lwm2m_Warning("No global IPv6 address found for interface %s: using local: %s\n", interface, linkLocalIpv6Address); strcpy(destAddress, linkLocalIpv6Address); found = true; } } if (!found) { Lwm2m_Error("Could not find an %s IP address for interface %s\n", addressFamily == AF_INET? "IPv4" : "IPv6", interface); returnCode = 1; } error_free: freeifaddrs(interfaceAddresses); error: return returnCode; }
static int coap_HandleRequest(void *packet, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { int result = 1; const char *url = NULL; int urlLen = 0; const uint8_t * payload = NULL; int payloadLen = 0; int content = -1; coap_packet_t * const request = (coap_packet_t *) packet; CoapResponse coapResponse = { .responseContent = buffer, .responseContentLen = preferred_size, .responseCode = 400, }; payloadLen = coap_get_payload(request, &payload); if ((urlLen = coap_get_header_uri_path(request, &url))) { char uriBuf[MAX_COAP_PATH] = { 0 }; rest_resource_flags_t method = (rest_resource_flags_t) (1 << (((coap_packet_t *) packet)->code - 1)); //coap_get_rest_method(request); uriBuf[0] = '/'; memcpy(&uriBuf[1], url, urlLen); char queryBuf[128] = "?"; const char * query = NULL; int queryLength = coap_get_header_uri_query(request, &query); if (queryLength > 0) memcpy(&queryBuf[1], query, queryLength); queryBuf[queryLength+1] = '\0'; CoapRequest coapRequest = { .ctxt = context, .addr = { 0 }, .path = uriBuf, .query = queryBuf, .token = request->token, .tokenLength = request->token_len, .requestContent = payload, .requestContentLen = payloadLen, }; NetworkAddress_SetAddressType(sourceAddress, &coapRequest.addr); switch (method) { case METHOD_GET: coap_get_header_accept(request, &content); coapRequest.contentType = content; int32_t observe; if (!coap_get_header_observe(request, &observe)) observe = -1; switch (observe) { case -1: Lwm2m_Debug("Coap GET for %s\n", uriBuf); coapRequest.type = COAP_GET_REQUEST; requestHandler(&coapRequest, &coapResponse); break; case 0: Lwm2m_Debug("Coap OBSERVE for %s\n", uriBuf); coapRequest.type = COAP_OBSERVE_REQUEST; requestHandler(&coapRequest, &coapResponse); coap_set_header_observe(response, 1); break; case 1: Lwm2m_Debug("Coap CANCEL OBSERVE for %s\n", uriBuf); coapRequest.type = COAP_CANCEL_OBSERVE_REQUEST; requestHandler(&coapRequest, &coapResponse); break; default: break; } coap_set_header_content_format(response, coapResponse.responseContentType); /* text/plain is the default, hence this option could be omitted. */ break; case METHOD_POST: coap_get_header_content_format(request, &content); coapRequest.contentType = content; coapRequest.type = COAP_POST_REQUEST; Lwm2m_Debug("Coap POST for %s\n", uriBuf); requestHandler(&coapRequest, &coapResponse); if (coapResponse.responseContentLen > 0 && coapResponse.responseCode == 201) { coap_set_header_location_path(response, coapResponse.responseContent); } break; case METHOD_PUT: coap_get_header_content_format(request, &content); coapRequest.contentType = content; coapRequest.type = COAP_PUT_REQUEST; Lwm2m_Debug("Coap PUT for %s\n", uriBuf); requestHandler(&coapRequest, &coapResponse); break; case METHOD_DELETE: coapRequest.contentType = ContentType_None; coapRequest.type = COAP_DELETE_REQUEST; Lwm2m_Debug("Coap DELETE for %s\n", uriBuf); requestHandler(&coapRequest, &coapResponse); break; default: break; } if (coapResponse.responseContentLen > 0 && coapResponse.responseCode == 205) { coap_set_payload(response, coapResponse.responseContent, coapResponse.responseContentLen); } } coap_set_status_code(response, COAP_RESPONSE_CODE(coapResponse.responseCode)); return result; }
void coap_createCoapRequest(coap_method_t method, const char * uri, ContentType contentType, ObserveState observeState, const char * payload, int payloadLen, TransactionCallback callback, void * context) { coap_packet_t request; char path[MAX_COAP_PATH] = { 0 }; char query[128] = { 0 }; coap_transaction_t *transaction; NetworkAddress * remoteAddress = NetworkAddress_New(uri, strlen(uri)); coap_getPathQueryFromURI(uri, path, query); Lwm2m_Info("Coap request: %s\n", uri); //Lwm2m_Debug("Coap request path: %s\n", path); //Lwm2m_Debug("Coap request query: %s\n", query); coap_init_message(&request, COAP_TYPE_CON, method, coap_get_mid()); coap_set_header_uri_path(&request, path); if (strlen(query) > 0) coap_set_header_uri_query(&request, query); // TODO - REVIEW: Erbium must copy path/query from request - else mem out of scope if (contentType != ContentType_None) { if ((method == COAP_POST) || (method == COAP_PUT)) { coap_set_header_content_format(&request, contentType); coap_set_payload(&request, payload, payloadLen); } else { coap_set_header_accept(&request, contentType); } } if (method == COAP_GET) { if (observeState == ObserveState_Establish) { coap_set_header_observe(&request, 0); int token = addObserve(remoteAddress, path, callback, context); if (token != 0) coap_set_token(&request, (const uint8_t *) &token, sizeof(token)); } else if (observeState == ObserveState_Cancel) { coap_set_header_observe(&request, 1); int token = removeObserve(remoteAddress, path); if (token != 0) coap_set_token(&request, (const uint8_t *) &token, sizeof(token)); } } if (CurrentTransaction[CurrentTransactionIndex].TransactionUsed && CurrentTransaction[CurrentTransactionIndex].TransactionPtr) { Lwm2m_Warning("Canceled previous transaction [%d]: %p\n", CurrentTransactionIndex, CurrentTransaction[CurrentTransactionIndex].TransactionPtr); coap_clear_transaction(&CurrentTransaction[CurrentTransactionIndex].TransactionPtr); } //if ((transaction = coap_new_transaction(request.mid, remote_ipaddr, uip_htons(remote_port)))) if ((transaction = coap_new_transaction(networkSocket, request.mid, remoteAddress))) { transaction->callback = coap_CoapRequestCallback; memcpy(CurrentTransaction[CurrentTransactionIndex].Path, path, MAX_COAP_PATH); CurrentTransaction[CurrentTransactionIndex].Callback = callback; CurrentTransaction[CurrentTransactionIndex].Context = context; CurrentTransaction[CurrentTransactionIndex].TransactionUsed = true; CurrentTransaction[CurrentTransactionIndex].TransactionPtr = transaction; NetworkAddress_SetAddressType(remoteAddress, &CurrentTransaction[CurrentTransactionIndex].Address); transaction->callback_data = &CurrentTransaction[CurrentTransactionIndex]; transaction->packet_len = coap_serialize_message(&request, transaction->packet); Lwm2m_Debug("Sending transaction [%d]: %p\n", CurrentTransactionIndex, CurrentTransaction[CurrentTransactionIndex].TransactionPtr); coap_send_transaction(transaction); CurrentTransactionIndex++; if (CurrentTransactionIndex >= MAX_COAP_TRANSACTIONS) { CurrentTransactionIndex = 0; } } }
static bool BootStrapFromFactory(Lwm2mContextType * context) { Lwm2m_Debug("Lwm2m_BootstrapFromFactory: %s\n", Lwm2mCore_GetUseFactoryBootstrap(context) ? "True" : "False"); return Lwm2mCore_GetUseFactoryBootstrap(context); }
static void coap_HandleResource(/*CoapRequestHandlerCallbacks * RequestCB,*/ void *packet, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { const char *url = NULL; int urlLen = 0; const uint8_t * payload = NULL; int payloadLen = 0; int content = -1; coap_packet_t *const request = (coap_packet_t *)packet; CoapResponse coapResponse = { .responseContent = buffer, .responseContentLen = preferred_size, .responseCode = 400, }; payloadLen = REST.get_request_payload(request, &payload); if ((urlLen = REST.get_url(request, &url))) { char uriBuf[64] = {0}; rest_resource_flags_t method = REST.get_method_type(request); uriBuf[0] = '/'; memcpy(&uriBuf[1], url, urlLen); const char * query = NULL; REST.get_query(request, &query); CoapRequest coapRequest = { .ctxt = context, .addr = { 0 }, .path = uriBuf, .query = query, .token = request->token, .tokenLength = request->token_len, .requestContent = payload, .requestContentLen = payloadLen, }; memcpy(&coapRequest.addr.Addr, &UIP_IP_BUF->srcipaddr, sizeof(uip_ipaddr_t)); coapRequest.addr.Port = uip_ntohs(UIP_UDP_BUF->srcport); switch(method) { case METHOD_GET: REST.get_header_accept(request, &content); coapRequest.contentType = content; int32_t observe; if (!coap_get_header_observe(request, &observe)) observe = -1; switch(observe) { case -1: Lwm2m_Debug("Coap GET for %s\n", uriBuf); coapRequest.type = COAP_GET_REQUEST; requestHandler(&coapRequest, &coapResponse); break; case 0: Lwm2m_Debug("Coap OBSERVE for %s\n", uriBuf); coapRequest.type = COAP_OBSERVE_REQUEST; requestHandler(&coapRequest, &coapResponse); coap_set_header_observe(response, 1); break; case 1: Lwm2m_Debug("Coap CANCEL OBSERVE for %s\n", uriBuf); coapRequest.type = COAP_CANCEL_OBSERVE_REQUEST; requestHandler(&coapRequest, &coapResponse); break; default: break; } REST.set_header_content_type(response, coapResponse.responseContentType); /* text/plain is the default, hence this option could be omitted. */ break; case METHOD_POST: REST.get_header_content_type(request, &content); coapRequest.contentType = content; coapRequest.type = COAP_POST_REQUEST; Lwm2m_Debug("Coap POST for %s\n", uriBuf); requestHandler(&coapRequest, &coapResponse); break; case METHOD_PUT: REST.get_header_content_type(request, &content); coapRequest.contentType = content; coapRequest.type = COAP_PUT_REQUEST; Lwm2m_Debug("Coap PUT for %s\n", uriBuf); requestHandler(&coapRequest, &coapResponse); break; case METHOD_DELETE: coapRequest.contentType = ContentType_None; coapRequest.type = COAP_DELETE_REQUEST; Lwm2m_Debug("Coap DELETE for %s\n", uriBuf); requestHandler(&coapRequest, &coapResponse); break; default: break; } if (coapResponse.responseContentLen > 0 && coapResponse.responseCode == 205 ) { REST.set_response_payload(response, coapResponse.responseContent, coapResponse.responseContentLen); } } REST.set_response_status(response, COAP_RESPONSE_CODE(coapResponse.responseCode)); }
static int Bootstrap_Start(Options * options) { int result = 0; if (options->Daemonise) { Daemonise(options->Verbose); } else { signal(SIGINT, CtrlCSignalHandler); } signal(SIGTERM, CtrlCSignalHandler); // open log files here if (options->LogFile) { errno = 0; logFile = fopen(options->LogFile, "at"); if (logFile != NULL) { Lwm2m_SetOutput(logFile); // redirect stdout dup2(fileno(logFile), STDOUT_FILENO); } else { Lwm2m_Error("Failed to open log file %s: %s\n", options->LogFile, strerror(errno)); } } if (options->Version) { Lwm2m_Printf(0, "%s\n", version); goto error_close_log; } Lwm2m_SetLogLevel((options->Verbose) ? DebugLevel_Debug : DebugLevel_Info); Lwm2m_PrintBanner(); if (options->Verbose) { PrintOptions(options); } Lwm2m_Info("Awa LWM2M Bootstrap Server, version %s\n", version); Lwm2m_Info(" Process ID : %d\n", getpid()); Lwm2m_Info(" CoAP port : %d\n", options->Port); if (options->InterfaceName != NULL) { Lwm2m_Info(" Interface : %s [IPv%d]\n", options->InterfaceName, options->AddressFamily == AF_INET? 4 : 6); } else if (strcmp(DEFAULT_IP_ADDRESS, options->IPAddress) != 0) { Lwm2m_Info(" IP Address : %s\n", options->IPAddress); } char ipAddress[NI_MAXHOST]; if (options->InterfaceName != NULL) { if (Lwm2mCore_GetIPAddressFromInterface(options->InterfaceName, options->AddressFamily, ipAddress, sizeof(ipAddress)) != 0) { result = 1; goto error_close_log; } Lwm2m_Info(" Interface Addr : %s\n", ipAddress); } else { strncpy(ipAddress, options->IPAddress, NI_MAXHOST); ipAddress[NI_MAXHOST - 1] = '\0'; // Defensive } CoapInfo * coap = coap_Init(ipAddress, options->Port, (options->Verbose) ? DebugLevel_Debug : DebugLevel_Info); if (coap == NULL) { printf("Unable to map address to network interface\n"); result = 1; goto error_close_log; } Lwm2mContextType * context = Lwm2mCore_Init(coap); // must happen after coap_Init() Lwm2m_RegisterObjectTypes(context); if (!Lwm2mBootstrap_BootStrapInit(context, options->Config, options->ConfigCount)) { printf("Failed to initialise boostrap\n"); result = 1; goto error_destroy; } // wait for messages on both the "IPC" and coap interfaces while (!quit) { int loop_result; struct pollfd fds[1]; int nfds = 1; int timeout; fds[0].fd = coap->fd; fds[0].events = POLLIN; timeout = Lwm2mCore_Process(context); loop_result = poll(fds, nfds, timeout); if (loop_result < 0) { if (errno == EINTR) { continue; } perror("poll:"); break; } else if (loop_result > 0) { if (fds[0].revents == POLLIN) { coap_HandleMessage(); } } coap_Process(); } Lwm2m_Debug("Exit triggered\n"); error_destroy: Lwm2mBootstrap_Destroy(); Lwm2mCore_Destroy(context); coap_Destroy(); error_close_log: Lwm2m_Info("Bootstrap Server exiting\n"); if (logFile != NULL) { fclose(logFile); } return result; }
static int Lwm2mServer_Start(Options * options) { int xmlFd; int result = 0; if (options->Daemonise) { Daemonise(options->Verbose); } else { signal(SIGINT, Lwm2m_CtrlCSignalHandler); } signal(SIGTERM, Lwm2m_CtrlCSignalHandler); // open log files here if (options->LogFile != NULL) { errno = 0; logFile = fopen(options->LogFile, "at"); if (logFile != NULL) { Lwm2m_SetOutput(logFile); // redirect stdout dup2(fileno(logFile), STDOUT_FILENO); } else { Lwm2m_Error("Failed to open log file %s: %s\n", options->LogFile, strerror(errno)); } } if (options->Version) { Lwm2m_Printf(0, "%s\n", version); goto error_close_log; } Lwm2m_SetLogLevel((options->Verbose) ? DebugLevel_Debug : DebugLevel_Info); Lwm2m_PrintBanner(); if (options->Verbose) { PrintOptions(options); } Lwm2m_Info("Awa LWM2M Server, version %s\n", version); Lwm2m_Info(" Process ID : %d\n", getpid()); Lwm2m_Info(" DTLS library : %s\n", DTLS_LibraryName); Lwm2m_Info(" CoAP library : %s\n", coap_LibraryName); Lwm2m_Info(" CoAP port : %d\n", options->CoapPort); Lwm2m_Info(" Secure : %s\n", options->Secure ? "true": "false"); Lwm2m_Info(" IPC port : %d\n", options->IpcPort); Lwm2m_Info(" Address family : IPv%d\n", options->AddressFamily == AF_INET ? 4 : 6); if (options->InterfaceName != NULL) { Lwm2m_Info("LWM2M server - Using interface %s [IPv%d]\n", options->InterfaceName, options->AddressFamily == AF_INET? 4 : 6); } else if (strcmp(DEFAULT_IP_ADDRESS, options->IPAddress) != 0) { Lwm2m_Info("LWM2M server - IP Address %s\n", options->IPAddress); } char ipAddress[NI_MAXHOST]; if (options->InterfaceName != NULL) { if (Lwm2mCore_GetIPAddressFromInterface(options->InterfaceName, options->AddressFamily, ipAddress, sizeof(ipAddress)) != 0) { result = 1; goto error_close_log; } Lwm2m_Info("LWM2M server - Interface Address %s\n", ipAddress); } else { strncpy(ipAddress, options->IPAddress, NI_MAXHOST); ipAddress[NI_MAXHOST - 1] = '\0'; // Defensive } CoapInfo * coap = coap_Init(ipAddress, options->CoapPort, options->Secure, (options->Verbose) ? DebugLevel_Debug : DebugLevel_Info); if (coap == NULL) { printf("Unable to map address to network interface\n"); result = 1; goto error_close_log; } if (options->Secure) { coap_SetCertificate(serverCert, sizeof(serverCert), CertificateFormat_PEM); coap_SetPSK(pskIdentity, pskKey, sizeof(pskKey)); } Lwm2mContextType * context = Lwm2mCore_Init(NULL, options->ContentType); // NULL, don't map coap with objectStore // must happen after coap_Init() Lwm2m_RegisterObjectTypes(context); // listen for UDP packets on port 12345 for now. xmlFd = xmlif_init(context, options->IpcPort); if (xmlFd < 0) { result = 1; goto error_destroy; } xmlif_RegisterHandlers(); // wait for messages on both the "IPC" and coap interfaces while (!quit) { int loop_result; struct pollfd fds[2]; int nfds = 2; int timeout; fds[0].fd = coap->fd; fds[0].events = POLLIN; fds[1].fd = xmlFd; fds[1].events = POLLIN; timeout = Lwm2mCore_Process(context); loop_result = poll(fds, nfds, timeout); if (loop_result < 0) { if (errno == EINTR) { continue; } perror("poll:"); break; } else if (loop_result > 0) { if (fds[0].revents == POLLIN) { coap_HandleMessage(); } if (fds[1].revents == POLLIN) { xmlif_process(fds[1].fd); } } coap_Process(); } Lwm2m_Debug("Exit triggered\n"); error_destroy: xmlif_destroy(xmlFd); Lwm2mCore_Destroy(context); coap_Destroy(); error_close_log: Lwm2m_Info("Server exiting\n"); if (logFile != NULL) { fclose(logFile); } return result; }
bool NetworkSocket_StartListening(NetworkSocket * networkSocket) { bool result = false; if (networkSocket) { int protocol = IPPROTO_UDP; int socketMode = SOCK_DGRAM; if ((networkSocket->SocketType & NetworkSocketType_TCP) == NetworkSocketType_TCP) { protocol = IPPROTO_TCP; socketMode = SOCK_STREAM; } struct sockaddr_in ip4AnyAddress; struct sockaddr_in6 ip6AnyAddress; struct sockaddr_in * ip4Address = NULL; struct sockaddr_in6 * ip6Address = NULL; if (networkSocket->BindAddress) { if (networkSocket->BindAddress->Address.Sa.sa_family == AF_INET6) { ip6Address = &networkSocket->BindAddress->Address.Sin6; } else if (networkSocket->BindAddress->Address.Sa.sa_family == AF_INET) { ip4Address = &networkSocket->BindAddress->Address.Sin; } } else { memset(&ip4AnyAddress, 0, sizeof(struct sockaddr_in)); ip4AnyAddress.sin_family = AF_INET; ip4AnyAddress.sin_addr.s_addr = INADDR_ANY; ip4AnyAddress.sin_port = htons(networkSocket->Port); ip4Address = &ip4AnyAddress; memset(&ip6AnyAddress, 0, sizeof(struct sockaddr_in6)); ip6AnyAddress.sin6_family = AF_INET6; ip6AnyAddress.sin6_port = htons(networkSocket->Port); ip6Address = &ip6AnyAddress; } if (ip4Address) networkSocket->Socket = socket(AF_INET, socketMode, protocol); else networkSocket->Socket = SOCKET_ERROR; if (networkSocket->Socket != SOCKET_ERROR) { struct sockaddr *address = NULL; socklen_t addressLength = 0; addressLength = sizeof(struct sockaddr_in); address = (struct sockaddr *)ip4Address; int flag = fcntl(networkSocket->Socket, F_GETFL); flag = flag | O_NONBLOCK; if (fcntl(networkSocket->Socket, F_SETFL, flag) < 0) { // ignore error } if (bind(networkSocket->Socket, address, addressLength) == SOCKET_ERROR) { Lwm2m_Debug("Failed to bind to ip4 socket\n"); } else { result = true; } } if (ip6Address) networkSocket->SocketIPv6 = socket(AF_INET6, socketMode, protocol); else networkSocket->SocketIPv6 = SOCKET_ERROR; if (networkSocket->SocketIPv6 != SOCKET_ERROR) { int yes = 1; if (setsockopt(networkSocket->SocketIPv6, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes) != SOCKET_ERROR)) { struct sockaddr *address = NULL; socklen_t addressLength = 0; addressLength = sizeof(struct sockaddr_in6); address = (struct sockaddr *)ip6Address; int flag = fcntl(networkSocket->SocketIPv6, F_GETFL); flag = flag | O_NONBLOCK; if (fcntl(networkSocket->SocketIPv6, F_SETFL, flag) < 0) { // ignore error } if (bind(networkSocket->SocketIPv6, address, addressLength) == SOCKET_ERROR) { Lwm2m_Debug("Failed to bind to ip6 socket\n"); } else { result = true; } } } } return result; }
static int Lwm2mClient_Start(Options * options) { FILE * logFile = NULL; uint8_t * loadedClientCert = NULL; int result = 0; uint8_t * key = NULL; if (options->Daemonise) { Daemonise(options->Verbose); } else { signal(SIGINT, Lwm2m_CtrlCSignalHandler); } signal(SIGTERM, Lwm2m_CtrlCSignalHandler); if (options->LogFile) { errno = 0; logFile = fopen(options->LogFile, "at"); if (logFile != NULL) { Lwm2m_SetOutput(logFile); // redirect stdout dup2(fileno(logFile), STDOUT_FILENO); } else { Lwm2m_Error("Failed to open log file %s: %s\n", options->LogFile, strerror(errno)); } } if (options->Version) { Lwm2m_Printf(0, "%s\n", version); goto error_close_log; } srandom((int)time(NULL)*getpid()); if (options->CoapPort == 0) { options->CoapPort = 6000 + (rand() % 32768); } Lwm2m_SetLogLevel((options->Verbose) ? DebugLevel_Debug : DebugLevel_Info); Lwm2m_PrintBanner(); if (options->Verbose) { PrintOptions(options); } Lwm2m_Info("Awa LWM2M Client, version %s\n", version); Lwm2m_Info(" Process ID : %d\n", getpid()); Lwm2m_Info(" Endpoint name : \'%s\'\n", options->EndPointName); Lwm2m_Info(" DTLS library : %s\n", DTLS_LibraryName); Lwm2m_Info(" CoAP library : %s\n", coap_LibraryName); Lwm2m_Info(" CoAP port : %d\n", options->CoapPort); Lwm2m_Info(" IPC port : %d\n", options->IpcPort); Lwm2m_Info(" Address family : IPv%d\n", options->AddressFamily == AF_INET ? 4 : 6); Lwm2mCore_SetDefaultContentType(options->DefaultContentType); CoapInfo * coap = coap_Init((options->AddressFamily == AF_INET) ? "0.0.0.0" : "::", options->CoapPort, false /* not a server */, (options->Verbose) ? DebugLevel_Debug : DebugLevel_Info); if (coap == NULL) { Lwm2m_Error("Failed to initialise CoAP on port %d\n", options->CoapPort); result = 1; goto error_close_log; } // always set key if (options->CertificateFile) { loadedClientCert = LoadCertificateFile(options->CertificateFile); } else coap_SetCertificate(clientCert, sizeof(clientCert), AwaCertificateFormat_PEM); if (options->PskIdentity && options->PskKey) { int hexKeyLength = strlen(options->PskKey); int keyLength = hexKeyLength / 2; key = (uint8_t *)malloc(keyLength); if (key) { char * value = options->PskKey; int index; for (index = 0; index < keyLength; index++) { key[index] = HexToByte(value); value += 2; } coap_SetPSK(options->PskIdentity, key, keyLength); } else coap_SetPSK(pskIdentity, pskKey, sizeof(pskKey)); } else coap_SetPSK(pskIdentity, pskKey, sizeof(pskKey)); // if required read the bootstrap information from a file const BootstrapInfo * factoryBootstrapInfo; if (options->FactoryBootstrapFile != NULL) { factoryBootstrapInfo = BootstrapInformation_ReadConfigFile(options->FactoryBootstrapFile); if (factoryBootstrapInfo == NULL) { Lwm2m_Error("Factory Bootstrap configuration file load failed\n"); result = 1; goto error_coap; } else { Lwm2m_Info("Factory Bootstrap:\n"); Lwm2m_Info("Server Configuration\n"); Lwm2m_Info("====================\n"); BootstrapInformation_Dump(factoryBootstrapInfo); } } else { factoryBootstrapInfo = NULL; } Lwm2mContextType * context = Lwm2mCore_Init(coap, options->EndPointName); // Must happen after coap_Init(). RegisterObjects(context, options); if (factoryBootstrapInfo != NULL) { Lwm2mCore_SetFactoryBootstrap(context, factoryBootstrapInfo); } // bootstrap information has been loaded, no need to hang onto this anymore BootstrapInformation_DeleteBootstrapInfo(factoryBootstrapInfo); // load any specified objDef files if (LoadObjectDefinitionsFromFiles(context, options->ObjDefsFiles, options->NumObjDefsFiles) != 0) { goto error_core; } // Listen for UDP packets on IPC port int xmlFd = xmlif_init(context, options->IpcPort); if (xmlFd < 0) { Lwm2m_Error("Failed to initialise XML interface on port %d\n", options->IpcPort); result = 1; goto error_core; } xmlif_RegisterHandlers(); // Wait for messages on both the IPC and CoAP interfaces while (!quit) { int loop_result; struct pollfd fds[2]; int nfds = 2; int timeout; fds[0].fd = coap->fd; fds[0].events = POLLIN; fds[1].fd = xmlFd; fds[1].events = POLLIN; timeout = Lwm2mCore_Process(context); loop_result = poll(fds, nfds, timeout); if (loop_result < 0) { if (errno == EINTR) { continue; } perror("poll:"); break; } else if (loop_result > 0) { if (fds[0].revents == POLLIN) { coap_HandleMessage(); } if (fds[1].revents == POLLIN) { xmlif_process(fds[1].fd); } } coap_Process(); } Lwm2m_Debug("Exit triggered\n"); xmlif_DestroyExecuteHandlers(); xmlif_destroy(xmlFd); error_core: Lwm2mCore_Destroy(context); error_coap: coap_Destroy(); error_close_log: free(loadedClientCert); free(key); Lwm2m_Info("Client exiting\n"); if (logFile) { fclose(logFile); } return result; }