view xsocket.c @ 262:ebbe0f198322

Fix DDS client connection retry
author Daniele Nicolodi <daniele.nicolodi@obspm.fr>
date Tue, 16 Jun 2015 17:16:11 +0200
parents a03df7dc98f8
children 8d9a4c5eb7a4
line wrap: on
line source

#ifdef _CVI_
#include <winsock2.h>
#include <ansi_c.h>
#define strdup(s) StrDup(s)
#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>
#endif

#include "xsocket.h"

#define XRETRY(code)								\
	({												\
		int __r, __n = 0;							\
		while (__n++ < 2) {							\
			__r = (code);							\
			if (__r != -EAGAIN)						\
				break;								\
		}											\
		__r;										\
	})


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 __exchange(struct xsocket *s, const char *out, size_t outlen, char *in, size_t inlen)
{
	int r;

	r = xsend(s, out, outlen);
	if (r < 0)
		return r;
		
	r = xrecv(s, in, inlen);
	if (r < 0)
		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 = XRETRY(__exchange(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 = XRETRY(__exchange(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;
}