dslinux/user/pixil/sys/ipc/client Makefile client.c

amadeus dslinux_amadeus at user.in-berlin.de
Tue Oct 3 13:27:09 CEST 2006


Update of /cvsroot/dslinux/dslinux/user/pixil/sys/ipc/client
In directory antilope:/tmp/cvs-serv11916/sys/ipc/client

Added Files:
	Makefile client.c 
Log Message:
adding pristine copy of pixil to HEAD so I can branch from it

--- NEW FILE: client.c ---
/*                                                                       
 * Copyright (c) 2003 Century Software, Inc.   All Rights Reserved.     
 *                                                                       
 * This file is part of the PIXIL Operating Environment                 
 *                                                                       
 * The use, copying and distribution of this file is governed by one    
 * of two licenses, the PIXIL Commercial License, or the GNU General    
 * Public License, version 2.                                           
 *                                                                       
 * Licensees holding a valid PIXIL Commercial License may use this file 
 * in accordance with the PIXIL Commercial License Agreement provided   
 * with the Software. Others are governed under the terms of the GNU   
 * General Public License version 2.                                    
 *                                                                       
 * This file may be distributed and/or modified under the terms of the  
 * GNU General Public License version 2 as published by the Free        
 * Software Foundation and appearing in the file LICENSE.GPL included   
 * in the packaging of this file.                                      
 *                                                                       
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING  
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A            
 * PARTICULAR PURPOSE.                                                  
 *                                                                       
 * RESTRICTED RIGHTS LEGEND                                             
 *                                                                     
 * Use, duplication, or disclosure by the government is subject to      
 * restriction as set forth in paragraph (b)(3)(b) of the Rights in     
 * Technical Data and Computer Software clause in DAR 7-104.9(a).       
 *                                                                      
 * See http://www.pixil.org/gpl/ for GPL licensing       
 * information.                                                         
 *                                                                      
 * See http://www.pixil.org/license.html or              
 * email cetsales at centurysoftware.com for information about the PIXIL   
 * Commercial License Agreement, or if any conditions of this licensing 
 * are not clear to you.                                                
 */


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/un.h>
#include <sys/poll.h>

#include <ipc/colosseum.h>

static int g_socket = 0;

/* Define malloc debug if you are afraid that you aren't freeing all your mallocs */

#ifdef MALLOC_DEBUG
static int g_malloc = 0;

#define CALLOC(size, count) debug_calloc(size, count)
#define FREE(ptr) debug_free(ptr)
#else
#define CALLOC(size, count) calloc(size, count)
#define FREE(ptr) free(ptr)
#endif

/* Define DEBUG to get lots of annoying printfs */

#ifdef DEBUG
#define DPRINT(str, args...) printf("DEBUG: "str, ## args)
#else
#define DPRINT(str, args...)
#endif

#define ERROR(str, args...) printf("ERROR: "str, ## args)


#ifdef MALLOC_DEBUG

static inline void *
debug_calloc(int size, int count)
{
    g_malloc++;
    return (calloc(size, count));
}

static inline void
debug_free(void *ptr)
{
    g_malloc--;
    return (free(ptr));
}

#endif

/* To better handle dynamic packets, we use this structure instead of 
  the queue structure 
*/

typedef struct pbuffer
{
    cl_packet *packet;
    int size;
    struct pbuffer *next;
}
pkt_buff_t;

static pkt_buff_t *pkt_queue = 0;

static inline void
pkt_free(pkt_buff_t * buf)
{
    if (!buf)
	return;
    if (buf->packet)
	FREE(buf->packet);
    FREE(buf);
}

static int
client_ServerDied(void)
{
    printf("The Colosseum server closed unexpectedly\n");
    ClClose();
    return (CL_CLIENT_NOSRVR);
}

