23 #include <sys/types.h> 30 #include <sys/types.h> 31 #include <sys/socket.h> 33 #include <netinet/in.h> 46 #define CMD_SERVER 0x00 47 #define CMD_CLIENT 0x07 53 #define RESP_MAX_CONNECTIONS 0xfe 56 #define BUFFER_SIZE 2048 59 #define RECV_TIMEOUT 5000 61 #define SEND_TIMEOUT 5000 64 #define PORT_STRING "19020" 67 #define SERVER_HELLO_SIZE 4 72 #define SERVER_NAME_MAX_LENGTH 256 85 log_err(ctx,
"Transport buffer malloc failed.");
116 log_err(ctx,
"Failed to receive data from device.");
119 log_err(ctx,
"Failed to receive data from device: " 120 "remote connection closed.");
127 log_dbgio(ctx,
"Received %zu bytes from device.", tmp);
137 uint8_t buf[SERVER_HELLO_SIZE];
138 char name[SERVER_NAME_MAX_LENGTH];
139 uint16_t proto_version;
144 ret =
_recv(devh, buf,
sizeof(buf));
147 log_err(ctx,
"Failed to receive hello message.");
151 if (buf[0] == RESP_MAX_CONNECTIONS) {
152 log_err(ctx,
"Maximum number of connections reached.");
156 if (buf[0] != CMD_SERVER) {
157 log_err(ctx,
"Invalid hello message received.");
163 log_dbg(ctx,
"Protocol version: 0x%04x.", proto_version);
166 ret =
_recv(devh, (uint8_t *)name, length);
169 log_err(ctx,
"Failed to receive server name.");
175 log_dbg(ctx,
"Server name: %s.", name);
188 timeout = RECV_TIMEOUT;
192 log_err(ctx,
"Failed to set socket receive timeout.");
196 timeout = SEND_TIMEOUT;
200 log_err(ctx,
"Failed to set socket send timeout.");
206 timeout.
tv_sec = RECV_TIMEOUT / 1000;
207 timeout.
tv_usec = (RECV_TIMEOUT % 1000) * 1000;
211 log_err(ctx,
"Failed to set socket receive timeout.");
215 timeout.
tv_sec = SEND_TIMEOUT / 1000;
216 timeout.
tv_usec = (SEND_TIMEOUT % 1000) * 1000;
220 log_err(ctx,
"Failed to set socket send timeout.");
232 struct addrinfo hints;
233 struct addrinfo *
info;
239 log_dbg(ctx,
"Trying to open device (IPv4 address = %s).",
245 log_err(ctx,
"Initialize device handle failed.");
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;
254 ret = getaddrinfo(dev->
ipv4_address, PORT_STRING, &hints, &info);
257 log_err(ctx,
"Address lookup failed.");
264 for (
struct addrinfo *rp = info; rp !=
NULL; rp = rp->ai_next) {
265 sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
270 if (!connect(sock, info->ai_addr, info->ai_addrlen))
280 log_err(ctx,
"Failed to open device.");
285 log_dbg(ctx,
"Device opened successfully.");
313 log_dbg(ctx,
"Closing device (IPv4 address = %s).",
318 log_dbg(ctx,
"Device closed successfully.");
324 size_t length,
bool has_command)
333 log_dbgio(ctx,
"Starting write operation (length = %zu bytes).",
337 log_warn(ctx,
"Last write operation left %zu bytes in the " 341 log_warn(ctx,
"Last write operation was not performed.");
347 devh->
buffer[0] = CMD_CLIENT;
364 log_dbgio(ctx,
"Starting read operation (length = %zu bytes).",
368 log_dbg(ctx,
"Last read operation left %zu bytes in the " 372 log_warn(ctx,
"Last read operation left %zu bytes.",
382 size_t read_length,
bool has_command)
386 if (!read_length || !write_length)
391 log_dbgio(ctx,
"Starting write / read operation (length = " 392 "%zu / %zu bytes).", write_length, read_length);
395 log_warn(ctx,
"Last write operation left %zu bytes in the " 399 log_warn(ctx,
"Last write operation was not performed.");
402 log_warn(ctx,
"Last read operation left %zu bytes in the " 406 log_warn(ctx,
"Last read operation left %zu bytes.",
413 devh->
buffer[0] = CMD_CLIENT;
436 log_err(ctx,
"Failed to send data to device.");
443 log_dbgio(ctx,
"Sent %zu bytes to device.", tmp);
464 buffer = realloc(devh->
buffer, size);
467 log_err(ctx,
"Failed to adjust buffer size to %zu bytes.",
475 log_dbg(ctx,
"Adjusted buffer size to %zu bytes.", size);
490 log_err(ctx,
"Requested to write %zu bytes but only %zu bytes " 491 "are expected for the write operation.", length,
500 if (length < devh->write_length) {
511 log_dbgio(ctx,
"Wrote %zu bytes into buffer.", length);
523 return _send(devh, buffer, length);
536 log_dbgio(ctx,
"Buffer filled up with %zu bytes.", tmp);
548 return _send(devh, buffer, length);
560 log_err(ctx,
"Requested to read %zu bytes but only %zu bytes " 561 "are expected for the read operation.", length,
566 if (length <= devh->bytes_available) {
573 log_dbgio(ctx,
"Read %zu bytes from buffer.", length);
585 log_dbgio(ctx,
"Read %zu bytes from buffer to flush it.",
592 ret =
_recv(devh, buffer, length);
static int initialize_handle(struct jaylink_device_handle *devh)
uint8_t * buffer
Buffer for write and read operations.
char ipv4_address[INET_ADDRSTRLEN]
IPv4 address.
static void cleanup_handle(struct jaylink_device_handle *devh)
size_t buffer_size
Buffer size.
JAYLINK_PRIV void log_err(const struct jaylink_context *ctx, const char *format,...)
size_t bytes_available
Number of bytes available in the buffer to be read.
JAYLINK_PRIV int transport_tcp_close(struct jaylink_device_handle *devh)
Opaque structure representing a device.
static struct ublast_lowlevel_priv info
JAYLINK_PRIV void log_dbgio(const struct jaylink_context *ctx, const char *format,...)
JAYLINK_PRIV int transport_tcp_write(struct jaylink_device_handle *devh, const uint8_t *buffer, size_t length)
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)
Opaque structure representing a libjaylink context.
JAYLINK_PRIV int transport_tcp_start_write(struct jaylink_device_handle *devh, size_t length, bool has_command)
#define JAYLINK_PRIV
Macro to mark private libjaylink symbol.
Internal libjaylink header file.
size_t read_length
Number of bytes left for the read operation.
JAYLINK_PRIV void log_dbg(const struct jaylink_context *ctx, const char *format,...)
JAYLINK_PRIV int transport_tcp_read(struct jaylink_device_handle *devh, uint8_t *buffer, size_t length)
struct jaylink_context * ctx
libjaylink context.
size_t write_pos
Current write position in the buffer.
JAYLINK_PRIV bool socket_recv(int sock, void *buffer, size_t *length, int flags)
Receive a message from a socket.
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.
JAYLINK_PRIV bool socket_send(int sock, const void *buffer, size_t *length, int flags)
Send a message on a socket.
Opaque structure representing a handle of a device.
int sock
Socket descriptor.
static int handle_server_hello(struct jaylink_device_handle *devh)
JAYLINK_PRIV void log_warn(const struct jaylink_context *ctx, const char *format,...)
Public libjaylink header file to be used by applications.
static struct jaylink_device_handle * devh
static int _send(struct jaylink_device_handle *devh, const uint8_t *buffer, size_t length)
size_t read_pos
Current read position in the buffer.
struct jaylink_device * dev
Device instance.
size_t write_length
Number of bytes left to be written before the write operation will be performed.
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.
JAYLINK_PRIV bool socket_close(int sock)
Close a socket.
JAYLINK_PRIV bool socket_set_option(int sock, int level, int option, const void *value, size_t length)
Set an option on a socket.
JAYLINK_PRIV int transport_tcp_start_read(struct jaylink_device_handle *devh, size_t length)