File indexing completed on 2025-05-11 08:24:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include <errno.h>
0027 #include <stdlib.h>
0028 #include <unistd.h>
0029
0030 #include <arpa/inet.h>
0031 #include <netinet/in.h>
0032 #include <netinet/tcp.h>
0033 #include <sys/types.h>
0034 #include <sys/socket.h>
0035
0036 #include <rtems/rtems-debugger.h>
0037 #include <rtems/debugger/rtems-debugger-server.h>
0038 #include <rtems/debugger/rtems-debugger-remote.h>
0039
0040 #include <rtems/rtems-debugger-remote-tcp.h>
0041
0042
0043
0044
0045 #define RTEMS_DB_PORT_DEFAULT (8284)
0046
0047
0048
0049
0050 typedef struct
0051 {
0052 int fd;
0053 int port;
0054 } rtems_debugger_remote_tcp;
0055
0056 static rtems_debugger_remote_tcp*
0057 tcp_remote(rtems_debugger_remote* remote)
0058 {
0059 rtems_debugger_remote_tcp* tcp = NULL;
0060 rtems_debugger_lock();
0061 if (remote != NULL && remote->data != NULL)
0062 tcp = (rtems_debugger_remote_tcp*) remote->data;
0063 rtems_debugger_unlock();
0064 return tcp;
0065 }
0066
0067 static int
0068 tcp_remote_begin(rtems_debugger_remote* remote, const char* device)
0069 {
0070 rtems_debugger_remote_tcp* tcp;
0071 int port;
0072 char* end;
0073
0074 rtems_debugger_lock();
0075
0076
0077
0078
0079 port = strtoul(device, &end, 10);
0080 if (port == 0 || *end != '\0') {
0081 rtems_debugger_printf("error: rtems-db: tcp remote: invalid port: %s\n", device);
0082 return -1;
0083 }
0084
0085 tcp = malloc(sizeof(rtems_debugger_remote_tcp));
0086 if (tcp == NULL) {
0087 errno = ENOMEM;
0088 return -1;
0089 }
0090
0091 remote->data = tcp;
0092
0093 tcp->fd = -1;
0094 tcp->port = port;
0095
0096 rtems_debugger_unlock();
0097
0098 return 0;
0099 }
0100
0101 static int
0102 tcp_remote_end(rtems_debugger_remote* remote)
0103 {
0104 rtems_debugger_lock();
0105
0106 if (remote != NULL && remote->data != NULL) {
0107 rtems_debugger_remote_tcp* tcp = (rtems_debugger_remote_tcp*) remote->data;
0108 if (tcp != NULL) {
0109 if (tcp->fd >= 0)
0110 close(tcp->fd);
0111 free(tcp);
0112 remote->data = NULL;
0113 }
0114 }
0115
0116 rtems_debugger_unlock();
0117
0118 return 0;
0119 }
0120
0121 static int
0122 tcp_remote_connect(rtems_debugger_remote* remote)
0123 {
0124 int ld;
0125 struct sockaddr_in addr = {0};
0126 socklen_t opt;
0127 socklen_t len;
0128 bool running;
0129 struct timeval timeout;
0130 rtems_debugger_remote_tcp* tcp = tcp_remote(remote);
0131 int r;
0132
0133 if (rtems_debugger_verbose())
0134 rtems_debugger_printf("error: rtems-db: tcp remote: connect\n");
0135
0136 ld = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
0137 if (ld < 0) {
0138 rtems_debugger_printf("error: rtems-db: tcp remote: socket: (%d) %s\n",
0139 errno, strerror(errno));
0140 return -1;
0141 }
0142
0143 opt = 1;
0144 r = setsockopt(ld,
0145 SOL_SOCKET,
0146 SO_REUSEADDR,
0147 (char *) &opt,
0148 sizeof(opt));
0149 if (r < 0) {
0150 close(ld);
0151 rtems_debugger_printf("error: rtems-db: tcp remote: setsocket: reuseaddr: (%d) %s\n",
0152 errno, strerror(errno));
0153 return -1;
0154 }
0155
0156 addr.sin_family = PF_INET;
0157 addr.sin_port = htons(tcp->port);
0158 addr.sin_addr.s_addr = INADDR_ANY;
0159
0160 r = bind(ld, (struct sockaddr *) &addr, sizeof(addr));
0161 if (r < 0) {
0162 close(ld);
0163 rtems_debugger_printf("error: rtems-db: tcp remote: bind: (%d) %s\n",
0164 errno, strerror(errno));
0165 return -1;
0166 }
0167
0168
0169
0170
0171 r = listen(ld, 1);
0172 if (r < 0) {
0173 close(ld);
0174 rtems_debugger_printf("error: rtems-db: tcp remote: listen: (%d) %s\n",
0175 errno, strerror(errno));
0176 return -1;
0177 }
0178
0179
0180
0181
0182 if (tcp->port == 0) {
0183 len = sizeof(addr);
0184 r = getsockname(ld, (struct sockaddr *) &addr, &len);
0185 if (r < 0 || len < sizeof(addr)) {
0186 close(ld);
0187 rtems_debugger_printf("error: rtems-db: tcp remote: getsockname: (%d) %s\n",
0188 errno, strerror(errno));
0189 return -1;
0190 }
0191 tcp->port = ntohs(addr.sin_port);
0192 }
0193
0194 rtems_debugger_printf("rtems-db: tcp remote: listing on port: %d\n",
0195 tcp->port);
0196
0197 len = sizeof(addr);
0198 tcp->fd = accept(ld, (struct sockaddr *) &addr, &len);
0199
0200 running = rtems_debugger_server_running();
0201
0202 close(ld);
0203
0204 if (tcp->fd < 0) {
0205
0206
0207
0208 if (errno != EBADF)
0209 rtems_debugger_printf("error: rtems-db: accept: (%d) %s\n",
0210 errno, strerror(errno));
0211 return -1;
0212 }
0213
0214 if (!running) {
0215 close(tcp->fd);
0216 errno = EIO;
0217 return -1;
0218 }
0219
0220 opt = 1;
0221 r = setsockopt(tcp->fd,
0222 SOL_SOCKET, SO_KEEPALIVE,
0223 (char*) &opt,
0224 sizeof(opt));
0225 if (r < 0) {
0226 int errno_ = errno;
0227 close(tcp->fd);
0228 rtems_debugger_printf("error: rtems-db: tcp remote: set keepalive: (%d) %s\n",
0229 errno, strerror(errno));
0230 errno = errno_;
0231 return -1;
0232 }
0233
0234 opt = 1;
0235 r = setsockopt(tcp->fd,
0236 IPPROTO_TCP, TCP_NODELAY,
0237 (char*) &opt, sizeof(opt));
0238 if (r < 0) {
0239 int errno_ = errno;
0240 close(tcp->fd);
0241 rtems_debugger_printf("error: rtems-db: tcp remote: set no-delay: (%d) %s\n",
0242 errno, strerror(errno));
0243 errno = errno_;
0244 return -1;
0245 }
0246
0247 timeout.tv_sec = rtems_debugger->timeout;
0248 timeout.tv_usec = 0;
0249
0250 r = setsockopt(tcp->fd,
0251 SOL_SOCKET, SO_RCVTIMEO,
0252 (char*) &timeout, sizeof(timeout));
0253 if (r < 0) {
0254 int errno_ = errno;
0255 close(tcp->fd);
0256 rtems_debugger_printf("error: rtems-db: tcp remote: set rcv-timeout: (%d) %s\n",
0257 errno, strerror(errno));
0258 errno = errno_;
0259 return -1;
0260 }
0261
0262 rtems_debugger_printf("rtems-db: tcp remote: connect host: %s\n",
0263 inet_ntoa(addr.sin_addr));
0264
0265 return 0;
0266 }
0267
0268 static int
0269 tcp_remote_disconnect(rtems_debugger_remote* remote)
0270 {
0271 rtems_debugger_remote_tcp* tcp;
0272
0273 rtems_debugger_lock();
0274
0275 rtems_debugger_printf("rtems-db: tcp remote: disconnect host\n");
0276
0277 tcp = (rtems_debugger_remote_tcp*) remote->data;
0278 close(tcp->fd);
0279 tcp->fd = -1;
0280
0281 rtems_debugger_unlock();
0282
0283 return 0;
0284 }
0285
0286 static bool
0287 tcp_remote_isconnected(rtems_debugger_remote* remote)
0288 {
0289 rtems_debugger_remote_tcp* tcp = tcp_remote(remote);
0290 return tcp != NULL && tcp->fd >= 0;
0291 }
0292
0293 static ssize_t
0294 tcp_remote_receive(rtems_debugger_remote* remote,
0295 void* buf,
0296 size_t nbytes)
0297 {
0298 rtems_debugger_remote_tcp* tcp = tcp_remote(remote);
0299 ssize_t len;
0300 if (tcp != NULL) {
0301 len = read(tcp->fd, buf, nbytes);
0302 }
0303 else {
0304 errno = EIO;
0305 len = -1;
0306 }
0307 return len;
0308 }
0309
0310 static ssize_t
0311 tcp_remote_send(rtems_debugger_remote* remote,
0312 const void* buf,
0313 size_t nbytes)
0314 {
0315 rtems_debugger_remote_tcp* tcp = tcp_remote(remote);
0316 ssize_t len;
0317 if (tcp != NULL) {
0318 len = write(tcp->fd, buf, nbytes);
0319 }
0320 else {
0321 errno = EIO;
0322 len = -1;
0323 }
0324 return len;
0325 }
0326
0327 static rtems_debugger_remote remote_tcp =
0328 {
0329 .name = "tcp",
0330 .begin = tcp_remote_begin,
0331 .end = tcp_remote_end,
0332 .connect = tcp_remote_connect,
0333 .disconnect = tcp_remote_disconnect,
0334 .isconnected = tcp_remote_isconnected,
0335 .read = tcp_remote_receive,
0336 .write = tcp_remote_send
0337 };
0338
0339 int
0340 rtems_debugger_register_tcp_remote(void)
0341 {
0342 return rtems_debugger_remote_register(&remote_tcp);
0343 }