TX1 node

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rpc.cpp Source File

rpc.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "rpc.h"
00017 
00018 using namespace std;
00019 
00020 namespace mbed {
00021 
00022 RPC::RPC(const char *name) {
00023     _from_construct = false;
00024     if (name != NULL) {
00025         _name = new char[strlen(name) + 1];
00026         strcpy(_name, name);
00027     } else {
00028         _name = new char[12];
00029         sprintf(_name, "obj%p", this);
00030     }
00031     // put this object at head of the list
00032     _next = _head;
00033     _head = this;
00034 }
00035 
00036 RPC::~RPC() {
00037     // remove this object from the list
00038     if (_head == this) { // first in the list, so just drop me
00039         _head = _next;
00040     } else {            // find the object before me, then drop me
00041         RPC* p = _head;
00042         while (p->_next != this) {
00043             p = p->_next;
00044         }
00045         p->_next = _next;
00046     }
00047 }
00048 
00049 const rpc_method *RPC::get_rpc_methods() {
00050     static const rpc_method methods[] = {
00051         {"delete", rpc_method_caller<RPC, &RPC::delete_self> },
00052         RPC_METHOD_END
00053     };
00054     return methods;
00055 }
00056 
00057 RPC *RPC::lookup(const char *name) {
00058     size_t len = strlen(name);
00059     for (RPC *p = _head; p != NULL; p = p->_next) {
00060         /* Check that p->_name matches name and is the correct length */
00061         if (strncmp(p->_name, name, len) == 0 && (strlen(p->_name) == len)) {
00062             return p;
00063         }
00064     }
00065     return NULL;
00066 }
00067 
00068 void RPC::delete_self() {
00069     delete[] _name;
00070     if (_from_construct) {
00071         delete this;
00072     }
00073 }
00074 
00075 void RPC::list_objs(Arguments *args, Reply *result) {
00076     for (RPC *ptr = RPC::_head; ptr != NULL; ptr = ptr->_next) {
00077         if (ptr->_from_construct) {
00078             result->putData<const char*>(ptr->_name);
00079         }
00080     }
00081 }
00082 
00083 void RPC::clear(Arguments*, Reply*) {
00084     RPC *ptr = RPC::_head;
00085     while (ptr != NULL) {
00086         RPC *tmp = ptr;
00087         ptr = ptr->_next;
00088         delete[] tmp->_name;
00089         if (tmp->_from_construct) {
00090             delete tmp;
00091         }
00092     }
00093 }
00094 
00095 const rpc_function RPC::_RPC_funcs[] = {
00096     {"clear", &RPC::clear },
00097     { "objects", &RPC::list_objs },
00098     RPC_METHOD_END
00099 };
00100 
00101 rpc_class RPC::_RPC_class = { "RPC", _RPC_funcs, NULL };
00102 
00103 RPC *RPC::_head = NULL;
00104 
00105 rpc_class *RPC::_classes = &_RPC_class;
00106 
00107 bool RPC::call(const char *request, char *reply) {
00108     if (request == NULL) return false;
00109 
00110     Arguments args(request);
00111     Reply r(reply);
00112 
00113     /* If there's no name print object and class names to result */
00114     if (args.obj_name == NULL) {
00115         for (RPC *p = RPC::_head; p != NULL; p = p->_next) {
00116             r.putData<const char*>(p->_name);
00117         }
00118         for (rpc_class *c = RPC::_classes; c != NULL; c = c->next) {
00119             r.putData<const char*>(c->name);
00120         }
00121         return true;
00122     }
00123 
00124     /* First try matching an instance */
00125     RPC *p = lookup(args.obj_name);
00126     if (p != NULL) {
00127         /* Get the list of methods we support */
00128         const rpc_method *cur_method = p->get_rpc_methods();
00129 
00130         /* When there's no method print method names to result */
00131         if (args.method_name == NULL) {
00132             while (true) {
00133                 for (; cur_method->name != NULL; cur_method++) {
00134                     r.putData<const char*>(cur_method->name);
00135                 }
00136 
00137                 /* write_name_arr's args are references, so result and cur_method will have changed */
00138                 if (cur_method->super != 0) {
00139                     cur_method = cur_method->super(p);
00140                 } else {
00141                     return true;
00142                 }
00143             }
00144         }
00145 
00146         /* Look through the methods for the one whose name matches */
00147         while (true) {
00148             for (; cur_method->name != NULL; cur_method++) {
00149                 if (strcmp(cur_method->name, args.method_name) == 0) {
00150                     (cur_method->method_caller)(p, &args, &r);
00151                     return true;
00152                 }
00153             }
00154 
00155             if (cur_method->super != 0) {
00156                 cur_method = cur_method->super(p);
00157             } else {
00158                 /* end of methods and no match */
00159                 return false;
00160             }
00161 
00162         }
00163     }
00164 
00165     /* Then try a class */
00166     for (const rpc_class *q = _classes; q != NULL; q = q->next) {
00167         if (strcmp(q->name, args.obj_name) == 0) {
00168             /* Matched the class name, so get its functions */
00169             const rpc_function *cur_func = q->static_functions;
00170             if (args.method_name == NULL) {
00171                 for (; cur_func->name != NULL; cur_func++) {
00172                     r.putData<const char*>(cur_func->name);
00173                 }
00174                 return true;
00175             } else {
00176                 /* Otherwise call the appropriate function */
00177                 for (; cur_func->name != NULL; cur_func++) {
00178                     if (strcmp(cur_func->name, args.method_name) == 0) {
00179                         (cur_func->function_caller)(&args, &r);
00180                         return true;
00181                     }
00182                 }
00183                 return false;
00184             }
00185         }
00186     }
00187 
00188     return false;
00189 }
00190 
00191 } // namespace mbed