use TCP to connect to mbed connector
Fork of mbedConnectorInterfaceWithDM by
source/ConnectorEndpoint.cpp
- Committer:
- ansond
- Date:
- 2016-06-15
- Revision:
- 46:62da4ce20276
- Parent:
- 45:db754b994deb
- Child:
- 54:dfee8691c83a
File content as of revision 46:62da4ce20276:
/** * @file ConnectorEndpoint.cpp * @brief mbed CoAP Endpoint base class * @author Doug Anson/Chris Paola * @version 1.0 * @see * * Copyright (c) 2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // Lower level Network #include "mbed-connector-interface/mbedEndpointNetwork.h" // ConnectorEndpoint #include "mbed-connector-interface/ConnectorEndpoint.h" // Utils support #include "mbed-connector-interface/Utils.h" // Device Manager support #include "mbed-connector-interface/DeviceManager.h" // DEBUG #ifndef NDEBUG #define DEBUG_OUT(...) { printf(__VA_ARGS__); } #else #define DEBUG_OUT(...) /* nothing */ #endif // our endpoint instance static Connector::Endpoint *__endpoint = NULL; // LWIP_INTERFACE #if defined(MCI_LWIP_INTERFACE) void *__network_interface = NULL; #endif // Connector namespace namespace Connector { // STATIC: Plumb the network void Endpoint::plumbNetwork(void *device_manager,bool canActAsRouterNode) { if (__endpoint == NULL) { // initialize our endpoint instance DEBUG_OUT("Endpoint::plumbNetwork: initializing endpoint instance...\r\n"); __endpoint = (Connector::Endpoint *)utils_init_endpoint(canActAsRouterNode); } // set the device manager if (device_manager != NULL) { // device manager has been supplied DEBUG_OUT("Endpoint::plumbNetwork: setting a device manager...\r\n"); __endpoint->setDeviceManager(device_manager); } else { // no device manager supplied DEBUG_OUT("Endpoint::plumbNetwork: no device manager supplied (OK)\r\n"); } // configure the endpoint now... DEBUG_OUT("Endpoint::plumbNetwork: configuring endpoint...\r\n"); utils_configure_endpoint((void *)__endpoint); // plumb network DEBUG_OUT("Endpoint::plumbNetwork: plumbing network...\r\n"); net_plumb_network((void *)__endpoint); } // STATIC: Finalize the endpoint's configuration and begin the endpoint's main even loop (static, not tied into Logger) void Endpoint::start() { // complete setup of our endpoint... DEBUG_OUT("Endpoint::start: building out endpoint...\r\n"); utils_build_endpoint((void *)__endpoint); // register the endpoint DEBUG_OUT("Endpoint::start: completing endpoint build out..\r\n"); net_perform_endpoint_registration(__endpoint); } // STATIC: Set the ConnectionStatusInterface Implementation instance void Endpoint::setConnectionStatusInterface(ConnectionStatusInterface *csi) { if (__endpoint != NULL) { __endpoint->setConnectionStatusInterfaceImpl(csi); } } // Constructor Endpoint::Endpoint(const Logger *logger, const Options *options) : M2MInterfaceObserver() { this->m_logger = (Logger *)logger; this->m_options = (Options *)options; this->m_device_manager = NULL; this->m_connected = false; this->m_registered = false; this->m_csi = NULL; this->m_oim = NULL; } // Copy Constructor Endpoint::Endpoint(const Endpoint &ep) { this->m_logger = ep.m_logger; this->m_options = ep.m_options; this->m_endpoint_interface = ep.m_endpoint_interface; this->m_endpoint_security = ep.m_endpoint_security; this->m_endpoint_object_list = ep.m_endpoint_object_list; this->m_device_manager = ep.m_device_manager; this->m_connected = ep.m_connected; this->m_registered = ep.m_registered; this->m_csi = ep.m_csi; this->m_oim = ep.m_oim; } // Destructor Endpoint::~Endpoint() { if (this->m_endpoint_interface != NULL) delete this->m_endpoint_interface; if (this->m_endpoint_security != NULL) delete this->m_endpoint_security; } // set the device manager void Endpoint::setDeviceManager(void *device_manager) { this->m_device_manager = device_manager; } // get the device manager void *Endpoint::getDeviceManager(void) { return this->m_device_manager; } // router node behavior setting void Endpoint::asRouterNode(bool canActAsRouterNode) { this->m_canActAsRouterNode = canActAsRouterNode; } // set our Options void Endpoint::setOptions(Options *options) { this->m_options = options; } // get our Options Options *Endpoint::getOptions() { return this->m_options; } // get our Server M2MSecurity *Endpoint::getEndpointSecurity() { return this->m_endpoint_security; } // get our ObjectList M2MObjectList Endpoint::getEndpointObjectList() { return this->m_endpoint_object_list; } // get our endpoint interface M2MInterface *Endpoint::getEndpointInterface() { return this->m_endpoint_interface; } // mbed-client: create our interface void Endpoint::createEndpointInterface() { // get the CoAP listening port uint16_t listening_port = (uint16_t)this->m_options->getConnectorPort(); // randomize the port if we are using certificates... if (this->m_options->getServerCertificateSize() > 0) { // Randomizing listening port for Certificate mode connectivity srand(time(NULL)); listening_port = rand() % 65535 + 12345; } // Binding Mode - TCP or UDP M2MInterface::BindingMode network_protocol = M2MInterface::UDP; if (this->m_options->getCoAPConnectionType() == COAP_TCP) network_protocol = M2MInterface::TCP; // Network Type IPv4 or IPv6 M2MInterface::NetworkStack ip_address_type = M2MInterface::LwIP_IPv4; if (this->m_options->getIPAddressType() == IP_ADDRESS_TYPE_IPV6) ip_address_type = M2MInterface::LwIP_IPv6; // DEBUG if (network_protocol == M2MInterface::TCP) this->logger()->log("Endpoint: Underlying Protocol: TCP"); if (network_protocol == M2MInterface::UDP) this->logger()->log("Endpoint: Underlying Protocol: UDP"); if (ip_address_type == M2MInterface::LwIP_IPv4) this->logger()->log("Endpoint: IP Address Type: IPv4"); if (ip_address_type == M2MInterface::LwIP_IPv6) this->logger()->log("Endpoint: IP Address Type: IPv6"); // Create the M2M Interface instance this->m_endpoint_interface = M2MInterfaceFactory::create_interface(*this, (char *)this->m_options->getEndpointNodename().c_str(), (char *)this->m_options->getEndpointType().c_str(), (int32_t)this->m_options->getLifetime(), listening_port, // listening port (char *)this->m_options->getDomain().c_str(), network_protocol, // CoAP over UDP or TCP... ip_address_type); // IPv4 addressing or IPv6 addressing #if defined (MCI_LWIP_INTERFACE) if (__network_interface != NULL && this->m_endpoint_interface != NULL) { this->logger()->log("Endpoint: Morpheus: binding network..."); this->m_endpoint_interface->set_platform_network_handler(__network_interface); } #endif } // mbed-client: createEndpointInstance() M2MSecurity *Endpoint::createEndpointInstance() { // Creates register server object with mbed device server address and other parameters M2MSecurity *server = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer); if (server != NULL) { const String url = this->m_options->getConnectorURL(); server->set_resource_value(M2MSecurity::M2MServerUri, url); server->set_resource_value(M2MSecurity::BootstrapServer, false); server->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Certificate); server->set_resource_value(M2MSecurity::ServerPublicKey,this->m_options->getServerCertificate(),this->m_options->getServerCertificateSize()); server->set_resource_value(M2MSecurity::PublicKey,this->m_options->getClientCertificate(),this->m_options->getClientCertificateSize()); server->set_resource_value(M2MSecurity::Secretkey,this->m_options->getClientKey(),this->m_options->getClientKeySize()); } return server; } // mbed-client: Callback from mbed client stack if any error is encountered void Endpoint::error(M2MInterface::Error error) { switch(error){ case M2MInterface::AlreadyExists: DEBUG_OUT("[ERROR:] M2MInterface::AlreadyExists"); break; case M2MInterface::BootstrapFailed: DEBUG_OUT("[ERROR:] M2MInterface::BootstrapFailed"); break; case M2MInterface::InvalidParameters: DEBUG_OUT("[ERROR:] M2MInterface::InvalidParameters"); break; case M2MInterface::NotRegistered: DEBUG_OUT("[ERROR:] M2MInterface::NotRegistered"); break; case M2MInterface::Timeout: DEBUG_OUT("[ERROR:] M2MInterface::Timeout"); break; case M2MInterface::NetworkError: DEBUG_OUT("[ERROR:] M2MInterface::NetworkError"); break; case M2MInterface::ResponseParseFailed: DEBUG_OUT("[ERROR:] M2MInterface::ResponseParseFailed"); break; case M2MInterface::UnknownError: DEBUG_OUT("[ERROR:] M2MInterface::UnknownError"); break; case M2MInterface::MemoryFail: DEBUG_OUT("[ERROR:] M2MInterface::MemoryFail"); break; case M2MInterface::NotAllowed: DEBUG_OUT("[ERROR:] M2MInterface::NotAllowed"); break; default: break; } } // register the endpoint void Endpoint::register_endpoint(M2MSecurity *endpoint_security, M2MObjectList endpoint_objects) { if (this->m_endpoint_interface != NULL && endpoint_security != NULL && endpoint_objects.size() > 0) { // register endpoint this->logger()->log("Registering endpoint..."); this->m_endpoint_interface->register_object(endpoint_security, endpoint_objects); } } // re-register the endpoint void Endpoint::re_register_endpoint() { if (this->m_endpoint_interface != NULL) { this->m_endpoint_interface->update_registration(this->m_endpoint_security,this->m_options->getLifetime()); } } // de-register endpoint void Endpoint::de_register_endpoint(void) { if (this->m_endpoint_interface != NULL) { // de-register endpoint this->logger()->log("De-registering endpoint..."); this->m_endpoint_interface->unregister_object(NULL); if (this->m_csi != NULL) { this->m_csi->begin_object_unregistering((void *)this); } } } // object registered void Endpoint::object_registered(M2MSecurity *security, const M2MServer &server) { this->logger()->log("Endpoint registered..."); this->m_connected = true; this->m_registered = true; #if defined (ENDPOINT_EARLY_CONFIG_DEREG_BUTTON) // setup the shutdown button (if enabled for a given platform...) this->logger()->log("Configuring optional de-registration button..."); net_setup_deregistration_button((void *)this); #endif if (this->m_csi != NULL) { this->m_csi->object_registered((void *)this,(void *)security,(void *)&server); } } // registration updated void Endpoint::registration_updated(M2MSecurity *security, const M2MServer &server) { this->logger()->log("Endpoint re-registered..."); this->m_connected = true; this->m_registered = true; if (this->m_csi != NULL) { this->m_csi->registration_updated((void *)this,(void *)security,(void *)&server); } } // object unregistered void Endpoint::object_unregistered(M2MSecurity *server) { // ready to exit this->logger()->log("Endpoint de-registered... Ready to exit..."); this->m_registered = false; if (this->m_csi != NULL) { this->m_csi->object_unregistered((void *)this,(void *)server); } } // bootstrap done void Endpoint::bootstrap_done(M2MSecurity *server) { this->logger()->log("Endpoint bootstrapped..."); if (this->m_csi != NULL) { this->m_csi->bootstrapped((void *)this,(void *)server); } } // resource value updated void Endpoint::value_updated(M2MBase *base, M2MBase::BaseType type) { // Lookup the resource and invoke process() on it... DynamicResource *target_res = this->lookupDynamicResource(base); if (target_res != NULL) { // DEBUG //this->logger()->log("Value Updated (Custom Resource)"); // its a custom resource... target_res->process(base->operation(),type); } else { // DEBUG //this->logger()->log("Value Updated (Device Manager)"); // let DeviceManager handle it ((DeviceManager *)this->m_device_manager)->process(base,type); } // CSI if (this->m_csi != NULL) { this->m_csi->value_updated((void *)this,(void *)base,(int)type); } } // lookup which DynamicResource cooresponds to a given M2MBase instance... DynamicResource *Endpoint::lookupDynamicResource(M2MBase *base) { const DynamicResourcesList *dynamic_resources = this->m_options->getDynamicResourceList(); for(int i=0; i<(int)dynamic_resources->size(); ++i) { M2MBase *t = (M2MBase *)dynamic_resources->at(i)->getResource(); if (t == base) { return dynamic_resources->at(i); } } return NULL; } // build out the endpoint void Endpoint::buildEndpoint() { // initialize as an mbed-client this->createEndpointInterface(); // Create our server instance this->m_endpoint_security = this->createEndpointInstance(); // We now have to bind our device resources if (this->m_device_manager != NULL) { // DEBUG this->logger()->log("Endpoint::build(): plumbing the device management objects and resources..."); // bind the device manager ((DeviceManager *)this->m_device_manager)->bind(); // push back the Device Resources Object if (this->m_options->getDeviceResourcesObject() != NULL) { // DEBUG this->logger()->log("Endpoint::build(): plumbing device resources object..."); // push back the device resources object this->m_endpoint_object_list.push_back((M2MObject *)this->m_options->getDeviceResourcesObject()); } else { // unable to plumb device manager this->logger()->log("Endpoint::build(): Unable to plumb device resources. Not installing device resource object..."); } // push back the Firmware Resources Object if (this->m_options->getFirmwareResourcesObject() != NULL) { // DEBUG this->logger()->log("Endpoint::build(): plumbing firmware resources object..."); // push back the firmware resources object this->m_endpoint_object_list.push_back((M2MObject *)this->m_options->getFirmwareResourcesObject()); } else { // unable to plumb firmware manager this->logger()->log("Endpoint::build(): Unable to plumb firmware resources. Not installing firmware resource object..."); } } else { // no device manager installed this->logger()->log("Endpoint::build(): No device manager installed."); } // Loop through Static Resources and bind each of them... this->logger()->log("Endpoint::build(): adding static resources..."); const StaticResourcesList *static_resources = this->m_options->getStaticResourceList(); for(int i=0; i<(int)static_resources->size(); ++i) { this->logger()->log("Endpoint::build(): binding static resource: [%s]...",static_resources->at(i)->getFullName().c_str()); static_resources->at(i)->bind(this); } // Loop through Dynamic Resources and bind each of them... this->logger()->log("Endpoint::build(): adding dynamic resources..."); const DynamicResourcesList *dynamic_resources = this->m_options->getDynamicResourceList(); for(int i=0; i<(int)dynamic_resources->size(); ++i) { this->logger()->log("Endpoint::build(): binding dynamic resource: [%s]...",dynamic_resources->at(i)->getFullName().c_str()); dynamic_resources->at(i)->bind(this); } // Get the ObjectList from the ObjectInstanceManager... NamedPointerList list = this->getObjectInstanceManager()->getObjectList(); // DEBUG //this->logger()->log("Endpoint::build(): All Resources bound. Number of Objects in list: %d",list.size()); // add all of the object instances we have created... for(int i=0;i<(int)list.size();++i) { // DEBUG //this->logger()->log("Endpoint::build(): adding Object Instance with ObjID: %s...",list.at(i).name().c_str()); // push back the object instance... this->m_endpoint_object_list.push_back((M2MObject *)(list.at(i).ptr())); } } // underlying network is connected (SET) void Endpoint::isConnected(bool connected) { this->m_connected = connected; } // underlying network is connected (GET) bool Endpoint::isConnected() { return this->m_connected; } // Registered with mDC/mDS bool Endpoint::isRegistered() { return this->m_registered; } // Set the ConnectionStatusInterface void Endpoint::setConnectionStatusInterfaceImpl(ConnectionStatusInterface *csi) { this->m_csi = csi; } // Set our ObjectInstanceManager void Endpoint::setObjectInstanceManager(ObjectInstanceManager *oim) { this->m_oim = oim; } // Get our ObjectInstanceManager ObjectInstanceManager *Endpoint::getObjectInstanceManager() { return this->m_oim; } // our logger Logger *Endpoint::logger() { return this->m_logger; } } // namespace Connector