/* serverlib.c
 *
 * Copyright (c) 1999 Scott Manley, Barath Raghavan, Jack Moffitt, and Alexander Haväng
 *
 * 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.
 *
 */


/* All code for making connections goes in here */

#include "liveice.h"
#include "serverlib.h"

extern int errno;



/* Create a new socket which can be bound to a socket later */
sckt *sopen(void){
	sckt *sp;
	if ((sp = (sckt *)malloc(sizeof(sckt)))==0)
		return 0;
	if ((sp->sd = socket(AF_INET, SOCK_STREAM, 0))==-1){
		free(sp);
		return 0;
	}
	sp->sinlen = sizeof(sp->sin);
	sp->bindflag = S_RESET;
	return sp;
}

/* close an exsiting socket */
int sclose(sckt *sp){
	int sd;
	sd = sp->sd;
	free(sp);
	return close(sd);
}

/* Attempt to connect to a listening socket */
int sclient(sckt *sp, char *name, int port){
	struct hostent *hostent;
	if ((hostent = gethostbyname(name))==0)
		return -1;
	sp->sin.sin_family = (short)hostent->h_addrtype;
	sp->sin.sin_port = htons((unsigned short)port);
	sp->sin.sin_addr.s_addr = *(unsigned long *)hostent->h_addr;
	if (connect(sp->sd, (struct sockaddr *)&sp->sin, sp->sinlen)==-1)
		return -1;
	return sp->sd;
}


/* Open socket for listening - return on connect */
int sserver(sckt *sp, int port, int sync){
	int flags;
	struct hostent *hostent;
	char localhost[S_NAMLEN+1];
	if (sp->bindflag==S_RESET){
		if (gethostname(localhost, S_NAMLEN)==-1 || (hostent = gethostbyname(localhost))==0)
			return -1;
		sp->sin.sin_family = (short)hostent->h_addrtype;
		sp->sin.sin_port = htons((unsigned short)port);
		sp->sin.sin_addr.s_addr = 0;
		/*  sp->sin.sin_addr.s_addr = *(unsigned long *)hostent->h_addr;*/
		if (bind(sp->sd, (struct sockaddr *)&sp->sin, sp->sinlen)==-1 || listen(sp->sd, 5)==-1)
			return -1;
		sp->bindflag = S_SET;
	}
	switch (sync)
	{  
	case S_DELAY:
		if ((flags = fcntl(sp->sd, F_GETFL))==-1
		    || fcntl(sp->sd, F_SETFL, flags&O_NDELAY)==-1)
			return -1;
		break;
	case S_NDELAY:
		if ((flags = fcntl(sp->sd, F_GETFL))==-1
		    || fcntl(sp->sd, F_SETFL, flags|O_NDELAY)==-1)
			return -1;
		break;    
	default:
		return -1;
	}
	return accept(sp->sd, (struct sockaddr *)&sp->sin, &sp->sinlen);
}

