A Simple Cookie Example
#include "funcs.h"
#define BUFSIZE 50
#define NOT_USED -1
int readsock;
sigjmp_buf env;
fd_set saveset;
struct timetable
{
int socket;
time_t requesttime;
};
struct timetable reqtimes[100];
main()
{
int readn(int readsock, char *string, int bufsize);
int writen(int readsock, char *string, int bufsize);
int makeNonBlocking(int socket);
void set_up_SIGPIPE(void);
fd_set readset;
int socket, passive, active, lowwater = 50, i;
char string[50];
int set_up_passive_socket(void);
long flags;
socklen_t socklen;
set_up_SIGPIPE();
passive = set_up_passive_socket();
FD_ZERO(&saveset);
FD_SET(passive, &saveset);
for (i = 0; i < 100; i++) reqtimes[i].socket = NOT_USED;
for(;;)
{
memcpy(&readset, &saveset, sizeof(fd_set));
select(FD_SETSIZE, &readset, NULL, NULL, NULL);
for (socket = 0; socket < 100; socket++)
{
if (reqtimes[socket].socket == NOT_USED) continue;
if (time(NULL) - reqtimes[socket].requesttime > 10)
{
close(socket);
FD_CLR(socket, &saveset);
reqtimes[socket].socket = NOT_USED;
}
}
if (FD_ISSET(passive, &readset))
{
active = accept(passive, NULL, NULL);
active = makeNonBlocking(active);
reqtimes[active].socket = active;
reqtimes[active].requesttime = time(NULL);
FD_SET(active, &saveset);
}
for(readsock = passive; readsock < FD_SETSIZE ; readsock++)
{
sigsetjmp(env, 1);
if (readsock != passive && FD_ISSET(readsock, &readset))
{
printf("Inside server! Socket is %d.\n", readsock);
memset(string, 0, BUFSIZE);
readn(readsock, string, BUFSIZE);
if (strcmp(string, "quit") == 0)
{
FD_CLR(readsock, &saveset);
close(readsock);
reqtimes[readsock].socket = NOT_USED;
continue;
}
reqtimes[readsock].requesttime = time(NULL);
printf("Got %s from client!\n", string);
writen(readsock, string, 1);
writen(readsock, string + 1, BUFSIZE - 1);
}
}
}
}
int set_up_passive_socket(void)
{
struct sockaddr_in sin;
int passive, makeNonBlocking(int passive);;
long flags;
sin.sin_family = AF_INET;
sin.sin_port = htons(3014);
sin.sin_addr.s_addr = htonl(INADDR_ANY);
if ((passive = socket(AF_INET,SOCK_STREAM,0)) < 0)
{
perror("Server: socket error!");
exit(1);
}
if (bind(passive, (struct sockaddr *) &sin, sizeof(sin)) < 0)
{
perror("Binding error in server!");
exit(2);
}
if (listen(passive, 5) < 0)
{
perror("Listen error in server!");
exit(3);
}
passive = makeNonBlocking(passive);
return passive;
}
int makeNonBlocking(int socket)
{
long flags;
if ((flags = fcntl(socket, F_GETFL, 0)) < 0)
{
perror("Get flags");
exit(1);
}
if (fcntl(socket, F_GETFL, flags | O_NONBLOCK) < 0)
{
perror("Set flags");
exit(1);
}
return socket;
}
void set_up_SIGPIPE(void)
{
void handler(int signum);
struct sigaction sa;
sa.sa_handler = handler;
sa.sa_flags = 0;
sigfillset(&sa.sa_mask);
sigaction(SIGPIPE, &sa, NULL);
}
void handler(int signum)
{
close(readsock);
FD_CLR(readsock, &saveset);
reqtimes[readsock].socket = NOT_USED;
readsock++;
siglongjmp(env, 1);
}
int readn(int fd, char *buf, int bytes)
{
int nleft;
int nread;
char *mover = buf;
nleft = bytes;
while (nleft > 0){
if ((nread = read(fd,mover,nleft)) < 0)
if (errno == EAGAIN)
{
errno = 0;
continue;
}
else raise(SIGPIPE);
else if (nread == 0)
raise(SIGPIPE); /**** EOF! ****/
nleft -= nread;
mover += nread;
}
return (bytes - nleft);
}
int writen(int fd, char *buf, int bytes)
{
int nleft;
int nwritten;
char *mover = buf;
nleft = bytes;
while (nleft > 0){
if ((nwritten = write(fd,mover,nleft)) < 0)
raise(SIGPIPE); /**** Error!! ****/
nleft -= nwritten;
mover += nwritten;
}
return bytes;
}