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/>.
22 #include "rtt_server.h"
29 * This server allows access to Real Time Transfer (RTT) channels via TCP
37 static int read_callback(unsigned int channel, const uint8_t *buffer,
38 size_t length, void *user_data)
41 struct connection *connection;
44 connection = (struct connection *)user_data;
47 while (offset < length) {
48 ret = connection_write(connection, buffer + offset, length - offset);
51 LOG_ERROR("Failed to write data to socket.");
61 static int rtt_new_connection(struct connection *connection)
64 struct rtt_service *service;
66 service = connection->service->priv;
68 LOG_DEBUG("rtt: New connection for channel %u", service->channel);
70 ret = rtt_register_sink(service->channel, &read_callback, connection);
78 static int rtt_connection_closed(struct connection *connection)
80 struct rtt_service *service;
82 service = (struct rtt_service *)connection->service->priv;
83 rtt_unregister_sink(service->channel, &read_callback, connection);
85 LOG_DEBUG("rtt: Connection for channel %u closed", service->channel);
90 static int rtt_input(struct connection *connection)
93 unsigned char buffer[1024];
94 struct rtt_service *service;
97 service = (struct rtt_service *)connection->service->priv;
98 bytes_read = connection_read(connection, buffer, sizeof(buffer));
101 return ERROR_SERVER_REMOTE_CLOSED;
102 else if (bytes_read < 0) {
103 LOG_ERROR("error during read: %s", strerror(errno));
104 return ERROR_SERVER_REMOTE_CLOSED;
108 rtt_write_channel(service->channel, buffer, &length);
113 COMMAND_HANDLER(handle_rtt_start_command)
116 struct rtt_service *service;
119 return ERROR_COMMAND_SYNTAX_ERROR;
121 service = malloc(sizeof(struct rtt_service));
126 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel);
128 ret = add_service("rtt", CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED,
129 rtt_new_connection, rtt_input, rtt_connection_closed, service);
131 if (ret != ERROR_OK) {
139 COMMAND_HANDLER(handle_rtt_stop_command)
142 return ERROR_COMMAND_SYNTAX_ERROR;
144 remove_service("rtt", CMD_ARGV[0]);
149 static const struct command_registration rtt_server_subcommand_handlers[] = {
152 .handler = handle_rtt_start_command,
154 .help = "Start a RTT server",
155 .usage = "<port> <channel>"
159 .handler = handle_rtt_stop_command,
161 .help = "Stop a RTT server",
164 COMMAND_REGISTRATION_DONE
167 static const struct command_registration rtt_server_command_handlers[] = {
171 .help = "RTT server",
173 .chain = rtt_server_subcommand_handlers
175 COMMAND_REGISTRATION_DONE
178 static const struct command_registration rtt_command_handlers[] = {
184 .chain = rtt_server_command_handlers
186 COMMAND_REGISTRATION_DONE
189 int rtt_server_register_commands(struct command_context *ctx)
191 return register_commands(ctx, NULL, rtt_command_handlers);