// This class is (c) 1998 by Ron Harvest.
// Use freely, but give credit to me as the originator.

#include <iostream.h>
#include <fcntl.h>
#include "server.h"
#include <strings.h>

server::server(char *host, unsigned long port) {
	inbuf = 0;
	bzero(buf,BUFSIZE+1);
	if((soc = connectto(host,port)) == -1) {
	    fprintf(stderr, "Cannot connect to host \"%s\"\n", host);
	    exit(1);
	}
}

int server::sockfd() {
	return soc;
}

// Takes a hostname and a port number and returns a socket, or -1 if 
// failed to connect 
int server::connectto(char *host, unsigned long port) {
	struct sockaddr_in peer;
	struct hostent *hp;
	int soc;

	// Get peer's address 
	hp = gethostbyname(host);
	if (hp==NULL)
		return -1;
	peer.sin_family = AF_INET; peer.sin_port = htons(port);
	bcopy(hp->h_addr_list[0],(char *)&peer.sin_addr,hp->h_length);	

	// Create socket 
	soc = socket(AF_INET,SOCK_STREAM,0);

	// Connect to server 
	if (connect(soc, (struct sockaddr *)&peer, sizeof(peer))==-1) {
		close(soc);
		return -1;
	} else return soc;
}

server::~server() {
	close(soc);
}

int server::noFullLine() {
	buf[BUFSIZE] = 0;

	char *t = index(buf,'\n');

	return ( !t ) || ( t > (buf + inbuf - 1) );
}

void server::readport() {
	int newdata;
	char *kills;
	fd_set fds, efds;

	while ( (inbuf < BUFSIZE) && noFullLine() ) {
		bzero(&fds,sizeof(fd_set)); FD_SET(soc, &fds);
		bzero(&efds,sizeof(fd_set)); FD_SET(soc, &efds);

		select(soc+1, &fds, 0, &efds, 0);
		
		if ( FD_ISSET(soc, &fds) ) {
			newdata = read(soc, buf+inbuf, BUFSIZE-inbuf);

			int removed = 0;

			for (int i = inbuf; i < inbuf+newdata-removed; i++) {
				if ((buf[i] == '\r') || (buf[i] == 0)) {
					memmove(buf+i, buf+i+1, BUFSIZE-i-1);
					buf[BUFSIZE-1] = 0;
					i--;
					removed++;
				}
			}
		
			inbuf += newdata; inbuf -= removed;
		} 
	}
}

char *server::returnWholeBuffer() {
	char *ret = strdup(buf);
	bzero(buf, BUFSIZE+1);
	inbuf = 0;
	return ret;
}

char *server::nextline() {
	char *ret;
	char *nnline;

	// Find the first newline 
	while (noFullLine()) {
		if (inbuf >= BUFSIZE) 
			return returnWholeBuffer();
		readport();
	}

	nnline = index(buf,'\n');

	// Copy everything up to the first newline to the return 
	ret = (char *)malloc(nnline-buf+1);
	ret[nnline-buf] = 0;
	bzero(ret,nnline-buf+1);
	strncpy(ret,buf,nnline-buf);	// Don't copy newline, leave spot zeroed

	inbuf -= nnline+1-buf;
	char *newstart = nnline + 1;
	memmove(buf, newstart, strlen(newstart)+1); 

	return ret;
}

int server::writeport(char *fmtstring, ...) {
	va_list ap;
	fd_set fds;
	char text[1024];

	bzero(text, 1024);

	va_start(ap,fmtstring);
	vsprintf(text,fmtstring,ap);	
	va_end(ap);

	bzero(&fds, sizeof(fd_set)); FD_SET(soc,&fds); 
	select(soc+1,0,&fds,0,0);
	write(soc,text,strlen(text)-1); 

	bzero(&fds, sizeof(fd_set)); FD_SET(soc,&fds);
	select(soc+1,0,&fds,0,0);
	write(soc,"\r\n",2);
}


syntax highlighted by Code2HTML, v. 0.9.1