Difference between revisions of "Server.c"

From Organic Design wiki
m
(server_init())
Line 2: Line 2:
 
// GPL: http://www.gnu.org/copyleft/lesser.html
 
// GPL: http://www.gnu.org/copyleft/lesser.html
 
// SRC: http://www.organicdesign.co.nz/server.c
 
// SRC: http://www.organicdesign.co.nz/server.c
 +
  
 
#define svrDELAY 1        // normal operation is 0 for no delay
 
#define svrDELAY 1        // normal operation is 0 for no delay
Line 7: Line 8:
 
#define svrBUFSIZE 10000  // dictates max message size
 
#define svrBUFSIZE 10000  // dictates max message size
 
#define svrMAXCLIENTS 1000 // used by listen()
 
#define svrMAXCLIENTS 1000 // used by listen()
#if __WIN32__
 
WSADATA wsaData;
 
if (WSAStartup(MAKEWORD(2,0),&wsaData)!=0) logErr("WSAStartup() failed!");
 
#else
 
int WSAGetLastError() { return errno; }
 
#endif
 
  
// Set up structures for socket & select
 
struct sockaddr_in addr;
 
struct timeval to;
 
fd_set *fdset;
 
unsigned long int sockopt_on = 1;
 
int sock, szAddr = sizeof(struct sockaddr_in);
 
memset((char*)&addr, 0, szAddr); // zero the struct
 
addr.sin_family = AF_INET;
 
addr.sin_port = htons(port);
 
addr.sin_addr.s_addr = htonl(INADDR_ANY);
 
  
// struct for a stream-node's state to point to
+
void server();
typedef struct siStruct {
+
void client();
int fd, inptr, outptr;
+
int nonblocking(int socket);
char *inbuf, *outbuf;
+
 
} streamInfo;
+
 
 +
void server_init() {
  
// make the passed socket non-blocking so accept() returns straight away for multiplexed model
 
// - if no incoming requests, returns EAGAIN or EWOULDBLOCK state
 
int nonblocking(int socket) {
 
 
#if __WIN32__
 
#if __WIN32__
ioctlsocket(socket,FIONBIO,&sockopt_on);
+
WSADATA wsaData;
 +
if (WSAStartup(MAKEWORD(2,0),&wsaData)!=0) logErr("WSAStartup() failed!");
 
#else
 
#else
fcntl(socket,F_SETFL,fcntl(socket,F_GETFL)|O_NONBLOCK);
+
int WSAGetLastError() { return errno; }
 
#endif
 
#endif
return socket;
+
 
 +
// Set up structures for socket & select
 +
struct sockaddr_in addr;
 +
struct timeval to;
 +
fd_set *fdset;
 +
unsigned long int sockopt_on = 1;
 +
int sock, szAddr = sizeof(struct sockaddr_in);
 +
memset((char*)&addr, 0, szAddr); // zero the struct
 +
addr.sin_family = AF_INET;
 +
addr.sin_port = htons(port);
 +
addr.sin_addr.s_addr = htonl(INADDR_ANY);
 +
 
 +
// struct for a stream-node's state to point to
 +
typedef struct siStruct {
 +
int fd, inptr, outptr;
 +
char *inbuf, *outbuf;
 +
} streamInfo;
 +
 
 +
// Do the usual socket polava: create,options,bind,listen
 +
if ((sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
 +
logErrNum("socket() failed returning %d",WSAGetLastError());
 +
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&sockopt_on,sizeof(int))<0) logErr("setsockopt() failed!");
 +
if (bind(nonblocking(sock),(struct sockaddr*)&addr,szAddr)<0) logErr("bind() failed!");
 +
if (listen(sock,svrMAXCLIENTS)<0) logErr("listen() failed!");
 +
if (errno) logAdd("Server failed to start!");
 +
 
 +
// make the passed socket non-blocking so accept() returns straight away for multiplexed model
 +
// - if no incoming requests, returns EAGAIN or EWOULDBLOCK state
 +
int nonblocking(int socket) {
 +
#if __WIN32__
 +
ioctlsocket(socket,FIONBIO,&sockopt_on);
 +
#else
 +
fcntl(socket,F_SETFL,fcntl(socket,F_GETFL)|O_NONBLOCK);
 +
#endif
 +
return socket;
 +
}
 +
 
 
}
 
}
 
// Do the usual socket polava: create,options,bind,listen
 
if ((sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
 
logErrNum("socket() failed returning %d",WSAGetLastError());
 
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&sockopt_on,sizeof(int))<0) logErr("setsockopt() failed!");
 
if (bind(nonblocking(sock),(struct sockaddr*)&addr,szAddr)<0) logErr("bind() failed!");
 
if (listen(sock,svrMAXCLIENTS)<0) logErr("listen() failed!");
 
if (errno) logAdd("Server failed to start!");
 
  
 
// Parses a message content and responds to client
 
