qutils.cc
// $Id: qutils.cc,v 1.4 2002/05/18 22:09:01 vickery Exp $
/* Utility functions used by both the client and the server.
*
* Remote shell project, CS-701, Spring 2002
*
* Functions:
*
* read_header() Reads the header of a message.
* read_body() Reads the body of a message, given the header.
* write_msg() Writes a header and message.
* send_msg() Create header and write message.
*
*/
#include "qutils.h"
#include "qclient.h"
#include "qserver.h"
// read_header()
// ------------------------------------------------------------------
/*
* Read a message header. Puts the message length and type code
* into host byte order.
*
* Arguments: fd The fd to read from.
* header Reference to the msg_header_t struct to be
* read.
* Returns: -1 If an error occured while reading.
* 0 If end of input is reached.
* >0 If the header is read successfully.
*/
int
read_header( int fd, msg_header_t &header )
{
char *buffer = new char[ sizeof(msg_header_t) ];
size_t soFar = 0;
ssize_t numRead = 0;
while ( soFar < sizeof(msg_header_t) )
{
numRead = read( fd,
&buffer[soFar],
sizeof(msg_header_t) - soFar );
if ( numRead < 0 )
{
delete [] buffer;
return -1;
}
if ( 0 == numRead )
{
delete [] buffer;
return 0;
}
soFar += numRead;
}
// Convert byte array to msg_header_t
memcpy( &header, buffer, sizeof(msg_header_t) );
delete [] buffer;
header.msg_length = ntohl( header.msg_length );
header.msg_type = ntohl( header.msg_type );
return (int) sizeof(msg_header_t);
}
// read_body()
// ------------------------------------------------------------------
/*
* Given a message header and a buffer, read the body of a message.
*
* Arguments: fd The fd to read from.
* header The msg_header_t struct containing the body
* length.
* buffer Pointer to buffer to hold the message.
* Returns: 0 If end of input is reached.
* -1 If an error occurs.
* >0 If the operation is successful.
*/
int
read_body( int fd, msg_header_t header, char *buffer )
{
size_t soFar = 0;
ssize_t numRead = 0;
while ( soFar < (unsigned) header.msg_length )
{
numRead = read( fd, &buffer[soFar], header.msg_length - soFar );
if ( numRead < 0 )
{
return -1;
}
if ( 0 == numRead )
{
return 0;
}
soFar += numRead;
}
return (int) header.msg_length;
}
// write_msg()
// ------------------------------------------------------------------
/*
* Writes a message to a socket. Puts the message length and type
* code into network byte order.
*
* Arguments: fd The fd to write to.
* msg_header The msg_header_t struct to write.
* msg_body The body of the message to write.
* Returns: 0 If both writes succeeded.
* -1 If either write failed.
*/
int
write_msg( int fd,
const msg_header_t msg_header,
const char *msg_body )
{
msg_header_t buf;
buf.msg_type = htonl( msg_header.msg_type );
buf.msg_length = htonl( msg_header.msg_length );
int result = write( fd, &buf, sizeof( buf ) );
if ( result < 0 )
return -1;
result = write( fd, msg_body, msg_header.msg_length );
if ( result < 0 )
return -1;
return 0;
}
// send_msg()
// ------------------------------------------------------------------
/*
* Create a message header and then write it and the body.
*
* Arguments: fd The fd to write to.
* msg_type Type code for the message type.
* msg_body The body of the message to write.
* Returns: 0 If successful.
* -1 If either the call to write_msg failed.
*/
int
send_msg( int fd, const int32_t msg_type, const char *msg_body )
{
msg_header_t buf;
buf.msg_type = msg_type;
buf.msg_length = strlen( msg_body );
int result = write_msg( fd, buf, msg_body );
if ( result < 0 )
{
writeLog( "SEND MSG FAILURE", strerror( errno ) );
}
return result;
}
// recv_msg()
// ------------------------------------------------------------------
/*
* Receive a message on a socket.
*
* Allocates memory for the message body, so it is the caller's
* responsibility to free it.
*
* Note: This function blocks until a message is received.
*
* Arguments:
*
* fd The fd to read from.
* msg_header Reference to the message header to read into.
* msg_body Output parameter will point to message body.
*
* Returns:
* Result of reading message body.
*/
int
recv_msg( int fd, struct msg_header_t& msg_header, char **msg_body )
{
int result = read_header( fd, msg_header );
if ( result <= 0 )
{
close( fd );
return -1;
}
*msg_body = new char[ msg_header.msg_length + 1 ];
memset( *msg_body, '0', msg_header.msg_length + 1 );
result = read_body( fd, msg_header, *msg_body );
if ( result < 0 )
{
close( fd );
return -1;
}
return result;
}