static void
client_QueuePacket(pkt_buff_t * packet)
{

    pkt_buff_t *head = pkt_queue;

    if (!head)
	pkt_queue = packet;
    else {
	for (; head->next; head = head->next);
	head->next = packet;
    }

    DPRINT("Queued a packet of size [%d]\n", packet->size);
    packet->next = 0;
}

static int
client_DequeuePacket(pkt_buff_t ** ret)
{

    if (pkt_queue) {
	*ret = pkt_queue;
	pkt_queue = pkt_queue->next;
	return (1);
    }

    return (0);
}

static int
client_SendToServer(int sock, unsigned char *data, int len)
{

    int ret;

    ret = write(sock, data, len);

    if (ret <= 0) {
	if (ret == 0)
	    return (1);
	return (-1);
    }

    return (0);
}

/* Grab a packet off of the server */

int
client_GetFromServer(int sock, pkt_buff_t ** ret_buffer)
{

    int ret;
    int dsize = 0;
    pkt_buff_t *buffer;
    cl_pkt_header header;

    struct pollfd pstruct;

    pstruct.fd = sock;
    pstruct.events = POLLIN;

    ret = poll(&pstruct, 1, 0);

    /* No data is available */

    if (ret <= 0) {
      if (ret == -1)
	perror("client_GetFromServer");

      return (ret);
    }

    /* Read the header */
    ret = read(sock, &header, sizeof(header));

    if (ret <= 0) {
	if (errno == EAGAIN || ret == 0) {
	  return (0);
	}
	perror("client_GetFromServer");
	return (-1);
    }

    if (!header.len)
	return (0);

    buffer = *ret_buffer = (pkt_buff_t *) CALLOC(1, sizeof(pkt_buff_t));

    if (!buffer) {
	ERROR("Error - Out of memory in client_GetFromServer\n");
	return (-1);
    }

    buffer->packet = (cl_packet *) CALLOC(header.len, 1);
    dsize = header.len - sizeof(header);

    if (!buffer->packet) {
	pkt_free(buffer);
	ERROR("Error - Out of memory in client_GetFromServer\n");
	return (-1);
    }

    buffer->size = header.len;
    memcpy(buffer->packet, &header, sizeof(header));

    /* Now, read in the rest of the packet */

    ret =
	read(sock, (unsigned char *) buffer->packet + sizeof(header), dsize);

    if (ret != dsize) {

	/* No matter what, free the existing packet buffer */
	pkt_free(buffer);

	if (ret < 0) {
	    if (errno == EAGAIN)
		return (0);

	    perror("client_GetFromServer");
	    return (-1);
	} else {
	    ERROR("bad packet size - expected [%d], got [%d].\n", dsize, ret);
	    return (-1);
	}
    }

    return (header.len);
}

static int
client_WaitForData(int sock, int timeout)
{

    fd_set iset, eset;

    FD_ZERO(&iset);
    FD_ZERO(&eset);

    FD_SET(sock, &iset);
    FD_SET(sock, &eset);

    if (timeout) {
	struct timeval tv;
	tv.tv_sec = timeout / 1000000;
	tv.tv_usec = timeout % 1000000;

	return (select(sock + 1, &iset, 0, &eset, &tv));
    } else
	return (select(sock + 1, &iset, 0, &eset, 0));
}

static int
client_WaitForServer(int sock, int packet_type,
		     pkt_buff_t ** pkt, int timeout)
{

    int qcount = 0;
    *pkt = 0;

    do {
	pkt_buff_t *buffer = 0;
	cl_packet *data;
	int ret;

	/* Wait for the data to come in on the line */
	ret = client_WaitForData(sock, timeout);

	if (ret == 0)
	    return (CL_CLIENT_TIMEOUT);
	else if (ret == -1) {
	    return (CL_CLIENT_ERROR);
	}

	ret = client_GetFromServer(sock, &buffer);

	if (ret < 0) {
	    return (CL_CLIENT_ERROR);
	}

	else if (ret == 0)
	    return (CL_CLIENT_TIMEOUT);

	data = (cl_packet *) buffer->packet;

	if (data->header.type == packet_type) {
	    *pkt = buffer;
	    if (qcount)
		write(sock, 0, 0);
	    return (0);
	}

	if (data->header.type == CL_PKT_MESSAGE) {
	    client_QueuePacket(buffer);
	    DPRINT("While waiting for a %d, a Message packet was queued\n",
		   packet_type);
	    qcount++;
	} else
	    ERROR("Got type [%d] when expecting type [%d]\n",
		  data->header.type, packet_type);

    } while (1);
}

