OpenOCD
transport_tcp.c
Go to the documentation of this file.
1 /*
2  * This file is part of the libjaylink project.
3  *
4  * Copyright (C) 2015-2017 Marc Schink <jaylink-dev@marcschink.de>
5  *
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.
10  *
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.
15  *
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/>.
18  */
19 
20 #include <stdlib.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include <sys/types.h>
24 
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
35 
36 #include "libjaylink.h"
37 #include "libjaylink-internal.h"
38 
46 #define CMD_SERVER 0x00
47 #define CMD_CLIENT 0x07
48 
53 #define RESP_MAX_CONNECTIONS 0xfe
54 
56 #define BUFFER_SIZE 2048
57 
59 #define RECV_TIMEOUT 5000
60 
61 #define SEND_TIMEOUT 5000
62 
64 #define PORT_STRING "19020"
65 
67 #define SERVER_HELLO_SIZE 4
68 
72 #define SERVER_NAME_MAX_LENGTH 256
73 
76 {
77  struct jaylink_context *ctx;
78 
79  ctx = devh->dev->ctx;
80 
81  devh->buffer_size = BUFFER_SIZE;
82  devh->buffer = malloc(devh->buffer_size);
83 
84  if (!devh->buffer) {
85  log_err(ctx, "Transport buffer malloc failed.");
86  return JAYLINK_ERR_MALLOC;
87  }
88 
89  devh->read_length = 0;
90  devh->bytes_available = 0;
91  devh->read_pos = 0;
92 
93  devh->write_length = 0;
94  devh->write_pos = 0;
95 
96  return JAYLINK_OK;
97 }
98 
100 {
101  free(devh->buffer);
102 }
103 
104 static int _recv(struct jaylink_device_handle *devh, uint8_t *buffer,
105  size_t length)
106 {
107  struct jaylink_context *ctx;
108  size_t tmp;
109 
110  ctx = devh->dev->ctx;
111 
112  while (length > 0) {
113  tmp = length;
114 
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;
122  }
123 
124  buffer += tmp;
125  length -= tmp;
126 
127  log_dbgio(ctx, "Received %zu bytes from device.", tmp);
128  }
129 
130  return JAYLINK_OK;
131 }
132 
134 {
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;
141 
142  ctx = devh->dev->ctx;
143 
144  ret = _recv(devh, buf, sizeof(buf));
145 
146  if (ret != JAYLINK_OK) {
147  log_err(ctx, "Failed to receive hello message.");
148  return ret;
149  }
150 
151  if (buf[0] == RESP_MAX_CONNECTIONS) {
152  log_err(ctx, "Maximum number of connections reached.");
153  return JAYLINK_ERR;
154  }
155 
156  if (buf[0] != CMD_SERVER) {
157  log_err(ctx, "Invalid hello message received.");
158  return JAYLINK_ERR_PROTO;
159  }
160 
161  proto_version = buffer_get_u16(buf, 1);
162 
163  log_dbg(ctx, "Protocol version: 0x%04x.", proto_version);
164 
165  length = buf[3];
166  ret = _recv(devh, (uint8_t *)name, length);
167 
168  if (ret != JAYLINK_OK) {
169  log_err(ctx, "Failed to receive server name.");
170  return ret;
171  }
172 
173  name[length] = '\0';
174 
175  log_dbg(ctx, "Server name: %s.", name);
176 
177  return JAYLINK_OK;
178 }
179 
181 {
182  struct jaylink_context *ctx;
183 
184  ctx = devh->dev->ctx;
185 #ifdef _WIN32
186  DWORD timeout;
187 
188  timeout = RECV_TIMEOUT;
189 
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;
194  }
195 
196  timeout = SEND_TIMEOUT;
197 
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;
202  }
203 #else
204  struct timeval timeout;
205 
206  timeout.tv_sec = RECV_TIMEOUT / 1000;
207  timeout.tv_usec = (RECV_TIMEOUT % 1000) * 1000;
208 
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;
213  }
214 
215  timeout.tv_sec = SEND_TIMEOUT / 1000;
216  timeout.tv_usec = (SEND_TIMEOUT % 1000) * 1000;
217 
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;
222  }
223 #endif
224  return JAYLINK_OK;
225 }
226 
228 {
229  int ret;
230  struct jaylink_context *ctx;
231  struct jaylink_device *dev;
232  struct addrinfo hints;
233  struct addrinfo *info;
234  int sock;
235 
236  dev = devh->dev;
237  ctx = dev->ctx;
238 
239  log_dbg(ctx, "Trying to open device (IPv4 address = %s).",
240  dev->ipv4_address);
241 
242  ret = initialize_handle(devh);
243 
244  if (ret != JAYLINK_OK) {
245  log_err(ctx, "Initialize device handle failed.");
246  return ret;
247  }
248 
249  memset(&hints, 0, sizeof(struct addrinfo));
250  hints.ai_family = AF_INET;
251  hints.ai_socktype = SOCK_STREAM;
252  hints.ai_protocol = IPPROTO_TCP;
253 
254  ret = getaddrinfo(dev->ipv4_address, PORT_STRING, &hints, &info);
255 
256  if (ret != 0) {
257  log_err(ctx, "Address lookup failed.");
258  cleanup_handle(devh);
259  return JAYLINK_ERR;
260  }
261 
262  sock = -1;
263 
264  for (struct addrinfo *rp = info; rp != NULL; rp = rp->ai_next) {
265  sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
266 
267  if (sock < 0)
268  continue;
269 
270  if (!connect(sock, info->ai_addr, info->ai_addrlen))
271  break;
272 
273  socket_close(sock);
274  sock = -1;
275  }
276 
277  freeaddrinfo(info);
278 
279  if (sock < 0) {
280  log_err(ctx, "Failed to open device.");
281  cleanup_handle(devh);
282  return JAYLINK_ERR;
283  }
284 
285  log_dbg(ctx, "Device opened successfully.");
286 
287  devh->sock = sock;
288  ret = set_socket_timeouts(devh);
289 
290  if (ret != JAYLINK_OK) {
291  socket_close(sock);
292  cleanup_handle(devh);
293  return ret;
294  }
295 
296  ret = handle_server_hello(devh);
297 
298  if (ret != JAYLINK_OK) {
299  socket_close(sock);
300  cleanup_handle(devh);
301  return ret;
302  }
303 
304  return JAYLINK_OK;
305 }
306 
308 {
309  struct jaylink_context *ctx;
310 
311  ctx = devh->dev->ctx;
312 
313  log_dbg(ctx, "Closing device (IPv4 address = %s).",
314  devh->dev->ipv4_address);
315 
316  cleanup_handle(devh);
317 
318  log_dbg(ctx, "Device closed successfully.");
319 
320  return JAYLINK_OK;
321 }
322 
324  size_t length, bool has_command)
325 {
326  struct jaylink_context *ctx;
327 
328  if (!length)
329  return JAYLINK_ERR_ARG;
330 
331  ctx = devh->dev->ctx;
332 
333  log_dbgio(ctx, "Starting write operation (length = %zu bytes).",
334  length);
335 
336  if (devh->write_pos > 0)
337  log_warn(ctx, "Last write operation left %zu bytes in the "
338  "buffer.", devh->write_pos);
339 
340  if (devh->write_length > 0)
341  log_warn(ctx, "Last write operation was not performed.");
342 
343  devh->write_length = length;
344  devh->write_pos = 0;
345 
346  if (has_command) {
347  devh->buffer[0] = CMD_CLIENT;
348  devh->write_pos++;
349  }
350 
351  return JAYLINK_OK;
352 }
353 
355  size_t length)
356 {
357  struct jaylink_context *ctx;
358 
359  if (!length)
360  return JAYLINK_ERR_ARG;
361 
362  ctx = devh->dev->ctx;
363 
364  log_dbgio(ctx, "Starting read operation (length = %zu bytes).",
365  length);
366 
367  if (devh->bytes_available > 0)
368  log_dbg(ctx, "Last read operation left %zu bytes in the "
369  "buffer.", devh->bytes_available);
370 
371  if (devh->read_length > 0)
372  log_warn(ctx, "Last read operation left %zu bytes.",
373  devh->read_length);
374 
375  devh->read_length = length;
376 
377  return JAYLINK_OK;
378 }
379 
381  struct jaylink_device_handle *devh, size_t write_length,
382  size_t read_length, bool has_command)
383 {
384  struct jaylink_context *ctx;
385 
386  if (!read_length || !write_length)
387  return JAYLINK_ERR_ARG;
388 
389  ctx = devh->dev->ctx;
390 
391  log_dbgio(ctx, "Starting write / read operation (length = "
392  "%zu / %zu bytes).", write_length, read_length);
393 
394  if (devh->write_pos > 0)
395  log_warn(ctx, "Last write operation left %zu bytes in the "
396  "buffer.", devh->write_pos);
397 
398  if (devh->write_length > 0)
399  log_warn(ctx, "Last write operation was not performed.");
400 
401  if (devh->bytes_available > 0)
402  log_warn(ctx, "Last read operation left %zu bytes in the "
403  "buffer.", devh->bytes_available);
404 
405  if (devh->read_length > 0)
406  log_warn(ctx, "Last read operation left %zu bytes.",
407  devh->read_length);
408 
409  devh->write_length = write_length;
410  devh->write_pos = 0;
411 
412  if (has_command) {
413  devh->buffer[0] = CMD_CLIENT;
414  devh->write_pos++;
415  }
416 
417  devh->read_length = read_length;
418  devh->bytes_available = 0;
419  devh->read_pos = 0;
420 
421  return JAYLINK_OK;
422 }
423 
424 static int _send(struct jaylink_device_handle *devh, const uint8_t *buffer,
425  size_t length)
426 {
427  struct jaylink_context *ctx;
428  size_t tmp;
429 
430  ctx = devh->dev->ctx;
431 
432  while (length > 0) {
433  tmp = length;
434 
435  if (!socket_send(devh->sock, buffer, &tmp, 0)) {
436  log_err(ctx, "Failed to send data to device.");
437  return JAYLINK_ERR_IO;
438  }
439 
440  buffer += tmp;
441  length -= tmp;
442 
443  log_dbgio(ctx, "Sent %zu bytes to device.", tmp);
444  }
445 
446  return JAYLINK_OK;
447 }
448 
449 static bool adjust_buffer(struct jaylink_device_handle *devh, size_t size)
450 {
451  struct jaylink_context *ctx;
452  uint8_t *buffer;
453  size_t num;
454 
455  ctx = devh->dev->ctx;
456 
457  /* Adjust buffer size to a multiple of BUFFER_SIZE bytes. */
458  num = size / BUFFER_SIZE;
459 
460  if (size % BUFFER_SIZE > 0)
461  num++;
462 
463  size = num * BUFFER_SIZE;
464  buffer = realloc(devh->buffer, size);
465 
466  if (!buffer) {
467  log_err(ctx, "Failed to adjust buffer size to %zu bytes.",
468  size);
469  return false;
470  }
471 
472  devh->buffer = buffer;
473  devh->buffer_size = size;
474 
475  log_dbg(ctx, "Adjusted buffer size to %zu bytes.", size);
476 
477  return true;
478 }
479 
481  const uint8_t *buffer, size_t length)
482 {
483  int ret;
484  struct jaylink_context *ctx;
485  size_t tmp;
486 
487  ctx = devh->dev->ctx;
488 
489  if (length > devh->write_length) {
490  log_err(ctx, "Requested to write %zu bytes but only %zu bytes "
491  "are expected for the write operation.", length,
492  devh->write_length);
493  return JAYLINK_ERR_ARG;
494  }
495 
496  /*
497  * Store data in the buffer if the expected number of bytes for the
498  * write operation is not reached.
499  */
500  if (length < devh->write_length) {
501  if (devh->write_pos + length > devh->buffer_size) {
502  if (!adjust_buffer(devh, devh->write_pos + length))
503  return JAYLINK_ERR_MALLOC;
504  }
505 
506  memcpy(devh->buffer + devh->write_pos, buffer, length);
507 
508  devh->write_length -= length;
509  devh->write_pos += length;
510 
511  log_dbgio(ctx, "Wrote %zu bytes into buffer.", length);
512  return JAYLINK_OK;
513  }
514 
515  /*
516  * Expected number of bytes for this write operation is reached and
517  * therefore the write operation will be performed.
518  */
519  devh->write_length = 0;
520 
521  /* Send data directly to the device if the buffer is empty. */
522  if (!devh->write_pos)
523  return _send(devh, buffer, length);
524 
525  tmp = MIN(length, devh->buffer_size - devh->write_pos);
526 
527  /*
528  * Fill up the internal buffer in order to reduce the number of
529  * messages sent to the device for performance reasons.
530  */
531  memcpy(devh->buffer + devh->write_pos, buffer, tmp);
532 
533  length -= tmp;
534  buffer += tmp;
535 
536  log_dbgio(ctx, "Buffer filled up with %zu bytes.", tmp);
537 
538  ret = _send(devh, devh->buffer, devh->write_pos + tmp);
539 
540  devh->write_pos = 0;
541 
542  if (ret != JAYLINK_OK)
543  return ret;
544 
545  if (!length)
546  return JAYLINK_OK;
547 
548  return _send(devh, buffer, length);
549 }
550 
552  uint8_t *buffer, size_t length)
553 {
554  int ret;
555  struct jaylink_context *ctx;
556 
557  ctx = devh->dev->ctx;
558 
559  if (length > devh->read_length) {
560  log_err(ctx, "Requested to read %zu bytes but only %zu bytes "
561  "are expected for the read operation.", length,
562  devh->read_length);
563  return JAYLINK_ERR_ARG;
564  }
565 
566  if (length <= devh->bytes_available) {
567  memcpy(buffer, devh->buffer + devh->read_pos, length);
568 
569  devh->read_length -= length;
570  devh->bytes_available -= length;
571  devh->read_pos += length;
572 
573  log_dbgio(ctx, "Read %zu bytes from buffer.", length);
574  return JAYLINK_OK;
575  }
576 
577  if (devh->bytes_available) {
578  memcpy(buffer, devh->buffer + devh->read_pos,
579  devh->bytes_available);
580 
581  buffer += devh->bytes_available;
582  length -= devh->bytes_available;
583  devh->read_length -= devh->bytes_available;
584 
585  log_dbgio(ctx, "Read %zu bytes from buffer to flush it.",
586  devh->bytes_available);
587 
588  devh->bytes_available = 0;
589  devh->read_pos = 0;
590  }
591 
592  ret = _recv(devh, buffer, length);
593 
594  if (ret != JAYLINK_OK)
595  return ret;
596 
597  devh->read_length -= length;
598 
599  return JAYLINK_OK;
600 }
static int initialize_handle(struct jaylink_device_handle *devh)
Definition: transport_tcp.c:75
static void cleanup_handle(struct jaylink_device_handle *devh)
Definition: transport_tcp.c:99
const char * name
Definition: armv4_5.c:87
long tv_sec
Definition: replacements.h:56
Definition: psoc6.c:94
JAYLINK_PRIV int transport_tcp_close(struct jaylink_device_handle *devh)
static struct ublast_lowlevel_priv info
JAYLINK_PRIV int transport_tcp_write(struct jaylink_device_handle *devh, const uint8_t *buffer, size_t length)
long tv_usec
Definition: replacements.h:57
static int set_socket_timeouts(struct jaylink_device_handle *devh)
static bool adjust_buffer(struct jaylink_device_handle *devh, size_t size)
static int _recv(struct jaylink_device_handle *devh, uint8_t *buffer, size_t length)
JAYLINK_PRIV int transport_tcp_start_write(struct jaylink_device_handle *devh, size_t length, bool has_command)
JAYLINK_PRIV int transport_tcp_read(struct jaylink_device_handle *devh, uint8_t *buffer, size_t length)
#define MIN(a, b)
Definition: replacements.h:32
JAYLINK_PRIV int transport_tcp_start_write_read(struct jaylink_device_handle *devh, size_t write_length, size_t read_length, bool has_command)
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:37
#define BUFFER_SIZE
Definition: presto.c:48
static int handle_server_hello(struct jaylink_device_handle *devh)
static int _send(struct jaylink_device_handle *devh, const uint8_t *buffer, size_t length)
#define NULL
Definition: usb.h:27
JAYLINK_PRIV int transport_tcp_open(struct jaylink_device_handle *devh)
JAYLINK_PRIV uint16_t buffer_get_u16(const uint8_t *buffer, size_t offset)
Read a 16-bit unsigned integer value from a buffer.
Definition: buffer.c:68
#define DWORD
Definition: x86_32_common.h:44
JAYLINK_PRIV int transport_tcp_start_read(struct jaylink_device_handle *devh, size_t length)