Doug Anson / mbedConnectorInterfaceV3
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ConnectorEndpoint.cpp Source File

ConnectorEndpoint.cpp

Go to the documentation of this file.
00001 /**
00002  * @file    ConnectorEndpoint.cpp
00003  * @brief   mbed CoAP Endpoint base class
00004  * @author  Doug Anson/Chris Paola
00005  * @version 1.0
00006  * @see
00007  *
00008  * Copyright (c) 2014
00009  *
00010  * Licensed under the Apache License, Version 2.0 (the "License");
00011  * you may not use this file except in compliance with the License.
00012  * You may obtain a copy of the License at
00013  *
00014  *     http://www.apache.org/licenses/LICENSE-2.0
00015  *
00016  * Unless required by applicable law or agreed to in writing, software
00017  * distributed under the License is distributed on an "AS IS" BASIS,
00018  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00019  * See the License for the specific language governing permissions and
00020  * limitations under the License.
00021  */
00022  
00023  // Lower level Network
00024 #include "mbed-connector-interface/mbedEndpointNetwork.h"
00025 
00026 // ConnectorEndpoint
00027 #include "mbed-connector-interface/ConnectorEndpoint.h"
00028 
00029 // Utils support
00030 #include "mbed-connector-interface/Utils.h"
00031 
00032 // DEBUG
00033 #ifndef NDEBUG
00034 #define DEBUG_OUT(...) { printf(__VA_ARGS__); }
00035 #else
00036 #define DEBUG_OUT(...) /* nothing */
00037 #endif
00038 
00039 // our endpoint instance
00040 static Connector::Endpoint *__endpoint = NULL;
00041 
00042 // Connector namespace
00043 namespace Connector {
00044 
00045 // STATIC: Plumb the network
00046 void Endpoint::plumbNetwork(void *device_manager,bool canActAsRouterNode) {
00047     if (__endpoint == NULL) {
00048         // initialize our endpoint instance
00049         DEBUG_OUT("Endpoint::plumbNetwork: initializing endpoint instance...\r\n");
00050         __endpoint = (Connector::Endpoint *)utils_init_endpoint(canActAsRouterNode);
00051     }
00052     
00053     // set the device manager
00054     if (device_manager != NULL) {
00055         // device manager has been supplied
00056         DEBUG_OUT("Endpoint::plumbNetwork: setting a device manager...\r\n");
00057         __endpoint->setDeviceManager(device_manager);
00058     }
00059     else {
00060         // no device manager supplied
00061         DEBUG_OUT("Endpoint::plumbNetwork: no device manager supplied (OK)\r\n");
00062     }
00063 
00064     // configure the endpoint now...
00065     DEBUG_OUT("Endpoint::plumbNetwork: configuring endpoint...\r\n");
00066     utils_configure_endpoint((void *)__endpoint);
00067     
00068     // plumb network
00069     DEBUG_OUT("Endpoint::plumbNetwork: plumbing network...\r\n");
00070     net_plumb_network((void *)__endpoint);
00071 }
00072 
00073 // STATIC: Finalize the endpoint's configuration and begin the endpoint's main even loop (static, not tied into Logger)
00074 void Endpoint::start()
00075 {
00076     // complete setup of our endpoint...
00077     DEBUG_OUT("Endpoint::start: building out endpoint...\r\n");
00078     utils_build_endpoint((void *)__endpoint);
00079     
00080     // register the endpoint
00081     DEBUG_OUT("Endpoint::start: completing endpoint build out..\r\n");
00082     net_perform_endpoint_registration(__endpoint);
00083 }
00084 
00085 // Constructor
00086 Endpoint::Endpoint(const Logger *logger, const Options *options)  : M2MInterfaceObserver() 
00087 {
00088     this->m_logger = (Logger *)logger;
00089     this->m_options = (Options *)options;
00090     this->m_device_manager = NULL;
00091     this->m_connected = false;
00092     this->m_registered = false;
00093 }
00094 
00095 // Copy Constructor
00096 Endpoint::Endpoint(const Endpoint &ep)
00097 {
00098     this->m_logger = ep.m_logger;
00099     this->m_options = ep.m_options;
00100     this->m_interface = ep.m_interface;
00101     this->m_server_instance = ep.m_server_instance;
00102     this->m_object_list = ep.m_object_list;
00103     this->m_device_object = ep.m_device_object;
00104     this->m_device_manager = ep.m_device_manager;
00105     this->m_connected = ep.m_connected;
00106     this->m_registered = ep.m_registered;
00107 }
00108 
00109 // Destructor
00110 Endpoint::~Endpoint() {
00111     if (this->m_interface != NULL)
00112         delete this->m_interface;
00113     if (this->m_server_instance != NULL)
00114         delete this->m_server_instance;
00115 }
00116 
00117 // set the device manager
00118 void Endpoint::setDeviceManager(void *device_manager) {
00119     this->m_device_manager = device_manager;
00120 }
00121 
00122 // get the device manager
00123 void *Endpoint::getDeviceManager(void) {
00124     return this->m_device_manager;
00125 }
00126 
00127 // router node behavior setting
00128 void Endpoint::asRouterNode(bool canActAsRouterNode) {
00129     this->m_canActAsRouterNode = canActAsRouterNode;
00130 }
00131 
00132 // set our Options
00133 void Endpoint::setOptions(Options *options) {
00134     this->m_options = options;
00135 }
00136 
00137 // get our Options
00138 Options *Endpoint::getOptions() {
00139     return this->m_options;
00140 }
00141 
00142 // get our Server
00143 M2MSecurity *Endpoint::getServer() {
00144     return this->m_server_instance;
00145 }
00146 
00147 // get our ObjectList
00148 M2MObjectList Endpoint::getObjectList() {
00149     return this->m_object_list;
00150 }
00151 
00152 // mbed-client: create our interface
00153 void Endpoint::create_interface() {
00154     // get the CoAP listening port
00155     uint16_t listening_port = (uint16_t)this->m_options->getConnectorPort();
00156     
00157     // randomize the port if we are using certificates...
00158     if (this->m_options->getServerCertificateSize() > 0) {
00159         // Randomizing listening port for Certificate mode connectivity
00160         srand(time(NULL));
00161         listening_port = rand() % 65535 + 12345;
00162     }
00163     
00164     // Binding Mode - TCP or UDP
00165     M2MInterface::BindingMode network_protocol = M2MInterface::UDP;
00166     if (this->m_options->getCoAPConnectionType() == COAP_TCP)  network_protocol = M2MInterface::TCP;
00167     
00168     // Network Type IPv4 or IPv6
00169     M2MInterface::NetworkStack ip_address_type = M2MInterface::LwIP_IPv4;
00170     if (this->m_options->getIPAddressType() == IP_ADDRESS_TYPE_IPV6) ip_address_type = M2MInterface::LwIP_IPv6;
00171     
00172     // DEBUG
00173     if (network_protocol == M2MInterface::TCP) this->logger()->log("Endpoint: Underlying Protocol: TCP");
00174     if (network_protocol == M2MInterface::UDP) this->logger()->log("Endpoint: Underlying Protocol: UDP");
00175     if (ip_address_type == M2MInterface::LwIP_IPv4) this->logger()->log("Endpoint: IP Address Type: IPv4");
00176     if (ip_address_type == M2MInterface::LwIP_IPv6) this->logger()->log("Endpoint: IP Address Type: IPv6");
00177     
00178     // Create the  M2M Interface instance
00179     this->m_interface = M2MInterfaceFactory::create_interface(*this,
00180                                               (char *)this->m_options->getEndpointNodename().c_str(),
00181                                               (char *)this->m_options->getEndpointType().c_str(),
00182                                               (int32_t)this->m_options->getLifetime(),
00183                                               listening_port,                                   // listening port
00184                                               (char *)this->m_options->getDomain().c_str(),
00185                                               network_protocol,                                 // CoAP over UDP or TCP...
00186                                               ip_address_type);                                 // IPv4 addressing or IPv6 addressing
00187 }
00188 
00189 // mbed-client: create_server_instance()
00190 M2MSecurity *Endpoint::create_server_instance()  {
00191         // Creates register server object with mbed device server address and other parameters
00192         M2MSecurity *server = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer);
00193         if (server != NULL)  {
00194             const String url = this->m_options->getConnectorURL();
00195             server->set_resource_value(M2MSecurity::M2MServerUri, url);
00196             server->set_resource_value(M2MSecurity::BootstrapServer, NULL);
00197             server->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Certificate);
00198             server->set_resource_value(M2MSecurity::ServerPublicKey,this->m_options->getServerCertificate(),this->m_options->getServerCertificateSize());
00199             server->set_resource_value(M2MSecurity::PublicKey,this->m_options->getClientCertificate(),this->m_options->getClientCertificateSize());
00200             server->set_resource_value(M2MSecurity::Secretkey,this->m_options->getClientKey(),this->m_options->getClientKeySize());
00201         }
00202         return server;
00203 }
00204 
00205 // mbed-client: Callback from mbed client stack if any error is encountered
00206 void Endpoint::error(M2MInterface::Error error) {
00207         switch(error){
00208             case M2MInterface::AlreadyExists:
00209                 DEBUG_OUT("[ERROR:] M2MInterface::AlreadyExists");
00210                 break;
00211             case M2MInterface::BootstrapFailed:
00212                DEBUG_OUT("[ERROR:] M2MInterface::BootstrapFailed");
00213                 break;
00214             case M2MInterface::InvalidParameters:
00215                DEBUG_OUT("[ERROR:] M2MInterface::InvalidParameters");
00216                 break;
00217             case M2MInterface::NotRegistered:
00218                 DEBUG_OUT("[ERROR:] M2MInterface::NotRegistered");
00219                 break;
00220             case M2MInterface::Timeout:
00221                 DEBUG_OUT("[ERROR:] M2MInterface::Timeout");
00222                 break;
00223             case M2MInterface::NetworkError:
00224                 DEBUG_OUT("[ERROR:] M2MInterface::NetworkError");
00225                 break;
00226             case M2MInterface::ResponseParseFailed:
00227                 DEBUG_OUT("[ERROR:] M2MInterface::ResponseParseFailed");
00228                 break;
00229             case M2MInterface::UnknownError:
00230                DEBUG_OUT("[ERROR:] M2MInterface::UnknownError");
00231                 break;
00232             case M2MInterface::MemoryFail:
00233                 DEBUG_OUT("[ERROR:] M2MInterface::MemoryFail");
00234                 break;
00235             case M2MInterface::NotAllowed:
00236                DEBUG_OUT("[ERROR:] M2MInterface::NotAllowed");
00237                 break;
00238             default:
00239                 break;
00240         }
00241 }
00242 
00243 // register the endpoint
00244 void Endpoint::register_endpoint(M2MSecurity *server_instance, M2MObjectList resources) {
00245     if (this->m_interface != NULL && server_instance != NULL && resources.size() > 0)  {
00246         // register  endpoint
00247         this->logger()->log("Registering endpoint...");
00248         this->m_interface->register_object(server_instance, resources);
00249     }
00250 }
00251 
00252 // re-register the endpoint
00253 void Endpoint::re_register_endpoint() {
00254     if (this->m_interface != NULL)  {
00255         this->m_interface->update_registration(this->m_server_instance, this->m_options->getLifetime());
00256     }  
00257 }
00258 
00259 // de-register endpoint 
00260 void Endpoint::de_register_endpoint(void) {
00261     if (this->m_interface != NULL) {
00262         // de-register endpoint
00263         this->logger()->log("De-registering endpoint...");
00264         this->m_interface->unregister_object(NULL);     
00265     }
00266 }
00267 
00268 // object registered
00269 void Endpoint::object_registered(M2MSecurity */*security_object */, const M2MServer &/*server_object*/)  {                     
00270     this->logger()->log("Endpoint registered");
00271     this->m_connected = true;
00272     this->m_registered = true;
00273 }
00274 
00275 // registration updated
00276 void Endpoint::registration_updated(M2MSecurity */*security_object*/, const M2MServer &/*server_object*/)  {
00277     this->logger()->log("Endpoint re-registered.");
00278     this->m_connected = true;
00279     this->m_registered = true;
00280 }
00281 
00282 // object unregistered
00283 void Endpoint::object_unregistered(M2MSecurity */*server_object*/)  {
00284     // ready to exit
00285     this->logger()->log("Endpoint de-registered... Ready to exit...");
00286     this->m_registered = false;
00287 }
00288 
00289 // bootstrap done
00290 void Endpoint::bootstrap_done(M2MSecurity * /*server_object */) {
00291     this->logger()->log("Bootstrapped");
00292 }
00293 
00294 // resource value updated
00295 void Endpoint::value_updated(M2MBase *base, M2MBase::BaseType type) {
00296     this->logger()->log("Value Updated");
00297     DynamicResource *target_res = this->lookupDynamicResource(base);
00298     target_res->process(base->operation(),type);
00299 }
00300 
00301 // lookup which DynamicResource cooresponds to a given M2MBase instance...
00302 DynamicResource *Endpoint::lookupDynamicResource(M2MBase *base) {
00303     DynamicResource *res = NULL;
00304     bool found = false;
00305     const DynamicResourcesList *dynamic_resources = this->m_options->getDynamicResourceList();
00306     for(int i=0; i<(int)dynamic_resources->size() && found == false; ++i) {
00307         M2MBase *t = dynamic_resources->at(i)->getResource();
00308         if (t == base) {
00309             res = dynamic_resources->at(i);
00310             found = true;
00311         }
00312     }   
00313     
00314     return res;
00315 }
00316 
00317 // build out the endpoint
00318 void Endpoint::build_endpoint()
00319 {   
00320    // initialize as an mbed-client
00321    this->create_interface();
00322    
00323    // Create our server instance
00324    this->m_server_instance = this->create_server_instance();
00325    
00326    // Loop through Static Resources and bind each of them...
00327     this->logger()->log("Endpoint::build(): adding device resources...");
00328     const DeviceResourcesList *device_resources = this->m_options->getDeviceResourceList();
00329     for(int i=0; i<(int)device_resources->size(); ++i) {
00330         this->logger()->log("Endpoint::build(): binding device resource: [%s]...",device_resources->at(i)->getFullName().c_str());
00331         this->m_object_list.push_back(device_resources->at(i)->bind(this));
00332     }
00333         
00334     // Loop through Static Resources and bind each of them...
00335     this->logger()->log("Endpoint::build(): adding static resources...");
00336     const StaticResourcesList *static_resources = this->m_options->getStaticResourceList();
00337     for(int i=0; i<(int)static_resources->size(); ++i) {
00338         this->logger()->log("Endpoint::build(): binding static resource: [%s]...",static_resources->at(i)->getFullName().c_str());
00339         this->m_object_list.push_back(static_resources->at(i)->bind(this));
00340     }
00341 
00342     // Loop through Dynamic Resources and bind each of them...
00343     this->logger()->log("Endpoint::build(): adding dynamic resources...");
00344     const DynamicResourcesList *dynamic_resources = this->m_options->getDynamicResourceList();
00345     for(int i=0; i<(int)dynamic_resources->size(); ++i) {
00346         this->logger()->log("Endpoint::build(): binding dynamic resource: [%s]...",dynamic_resources->at(i)->getFullName().c_str());
00347         this->m_object_list.push_back(dynamic_resources->at(i)->bind(this));
00348     }
00349 }
00350 
00351 // underlying network is connected (SET)
00352 void Endpoint::isConnected(bool connected) {
00353     this->m_connected = connected;
00354 }
00355 
00356 // underlying network is connected (GET)
00357 bool Endpoint::isConnected() {
00358      return this->m_connected;
00359 }
00360 
00361 // Registered with mDC/mDS
00362 bool Endpoint::isRegistered() {
00363      return this->m_registered;
00364 }
00365 
00366 // our logger
00367 Logger *Endpoint::logger()
00368 {
00369     return this->m_logger;
00370 }
00371 
00372 } // namespace Connector