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.
 
 
 
 
 
 

193 lines
4.2 KiB

  1. /*
  2. * Copyright (C) 2016-2017 by Marc Schink <dev@zapb.de>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <stdint.h>
  18. #include <rtt/rtt.h>
  19. #include "server.h"
  20. #include "rtt_server.h"
  21. /**
  22. * @file
  23. *
  24. * RTT server.
  25. *
  26. * This server allows access to Real Time Transfer (RTT) channels via TCP
  27. * connections.
  28. */
  29. struct rtt_service {
  30. unsigned int channel;
  31. };
  32. static int read_callback(unsigned int channel, const uint8_t *buffer,
  33. size_t length, void *user_data)
  34. {
  35. int ret;
  36. struct connection *connection;
  37. size_t offset;
  38. connection = (struct connection *)user_data;
  39. offset = 0;
  40. while (offset < length) {
  41. ret = connection_write(connection, buffer + offset, length - offset);
  42. if (ret < 0) {
  43. LOG_ERROR("Failed to write data to socket.");
  44. return ERROR_FAIL;
  45. }
  46. offset += ret;
  47. }
  48. return ERROR_OK;
  49. }
  50. static int rtt_new_connection(struct connection *connection)
  51. {
  52. int ret;
  53. struct rtt_service *service;
  54. service = connection->service->priv;
  55. LOG_DEBUG("rtt: New connection for channel %u", service->channel);
  56. ret = rtt_register_sink(service->channel, &read_callback, connection);
  57. if (ret != ERROR_OK)
  58. return ret;
  59. return ERROR_OK;
  60. }
  61. static int rtt_connection_closed(struct connection *connection)
  62. {
  63. struct rtt_service *service;
  64. service = (struct rtt_service *)connection->service->priv;
  65. rtt_unregister_sink(service->channel, &read_callback, connection);
  66. LOG_DEBUG("rtt: Connection for channel %u closed", service->channel);
  67. return ERROR_OK;
  68. }
  69. static int rtt_input(struct connection *connection)
  70. {
  71. int bytes_read;
  72. unsigned char buffer[1024];
  73. struct rtt_service *service;
  74. size_t length;
  75. service = (struct rtt_service *)connection->service->priv;
  76. bytes_read = connection_read(connection, buffer, sizeof(buffer));
  77. if (!bytes_read)
  78. return ERROR_SERVER_REMOTE_CLOSED;
  79. else if (bytes_read < 0) {
  80. LOG_ERROR("error during read: %s", strerror(errno));
  81. return ERROR_SERVER_REMOTE_CLOSED;
  82. }
  83. length = bytes_read;
  84. rtt_write_channel(service->channel, buffer, &length);
  85. return ERROR_OK;
  86. }
  87. COMMAND_HANDLER(handle_rtt_start_command)
  88. {
  89. int ret;
  90. struct rtt_service *service;
  91. if (CMD_ARGC != 2)
  92. return ERROR_COMMAND_SYNTAX_ERROR;
  93. service = malloc(sizeof(struct rtt_service));
  94. if (!service)
  95. return ERROR_FAIL;
  96. COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel);
  97. ret = add_service("rtt", CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED,
  98. rtt_new_connection, rtt_input, rtt_connection_closed, service);
  99. if (ret != ERROR_OK) {
  100. free(service);
  101. return ERROR_FAIL;
  102. }
  103. return ERROR_OK;
  104. }
  105. COMMAND_HANDLER(handle_rtt_stop_command)
  106. {
  107. if (CMD_ARGC != 1)
  108. return ERROR_COMMAND_SYNTAX_ERROR;
  109. remove_service("rtt", CMD_ARGV[0]);
  110. return ERROR_OK;
  111. }
  112. static const struct command_registration rtt_server_subcommand_handlers[] = {
  113. {
  114. .name = "start",
  115. .handler = handle_rtt_start_command,
  116. .mode = COMMAND_ANY,
  117. .help = "Start a RTT server",
  118. .usage = "<port> <channel>"
  119. },
  120. {
  121. .name = "stop",
  122. .handler = handle_rtt_stop_command,
  123. .mode = COMMAND_ANY,
  124. .help = "Stop a RTT server",
  125. .usage = "<port>"
  126. },
  127. COMMAND_REGISTRATION_DONE
  128. };
  129. static const struct command_registration rtt_server_command_handlers[] = {
  130. {
  131. .name = "server",
  132. .mode = COMMAND_ANY,
  133. .help = "RTT server",
  134. .usage = "",
  135. .chain = rtt_server_subcommand_handlers
  136. },
  137. COMMAND_REGISTRATION_DONE
  138. };
  139. static const struct command_registration rtt_command_handlers[] = {
  140. {
  141. .name = "rtt",
  142. .mode = COMMAND_ANY,
  143. .help = "RTT",
  144. .usage = "",
  145. .chain = rtt_server_command_handlers
  146. },
  147. COMMAND_REGISTRATION_DONE
  148. };
  149. int rtt_server_register_commands(struct command_context *ctx)
  150. {
  151. return register_commands(ctx, NULL, rtt_command_handlers);
  152. }