423 lines
11 KiB
C
423 lines
11 KiB
C
/* This module supports sending and receiving data objects over a
|
|
socket conection.
|
|
|
|
Copyright 1993 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
|
|
static char udr_c[]="@(#)udr.c 2.8 Daniel Mann";
|
|
static char udr_c_AMD[]="@(#)udr.c 2.3, AMD";
|
|
/*
|
|
* All data is serialised into a character stream,
|
|
* and de-serialised back into the approproiate objects.
|
|
********************************************************************** HISTORY
|
|
*/
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
|
|
/* This used to say sys/fcntl.h, but the only systems I know of that
|
|
require that are old (pre-4.3, at least) BSD systems, which we
|
|
probably don't need to worry about. */
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/socket.h>
|
|
#include "udiproc.h"
|
|
#include "udisoc.h"
|
|
|
|
extern int errno;
|
|
extern char* malloc();
|
|
|
|
/* local type decs. and macro defs. not in a .h file ************* MACRO/TYPE
|
|
*/
|
|
|
|
/* global dec/defs. which are not in a .h file ************* EXPORT DEC/DEFS
|
|
*/
|
|
int udr_errno; /* error occurs during UDR service */
|
|
|
|
/* local dec/defs. which are not in a .h file *************** LOCAL DEC/DEFS
|
|
*/
|
|
|
|
/****************************************************************** UDR_CREATE
|
|
* Build UDR structure for character stream processing.
|
|
*/
|
|
int udr_create(udrs, sd, size)
|
|
UDR* udrs;
|
|
int sd;
|
|
int size;
|
|
{
|
|
udrs->sd = sd;
|
|
if(!udrs->buff) udrs->buff = malloc(size);
|
|
udrs->getbytes = udrs->buff; /* set the buffer to the start */
|
|
udrs->putbytes = udrs->buff;
|
|
udrs->putend = udrs->buff;
|
|
udrs->udr_op = -1; /* don't know the direction */
|
|
udrs->previous_op = -1; /* don't know the direction */
|
|
udrs->bufsize = size;
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************** UDR_FREE
|
|
* Free USR structure and close socket.
|
|
*/
|
|
int udr_free(udrs)
|
|
UDR* udrs;
|
|
{
|
|
close(udrs->sd);
|
|
free(udrs->buff);
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************** UDR_SIGNAL
|
|
* Send a signal to the process at the other end of the socket,
|
|
* indicating that it should expect to recieve a new message shortly.
|
|
*/
|
|
int udr_signal(udrs)
|
|
UDR* udrs;
|
|
{
|
|
if(send(udrs->sd, "I", 1, MSG_OOB) == -1)
|
|
{ perror("ERROR, udr_signal(), send(...MSG_OOB)");
|
|
udr_errno = UDIErrorIPCInternal;
|
|
return -1; /* return error code */
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/***************************************************************** UDR_SENDNOW
|
|
* used to flush the current character stream buffer to
|
|
* the associated socket. */
|
|
int udr_sendnow(udrs)
|
|
UDR* udrs;
|
|
{
|
|
int size = (UDIUInt32)(udrs->putend) - (UDIUInt32)(udrs->buff);
|
|
if(udrs->previous_op == 0)
|
|
{ udr_errno = UDIErrorIPCInternal;
|
|
return -1;
|
|
}
|
|
udrs->putbytes = udrs->buff;
|
|
udrs->putend = udrs->buff;
|
|
if (write(udrs->sd, udrs->buff, size) == -1)
|
|
{ perror("ERROR, udr_sendnow(), write() call: ");
|
|
udr_errno = UDIErrorIPCInternal;
|
|
return -1; /* return error code */
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************** UDR_WORK
|
|
* Function to send or recieve data from the buffers supporting
|
|
* socket communication. The buffer contains serialised objects
|
|
* sent/recieved over a socket connection.
|
|
*/
|
|
int udr_work(udrs, object_p, size)
|
|
UDR* udrs;
|
|
void* object_p;
|
|
int size;
|
|
{
|
|
int cnt, remain;
|
|
|
|
if(udrs->udr_op != udrs->previous_op)
|
|
{ if(udrs->previous_op == 0)
|
|
{ udr_errno = UDIErrorIPCInternal;
|
|
return -1;
|
|
}
|
|
udrs->previous_op= udrs->udr_op;
|
|
udrs->putbytes = udrs->buff;
|
|
udrs->getbytes = udrs->buff;
|
|
}
|
|
|
|
if(udrs->udr_op == UDR_ENCODE)
|
|
{ /* write data into character stream buffer */
|
|
if( (UDIUInt32)(udrs->putbytes) + size >
|
|
(UDIUInt32)(udrs->buff) + (UDIUInt32)(udrs->bufsize) )
|
|
{ udr_errno = UDIErrorIPCInternal;
|
|
return -1;
|
|
}
|
|
memcpy(udrs->putbytes, (char*)object_p, size);
|
|
udrs->putbytes += size;
|
|
if(udrs->putbytes > udrs->putend) udrs->putend = udrs->putbytes;
|
|
}
|
|
else if(udrs->udr_op == UDR_DECODE)
|
|
{
|
|
if( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->getbytes) < size )
|
|
{ /* need more data in character stream buffer */
|
|
remain = (UDIUInt32)(udrs->bufsize) -
|
|
( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->buff) );
|
|
if( ((UDIUInt32)(udrs->bufsize) + (UDIUInt32)(udrs->buff)
|
|
- (UDIUInt32)(udrs->getbytes)) < size)
|
|
{ udr_errno = UDIErrorIPCInternal;
|
|
return -1;
|
|
}
|
|
cnt = read(udrs->sd, (char*)udrs->putbytes, remain);
|
|
if(cnt == -1) perror("ERROR udr_work(), read() failure: ");
|
|
udrs->putbytes += cnt;
|
|
if( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->getbytes) < size )
|
|
{ udr_errno = UDIErrorIPCInternal;
|
|
return -1; /* return error code */
|
|
}
|
|
} /* read data from character stream buffer */
|
|
memcpy((char*)object_p, udrs->getbytes, size);
|
|
udrs->getbytes += size;
|
|
}
|
|
else
|
|
{ udr_errno = UDIErrorIPCInternal;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/************************************************************* UDR_UDIResource
|
|
*/
|
|
int udr_UDIResource(udrs, object_p)
|
|
UDR* udrs;
|
|
UDIResource* object_p;
|
|
{
|
|
int retval;
|
|
|
|
retval = udr_CPUSpace(udrs, &object_p->Space);
|
|
retval = retval | udr_CPUOffset(udrs, &object_p->Offset);
|
|
return retval;
|
|
}
|
|
|
|
/**************************************************************** UDR_UDIRange
|
|
*/
|
|
int udr_UDIRange(udrs, object_p)
|
|
UDR* udrs;
|
|
UDIRange* object_p;
|
|
{
|
|
int retval;
|
|
|
|
retval = udr_CPUOffset(udrs, &object_p->Low);
|
|
retval = retval | udr_CPUOffset(udrs, &object_p->High);
|
|
return retval;
|
|
}
|
|
|
|
/********************************************************** UDR_UDIMemoryRange
|
|
*/
|
|
int udr_UDIMemoryRange(udrs, object_p)
|
|
UDR* udrs;
|
|
UDIMemoryRange* object_p;
|
|
{
|
|
int retval;
|
|
|
|
retval = udr_CPUSpace(udrs, &object_p->Space);
|
|
retval = retval | udr_CPUOffset(udrs, &object_p->Offset);
|
|
retval = retval | udr_CPUSizeT(udrs, &object_p->Size);
|
|
return retval;
|
|
}
|
|
|
|
/****************************************************************** UDR_string
|
|
*/
|
|
int udr_string(udrs, sp)
|
|
UDR* udrs;
|
|
char* sp;
|
|
{
|
|
int len, retval;
|
|
|
|
if(udrs->udr_op == UDR_ENCODE)
|
|
{
|
|
if(sp)
|
|
{ len = strlen(sp) + 1;
|
|
retval = udr_UDIInt32(udrs, &len);
|
|
retval = retval | udr_work(udrs, sp, len);
|
|
}
|
|
else /* deal with NULL pointer */
|
|
{ len = 0;
|
|
retval = udr_UDIInt32(udrs, &len);
|
|
}
|
|
}
|
|
else if(udrs->udr_op == UDR_DECODE)
|
|
{
|
|
retval = udr_UDIInt32(udrs, &len);
|
|
if(len)
|
|
retval = retval | udr_work(udrs, sp, len);
|
|
else *sp = '\0'; /* terminate string */
|
|
}
|
|
else
|
|
{ udr_errno = UDIErrorIPCInternal;
|
|
return -1;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
/******************************************************************* UDR_BYTES
|
|
*/
|
|
int udr_bytes(udrs, ptr, len)
|
|
UDR* udrs;
|
|
char* ptr;
|
|
int len;
|
|
{
|
|
return udr_work(udrs, ptr, len);
|
|
}
|
|
|
|
/********************************************************************* UDR_INT
|
|
*/
|
|
int udr_int(udrs, int_p)
|
|
UDR* udrs;
|
|
int* int_p;
|
|
{
|
|
int ret_val;
|
|
UDIInt32 udr_obj; /* object of know size */
|
|
|
|
if(udrs->udr_op == UDR_ENCODE)
|
|
{
|
|
udr_obj = *int_p; /* copy into know object size */
|
|
return udr_UDIInt32(udrs, &udr_obj);
|
|
}
|
|
else if(udrs->udr_op == UDR_DECODE)
|
|
{
|
|
ret_val = udr_UDIInt32(udrs, &udr_obj); /* get object of known size */
|
|
*int_p = udr_obj;
|
|
return ret_val;
|
|
}
|
|
else
|
|
{ udr_errno = UDIErrorIPCInternal;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/****************************************************************** UDR_INLINE
|
|
*/
|
|
char* udr_inline(udrs, size)
|
|
UDR* udrs;
|
|
int size;
|
|
{
|
|
if(udrs->udr_op != udrs->previous_op)
|
|
{ if(udrs->previous_op == 0)
|
|
{ udr_errno = UDIErrorIPCInternal;
|
|
return 0;
|
|
}
|
|
udrs->previous_op= udrs->udr_op;
|
|
udrs->putbytes = udrs->buff;
|
|
udrs->getbytes = udrs->buff;
|
|
}
|
|
if(udrs->udr_op == UDR_ENCODE)
|
|
{
|
|
if(udrs->putbytes + size > udrs->bufsize + udrs->buff)
|
|
return 0;
|
|
udrs->putbytes += size;
|
|
return udrs->putbytes - size;
|
|
}
|
|
else if(udrs->udr_op == UDR_DECODE)
|
|
{
|
|
if(udrs->getbytes + size > udrs->bufsize + udrs->buff)
|
|
return 0;
|
|
udrs->getbytes += size;
|
|
return udrs->getbytes - size;
|
|
}
|
|
else
|
|
{ udr_errno = UDIErrorIPCInternal;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/****************************************************************** UDR_GETPOS
|
|
*/
|
|
char* udr_getpos(udrs)
|
|
UDR* udrs;
|
|
{
|
|
if(udrs->udr_op == UDR_ENCODE)
|
|
{
|
|
return udrs->putbytes;
|
|
}
|
|
else if(udrs->udr_op == UDR_DECODE)
|
|
{
|
|
return udrs->getbytes;
|
|
}
|
|
else
|
|
{ udr_errno = UDIErrorIPCInternal;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/****************************************************************** UDR_SETPOS
|
|
*/
|
|
int udr_setpos(udrs, pos)
|
|
UDR* udrs;
|
|
char* pos;
|
|
{
|
|
if( ((UDIUInt32)pos > (UDIUInt32)(udrs->buff) + (UDIUInt32)(udrs->bufsize))
|
|
|| ((UDIUInt32)pos < (UDIUInt32)(udrs->buff) ) )
|
|
{ udr_errno = UDIErrorIPCInternal;
|
|
return 0;
|
|
}
|
|
if(udrs->udr_op == UDR_ENCODE)
|
|
{
|
|
udrs->putbytes = pos;
|
|
return 1;
|
|
}
|
|
else if(udrs->udr_op == UDR_DECODE)
|
|
{
|
|
udrs->getbytes = pos;
|
|
return 1;
|
|
}
|
|
else
|
|
{ udr_errno = UDIErrorIPCInternal;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/***************************************************************** UDR_READNOW
|
|
* Try and ensure "size" bytes are available in the
|
|
* receive buffer character stream.
|
|
*/
|
|
int udr_readnow(udrs, size)
|
|
UDR* udrs;
|
|
int size;
|
|
{
|
|
int cnt, remain;
|
|
|
|
if(udrs->udr_op == UDR_ENCODE)
|
|
{
|
|
udr_errno = UDIErrorIPCInternal;
|
|
return -1;
|
|
}
|
|
else if(udrs->udr_op == UDR_DECODE)
|
|
{
|
|
if( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->getbytes) < size )
|
|
{ /* need more data in character stream buffer */
|
|
remain = (UDIUInt32)(udrs->bufsize) -
|
|
( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->buff) );
|
|
cnt = read(udrs->sd, (char*)udrs->putbytes, remain);
|
|
if(cnt == -1) perror("ERROR udr_work(), read() failure: ");
|
|
udrs->putbytes += cnt;
|
|
if( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->getbytes) < size )
|
|
{ fprintf(stderr,"ERROR, udr_readnow() too few bytes in stream\n");
|
|
return -1; /* return error code */
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{ udr_errno = UDIErrorIPCInternal;
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************* UDR_ALIGN
|
|
*/
|
|
int udr_align(udrs, size)
|
|
UDR* udrs;
|
|
int size;
|
|
{
|
|
char* align;
|
|
int offset;
|
|
|
|
align = udr_getpos(udrs);
|
|
offset = size - ((int)align & (size -1));
|
|
offset = offset & (size -1);
|
|
if(offset) udr_setpos(udrs, align + offset);
|
|
}
|