You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

rpc.cpp 5.4KB

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