<commit_before>/*
 * libiio - Library for interfacing industrial I/O (IIO) devices
 *
 * Copyright (C) 2014 Analog Devices, Inc.
 * Author: <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * */

#include "debug.h"
#include "iio-private.h"

#include <errno.h>
#include <netdb.h>
#include <pthread.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

#define IIOD_PORT 30431

struct iio_context_pdata {
	int fd;
};

static pthread_mutex_t hostname_lock = PTHREAD_MUTEX_INITIALIZER;

static ssize_t write_all(const void *src, size_t len, int fd)
{
	const void *ptr = src;
	while (len) {
		ssize_t ret = send(fd, ptr, len, 0);
		if (ret < 0)
			return -errno;
		ptr += ret;
		len -= ret;
	}
	return ptr - src;
}

static ssize_t read_all(void *dst, size_t len, int fd)
{
	void *ptr = dst;
	while (len) {
		ssize_t ret = recv(fd, ptr, len, 0);
		if (ret < 0)
			return -errno;
		ptr += ret;
		len -= ret;
	}
	return ptr - dst;
}

static void network_shutdown(struct iio_context *ctx)
{
	struct iio_context_pdata *pdata = ctx->pdata;

	write_all("\r\nEXIT\r\n", sizeof("\r\nEXIT\r\n") - 1, pdata->fd);
	close(pdata->fd);
	free(pdata);
}

static struct iio_backend_ops network_ops = {
	.shutdown = network_shutdown,
};

static struct iio_context * get_context(int fd)
{
	struct iio_context *ctx;
	unsigned int i;
	unsigned long xml_len;
	char *xml, *ptr, buf[1024];

	DEBUG("Writing PRINT command\n");
	ssize_t ret = write_all("PRINT\r\n", sizeof("PRINT\r\n") - 1, fd);
	if (ret < 0) {
		char buf[1024];
		strerror_r(-ret, buf, sizeof(buf));
		ERROR("Unable to send PRINT command: %s\n", buf);
		return NULL;
	}

	DEBUG("Reading response...\n");
	for (i = 0; i < sizeof(buf) - 1; i++) {
		ssize_t ret = read_all(buf + i, 1, fd);
		if (ret < 0) {
			char buf[1024];
			strerror_r(-ret, buf, sizeof(buf));
			ERROR("Unable to read response to PRINT: %s\n", buf);
			return NULL;
		}

		if (buf[i] == '\n')
			break;
	}

	buf[i] = '\0';
	xml_len = strtoul(buf, &ptr, 10);
	if (ptr == buf) {
		ERROR("Unrecognized response from server\n");
		return NULL;
	}

	DEBUG("Server returned a XML string of length %lu\n", xml_len);

	xml = malloc(xml_len);
	if (!xml) {<commit_msg>Network backend: Added helper function read_integer<commit_after>/*
 * libiio - Library for interfacing industrial I/O (IIO) devices
 *
 * Copyright (C) 2014 Analog Devices, Inc.
 * Author: <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * */

#include "debug.h"
#include "iio-private.h"

#include <errno.h>
#include <netdb.h>
#include <pthread.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

#define IIOD_PORT 30431

struct iio_context_pdata {
	int fd;
};

static pthread_mutex_t hostname_lock = PTHREAD_MUTEX_INITIALIZER;

static ssize_t write_all(const void *src, size_t len, int fd)
{
	const void *ptr = src;
	while (len) {
		ssize_t ret = send(fd, ptr, len, 0);
		if (ret < 0)
			return -errno;
		ptr += ret;
		len -= ret;
	}
	return ptr - src;
}

static ssize_t read_all(void *dst, size_t len, int fd)
{
	void *ptr = dst;
	while (len) {
		ssize_t ret = recv(fd, ptr, len, 0);
		if (ret < 0)
			return -errno;
		ptr += ret;
		len -= ret;
	}
	return ptr - dst;
}

static int read_integer(int fd, long *val)
{
	unsigned int i;
	char buf[1024], *ptr;
	ssize_t ret;
	bool found = false;

	for (i = 0; i < sizeof(buf) - 1; i++) {
		ret = read_all(buf + i, 1, fd);
		if (ret < 0)
			return (int) ret;

		/* Skip the eventual first few carriage returns */
		if (buf[i] != '\n')
			found = true;
		else if (found)
			break;
	}

	buf[i] = '\0';
	ret = (ssize_t) strtol(buf, &ptr, 10);
	if (ptr == buf)
		return -EINVAL;
	*val = (long) ret;
	return 0;
}

static void network_shutdown(struct iio_context *ctx)
{
	struct iio_context_pdata *pdata = ctx->pdata;

	write_all("\r\nEXIT\r\n", sizeof("\r\nEXIT\r\n") - 1, pdata->fd);
	close(pdata->fd);
	free(pdata);
}

static struct iio_backend_ops network_ops = {
	.shutdown = network_shutdown,
};

static struct iio_context * get_context(int fd)
{
	struct iio_context *ctx;
	long xml_len;
	char *xml;
	ssize_t ret;

	DEBUG("Writing PRINT command\n");
	ret = write_all("PRINT\r\n", sizeof("PRINT\r\n") - 1, fd);
	if (ret < 0) {
		char buf[1024];
		strerror_r(-ret, buf, sizeof(buf));
		ERROR("Unable to send PRINT command: %s\n", buf);
		return NULL;
	}

	DEBUG("Reading response...\n");
	ret = read_integer(fd, &xml_len);
	if (ret < 0) {
		char buf[1024];
		strerror_r(-ret, buf, sizeof(buf));
		ERROR("Unable to read response to PRINT: %s\n", buf);
		return NULL;
	}

	if (xml_len < 0) {
		char buf[1024];
		strerror_r(-xml_len, buf, sizeof(buf));
		ERROR("Server returned an error: %s\n", buf);
		return NULL;
	}

	DEBUG("Server returned a XML string of length %li\n", xml_len);

	xml = malloc(xml_len);
	if (!xml) {
{'fraction_non_alphanumeric': 0.1426110919738202, 'fraction_numerical': 0.013951085084395453, 'mean_word_length': 3.6381789137380194, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 16}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1481073', 'n_tokens_mistral': 2327, 'n_tokens_neox': 2173, 'n_words': 701}