ipdbg: fix double free of virtual-ir data
[openocd.git] / src / server / rtt_server.c
blob97691534751caf1e29c44023d8cc8f87b7040ea7
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /*
4 * Copyright (C) 2016-2017 by Marc Schink <dev@zapb.de>
5 */
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
11 #include <stdint.h>
12 #include <rtt/rtt.h>
14 #include "server.h"
15 #include "rtt_server.h"
17 /**
18 * @file
20 * RTT server.
22 * This server allows access to Real Time Transfer (RTT) channels via TCP
23 * connections.
26 struct rtt_service {
27 unsigned int channel;
28 char *hello_message;
31 static int read_callback(unsigned int channel, const uint8_t *buffer,
32 size_t length, void *user_data)
34 int ret;
35 struct connection *connection;
36 size_t offset;
38 connection = (struct connection *)user_data;
39 offset = 0;
41 while (offset < length) {
42 ret = connection_write(connection, buffer + offset, length - offset);
44 if (ret < 0) {
45 LOG_ERROR("Failed to write data to socket.");
46 return ERROR_FAIL;
49 offset += ret;
52 return ERROR_OK;
55 static int rtt_new_connection(struct connection *connection)
57 int ret;
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);
66 if (ret != ERROR_OK)
67 return ret;
69 if (service->hello_message)
70 connection_write(connection, service->hello_message, strlen(service->hello_message));
72 return ERROR_OK;
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);
84 return ERROR_OK;
87 static int rtt_input(struct connection *connection)
89 int bytes_read;
90 unsigned char buffer[1024];
91 struct rtt_service *service;
92 size_t length;
94 service = (struct rtt_service *)connection->service->priv;
95 bytes_read = connection_read(connection, buffer, sizeof(buffer));
97 if (!bytes_read)
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;
104 length = bytes_read;
105 rtt_write_channel(service->channel, buffer, &length);
107 return ERROR_OK;
110 static const struct service_driver rtt_service_driver = {
111 .name = "rtt",
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)
121 int ret;
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));
129 if (!service)
130 return ERROR_FAIL;
132 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel);
134 if (CMD_ARGC >= 3) {
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");
141 free(service);
142 return ERROR_FAIL;
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) {
151 free(service);
152 return ERROR_FAIL;
155 return ERROR_OK;
158 COMMAND_HANDLER(handle_rtt_stop_command)
160 if (CMD_ARGC != 1)
161 return ERROR_COMMAND_SYNTAX_ERROR;
163 remove_service("rtt", CMD_ARGV[0]);
165 return ERROR_OK;
168 static const struct command_registration rtt_server_subcommand_handlers[] = {
170 .name = "start",
171 .handler = handle_rtt_start_command,
172 .mode = COMMAND_ANY,
173 .help = "Start a RTT server",
174 .usage = "<port> <channel> [message]"
177 .name = "stop",
178 .handler = handle_rtt_stop_command,
179 .mode = COMMAND_ANY,
180 .help = "Stop a RTT server",
181 .usage = "<port>"
183 COMMAND_REGISTRATION_DONE
186 static const struct command_registration rtt_server_command_handlers[] = {
188 .name = "server",
189 .mode = COMMAND_ANY,
190 .help = "RTT server",
191 .usage = "",
192 .chain = rtt_server_subcommand_handlers
194 COMMAND_REGISTRATION_DONE
197 static const struct command_registration rtt_command_handlers[] = {
199 .name = "rtt",
200 .mode = COMMAND_ANY,
201 .help = "RTT",
202 .usage = "",
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);