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
31 static int read_callback(unsigned int channel
, const uint8_t *buffer
,
32 size_t length
, void *user_data
)
35 struct connection
*connection
;
38 connection
= (struct connection
*)user_data
;
41 while (offset
< length
) {
42 ret
= connection_write(connection
, buffer
+ offset
, length
- offset
);
45 LOG_ERROR("Failed to write data to socket.");
55 static int rtt_new_connection(struct connection
*connection
)
58 struct rtt_service
*service
;
60 service
= connection
->service
->priv
;
62 LOG_DEBUG("rtt: New connection for channel %u", service
->channel
);
64 ret
= rtt_register_sink(service
->channel
, &read_callback
, connection
);
69 if (service
->hello_message
)
70 connection_write(connection
, service
->hello_message
, strlen(service
->hello_message
));
75 static int rtt_connection_closed(struct connection
*connection
)
77 struct rtt_service
*service
;
79 service
= (struct rtt_service
*)connection
->service
->priv
;
80 rtt_unregister_sink(service
->channel
, &read_callback
, connection
);
82 LOG_DEBUG("rtt: Connection for channel %u closed", service
->channel
);
87 static int rtt_input(struct connection
*connection
)
90 unsigned char buffer
[1024];
91 struct rtt_service
*service
;
94 service
= (struct rtt_service
*)connection
->service
->priv
;
95 bytes_read
= connection_read(connection
, buffer
, sizeof(buffer
));
98 return ERROR_SERVER_REMOTE_CLOSED
;
99 else if (bytes_read
< 0) {
100 LOG_ERROR("error during read: %s", strerror(errno
));
101 return ERROR_SERVER_REMOTE_CLOSED
;
105 rtt_write_channel(service
->channel
, buffer
, &length
);
110 static const struct service_driver rtt_service_driver
= {
112 .new_connection_during_keep_alive_handler
= NULL
,
113 .new_connection_handler
= rtt_new_connection
,
114 .input_handler
= rtt_input
,
115 .connection_closed_handler
= rtt_connection_closed
,
116 .keep_client_alive_handler
= NULL
,
119 COMMAND_HANDLER(handle_rtt_start_command
)
122 struct rtt_service
*service
;
124 if (CMD_ARGC
< 2 || CMD_ARGC
> 3)
125 return ERROR_COMMAND_SYNTAX_ERROR
;
127 service
= calloc(1, sizeof(struct rtt_service
));
132 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[1], service
->channel
);
135 const char *hello_message
= CMD_ARGV
[2];
136 size_t hello_length
= strlen(hello_message
);
138 service
->hello_message
= malloc(hello_length
+ 2);
139 if (!service
->hello_message
) {
140 LOG_ERROR("Out of memory");
144 strcpy(service
->hello_message
, hello_message
);
145 service
->hello_message
[hello_length
] = '\n';
146 service
->hello_message
[hello_length
+ 1] = '\0';
148 ret
= add_service(&rtt_service_driver
, CMD_ARGV
[0], CONNECTION_LIMIT_UNLIMITED
, service
);
150 if (ret
!= ERROR_OK
) {
158 COMMAND_HANDLER(handle_rtt_stop_command
)
161 return ERROR_COMMAND_SYNTAX_ERROR
;
163 remove_service("rtt", CMD_ARGV
[0]);
168 static const struct command_registration rtt_server_subcommand_handlers
[] = {
171 .handler
= handle_rtt_start_command
,
173 .help
= "Start a RTT server",
174 .usage
= "<port> <channel> [message]"
178 .handler
= handle_rtt_stop_command
,
180 .help
= "Stop a RTT server",
183 COMMAND_REGISTRATION_DONE
186 static const struct command_registration rtt_server_command_handlers
[] = {
190 .help
= "RTT server",
192 .chain
= rtt_server_subcommand_handlers
194 COMMAND_REGISTRATION_DONE
197 static const struct command_registration rtt_command_handlers
[] = {
203 .chain
= rtt_server_command_handlers
205 COMMAND_REGISTRATION_DONE
208 int rtt_server_register_commands(struct command_context
*ctx
)
210 return register_commands(ctx
, NULL
, rtt_command_handlers
);