2 * Copyright (C) 2016-2017 by Marc Schink <dev@zapb.de>
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.
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.
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/>.
26 #include "rtt_server.h"
33 * This server allows access to Real Time Transfer (RTT) channels via TCP
41 static int read_callback(unsigned int channel, const uint8_t *buffer,
42 size_t length, void *user_data)
45 struct connection *connection;
48 connection = (struct connection *)user_data;
51 while (offset < length) {
52 ret = connection_write(connection, buffer + offset, length - offset);
55 LOG_ERROR("Failed to write data to socket.");
65 static int rtt_new_connection(struct connection *connection)
68 struct rtt_service *service;
70 service = connection->service->priv;
72 LOG_DEBUG("rtt: New connection for channel %u", service->channel);
74 ret = rtt_register_sink(service->channel, &read_callback, connection);
82 static int rtt_connection_closed(struct connection *connection)
84 struct rtt_service *service;
86 service = (struct rtt_service *)connection->service->priv;
87 rtt_unregister_sink(service->channel, &read_callback, connection);
89 LOG_DEBUG("rtt: Connection for channel %u closed", service->channel);
94 static int rtt_input(struct connection *connection)
97 unsigned char buffer[1024];
98 struct rtt_service *service;
101 service = (struct rtt_service *)connection->service->priv;
102 bytes_read = connection_read(connection, buffer, sizeof(buffer));
105 return ERROR_SERVER_REMOTE_CLOSED;
106 else if (bytes_read < 0) {
107 LOG_ERROR("error during read: %s", strerror(errno));
108 return ERROR_SERVER_REMOTE_CLOSED;
112 rtt_write_channel(service->channel, buffer, &length);
117 static const struct service_driver rtt_service_driver = {
119 .new_connection_during_keep_alive_handler = NULL,
120 .new_connection_handler = rtt_new_connection,
121 .input_handler = rtt_input,
122 .connection_closed_handler = rtt_connection_closed,
123 .keep_client_alive_handler = NULL,
126 COMMAND_HANDLER(handle_rtt_start_command)
129 struct rtt_service *service;
132 return ERROR_COMMAND_SYNTAX_ERROR;
134 service = malloc(sizeof(struct rtt_service));
139 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel);
141 ret = add_service(&rtt_service_driver, CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED, service);
143 if (ret != ERROR_OK) {
151 COMMAND_HANDLER(handle_rtt_stop_command)
154 return ERROR_COMMAND_SYNTAX_ERROR;
156 remove_service("rtt", CMD_ARGV[0]);
161 static const struct command_registration rtt_server_subcommand_handlers[] = {
164 .handler = handle_rtt_start_command,
166 .help = "Start a RTT server",
167 .usage = "<port> <channel>"
171 .handler = handle_rtt_stop_command,
173 .help = "Stop a RTT server",
176 COMMAND_REGISTRATION_DONE
179 static const struct command_registration rtt_server_command_handlers[] = {
183 .help = "RTT server",
185 .chain = rtt_server_subcommand_handlers
187 COMMAND_REGISTRATION_DONE
190 static const struct command_registration rtt_command_handlers[] = {
196 .chain = rtt_server_command_handlers
198 COMMAND_REGISTRATION_DONE
201 int rtt_server_register_commands(struct command_context *ctx)
203 return register_commands(ctx, NULL, rtt_command_handlers);