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
);