static int
client_MakeRequest(int sock, int packet_type,
		   cl_packet * packet, int len, int timeout)
{

    pkt_buff_t *buffer = 0;

    int ret;
    int size = 0;

    packet->header.type = packet_type;
    packet->header.len = len;

    ret = client_SendToServer(sock, (unsigned char *) packet, len);

    if (ret == -1) {
	return (CL_CLIENT_ERROR);
    } else if (ret == 1)
	return (client_ServerDied());

    bzero(packet, len);
    ret = client_WaitForServer(sock, packet_type, &buffer, timeout);

    if (ret < 0 || buffer == 0) {
	ERROR("Got an error from client_WaitForServer\n");
	pkt_free(buffer);
	return (ret);
    }

    /* This is where we actually transfer the packet */

    if (buffer->size != len)
	ERROR("Unexpected size [%d] in client_MakeRequest\n", buffer->size);

    if (buffer->size > CL_MAX_PKT_SIZE) {
	ERROR("I refuse to try and handle a packet of size [%d]\n",
	      buffer->size);
	pkt_free(buffer);
	return (CL_CLIENT_INVALID);
    }

    size = (len > buffer->size) ? buffer->size : len;

    bzero(packet, len);
    memcpy(packet, buffer->packet, size);

    pkt_free(buffer);		/* Free the buffer - very important */
    return (size);
}

