Blame ld10k1/src/comm.c

Packit 427e91
/*
Packit 427e91
 *  EMU10k1 loader lib
Packit 427e91
 *  Copyright (c) 2003,2004 by Peter Zubaj
Packit 427e91
 *
Packit 427e91
 *
Packit 427e91
 *   This library is free software; you can redistribute it and/or modify
Packit 427e91
 *   it under the terms of the GNU Lesser General Public License as
Packit 427e91
 *   published by the Free Software Foundation; either version 2.1 of
Packit 427e91
 *   the License, or (at your option) any later version.
Packit 427e91
 *
Packit 427e91
 *   This program is distributed in the hope that it will be useful,
Packit 427e91
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 427e91
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 427e91
 *   GNU Lesser General Public License for more details.
Packit 427e91
 *
Packit 427e91
 *   You should have received a copy of the GNU Lesser General Public
Packit 427e91
 *   License along with this library; if not, write to the Free Software
Packit 427e91
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit 427e91
 *
Packit 427e91
 */
Packit 427e91
 
Packit 427e91
#include <stddef.h>
Packit 427e91
#include <stdio.h>
Packit 427e91
#include <errno.h>
Packit 427e91
#include <stdlib.h>
Packit 427e91
#include <string.h>
Packit 427e91
#include <unistd.h>
Packit 427e91
#include <sys/socket.h>
Packit 427e91
#include <sys/un.h>
Packit 427e91
#include <sys/stat.h>
Packit 427e91
#include <netinet/in.h>
Packit 427e91
#include <netdb.h>
Packit 427e91
Packit 427e91
#include "comm.h"
Packit 427e91
#include "ld10k1_error.h"
Packit 427e91
Packit 427e91
/* taken from glibc example */
Packit 427e91
int setup_comm(comm_param *param)
Packit 427e91
{
Packit 427e91
	int sock;
Packit 427e91
	struct sockaddr_un lname;
Packit 427e91
	struct sockaddr_in iname;
Packit 427e91
	size_t size;
Packit 427e91
Packit 427e91
	/* Create the socket. */
Packit 427e91
	if (param->type == COMM_TYPE_LOCAL)
Packit 427e91
		sock = socket (PF_LOCAL, SOCK_STREAM, 0);
Packit 427e91
	else
Packit 427e91
		sock = socket (PF_INET, SOCK_STREAM, 0);
Packit 427e91
	if (sock < 0)
Packit 427e91
		return -1;
Packit 427e91
Packit 427e91
	if (param->server)	{
Packit 427e91
		if (param->type == COMM_TYPE_LOCAL) {
Packit 427e91
			unlink(param->name);
Packit 427e91
Packit 427e91
			/* Bind a name to the socket. */
Packit 427e91
			memset(&lname, 0, sizeof(struct sockaddr_un));
Packit 427e91
			lname.sun_family = AF_LOCAL;
Packit 427e91
			strncpy (lname.sun_path, param->name, sizeof (lname.sun_path) - 1);
Packit 427e91
			lname.sun_path[sizeof (lname.sun_path) - 1] = '\0';
Packit 427e91
Packit 427e91
			/* The size of the address is
Packit 427e91
			the offset of the start of the filename,
Packit 427e91
			plus its length,
Packit 427e91
			plus one for the terminating null byte.
Packit 427e91
			Alternatively you can just do:
Packit 427e91
			size = SUN_LEN (&name);
Packit 427e91
			*/
Packit 427e91
			size = (offsetof (struct sockaddr_un, sun_path)	+ strlen (lname.sun_path) + 1);
Packit 427e91
Packit 427e91
			if (bind (sock, (struct sockaddr *) &lname, size) < 0)
Packit 427e91
				return -1;
Packit 427e91
Packit 427e91
			chmod(param->name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
Packit 427e91
		} else {
Packit 427e91
			/* Give the socket a name. */
Packit 427e91
			memset(&iname, 0, sizeof(struct sockaddr_in));
Packit 427e91
			iname.sin_family = AF_INET;
Packit 427e91
			iname.sin_port = htons (param->port);
Packit 427e91
			iname.sin_addr.s_addr = htonl(INADDR_ANY);
Packit 427e91
			if (bind(sock, (struct sockaddr *) &iname, sizeof (iname)) < 0)
Packit 427e91
				return -1;
Packit 427e91
		}
Packit 427e91
	}
Packit 427e91
Packit 427e91
	return sock;
Packit 427e91
}
Packit 427e91
Packit 427e91
int connect_comm(int conn_num, comm_param *param)
Packit 427e91
{
Packit 427e91
	struct sockaddr_un lname;
Packit 427e91
	struct sockaddr_in iname;
Packit 427e91
	struct hostent *hostinfo;
Packit 427e91
	size_t size;
Packit 427e91
	
Packit 427e91
	int attempt;
Packit 427e91
	int max_attempt;
Packit 427e91
	int not_connected;
Packit 427e91
	
Packit 427e91
	attempt = 0;
Packit 427e91
	if (param->wfc)
Packit 427e91
		max_attempt = param->wfc / 10;
Packit 427e91
	else
Packit 427e91
		max_attempt = 0;
Packit 427e91
Packit 427e91
	if (param->type == COMM_TYPE_LOCAL) {
Packit 427e91
		memset(&lname, 0, sizeof(struct sockaddr_un));
Packit 427e91
		lname.sun_family = AF_LOCAL;
Packit 427e91
		strncpy (lname.sun_path, param->name, sizeof (lname.sun_path) - 1);
Packit 427e91
		lname.sun_path[sizeof(lname.sun_path) - 1] = '\0';
Packit 427e91
Packit 427e91
		size = (offsetof(struct sockaddr_un, sun_path)) + strlen(lname.sun_path) + 1;
Packit 427e91
Packit 427e91
		while (1)
Packit 427e91
		{
Packit 427e91
			not_connected = connect(conn_num, (struct sockaddr *) &lname, size);
Packit 427e91
			if (!not_connected)
Packit 427e91
				break;
Packit 427e91
			if (attempt >= max_attempt)
Packit 427e91
				return -1;
Packit 427e91
			attempt++;
Packit 427e91
			usleep(10000);
Packit 427e91
		}
Packit 427e91
	} else {
Packit 427e91
		memset(&iname, 0, sizeof(struct sockaddr_in));
Packit 427e91
		iname.sin_family = AF_INET;
Packit 427e91
		iname.sin_port = htons(param->port);
Packit 427e91
		hostinfo = gethostbyname(param->name);
Packit 427e91
		if (hostinfo == NULL)
Packit 427e91
			return -1;
Packit 427e91
		iname.sin_addr = *(struct in_addr *)hostinfo->h_addr;
Packit 427e91
		
Packit 427e91
		while (1)
Packit 427e91
		{
Packit 427e91
			not_connected = connect(conn_num, (struct sockaddr *) &iname, sizeof(struct sockaddr_in));
Packit 427e91
			if (!not_connected)
Packit 427e91
				break;
Packit 427e91
			if (attempt >= max_attempt)
Packit 427e91
				return -1;
Packit 427e91
			attempt++;
Packit 427e91
			usleep(10000);
Packit 427e91
		}
Packit 427e91
	}
Packit 427e91
	return 0;
Packit 427e91
}
Packit 427e91
Packit 427e91
int listen_comm(int conn_num)
Packit 427e91
{
Packit 427e91
	if (listen(conn_num, 1) < 0)
Packit 427e91
		return -1;
Packit 427e91
	return 0;
Packit 427e91
}
Packit 427e91
Packit 427e91
int accept_comm(int conn_num)
Packit 427e91
{
Packit 427e91
	struct sockaddr addr;
Packit 427e91
	socklen_t addr_len;
Packit 427e91
	int sock;
Packit 427e91
Packit 427e91
	addr_len = sizeof(addr);
Packit 427e91
	
Packit 427e91
	sock = accept(conn_num, &addr, &addr_len);
Packit 427e91
	
Packit 427e91
	if (sock < 0)
Packit 427e91
		return -1;
Packit 427e91
Packit 427e91
	return sock;
Packit 427e91
}
Packit 427e91
Packit 427e91
int free_comm(int conn_num)
Packit 427e91
{	
Packit 427e91
	if (shutdown(conn_num, 2))
Packit 427e91
		return -1;
Packit 427e91
	if (close(conn_num) < 0)
Packit 427e91
		return -1;
Packit 427e91
Packit 427e91
	return 0;
Packit 427e91
}
Packit 427e91
Packit 427e91
#define MAX_ATEMPT 5
Packit 427e91
Packit 427e91
int read_all(int conn_num, void *data, int data_size)
Packit 427e91
{
Packit 427e91
	int offset = 0;
Packit 427e91
	int how_much = data_size;
Packit 427e91
	int atempt = 0;
Packit 427e91
	int readed = 0;
Packit 427e91
	
Packit 427e91
	while (atempt < MAX_ATEMPT && how_much > 0)	{
Packit 427e91
		readed = read(conn_num, ((char *)data) + offset, how_much);
Packit 427e91
		if (readed < 0)
Packit 427e91
			return LD10K1_ERR_COMM_READ;
Packit 427e91
		offset += readed;
Packit 427e91
		how_much -= readed;
Packit 427e91
		atempt++;
Packit 427e91
		if (how_much > 0)
Packit 427e91
			usleep(10000);
Packit 427e91
	}
Packit 427e91
	
Packit 427e91
	if (how_much > 0)
Packit 427e91
		return LD10K1_ERR_COMM_READ;
Packit 427e91
	else
Packit 427e91
		return data_size;
Packit 427e91
}
Packit 427e91
Packit 427e91
int write_all(int conn_num, void *data, int data_size)
Packit 427e91
{
Packit 427e91
	int offset = 0;
Packit 427e91
	int how_much = data_size;
Packit 427e91
	int atempt = 0;
Packit 427e91
	int writed = 0;
Packit 427e91
	
Packit 427e91
	while (atempt < MAX_ATEMPT && how_much > 0)	{
Packit 427e91
		writed = write(conn_num, ((char *)data) + offset, how_much);
Packit 427e91
		if (writed < 0)
Packit 427e91
			return LD10K1_ERR_COMM_WRITE;
Packit 427e91
		offset += writed;
Packit 427e91
		how_much -= writed;
Packit 427e91
		atempt++;
Packit 427e91
		if (how_much > 0)
Packit 427e91
			usleep(50000);
Packit 427e91
	}
Packit 427e91
	
Packit 427e91
	if (how_much > 0)
Packit 427e91
		return LD10K1_ERR_COMM_WRITE;
Packit 427e91
	else
Packit 427e91
		return data_size;
Packit 427e91
}
Packit 427e91
Packit 427e91
int send_request(int conn_num, int op, void *data, int data_size)
Packit 427e91
{
Packit 427e91
	int nbytes;
Packit 427e91
	struct msg_req header;
Packit 427e91
Packit 427e91
	header.op = op;
Packit 427e91
	header.size = data_size;
Packit 427e91
Packit 427e91
	/* header */
Packit 427e91
	nbytes = write_all(conn_num, &header, sizeof(header));
Packit 427e91
	if (nbytes < 0)
Packit 427e91
		return nbytes;
Packit 427e91
Packit 427e91
	if (data_size > 0) {
Packit 427e91
		/* data */
Packit 427e91
		nbytes = write_all(conn_num, data, data_size);
Packit 427e91
		if (nbytes < 0)
Packit 427e91
			return nbytes;
Packit 427e91
	}
Packit 427e91
	return 0;
Packit 427e91
}
Packit 427e91
Packit 427e91
int send_response(int conn_num, int op, int err, void *data, int data_size)
Packit 427e91
{
Packit 427e91
	int nbytes;
Packit 427e91
	struct msg_resp header;
Packit 427e91
Packit 427e91
	header.op = op;
Packit 427e91
	header.err = err;
Packit 427e91
	header.size = data_size;
Packit 427e91
Packit 427e91
	/* header */
Packit 427e91
	nbytes = write_all(conn_num, &header, sizeof(header));
Packit 427e91
	if (nbytes < 0)
Packit 427e91
		return nbytes;
Packit 427e91
Packit 427e91
	if (data_size > 0) {
Packit 427e91
		/* data */
Packit 427e91
		nbytes = write_all(conn_num, data, data_size);
Packit 427e91
		if (nbytes < 0)
Packit 427e91
			return nbytes;
Packit 427e91
	}
Packit 427e91
	return 0;
Packit 427e91
}
Packit 427e91
Packit 427e91
int send_msg_data(int conn_num, void *data, int data_size)
Packit 427e91
{
Packit 427e91
	int nbytes;
Packit 427e91
Packit 427e91
	if (data_size > 0) {
Packit 427e91
		/* data */
Packit 427e91
		nbytes = write_all(conn_num, data, data_size);
Packit 427e91
		if (nbytes < 0)
Packit 427e91
			return nbytes;
Packit 427e91
	}
Packit 427e91
	return 0;
Packit 427e91
}
Packit 427e91
Packit 427e91
int receive_request(int conn_num, int *op, int *data_size)
Packit 427e91
{
Packit 427e91
	struct msg_req header;
Packit 427e91
	int nbytes;
Packit 427e91
	
Packit 427e91
	nbytes = read_all(conn_num, &header, sizeof(header));
Packit 427e91
	if (nbytes < 0)
Packit 427e91
		return nbytes;
Packit 427e91
	if (nbytes == 0) {
Packit 427e91
		*op = -1;
Packit 427e91
		*data_size = 0;
Packit 427e91
		return 0;
Packit 427e91
	}
Packit 427e91
	*op = header.op;
Packit 427e91
	*data_size = header.size;
Packit 427e91
	return 0;
Packit 427e91
}
Packit 427e91
Packit 427e91
int receive_response(int conn_num, int *op, int *data_size)
Packit 427e91
{
Packit 427e91
	struct msg_resp header;
Packit 427e91
	int nbytes;
Packit 427e91
	
Packit 427e91
	nbytes = read_all(conn_num, &header, sizeof(header));
Packit 427e91
	if (nbytes < 0)
Packit 427e91
		return nbytes;
Packit 427e91
	if (nbytes == 0) {
Packit 427e91
		*op = -1;
Packit 427e91
		*data_size = 0;
Packit 427e91
		return 0;
Packit 427e91
	}
Packit 427e91
	*op = header.op;
Packit 427e91
	*data_size = header.size;
Packit 427e91
	if (header.err < 0)
Packit 427e91
		return header.err;
Packit 427e91
	return 0;
Packit 427e91
}
Packit 427e91
Packit 427e91
int receive_msg_data(int conn_num, void *data, int data_size)
Packit 427e91
{
Packit 427e91
	int nbytes;
Packit 427e91
	nbytes = read_all(conn_num, data, data_size);
Packit 427e91
	if (nbytes < 0)
Packit 427e91
		return nbytes;
Packit 427e91
	return 0;
Packit 427e91
}
Packit 427e91
Packit 427e91
void *receive_msg_data_malloc(int conn_num, int data_size)
Packit 427e91
{
Packit 427e91
	void *tmp;
Packit 427e91
	
Packit 427e91
	tmp = malloc(data_size);
Packit 427e91
	if (!tmp)
Packit 427e91
		return NULL;
Packit 427e91
		
Packit 427e91
	if (receive_msg_data(conn_num, tmp, data_size)) {
Packit 427e91
		free(tmp);
Packit 427e91
		return NULL;	
Packit 427e91
	}
Packit 427e91
	return tmp;
Packit 427e91
}