// Parses a message content and responds to client
Line 62: Line 74:
  
 
}
 
}
 
  
 
// Function called by each stream-node in network's reduction loop
 
// Function called by each stream-node in network's reduction loop

Revision as of 05:25, 28 July 2006

// This article and all its includes are licenced under LGPL // GPL: http://www.gnu.org/copyleft/lesser.html // SRC: http://www.organicdesign.co.nz/server.c


  1. define svrDELAY 1 // normal operation is 0 for no delay
  2. define svrPAKSIZE 128 // keep packet-size small for non-multithreaded design
  3. define svrBUFSIZE 10000 // dictates max message size
  4. define svrMAXCLIENTS 1000 // used by listen()


void server(); void client(); int nonblocking(int socket);


void server_init() {

#if __WIN32__ WSADATA wsaData; if (WSAStartup(MAKEWORD(2,0),&wsaData)!=0) logErr("WSAStartup() failed!"); #else int WSAGetLastError() { return errno; } #endif

// Set up structures for socket & select struct sockaddr_in addr; struct timeval to; fd_set *fdset; unsigned long int sockopt_on = 1; int sock, szAddr = sizeof(struct sockaddr_in); memset((char*)&addr, 0, szAddr); // zero the struct addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY);

// struct for a stream-node's state to point to typedef struct siStruct { int fd, inptr, outptr; char *inbuf, *outbuf; } streamInfo;

// Do the usual socket polava: create,options,bind,listen if ((sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0) logErrNum("socket() failed returning %d",WSAGetLastError()); if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&sockopt_on,sizeof(int))<0) logErr("setsockopt() failed!"); if (bind(nonblocking(sock),(struct sockaddr*)&addr,szAddr)<0) logErr("bind() failed!"); if (listen(sock,svrMAXCLIENTS)<0) logErr("listen() failed!"); if (errno) logAdd("Server failed to start!");

// make the passed socket non-blocking so accept() returns straight away for multiplexed model // - if no incoming requests, returns EAGAIN or EWOULDBLOCK state int nonblocking(int socket) { #if __WIN32__ ioctlsocket(socket,FIONBIO,&sockopt_on); #else fcntl(socket,F_SETFL,fcntl(socket,F_GETFL)|O_NONBLOCK); #endif return socket; }

}

// Parses a message content and responds to client void processMessage(char* msg) {

// Create a new context node

// validate and extract event, params and mime-type // /GET\s+\/+(.*?)(\/(.+))?\s+(HTTP\/[0-9.]+)/

// add appropriate response to nodal context // - restart, click?x&y, else content/mime/type

}

// Function called by each stream-node in network's reduction loop // - there is also a streams-container node containing zero or more stream nodes void server() { FD_ZERO(fdset); FD_SET(sock,fdset); to.tv_sec = to.tv_usec = svrDELAY; if (select(sock+1,fdset,NULL,NULL,&to)>0) { // New connection request, accpet and create new stream-node int fd = nonblocking(accept(sock,NULL,NULL)); if (fd>0) { streamInfo *newsi = malloc(sizeof(streamInfo)); newsi->fd = fd; newsi->inbuf = malloc(svrBUFSIZE); newsi->outbuf = malloc(svrBUFSIZE); newsi->inptr = 0; newsi->outptr = 0; //nodeSetState(newNode = add-me-to-stream-loop, nodeSTREAMINFO, newsi); nodeSetValue(nodeROOT,nodeCURRENT,nodeROOT); // nodally exit on request test } else logErr("accept(): failed!"); } }


// Each of the stream nodes points to this function in its State void client() {

// Get the info for this stream ready for reading/writing a packet if necessary streamInfo *info = nodeGetState(this, nodeSTREAMINFO); int i,fd = info->fd, inptr = info->inptr, outptr = info->outptr; char *inbuf = info->inbuf, *outbuf = info->outbuf;

// Data to receive? FD_ZERO(fdset); FD_SET(fd,fdset); to.tv_sec = to.tv_usec = svrDELAY; if (select(fd+1,fdset,NULL,NULL,&to)>0) { // read a packet into inbuf if (i = recv(fd,inbuf+inptr,svrPAKSIZE,0)>0) {

// test if complete message in buffer char *message = NULL; while (i--) { // /\r?\n\r?\n\x00?/ }

if (message) { //inptr = info->inptr -= msg_size; // hook a process into the loop } } else if (i == 0) { // zero bytes to read, do orderly termination // todo: remove this stream node from loop free(inbuf); free(outbuf); free(info); } else logErr("recv(): failed!"); }

// Data to send? FD_ZERO(fdset); FD_SET(fd,fdset); to.tv_sec = to.tv_usec = svrDELAY; if (select(fd+1,NULL,fdset,NULL,&to)>0) { // write a packet from outbuf int len = svrPAKSIZE; // or less if (send(fd,outbuf+outptr,len,0)<0) logErr("send() failed!"); }

}