mbed RPC
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Sun Jul 24 2022 15:11:06 by 1.7.2