mbed-os

Fork of mbed-os by erkin yucel

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /* mbed Microcontroller Library
elessair 0:f269e3021894 2 * Copyright (c) 2006-2013 ARM Limited
elessair 0:f269e3021894 3 *
elessair 0:f269e3021894 4 * Licensed under the Apache License, Version 2.0 (the "License");
elessair 0:f269e3021894 5 * you may not use this file except in compliance with the License.
elessair 0:f269e3021894 6 * You may obtain a copy of the License at
elessair 0:f269e3021894 7 *
elessair 0:f269e3021894 8 * http://www.apache.org/licenses/LICENSE-2.0
elessair 0:f269e3021894 9 *
elessair 0:f269e3021894 10 * Unless required by applicable law or agreed to in writing, software
elessair 0:f269e3021894 11 * distributed under the License is distributed on an "AS IS" BASIS,
elessair 0:f269e3021894 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
elessair 0:f269e3021894 13 * See the License for the specific language governing permissions and
elessair 0:f269e3021894 14 * limitations under the License.
elessair 0:f269e3021894 15 */
elessair 0:f269e3021894 16 #include "rpc.h"
elessair 0:f269e3021894 17
elessair 0:f269e3021894 18 using namespace std;
elessair 0:f269e3021894 19
elessair 0:f269e3021894 20 namespace mbed {
elessair 0:f269e3021894 21
elessair 0:f269e3021894 22 RPC::RPC(const char *name) {
elessair 0:f269e3021894 23 _from_construct = false;
elessair 0:f269e3021894 24 if (name != NULL) {
elessair 0:f269e3021894 25 _name = new char[strlen(name) + 1];
elessair 0:f269e3021894 26 strcpy(_name, name);
elessair 0:f269e3021894 27 } else {
elessair 0:f269e3021894 28 _name = new char[12];
elessair 0:f269e3021894 29 sprintf(_name, "obj%p", this);
elessair 0:f269e3021894 30 }
elessair 0:f269e3021894 31 // put this object at head of the list
elessair 0:f269e3021894 32 _next = _head;
elessair 0:f269e3021894 33 _head = this;
elessair 0:f269e3021894 34 }
elessair 0:f269e3021894 35
elessair 0:f269e3021894 36 RPC::~RPC() {
elessair 0:f269e3021894 37 // remove this object from the list
elessair 0:f269e3021894 38 if (_head == this) { // first in the list, so just drop me
elessair 0:f269e3021894 39 _head = _next;
elessair 0:f269e3021894 40 } else { // find the object before me, then drop me
elessair 0:f269e3021894 41 RPC* p = _head;
elessair 0:f269e3021894 42 while (p->_next != this) {
elessair 0:f269e3021894 43 p = p->_next;
elessair 0:f269e3021894 44 }
elessair 0:f269e3021894 45 p->_next = _next;
elessair 0:f269e3021894 46 }
elessair 0:f269e3021894 47 }
elessair 0:f269e3021894 48
elessair 0:f269e3021894 49 const rpc_method *RPC::get_rpc_methods() {
elessair 0:f269e3021894 50 static const rpc_method methods[] = {
elessair 0:f269e3021894 51 {"delete", rpc_method_caller<RPC, &RPC::delete_self> },
elessair 0:f269e3021894 52 RPC_METHOD_END
elessair 0:f269e3021894 53 };
elessair 0:f269e3021894 54 return methods;
elessair 0:f269e3021894 55 }
elessair 0:f269e3021894 56
elessair 0:f269e3021894 57 RPC *RPC::lookup(const char *name) {
elessair 0:f269e3021894 58 size_t len = strlen(name);
elessair 0:f269e3021894 59 for (RPC *p = _head; p != NULL; p = p->_next) {
elessair 0:f269e3021894 60 /* Check that p->_name matches name and is the correct length */
elessair 0:f269e3021894 61 if (strncmp(p->_name, name, len) == 0 && (strlen(p->_name) == len)) {
elessair 0:f269e3021894 62 return p;
elessair 0:f269e3021894 63 }
elessair 0:f269e3021894 64 }
elessair 0:f269e3021894 65 return NULL;
elessair 0:f269e3021894 66 }
elessair 0:f269e3021894 67
elessair 0:f269e3021894 68 void RPC::delete_self() {
elessair 0:f269e3021894 69 delete[] _name;
elessair 0:f269e3021894 70 if (_from_construct) {
elessair 0:f269e3021894 71 delete this;
elessair 0:f269e3021894 72 }
elessair 0:f269e3021894 73 }
elessair 0:f269e3021894 74
elessair 0:f269e3021894 75 void RPC::list_objs(Arguments *args, Reply *result) {
elessair 0:f269e3021894 76 for (RPC *ptr = RPC::_head; ptr != NULL; ptr = ptr->_next) {
elessair 0:f269e3021894 77 if (ptr->_from_construct) {
elessair 0:f269e3021894 78 result->putData<const char*>(ptr->_name);
elessair 0:f269e3021894 79 }
elessair 0:f269e3021894 80 }
elessair 0:f269e3021894 81 }
elessair 0:f269e3021894 82
elessair 0:f269e3021894 83 void RPC::clear(Arguments*, Reply*) {
elessair 0:f269e3021894 84 RPC *ptr = RPC::_head;
elessair 0:f269e3021894 85 while (ptr != NULL) {
elessair 0:f269e3021894 86 RPC *tmp = ptr;
elessair 0:f269e3021894 87 ptr = ptr->_next;
elessair 0:f269e3021894 88 delete[] tmp->_name;
elessair 0:f269e3021894 89 if (tmp->_from_construct) {
elessair 0:f269e3021894 90 delete tmp;
elessair 0:f269e3021894 91 }
elessair 0:f269e3021894 92 }
elessair 0:f269e3021894 93 }
elessair 0:f269e3021894 94
elessair 0:f269e3021894 95 const rpc_function RPC::_RPC_funcs[] = {
elessair 0:f269e3021894 96 {"clear", &RPC::clear },
elessair 0:f269e3021894 97 { "objects", &RPC::list_objs },
elessair 0:f269e3021894 98 RPC_METHOD_END
elessair 0:f269e3021894 99 };
elessair 0:f269e3021894 100
elessair 0:f269e3021894 101 rpc_class RPC::_RPC_class = { "RPC", _RPC_funcs, NULL };
elessair 0:f269e3021894 102
elessair 0:f269e3021894 103 RPC *RPC::_head = NULL;
elessair 0:f269e3021894 104
elessair 0:f269e3021894 105 rpc_class *RPC::_classes = &_RPC_class;
elessair 0:f269e3021894 106
elessair 0:f269e3021894 107 bool RPC::call(const char *request, char *reply) {
elessair 0:f269e3021894 108 if (request == NULL) return false;
elessair 0:f269e3021894 109
elessair 0:f269e3021894 110 Arguments args(request);
elessair 0:f269e3021894 111 Reply r(reply);
elessair 0:f269e3021894 112
elessair 0:f269e3021894 113 /* If there's no name print object and class names to result */
elessair 0:f269e3021894 114 if (args.obj_name == NULL) {
elessair 0:f269e3021894 115 for (RPC *p = RPC::_head; p != NULL; p = p->_next) {
elessair 0:f269e3021894 116 r.putData<const char*>(p->_name);
elessair 0:f269e3021894 117 }
elessair 0:f269e3021894 118 for (rpc_class *c = RPC::_classes; c != NULL; c = c->next) {
elessair 0:f269e3021894 119 r.putData<const char*>(c->name);
elessair 0:f269e3021894 120 }
elessair 0:f269e3021894 121 return true;
elessair 0:f269e3021894 122 }
elessair 0:f269e3021894 123
elessair 0:f269e3021894 124 /* First try matching an instance */
elessair 0:f269e3021894 125 RPC *p = lookup(args.obj_name);
elessair 0:f269e3021894 126 if (p != NULL) {
elessair 0:f269e3021894 127 /* Get the list of methods we support */
elessair 0:f269e3021894 128 const rpc_method *cur_method = p->get_rpc_methods();
elessair 0:f269e3021894 129
elessair 0:f269e3021894 130 /* When there's no method print method names to result */
elessair 0:f269e3021894 131 if (args.method_name == NULL) {
elessair 0:f269e3021894 132 while (true) {
elessair 0:f269e3021894 133 for (; cur_method->name != NULL; cur_method++) {
elessair 0:f269e3021894 134 r.putData<const char*>(cur_method->name);
elessair 0:f269e3021894 135 }
elessair 0:f269e3021894 136
elessair 0:f269e3021894 137 /* write_name_arr's args are references, so result and cur_method will have changed */
elessair 0:f269e3021894 138 if (cur_method->super != 0) {
elessair 0:f269e3021894 139 cur_method = cur_method->super(p);
elessair 0:f269e3021894 140 } else {
elessair 0:f269e3021894 141 return true;
elessair 0:f269e3021894 142 }
elessair 0:f269e3021894 143 }
elessair 0:f269e3021894 144 }
elessair 0:f269e3021894 145
elessair 0:f269e3021894 146 /* Look through the methods for the one whose name matches */
elessair 0:f269e3021894 147 while (true) {
elessair 0:f269e3021894 148 for (; cur_method->name != NULL; cur_method++) {
elessair 0:f269e3021894 149 if (strcmp(cur_method->name, args.method_name) == 0) {
elessair 0:f269e3021894 150 (cur_method->method_caller)(p, &args, &r);
elessair 0:f269e3021894 151 return true;
elessair 0:f269e3021894 152 }
elessair 0:f269e3021894 153 }
elessair 0:f269e3021894 154
elessair 0:f269e3021894 155 if (cur_method->super != 0) {
elessair 0:f269e3021894 156 cur_method = cur_method->super(p);
elessair 0:f269e3021894 157 } else {
elessair 0:f269e3021894 158 /* end of methods and no match */
elessair 0:f269e3021894 159 return false;
elessair 0:f269e3021894 160 }
elessair 0:f269e3021894 161
elessair 0:f269e3021894 162 }
elessair 0:f269e3021894 163 }
elessair 0:f269e3021894 164
elessair 0:f269e3021894 165 /* Then try a class */
elessair 0:f269e3021894 166 for (const rpc_class *q = _classes; q != NULL; q = q->next) {
elessair 0:f269e3021894 167 if (strcmp(q->name, args.obj_name) == 0) {
elessair 0:f269e3021894 168 /* Matched the class name, so get its functions */
elessair 0:f269e3021894 169 const rpc_function *cur_func = q->static_functions;
elessair 0:f269e3021894 170 if (args.method_name == NULL) {
elessair 0:f269e3021894 171 for (; cur_func->name != NULL; cur_func++) {
elessair 0:f269e3021894 172 r.putData<const char*>(cur_func->name);
elessair 0:f269e3021894 173 }
elessair 0:f269e3021894 174 return true;
elessair 0:f269e3021894 175 } else {
elessair 0:f269e3021894 176 /* Otherwise call the appropriate function */
elessair 0:f269e3021894 177 for (; cur_func->name != NULL; cur_func++) {
elessair 0:f269e3021894 178 if (strcmp(cur_func->name, args.method_name) == 0) {
elessair 0:f269e3021894 179 (cur_func->function_caller)(&args, &r);
elessair 0:f269e3021894 180 return true;
elessair 0:f269e3021894 181 }
elessair 0:f269e3021894 182 }
elessair 0:f269e3021894 183 return false;
elessair 0:f269e3021894 184 }
elessair 0:f269e3021894 185 }
elessair 0:f269e3021894 186 }
elessair 0:f269e3021894 187
elessair 0:f269e3021894 188 return false;
elessair 0:f269e3021894 189 }
elessair 0:f269e3021894 190
elessair 0:f269e3021894 191 } // namespace mbed