1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2016-2017 by Marc Schink <dev@zapb.de>
15 #include "rtt_server.h"
22 * This server allows access to Real Time Transfer (RTT) channels via TCP
30 static int read_callback(unsigned int channel, const uint8_t *buffer,
31 size_t length, void *user_data)
34 struct connection *connection;
37 connection = (struct connection *)user_data;
40 while (offset < length) {
41 ret = connection_write(connection, buffer + offset, length - offset);
44 LOG_ERROR("Failed to write data to socket.");
54 static int rtt_new_connection(struct connection *connection)
57 struct rtt_service *service;
59 service = connection->service->priv;
61 LOG_DEBUG("rtt: New connection for channel %u", service->channel);
63 ret = rtt_register_sink(service->channel, &read_callback, connection);
71 static int rtt_connection_closed(struct connection *connection)
73 struct rtt_service *service;
75 service = (struct rtt_service *)connection->service->priv;
76 rtt_unregister_sink(service->channel, &read_callback, connection);
78 LOG_DEBUG("rtt: Connection for channel %u closed", service->channel);
83 static int rtt_input(struct connection *connection)
86 unsigned char buffer[1024];
87 struct rtt_service *service;
90 service = (struct rtt_service *)connection->service->priv;
91 bytes_read = connection_read(connection, buffer, sizeof(buffer));
94 return ERROR_SERVER_REMOTE_CLOSED;
95 else if (bytes_read < 0) {
96 LOG_ERROR("error during read: %s", strerror(errno));
97 return ERROR_SERVER_REMOTE_CLOSED;
101 rtt_write_channel(service->channel, buffer, &length);
106 static const struct service_driver rtt_service_driver = {
108 .new_connection_during_keep_alive_handler = NULL,
109 .new_connection_handler = rtt_new_connection,
110 .input_handler = rtt_input,
111 .connection_closed_handler = rtt_connection_closed,
112 .keep_client_alive_handler = NULL,
115 COMMAND_HANDLER(handle_rtt_start_command)
118 struct rtt_service *service;
121 return ERROR_COMMAND_SYNTAX_ERROR;
123 service = malloc(sizeof(struct rtt_service));
128 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel);
130 ret = add_service(&rtt_service_driver, CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED, service);
132 if (ret != ERROR_OK) {
140 COMMAND_HANDLER(handle_rtt_stop_command)
143 return ERROR_COMMAND_SYNTAX_ERROR;
145 remove_service("rtt", CMD_ARGV[0]);
150 static const struct command_registration rtt_server_subcommand_handlers[] = {
153 .handler = handle_rtt_start_command,
155 .help = "Start a RTT server",
156 .usage = "<port> <channel>"
160 .handler = handle_rtt_stop_command,
162 .help = "Stop a RTT server",
165 COMMAND_REGISTRATION_DONE
168 static const struct command_registration rtt_server_command_handlers[] = {
172 .help = "RTT server",
174 .chain = rtt_server_subcommand_handlers
176 COMMAND_REGISTRATION_DONE
179 static const struct command_registration rtt_command_handlers[] = {
185 .chain = rtt_server_command_handlers
187 COMMAND_REGISTRATION_DONE
190 int rtt_server_register_commands(struct command_context *ctx)
192 return register_commands(ctx, NULL, rtt_command_handlers);