All pastes #833835 Raw Edit

Guilt

public text v1 · immutable
#833835 ·published 2007-12-27 17:50 UTC
rendered paste body
#include <netlib.h>

#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#ifdef FREEBSD_SENDFILE
#include <sys/types.h>
#include <sys/uio.h>
#endif /* FREEBSD_SENDFILE */

#define READ_BUFF_SIZE 4096
#define MISC_BUFF_SIZE 256

#ifndef min
#define min(a,b) (a)<(b)?(a):(b)
#endif

int32 Skipn(fd in, int32 n){
	int32 ntotread=0;
	int32 nread;
	uint8 c[READ_BUFF_SIZE];
	while(ntotread<n){
		nread=read(in,c,min(n-ntotread,READ_BUFF_SIZE));
		if(nread<=0){
			if(errno==EINTR) continue;
			return NET_ERROR;
		}
		ntotread+=nread;
	}
	return ntotread;
}

int32 Relayn(fd in, fd out, int32 n){
	int32 ntotread;
	int32 nread;
	int32 nwritten;
	uint8 c[READ_BUFF_SIZE];

	#ifdef FREEBSD_SENDFILE
		if(n>0) {
			if(sendfile(in, out, 0, n, &ntotread, 0)<0) {
				if(errno!=EINVAL)
					return NET_ERROR;
			} else 
				return ntotread;
		} else if(n<0) {
			if(sendfile(in, out, 0, 0, &ntotread, 0)<0) {
				if(errno!=EINVAL)
					return NET_ERROR;
			} else 
				return ntotread;
		}
	#endif /* FREEBSD_SENDFILE */

	ntotread=0;
	while(n<0||ntotread<n){
		nread=read(in,c,n<0?READ_BUFF_SIZE:min(READ_BUFF_SIZE,n-ntotread));
		if(nread<=0){
			if(errno==EINTR) continue;
			if(n<0) return ntotread;
			return NET_ERROR;
		}
		nwritten=write(out,c,nread);
		while(nwritten<nread) {
			if(errno==EINTR) {
				nwritten=write(out,c,nread);
				continue;
			}
			return NET_ERROR;
		}
		ntotread+=nread;
	}
	return ntotread;
}

int32 Readn(fd in, void *buff, int32 n){
	int32 ntotread=0;
	int32 nread;
	uint8 *vbuff=buff;
	while(ntotread<n){
		nread=read(in,vbuff,n-ntotread);
		if(nread<=0){
			if(errno==EINTR) continue;
			return NET_ERROR;
		}
		ntotread+=nread;
		vbuff+=nread;
	}
	return ntotread;
}

int32 Writen(fd out, void *buff, int32 n){
	int32 ntotwritten=0;
	int32 nwritten;
	uint8 *vbuff=buff;
	while(ntotwritten<n){
		nwritten=write(out,vbuff,n-ntotwritten);
		if(nwritten<=0){
			if(errno==EINTR) continue;
			return NET_ERROR;
		}
		ntotwritten+=nwritten;
		vbuff+=nwritten;
	}
	return ntotwritten;
}

int32 Readline(fd in, void *buff, int32 maxsize){
	int32 nread=0;
	int32 ntotread=0;
	uint8 *cbuff=buff;
	uint8 c=0;
	maxsize-=sizeof(uint8);
	if(maxsize<0) return ntotread; 
	while(ntotread<maxsize){
		nread=read(in,&c,sizeof(uint8));
		if(nread<0) {
			if(errno==EINTR) continue;
			return NET_ERROR;			
		}
		if(nread<sizeof(uint8)) {
			ntotread+=nread;
			break;
		}
		if(!c||c=='\n'||c=='\r') break;
		*cbuff=c;
		cbuff+=nread;
		ntotread+=nread;
	}
	while(c&&c!='\n'&&c!='\r') {
		nread=read(in,&c,sizeof(uint8));
		if(nread<0) {
			if(errno==EINTR) continue;
			return NET_ERROR;			
		}
	} 
	#ifdef NET_CR
	while(c&&c!='\n') {
		nread=read(in,&c,sizeof(uint8));
		if(nread<0) {
			if(errno==EINTR) continue;
			return NET_ERROR;
		}			
	}
	#endif /* NET_CR */
	*(cbuff++)=0;	
	return ntotread;
}

