/********************************/
/*  sem_interface.c by IoDream  */
/* sem_server client functions  */
/*   Not released yet           */
/*       PUBLIC DOMAIN          */
/********************************/

/* IoDream (IoDream@ifrance.com) */

/* C++ compilers friendly */
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include "j_net.h"
#include "sem_config.h"
#include "sem_debug.h"
#include "sem_interface.h"

const char mess_item_ok[] = "OK";
const char mess_item_error[] = "ERROR";

/* Fill the p_request string with request (req, id).
   Return 0 if OK, or -1 in case of failure.
   Note: don't forget to allocate enough space to the string. */
int sem_request_create(int req, int id, char *p_request)
{
	if ((req < 0) || (SEM_REQ_LAST < req))
	{
		fprintf(stderr, "sem_interface-:  sem_create_request bad request number: %d\n", req);
		return(-1);
	}
	if (p_request == NULL)
	{
		fprintf(stderr, "sem_interface-:  sem_create_request p_request is NULL\n");
		return(-1);
	}
	if (req < SEM_REQ_RESET)
		(void) sprintf(p_request, "%s %d\n" , sem_req_txt[req], id);
	else
		(void) sprintf(p_request, "%s\n" , sem_req_txt[req]);
	return(0);
}

/* Send the request (req, id) to the sem_server @server:port_number.
   Return TRUE if OK, FALSE if an error occured (check *p_error), or -1 in case of system failure.
   Note: the p_error string is dynamically allocated, so don't forget to free it after use. */
int sem_request_send(char *server, short port_number, int req, int id, char **p_error)
{
	char request[SEM_MAXLEN_MESSAGE];

	if ((req < 0) || (SEM_REQ_LAST < req))
	{
		fprintf(stderr, "sem_interface-:  sem_request_send bad request number: %d\n", req);
		return(-1);
	}
	memset(request, 0, sizeof(request));
	if (sem_request_create(req, id, request) < 0)
		return(-1);
	return(sem_request_send_string(server, port_number, request, p_error));
}

/* Send the request string to the sem_server @server:port_number.
   Return TRUE if OK, FALSE if an error occured (check *p_error),
    -1 in case of system failure, or -2 if it could not connect.
   Note: the p_error string is dynamically allocated, so don't forget to free it after use. */
int sem_request_send_string(char *server, short port_number, char *string, char **p_error)
{
	char message[SEM_MAXLEN_MESSAGE];
	int	len_item, res;
	short local_sock;
	char *item = message;
	char *p_aux;

	if (server == NULL)
	{
		fprintf(stderr, "sem_interface-:  sem_request_send server argument is NULL\n");
		return(-1);
	}
	if (p_error == NULL)
	{
		fprintf(stderr, "sem_interface-:  sem_request_send p_error argument is NULL\n");
		return(-1);
	}
	*p_error = NULL;

	if ((local_sock = j_net_connect(server, port_number)) < 0)
	{
		fprintf(stderr, "sem_interface-:  sem_request_send cannot connect to server\n");
		return(-2);
	}
	DEBUG_(printf("sem_interface-:  sem_request_send connected to sem_server\n");)

	DEBUG_(printf("sem_interface-:  envoi du message: %s", string);)
	if (j_net_write_all(local_sock, string, strlen(string)) < 0)
	{
		perror("sem_interface-:  sem_request_send_ j_net_write_all()");
		j_net_shutdown_socket(local_sock, SHUT_RDWR);
		j_net_close_socket(local_sock);
		return(-1);
	}

	if (parse_request(string, &res, NULL) == SEM_REQ_RESET)
		res = TRUE;
	else
	{
		memset(message, 0, sizeof(message));
		if ((len_item = j_net_read_max(local_sock, message, sizeof(message))) < 0)
		{
			perror("sem_interface-:  sem_request_send j_net_read_max()");
			j_net_shutdown_socket(local_sock, SHUT_RDWR);
			j_net_close_socket(local_sock);
			return(-1);
		}
		if (len_item == 0)
		{
			j_net_shutdown_socket(local_sock, SHUT_RDWR);
			j_net_close_socket(local_sock);
			return(-1);
		}
		if ((len_item = next_item(&item, &p_aux, ' ')) == 0)
		{
			j_net_shutdown_socket(local_sock, SHUT_RDWR);
			j_net_close_socket(local_sock);
			return(-1);
		}
		if (strncmp(item, mess_item_ok, strlen(mess_item_ok)) == 0)
			res = TRUE;
		else if (strncmp(item, mess_item_error, strlen(mess_item_error)) == 0)
		{
			res = FALSE;
			if (p_error != NULL)
			{
				*p_error = malloc(SEM_MAXLEN_MESSAGE);
				(void) strcpy(*p_error, p_aux);
			}
		}
		else
			res = -1;
	}

	j_net_shutdown_socket(local_sock, SHUT_RDWR);
	j_net_close_socket(local_sock);

	return(res);
}

/* C++ compilers friendly */
#ifdef __cplusplus
}
#endif /*__cplusplus*/
