/**
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "bgnet.h"
/*------------------------------------------------------------------------
* The CNAI API library is documented in chapter 3 of Computer Networks and
* Internets, 4th edition by Douglas E. Comer, Prentice-Hall, 2003.
*
* recvln - recv from socket until newline or EOF is encountered
* Flush to newline or EOF and return on full buffer. Returns data length.
*------------------------------------------------------------------------
*/
static int recvln(int conn, char *buff, int buffsz)
{
char *bp = buff, c;
int n = -1;
while(bp - buff < buffsz &&
(n = recv(conn, bp, 1, 0)) > 0) {
if (*bp++ == '\n')
return (bp - buff);
}
if (n < 0)
return -1;
if (bp - buff == buffsz)
while (recv(conn, &c, 1, 0) > 0 && c != '\n');
return (bp - buff);
}
int Bgnet::Connect( const char *host, int port )
{
int fd;
struct hostent *he;
struct sockaddr_in their_addr; // connector's address information
if( ( he = gethostbyname( host ) ) == NULL ) // get the host info
{
perror( "gethostbyname" );
return ( -1 );
}
if( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 )
{
perror( "socket" );
return ( -1 );
}
their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons( port ); // short, network byte order
their_addr.sin_addr = *( ( struct in_addr * )he->h_addr );
memset( their_addr.sin_zero, '\0', sizeof their_addr.sin_zero );
if( connect( fd, ( struct sockaddr * )&their_addr, sizeof their_addr ) == -1 )
{
perror( "connect" );
return ( -1 );
}
return fd;
}
void Bgnet::Disconnect( int fd )
{
close( fd );
}
int Bgnet::SendAll( int fd, const char *data, int data_length )
{
int bytes_sent = 0;
int result;
while( bytes_sent < data_length )
{
result = send( fd, data + bytes_sent, data_length - bytes_sent, 0 );
if( result == -1 )
{
if( errno == EAGAIN )
continue; // optionally, you may also want to check if errno == EINTR
bytes_sent = -1;
}
bytes_sent += result;
}
return bytes_sent;
}
int Bgnet::Select( int fd )
{
struct timeval tv;
fd_set readfds;
tv.tv_sec = 2;
tv.tv_usec = 500000;
FD_ZERO( &readfds );
FD_SET( fd, &readfds );
// don't care about writefds and exceptfds:
select( fd + 1, &readfds, NULL, NULL, &tv );
if( FD_ISSET( fd, &readfds ) )
return 1;
else
return 0;
}
int Bgnet::Receive( int fd, char *buf, int len )
{
int numbytes;
bzero( buf, len );
if( ( numbytes = recvln( fd, buf, len - 1 ) ) == -1 )
{
perror( "recv" );
return ( -1 );
}
buf[numbytes] = '\0';
//printf( "Received: %s", buf );
return numbytes;
}