int32 Writeline(fd out, void *buff){
	int32 nwritten=0;
	int32 ntotwritten=0;
	int32 length=0;
	#ifdef NET_CR
	uint8 pterm='\r';
	#endif /* NET_CR */
	uint8 term='\n';
	uint8 *cbuff=buff;
	for(;*cbuff&&*cbuff!='\n'&&*cbuff!='\r';++length,++cbuff);
	nwritten=Writen(out,buff,length*sizeof(uint8));
	if(nwritten<length*sizeof(uint8)) return NET_ERROR;
	ntotwritten+=nwritten;
	#ifdef NET_CR
		nwritten=Writen(out,&pterm,sizeof(uint8));
		if(nwritten<sizeof(uint8)) return NET_ERROR;
		ntotwritten+=nwritten;
	#endif /* NET_CR */
	nwritten=Writen(out,&term,sizeof(uint8));
	if(nwritten<sizeof(uint8)) return NET_ERROR;
	ntotwritten+=nwritten;
	return ntotwritten;
}

int32 Close(fd *in){
	close(*in);
	*in=-1;
 	return NET_OK;
}

static struct addrinfo *getResults(char *ip, char *service, int32 flags, int32 socktype, int32 protocol) {
	int status;
	struct addrinfo hints, *results=NULL;
	memset(&hints,0,sizeof(struct addrinfo));
	hints.ai_flags=flags;
	hints.ai_family=AF_UNSPEC;
	hints.ai_socktype=socktype;
	hints.ai_protocol=protocol;
	hints.ai_addrlen=0;
	hints.ai_canonname=NULL;
	hints.ai_addr=NULL;
	hints.ai_next=NULL;
	status=getaddrinfo(ip, service, &hints, &results);
	if(status) {
		results=NULL;
	} 	
	return results;
}

static int freeResults(struct addrinfo *results) {
	freeaddrinfo(results);
	return NET_OK;
}

static int32 Socket(fd *in, int32 addrfamily, int32 socktype){
	if((*in=socket(addrfamily,socktype,0)<0)) 
	 	return NET_ERROR;
	return NET_OK;
}

int32 Connect(fd *in, char *ip, char *service){
	struct addrinfo *results, *rp;
		
	results=getResults(ip, service, 0, 0, 0);
	if(results==NULL) return NET_ERROR;

	for(rp=results; rp; rp=rp->ai_next) {
		int status=Socket(in, rp->ai_family, rp->ai_socktype);
		if(status>=0) {
			if(connect(*in,rp->ai_addr,rp->ai_addrlen)>=0) break;
			Close(in);
		}
	}

	freeResults(results); results=NULL;

	if(rp==NULL) return NET_ERROR;
			       
	return NET_OK;
}

int32 Bind(fd *bindin, char *ip, char *service){
	struct addrinfo *results, *rp;

	results=getResults(ip, service, AI_PASSIVE, SOCK_STREAM, 0);
	if(results==NULL) return NET_ERROR;

	for(rp=results; rp; rp=rp->ai_next) {
		int status;
		status=Socket(bindin, rp->ai_family, rp->ai_socktype); rp->ai_protocol=0;
		if(status==NET_OK) {
			int opt=1; setsockopt(*bindin,SOL_SOCKET,SO_REUSEADDR,(const char *)&opt,sizeof(opt)); 
			if(bind(*bindin,rp->ai_addr,rp->ai_addrlen)>=0) break;
			Close(bindin);
		}
	}

	freeResults(results); results=NULL;

	if(rp==NULL) return NET_ERROR;

    	if(listen(*bindin,NET_BACKLOG)!=0) {
		Close(bindin);
       		return NET_ERROR;
    	}
		                     
	return NET_OK;
}

int32 Accept(fd *bindin, fd *acceptin) {
    struct sockaddr caddr;
    uint32 caddrs=sizeof(caddr);

    *acceptin = accept(*bindin,(struct sockaddr *)&caddr, &caddrs);
    if(*acceptin<0) {
    	return NET_ERROR;
    }

    return NET_OK;
}