cdev-1.7.2n
This commit is contained in:
BIN
extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevAddr.o
Normal file
BIN
extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevAddr.o
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocket.o
Normal file
BIN
extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevSocket.o
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevTime.o
Normal file
BIN
extensions/cdevGenericServer/cdevReactor/.obj/Linux/cdevTime.o
Normal file
Binary file not shown.
BIN
extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevAddr.o
Normal file
BIN
extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevAddr.o
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevTime.o
Normal file
BIN
extensions/cdevGenericServer/cdevReactor/.shobj/Linux/cdevTime.o
Normal file
Binary file not shown.
49
extensions/cdevGenericServer/cdevReactor/Makefile
Executable file
49
extensions/cdevGenericServer/cdevReactor/Makefile
Executable file
@@ -0,0 +1,49 @@
|
||||
ARCH = OS
|
||||
SHOBJ = YES
|
||||
|
||||
#include ../include/makeinclude/Makefile.$(ARCH)
|
||||
include ../include/makeinclude/Makefile.linux
|
||||
|
||||
APPNAME = CDEV Reactor Library
|
||||
OBJS = $(OBJDIR)/cdevAddr.o\
|
||||
$(OBJDIR)/cdevEventHandler.o\
|
||||
$(OBJDIR)/cdevHandleSet.o\
|
||||
$(OBJDIR)/cdevReactor.o\
|
||||
$(OBJDIR)/cdevSocket.o\
|
||||
$(OBJDIR)/cdevSocketAcceptor.o\
|
||||
$(OBJDIR)/cdevSocketConnector.o\
|
||||
$(OBJDIR)/cdevSocketDatagram.o\
|
||||
$(OBJDIR)/cdevSocketStream.o\
|
||||
$(OBJDIR)/cdevStreamNode.o\
|
||||
$(OBJDIR)/cdevStreamQueue.o\
|
||||
$(OBJDIR)/cdevTime.o
|
||||
|
||||
# ******************************************************************************
|
||||
# * The BINARIES definition names all of the binary files that should be deleted
|
||||
# * whenever "make clean" is executed.
|
||||
# ******************************************************************************
|
||||
BINARIES = $(BASELIB)/libcdevReactor.$(SHARED_EXT) \
|
||||
$(BASELIB)/libcdevReactor.a
|
||||
|
||||
# ******************************************************************************
|
||||
# * The TARGETS variable is used to specify the name of the library to build.
|
||||
# ******************************************************************************
|
||||
ifeq ($(SHOBJ),YES)
|
||||
TARGETS = $(BASELIB)/libcdevReactor.$(SHARED_EXT)
|
||||
else
|
||||
TARGETS = $(BASELIB)/libcdevReactor.a
|
||||
endif
|
||||
|
||||
targets : $(TARGETS)
|
||||
|
||||
$(BASELIB)/libcdevReactor.a : $(OBJS)
|
||||
$(LINK.a) $@ $^
|
||||
@$(RANLIB) $@ > /dev/null
|
||||
@mkdir -p $(CDEVLIB)
|
||||
@cp $@ $(CDEVLIB)
|
||||
|
||||
$(BASELIB)/libcdevReactor.$(SHARED_EXT) : $(OBJS)
|
||||
$(LINK.so) -o $@ $^ $(NETLIBS)
|
||||
@mkdir -p $(CDEVLIB)
|
||||
@cp $@ $(CDEVLIB)
|
||||
|
||||
54
extensions/cdevGenericServer/cdevReactor/NMakefile.mak
Normal file
54
extensions/cdevGenericServer/cdevReactor/NMakefile.mak
Normal file
@@ -0,0 +1,54 @@
|
||||
.SUFFIXES: .cc .obj
|
||||
|
||||
ARCH = WINNT-4.0
|
||||
SHOBJ = YES
|
||||
APPNAME = CDEV Reactor Library
|
||||
|
||||
include ..\include\makeinclude\Makefile.WINNT-4.0
|
||||
|
||||
OBJS = $(OBJDIR)/cdevAddr.obj\
|
||||
$(OBJDIR)/cdevEventHandler.obj\
|
||||
$(OBJDIR)/cdevHandleSet.obj\
|
||||
$(OBJDIR)/cdevReactor.obj\
|
||||
$(OBJDIR)/cdevSocket.obj\
|
||||
$(OBJDIR)/cdevSocketAcceptor.obj\
|
||||
$(OBJDIR)/cdevSocketConnector.obj\
|
||||
$(OBJDIR)/cdevSocketDatagram.obj\
|
||||
$(OBJDIR)/cdevSocketStream.obj\
|
||||
$(OBJDIR)/cdevStreamNode.obj\
|
||||
$(OBJDIR)/cdevStreamQueue.obj\
|
||||
$(OBJDIR)/cdevTime.obj
|
||||
|
||||
CXXEXTRA = /D "_CDEV_REACTOR_EXPORTS_=1"
|
||||
|
||||
# ******************************************************************************
|
||||
# * The BINARIES definition names all of the binary files that should be deleted
|
||||
# * whenever "make clean" is executed.
|
||||
# ******************************************************************************
|
||||
BINARIES = $(BASELIB)\cdevReactor.dll \
|
||||
$(BASELIB)\cdevReactor.lib
|
||||
|
||||
# ******************************************************************************
|
||||
# * The TARGETS variable is used to specify the name of the library to build.
|
||||
# ******************************************************************************
|
||||
!IF "$(SHOBJ)" == "YES"
|
||||
TARGETS = $(CDEVLIB)\cdevReactor.dll
|
||||
!ELSE
|
||||
TARGETS = $(CDEVLIB)\cdevReactor.lib
|
||||
!ENDIF
|
||||
|
||||
targets : $(TARGETS)
|
||||
|
||||
$(CDEVLIB)\cdevReactor.lib : $(OBJS)
|
||||
@echo =^> Building $(@F)
|
||||
@echo =^> Objects: $(?F)
|
||||
-@if exist $@ erase $@
|
||||
$(LIB32) $(LINK_LIB_FLAGS) /out:$@ $(OBJS)
|
||||
@echo ^<= Done...
|
||||
|
||||
$(CDEVLIB)\cdevReactor.dll : $(OBJS)
|
||||
@echo =^> Building $(@F)
|
||||
@echo =^> Objects: $(?F)
|
||||
-@if exist $@ erase $@
|
||||
$(LIB32) $(LINK_DLL_FLAGS) /out:$@ /implib:$(@D)\$(@B).lib $(OBJS)
|
||||
@echo ^<= Done...
|
||||
129
extensions/cdevGenericServer/cdevReactor/ServerTest/ClientTest1.cc
Executable file
129
extensions/cdevGenericServer/cdevReactor/ServerTest/ClientTest1.cc
Executable file
@@ -0,0 +1,129 @@
|
||||
#include <cdevReactor.h>
|
||||
#include <cdevSocketAcceptor.h>
|
||||
#include <cdevBufferedSocket.cc>
|
||||
#include "TestNode.h"
|
||||
|
||||
TestNode * TestNode::freeList = NULL;
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
cdevReactor GlobalReactor;
|
||||
|
||||
class ServerHandler : public cdevEventHandler, public cdevNodeFactory
|
||||
{
|
||||
private:
|
||||
cdevBufferedSocket stream;
|
||||
int count;
|
||||
int inboundCount;
|
||||
|
||||
public:
|
||||
ServerHandler ( const cdevAddr &addr )
|
||||
: count(0), inboundCount(0), stream(0, 1, this)
|
||||
{
|
||||
open(addr);
|
||||
}
|
||||
|
||||
int open ( const cdevAddr & addr )
|
||||
{
|
||||
int retval = -1;
|
||||
|
||||
if((retval = stream.connect(addr))==0)
|
||||
{
|
||||
retval = GlobalReactor.registerHandler(this, WRITE_MASK);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int getHandle ( void ) const
|
||||
{
|
||||
return stream.getHandle();
|
||||
}
|
||||
|
||||
void setHandle ( int handle )
|
||||
{
|
||||
stream.setHandle(handle);
|
||||
}
|
||||
|
||||
cdevStreamNode * newNode ( ssize_t size )
|
||||
{
|
||||
TestNode * node = new TestNode;
|
||||
node->setLen(size);
|
||||
return node;
|
||||
}
|
||||
|
||||
int handleInput ( void )
|
||||
{
|
||||
int retval = 0;
|
||||
cdevStreamNode * node = NULL;
|
||||
|
||||
if((retval = stream.receive())>0)
|
||||
{
|
||||
while((node=stream.dequeueInbound())!=NULL)
|
||||
{
|
||||
if(((inboundCount++)%1000)==0) fprintf(stdout, "CLIENT: I received \"%s\"\n", node->getBuf());
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
if(retval<0) setMask(DONT_CALL);
|
||||
else if(!stream.inboundReady()) setMask(WRITE_MASK);
|
||||
|
||||
return retval>=0?0:-1;
|
||||
}
|
||||
|
||||
int handleOutput ( void )
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if(!stream.outboundReady())
|
||||
{
|
||||
for(int i=0; i<1000; i++)
|
||||
{
|
||||
TestNode * node = new TestNode;
|
||||
node->setLen(sprintf(node->getBuf(), "Client Packet %i", count++)+1);
|
||||
stream.enqueueOutbound(node);
|
||||
}
|
||||
setMask(WRITE_MASK);
|
||||
}
|
||||
|
||||
retval=stream.transmit();
|
||||
if(retval<0) setMask(DONT_CALL);
|
||||
else if(!stream.outboundReady()) setMask(READ_MASK);
|
||||
|
||||
return retval>=0?0:-1;
|
||||
}
|
||||
|
||||
int handleClose ( void )
|
||||
{
|
||||
stream.close();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main ( int argc, char * argv[], char * envp [] )
|
||||
{
|
||||
if(argc<3)
|
||||
{
|
||||
fprintf(stderr, "%s [host] [port]\n", "ClientTest1");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char * host = argv[1];
|
||||
short port = atoi(argv[2]);
|
||||
|
||||
|
||||
|
||||
cdevInetAddr serverAddr( port, host);
|
||||
printf("Connecting to %s:%i\n", serverAddr.getHostName(),serverAddr.getPortNum());
|
||||
ServerHandler * client = new ServerHandler(serverAddr);
|
||||
|
||||
for(int i=0; i<100; i++)
|
||||
{
|
||||
if(i%10==0) fprintf(stdout, "====> Have reached iteration %i\n", i);
|
||||
GlobalReactor.handleEvents(1.0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
17
extensions/cdevGenericServer/cdevReactor/ServerTest/Makefile
Executable file
17
extensions/cdevGenericServer/cdevReactor/ServerTest/Makefile
Executable file
@@ -0,0 +1,17 @@
|
||||
SHOBJ=NO
|
||||
ARCH =OS
|
||||
|
||||
include ../../include/makeinclude/Makefile.$(ARCH)
|
||||
|
||||
APPNAME = "cdevReactor Client/Server Test"
|
||||
CXXEXTRA = -I../
|
||||
TARGETS = ServerTest1 ClientTest1
|
||||
|
||||
targets : $(TARGETS)
|
||||
|
||||
ServerTest1 : $(OBJDIR)/ServerTest1.o
|
||||
$(LINK.cc) -o $@ $^ -L$(CDEVLIB) -lcdevReactor -lm
|
||||
|
||||
ClientTest1 : $(OBJDIR)/ClientTest1.o
|
||||
$(LINK.cc) -o $@ $^ -L$(CDEVLIB) -lcdevReactor -lm
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
.SUFFIXES: .cc .obj
|
||||
|
||||
ARCH = WINNT-4.0
|
||||
|
||||
include ..\..\include\makeinclude\Makefile.WINNT-4.0
|
||||
|
||||
BASEBIN = .
|
||||
OBJDIR = .exec\WINNT-4.0
|
||||
CXXINCLUDES = /I ..\
|
||||
|
||||
TARGETS = $(BASEBIN)\ServerTest1.exe $(BASEBIN)\ClientTest1.exe
|
||||
|
||||
targets : $(TARGETS)
|
||||
|
||||
|
||||
$(BASEBIN)\ServerTest1.exe : .exec\$(TARGETDIR)\ServerTest1.obj
|
||||
$(LINK) \
|
||||
$(CDEVLIB)\cdevReactor.lib $(LINK_EXE_FLAGS) /out:$@ \
|
||||
.exec\$(TARGETDIR)\ServerTest1.obj
|
||||
|
||||
$(BASEBIN)\ClientTest1.exe : .exec\$(TARGETDIR)\ClientTest1.obj
|
||||
$(LINK) \
|
||||
$(CDEVLIB)\cdevReactor.lib $(LINK_EXE_FLAGS) /out:$@ \
|
||||
.exec\$(TARGETDIR)\ClientTest1.obj
|
||||
|
||||
purgeworkspace :
|
||||
-@del *.dsp
|
||||
-@del *.plg
|
||||
-@del *.dsw
|
||||
-@del *.ncb
|
||||
-@del *.opt
|
||||
|
||||
176
extensions/cdevGenericServer/cdevReactor/ServerTest/ServerTest1.cc
Executable file
176
extensions/cdevGenericServer/cdevReactor/ServerTest/ServerTest1.cc
Executable file
@@ -0,0 +1,176 @@
|
||||
#include <cdevReactor.h>
|
||||
#include <cdevSocketAcceptor.h>
|
||||
#include <cdevBufferedSocket.cc>
|
||||
#include "TestNode.h"
|
||||
|
||||
TestNode * TestNode::freeList = NULL;
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
cdevReactor GlobalReactor;
|
||||
|
||||
class ClientHandler : public cdevEventHandler, public cdevNodeFactory
|
||||
{
|
||||
friend class Acceptor;
|
||||
|
||||
private:
|
||||
cdevBufferedSocket stream;
|
||||
int inboundCount;
|
||||
int count;
|
||||
|
||||
public:
|
||||
ClientHandler ( void ) : count(0), inboundCount(0), stream(0, 1, this) {}
|
||||
|
||||
int open ( void )
|
||||
{
|
||||
return GlobalReactor.registerHandler(this, READ_MASK);
|
||||
}
|
||||
|
||||
int getHandle ( void ) const
|
||||
{
|
||||
return stream.getHandle();
|
||||
}
|
||||
|
||||
void setHandle ( int handle )
|
||||
{
|
||||
stream.setHandle(handle);
|
||||
}
|
||||
|
||||
cdevStreamNode * newNode ( ssize_t size )
|
||||
{
|
||||
TestNode * node = new TestNode;
|
||||
node->setLen(size);
|
||||
return node;
|
||||
}
|
||||
|
||||
int handleInput ( void )
|
||||
{
|
||||
int retval = 0;
|
||||
cdevStreamNode * node = NULL;
|
||||
|
||||
if((retval = stream.receive())>0)
|
||||
{
|
||||
while((node=stream.dequeueInbound())!=NULL)
|
||||
{
|
||||
if(((inboundCount++)%1000)==0) fprintf(stdout, "SERVER: I received \"%s\"\n", node->getBuf());
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
if(!stream.inboundReady())
|
||||
{
|
||||
for(int i=0; i<1000; i++)
|
||||
{
|
||||
TestNode * node = new TestNode;
|
||||
node->setLen(sprintf(node->getBuf(), "Server Packet %i", count++)+1);
|
||||
stream.enqueueOutbound(node);
|
||||
}
|
||||
setMask(READ_MASK|WRITE_MASK);
|
||||
}
|
||||
|
||||
if(retval<0) setMask(DONT_CALL);
|
||||
|
||||
return retval>=0?0:-1;
|
||||
}
|
||||
|
||||
int handleOutput ( void )
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
retval=stream.transmit();
|
||||
if(retval<0) setMask(DONT_CALL);
|
||||
else if(!stream.outboundReady()) setMask(READ_MASK);
|
||||
|
||||
return retval>=0?0:-1;
|
||||
}
|
||||
|
||||
int handleClose ( void )
|
||||
{
|
||||
fprintf(stdout, "Closing connection to host\n");
|
||||
stream.close();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Acceptor : public cdevEventHandler
|
||||
{
|
||||
public:
|
||||
Acceptor ( const cdevAddr &addr )
|
||||
{
|
||||
open(addr);
|
||||
GlobalReactor.registerHandler(this, READ_MASK);
|
||||
}
|
||||
|
||||
int open ( const cdevAddr &addr )
|
||||
{
|
||||
int result = -1;
|
||||
if (acceptor.open (addr, TRUE) == -1)
|
||||
{
|
||||
fprintf(stdout, "Acceptor [ERROR]: Failed to open listening port");
|
||||
}
|
||||
else if (acceptor.setFlags (O_NONBLOCK) == -1)
|
||||
{
|
||||
fprintf(stdout, "Acceptor [ERROR]: Could not enable non-blocking I/O");
|
||||
}
|
||||
else result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
int getHandle ( void ) const
|
||||
{
|
||||
return acceptor.getHandle();
|
||||
}
|
||||
|
||||
void setHandle ( int handle )
|
||||
{
|
||||
acceptor.setHandle(handle);
|
||||
}
|
||||
|
||||
int handleInput ( void )
|
||||
{
|
||||
cdevInetAddr addr;
|
||||
ClientHandler * handler = new ClientHandler;
|
||||
if(acceptor.accept(handler->stream, &addr)!=-1)
|
||||
{
|
||||
fprintf(stdout, "Received connection from host %s\n", addr.getHostName());
|
||||
handler->open();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handleClose ( void )
|
||||
{
|
||||
acceptor.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
cdevSocketAcceptor acceptor;
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main (int argc, char * argv[], char * envp[])
|
||||
{
|
||||
if(argc<2)
|
||||
{
|
||||
fprintf(stderr, "%s [port]\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
short port = atoi(argv[1]);
|
||||
cdevInetAddr acceptAddr(port, (long)INADDR_ANY);
|
||||
Acceptor * acceptor = new Acceptor(acceptAddr);
|
||||
|
||||
for(int i=0; i<100; i++)
|
||||
{
|
||||
if(i%10==0) fprintf(stdout, "====> Have reached iteration %i\n", i);
|
||||
GlobalReactor.handleEvents(1.0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
48
extensions/cdevGenericServer/cdevReactor/ServerTest/TestNode.h
Executable file
48
extensions/cdevGenericServer/cdevReactor/ServerTest/TestNode.h
Executable file
@@ -0,0 +1,48 @@
|
||||
#include <cdevStreamQueue.h>
|
||||
|
||||
class TestNode : public cdevStreamNode
|
||||
{
|
||||
private:
|
||||
static TestNode * freeList;
|
||||
TestNode * freeListNext;
|
||||
|
||||
char buf[75];
|
||||
size_t len;
|
||||
|
||||
public:
|
||||
TestNode ( void )
|
||||
: len(0), freeListNext(NULL)
|
||||
{
|
||||
}
|
||||
size_t getLen ( void ) const { return len; }
|
||||
void setLen ( size_t size ) { len = size; }
|
||||
char * getBuf ( void ) const { return (char *)buf; }
|
||||
void setBuf ( char * buffer, size_t size)
|
||||
{
|
||||
strcpy(buf, buffer);
|
||||
len = size;
|
||||
}
|
||||
|
||||
void * operator new ( size_t )
|
||||
{
|
||||
TestNode * node;
|
||||
if(freeList==NULL)
|
||||
{
|
||||
freeList = ::new TestNode[1000];
|
||||
for(int i=0; i<999; i++)
|
||||
{
|
||||
freeList[i].freeListNext = &freeList[i+1];
|
||||
}
|
||||
}
|
||||
node = freeList;
|
||||
freeList = node->freeListNext;
|
||||
return node;
|
||||
}
|
||||
|
||||
void operator delete ( void * ptr )
|
||||
{
|
||||
TestNode * node = (TestNode *)ptr;
|
||||
node->freeListNext = freeList;
|
||||
freeList = node;
|
||||
}
|
||||
};
|
||||
17
extensions/cdevGenericServer/cdevReactor/TimerTest/Makefile
Executable file
17
extensions/cdevGenericServer/cdevReactor/TimerTest/Makefile
Executable file
@@ -0,0 +1,17 @@
|
||||
SHOBJ=NO
|
||||
ARCH =OS
|
||||
|
||||
include ../../include/makeinclude/Makefile.$(ARCH)
|
||||
|
||||
APPNAME = "cdevReactor Timer Test"
|
||||
TARGETS = TimerTest1 TimerTest2
|
||||
CXXEXTRA = -I../
|
||||
|
||||
targets : $(TARGETS)
|
||||
|
||||
TimerTest1 : $(OBJDIR)/TimerTest1.o
|
||||
$(LINK.cc) -o $@ $^ -L$(CDEVLIB) -lcdevReactor -lm
|
||||
|
||||
TimerTest2 : $(OBJDIR)/TimerTest2.o
|
||||
$(LINK.cc) -o $@ $^ -L$(CDEVLIB) -lcdevReactor -lm
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
.SUFFIXES: .cc .obj
|
||||
|
||||
ARCH = WINNT-4.0
|
||||
|
||||
include ..\..\include\makeinclude\Makefile.WINNT-4.0
|
||||
|
||||
BASEBIN = .
|
||||
OBJDIR = .exec\WINNT-4.0
|
||||
CXXINCLUDES = /I ..\
|
||||
|
||||
TARGETS = $(BASEBIN)\TimerTest1.exe $(BASEBIN)\TimerTest2.exe
|
||||
|
||||
targets : $(TARGETS)
|
||||
|
||||
$(BASEBIN)\TimerTest1.exe : .exec\$(TARGETDIR)\TimerTest1.obj
|
||||
$(LINK) \
|
||||
$(CDEVLIB)\cdevReactor.lib $(LINK_EXE_FLAGS) /out:$@ \
|
||||
.exec\$(TARGETDIR)\TimerTest1.obj
|
||||
|
||||
|
||||
$(BASEBIN)\TimerTest2.exe : .exec\$(TARGETDIR)\TimerTest2.obj
|
||||
$(LINK) \
|
||||
$(CDEVLIB)\cdevReactor.lib $(LINK_EXE_FLAGS) /out:$@ \
|
||||
.exec\$(TARGETDIR)\TimerTest2.obj
|
||||
28
extensions/cdevGenericServer/cdevReactor/TimerTest/SocketTest1.cc
Executable file
28
extensions/cdevGenericServer/cdevReactor/TimerTest/SocketTest1.cc
Executable file
@@ -0,0 +1,28 @@
|
||||
#include <cdevReactor.h>
|
||||
#include <stdio.h>
|
||||
|
||||
class simpleAcceptor : public cdevEventHandler
|
||||
{
|
||||
|
||||
}
|
||||
class simpleServer : public cdevEventHandler
|
||||
{
|
||||
public:
|
||||
int handleOpen ( void )
|
||||
{
|
||||
}
|
||||
|
||||
int handleInput ( void )
|
||||
{
|
||||
char block[1024];
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
int main ()
|
||||
{
|
||||
cdevReactor reactor;
|
||||
simpleTimer timer;
|
||||
reactor.registerTimer(&timer);
|
||||
for(int i=0; i<10; i++) reactor.handleEvents();
|
||||
}
|
||||
27
extensions/cdevGenericServer/cdevReactor/TimerTest/TimerTest1.cc
Executable file
27
extensions/cdevGenericServer/cdevReactor/TimerTest/TimerTest1.cc
Executable file
@@ -0,0 +1,27 @@
|
||||
#include <cdevReactor.h>
|
||||
#include <stdio.h>
|
||||
|
||||
class simpleTimer : public cdevEventHandler
|
||||
{
|
||||
public:
|
||||
simpleTimer ( void )
|
||||
{
|
||||
setTimeoutRate(1.0);
|
||||
}
|
||||
|
||||
int handleTimeout ( void )
|
||||
{
|
||||
fprintf(stdout, ".");
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main ()
|
||||
{
|
||||
cdevReactor reactor;
|
||||
simpleTimer timer;
|
||||
reactor.registerTimer(&timer);
|
||||
for(int i=0; i<10; i++) reactor.handleEvents();
|
||||
return 0;
|
||||
}
|
||||
48
extensions/cdevGenericServer/cdevReactor/TimerTest/TimerTest2.cc
Executable file
48
extensions/cdevGenericServer/cdevReactor/TimerTest/TimerTest2.cc
Executable file
@@ -0,0 +1,48 @@
|
||||
#include <cdevReactor.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
class simpleTimer : public cdevEventHandler
|
||||
{
|
||||
private:
|
||||
char c;
|
||||
|
||||
public:
|
||||
simpleTimer ( char outputChar='.', double timeout=1.0 )
|
||||
: c(outputChar)
|
||||
{
|
||||
setTimeoutRate(timeout);
|
||||
}
|
||||
|
||||
int handleTimeout ( void )
|
||||
{
|
||||
fprintf(stdout, "%c", c);
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int main (int argc, char ** argv)
|
||||
{
|
||||
int iterations = 100;
|
||||
cdevReactor reactor;
|
||||
simpleTimer timer1('.', 1.0);
|
||||
simpleTimer timer2('-', 0.5);
|
||||
simpleTimer timer3(',', 10.0);
|
||||
simpleTimer timer4('+', 0.25);
|
||||
simpleTimer timer5('-', 0.05);
|
||||
|
||||
if(argc>1) iterations = atoi(argv[1]);
|
||||
if(iterations<=0) iterations=100;
|
||||
|
||||
fprintf(stdout, "Processing for %i iterations\n", iterations);
|
||||
|
||||
reactor.registerTimer(&timer1);
|
||||
reactor.registerTimer(&timer2);
|
||||
reactor.registerTimer(&timer3);
|
||||
reactor.registerTimer(&timer4);
|
||||
reactor.registerTimer(&timer5);
|
||||
|
||||
for(int i=0; i<iterations; i++) reactor.handleEvents();
|
||||
return 0;
|
||||
}
|
||||
190
extensions/cdevGenericServer/cdevReactor/cdevAddr.cc
Normal file
190
extensions/cdevGenericServer/cdevReactor/cdevAddr.cc
Normal file
@@ -0,0 +1,190 @@
|
||||
#include "cdevAddr.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevInetAddr::set :
|
||||
// * Allows the caller to set the address using a port number and
|
||||
// * internet address.
|
||||
// *****************************************************************************
|
||||
int cdevInetAddr::set (unsigned short portnum, long ip_addr)
|
||||
{
|
||||
setType(AF_INET);
|
||||
setSize(sizeof(inet_addr));
|
||||
inet_addr.sin_family = AF_INET;
|
||||
inet_addr.sin_port = htons(portnum);
|
||||
|
||||
if(ip_addr == INADDR_ANY) inet_addr.sin_addr.s_addr=INADDR_ANY;
|
||||
else memcpy((void *)&inet_addr.sin_addr,
|
||||
(void *)&ip_addr,
|
||||
sizeof(inet_addr.sin_addr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevInetAddr::set :
|
||||
// * Allows the caller to set the address using a port number and host name.
|
||||
// *****************************************************************************
|
||||
int cdevInetAddr::set (unsigned short portnum, const char hostname[])
|
||||
{
|
||||
hostent * server_info;
|
||||
long addr;
|
||||
int retval;
|
||||
|
||||
setType(AF_INET);
|
||||
setSize(sizeof(inet_addr));
|
||||
memset((void *)&inet_addr, 0, sizeof(inet_addr));
|
||||
|
||||
if(hostname==NULL || *hostname==0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
retval = -1;
|
||||
}
|
||||
else if((addr=::inet_addr(hostname))!=-1 ||
|
||||
::strcmp(hostname, "255.255.255.255")==0)
|
||||
{
|
||||
retval = set(portnum, addr);
|
||||
}
|
||||
else if((server_info=::gethostbyname(hostname)) != 0)
|
||||
{
|
||||
::memcpy((void *)&addr, (void *)server_info->h_addr, server_info->h_length);
|
||||
retval = set(portnum, addr);
|
||||
}
|
||||
else retval = -1;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevInetAddr::set :
|
||||
// * Allows the caller to set the address using a sockaddr_in structure
|
||||
// * and its length.
|
||||
// *****************************************************************************
|
||||
int cdevInetAddr::set (const sockaddr_in *addr, int len)
|
||||
{
|
||||
setType(AF_INET);
|
||||
setSize(len);
|
||||
memcpy((void *)&inet_addr, (void *)addr, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevInetAddr::cdevInetAddr :
|
||||
// * This constructor creates an empty address object.
|
||||
// *****************************************************************************
|
||||
cdevInetAddr::cdevInetAddr ( void )
|
||||
: cdevAddr(AF_INET, sizeof(sockaddr_in))
|
||||
{
|
||||
::memset((void *)&inet_addr, 0, sizeof(inet_addr));
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevInetAddr::cdevInetAddr :
|
||||
// * This constructor copies the contents of one cdevInetAddr object to
|
||||
// * the new cdevInetAddr object.
|
||||
// *****************************************************************************
|
||||
cdevInetAddr::cdevInetAddr ( const cdevInetAddr & addr )
|
||||
: cdevAddr(AF_INET, sizeof(inet_addr))
|
||||
{
|
||||
memcpy((void *)&inet_addr, (void *)&addr.inet_addr, sizeof(inet_addr));
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevInetAddr::cdevInetAddr :
|
||||
// * This constructor creates a new cdevInetAddr object that contains the
|
||||
// * address provided in the sockaddr_in object.
|
||||
// *****************************************************************************
|
||||
cdevInetAddr::cdevInetAddr (const sockaddr_in *addr, int len)
|
||||
{
|
||||
set(addr, len);
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevInetAddr::cdevInetAddr :
|
||||
// * This constructor initializes the new cdevInetAddr object using the
|
||||
// * specified port number and host name.
|
||||
// *****************************************************************************
|
||||
cdevInetAddr::cdevInetAddr (unsigned short portnum, char hostname[])
|
||||
{
|
||||
set(portnum, hostname);
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevInetAddr::cdevInetAddr :
|
||||
// * This constructor initializes the new cdevInetAddr object with the
|
||||
// * specified port number and ip address.
|
||||
// *****************************************************************************
|
||||
cdevInetAddr::cdevInetAddr (unsigned short portnum, long ip_addr)
|
||||
{
|
||||
set(portnum, ip_addr);
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevInetAddr::getHostName :
|
||||
// * This method allows the caller to return the name of the host that
|
||||
// * the cdevInetAddr structure identifies.
|
||||
// *****************************************************************************
|
||||
const char * cdevInetAddr::getHostName ( void ) const
|
||||
{
|
||||
char * retval;
|
||||
hostent * hp;
|
||||
int len = sizeof(inet_addr.sin_addr.s_addr);
|
||||
|
||||
if((hp = ::gethostbyaddr((char *)&inet_addr.sin_addr, len, addr_type))==0)
|
||||
{
|
||||
retval = NULL;
|
||||
}
|
||||
else retval = hp->h_name;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevInetAddr::getHostAddr :
|
||||
// * This method allows the caller to retrieve the internet address (in
|
||||
// * string format) of the host that the cdevInetAddr object identifies.
|
||||
// *****************************************************************************
|
||||
const char * cdevInetAddr::getHostAddr ( void ) const
|
||||
{
|
||||
return ::inet_ntoa(inet_addr.sin_addr);
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevInetAddr::getInetAddr :
|
||||
// * This method allows the caller to obtain the internet address of the
|
||||
// * host that the cdevInetAddr object identifies.
|
||||
// *****************************************************************************
|
||||
unsigned long cdevInetAddr::getInetAddr ( void ) const
|
||||
{
|
||||
return ntohl((unsigned long)inet_addr.sin_addr.s_addr);
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevInetAddr::getPortNum :
|
||||
// * This method allows the caller to retrieve the port number that is
|
||||
// * associated with this cdevInetAddr.
|
||||
// *****************************************************************************
|
||||
unsigned short cdevInetAddr::getPortNum ( void ) const
|
||||
{
|
||||
return ntohs (inet_addr.sin_port);
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevInetAddr::getAddress :
|
||||
// * Returns the address of the sockaddr_in structure.
|
||||
// *****************************************************************************
|
||||
void * cdevInetAddr::getAddress ( void ) const
|
||||
{
|
||||
return (void *)&inet_addr;
|
||||
}
|
||||
|
||||
48
extensions/cdevGenericServer/cdevReactor/cdevAddr.h
Executable file
48
extensions/cdevGenericServer/cdevReactor/cdevAddr.h
Executable file
@@ -0,0 +1,48 @@
|
||||
#ifndef _CDEV_ADDR_H_
|
||||
#define _CDEV_ADDR_H_
|
||||
|
||||
#include "cdevPlatforms.h"
|
||||
|
||||
class CDEV_REACTOR_API cdevAddr
|
||||
{
|
||||
protected:
|
||||
int addr_type;
|
||||
int addr_size;
|
||||
|
||||
public:
|
||||
cdevAddr ( void ) : addr_type(0), addr_size(0) {}
|
||||
cdevAddr ( int type, int size ) : addr_type(type), addr_size(size) {}
|
||||
int getSize ( void ) const { return addr_size; }
|
||||
void setSize ( int size ) { addr_size = size; }
|
||||
int getType ( void ) const { return addr_type; }
|
||||
void setType ( int type ) { addr_type = type; }
|
||||
|
||||
virtual void * getAddress ( void ) const { return NULL; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
class CDEV_REACTOR_API cdevInetAddr : public cdevAddr
|
||||
{
|
||||
protected:
|
||||
sockaddr_in inet_addr;
|
||||
|
||||
public:
|
||||
cdevInetAddr (void);
|
||||
cdevInetAddr (const cdevInetAddr & addr);
|
||||
cdevInetAddr (const sockaddr_in *, int len);
|
||||
cdevInetAddr (unsigned short portnum, char hostname[]);
|
||||
cdevInetAddr (unsigned short portnum, long ip_addr=INADDR_ANY);
|
||||
|
||||
int set (unsigned short portnum, const char hostname[]);
|
||||
int set (unsigned short portnum, long ip_addr=INADDR_ANY);
|
||||
int set (const sockaddr_in *, int len);
|
||||
|
||||
const char * getHostName ( void ) const;
|
||||
const char * getHostAddr ( void ) const;
|
||||
unsigned long getInetAddr ( void ) const;
|
||||
unsigned short getPortNum ( void ) const;
|
||||
void * getAddress ( void ) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
256
extensions/cdevGenericServer/cdevReactor/cdevBufferedSocket.cc
Executable file
256
extensions/cdevGenericServer/cdevReactor/cdevBufferedSocket.cc
Executable file
@@ -0,0 +1,256 @@
|
||||
#include "cdevBufferedSocket.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevBufferedSocket::sigPipeHandler :
|
||||
// * This is a default signal pipe handler.
|
||||
// *****************************************************************************
|
||||
void cdevBufferedSocket::sigPipeHandler ( int )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevBufferedSocket::newNode :
|
||||
// * This method will return a pointer to a cdevSimpleStreamNode. This
|
||||
// * node will then be populated with data that is read from the socket.
|
||||
// *****************************************************************************
|
||||
cdevStreamNode * cdevBufferedSocket::newNode ( ssize_t size )
|
||||
{
|
||||
cdevSimpleStreamNode * ptr = NULL;
|
||||
if(size>0) ptr = new cdevSimpleStreamNode(new char[size], size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevBufferedSocket::transmit :
|
||||
// * This method will attempt to transmit as many packets as immediately
|
||||
// * possible from the activeOut cdevStreamQueue. The function will cease
|
||||
// * transmitting when the queue is empty or when the receiver is fails
|
||||
// * to accept data after a pre-specified number of retries.
|
||||
// *****************************************************************************
|
||||
ssize_t cdevBufferedSocket::transmit ( void )
|
||||
{
|
||||
int totalSent = 0;
|
||||
int parm = 0;
|
||||
int retval = 0;
|
||||
int retries = 0;
|
||||
|
||||
#ifndef WIN32
|
||||
void (*oldSig)(int) = signal(SIGPIPE, sigPipeHandler);
|
||||
#endif
|
||||
|
||||
setOption(IPPROTO_TCP, TCP_NODELAY, &parm, sizeof(parm));
|
||||
|
||||
if(activeOut.isEmpty())
|
||||
{
|
||||
if(!waitingOut.isEmpty())
|
||||
{
|
||||
activeOut.enqueue(waitingOut);
|
||||
headerXfrLen = 0;
|
||||
dataXfrLen = 0;
|
||||
outboundHeader[0] = htonl(magicNumber);
|
||||
outboundHeader[1] = htonl(activeOut.getSize()+sizeof(size_t));
|
||||
outboundHeader[2] = htonl(activeOut.getCount());
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
while(headerXfrLen<12 && retries<RETRYCNT && retval>=0)
|
||||
{
|
||||
retval = send(((char *)outboundHeader)+headerXfrLen, 12-headerXfrLen);
|
||||
if(retval>=0)
|
||||
{
|
||||
retries = retval?0:retries+1;
|
||||
headerXfrLen += retval;
|
||||
totalSent += retval;
|
||||
}
|
||||
}
|
||||
|
||||
while(headerXfrLen>=12 && retries<RETRYCNT && retval>=0 && !activeOut.isEmpty())
|
||||
{
|
||||
cdevStreamNode * node = activeOut.dequeue();
|
||||
|
||||
while(dataXfrLen<4 && retries<RETRYCNT && retval>=0)
|
||||
{
|
||||
parm = htonl(node->getLen());
|
||||
retval = send(((char *)&parm)+dataXfrLen, 4-dataXfrLen);
|
||||
if(retval>=0)
|
||||
{
|
||||
retries = retval?0:retries+1;
|
||||
dataXfrLen += retval;
|
||||
totalSent += retval;
|
||||
}
|
||||
}
|
||||
|
||||
while(dataXfrLen>=4 && dataXfrLen<node->getLen()+4 && retries<RETRYCNT && retval>=0)
|
||||
{
|
||||
retval = send(node->getBuf()+(dataXfrLen-4), node->getLen()-(dataXfrLen-4));
|
||||
if(retval>=0)
|
||||
{
|
||||
retries = retval?0:retries+1;
|
||||
dataXfrLen += retval;
|
||||
totalSent += retval;
|
||||
}
|
||||
}
|
||||
|
||||
if(dataXfrLen<node->getLen()+4) activeOut.poke(node);
|
||||
else {
|
||||
if(deleteFlag) delete node;
|
||||
dataXfrLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
parm = 1;
|
||||
setOption(IPPROTO_TCP, TCP_NODELAY, &parm, sizeof(parm));
|
||||
|
||||
#ifndef WIN32
|
||||
signal(SIGPIPE, oldSig);
|
||||
#endif
|
||||
|
||||
return retval>=0?totalSent:-1;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevBufferedSocket::receive :
|
||||
// * This method will attempt to receive as many packets as immediately
|
||||
// * possible from the socket into the waitingIn cdevStreamQueue. The
|
||||
// * function will cease receiving when a complete transmission block
|
||||
// * (multiple packets) have been received or when the sender has failed
|
||||
// * to transmit data after a pre-specified number of retries.
|
||||
// *****************************************************************************
|
||||
ssize_t cdevBufferedSocket::receive ( void )
|
||||
{
|
||||
int totalRecv = 0;
|
||||
int parm = 0;
|
||||
int retval = 0;
|
||||
int retries = 0;
|
||||
size_t packetCnt = 0;
|
||||
|
||||
while(headerRcvLen<12 && retries<RETRYCNT && retval>=0)
|
||||
{
|
||||
if((retval = recv(((char *)inboundHeader)+headerRcvLen, 12-headerRcvLen))==0)
|
||||
{
|
||||
int errCode = GetSocketErrno();
|
||||
|
||||
if(errCode!=EWOULDBLOCK && errCode!=EAGAIN) retval = -1;
|
||||
else retries++;
|
||||
}
|
||||
else if(retval>=0)
|
||||
{
|
||||
retries = retval?0:retries+1;
|
||||
headerRcvLen += retval;
|
||||
totalRecv += retval;
|
||||
}
|
||||
if(headerRcvLen>=12)
|
||||
{
|
||||
inboundHeader[0] = ntohl(inboundHeader[0]);
|
||||
inboundHeader[1] = ntohl(inboundHeader[1]);
|
||||
inboundHeader[2] = ntohl(inboundHeader[2]);
|
||||
|
||||
if(inboundHeader[0]!=magicNumber) retval=-1;
|
||||
}
|
||||
}
|
||||
|
||||
while(headerRcvLen>=12 && retries<RETRYCNT && retval>=0 &&
|
||||
inboundHeader[1]>0 && inboundHeader[2]>0)
|
||||
{
|
||||
while(dataRcvLen<4 && retries<RETRYCNT && retval>=0)
|
||||
{
|
||||
if((retval = recv(((char *)&subPacketLen)+dataRcvLen, 4-dataRcvLen))==0)
|
||||
{
|
||||
int errCode = GetSocketErrno();
|
||||
|
||||
if(errCode!=EWOULDBLOCK && errCode!=EAGAIN) retval = -1;
|
||||
else retries++;
|
||||
}
|
||||
else if(retval>0)
|
||||
{
|
||||
retries = 0;
|
||||
dataRcvLen += retval;
|
||||
totalRecv += retval;
|
||||
inboundHeader[1]-=retval;
|
||||
}
|
||||
if(dataRcvLen>=4)
|
||||
{
|
||||
subPacketLen = ntohl(subPacketLen);
|
||||
rcvNode = nodeFactory->newNode(subPacketLen);
|
||||
memset(rcvNode->getBuf(), rcvNode->getLen(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
while(dataRcvLen>=4 && dataRcvLen<rcvNode->getLen()+4 && retries<RETRYCNT && retval>=0)
|
||||
{
|
||||
if((retval = recv(rcvNode->getBuf()+(dataRcvLen-4), rcvNode->getLen()-(dataRcvLen-4)))==0)
|
||||
{
|
||||
int errCode = GetSocketErrno();
|
||||
|
||||
if(errCode!=EWOULDBLOCK && errCode!=EAGAIN) retval = -1;
|
||||
else retries++;
|
||||
}
|
||||
else if(retval>=0)
|
||||
{
|
||||
retries = 0;
|
||||
dataRcvLen += retval;
|
||||
totalRecv += retval;
|
||||
inboundHeader[1]-=retval;
|
||||
}
|
||||
if(dataRcvLen>=(rcvNode->getLen()+4))
|
||||
{
|
||||
waitingIn.enqueue(rcvNode);
|
||||
rcvNode = NULL;
|
||||
dataRcvLen = 0;
|
||||
subPacketLen = 0;
|
||||
inboundHeader[2]--;
|
||||
}
|
||||
}
|
||||
if(inboundHeader[1]<=0 || inboundHeader[2]<=0)
|
||||
{
|
||||
if(rcvNode) // Only received a partial packet on final entry
|
||||
{
|
||||
delete rcvNode;
|
||||
rcvNode = NULL;
|
||||
retval = -1;
|
||||
}
|
||||
headerRcvLen = 0;
|
||||
dataRcvLen = 0;
|
||||
inboundHeader[0]=(inboundHeader[1]=(inboundHeader[2]=0));
|
||||
}
|
||||
}
|
||||
return retval>=0?totalRecv:-1;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevBufferedSocket::getBlockingSemantics :
|
||||
// * Identifies the cdevBufferedSocket object as a NON-BLOCKING entity.
|
||||
// *****************************************************************************
|
||||
int cdevBufferedSocket::getBlockingSemantics ( void ) const
|
||||
{
|
||||
return O_NONBLOCK;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevBufferedSocket::getRcvBufferSize :
|
||||
// * This method is called during the configureHandle method to obtain the
|
||||
// * size of the receive buffer that will be used by the socket. This class
|
||||
// * returns the value 56000 - telling the cdevSocketStream to set the
|
||||
// * receive buffer size to 56 kilobytes.
|
||||
// *****************************************************************************
|
||||
int cdevBufferedSocket::getRcvBufferSize ( void ) const
|
||||
{
|
||||
return 56000;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevBufferedSocket::getSndBufferSize :
|
||||
// * This method is called during the configureHandle method to obtain the
|
||||
// * size of the send buffer that will be used by the socket. This class
|
||||
// * returns the value 56000 - telling the cdevSocketStream to set the
|
||||
// * send buffer size to 56 kilobytes.
|
||||
// *****************************************************************************
|
||||
int cdevBufferedSocket::getSndBufferSize ( void ) const
|
||||
{
|
||||
return 56000;
|
||||
}
|
||||
114
extensions/cdevGenericServer/cdevReactor/cdevBufferedSocket.h
Executable file
114
extensions/cdevGenericServer/cdevReactor/cdevBufferedSocket.h
Executable file
@@ -0,0 +1,114 @@
|
||||
#ifndef _CDEV_BUFFERED_SOCKET_H_
|
||||
#define _CDEV_BUFFERED_SOCKET_H_
|
||||
|
||||
#include "cdevSocketConnector.h"
|
||||
#include "cdevStreamQueue.h"
|
||||
|
||||
class cdevBufferedSocket : public cdevSocketConnector, public cdevNodeFactory
|
||||
{
|
||||
private:
|
||||
cdevNodeFactory * nodeFactory;
|
||||
|
||||
int magicNumber;
|
||||
int deleteFlag;
|
||||
|
||||
cdevStreamQueue activeOut;
|
||||
cdevStreamQueue waitingOut;
|
||||
int outboundHeader[3];
|
||||
size_t headerXfrLen;
|
||||
size_t dataXfrLen;
|
||||
|
||||
cdevStreamQueue waitingIn;
|
||||
cdevStreamNode * rcvNode;
|
||||
int inboundHeader[3];
|
||||
size_t headerRcvLen;
|
||||
size_t dataRcvLen;
|
||||
size_t subPacketLen;
|
||||
|
||||
static void sigPipeHandler (int);
|
||||
|
||||
public:
|
||||
enum {RETRYCNT = 1000 };
|
||||
|
||||
inline cdevBufferedSocket ( int MagicNumber=0, int deleteNodes = 1, cdevNodeFactory * factory=NULL );
|
||||
|
||||
inline int outboundReady ( void );
|
||||
inline int inboundReady ( void );
|
||||
inline void enqueueOutbound ( cdevStreamNode * node );
|
||||
inline cdevStreamNode * dequeueInbound ( void );
|
||||
|
||||
cdevStreamNode * newNode ( ssize_t size );
|
||||
ssize_t transmit ( void );
|
||||
ssize_t receive ( void );
|
||||
|
||||
int getBlockingSemantics ( void ) const;
|
||||
int getRcvBufferSize ( void ) const;
|
||||
int getSndBufferSize ( void ) const;
|
||||
};
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevBufferedSocket::cdevBufferedSocket :
|
||||
// * This is the constructor for the cdevBufferedSocket, it will initialize
|
||||
// * all internal variables and sub-classes.
|
||||
// *****************************************************************************
|
||||
inline cdevBufferedSocket::cdevBufferedSocket ( int MagicNumber, int deleteNodes, cdevNodeFactory * factory )
|
||||
: nodeFactory(factory),
|
||||
magicNumber(MagicNumber),
|
||||
deleteFlag (deleteNodes),
|
||||
activeOut(deleteNodes),
|
||||
waitingOut(deleteNodes),
|
||||
headerXfrLen(0),
|
||||
dataXfrLen(0),
|
||||
waitingIn(),
|
||||
rcvNode(NULL),
|
||||
headerRcvLen(0),
|
||||
dataRcvLen(0),
|
||||
subPacketLen(0)
|
||||
{
|
||||
if(nodeFactory==NULL) nodeFactory=this;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevBufferedSocket::outboundReady :
|
||||
// * This method returns an integer value indicating that outbound data is
|
||||
// * ready for transmission.
|
||||
// *****************************************************************************
|
||||
inline int cdevBufferedSocket::outboundReady ( void )
|
||||
{
|
||||
return !(activeOut.isEmpty() && waitingOut.isEmpty());
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevBufferedSocket::inboundReady :
|
||||
// * This method returns a flag indicating that inbound data is ready to be
|
||||
// * dequeued and processed.
|
||||
// *****************************************************************************
|
||||
inline int cdevBufferedSocket::inboundReady ( void )
|
||||
{
|
||||
return !(waitingIn.isEmpty() && headerRcvLen==0);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevBufferedSocket::enqueueOutbound :
|
||||
// * This method places the user defined cdevStreamNode pointer into the
|
||||
// * waitingOut object.
|
||||
// *****************************************************************************
|
||||
inline void cdevBufferedSocket::enqueueOutbound ( cdevStreamNode * node )
|
||||
{
|
||||
waitingOut.enqueue(node);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevBufferedSocket::dequeueInbound :
|
||||
// * This method dequeues the next available cdevStreamNode object from the
|
||||
// * waitingIn object.
|
||||
// *****************************************************************************
|
||||
inline cdevStreamNode * cdevBufferedSocket::dequeueInbound ( void )
|
||||
{
|
||||
return waitingIn.dequeue();
|
||||
}
|
||||
|
||||
|
||||
#endif /* _CDEV_BUFFERED_SOCKET_H_ */
|
||||
96
extensions/cdevGenericServer/cdevReactor/cdevEventHandler.cc
Executable file
96
extensions/cdevGenericServer/cdevReactor/cdevEventHandler.cc
Executable file
@@ -0,0 +1,96 @@
|
||||
#include "cdevReactor.h"
|
||||
#include "cdevEventHandler.h"
|
||||
#include <math.h>
|
||||
|
||||
cdevEventHandler::cdevEventHandler ( void )
|
||||
: mask(0),
|
||||
next(NULL),
|
||||
timeoutRate(0, 0),
|
||||
nextTimeout(0, 0),
|
||||
reactor(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
cdevEventHandler::~cdevEventHandler ( void )
|
||||
{
|
||||
if(reactor!=NULL) reactor->extractHandler(this);
|
||||
handleClose();
|
||||
}
|
||||
|
||||
void cdevEventHandler::setHandle ( int )
|
||||
{
|
||||
}
|
||||
|
||||
int cdevEventHandler::getHandle ( void ) const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void cdevEventHandler::setReactor (cdevReactor * r)
|
||||
{
|
||||
reactor = r;
|
||||
}
|
||||
|
||||
|
||||
cdevEventHandler * cdevEventHandler::getNext (void )
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
|
||||
void cdevEventHandler::setNext (cdevEventHandler * n)
|
||||
{
|
||||
next = n;
|
||||
}
|
||||
|
||||
|
||||
int cdevEventHandler::getMask ( void )
|
||||
{
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
cdevReactor * cdevEventHandler::getReactor ( void )
|
||||
{
|
||||
return reactor;
|
||||
}
|
||||
|
||||
|
||||
cdevTime & cdevEventHandler::getTimeoutRate ( void )
|
||||
{
|
||||
return timeoutRate;
|
||||
}
|
||||
|
||||
cdevTime & cdevEventHandler::getNextTimeout ( void )
|
||||
{
|
||||
return nextTimeout;
|
||||
}
|
||||
|
||||
|
||||
void cdevEventHandler::setMask ( unsigned Mask )
|
||||
{
|
||||
mask = (Mask&(READ_MASK|WRITE_MASK|EXCEPT_MASK|DONT_CALL));
|
||||
}
|
||||
|
||||
|
||||
void cdevEventHandler::setTimeoutRate ( cdevTime time )
|
||||
{
|
||||
timeoutRate = time;
|
||||
resetTimer();
|
||||
}
|
||||
|
||||
|
||||
void cdevEventHandler::resetTimer ( void )
|
||||
{
|
||||
nextTimeout.setTime();
|
||||
nextTimeout = nextTimeout+getTimeoutRate();
|
||||
}
|
||||
|
||||
int cdevEventHandler::handleInput ( void ) { return 0; }
|
||||
int cdevEventHandler::handleOutput ( void ) { return 0; }
|
||||
int cdevEventHandler::handleExcept ( void ) { return 0; }
|
||||
int cdevEventHandler::handleTimeout ( void ) { return 0; }
|
||||
int cdevEventHandler::handleSignal ( void ) { return -1; }
|
||||
int cdevEventHandler::handleClose ( void ) { return 0; }
|
||||
|
||||
54
extensions/cdevGenericServer/cdevReactor/cdevEventHandler.h
Executable file
54
extensions/cdevGenericServer/cdevReactor/cdevEventHandler.h
Executable file
@@ -0,0 +1,54 @@
|
||||
#ifndef _CDEV_EVENT_HANDLER_H_
|
||||
#define _CDEV_EVENT_HANDLER_H_ 1
|
||||
|
||||
#include "cdevTime.h"
|
||||
|
||||
class CDEV_REACTOR_API cdevEventHandler
|
||||
{
|
||||
friend class cdevReactor;
|
||||
|
||||
public:
|
||||
enum {
|
||||
READ_MASK = 0x01,
|
||||
EXCEPT_MASK = 0x02,
|
||||
WRITE_MASK = 0x04,
|
||||
DONT_CALL = 0x100
|
||||
} REACTOR_MASK;
|
||||
|
||||
private:
|
||||
void setReactor (cdevReactor * r);
|
||||
cdevEventHandler * getNext (void );
|
||||
void setNext (cdevEventHandler * n);
|
||||
cdevTime & getNextTimeout (void);
|
||||
|
||||
protected:
|
||||
cdevEventHandler * next;
|
||||
cdevTime nextTimeout;
|
||||
cdevReactor * reactor;
|
||||
cdevTime timeoutRate;
|
||||
int mask;
|
||||
|
||||
public:
|
||||
cdevEventHandler ( void );
|
||||
virtual ~cdevEventHandler ( void );
|
||||
|
||||
virtual void setMask ( unsigned Mask );
|
||||
virtual void setHandle ( int handle );
|
||||
virtual int getHandle ( void ) const;
|
||||
virtual int getMask ( void );
|
||||
virtual cdevReactor * getReactor ( void );
|
||||
|
||||
virtual cdevTime & getTimeoutRate ( void );
|
||||
virtual void setTimeoutRate ( cdevTime time );
|
||||
virtual void resetTimer ( void );
|
||||
|
||||
virtual int handleInput ( void );
|
||||
virtual int handleOutput ( void );
|
||||
virtual int handleExcept ( void );
|
||||
virtual int handleTimeout ( void );
|
||||
virtual int handleSignal ( void );
|
||||
virtual int handleClose ( void );
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
304
extensions/cdevGenericServer/cdevReactor/cdevHandleSet.cc
Normal file
304
extensions/cdevGenericServer/cdevReactor/cdevHandleSet.cc
Normal file
@@ -0,0 +1,304 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 1994,1995 Southeastern Universities Research Association,
|
||||
// Continuous Electron Beam Accelerator Facility
|
||||
//
|
||||
// This software was developed under a United States Government license
|
||||
// described in the NOTICE file included as part of this distribution.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Description:
|
||||
// FD_Set Wrapper Based on ACE
|
||||
//
|
||||
|
||||
#include "cdevHandleSet.h"
|
||||
|
||||
#ifndef __VMS
|
||||
#ifndef __linux
|
||||
extern "C" bzero (char *, int);
|
||||
#endif
|
||||
#else
|
||||
extern "C" bzero (char *, unsigned int);
|
||||
#endif
|
||||
|
||||
#if defined(__VMS) && defined(_TGV_MULTINET)
|
||||
// *********************************************************************
|
||||
// * Unfortunately when you use TGV Multinet, the bit offsets in the
|
||||
// * file * descriptor bitmasks used by select() cannot be found by
|
||||
// * simply using the value of the file descriptor. Fortunately, there
|
||||
// * is a simple relationship between the file descriptor value and the
|
||||
// * desired bit offset.
|
||||
// * (These macros are required because this file accesses the file
|
||||
// * descriptor bitmasks directly, without using the FD_SET(), FD_CLR(),
|
||||
// * FD_ISSSET() macros).
|
||||
// *********************************************************************
|
||||
#define FD_TO_BIT_OFFSET( fd ) ((fd)/CHANNELSIZE)
|
||||
#define FD_FROM_BIT_OFFSET( ibit ) ((ibit)*CHANNELSIZE)
|
||||
#else
|
||||
// *********************************************************************
|
||||
// * Under most operating systems the file descriptor value and the
|
||||
// * associated bit offset are one and the same.
|
||||
// *********************************************************************
|
||||
#define FD_TO_BIT_OFFSET( fd ) (fd)
|
||||
#define FD_FROM_BIT_OFFSET( ibit ) (ibit)
|
||||
#endif
|
||||
|
||||
#ifdef CDEV_HAS_UNDERSCORE_FDBITS
|
||||
#define fds_bits __fds_bits
|
||||
#endif
|
||||
|
||||
inline int BIT_ENABLED (unsigned long word, int bit = 1) { return (word & bit) != 0; }
|
||||
inline int BIT_DISABLED (unsigned long word, int bit = 1) { return (word & bit) == 0; }
|
||||
inline void SET_BIT (unsigned long &word, int bit) { word |= bit; }
|
||||
inline void CLR_BIT (unsigned long &word, int bit) { word &= ~bit; }
|
||||
|
||||
const char cdevHandleSet::nbits_[256] =
|
||||
{
|
||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
|
||||
};
|
||||
|
||||
// *****************************************************************************
|
||||
// * Counts the number of bits enabled in N. Uses a table lookup to speed up
|
||||
// * the count.
|
||||
// *****************************************************************************
|
||||
|
||||
int cdevHandleSet::count_bits (unsigned long n) const
|
||||
{
|
||||
return (cdevHandleSet::nbits_[n & 0xff] + cdevHandleSet::nbits_[(n >> 8) & 0xff] +
|
||||
cdevHandleSet::nbits_[(n >> 16) & 0xff] + cdevHandleSet::nbits_[n >> 24]);
|
||||
}
|
||||
|
||||
void cdevHandleSetIterator::operator++ (void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
this->index_++;
|
||||
#else
|
||||
this->val_ = (this->val_ >> 1) & cdevHandleSet::MSB_MASK;
|
||||
this->num_++;
|
||||
|
||||
if (this->val_ == 0)
|
||||
{
|
||||
for (this->index_++;
|
||||
this->index_ < cdevHandleSet::NUM_WORDS && fds_.mask_.fds_bits[this->index_] == 0;
|
||||
this->index_++);
|
||||
|
||||
if (this->index_ == cdevHandleSet::NUM_WORDS)
|
||||
{
|
||||
this->num_ = fds_.max_handle_ + 1;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->val_ = fds_.mask_.fds_bits[this->index_];
|
||||
this->num_ = this->index_ * cdevHandleSet::WORD_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
for (; BIT_DISABLED (this->val_); this->num_++)
|
||||
this->val_ = (this->val_ >> 1) & cdevHandleSet::MSB_MASK;
|
||||
#endif
|
||||
}
|
||||
|
||||
cdevHandleSetIterator::cdevHandleSetIterator (cdevHandleSet &f)
|
||||
: fds_ (f), index_ (0), num_ (f.size_ == 0 ? f.max_handle_ + 1 : 0)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
for (; fds_.mask_.fds_bits[this->index_] == 0; this->index_++)
|
||||
this->num_ += cdevHandleSet::WORD_SIZE;
|
||||
|
||||
for (this->val_ = this->fds_.mask_.fds_bits[this->index_];
|
||||
(BIT_DISABLED (this->val_)) && this->num_ < cdevHandleSet::MAX_SIZE;
|
||||
this->num_++)
|
||||
this->val_ = (this->val_ >> 1) & cdevHandleSet::MSB_MASK;
|
||||
#endif
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * Synchronize the underlying FD_SET with the MAX_FD and the SIZE.
|
||||
// *****************************************************************************
|
||||
void cdevHandleSet::sync (int max)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
this->size_ = 0;
|
||||
|
||||
for (int i = max / cdevHandleSet::WORD_SIZE; i >= 0; i--)
|
||||
this->size_ += count_bits (this->mask_.fds_bits[i]);
|
||||
|
||||
this->set_max (max);
|
||||
#endif
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * Resets the MAX_FD after a clear of the original MAX_FD.
|
||||
// *****************************************************************************
|
||||
void cdevHandleSet::set_max (int current_max)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
int i = 0;
|
||||
|
||||
if (this->size_ == 0)
|
||||
this->max_handle_ = -1;
|
||||
else
|
||||
{
|
||||
for (i = current_max / cdevHandleSet::WORD_SIZE;
|
||||
this->mask_.fds_bits[i] == 0;
|
||||
i--)
|
||||
;
|
||||
|
||||
this->max_handle_ = i * cdevHandleSet::WORD_SIZE;
|
||||
for (fd_mask val = this->mask_.fds_bits[i];
|
||||
(val & ~1) != 0;
|
||||
val = (val >> 1) & cdevHandleSet::MSB_MASK)
|
||||
this->max_handle_++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * Debugging method that prints out the underlying mask.
|
||||
// *****************************************************************************
|
||||
int cdevHandleSet::asciiDump (FILE * fp)
|
||||
{
|
||||
fprintf(fp, "[ ");
|
||||
for (int i = 0; i < this->max_handle_ + 1; i++)
|
||||
if (this->is_set (i))
|
||||
fprintf(fp," %d ", i);
|
||||
|
||||
fprintf(fp, " ]");
|
||||
return this->size_;
|
||||
}
|
||||
|
||||
void cdevHandleSet::reset (void)
|
||||
{
|
||||
this->max_handle_ = -1;
|
||||
this->size_ = 0;
|
||||
FD_ZERO (&this->mask_);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * Constructor, initializes the bitmask to all 0s.
|
||||
// *****************************************************************************
|
||||
cdevHandleSet::cdevHandleSet (void)
|
||||
{
|
||||
this->reset ();
|
||||
}
|
||||
|
||||
cdevHandleSet::cdevHandleSet (const fd_set &fd_mask): size_ (0)
|
||||
{
|
||||
memcpy ((void *) &this->mask_, (void *) &fd_mask, sizeof this->mask_);
|
||||
// sync is empty for WIN32
|
||||
this->sync (FD_SETSIZE);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * Returns the number of the large bit.
|
||||
// *****************************************************************************
|
||||
int cdevHandleSet::max_set (void) const
|
||||
{
|
||||
return this->max_handle_;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * Checks whether FD is enabled.
|
||||
// *****************************************************************************
|
||||
int cdevHandleSet::is_set (int fd) const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return FD_ISSET ((SOCKET)fd, &this->mask_);
|
||||
#else
|
||||
return FD_ISSET (fd, &this->mask_);
|
||||
#endif
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * Enables the FD.
|
||||
// *****************************************************************************
|
||||
void cdevHandleSet::set_bit (int fd)
|
||||
{
|
||||
if (!this->is_set (fd))
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FD_SET ((SOCKET)fd, &this->mask_);
|
||||
#else
|
||||
FD_SET (fd, &this->mask_);
|
||||
this->size_++;
|
||||
// *****************************************************
|
||||
// * again VMS system has different idea
|
||||
// *****************************************************
|
||||
#if defined(__VMS) && defined(_TGV_MULTINET)
|
||||
if (FD_TO_BIT_OFFSET(fd) > this->max_handle_)
|
||||
this->max_handle_ = FD_TO_BIT_OFFSET(fd);
|
||||
#else
|
||||
if (fd > this->max_handle_)
|
||||
this->max_handle_ = fd;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * Disables the FD.
|
||||
// *****************************************************************************
|
||||
void cdevHandleSet::clr_bit (int fd)
|
||||
{
|
||||
if (this->is_set (fd))
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FD_CLR ((SOCKET)fd, &this->mask_);
|
||||
#else
|
||||
FD_CLR (fd, &this->mask_);
|
||||
this->size_--;
|
||||
|
||||
#if defined(__VMS) && defined(_TGV_MULTINET)
|
||||
if (FD_TO_BIT_OFFSET(fd) == this->max_handle_)
|
||||
this->set_max (this->max_handle_);
|
||||
#else
|
||||
if (fd == this->max_handle_)
|
||||
this->set_max (this->max_handle_);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * Returns a count of the number of enabled bits.
|
||||
// *****************************************************************************
|
||||
int cdevHandleSet::num_set (void) const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return this->mask_.fd_count;
|
||||
#else
|
||||
return this->size_;
|
||||
#endif
|
||||
}
|
||||
|
||||
int cdevHandleSetIterator::operator () (void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return this->index_ < this->fds_.mask_.fd_count
|
||||
? fds_.mask_.fd_array[this->index_] : -1;
|
||||
#else
|
||||
#if defined(__VMS) && defined(_TGV_MULTINET)
|
||||
return FD_FROM_BIT_OFFSET(this->num_ <= this->fds_.max_handle_
|
||||
? this->num_ :-1);
|
||||
#else
|
||||
return this->num_ <= this->fds_.max_handle_
|
||||
? this->num_ : -1;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
87
extensions/cdevGenericServer/cdevReactor/cdevHandleSet.h
Normal file
87
extensions/cdevGenericServer/cdevReactor/cdevHandleSet.h
Normal file
@@ -0,0 +1,87 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 1994,1995 Southeastern Universities Research Association,
|
||||
// Continuous Electron Beam Accelerator Facility
|
||||
//
|
||||
// This software was developed under a United States Government license
|
||||
// described in the NOTICE file included as part of this distribution.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Description:
|
||||
// File Descriptor Mask Class (Based On ACE Handler_Set)
|
||||
|
||||
#ifndef _CDEV_HANDLE_SET_H_
|
||||
#define _CDEV_HANDLE_SET_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "cdevPlatforms.h"
|
||||
|
||||
class CDEV_REACTOR_API cdevHandleSet
|
||||
{
|
||||
friend class cdevHandleSetIterator;
|
||||
friend class cdevReactor;
|
||||
|
||||
public:
|
||||
cdevHandleSet (void);
|
||||
cdevHandleSet (const fd_set &mask);
|
||||
|
||||
void reset (void);
|
||||
int is_set (int) const;
|
||||
void set_bit (int);
|
||||
void clr_bit (int);
|
||||
int num_set (void) const;
|
||||
int max_set (void) const;
|
||||
int asciiDump (FILE * fp = stdout);
|
||||
void sync (int max = FD_SETSIZE);
|
||||
|
||||
operator fd_set *( void ) { return &mask_; }
|
||||
|
||||
private:
|
||||
int size_;
|
||||
int max_handle_;
|
||||
fd_set mask_;
|
||||
|
||||
enum {
|
||||
#ifdef _WIN32
|
||||
MAX_SIZE = FD_SETSIZE,
|
||||
#else
|
||||
MAX_SIZE = NOFILE,
|
||||
WORD_SIZE = NFDBITS,
|
||||
NUM_WORDS = howmany (NOFILE, NFDBITS),
|
||||
#ifdef __DECCXX
|
||||
MSB_MASK = ~(1U << (NFDBITS - 1))
|
||||
#elif defined(CDEV_HAS_64BIT_LONGS)
|
||||
MSB_MASK = ~(1UL << (NFDBITS - 1))
|
||||
#else
|
||||
MSB_MASK = ~(1 << (NFDBITS - 1))
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
int count_bits (unsigned long n) const;
|
||||
void set_max (int max);
|
||||
|
||||
static const char nbits_[256];
|
||||
};
|
||||
|
||||
class CDEV_REACTOR_API cdevHandleSetIterator
|
||||
{
|
||||
public:
|
||||
cdevHandleSetIterator (cdevHandleSet &);
|
||||
int operator ()(void);
|
||||
void operator++ (void);
|
||||
|
||||
private:
|
||||
cdevHandleSet &fds_;
|
||||
int num_;
|
||||
|
||||
#ifdef _WIN32
|
||||
unsigned int index_;
|
||||
#else
|
||||
int index_;
|
||||
fd_mask val_;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* _CDEV_HANDLE_SET_H_ */
|
||||
585
extensions/cdevGenericServer/cdevReactor/cdevReactor.cc
Executable file
585
extensions/cdevGenericServer/cdevReactor/cdevReactor.cc
Executable file
@@ -0,0 +1,585 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "cdevReactor.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// * This is the number of times that InitializeNetwork was called to perform
|
||||
// * network initialization. The InitializeNetwork and corresponding
|
||||
// * TerminateNetwork methods are wrappers to provide support for WIN32
|
||||
// * WSAStartup and WSACleanup methods. They perform no actiual function on
|
||||
// * UNIX platforms.
|
||||
// *****************************************************************************
|
||||
int cdevReactor::netInitCount = 0;
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevReactor::cdevReactor :
|
||||
// * This is the constructor for the cdevReactor class. It takes no
|
||||
// * arguments. It will set maxEntries to the value of the MAX_SIZE
|
||||
// * variable and the size variable (the highest fd installed) will be set
|
||||
// * to zero.
|
||||
// *
|
||||
// * The method will allocate space in the handlers array for the
|
||||
// * cdevEventHandlers that will be installed during operation. The
|
||||
// * read_set, write_set and except_set masks will be cleared. These masks
|
||||
// * will be populated later as file descriptors are added to the
|
||||
// * cdevReactor.
|
||||
// *****************************************************************************
|
||||
cdevReactor::cdevReactor ( void )
|
||||
: maxEntries(cdevHandleSet::MAX_SIZE),
|
||||
size (0),
|
||||
handlers (NULL),
|
||||
timers (NULL)
|
||||
{
|
||||
if(!netInitCount)
|
||||
{
|
||||
if(InitializeNetwork()==0) netInitCount++;
|
||||
}
|
||||
else netInitCount++;
|
||||
|
||||
handlers = (cdevEventHandler **)malloc((maxEntries+1)*sizeof(cdevEventHandler *));
|
||||
memset(handlers, 0, sizeof(cdevEventHandler *)*(maxEntries+1));
|
||||
read_set.reset();
|
||||
write_set.reset();
|
||||
except_set.reset();
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevReactor::~cdevReactor :
|
||||
// * This is the destructor for the cdevReactor class. It wil first remove
|
||||
// * all of the timer cdevEventHandlers from the timer array, it will then
|
||||
// * remove all of the file-descriptor based cdevEventHandlers from the
|
||||
// * handlers array. It will finish by deleteing the handlers array that
|
||||
// * was allocated in the constructor.
|
||||
// *****************************************************************************
|
||||
cdevReactor::~cdevReactor ( void )
|
||||
{
|
||||
if(netInitCount && (-netInitCount)==0) TerminateNetwork();
|
||||
|
||||
while(timers!=NULL) removeHandler(timers);
|
||||
for(int i=0; i<=maxEntries; i++)
|
||||
{
|
||||
if(handlers[i]!=NULL) removeHandler(handlers[i]);
|
||||
}
|
||||
delete handlers;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevReactor::calculateMask :
|
||||
// * This method will walk through the handlers array and setup the read_set,
|
||||
// * write_set and except_set masks.
|
||||
// *****************************************************************************
|
||||
void cdevReactor::calculateMask ( void )
|
||||
{
|
||||
int i;
|
||||
read_set.reset();
|
||||
write_set.reset();
|
||||
except_set.reset();
|
||||
size = 0;
|
||||
|
||||
for(i=0; i<=maxEntries; i++)
|
||||
{
|
||||
unsigned mask;
|
||||
if(handlers[i]!=NULL)
|
||||
{
|
||||
mask = handlers[i]->getMask();
|
||||
if(!(mask&cdevEventHandler::DONT_CALL))
|
||||
{
|
||||
if(mask&cdevEventHandler::READ_MASK)
|
||||
{
|
||||
read_set.set_bit(i);
|
||||
size = i+1;
|
||||
}
|
||||
if(mask&cdevEventHandler::WRITE_MASK)
|
||||
{
|
||||
write_set.set_bit(i);
|
||||
size = i+1;
|
||||
}
|
||||
if(mask&cdevEventHandler::EXCEPT_MASK)
|
||||
{
|
||||
except_set.set_bit(i);
|
||||
size = i+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevReactor::calculateTimeout :
|
||||
// * This method will walk through the timers and determine the duration of
|
||||
// * time that the cdevReactor should wait for events on the file
|
||||
// * descriptors before automatically terminating.
|
||||
// *****************************************************************************
|
||||
int cdevReactor::calculateTimeout ( cdevTime defaultPeriod, struct timeval &timeout )
|
||||
{
|
||||
if(defaultPeriod==cdevTime(0,0)) timeout.tv_sec=(timeout.tv_usec=0);
|
||||
else {
|
||||
cdevTime now;
|
||||
cdevTime target;
|
||||
cdevEventHandler * timer;
|
||||
|
||||
if(defaultPeriod<cdevTime(0,0)) defaultPeriod.setTime(60, 0);
|
||||
|
||||
now.setTime();
|
||||
target.setTime(now+defaultPeriod);
|
||||
|
||||
for(timer=timers; timer!=NULL && target>now; timer=timer->getNext())
|
||||
{
|
||||
cdevTime nextTimeout = timer->getNextTimeout();
|
||||
|
||||
if(!(timer->getMask()&cdevEventHandler::DONT_CALL) &&
|
||||
(double)nextTimeout > 0.0)
|
||||
{
|
||||
if(nextTimeout<target) target = nextTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
if(target<=now) timeout.tv_sec=(timeout.tv_usec=0);
|
||||
else timeout=target-now+(cdevTime)0.01;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevReactor::checkHandlers :
|
||||
// * This method is used to remove any cdevEventHandlers that have dead
|
||||
// * sockets from the cdevReactor prior to beginning I/O operations. The
|
||||
// * method calls select with all of the file handles installed. If select
|
||||
// * returns a -1, then each of the file handles is checked independently.
|
||||
// * When the bad handler is identified, its cdevEventHandler object will
|
||||
// * be elliminated.
|
||||
|
||||
// * This method returns the number of cdevEventHandlers that were deleted.
|
||||
// *****************************************************************************
|
||||
int cdevReactor::checkHandlers ( void )
|
||||
{
|
||||
int i;
|
||||
int eventCnt = 0;
|
||||
struct timeval t;
|
||||
|
||||
read_set.reset();
|
||||
write_set.reset();
|
||||
except_set.reset();
|
||||
t.tv_sec = 0;
|
||||
t.tv_usec = 0;
|
||||
|
||||
for(i=0; i<maxEntries; i++)
|
||||
{
|
||||
if(handlers[i]!=NULL)
|
||||
{
|
||||
read_set.set_bit(i);
|
||||
size = i+1;
|
||||
}
|
||||
}
|
||||
|
||||
if(cdevSelect(size, read_set, write_set, except_set, &t)<0)
|
||||
{
|
||||
for(i=0; i<maxEntries; i++)
|
||||
{
|
||||
if(handlers[i]!=NULL)
|
||||
{
|
||||
read_set.set_bit(i);
|
||||
|
||||
if(cdevSelect(i, read_set, write_set, except_set, &t)<0)
|
||||
{
|
||||
if(handlers[i]->handleSignal()<0)
|
||||
{
|
||||
removeHandler(handlers[i]);
|
||||
eventCnt++;
|
||||
}
|
||||
}
|
||||
read_set.clr_bit(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return eventCnt;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevReactor::registerHandler :
|
||||
// * This method is called to register a file-descriptor based
|
||||
// * cdevEventHandler with the reactor. It will first check the validity
|
||||
// * of the handler and its file descriptor. It will then determine if
|
||||
// * another handler already occupies the position associated with the
|
||||
// * specified handle.
|
||||
// *
|
||||
// * If the handler is valid, it will install it in the handlers array and
|
||||
// * will add it to the read_set, write_set and except_set masks as
|
||||
// * required. The size variable will be incremented if the new handler
|
||||
// * has the highest file-descriptor in the array.
|
||||
// *****************************************************************************
|
||||
int cdevReactor::registerHandler ( cdevEventHandler * handler, unsigned mask )
|
||||
{
|
||||
int fd = -1;
|
||||
REACTOR_RESULT result = SUCCESS;
|
||||
|
||||
if(handler == NULL)
|
||||
{
|
||||
result = INVALID_HANDLER;
|
||||
}
|
||||
else if(handler->getReactor()!=NULL && handler->getReactor()!=this)
|
||||
{
|
||||
result = UNKNOWN_HANDLER;
|
||||
}
|
||||
else if((fd = handler->getHandle())<=0)
|
||||
{
|
||||
result = INVALID_HANDLE;
|
||||
}
|
||||
else if(fd<maxEntries && handlers[handler->getHandle()]!=NULL)
|
||||
{
|
||||
result = HANDLE_EXISTS;
|
||||
}
|
||||
else {
|
||||
if(fd>=maxEntries)
|
||||
{
|
||||
int oldMaxEntries = maxEntries;
|
||||
maxEntries = fd+1;
|
||||
handlers = (cdevEventHandler **)realloc(handlers, (maxEntries+1) * sizeof(cdevEventHandler *));
|
||||
memset(&handlers[oldMaxEntries], 0, sizeof(cdevEventHandler *)*((maxEntries+1)-oldMaxEntries));
|
||||
}
|
||||
handler->setReactor(this);
|
||||
handler->setMask (mask);
|
||||
handlers[fd] = handler;
|
||||
}
|
||||
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevReactor::removeHandler :
|
||||
// * This method allows the caller to remove an cdevEventHandler from the
|
||||
// * cdevReactor and delete it. The method will call the extractHandler
|
||||
// * method to remove the cdevEventHandler from the cdevReactor after which
|
||||
// * the handler will be deleted.
|
||||
// *****************************************************************************
|
||||
int cdevReactor::removeHandler ( cdevEventHandler * handler )
|
||||
{
|
||||
REACTOR_RESULT result = INVALID_HANDLER;
|
||||
if(handler!=NULL)
|
||||
{
|
||||
extractHandler(handler);
|
||||
delete handler;
|
||||
result = SUCCESS;
|
||||
}
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevReactor::removeHandler :
|
||||
// * This method will remove the specified handler using the file descriptor
|
||||
// * provided by the caller.
|
||||
// *****************************************************************************
|
||||
int cdevReactor::removeHandler ( int fd )
|
||||
{
|
||||
REACTOR_RESULT result = SUCCESS;
|
||||
|
||||
if(fd>0 && fd<=maxEntries)
|
||||
{
|
||||
result = (REACTOR_RESULT)removeHandler(handlers[fd]);
|
||||
}
|
||||
else result = INVALID_HANDLE;
|
||||
|
||||
return (int) result;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevReactor::extractHandler :
|
||||
// * This method will remove the specified cdevEventHandler from the
|
||||
// * cdevReactor, however, it will not delete the cdevEventHandler when
|
||||
// * finished.
|
||||
// *****************************************************************************
|
||||
int cdevReactor::extractHandler ( cdevEventHandler * handler )
|
||||
{
|
||||
int fd = -1;
|
||||
REACTOR_RESULT result = UNKNOWN_HANDLER;
|
||||
|
||||
if(handler == NULL) result = INVALID_HANDLER;
|
||||
else {
|
||||
cdevEventHandler * currTimer = timers;
|
||||
cdevEventHandler * prevTimer = NULL;
|
||||
|
||||
while(currTimer!=NULL && currTimer!=handler)
|
||||
{
|
||||
prevTimer = currTimer;
|
||||
currTimer = prevTimer->getNext();
|
||||
}
|
||||
|
||||
if(currTimer)
|
||||
{
|
||||
if(prevTimer) prevTimer->setNext(currTimer->getNext());
|
||||
else timers = currTimer->getNext();
|
||||
result = SUCCESS;
|
||||
}
|
||||
|
||||
if((fd = handler->getHandle())>=0 &&
|
||||
fd<=maxEntries &&
|
||||
handlers[fd]==handler)
|
||||
{
|
||||
handlers[fd] = NULL;
|
||||
result = SUCCESS;
|
||||
}
|
||||
else for(fd=0; fd<=maxEntries; fd++)
|
||||
{
|
||||
if(handlers[fd]==handler)
|
||||
{
|
||||
handlers[fd] = NULL;
|
||||
result = SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if(result==SUCCESS)
|
||||
{
|
||||
handler->setMask(0);
|
||||
handler->setReactor(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevReactor::getHandler :
|
||||
// * This method allows the caller to retrieve the cdevEventHandler
|
||||
// * associated with a specific file descriptor.
|
||||
// *****************************************************************************
|
||||
int cdevReactor::getHandler ( int fd, cdevEventHandler * & handler )
|
||||
{
|
||||
REACTOR_RESULT result = SUCCESS;
|
||||
|
||||
handler = NULL;
|
||||
|
||||
if(fd<=0 || fd>maxEntries) result = INVALID_HANDLE;
|
||||
else if((handler = handlers[fd])==NULL) result = INVALID_HANDLE;
|
||||
|
||||
return (int) result;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevReactor::registerTimer :
|
||||
// * This method will install a timer cdevEventHandler in the timers array.
|
||||
// * The handleTimeout method of this class will be called each time the
|
||||
// * timer expires. The timer's handleTimeout method will be called
|
||||
// * immediately, and then the timer will be set to expire at the next
|
||||
// * time period.
|
||||
// *****************************************************************************
|
||||
int cdevReactor::registerTimer ( cdevEventHandler * timer )
|
||||
{
|
||||
REACTOR_RESULT result = SUCCESS;
|
||||
|
||||
if(timer==NULL)
|
||||
{
|
||||
result = INVALID_HANDLER;
|
||||
}
|
||||
else if(timer->getReactor()!=NULL && timer->getReactor()!=this)
|
||||
{
|
||||
result = UNKNOWN_HANDLER;
|
||||
}
|
||||
else if((double)timer->getTimeoutRate()<=0.0)
|
||||
{
|
||||
result = INVALID_TIMEOUT;
|
||||
}
|
||||
else {
|
||||
timer->setReactor(this);
|
||||
timer->resetTimer();
|
||||
timer->setNext(timers);
|
||||
timers = timer;
|
||||
}
|
||||
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevReactor::cancelTimer :
|
||||
// * This method will remove the timer from the array of timers that are
|
||||
// * being serviced by the reactor, however, it will NOT delete the
|
||||
// * cdevEventHandler. Additionally, if the handler is also being used
|
||||
// * for file-descriptor based operations - it will be not be removed from
|
||||
// * that array.
|
||||
// *
|
||||
// * The user is responsible for deleteing the cdevEventHandler if it will
|
||||
// * no longer be needed.
|
||||
// *****************************************************************************
|
||||
int cdevReactor::cancelTimer ( cdevEventHandler * timer )
|
||||
{
|
||||
REACTOR_RESULT result = SUCCESS;
|
||||
|
||||
if(timer==NULL) result = INVALID_HANDLER;
|
||||
else
|
||||
{
|
||||
cdevEventHandler * currTimer = timers;
|
||||
cdevEventHandler * prevTimer = NULL;
|
||||
|
||||
while(currTimer!=NULL && currTimer!=timer)
|
||||
{
|
||||
prevTimer = currTimer;
|
||||
currTimer = prevTimer->getNext();
|
||||
}
|
||||
|
||||
if(currTimer)
|
||||
{
|
||||
if(prevTimer) prevTimer->setNext(currTimer->getNext());
|
||||
else timers = currTimer->getNext();
|
||||
currTimer->setNext(NULL);
|
||||
}
|
||||
else result = UNKNOWN_HANDLER;
|
||||
}
|
||||
|
||||
return (int)result;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevReactor::handleFileEvent :
|
||||
// * This method will process the events that have occurred on a single
|
||||
// * file descriptor. The caller must provide two arguments...
|
||||
// *
|
||||
// * fd_set * fds : The fd_set to be checked
|
||||
// * REACTOR_EVENT event : The type of event being processed...
|
||||
// * INPUT, OUTPUT, EXCEPTION, or SIGNAL.
|
||||
// *
|
||||
// * This method will return the number of events that have been processed
|
||||
// * to completion. Note that if a cdevEventHandler returns a value greater
|
||||
// * than 0, it will be called again after all other ready file descriptors
|
||||
// * have been called - therefore, its occurance will not be included in the
|
||||
// * number of events returned by this method.
|
||||
// *****************************************************************************
|
||||
int cdevReactor::handleFileEvent ( cdevHandleSet * fds, REACTOR_EVENT event)
|
||||
{
|
||||
int result = 0;
|
||||
int eventCnt = 0;
|
||||
int i;
|
||||
|
||||
for(i=0; i<=size; i++)
|
||||
{
|
||||
if(fds->is_set(i))
|
||||
{
|
||||
if(handlers[i])
|
||||
{
|
||||
if(event==INPUT) result = handlers[i]->handleInput();
|
||||
else if(event==OUTPUT) result = handlers[i]->handleOutput();
|
||||
else if(event==EXCEPTION) result = handlers[i]->handleExcept();
|
||||
else if(event==SIGNAL) result = handlers[i]->handleSignal();
|
||||
|
||||
if(result<=0)
|
||||
{
|
||||
if(result<0) removeHandler(handlers[i]);
|
||||
eventCnt++;
|
||||
fds->clr_bit(i);
|
||||
}
|
||||
}
|
||||
else eventCnt++;
|
||||
}
|
||||
}
|
||||
|
||||
return eventCnt;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevReactor::handleEvents :
|
||||
// * This method is called to allow the cdevReactor to wait for events to
|
||||
// * occur on the cdevEventHandler objects. This method will process events
|
||||
// * until the specified time period has expired - if a negative time period
|
||||
// * (or no time period) has been specified, then it will process messages
|
||||
// * until the next event occurs.
|
||||
// *
|
||||
// * The flags parameter was added to allow the caller to specify either
|
||||
// * UNTIL_TIMEOUT or UNTIL_EVENT. If the caller specifies UNTIL_TIMEOUT,
|
||||
// * the cdevReactor will continue to handle events until the time period
|
||||
// * has expired. If the caller specifies UNTIL_EVENT, the cdevReactor will
|
||||
// * return after the first SOCKET-BASED EVENT occurs or after the time
|
||||
// * expires, whichever comes first.
|
||||
// *
|
||||
// * Note: If the cdevEventHandler may return a -1, 0, or 1. These return
|
||||
// * codes will have the following effect.
|
||||
// *
|
||||
// * -1 : The cdevEventHandler will be removed from the cdevReactor
|
||||
// * and deleted.
|
||||
// * 0 : The bit associated with the cdevEventHandler will be
|
||||
// * cleared and processing will continue.
|
||||
// * 1 : The bit associated with the cdevEventHandler will not be
|
||||
// * cleared and it will be called to process more data after
|
||||
// * after all of the subsequent cdevEventHandlers have been
|
||||
// * called - this allows the cdevEventHandler in a lengthy
|
||||
// * process to yeild time back for processing other events.
|
||||
// *****************************************************************************
|
||||
int cdevReactor::handleEvents ( cdevTime period, int flags )
|
||||
{
|
||||
int result = 0;
|
||||
int finished = 0;
|
||||
cdevTime startTime, currTime;
|
||||
struct timeval timeout;
|
||||
|
||||
startTime.setTime();
|
||||
|
||||
do
|
||||
{
|
||||
int i;
|
||||
|
||||
calculateMask ();
|
||||
calculateTimeout(period, timeout);
|
||||
|
||||
result=cdevSelect(size, read_set, write_set, except_set, &timeout);
|
||||
|
||||
if(result<0)
|
||||
{
|
||||
finished = 1;
|
||||
checkHandlers();
|
||||
}
|
||||
else {
|
||||
if(result>0)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
||||
while(cnt<result)
|
||||
{
|
||||
cnt+=handleFileEvent(&read_set, INPUT);
|
||||
cnt+=handleFileEvent(&write_set, OUTPUT);
|
||||
cnt+=handleFileEvent(&except_set, EXCEPTION);
|
||||
}
|
||||
if(flags==UNTIL_EVENT && cnt>0) finished = 1;
|
||||
}
|
||||
|
||||
if(timers!=NULL)
|
||||
{
|
||||
cdevEventHandler * timer=timers;
|
||||
|
||||
currTime.setTime();
|
||||
|
||||
while(timer!=NULL)
|
||||
{
|
||||
cdevTime nextTimeout = timer->getNextTimeout();
|
||||
|
||||
if((timer->getMask()&cdevEventHandler::DONT_CALL)==0 &&
|
||||
(double)nextTimeout>0.0 && nextTimeout<=currTime)
|
||||
{
|
||||
if(timer->handleTimeout()<0)
|
||||
{
|
||||
cdevEventHandler *temp = timer->getNext();
|
||||
removeHandler(timer);
|
||||
timer = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
timer->resetTimer();
|
||||
timer = timer->getNext();
|
||||
}
|
||||
currTime.setTime();
|
||||
}
|
||||
else timer = timer->getNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currTime.setTime();
|
||||
period = period-(currTime-startTime);
|
||||
} while(!finished && period>cdevTime(0,0));
|
||||
|
||||
return result;
|
||||
}
|
||||
65
extensions/cdevGenericServer/cdevReactor/cdevReactor.h
Executable file
65
extensions/cdevGenericServer/cdevReactor/cdevReactor.h
Executable file
@@ -0,0 +1,65 @@
|
||||
#ifndef _CDEV_REACTOR_H_
|
||||
#define _CDEV_REACTOR_H_ 1
|
||||
|
||||
#include "cdevTime.h"
|
||||
#include "cdevHandleSet.h"
|
||||
#include "cdevEventHandler.h"
|
||||
|
||||
class CDEV_REACTOR_API cdevReactor
|
||||
{
|
||||
public:
|
||||
typedef enum {
|
||||
INPUT = 0,
|
||||
OUTPUT = 1,
|
||||
EXCEPTION = 2,
|
||||
SIGNAL = 3
|
||||
} REACTOR_EVENT;
|
||||
|
||||
typedef enum {
|
||||
REACTOR_ERROR = -1,
|
||||
SUCCESS = 0,
|
||||
INVALID_HANDLE = 1,
|
||||
INVALID_HANDLER = 2,
|
||||
HANDLE_EXISTS = 3,
|
||||
UNKNOWN_HANDLER = 4,
|
||||
INVALID_TIMEOUT = 5
|
||||
} REACTOR_RESULT;
|
||||
|
||||
typedef enum {
|
||||
UNTIL_TIMEOUT = 0,
|
||||
UNTIL_EVENT = 1
|
||||
} HANDLE_EVENT_FLAG;
|
||||
|
||||
protected:
|
||||
static int netInitCount;
|
||||
|
||||
int maxEntries;
|
||||
int size;
|
||||
cdevHandleSet read_set;
|
||||
cdevHandleSet write_set;
|
||||
cdevHandleSet except_set;
|
||||
cdevEventHandler ** handlers;
|
||||
cdevEventHandler * timers;
|
||||
|
||||
private:
|
||||
void calculateMask ( void );
|
||||
int calculateTimeout ( cdevTime defaultPeriod, struct timeval &timeout );
|
||||
int handleFileEvent ( cdevHandleSet * fds, REACTOR_EVENT event);
|
||||
public:
|
||||
cdevReactor ( void );
|
||||
virtual ~cdevReactor ( void );
|
||||
|
||||
virtual int checkHandlers ( void );
|
||||
virtual int registerHandler ( cdevEventHandler * handler, unsigned mask );
|
||||
virtual int removeHandler ( cdevEventHandler * handler );
|
||||
virtual int removeHandler ( int fd );
|
||||
virtual int extractHandler ( cdevEventHandler * handler );
|
||||
virtual int getHandler ( int fd, cdevEventHandler * &handler );
|
||||
|
||||
virtual int registerTimer ( cdevEventHandler * timer );
|
||||
virtual int cancelTimer ( cdevEventHandler * timer );
|
||||
|
||||
virtual int handleEvents ( cdevTime period = -1.0, int flags = UNTIL_TIMEOUT );
|
||||
};
|
||||
|
||||
#endif
|
||||
157
extensions/cdevGenericServer/cdevReactor/cdevSocket.cc
Normal file
157
extensions/cdevGenericServer/cdevReactor/cdevSocket.cc
Normal file
@@ -0,0 +1,157 @@
|
||||
#include "cdevSocket.h"
|
||||
|
||||
void cdevSocket::setHandle ( int fd )
|
||||
{
|
||||
handle = fd;
|
||||
}
|
||||
|
||||
|
||||
int cdevSocket::getHandle ( void ) const
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
int cdevSocket::open (int type, int protocol_family, int protocol)
|
||||
{
|
||||
setHandle(::socket(protocol_family, type, protocol));
|
||||
return getHandle();
|
||||
}
|
||||
|
||||
|
||||
int cdevSocket::close (void)
|
||||
{
|
||||
int result = ::close(getHandle());
|
||||
setHandle(INVALID_HANDLE);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int cdevSocket::unsetFlags ( int flags )
|
||||
{
|
||||
int retval = -1;
|
||||
int fd = getHandle();
|
||||
|
||||
if(fd!=cdevSocket::INVALID_HANDLE)
|
||||
{
|
||||
#ifdef WIN32
|
||||
if(flags==O_NONBLOCK)
|
||||
{
|
||||
unsigned long val = 0;
|
||||
retval = ::ioctlsocket(fd, FIONBIO, &val);
|
||||
}
|
||||
#else
|
||||
int val;
|
||||
if((val=::fcntl(fd, F_GETFL, 0)) != -1)
|
||||
{
|
||||
val &= ~flags;
|
||||
retval = (::fcntl(fd, F_SETFL, val)!=-1)?0:1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
int cdevSocket::setFlags ( int flags )
|
||||
{
|
||||
int retval = -1;
|
||||
int fd = getHandle();
|
||||
|
||||
if(fd!=cdevSocket::INVALID_HANDLE)
|
||||
{
|
||||
#ifdef WIN32
|
||||
if(flags==O_NONBLOCK)
|
||||
{
|
||||
unsigned long val = 1;
|
||||
retval = ::ioctlsocket(fd, FIONBIO, &val);
|
||||
}
|
||||
#else
|
||||
int val;
|
||||
if ((val=::fcntl(fd, F_GETFL, 0)) != -1)
|
||||
{
|
||||
val |= flags;
|
||||
if(::fcntl(fd, F_SETFL, val) != -1) retval = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
int cdevSocket::getFlags ( void )
|
||||
{
|
||||
int retval = -1;
|
||||
int fd = getHandle();
|
||||
|
||||
#ifdef WIN32
|
||||
retval = 0;
|
||||
#else
|
||||
if(fd!=cdevSocket::INVALID_HANDLE)
|
||||
{
|
||||
retval=::fcntl(fd, F_GETFL, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int cdevSocket::setOption (int level, int option, void *optval, int optlen) const
|
||||
{
|
||||
return ::setsockopt(getHandle(), level, option, (char *)optval, (SOCKOPT_SIZE_PARM)optlen);
|
||||
}
|
||||
|
||||
|
||||
int cdevSocket::getOption (int level, int option, void *optval, int *optlen) const
|
||||
{
|
||||
return ::getsockopt(getHandle(), level, option, (char *)optval, (SOCKOPT_SIZE_PARM *)optlen);
|
||||
}
|
||||
|
||||
|
||||
int cdevSocket::getLocalAddress (cdevAddr & addr)
|
||||
{
|
||||
int retval;
|
||||
int len=addr.getSize();
|
||||
|
||||
if(::getsockname(getHandle(), (sockaddr *)addr.getAddress(), (SOCKOPT_SIZE_PARM *)&len)==INVALID_HANDLE)
|
||||
{
|
||||
retval = INVALID_HANDLE;
|
||||
}
|
||||
else {
|
||||
addr.setSize(len);
|
||||
retval = 0;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
int cdevSocket::getRemoteAddress (cdevAddr & addr)
|
||||
{
|
||||
int retval;
|
||||
int len = addr.getSize();
|
||||
if(::getpeername(getHandle(), (sockaddr *)addr.getAddress(), (SOCKOPT_SIZE_PARM *)&len)==INVALID_HANDLE)
|
||||
{
|
||||
retval = INVALID_HANDLE;
|
||||
}
|
||||
else {
|
||||
addr.setSize(len);
|
||||
retval = 0;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
cdevSocket::cdevSocket ( void )
|
||||
: handle(INVALID_HANDLE)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
cdevSocket::cdevSocket(int type, int protocol_family, int protocol)
|
||||
: handle(INVALID_HANDLE)
|
||||
{
|
||||
setHandle(open(type, protocol_family, protocol));
|
||||
}
|
||||
|
||||
34
extensions/cdevGenericServer/cdevReactor/cdevSocket.h
Executable file
34
extensions/cdevGenericServer/cdevReactor/cdevSocket.h
Executable file
@@ -0,0 +1,34 @@
|
||||
#ifndef _CDEV_SOCKET_H_
|
||||
#define _CDEV_SOCKET_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include "cdevAddr.h"
|
||||
|
||||
class CDEV_REACTOR_API cdevSocket
|
||||
{
|
||||
protected:
|
||||
int handle;
|
||||
sockaddr_in sa;
|
||||
|
||||
cdevSocket(void);
|
||||
cdevSocket(int type, int protocol_family, int protocol=0);
|
||||
|
||||
public:
|
||||
enum {INVALID_HANDLE=-1};
|
||||
|
||||
void setHandle (int fd);
|
||||
int getHandle (void) const;
|
||||
int open (int type, int protocol_family, int protocol);
|
||||
int close (void);
|
||||
int unsetFlags (int flags);
|
||||
int setFlags (int flags);
|
||||
int getFlags (void);
|
||||
int setOption (int level, int option, void *optval, int optlen) const;
|
||||
int getOption (int level, int option, void *optval, int *optlen) const;
|
||||
int getLocalAddress (cdevAddr & address);
|
||||
int getRemoteAddress (cdevAddr & address);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "cdevSocketAcceptor.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSocketAcceptor::cdevSocketAcceptor :
|
||||
// * Do nothing routine for constructor.
|
||||
// *****************************************************************************
|
||||
cdevSocketAcceptor::cdevSocketAcceptor(void)
|
||||
{
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSocketAcceptor::open :
|
||||
// * General purpose routine for performing server cdevSocket creation.
|
||||
// *****************************************************************************
|
||||
int cdevSocketAcceptor::open
|
||||
(
|
||||
const cdevAddr &addr,
|
||||
int reuse_addr,
|
||||
int protocol_family,
|
||||
int backlog,
|
||||
int protocol,
|
||||
int reopen)
|
||||
{
|
||||
int one = 1;
|
||||
int retval;
|
||||
|
||||
if(reopen) cdevSocket::open(SOCK_STREAM, protocol_family, protocol);
|
||||
|
||||
if(this->getHandle() == cdevSocket::INVALID_HANDLE)
|
||||
{
|
||||
retval = cdevSocket::INVALID_HANDLE;
|
||||
close();
|
||||
}
|
||||
else {
|
||||
if(reuse_addr && setOption(SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == cdevSocket::INVALID_HANDLE)
|
||||
{
|
||||
close();
|
||||
}
|
||||
else if(::bind(getHandle(), (sockaddr *)addr.getAddress(),
|
||||
addr.getSize()) == cdevSocket::INVALID_HANDLE ||
|
||||
::listen(getHandle(), backlog) == cdevSocket::INVALID_HANDLE)
|
||||
{
|
||||
close();
|
||||
}
|
||||
retval = getHandle();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSocketAcceptor::cdevSocketAcceptor :
|
||||
// * General purpose routine for performing server cdevSocket creation.
|
||||
// *****************************************************************************
|
||||
cdevSocketAcceptor::cdevSocketAcceptor (
|
||||
const cdevAddr &addr,
|
||||
int reuse_addr,
|
||||
int protocol_family,
|
||||
int backlog,
|
||||
int protocol)
|
||||
: cdevSocket(SOCK_STREAM, protocol_family, protocol)
|
||||
{
|
||||
open(addr, reuse_addr, protocol_family, backlog, protocol, 0);
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSocketAcceptor::accept :
|
||||
// * General purpose routine for accepting new connections.
|
||||
// *****************************************************************************
|
||||
int cdevSocketAcceptor::accept(cdevSocketStream &new_stream, cdevAddr *addr) const
|
||||
{
|
||||
sockaddr *sock_addr=0;
|
||||
int *len_ptr=0;
|
||||
int len;
|
||||
int new_handle;
|
||||
|
||||
if(addr != 0)
|
||||
{
|
||||
len=addr->getSize();
|
||||
len_ptr= &len;
|
||||
sock_addr=(sockaddr *) addr->getAddress();
|
||||
}
|
||||
|
||||
do {
|
||||
new_handle=::accept(this->getHandle(), sock_addr, (SOCKOPT_SIZE_PARM *)len_ptr);
|
||||
} while(new_handle==cdevSocket::INVALID_HANDLE && errno==EINTR);
|
||||
|
||||
if(addr != 0) addr->setSize(*len_ptr);
|
||||
|
||||
new_stream.setHandle(new_handle);
|
||||
new_stream.configureHandle();
|
||||
|
||||
return new_handle;
|
||||
}
|
||||
32
extensions/cdevGenericServer/cdevReactor/cdevSocketAcceptor.h
Executable file
32
extensions/cdevGenericServer/cdevReactor/cdevSocketAcceptor.h
Executable file
@@ -0,0 +1,32 @@
|
||||
#ifndef _CDEV_SOCKET_ACCEPTOR_H_
|
||||
#define _CDEV_SOCKET_ACCEPTOR_H_
|
||||
|
||||
#include "cdevSocketStream.h"
|
||||
|
||||
class CDEV_REACTOR_API cdevSocketAcceptor : public cdevSocket
|
||||
{
|
||||
public:
|
||||
cdevSocketAcceptor(void);
|
||||
cdevSocketAcceptor(
|
||||
const cdevAddr &addr,
|
||||
int reuse_addr = 0,
|
||||
int protocol_family = PF_INET,
|
||||
int backlog = 5,
|
||||
int protocol = 0);
|
||||
|
||||
int open(const cdevAddr &addr,
|
||||
int reuse_addr = 0,
|
||||
int protocol_family = PF_INET,
|
||||
int backlog = 5,
|
||||
int protocol = 0,
|
||||
int reopen = 1);
|
||||
|
||||
int accept(
|
||||
cdevSocketStream &new_stream,
|
||||
cdevAddr *remote_addr=0) const;
|
||||
|
||||
private:
|
||||
int getRemoteAddress(cdevAddr &) const;
|
||||
};
|
||||
|
||||
#endif /* _CDEV_SOCKET_ACCEPTOR_H */
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "cdevSocketConnector.h"
|
||||
#include "cdevHandleSet.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSocketConnector::connect :
|
||||
// * Actively connect and produce a new cdevSocketStream if things go well...
|
||||
// *****************************************************************************
|
||||
int cdevSocketConnector::connect ( const cdevAddr & remote_addr )
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if(getHandle() == cdevSocket::INVALID_HANDLE &&
|
||||
cdevSocket::open(SOCK_STREAM, PF_INET, 0) == cdevSocket::INVALID_HANDLE)
|
||||
{
|
||||
retval = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
double secondsWaited = 0.0;
|
||||
sockaddr *addr=(sockaddr *) remote_addr.getAddress();
|
||||
size_t size=remote_addr.getSize();
|
||||
|
||||
if(configureHandle()<0)
|
||||
{
|
||||
retval = -1;
|
||||
}
|
||||
else if(::connect(getHandle(), addr, size) == cdevSocket::INVALID_HANDLE)
|
||||
{
|
||||
int errCode = GetSocketErrno();
|
||||
|
||||
if(getBlockingSemantics()==O_NONBLOCK && errCode==EINPROGRESS)
|
||||
{
|
||||
errCode=EWOULDBLOCK;
|
||||
}
|
||||
|
||||
if(errCode == EISCONN)
|
||||
{
|
||||
retval = 0;
|
||||
}
|
||||
else if(errCode != EWOULDBLOCK)
|
||||
{
|
||||
close();
|
||||
setHandle(cdevSocket::INVALID_HANDLE);
|
||||
retval = -1;
|
||||
}
|
||||
else {
|
||||
cdevHandleSet ws;
|
||||
cdevHandleSet es;
|
||||
struct timeval tv;
|
||||
int fd = getHandle();
|
||||
|
||||
ws.set_bit(fd);
|
||||
es.set_bit(fd);
|
||||
tv.tv_sec = 3;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if(cdevSelect(fd+1, NULL, ws, es, &tv)>0 && ws.is_set(fd)) retval = 0;
|
||||
else retval = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
12
extensions/cdevGenericServer/cdevReactor/cdevSocketConnector.h
Executable file
12
extensions/cdevGenericServer/cdevReactor/cdevSocketConnector.h
Executable file
@@ -0,0 +1,12 @@
|
||||
#ifndef _CDEV_SOCKET_CONNECTOR_H_
|
||||
#define _CDEV_SOCKET_CONNECTOR_H_
|
||||
|
||||
#include "cdevSocketStream.h"
|
||||
|
||||
class CDEV_REACTOR_API cdevSocketConnector : public cdevSocketStream
|
||||
{
|
||||
public:
|
||||
int connect (const cdevAddr & remote_addr );
|
||||
};
|
||||
|
||||
#endif /* _CDEV_SOCK_CONNECTOR_H */
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "cdevSocketDatagram.h"
|
||||
|
||||
int cdevSocketDatagram::open ( const cdevAddr &addr, int protocol_family, int protocol )
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if((result = cdevSocket::open(SOCK_DGRAM, protocol_family, protocol))!=-1)
|
||||
{
|
||||
result = bind(getHandle(), (sockaddr *)addr.getAddress(), addr.getSize());
|
||||
}
|
||||
if(result!=0) close();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
ssize_t cdevSocketDatagram::send (const void *buf, size_t n, const cdevAddr &addr, int flags) const
|
||||
{
|
||||
sockaddr *saddr = (sockaddr *) addr.getAddress ();
|
||||
size_t len = addr.getSize ();
|
||||
return sendto (this->getHandle (), (const char *) buf, n, flags, (struct sockaddr *) saddr, len);
|
||||
}
|
||||
|
||||
|
||||
ssize_t cdevSocketDatagram::recv (void *buf, size_t n, cdevAddr &addr, int flags) const
|
||||
{
|
||||
sockaddr *saddr = (sockaddr *) addr.getAddress();
|
||||
int len = addr.getSize();
|
||||
ssize_t status = recvfrom (this->getHandle(), (char *)buf, n, flags, (sockaddr *) saddr, (SOCKOPT_SIZE_PARM *)&len);
|
||||
addr.setSize (len);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
cdevSocketDatagram::cdevSocketDatagram ( void )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
cdevSocketDatagram::cdevSocketDatagram ( const cdevAddr &addr, int protocol_family, int protocol )
|
||||
{
|
||||
open(addr, protocol_family, protocol);
|
||||
}
|
||||
|
||||
18
extensions/cdevGenericServer/cdevReactor/cdevSocketDatagram.h
Executable file
18
extensions/cdevGenericServer/cdevReactor/cdevSocketDatagram.h
Executable file
@@ -0,0 +1,18 @@
|
||||
#if !defined (_CDEV_SOCKET_DATAGRAM_H_)
|
||||
#define _CDEV_SOCKET_DATAGRAM_H
|
||||
|
||||
#include "cdevSocket.h"
|
||||
#include "cdevAddr.h"
|
||||
|
||||
class CDEV_REACTOR_API cdevSocketDatagram : public cdevSocket
|
||||
{
|
||||
public:
|
||||
cdevSocketDatagram (void);
|
||||
cdevSocketDatagram (const cdevAddr &addr, int protocol_family = PF_INET, int protocol = 0);
|
||||
int open (const cdevAddr &addr, int protocol_family = PF_INET, int protocol = 0);
|
||||
ssize_t send (const void *buf, size_t n, const cdevAddr &addr, int flags = 0) const;
|
||||
ssize_t recv (void *buf, size_t n, cdevAddr &addr, int flags = 0) const;
|
||||
|
||||
};
|
||||
|
||||
#endif /* _CDEV_SOCKET_DATAGRAM_H_ */
|
||||
177
extensions/cdevGenericServer/cdevReactor/cdevSocketStream.cc
Executable file
177
extensions/cdevGenericServer/cdevReactor/cdevSocketStream.cc
Executable file
@@ -0,0 +1,177 @@
|
||||
#include "cdevSocketStream.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSocketStream::cdevSocketStream :
|
||||
// * Constructor for the cdevSocketStream class. Only serves to initialize
|
||||
// * the readRetryCount variable.
|
||||
// *****************************************************************************
|
||||
cdevSocketStream::cdevSocketStream ( void )
|
||||
{
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSocketStream::send :
|
||||
// * Send an n byte message to the connected socket.
|
||||
// *****************************************************************************
|
||||
ssize_t cdevSocketStream::send(const void *buf, size_t n, int flags) const
|
||||
{
|
||||
int retval;
|
||||
if((retval = ::send(getHandle(), (const char *) buf, n, flags))<=0)
|
||||
{
|
||||
int errCode = GetSocketErrno();
|
||||
|
||||
if(errCode==EAGAIN || errCode==EWOULDBLOCK) retval = 0;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSocketStream::send_n :
|
||||
// * This method will transmit an n byte message to a connected socket,
|
||||
// * waiting until all data has been transmitted or an error occurs.
|
||||
// *****************************************************************************
|
||||
ssize_t cdevSocketStream::send_n(const void *buf, size_t n, int flags) const
|
||||
{
|
||||
ssize_t amntsent = 0;
|
||||
int result = 0;
|
||||
|
||||
while(amntsent<(ssize_t)n && result>=0)
|
||||
{
|
||||
if((result = ::send(getHandle(), (const char *)buf+amntsent, n-amntsent, flags))<=0)
|
||||
{
|
||||
int errCode = GetSocketErrno();
|
||||
|
||||
if(errCode==EAGAIN || errCode==EWOULDBLOCK) result = 0;
|
||||
else result = -1;
|
||||
}
|
||||
else amntsent+=result;
|
||||
}
|
||||
return (amntsent>=(ssize_t)n)?amntsent:-1;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSocketStream::recv :
|
||||
// * Recv an n byte message from the connected socket.
|
||||
// *****************************************************************************
|
||||
ssize_t cdevSocketStream::recv(void *buf, size_t n, int flags)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if((retval = ::recv(getHandle(), (char *)buf, n, flags))<=0)
|
||||
{
|
||||
int errCode = GetSocketErrno();
|
||||
|
||||
if(errCode==EAGAIN || errCode==EWOULDBLOCK) retval = 0;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSocketStream::recv_n :
|
||||
// * This method will receive an n byte message from a connected socket,
|
||||
// * waiting until all data has been received or an error occurs.
|
||||
// *****************************************************************************
|
||||
ssize_t cdevSocketStream::recv_n(void *buf, size_t n, int flags)
|
||||
{
|
||||
ssize_t amntrecv = 0;
|
||||
int result = 0;
|
||||
|
||||
while(amntrecv < (ssize_t)n)
|
||||
{
|
||||
if((result = ::recv(getHandle(), (char *)buf+amntrecv, n-amntrecv, flags)) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (result == 0)
|
||||
break;
|
||||
else amntrecv+=result;
|
||||
}
|
||||
return amntrecv;
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSocketStream::closeReader :
|
||||
// * Shut down just the reading end of a cdevSocket.
|
||||
// *****************************************************************************
|
||||
int cdevSocketStream::closeReader(void)
|
||||
{
|
||||
return ::shutdown(getHandle(), 0);
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * cdevSocketStream::closeWriter :
|
||||
// * Shut down just the writing end of a cdevSocket.
|
||||
// *****************************************************************************
|
||||
int cdevSocketStream::closeWriter(void)
|
||||
{
|
||||
return ::shutdown(getHandle(), 1);
|
||||
}
|
||||
|
||||
|
||||
int cdevSocketStream::getBlockingSemantics ( void ) const
|
||||
{
|
||||
return O_NONBLOCK;
|
||||
}
|
||||
|
||||
int cdevSocketStream::getRcvLowWaterMark ( void ) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cdevSocketStream::getRcvBufferSize ( void ) const
|
||||
{
|
||||
return 56000;
|
||||
}
|
||||
|
||||
int cdevSocketStream::getSndLowWaterMark ( void ) const
|
||||
{
|
||||
return 16000;
|
||||
}
|
||||
|
||||
int cdevSocketStream::getSndBufferSize ( void ) const
|
||||
{
|
||||
return 56000;
|
||||
}
|
||||
|
||||
int cdevSocketStream::configureHandle ( void )
|
||||
{
|
||||
int retval = 0;
|
||||
int parm = 1;
|
||||
|
||||
|
||||
if(getBlockingSemantics()==O_NONBLOCK && setFlags(O_NONBLOCK)==-1)
|
||||
{
|
||||
retval = -1;
|
||||
}
|
||||
|
||||
setOption(IPPROTO_TCP, TCP_NODELAY, &parm, sizeof(parm));
|
||||
|
||||
if((parm = getRcvBufferSize())>0)
|
||||
{
|
||||
setOption(SOL_SOCKET, SO_RCVBUF, &parm, sizeof(parm));
|
||||
}
|
||||
#ifndef __linux
|
||||
if((parm = getRcvLowWaterMark())>0)
|
||||
{
|
||||
setOption(SOL_SOCKET, SO_RCVLOWAT, &parm, sizeof(parm));
|
||||
}
|
||||
#endif
|
||||
|
||||
if((parm = getSndBufferSize())>0)
|
||||
{
|
||||
setOption(SOL_SOCKET, SO_SNDBUF, &parm, sizeof(parm));
|
||||
}
|
||||
|
||||
#ifndef __linux
|
||||
if((parm = getSndLowWaterMark())>0)
|
||||
{
|
||||
setOption(SOL_SOCKET, SO_SNDLOWAT, &parm, sizeof(parm));
|
||||
}
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
29
extensions/cdevGenericServer/cdevReactor/cdevSocketStream.h
Executable file
29
extensions/cdevGenericServer/cdevReactor/cdevSocketStream.h
Executable file
@@ -0,0 +1,29 @@
|
||||
#if !defined (_CDEV_SOCKET_STREAM_H)
|
||||
#define _CDEV_SOCKET_STREAM_H
|
||||
|
||||
#include "cdevSocket.h"
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
class CDEV_REACTOR_API cdevSocketStream : public cdevSocket
|
||||
{
|
||||
public:
|
||||
cdevSocketStream (void);
|
||||
ssize_t send (const void *buf, size_t n, int flags=0) const;
|
||||
ssize_t recv (void *buf, size_t n, int flags=0);
|
||||
ssize_t send_n (const void *buf, size_t n, int flags=0) const;
|
||||
ssize_t recv_n (void * buf, size_t n, int flags=0);
|
||||
|
||||
int closeReader (void);
|
||||
int closeWriter (void);
|
||||
|
||||
virtual int getBlockingSemantics ( void ) const;
|
||||
virtual int getRcvLowWaterMark ( void ) const;
|
||||
virtual int getSndLowWaterMark ( void ) const;
|
||||
virtual int getRcvBufferSize ( void ) const;
|
||||
virtual int getSndBufferSize ( void ) const;
|
||||
virtual int configureHandle ( void );
|
||||
};
|
||||
|
||||
#endif /* _CDEV_SOCKET_STREAM_H_ */
|
||||
|
||||
20
extensions/cdevGenericServer/cdevReactor/cdevStreamNode.cc
Normal file
20
extensions/cdevGenericServer/cdevReactor/cdevStreamNode.cc
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "cdevStreamNode.h"
|
||||
|
||||
cdevStreamNode::cdevStreamNode ( void )
|
||||
: nextStreamNode(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
cdevStreamNode::~cdevStreamNode ( void )
|
||||
{
|
||||
}
|
||||
|
||||
cdevStreamNode * cdevStreamNode::getNext( void ) const
|
||||
{
|
||||
return nextStreamNode;
|
||||
}
|
||||
|
||||
void cdevStreamNode::setNext (cdevStreamNode * node)
|
||||
{
|
||||
nextStreamNode = node;
|
||||
}
|
||||
33
extensions/cdevGenericServer/cdevReactor/cdevStreamNode.h
Executable file
33
extensions/cdevGenericServer/cdevReactor/cdevStreamNode.h
Executable file
@@ -0,0 +1,33 @@
|
||||
#ifndef _CDEV_STREAM_NODE_H_
|
||||
#define _CDEV_STREAM_NODE_H_
|
||||
|
||||
#include "cdevPlatforms.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// * class cdevStreamNode :
|
||||
// * This is a virtual base class that defines the functionality that will
|
||||
// * be required for data nodes that are inserted into the
|
||||
// * cdevBufferedSocket.
|
||||
// *****************************************************************************
|
||||
class CDEV_REACTOR_API cdevStreamNode
|
||||
{
|
||||
friend class cdevStreamQueue;
|
||||
|
||||
public:
|
||||
virtual ~cdevStreamNode ( void );
|
||||
|
||||
virtual size_t getLen(void) const = 0;
|
||||
virtual void setLen(size_t size) = 0;
|
||||
virtual char * getBuf(void) const = 0;
|
||||
virtual void setBuf(char * buf, size_t len) = 0;
|
||||
|
||||
protected:
|
||||
cdevStreamNode * nextStreamNode;
|
||||
|
||||
cdevStreamNode ( void );
|
||||
|
||||
cdevStreamNode * getNext( void ) const;
|
||||
void setNext(cdevStreamNode * node);
|
||||
};
|
||||
|
||||
#endif /* _CDEV_STREAM_NODE_H_ */
|
||||
35
extensions/cdevGenericServer/cdevReactor/cdevStreamQueue.cc
Normal file
35
extensions/cdevGenericServer/cdevReactor/cdevStreamQueue.cc
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "cdevStreamQueue.h"
|
||||
|
||||
cdevSimpleStreamNode::cdevSimpleStreamNode( char * buffer, size_t size)
|
||||
: cdevStreamNode(), buf(buffer), len(size)
|
||||
{
|
||||
}
|
||||
|
||||
cdevSimpleStreamNode::~cdevSimpleStreamNode ( void )
|
||||
{
|
||||
if(buf) delete buf;
|
||||
}
|
||||
|
||||
size_t cdevSimpleStreamNode::getLen (void) const
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
||||
void cdevSimpleStreamNode:: setLen (size_t size)
|
||||
{
|
||||
len=size;
|
||||
}
|
||||
|
||||
char * cdevSimpleStreamNode::getBuf (void) const
|
||||
{
|
||||
return buf;
|
||||
}
|
||||
|
||||
void cdevSimpleStreamNode::setBuf (char * buffer, size_t size)
|
||||
{
|
||||
buf=buffer; len=size;
|
||||
}
|
||||
|
||||
cdevNodeFactory::~cdevNodeFactory ( void )
|
||||
{
|
||||
}
|
||||
126
extensions/cdevGenericServer/cdevReactor/cdevStreamQueue.h
Executable file
126
extensions/cdevGenericServer/cdevReactor/cdevStreamQueue.h
Executable file
@@ -0,0 +1,126 @@
|
||||
#ifndef _CDEV_STREAM_QUEUE_H_
|
||||
#define _CDEV_STREAM_QUEUE_H_
|
||||
|
||||
#include "cdevStreamNode.h"
|
||||
|
||||
// *****************************************************************************
|
||||
// * class cdevSimpleStreamNode :
|
||||
// * This is a simple implementation class of the cdevStreamNode. It will
|
||||
// * be used if the developer does not provide his own implementation class.
|
||||
// *****************************************************************************
|
||||
class CDEV_REACTOR_API cdevSimpleStreamNode : public cdevStreamNode
|
||||
{
|
||||
protected:
|
||||
char * buf;
|
||||
size_t len;
|
||||
|
||||
public:
|
||||
cdevSimpleStreamNode ( char * buffer=NULL, size_t size=0);
|
||||
~cdevSimpleStreamNode ( void );
|
||||
|
||||
size_t getLen (void) const;
|
||||
void setLen (size_t size);
|
||||
char * getBuf (void) const;
|
||||
void setBuf (char * buffer, size_t size);
|
||||
};
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * class cdevNodeFactory :
|
||||
// * This class will generate a user defined instance of a cdevStreamNode
|
||||
// * sub-class. This class is used within the cdevBufferedSocket to
|
||||
// * convert incoming binary packets into a user defined structure.
|
||||
// *****************************************************************************
|
||||
class CDEV_REACTOR_API cdevNodeFactory
|
||||
{
|
||||
public:
|
||||
virtual ~cdevNodeFactory ( void );
|
||||
|
||||
virtual cdevStreamNode * newNode ( ssize_t size ) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// * class cdevStreamQueue :
|
||||
// * This is a class that will store the data items that are being enqueued
|
||||
// * by the cdevBufferedSocket.
|
||||
// *****************************************************************************
|
||||
class CDEV_REACTOR_API cdevStreamQueue
|
||||
{
|
||||
private:
|
||||
cdevStreamNode * head;
|
||||
cdevStreamNode * tail;
|
||||
int deleteFlag;
|
||||
size_t nEntries;
|
||||
size_t totalLen;
|
||||
|
||||
public:
|
||||
cdevStreamQueue ( int deleteNodesFlag = 1 )
|
||||
: head(NULL), tail(NULL), deleteFlag(deleteNodesFlag),
|
||||
nEntries(0), totalLen(0)
|
||||
{
|
||||
}
|
||||
|
||||
~cdevStreamQueue ( void )
|
||||
{
|
||||
if(deleteFlag) while(!isEmpty()) delete dequeue();
|
||||
}
|
||||
|
||||
void enqueue( cdevStreamQueue & queue )
|
||||
{
|
||||
head = queue.head;
|
||||
tail = queue.tail;
|
||||
nEntries = queue.nEntries;
|
||||
totalLen = queue.totalLen;
|
||||
queue.head = NULL;
|
||||
queue.tail = NULL;
|
||||
queue.nEntries = 0;
|
||||
queue.totalLen = 0;
|
||||
}
|
||||
|
||||
void enqueue ( cdevStreamNode * node )
|
||||
{
|
||||
if(node)
|
||||
{
|
||||
if(tail!=NULL) tail->setNext(node);
|
||||
else head = node;
|
||||
tail = node;
|
||||
totalLen+=(node->getLen()+sizeof(node->getLen()));
|
||||
nEntries++;
|
||||
}
|
||||
}
|
||||
|
||||
cdevStreamNode * dequeue ( void )
|
||||
{
|
||||
cdevStreamNode * node = NULL;
|
||||
if(head!=NULL)
|
||||
{
|
||||
node = head;
|
||||
head = node->getNext();
|
||||
node->setNext(NULL);
|
||||
if(head==NULL) tail = NULL;
|
||||
totalLen-=(node->getLen()+sizeof(node->getLen()));
|
||||
nEntries--;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
cdevStreamNode * peek ( void )
|
||||
{
|
||||
return head;
|
||||
}
|
||||
|
||||
void poke ( cdevStreamNode * node )
|
||||
{
|
||||
node->setNext(head);
|
||||
head = node;
|
||||
if(tail==NULL) tail = head;
|
||||
}
|
||||
|
||||
int isEmpty ( void ) const { return head==NULL?1:0; }
|
||||
size_t getCount ( void ) const { return nEntries; }
|
||||
size_t getSize ( void ) const { return totalLen; }
|
||||
};
|
||||
|
||||
#endif /* _CDEV_STREAM_QUEUE_H */
|
||||
210
extensions/cdevGenericServer/cdevReactor/cdevTime.cc
Normal file
210
extensions/cdevGenericServer/cdevReactor/cdevTime.cc
Normal file
@@ -0,0 +1,210 @@
|
||||
#include "cdevTime.h"
|
||||
|
||||
cdevTime::cdevTime ( long sec, long usec )
|
||||
{
|
||||
setTime(sec, usec);
|
||||
}
|
||||
|
||||
|
||||
cdevTime::cdevTime ( double t )
|
||||
{
|
||||
setTime(t);
|
||||
}
|
||||
|
||||
|
||||
cdevTime::cdevTime ( timeval & t )
|
||||
{
|
||||
setTime(t);
|
||||
}
|
||||
|
||||
|
||||
cdevTime::cdevTime ( const cdevTime & t )
|
||||
{
|
||||
setTime(t);
|
||||
}
|
||||
|
||||
|
||||
void cdevTime::getTime ( double * t ) const
|
||||
{
|
||||
if(t) *t = (double)tv_sec+(double)tv_usec/(double)ONE_SECOND;
|
||||
}
|
||||
|
||||
|
||||
void cdevTime::getTime ( long * sec, long * usec) const
|
||||
{
|
||||
if(sec && usec)
|
||||
{
|
||||
*sec = tv_sec;
|
||||
*usec = tv_usec;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cdevTime::getTime ( timeval * t ) const
|
||||
{
|
||||
if(t) {
|
||||
t->tv_sec = tv_sec;
|
||||
t->tv_usec = tv_usec;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cdevTime::setTime ( void )
|
||||
{
|
||||
struct timeval tv_time;
|
||||
|
||||
gettimeofday(&tv_time);
|
||||
|
||||
tv_sec = tv_time.tv_sec;
|
||||
tv_usec = tv_time.tv_usec;
|
||||
}
|
||||
|
||||
|
||||
void cdevTime::setTime ( double t )
|
||||
{
|
||||
tv_sec = (long)t;
|
||||
tv_usec = (long)((double)fmod(t, 1.0)*(double)ONE_SECOND);
|
||||
normalize();
|
||||
}
|
||||
|
||||
|
||||
void cdevTime::setTime ( long sec, long usec )
|
||||
{
|
||||
tv_sec = sec;
|
||||
tv_usec = usec;
|
||||
normalize();
|
||||
}
|
||||
|
||||
|
||||
void cdevTime::setTime ( timeval & t )
|
||||
{
|
||||
tv_sec = t.tv_sec;
|
||||
tv_usec = t.tv_usec;
|
||||
normalize();
|
||||
}
|
||||
|
||||
|
||||
void cdevTime::setTime ( const cdevTime & t )
|
||||
{
|
||||
t.getTime(&tv_sec, &tv_usec);
|
||||
normalize();
|
||||
}
|
||||
|
||||
|
||||
void cdevTime::clear ( void )
|
||||
{
|
||||
tv_sec = 0;
|
||||
tv_usec = 0;
|
||||
}
|
||||
|
||||
|
||||
int cdevTime::isSet ( void ) const
|
||||
{
|
||||
return (tv_sec||tv_usec)?1:0;
|
||||
}
|
||||
|
||||
|
||||
int cdevTime::normalize ( void )
|
||||
{
|
||||
while ((this->tv_usec >= ONE_SECOND)
|
||||
|| (this->tv_sec < 0 && this->tv_usec > 0 ))
|
||||
{
|
||||
this->tv_usec -= ONE_SECOND;
|
||||
this->tv_sec++;
|
||||
}
|
||||
|
||||
while ((this->tv_usec <= -ONE_SECOND)
|
||||
|| (this->tv_sec > 0 && this->tv_usec < 0))
|
||||
{
|
||||
this->tv_usec += ONE_SECOND;
|
||||
this->tv_sec--;
|
||||
}
|
||||
|
||||
return isSet();
|
||||
}
|
||||
|
||||
|
||||
cdevTime & cdevTime::operator = ( const cdevTime & t )
|
||||
{
|
||||
if (this != &t)
|
||||
{
|
||||
tv_sec = t.tv_sec;
|
||||
tv_usec = t.tv_usec;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
cdevTime::operator double ( void )
|
||||
{
|
||||
return (double)tv_sec+(double)tv_usec/(double)ONE_SECOND;
|
||||
}
|
||||
|
||||
|
||||
cdevTime::operator timeval ( void )
|
||||
{
|
||||
timeval tv_time;
|
||||
|
||||
tv_time.tv_sec = tv_sec;
|
||||
tv_time.tv_usec = tv_usec;
|
||||
|
||||
return tv_time;
|
||||
}
|
||||
|
||||
|
||||
cdevTime operator + (cdevTime t1, cdevTime t2)
|
||||
{
|
||||
cdevTime sum (t1.tv_sec + t2.tv_sec, t1.tv_usec + t2.tv_usec);
|
||||
|
||||
sum.normalize ();
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
cdevTime operator - (cdevTime t1, cdevTime t2)
|
||||
{
|
||||
cdevTime delta (t1.tv_sec - t2.tv_sec, t1.tv_usec - t2.tv_usec);
|
||||
|
||||
delta.normalize ();
|
||||
return delta;
|
||||
}
|
||||
|
||||
|
||||
int operator > (cdevTime t1, cdevTime t2)
|
||||
{
|
||||
if (t1.tv_sec > t2.tv_sec) return 1;
|
||||
else if (t1.tv_sec == t2.tv_sec && t1.tv_usec > t2.tv_usec) return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
int operator >= (cdevTime t1, cdevTime t2)
|
||||
{
|
||||
if (t1.tv_sec > t2.tv_sec) return 1;
|
||||
else if (t1.tv_sec == t2.tv_sec && t1.tv_usec >= t2.tv_usec) return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
int operator < (cdevTime t1, cdevTime t2)
|
||||
{
|
||||
return t2 > t1;
|
||||
}
|
||||
|
||||
|
||||
int operator <= (cdevTime t1, cdevTime t2)
|
||||
{
|
||||
return t2 >= t1;
|
||||
}
|
||||
|
||||
|
||||
int operator == (cdevTime t1, cdevTime t2)
|
||||
{
|
||||
return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec;
|
||||
}
|
||||
|
||||
|
||||
int operator != (cdevTime t1, cdevTime t2)
|
||||
{
|
||||
return !(t1 == t2);
|
||||
}
|
||||
51
extensions/cdevGenericServer/cdevReactor/cdevTime.h
Executable file
51
extensions/cdevGenericServer/cdevReactor/cdevTime.h
Executable file
@@ -0,0 +1,51 @@
|
||||
#ifndef _CDEV_TIME_H_
|
||||
#define _CDEV_TIME_H_ 1
|
||||
|
||||
#include "cdevPlatforms.h"
|
||||
|
||||
#define ONE_SECOND 1000000
|
||||
|
||||
typedef struct timeval timeval;
|
||||
|
||||
class CDEV_REACTOR_API cdevTime
|
||||
{
|
||||
private:
|
||||
long tv_sec;
|
||||
long tv_usec;
|
||||
|
||||
public:
|
||||
cdevTime ( long sec=0, long usec=0 );
|
||||
cdevTime ( double t );
|
||||
cdevTime ( timeval &t );
|
||||
cdevTime ( const cdevTime &t );
|
||||
|
||||
void getTime ( double * t ) const;
|
||||
void getTime ( long *sec, long *usec) const;
|
||||
void getTime ( timeval * t ) const;
|
||||
|
||||
void setTime ( void );
|
||||
void setTime ( double t );
|
||||
void setTime ( long sec, long usec);
|
||||
void setTime ( timeval &t );
|
||||
void setTime ( const cdevTime &t );
|
||||
|
||||
void clear ( void );
|
||||
int isSet ( void ) const;
|
||||
int normalize ( void );
|
||||
|
||||
operator double ( void );
|
||||
operator timeval ( void );
|
||||
|
||||
cdevTime & operator = (const cdevTime& t);
|
||||
|
||||
friend cdevTime operator + (cdevTime t1, cdevTime t2);
|
||||
friend cdevTime operator - (cdevTime t1, cdevTime t2);
|
||||
friend int operator < (cdevTime t1, cdevTime t2);
|
||||
friend int operator > (cdevTime t1, cdevTime t2);
|
||||
friend int operator <= (cdevTime t1, cdevTime t2);
|
||||
friend int operator >= (cdevTime t1, cdevTime t2);
|
||||
friend int operator == (cdevTime t1, cdevTime t2);
|
||||
friend int operator != (cdevTime t1, cdevTime t2);
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user