view xsocket.c @ 264:a40c8af8b028

Improve fake data generator used in testing
author Daniele Nicolodi <daniele.nicolodi@obspm.fr>
date Tue, 16 Jun 2015 17:38:30 +0200
parents 8d9a4c5eb7a4
children
line wrap: on
line source

#ifdef _CVI_
#include <winsock2.h>
#include <toolbox.h>
#include <lowlvlio.h>
#include <ansi_c.h>
#define strdup(s) StrDup(s)
#define ERRNO 1
#else
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <ctype.h>
#include <math.h>
#include <stdarg.h>
#define ERRNO errno
#endif

#include "xsocket.h"

struct xsocket * xsocket(const char *hostname, const int port)
{
	struct xsocket *s = malloc(sizeof(struct xsocket));
	if (! s)
		return NULL;
	
	s->hostname = strdup(hostname);
	s->port = port;
	s->fd = -1;

	return s;
}


int xconnect(struct xsocket *s)
{
	int r, sock;
	struct sockaddr_in addr;
	struct hostent* host;	

#ifdef _CVI_
	WSADATA wsdata;
	WSAStartup(MAKEWORD(2,2), &wsdata);	
#endif

	if (s->fd >= 0)
		return 0;

	host = gethostbyname(s->hostname);
	if (host == NULL)
		return -ERRNO;
	
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock < 0)
		return -ERRNO;
	
	addr.sin_family = host->h_addrtype;
	memcpy(&addr.sin_addr.s_addr, host->h_addr_list[0], host->h_length);
	addr.sin_port = htons(s->port);

	r = connect(sock, (struct sockaddr*)&addr, sizeof(addr));
	if (r < 0)
		return -ERRNO;
	
	s->fd = sock;
	return 0;
}


int xsend(struct xsocket *s, const char *data, size_t len)
{
	int r;

	r = xconnect(s);
	if (r < 0)
		return r;
	
	r = send(s->fd, data, len, 0);
	if (r < 0)
		return -ERRNO;

	return r;
}


int xrecv(struct xsocket *s, char *buffer, size_t len)
{
	int r;
	
	r = recv(s->fd, buffer, len, 0);
	if (r < 0)
		return -ERRNO;
	if (r == 0) {
		close(s->fd);
		s->fd = -1;
		return -EAGAIN;
	}

	return r;
}


static inline int __talk(struct xsocket *s, const char *out, size_t outlen, char *in, size_t inlen)
{
	int r = 0, n = 0;
	
	while (n++ < 2) {
		r = xsend(s, out, outlen);
		if (r < 0)
			return r;
		
		r = xrecv(s, in, inlen);
		if ((r < 0) && (r != -EAGAIN))
			return r;
	}
	
	return r;
}


int xask(struct xsocket *s, const char *cmd, size_t len, char *buffer, size_t bufferlen)
{
	int r;
	char *data;

	data = malloc(len + 2);
	memcpy(data, cmd, len);	
	data[len++] = '\r';
	data[len++] = '\n';

	r = __talk(s, data, len, buffer, bufferlen);
	if (r < 0)
		return r;

	if ((buffer[--r] != '\n') || (buffer[--r] != '\r'))
		return -EINVAL;
	buffer[r] = '\0';
		
	return 0;
}


int xcommand(struct xsocket *s, const char *frmt, ...)
{
	int r, len;
	char buffer[1024];
	va_list v;
	
	va_start(v, frmt);
	len = vsnprintf(buffer, sizeof(buffer) - 2, frmt, v);
	va_end(v);
	buffer[len++] = '\r';
	buffer[len++] = '\n';

	r = __talk(s, buffer, len, buffer, sizeof(buffer));
	if (r < 0)
		return r;

	if ((buffer[--r] != '\n') || (buffer[--r] != '\r'))
		return -EINVAL;
	buffer[r] = '\0';

	if (strcmp(buffer, "OK") != 0)
		return -EINVAL;
	
	return 0;
}