Project

General

Profile

Bug #2716 » server.c

jorisgio, 08/18/2014 10:12 AM

 
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <err.h>
#include <errno.h>
#include <strings.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>


#define PORT 8001
#define CPORT 8002
#define PATH "/tmp/sendfile"
#define H_SIZE 1000
#define T_SIZE 4096
#define N_SEC 50000000


int main() {
int s, sc, fd, kq;

off_t size;

struct sockaddr_in addr;
struct sockaddr_in copy;
struct timespec req, actual;
struct sf_hdtr header;
bzero(&header, sizeof(struct sf_hdtr));
bzero(&req, sizeof(struct timespec));
bzero(&actual, sizeof(struct timespec));
req.tv_nsec = N_SEC;
#if 0
struct iovec vec;

vec.iov_base = malloc(H_SIZE);
vec.iov_len= H_SIZE;

fd = open("/dev/urandom", O_RDONLY);
read(fd, vec.iov_base, H_SIZE);
close(fd);

header.headers = &vec;
header.hdr_cnt = 1;
#endif

s = socket(PF_INET, SOCK_STREAM, 0);
if (s < 0)
err(errno, "Cannot create socket");

bzero(&addr, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
inet_aton("127.0.0.1", &addr.sin_addr);

if (bind(s, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))) {
close(s);
err(errno, "Cannot bind to 127.0.0.1 %d", (int) PORT);
}

if (listen(s, 0)) {
close(s);
err(errno, "Cannot listen to socket");
}

kq = kqueue();
if (kq < 0) {
close(s);
err(errno, "Cannot create kqueue");
}

addr.sin_port = htons(CPORT);
char *buf = malloc(T_SIZE);

while ((sc = accept(s, NULL, 0)) > 0) {
off_t sbytes;
off_t off;
off_t ssize;
int nevt, ss;
struct kevent evt;

fd = open(PATH, O_RDWR | O_CREAT);
if (fd < 0) {
close(s);
err(errno, "Cannot open file to send");
}
ftruncate(fd, 0);
unlink(PATH);
fcntl(sc, F_SETFL, O_NONBLOCK);

EV_SET(&evt, sc, EVFILT_READ, EV_ADD, 0, 0, NULL);
nevt = 1;
size = 0;
do {
kevent(kq, &evt, nevt, &evt, 1, NULL);
nevt = 0;
ssize = evt.data;
do {
sbytes = ((ssize > T_SIZE) ? T_SIZE : ssize);
off = read(sc, buf, sbytes);
if (off != sbytes) {
err(errno, "something went wrong during read");
}
off = write(fd, buf, sbytes);
if (sbytes != off) {
err(errno, "something went wrong during write");
}
ssize -= sbytes;
size += sbytes;
} while(ssize > 0);
} while((evt.flags & EV_EOF) == 0);


retry:
ss = socket(PF_INET, SOCK_STREAM, 0);
if (ss < 0) {
close(sc);
close(fd);
close(s);
err(errno, "Cannot create proxy socket");
}
bcopy(&addr, &copy, sizeof(struct sockaddr_in));
if(connect(ss, (struct sockaddr *)&copy, sizeof(struct sockaddr_in))) {
close(ss);
if (errno == ECONNREFUSED) {
nanosleep(&req, &actual);
goto retry;
}
close(sc);
close(fd);
close(s);
err(errno, "Cannot connect to proxy");
}

sbytes = 0;
off = 0;
ssize = size;
while (sendfile(fd, ss, off, ssize, &header, &sbytes, 0) == -1) {
if (errno != EAGAIN) {
close(sc);
close(s);
close(fd);
close(ss);
err(errno, "Cannot send file");
}
off += sbytes;
ssize -= sbytes;
if (ssize <= 0)
break;
sbytes = 0;
}
EV_SET(&evt, sc, EVFILT_READ, EV_DELETE, 0, 0, NULL);
kevent(kq, &evt, 1, NULL, 0, NULL);
close(sc);
close(ss);
close(fd);

}
}


(1-1/2)