static int
local_Register(unsigned char *name, int inflags, int *outflags)
{

    struct sockaddr_un saddr;
    cl_pkt_reg pkt;
    int ret;

    if (!name)
	return (CL_CLIENT_INVALID);
    if (g_socket)
	return (CL_CLIENT_CONNECTED);

    /* First, create a socket and try to connect */

    g_socket = socket(AF_UNIX, SOCK_STREAM, 0);
    if (!g_socket) {
	perror("Socket Error: ");
	return (CL_CLIENT_SOCK_ERROR);
    }

    /* Try to connect to the named socket */

    saddr.sun_family = AF_UNIX;
    strncpy(saddr.sun_path, CL_NAMED_SOCKET, sizeof(saddr.sun_path));

    /* Try to connect.  If the connection is refused, then we will */
    /* assume that no server is available */

    if (connect(g_socket, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) {
	close(g_socket);
	g_socket = 0;
	if ((errno == ECONNREFUSED) || (errno == ENOENT))
	    return (CL_CLIENT_NOSRVR);
	else
	    return (CL_CLIENT_SOCK_ERROR);
    }
#ifdef NOTUSED
    /* Now, make the socket non blocking */
    if (fcntl(g_socket, F_SETFL, O_NONBLOCK)) {
	close(g_socket);
	g_socket = 0;
	return (CL_CLIENT_SOCK_ERROR);
    }
#endif

    bzero(&pkt, sizeof(pkt));
    strncpy(pkt.name, name, CL_MAX_NAME_LEN);

    pkt.start_flags = inflags;

    ret = client_MakeRequest(g_socket, CL_PKT_REGISTER, (cl_packet *) & pkt,
			     sizeof(pkt), 0);

    if (ret < 0)
	return (ret);

    switch (pkt.header.resp) {
    case CL_E_APPEXISTS:
	return (CL_CLIENT_BADNAME);

    case 0:
	if (outflags)
	    *outflags = pkt.start_flags;
	return (g_socket);

    default:
	printf("Error %d returned from server\n", pkt.header.resp);
	return (CL_CLIENT_ERROR);
    }
}

int
ClRegister(unsigned char *name, int *flags)
{
    return (local_Register(name, CL_NORMAL_CLIENT, flags));
}

int
ClReconnect(unsigned char *name)
{
    g_socket = 0;
    return (local_Register(name, CL_NORMAL_CLIENT, 0));
}

int
ClClose(void)
{

    pkt_buff_t *head = pkt_queue;

    if (!g_socket)
	return (CL_CLIENT_NOCONN);

    /* Free any queued packets */

    while (head) {
	pkt_buff_t *next = head->next;
	pkt_free(head);
	head = next;
    }

    close(g_socket);
    g_socket = 0;

#ifdef MALLOC_DEBUG
    printf("MALLOC_DEBUG:  The end result was %d\n", g_malloc);
#endif

    return (0);
}

int
ClFindApp(unsigned char *name)
{

    cl_pkt_findapp pkt;
    int ret;

    if (!g_socket)
	return (CL_CLIENT_NOCONN);
    if (!name)
	return (CL_CLIENT_INVALID);

    bzero(&pkt, sizeof(pkt));

    /* Construct the find app packet */
    strncpy(pkt.name, name, CL_MAX_NAME_LEN);

    ret = client_MakeRequest(g_socket, CL_PKT_FINDAPP,
			     (cl_packet *) & pkt, sizeof(pkt), 0);

    if (ret < 0)
	return (ret);

    switch (pkt.header.resp) {
    case CL_E_NOAPP:
	return (CL_CLIENT_NOTFOUND);

    case 0:
	return (pkt.ipc_id);

    default:
	printf("Error %d returned from server\n", pkt.header.resp);
	return (CL_CLIENT_ERROR);
    }
}

int
ClStartApp(unsigned char *name, unsigned char *args, int flags, int timeout)
{

    cl_pkt_start pkt;
    int ret;

    if (!g_socket)
	return (CL_CLIENT_NOCONN);
    if (!name)
	return (CL_CLIENT_INVALID);

    bzero(&pkt, sizeof(pkt));

    /* Construct the find app packet */
    strncpy(pkt.name, name, CL_MAX_NAME_LEN);

    if (args)
	strncpy(pkt.argstr, args, CL_MAX_ARG_LEN);

    pkt.timeout = timeout;
    pkt.start_flags = flags;

    /* Wait up to timeout seconds */
    ret = client_MakeRequest(g_socket, CL_PKT_STARTAPP,
			     (cl_packet *) & pkt, sizeof(pkt),
			     timeout * 1000000);

    if (ret < 0)
	return (ret);

    switch (pkt.header.resp) {
    case CL_E_NOAPP:
    case CL_E_APPERR:
	return (CL_CLIENT_NOTFOUND);

    case 0:
	return (pkt.ipc_id);

    default:
	printf("Error %d returned from server\n", pkt.header.resp);
	return (CL_CLIENT_ERROR);
    }

}

int
ClSpawnApp(unsigned char *name, unsigned char *args)
{

    cl_pkt_spawn pkt;
    int ret;

    if (!g_socket)
	return (CL_CLIENT_NOCONN);
    if (!name)
	return (CL_CLIENT_INVALID);

    bzero(&pkt, sizeof(pkt));

    /* Construct the find app packet */
    strncpy(pkt.name, name, CL_MAX_NAME_LEN);

    if (args)
	strncpy(pkt.argstr, args, CL_MAX_ARG_LEN);

    /* Wait up to timeout seconds */

    ret = client_MakeRequest(g_socket, CL_PKT_SPAWNAPP,
			     (cl_packet *) & pkt, sizeof(pkt), 0);

    if (ret < 0)
	return (ret);

    switch (pkt.header.resp) {
    case CL_E_SPAWNERR:
	return (CL_CLIENT_NOTFOUND);

    case 0:
	return (pkt.pid);

    default:
	printf("Error %d returned from server\n", pkt.header.resp);
	return (CL_CLIENT_ERROR);
    }
}

int
clGetAppInfo(cl_app_info * info)
{

    int ret;
    cl_pkt_appinfo pkt;

    pkt.flags = info->flags;

    switch (info->flags) {
    case CL_APP_INFO_NAME:
	strcpy(pkt.name, info->name);
	break;
    case CL_APP_INFO_PID:
	pkt.processid = info->processid;
	break;
    }

    /* Wait 500 ms for a response */
    ret = client_MakeRequest(g_socket, CL_PKT_APP_INFO,
			     (cl_packet *) & pkt, sizeof(pkt), 0);

    if (ret < 0)
	return (ret);

    if (pkt.header.resp == CL_E_NOSUCHAPP)
	return (CL_CLIENT_NOTFOUND);

    info->flags = pkt.flags;
    info->processid = pkt.processid;
    strcpy(info->name, pkt.name);

    return (0);
}

int
ClSendMessage(int id, void *message, int len)
{

    pkt_buff_t *buffer = 0;
    cl_packet *response = 0;
    cl_pkt_message *pkt = 0;
    int ret = 0;

    if (!g_socket)
	return (CL_CLIENT_NOCONN);
    if (!message)
	return (CL_CLIENT_INVALID);

    if (!len)
	return (0);

    /* Allocate enough room for the packet */
    /* Note:  This must be on the heap because it can be pretty big */

    if (MESSAGE_PKT_SIZE(len) > CL_MAX_PKT_SIZE) {
	ERROR("Message size [%d] is too big - Rejecting it\n", len);
	return (CL_CLIENT_INVALID);
    }

    pkt = CALLOC(MESSAGE_PKT_SIZE(len), 1);

    pkt->dest = id;
    pkt->msglen = len;

    memcpy(&pkt->message, message, len);

    pkt->header.type = CL_PKT_MESSAGE;
    pkt->header.len = MESSAGE_PKT_SIZE(len);

    /* Send the packet */

    ret =
	client_SendToServer(g_socket, (unsigned char *) pkt,
			    MESSAGE_PKT_SIZE(len));

    if (ret == -1) {
	FREE(pkt);
	return (CL_CLIENT_ERROR);
    }

    else if (ret == 1) {
	FREE(pkt);
	return (client_ServerDied());
    }

    ret = client_WaitForServer(g_socket, CL_PKT_MSG_RESPONSE, &buffer, 0);

    if (ret < 0 || buffer == 0) {
	pkt_free(buffer);
	FREE(pkt);
	return (CL_CLIENT_ERROR);
    }

    response = (cl_packet *) buffer->packet;

    switch (response->header.resp) {
    case CL_E_NODEST:
	ret = CL_CLIENT_NODEST;
	break;

    case 0:
	ret = 0;
	break;

    default:
	ret = CL_CLIENT_ERROR;
	break;
    }

    FREE(pkt);
    pkt_free(buffer);

    return (ret);
}

int
ClLookupName(int id, unsigned char *name, int *len)
{

    int ret;
    cl_pkt_findname pkt;

    bzero(&pkt, sizeof(pkt));

    if (!g_socket)
	return (CL_CLIENT_NOCONN);
    if (!name || !len || !*len)
	return (CL_CLIENT_INVALID);

    /* Construct the find app packet */
    pkt.id = id;

    /* Wait 500 ms for a response */
    ret = client_MakeRequest(g_socket, CL_PKT_FINDNAME,
			     (cl_packet *) & pkt, sizeof(pkt), 0);

    if (ret < 0)
	return (ret);

    strncpy(name, pkt.name, *len);

    *len = strlen(pkt.name);
    return (0);
}

int
ClGetMessage(void *msg, int *len, unsigned short *src)
{

    pkt_buff_t *buffer = 0;
    cl_pkt_message *msgpkt;

    int wlen;

    if (!g_socket)
	return (CL_CLIENT_NOCONN);
    if (!msg || !len || !*len)
	return (CL_CLIENT_INVALID);

    /* It there is something in the queue, get it there first */
    if (client_DequeuePacket(&buffer) == 0) {
	int rlen = client_GetFromServer(g_socket, &buffer);

	if (rlen == 0) {
	  printf("CLCLIENT:  client_GetFromServer() returned 0\n");
	  return (CL_CLIENT_NODATA);
	}
	else if (rlen == -1)
	    return (CL_CLIENT_ERROR);
    }

    msgpkt = (cl_pkt_message *) buffer->packet;

    /* This shouldn't happen, but it occasionally does */

    if (msgpkt->header.type == CL_PKT_MSG_RESPONSE) {
      printf("CLCLIENT:  Invalid header type\n");
      return (CL_CLIENT_NODATA);
    }

    wlen = (msgpkt->msglen > *len ? *len : msgpkt->msglen);

    memcpy(msg, &msgpkt->message, wlen);
    *len = wlen;

    *src = msgpkt->src;

    pkt_free(buffer);

    return (msgpkt->dest == CL_MSG_BROADCAST_ID)
	? CL_CLIENT_BROADCAST : CL_CLIENT_SUCCESS;
}

int
ClGetNextMessage(void *msg, int *len)
{

    int msgsrc = 0;

    pkt_buff_t *buffer = 0;
    cl_pkt_message *pkt;
    int wlen;

    /* It there is something in the queue, get it there first */

    if (!g_socket)
	return (CL_CLIENT_NOCONN);
    if (!msg || !len || !*len)
	return (CL_CLIENT_INVALID);

    if (!client_DequeuePacket(&buffer)) {
	int ret = client_WaitForServer(g_socket, CL_PKT_MESSAGE, &buffer, 0);

	if (ret == 1)
	    return (client_ServerDied());
	else if (ret == -1)
	    return (CL_CLIENT_ERROR);
    }

    pkt = (cl_pkt_message *) buffer->packet;

    wlen = (pkt->msglen > *len ? *len : pkt->msglen);
    memcpy(msg, &pkt->message, wlen);
    *len = wlen;
    msgsrc = pkt->src;

    pkt_free(buffer);
    return (msgsrc);
}

#ifdef HAVE_LOGGING

int
ClLogMessage(int level, unsigned char *message)
{

    cl_pkt_log pkt;
    int ret;

    if (!g_socket)
	return (CL_CLIENT_NOCONN);
    if (!message)
	return (CL_CLIENT_INVALID);

    bzero(&pkt, sizeof(pkt));

    pkt.level = level;
    strncpy(pkt.message, message, CL_MAX_LOG_LEN);

    pkt.header.type = CL_PKT_LOG;
    pkt.header.len = sizeof(pkt);

    ret = client_SendToServer(g_socket, (unsigned char *) &pkt, sizeof(pkt));

    return (ret);
}

int
ClRegisterLogger(char *name)
{
    return (local_Register(name, CL_LOG_CLIENT, 0));
}

#else /* HAVE_LOGGING */

int
ClLogMessage(int level, unsigned char *name)
{
    return (CL_E_NOTIMPLEMENT);
}

int
ClRegisterLogger(char *name)
{
    return (CL_E_NOTIMPLEMENT);
}

#endif /* HAVE_LOGGING */

--- NEW FILE: Makefile ---
#ipc/client/Makefile

LIB_STATIC=libipc.a
LIB_SHARED=libipc.so

SRC=${shell ls *.c}
OBJS=${SRC:.c=.o}

INCLUDES=-I./include

include $(BASE_DIR)/Rules.make




More information about the dslinux-commit mailing list