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;
}