Add jaylink_device_get_usb_bus_ports()
[libjaylink.git] / libjaylink / transport_tcp.c
blob7e1017933005d86dac79c95613e6ae2d9e4fee88
1 /*
2 * This file is part of the libjaylink project.
4 * Copyright (C) 2015-2017 Marc Schink <jaylink-dev@marcschink.de>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <stdlib.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include <sys/types.h>
25 #ifdef _WIN32
26 #include <winsock2.h>
27 #include <ws2tcpip.h>
28 #else
29 #include <sys/time.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netdb.h>
33 #include <netinet/in.h>
34 #endif
36 #include "libjaylink.h"
37 #include "libjaylink-internal.h"
39 /**
40 * @file
42 * Transport abstraction layer (TCP/IP).
45 /** @cond PRIVATE */
46 #define CMD_SERVER 0x00
47 #define CMD_CLIENT 0x07
49 /**
50 * Response status code indicating that the maximum number of simultaneous
51 * connections on the device has been reached.
53 #define RESP_MAX_CONNECTIONS 0xfe
55 /** Buffer size in bytes. */
56 #define BUFFER_SIZE 2048
58 /** Timeout of a receive operation in milliseconds. */
59 #define RECV_TIMEOUT 5000
60 /** Timeout of a send operation in milliseconds. */
61 #define SEND_TIMEOUT 5000
63 /** String of the port number for the J-Link TCP/IP protocol. */
64 #define PORT_STRING "19020"
66 /** Size of the server's hello message in bytes. */
67 #define SERVER_HELLO_SIZE 4
68 /**
69 * Maximum length of the server name including trailing null-terminator in
70 * bytes.
72 #define SERVER_NAME_MAX_LENGTH 256
73 /** @endcond */
75 static int initialize_handle(struct jaylink_device_handle *devh)
77 struct jaylink_context *ctx;
79 ctx = devh->dev->ctx;
81 devh->buffer_size = BUFFER_SIZE;
82 devh->buffer = malloc(devh->buffer_size);
84 if (!devh->buffer) {
85 log_err(ctx, "Transport buffer malloc failed.");
86 return JAYLINK_ERR_MALLOC;
89 devh->read_length = 0;
90 devh->bytes_available = 0;
91 devh->read_pos = 0;
93 devh->write_length = 0;
94 devh->write_pos = 0;
96 return JAYLINK_OK;
99 static void cleanup_handle(struct jaylink_device_handle *devh)
101 free(devh->buffer);
104 static int _recv(struct jaylink_device_handle *devh, uint8_t *buffer,
105 size_t length)
107 struct jaylink_context *ctx;
108 size_t tmp;
110 ctx = devh->dev->ctx;
112 while (length > 0) {
113 tmp = length;
115 if (!socket_recv(devh->sock, buffer, &tmp, 0)) {
116 log_err(ctx, "Failed to receive data from device.");
117 return JAYLINK_ERR_IO;
118 } else if (!tmp) {
119 log_err(ctx, "Failed to receive data from device: "
120 "remote connection closed.");
121 return JAYLINK_ERR_IO;
124 buffer += tmp;
125 length -= tmp;
127 log_dbgio(ctx, "Received %zu bytes from device.", tmp);
130 return JAYLINK_OK;
133 static int handle_server_hello(struct jaylink_device_handle *devh)
135 int ret;
136 struct jaylink_context *ctx;
137 uint8_t buf[SERVER_HELLO_SIZE];
138 char name[SERVER_NAME_MAX_LENGTH];
139 uint16_t proto_version;
140 size_t length;
142 ctx = devh->dev->ctx;
144 ret = _recv(devh, buf, sizeof(buf));
146 if (ret != JAYLINK_OK) {
147 log_err(ctx, "Failed to receive hello message.");
148 return ret;
151 if (buf[0] == RESP_MAX_CONNECTIONS) {
152 log_err(ctx, "Maximum number of connections reached.");
153 return JAYLINK_ERR;
156 if (buf[0] != CMD_SERVER) {
157 log_err(ctx, "Invalid hello message received.");
158 return JAYLINK_ERR_PROTO;
161 proto_version = buffer_get_u16(buf, 1);
163 log_dbg(ctx, "Protocol version: 0x%04x.", proto_version);
165 length = buf[3];
166 ret = _recv(devh, (uint8_t *)name, length);
168 if (ret != JAYLINK_OK) {
169 log_err(ctx, "Failed to receive server name.");
170 return ret;
173 name[length] = '\0';
175 log_dbg(ctx, "Server name: %s.", name);
177 return JAYLINK_OK;
180 static int set_socket_timeouts(struct jaylink_device_handle *devh)
182 struct jaylink_context *ctx;
184 ctx = devh->dev->ctx;
185 #ifdef _WIN32
186 DWORD timeout;
188 timeout = RECV_TIMEOUT;
190 if (!socket_set_option(devh->sock, SOL_SOCKET, SO_RCVTIMEO, &timeout,
191 sizeof(timeout))) {
192 log_err(ctx, "Failed to set socket receive timeout.");
193 return JAYLINK_ERR;
196 timeout = SEND_TIMEOUT;
198 if (!socket_set_option(devh->sock, SOL_SOCKET, SO_SNDTIMEO, &timeout,
199 sizeof(timeout))) {
200 log_err(ctx, "Failed to set socket send timeout.");
201 return JAYLINK_ERR;
203 #else
204 struct timeval timeout;
206 timeout.tv_sec = RECV_TIMEOUT / 1000;
207 timeout.tv_usec = (RECV_TIMEOUT % 1000) * 1000;
209 if (!socket_set_option(devh->sock, SOL_SOCKET, SO_RCVTIMEO, &timeout,
210 sizeof(struct timeval))) {
211 log_err(ctx, "Failed to set socket receive timeout.");
212 return JAYLINK_ERR;
215 timeout.tv_sec = SEND_TIMEOUT / 1000;
216 timeout.tv_usec = (SEND_TIMEOUT % 1000) * 1000;
218 if (!socket_set_option(devh->sock, SOL_SOCKET, SO_SNDTIMEO, &timeout,
219 sizeof(struct timeval))) {
220 log_err(ctx, "Failed to set socket send timeout.");
221 return JAYLINK_ERR;
223 #endif
224 return JAYLINK_OK;
227 JAYLINK_PRIV int transport_tcp_open(struct jaylink_device_handle *devh)
229 int ret;
230 struct jaylink_context *ctx;
231 struct jaylink_device *dev;
232 struct addrinfo hints;
233 struct addrinfo *info;
234 struct addrinfo *rp;
235 int sock;
237 dev = devh->dev;
238 ctx = dev->ctx;
240 log_dbg(ctx, "Trying to open device (IPv4 address = %s).",
241 dev->ipv4_address);
243 ret = initialize_handle(devh);
245 if (ret != JAYLINK_OK) {
246 log_err(ctx, "Initialize device handle failed.");
247 return ret;
250 memset(&hints, 0, sizeof(struct addrinfo));
251 hints.ai_family = AF_INET;
252 hints.ai_socktype = SOCK_STREAM;
253 hints.ai_protocol = IPPROTO_TCP;
255 ret = getaddrinfo(dev->ipv4_address, PORT_STRING, &hints, &info);
257 if (ret != 0) {
258 log_err(ctx, "Address lookup failed.");
259 cleanup_handle(devh);
260 return JAYLINK_ERR;
263 sock = -1;
265 for (rp = info; rp != NULL; rp = rp->ai_next) {
266 sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
268 if (sock < 0)
269 continue;
271 if (!connect(sock, info->ai_addr, info->ai_addrlen))
272 break;
274 socket_close(sock);
275 sock = -1;
278 freeaddrinfo(info);
280 if (sock < 0) {
281 log_err(ctx, "Failed to open device.");
282 cleanup_handle(devh);
283 return JAYLINK_ERR;
286 log_dbg(ctx, "Device opened successfully.");
288 devh->sock = sock;
289 ret = set_socket_timeouts(devh);
291 if (ret != JAYLINK_OK) {
292 socket_close(sock);
293 cleanup_handle(devh);
294 return ret;
297 ret = handle_server_hello(devh);
299 if (ret != JAYLINK_OK) {
300 socket_close(sock);
301 cleanup_handle(devh);
302 return ret;
305 return JAYLINK_OK;
308 JAYLINK_PRIV int transport_tcp_close(struct jaylink_device_handle *devh)
310 struct jaylink_context *ctx;
312 ctx = devh->dev->ctx;
314 log_dbg(ctx, "Closing device (IPv4 address = %s).",
315 devh->dev->ipv4_address);
317 cleanup_handle(devh);
319 log_dbg(ctx, "Device closed successfully.");
321 return JAYLINK_OK;
324 JAYLINK_PRIV int transport_tcp_start_write(struct jaylink_device_handle *devh,
325 size_t length, bool has_command)
327 struct jaylink_context *ctx;
329 if (!length)
330 return JAYLINK_ERR_ARG;
332 ctx = devh->dev->ctx;
334 log_dbgio(ctx, "Starting write operation (length = %zu bytes).",
335 length);
337 if (devh->write_pos > 0)
338 log_warn(ctx, "Last write operation left %zu bytes in the "
339 "buffer.", devh->write_pos);
341 if (devh->write_length > 0)
342 log_warn(ctx, "Last write operation was not performed.");
344 devh->write_length = length;
345 devh->write_pos = 0;
347 if (has_command) {
348 devh->buffer[0] = CMD_CLIENT;
349 devh->write_pos++;
352 return JAYLINK_OK;
355 JAYLINK_PRIV int transport_tcp_start_read(struct jaylink_device_handle *devh,
356 size_t length)
358 struct jaylink_context *ctx;
360 if (!length)
361 return JAYLINK_ERR_ARG;
363 ctx = devh->dev->ctx;
365 log_dbgio(ctx, "Starting read operation (length = %zu bytes).",
366 length);
368 if (devh->bytes_available > 0)
369 log_dbg(ctx, "Last read operation left %zu bytes in the "
370 "buffer.", devh->bytes_available);
372 if (devh->read_length > 0)
373 log_warn(ctx, "Last read operation left %zu bytes.",
374 devh->read_length);
376 devh->read_length = length;
378 return JAYLINK_OK;
381 JAYLINK_PRIV int transport_tcp_start_write_read(
382 struct jaylink_device_handle *devh, size_t write_length,
383 size_t read_length, bool has_command)
385 struct jaylink_context *ctx;
387 if (!read_length || !write_length)
388 return JAYLINK_ERR_ARG;
390 ctx = devh->dev->ctx;
392 log_dbgio(ctx, "Starting write / read operation (length = "
393 "%zu / %zu bytes).", write_length, read_length);
395 if (devh->write_pos > 0)
396 log_warn(ctx, "Last write operation left %zu bytes in the "
397 "buffer.", devh->write_pos);
399 if (devh->write_length > 0)
400 log_warn(ctx, "Last write operation was not performed.");
402 if (devh->bytes_available > 0)
403 log_warn(ctx, "Last read operation left %zu bytes in the "
404 "buffer.", devh->bytes_available);
406 if (devh->read_length > 0)
407 log_warn(ctx, "Last read operation left %zu bytes.",
408 devh->read_length);
410 devh->write_length = write_length;
411 devh->write_pos = 0;
413 if (has_command) {
414 devh->buffer[0] = CMD_CLIENT;
415 devh->write_pos++;
418 devh->read_length = read_length;
419 devh->bytes_available = 0;
420 devh->read_pos = 0;
422 return JAYLINK_OK;
425 static int _send(struct jaylink_device_handle *devh, const uint8_t *buffer,
426 size_t length)
428 struct jaylink_context *ctx;
429 size_t tmp;
431 ctx = devh->dev->ctx;
433 while (length > 0) {
434 tmp = length;
436 if (!socket_send(devh->sock, buffer, &tmp, 0)) {
437 log_err(ctx, "Failed to send data to device.");
438 return JAYLINK_ERR_IO;
441 buffer += tmp;
442 length -= tmp;
444 log_dbgio(ctx, "Sent %zu bytes to device.", tmp);
447 return JAYLINK_OK;
450 static bool adjust_buffer(struct jaylink_device_handle *devh, size_t size)
452 struct jaylink_context *ctx;
453 uint8_t *buffer;
454 size_t num;
456 ctx = devh->dev->ctx;
458 /* Adjust buffer size to a multiple of BUFFER_SIZE bytes. */
459 num = size / BUFFER_SIZE;
461 if (size % BUFFER_SIZE > 0)
462 num++;
464 size = num * BUFFER_SIZE;
465 buffer = realloc(devh->buffer, size);
467 if (!buffer) {
468 log_err(ctx, "Failed to adjust buffer size to %zu bytes.",
469 size);
470 return false;
473 devh->buffer = buffer;
474 devh->buffer_size = size;
476 log_dbg(ctx, "Adjusted buffer size to %zu bytes.", size);
478 return true;
481 JAYLINK_PRIV int transport_tcp_write(struct jaylink_device_handle *devh,
482 const uint8_t *buffer, size_t length)
484 int ret;
485 struct jaylink_context *ctx;
486 size_t tmp;
488 ctx = devh->dev->ctx;
490 if (length > devh->write_length) {
491 log_err(ctx, "Requested to write %zu bytes but only %zu bytes "
492 "are expected for the write operation.", length,
493 devh->write_length);
494 return JAYLINK_ERR_ARG;
498 * Store data in the buffer if the expected number of bytes for the
499 * write operation is not reached.
501 if (length < devh->write_length) {
502 if (devh->write_pos + length > devh->buffer_size) {
503 if (!adjust_buffer(devh, devh->write_pos + length))
504 return JAYLINK_ERR_MALLOC;
507 memcpy(devh->buffer + devh->write_pos, buffer, length);
509 devh->write_length -= length;
510 devh->write_pos += length;
512 log_dbgio(ctx, "Wrote %zu bytes into buffer.", length);
513 return JAYLINK_OK;
517 * Expected number of bytes for this write operation is reached and
518 * therefore the write operation will be performed.
520 devh->write_length = 0;
522 /* Send data directly to the device if the buffer is empty. */
523 if (!devh->write_pos)
524 return _send(devh, buffer, length);
526 tmp = MIN(length, devh->buffer_size - devh->write_pos);
529 * Fill up the internal buffer in order to reduce the number of
530 * messages sent to the device for performance reasons.
532 memcpy(devh->buffer + devh->write_pos, buffer, tmp);
534 length -= tmp;
535 buffer += tmp;
537 log_dbgio(ctx, "Buffer filled up with %zu bytes.", tmp);
539 ret = _send(devh, devh->buffer, devh->write_pos + tmp);
541 devh->write_pos = 0;
543 if (ret != JAYLINK_OK)
544 return ret;
546 if (!length)
547 return JAYLINK_OK;
549 return _send(devh, buffer, length);
552 JAYLINK_PRIV int transport_tcp_read(struct jaylink_device_handle *devh,
553 uint8_t *buffer, size_t length)
555 int ret;
556 struct jaylink_context *ctx;
558 ctx = devh->dev->ctx;
560 if (length > devh->read_length) {
561 log_err(ctx, "Requested to read %zu bytes but only %zu bytes "
562 "are expected for the read operation.", length,
563 devh->read_length);
564 return JAYLINK_ERR_ARG;
567 if (length <= devh->bytes_available) {
568 memcpy(buffer, devh->buffer + devh->read_pos, length);
570 devh->read_length -= length;
571 devh->bytes_available -= length;
572 devh->read_pos += length;
574 log_dbgio(ctx, "Read %zu bytes from buffer.", length);
575 return JAYLINK_OK;
578 if (devh->bytes_available) {
579 memcpy(buffer, devh->buffer + devh->read_pos,
580 devh->bytes_available);
582 buffer += devh->bytes_available;
583 length -= devh->bytes_available;
584 devh->read_length -= devh->bytes_available;
586 log_dbgio(ctx, "Read %zu bytes from buffer to flush it.",
587 devh->bytes_available);
589 devh->bytes_available = 0;
590 devh->read_pos = 0;
593 ret = _recv(devh, buffer, length);
595 if (ret != JAYLINK_OK)
596 return ret;
598 devh->read_length -= length;
600 return JAYLINK_OK;