From 070374dde0f53bff26078550997f7682e84412e5 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 10 Apr 2007 20:16:19 +0000 Subject: I did it, the streams don't start with an S now. --- src/socket.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/socket.h (limited to 'src/socket.h') diff --git a/src/socket.h b/src/socket.h new file mode 100644 index 0000000..8ccde71 --- /dev/null +++ b/src/socket.h @@ -0,0 +1,24 @@ +#ifndef SOCKET_H +#define SOCKET_H + +#include + +#include "stream.h" + +namespace Bu +{ + /** + * + */ + class Socket : public Stream + { + public: + Socket(); + virtual ~Socket(); + + private: + + }; +} + +#endif -- cgit v1.2.3 From 1fa3ca5f24c018126333ca2d6609730e1ae17386 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Tue, 10 Apr 2007 21:48:23 +0000 Subject: Added more comments, help, and socket actually reads and writes some, but it's not done. I need to decide how I want to do the buffering... --- src/archive.h | 47 +++++++++++ src/exceptions.cpp | 1 + src/exceptions.h | 2 + src/socket.cpp | 232 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/socket.h | 23 +++++- src/stream.h | 10 +++ 6 files changed, 312 insertions(+), 3 deletions(-) (limited to 'src/socket.h') diff --git a/src/archive.h b/src/archive.h index 9ac3303..2f782d3 100644 --- a/src/archive.h +++ b/src/archive.h @@ -9,6 +9,53 @@ namespace Bu { + /** + * Provides a framework for serialization of objects and primitives. The + * archive will handle any basic primitive, a few special types, like char * + * strings, as well as STL classes and anything that inherits from the + * Archival class. Each Archive operates on a Stream, so you can send the + * data using an Archive almost anywhere. + * + * In order to use an Archive to store something to a file, try something + * like: + *@code + * File sOut("output", "wb"); // This is a stream subclass + * Archive ar( sOut, Archive::save ); + * ar << myClass; + @endcode + * In this example myClass is any class that inherits from Archival. When + * the storage operator is called, the Archival::archive() function in the + * myClass object is called with a reference to the Archive. This can be + * handled in one of two ways: + *@code + * void MyClass::archive( Archive &ar ) + * { + * ar && sName && nAge && sJob; + * } + @endcode + * Here we don't worry about weather we're loading or saving by using the + * smart && operator. This allows us to write very consistent, very simple + * archive functions that really do a lot of work. If we wanted to do + * something different in the case of loading or saving we would do: + *@code + * void MyClass::archive( Archive &ar ) + * { + * if( ar.isLoading() ) + * { + * ar >> sName >> nAge >> sJob; + * } else + * { + * ar << sName << nAge << sJob; + * } + * } + @endcode + * Archive currently does not provide facility to make fully portable + * archives. For example, it will not convert between endianness for you, + * nor will it take into account differences between primitive sizes on + * different platforms. This, at the moment, is up to the user to ensure. + * One way of dealing with the latter problem is to make sure and use + * explicit primitive types from the stdint.h header, i.e. int32_t. + */ class Archive { private: diff --git a/src/exceptions.cpp b/src/exceptions.cpp index 37f09a4..a512105 100644 --- a/src/exceptions.cpp +++ b/src/exceptions.cpp @@ -7,4 +7,5 @@ namespace Bu subExceptionDef( FileException ) subExceptionDef( ConnectionException ) subExceptionDef( PluginException ) + subExceptionDef( UnsupportedException ) } diff --git a/src/exceptions.h b/src/exceptions.h index b28d292..3efa19f 100644 --- a/src/exceptions.h +++ b/src/exceptions.h @@ -10,6 +10,7 @@ namespace Bu subExceptionDecl( FileException ) subExceptionDecl( ConnectionException ) subExceptionDecl( PluginException ) + subExceptionDecl( UnsupportedException ) enum eFileException { @@ -19,6 +20,7 @@ namespace Bu enum eConnectionException { excodeReadError, + excodeWriteError, excodeBadReadError, excodeConnectionClosed, excodeSocketTimeout diff --git a/src/socket.cpp b/src/socket.cpp index c5c592b..e206bb5 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -1,10 +1,240 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "socket.h" +#include "exceptions.h" -Bu::Socket::Socket() +#define RBS (1024*2) + +Bu::Socket::Socket( int nSocket ) : + nSocket( nSocket ), + bActive( true ) { } +Bu::Socket::Socket( const Bu::FString &sAddr, int nPort, int nTimeout ) +{ + struct sockaddr_in xServerName; + bActive = false; + + /* Create the socket. */ + nSocket = socket( PF_INET, SOCK_STREAM, 0 ); + + if( nSocket < 0 ) + { + throw ExceptionBase("Couldn't create socket.\n"); + } + + // These lines set the socket to non-blocking, a good thing? + int flags; + flags = fcntl(nSocket, F_GETFL, 0); + flags |= O_NONBLOCK; + if (fcntl(nSocket, F_SETFL, flags) < 0) + { + throw ExceptionBase("Couldn't set socket options.\n"); + } + + /* Connect to the server. */ + //printf("Resolving hostname (%s)...\n", sAddr ); + { + struct hostent *hostinfo; + + xServerName.sin_family = AF_INET; + xServerName.sin_port = htons( nPort ); + hostinfo = gethostbyname( sAddr.getStr() ); + if (hostinfo == NULL) + { + throw ExceptionBase("Couldn't resolve hostname.\n"); + } + xServerName.sin_addr = *(struct in_addr *) hostinfo->h_addr; + } + + //printf("Making actual connection..."); + //fflush( stdout ); + connect( + nSocket, + (struct sockaddr *)&xServerName, + sizeof(xServerName) + ); + //printf("Connected.\n"); + + bActive = true; + + if( nTimeout > 0 ) + { + fd_set rfds, wfds, efds; + int retval; + + FD_ZERO(&rfds); + FD_SET(nSocket, &rfds); + FD_ZERO(&wfds); + FD_SET(nSocket, &wfds); + FD_ZERO(&efds); + FD_SET(nSocket, &efds); + + struct timeval tv; + tv.tv_sec = nTimeout; + tv.tv_usec = 0; + + retval = select( nSocket+1, &rfds, &wfds, &efds, &tv ); + + if( retval == 0 ) + { + close(); + throw ExceptionBase("Connection timeout.\n"); + } + + } +} + Bu::Socket::~Socket() { } +void Bu::Socket::close() +{ + if( bActive ) + { + fsync( nSocket ); + ::close( nSocket ); + } + bActive = false; + //xInputBuf.clearData(); + //xOutputBuf.clearData(); + //if( pProtocol != NULL ) + //{ + // delete pProtocol; + // pProtocol = NULL; + //} +} + +void Bu::Socket::read() +{ + char buffer[RBS]; + int nbytes; + int nTotalRead=0; + + for(;;) + { + //memset( buffer, 0, RBS ); + + nbytes = ::read( nSocket, buffer, RBS ); + if( nbytes < 0 && errno != 0 && errno != EAGAIN ) + { + //printf("errno: %d, %s\n", errno, strerror( errno ) ); + /* Read error. */ + //perror("readInput"); + throw ConnectionException( + excodeReadError, + "Read error: %s", + strerror( errno ) + ); + } + else + { + if( nbytes <= 0 ) + break; + nTotalRead += nbytes; + sReadBuf.append( buffer, nbytes ); + /* Data read. */ + if( nbytes < RBS ) + { + break; + } + + /* New test, if data is divisible by RBS bytes on some libs the + * read could block, this keeps it from happening. + */ + { + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(nSocket, &rfds); + struct timeval tv = { 0, 0 }; + int retval = select( nSocket+1, &rfds, NULL, NULL, &tv ); + if( retval == -1 ) + throw ConnectionException( + excodeBadReadError, + "Bad Read error" + ); + if( !FD_ISSET( nSocket, &rfds ) ) + break; + } + } + } + + /* + if( pProtocol != NULL && nTotalRead > 0 ) + { + pProtocol->onNewData(); + }*/ +} + +size_t Bu::Socket::read( void *pBuf, size_t nBytes ) +{ + read(); + + + + return sReadBuf.getSize(); +} + +size_t Bu::Socket::write( const void *pBuf, size_t nBytes ) +{ + int nWrote = TEMP_FAILURE_RETRY( ::write( nSocket, pBuf, nBytes ) ); + if( nWrote < 0 ) + { + throw ConnectionException( excodeWriteError, strerror(errno) ); + } + return nWrote; +} + +long Bu::Socket::tell() +{ + throw UnsupportedException(); +} + +void Bu::Socket::seek( long offset ) +{ + throw UnsupportedException(); +} + +void Bu::Socket::setPos( long pos ) +{ + throw UnsupportedException(); +} + +void Bu::Socket::setPosEnd( long pos ) +{ + throw UnsupportedException(); +} + +bool Bu::Socket::isEOS() +{ + return !bActive; +} + +bool Bu::Socket::canRead() +{ + return true; +} + +bool Bu::Socket::canWrite() +{ + return true; +} + +bool Bu::Socket::canSeek() +{ + return false; +} + diff --git a/src/socket.h b/src/socket.h index 8ccde71..3d0125d 100644 --- a/src/socket.h +++ b/src/socket.h @@ -4,6 +4,7 @@ #include #include "stream.h" +#include "fstring.h" namespace Bu { @@ -13,11 +14,29 @@ namespace Bu class Socket : public Stream { public: - Socket(); + Socket( int nSocket ); + Socket( const FString &sAddr, int nPort, int nTimeout=30 ); virtual ~Socket(); + + virtual void close(); + virtual void read(); + virtual size_t read( void *pBuf, size_t nBytes ); + virtual size_t write( const void *pBuf, size_t nBytes ); - private: + virtual long tell(); + virtual void seek( long offset ); + virtual void setPos( long pos ); + virtual void setPosEnd( long pos ); + virtual bool isEOS(); + + virtual bool canRead(); + virtual bool canWrite(); + virtual bool canSeek(); + private: + int nSocket; + bool bActive; + FString sReadBuf; }; } diff --git a/src/stream.h b/src/stream.h index ae94234..e640959 100644 --- a/src/stream.h +++ b/src/stream.h @@ -6,6 +6,16 @@ namespace Bu { + /** + * The basis for a completely general data transport mechanism. Anything + * that inherits from this should provide at least the basic read and/or + * write functions, and very probably the close function. Any functions + * that aren't supported should throw an exception if called. + * + * The constructor of a child class should pretty much universally be used + * to open the stream. I can't think of anything that should require an + * exception. + */ class Stream { public: -- cgit v1.2.3 From 530014a3cce53e86dce8917e98a4e86d02f176aa Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 26 Apr 2007 15:06:49 +0000 Subject: Merged Ito and put it in the BU namespace. I should probably clean up the formatting on the comments, some of the lines wrap, but I'm not too worried about it right now. I also fixed up the doxygen config and build.conf files so that everything is building nice and smooth now. --- Doxyfile | 4 +- build.conf | 26 ++++-- mkincs.sh | 5 ++ src/exceptions.cpp | 1 + src/exceptions.h | 1 + src/ito.cpp | 40 +++++++++ src/ito.h | 98 ++++++++++++++++++++ src/itoatom.h | 56 ++++++++++++ src/itocondition.cpp | 42 +++++++++ src/itocondition.h | 81 +++++++++++++++++ src/itomutex.cpp | 27 ++++++ src/itomutex.h | 61 +++++++++++++ src/itoqueue.h | 231 ++++++++++++++++++++++++++++++++++++++++++++++++ src/main.dox | 14 +++ src/serversocket.cpp | 148 +++++++++++++++++++++++++++++++ src/serversocket.h | 31 +++++++ src/socket.cpp | 16 +--- src/socket.h | 4 +- src/tests/itoqueue1.cpp | 110 +++++++++++++++++++++++ src/tests/itoqueue2.cpp | 83 +++++++++++++++++ 20 files changed, 1059 insertions(+), 20 deletions(-) create mode 100755 mkincs.sh create mode 100644 src/ito.cpp create mode 100644 src/ito.h create mode 100644 src/itoatom.h create mode 100644 src/itocondition.cpp create mode 100644 src/itocondition.h create mode 100644 src/itomutex.cpp create mode 100644 src/itomutex.h create mode 100644 src/itoqueue.h create mode 100644 src/main.dox create mode 100644 src/serversocket.cpp create mode 100644 src/serversocket.h create mode 100644 src/tests/itoqueue1.cpp create mode 100644 src/tests/itoqueue2.cpp (limited to 'src/socket.h') diff --git a/Doxyfile b/Doxyfile index 6c7412e..c3168fa 100644 --- a/Doxyfile +++ b/Doxyfile @@ -74,9 +74,9 @@ QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = NO +WARN_NO_PARAMDOC = YES WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = +WARN_LOGFILE = Doxywarn #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- diff --git a/build.conf b/build.conf index bc186f9..c289205 100644 --- a/build.conf +++ b/build.conf @@ -1,13 +1,17 @@ # This is a build file for libbu++ -default action: check "libbu++.a" -"clean" action: clean targets() -"tests" action: check targets() filter regexp("^tests/.*$") -"all" action: check targets() -"fstring" action: check "tests/fstring" +default action: check group "lnhdrs", check "libbu++.a" +"tests" action: check group "lnhdrs", check group "tests" +"all" action: check group "lnhdrs", check targets() set "CXXFLAGS" += "-ggdb -Wall" +filesIn("src") filter regexp("^src/(.*)\\.h$", "src/bu/{re:1}.h"): + rule "hln", + group "lnhdrs", + target file, + input "src/{re:1}.h" + "libbu++.a": rule "lib", target file, @@ -17,6 +21,7 @@ set "CXXFLAGS" += "-ggdb -Wall" directoriesIn("src/tests","tests/"): rule "exe", target file, + group "tests", requires "libbu++.a", set "CXXFLAGS" += "-Isrc", set "LDFLAGS" += "-L. -lbu++", @@ -25,14 +30,18 @@ directoriesIn("src/tests","tests/"): filesIn("src/tests") filter regexp("^src/tests/(.*)\\.cpp$", "tests/{re:1}"): rule "exe", target file, + group "tests", requires "libbu++.a", set "CXXFLAGS" += "-Isrc", set "LDFLAGS" += "-L. -lbu++", input "src/{target}.cpp" +["tests/itoqueue1", "tests/itoqueue2"]: set "LDFLAGS" += "-lpthread" + directoriesIn("src/unit","unit/"): rule "exe", target file, + group "tests", requires "libbu++.a", set "CXXFLAGS" += "-Isrc", set "LDFLAGS" += "-L. -lbu++", @@ -41,6 +50,7 @@ directoriesIn("src/unit","unit/"): filesIn("src/unit") filter regexp("^src/unit/(.*)\\.cpp$", "unit/{re:1}"): rule "exe", target file, + group "tests", requires "libbu++.a", set "CXXFLAGS" += "-Isrc", set "LDFLAGS" += "-L. -lbu++", @@ -63,3 +73,9 @@ rule "cpp": produces "{re:1}.o", requires commandToList("g++ -M {CXXFLAGS} {match}", "make"), perform command("g++ {CXXFLAGS} -c -o {target} {match}") + +rule "hln": + matches regexp("src/(.*)\\.h"), + produces "src/bu/{re:1}.h", + perform command("ln -s ../{re:1}.h {target}") + diff --git a/mkincs.sh b/mkincs.sh new file mode 100755 index 0000000..6f72f89 --- /dev/null +++ b/mkincs.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +cd src/bu +rm * +for i in ../*.h; do ln -s $i; done diff --git a/src/exceptions.cpp b/src/exceptions.cpp index a512105..d9f4e70 100644 --- a/src/exceptions.cpp +++ b/src/exceptions.cpp @@ -5,6 +5,7 @@ namespace Bu { subExceptionDef( XmlException ) subExceptionDef( FileException ) + subExceptionDef( SocketException ) subExceptionDef( ConnectionException ) subExceptionDef( PluginException ) subExceptionDef( UnsupportedException ) diff --git a/src/exceptions.h b/src/exceptions.h index 3efa19f..f146b73 100644 --- a/src/exceptions.h +++ b/src/exceptions.h @@ -8,6 +8,7 @@ namespace Bu { subExceptionDecl( XmlException ) subExceptionDecl( FileException ) + subExceptionDecl( SocketException ) subExceptionDecl( ConnectionException ) subExceptionDecl( PluginException ) subExceptionDecl( UnsupportedException ) diff --git a/src/ito.cpp b/src/ito.cpp new file mode 100644 index 0000000..001ca06 --- /dev/null +++ b/src/ito.cpp @@ -0,0 +1,40 @@ +#include "ito.h" + +Bu::Ito::Ito() +{ +} + +Bu::Ito::~Ito() +{ +} + +bool Bu::Ito::start() +{ + nHandle = pthread_create( &ptHandle, NULL, threadRunner, this ); + + return true; +} + +bool Bu::Ito::stop() +{ + pthread_exit( &ptHandle ); + + return true; +} + +void *Bu::Ito::threadRunner( void *pThread ) +{ + return ((Ito *)pThread)->run(); +} + +bool Bu::Ito::join() +{ + pthread_join( ptHandle, NULL ); + return true; +} + +void Bu::Ito::yield() +{ + pthread_yield(); +} + diff --git a/src/ito.h b/src/ito.h new file mode 100644 index 0000000..01253f5 --- /dev/null +++ b/src/ito.h @@ -0,0 +1,98 @@ +#ifndef ITO_H +#define ITO_H + +#include + +namespace Bu +{ + /** + * Simple thread class. This wraps the basic pthread (posix threads) system in + * an object oriented sort of way. It allows you to create a class with + * standard member variables and callable functions that can be run in it's own + * thread, one per class instance. + *@author Mike Buland + */ + class Ito + { + public: + /** + * Construct an Ito thread. + */ + Ito(); + + /** + * Destroy an Ito thread. + */ + virtual ~Ito(); + + /** + * Begin thread execution. This will call the overridden run function, + * which will simply execute in it's own thread until the function exits, + * the thread is killed, or the thread is cancelled (optionally). The + * thread started in this manner has access to all of it's class variables, + * but be sure to protect possible multiple-access with ItoMutex objects. + *@returns True if starting the thread was successful. False if something + * went wrong and the thread has not started. + */ + bool start(); + + /** + * Forcibly kill a thread. This is not generally considered a good thing to + * do, but in those rare cases you need it, it's invaluable. The problem + * with stopping (or killing) a thread is that it stops it the moment you + * call stop, no matter what it's doing. The object oriented approach to + * this will help clean up any class variables that were used, but anything + * not managed as a member variable will probably create a memory leak type + * of situation. Instead of stop, consider using cancel, which can be + * handled by the running thread in a graceful manner. + *@returns True if the thread was stopped, false otherwise. When this + * function returns the thread may not have stopped, to ensure that the + * thread has really stopped, call join. + */ + bool stop(); + + /** + * The workhorse of the Ito class. This is the function that will run in + * the thread, when this function exits the thread dies and is cleaned up + * by the system. Make sure to read up on ItoMutex, ItoCondition, and + * cancel to see how to control and protect everything you do in a safe way + * within this function. + *@returns I'm not sure right now, but this is the posix standard form. + */ + virtual void *run()=0; + + /** + * Join the thread in action. This function performs what is commonly + * called a thread join. That is that it effectively makes the calling + * thread an the Ito thread contained in the called object one in the same, + * and pauses the calling thread until the called thread exits. That is, + * when called from, say, your main(), mythread.join() will not return until + * the thread mythread has exited. This is very handy at the end of + * programs to ensure all of your data was cleaned up. + *@returns True if the thread was joined, false if the thread couldn't be + * joined, usually because it isn't running to begin with. + */ + bool join(); + + private: + pthread_t ptHandle; /**< Internal handle to the posix thread. */ + int nHandle; /**< Numeric handle to the posix thread. */ + + protected: + /** + * This is the hidden-heard of the thread system. While run is what the + * user gets to override, and everything said about it is true, this is + * the function that actually makes up the thread, it simply calls the + * run member function in an OO-friendly way. This is what allows us to + * use member variables from within the thread itself. + *@param Should always be this. + *@returns This is specified by posix, I'm not sure yet. + */ + static void *threadRunner( void *pThread ); + + void yield(); + + }; +} + +#endif diff --git a/src/itoatom.h b/src/itoatom.h new file mode 100644 index 0000000..96090f2 --- /dev/null +++ b/src/itoatom.h @@ -0,0 +1,56 @@ +#ifndef ITO_QUEUE_H +#define ITO_QUEUE_H + +#include + +#include "itomutex.h" +#include "itocondition.h" + +/** + * A thread-safe wrapper class. + *@author Mike Buland + */ +template +class ItoAtom +{ +public: + /** + * Construct an empty queue. + */ + ItoAtom() + { + } + + ItoAtom( const T &src ) : + data( src ) + { + } + + ~ItoQueue() + { + } + + T get() + { + mOperate.lock(); + mOperate.unlock(); + return data; + } + + void set( const T &val ) + { + mOperate.lock(); + data = val; + cBlock.signal(); + mOperate.unlock(); + } + +private: + Item *pStart; /**< The start of the queue, the next element to dequeue. */ + Item *pEnd; /**< The end of the queue, the last element to dequeue. */ + + ItoMutex mOperate; /**< The master mutex, used on all operations. */ + ItoCondition cBlock; /**< The condition for blocking dequeues. */ +}; + +#endif diff --git a/src/itocondition.cpp b/src/itocondition.cpp new file mode 100644 index 0000000..d8f5375 --- /dev/null +++ b/src/itocondition.cpp @@ -0,0 +1,42 @@ +#include + +#include "itocondition.h" + +Bu::ItoCondition::ItoCondition() +{ + pthread_cond_init( &cond, NULL ); +} + +Bu::ItoCondition::~ItoCondition() +{ + pthread_cond_destroy( &cond ); +} + +int Bu::ItoCondition::wait() +{ + return pthread_cond_wait( &cond, &mutex ); +} + +int Bu::ItoCondition::wait( int nSec, int nUSec ) +{ + struct timeval now; + struct timespec timeout; + struct timezone tz; + + gettimeofday( &now, &tz ); + timeout.tv_sec = now.tv_sec + nSec + ((now.tv_usec + nUSec)/1000000); + timeout.tv_nsec = ((now.tv_usec + nUSec)%1000000)*1000; + + return pthread_cond_timedwait( &cond, &mutex, &timeout ); +} + +int Bu::ItoCondition::signal() +{ + return pthread_cond_signal( &cond ); +} + +int Bu::ItoCondition::broadcast() +{ + return pthread_cond_broadcast( &cond ); +} + diff --git a/src/itocondition.h b/src/itocondition.h new file mode 100644 index 0000000..4771b22 --- /dev/null +++ b/src/itocondition.h @@ -0,0 +1,81 @@ +#ifndef ITO_CONDITION_H +#define ITO_CONDITION_H + +#include + +#include "itomutex.h" + +namespace Bu +{ + /** + * Ito condition. This is a fairly simple condition mechanism. As you may + * notice this class inherits from the ItoMutex class, this is because all + * conditions must be within a locked block. The standard usage of a condition + * is to pause one thread, perhaps indefinately, until another thread signals + * that it is alright to procede. + *
+ * Standard usage for the thread that wants to wait is as follows: + *
+	 * ItoCondition cond;
+	 * ... // Perform setup and enter your run loop
+	 * cond.lock();
+	 * while( !isFinished() ) // Could be anything you're waiting for
+	 *     cond.wait();
+	 * ...  // Take care of what you have to.
+	 * cond.unlock();
+	 * 
+ * The usage for the triggering thread is much simpler, when it needs to tell + * the others that it's time to grab some data it calls either signal or + * broadcast. See both of those functions for the difference. + *@author Mike Buland + */ + class ItoCondition : public ItoMutex + { + public: + /** + * Create a condition. + */ + ItoCondition(); + + /** + * Destroy a condition. + */ + ~ItoCondition(); + + /** + * Wait forever, or until signalled. This has to be called from within a + * locked section, i.e. before calling this this object's lock function + * should be called. + */ + int wait(); + + /** + * Wait for a maximum of nSec seconds and nUSec micro-seconds or until + * signalled. This is a little more friendly function if you want to + * perform other operations in the thrad loop that calls this function. + * Like the other wait function, this must be inside a locked section. + *@param nSec The seconds to wait. + *@param nUSec the micro-seconds to wait. + */ + int wait( int nSec, int nUSec ); + + /** + * Notify the next thread waiting on this condition that they can go ahead. + * This only signals one thread, the next one in the condition queue, that + * it is safe to procede with whatever operation was being waited on. + */ + int signal(); + + /** + * Notify all threads waiting on this condition that they can go ahead now. + * This function is slower than signal, but more effective in certain + * situations where you may not know how many threads should be activated. + */ + int broadcast(); + + private: + pthread_cond_t cond; /**< Internal condition reference. */ + }; +} + +#endif diff --git a/src/itomutex.cpp b/src/itomutex.cpp new file mode 100644 index 0000000..dc51af9 --- /dev/null +++ b/src/itomutex.cpp @@ -0,0 +1,27 @@ +#include "itomutex.h" + +Bu::ItoMutex::ItoMutex() +{ + pthread_mutex_init( &mutex, NULL ); +} + +Bu::ItoMutex::~ItoMutex() +{ + pthread_mutex_destroy( &mutex ); +} + +int Bu::ItoMutex::lock() +{ + return pthread_mutex_lock( &mutex ); +} + +int Bu::ItoMutex::unlock() +{ + return pthread_mutex_unlock( &mutex ); +} + +int Bu::ItoMutex::trylock() +{ + return pthread_mutex_trylock( &mutex ); +} + diff --git a/src/itomutex.h b/src/itomutex.h new file mode 100644 index 0000000..80956b8 --- /dev/null +++ b/src/itomutex.h @@ -0,0 +1,61 @@ +#ifndef ITO_MUTEX_H +#define ITO_MUTEX_H + +#include + +namespace Bu +{ + /** + * Simple mutex wrapper. Currently this doesn't do anything extra for you + * except keep all of the functionality together in an OO sorta' way and keep + * you from having to worry about cleaning up your mutexes properly, or initing + * them. + *@author Mike Buland + */ + class ItoMutex + { + public: + /** + * Create an unlocked mutex. + */ + ItoMutex(); + + /** + * Destroy a mutex. This can only be done when a mutex is unlocked. + * Failure to unlock before destroying a mutex object could cause it to + * wait for the mutex to unlock, the odds of which are usually farily low + * at deconstruction time. + */ + ~ItoMutex(); + + /** + * Lock the mutex. This causes all future calls to lock on this instance + * of mutex to block until the first thread that called mutex unlocks it. + * At that point the next thread that called lock will get a chance to go + * to work. Because of the nature of a mutex lock it is a very bad idea to + * do any kind of serious or rather time consuming computation within a + * locked section. This can cause thread-deadlock and your program may + * hang. + */ + int lock(); + + /** + * Unlock the mutex. This allows the next thread that asked for a lock to + * lock the mutex and continue with execution. + */ + int unlock(); + + /** + * Try to lock the mutex. This is the option to go with if you cannot avoid + * putting lengthy operations within a locked section. trylock will attempt + * to lock the mutex, if the mutex is already locked this function returns + * immediately with an error code. + */ + int trylock(); + + protected: + pthread_mutex_t mutex; /**< The internal mutex reference. */ + }; +} + +#endif diff --git a/src/itoqueue.h b/src/itoqueue.h new file mode 100644 index 0000000..322698d --- /dev/null +++ b/src/itoqueue.h @@ -0,0 +1,231 @@ +#ifndef ITO_QUEUE_H +#define ITO_QUEUE_H + +#include + +#include "itomutex.h" +#include "itocondition.h" + +namespace Bu +{ + /** + * A thread-safe queue class. This class is a very simple queue with some cool + * extra functionality for use with the Ito system. The main extra that it + * provides is the option to either dequeue without blocking, with infinite + * blocking, or with timed blocking, which will return a value if something is + * enqueued within the specified time limit, or NULL if the time limit is + * exceded. + *@author Mike Buland + */ + template + class ItoQueue + { + private: + /** + * Helper struct. Keeps track of linked-list items for the queue data. + */ + typedef struct Item + { + T pData; + Item *pNext; + } Item; + + public: + /** + * Construct an empty queue. + */ + ItoQueue() : + pStart( NULL ), + pEnd( NULL ), + nSize( 0 ) + { + } + + /** + * Destroy the queue. This function will simply free all contained + * structures. If you stored pointers in the queue, this will lose the + * pointers without cleaning up the memory they pointed to. Make sure + * you're queue is empty before allowing it to be destroyed! + */ + ~ItoQueue() + { + Item *pCur = pStart; + while( pCur ) + { + Item *pTmp = pCur->pNext; + delete pCur; + pCur = pTmp; + } + } + + /** + * Enqueue a pieces of data. The new data will go at the end of the queue, + * and unless another piece of data is enqueued, will be the last piece of + * data to be dequeued. + *@param pData The data to enqueue. If this is not a primitive data type + * it's probably best to use a pointer type. + */ + void enqueue( T pData ) + { + mOperate.lock(); + + if( pStart == NULL ) + { + pStart = pEnd = new Item; + pStart->pData = pData; + pStart->pNext = NULL; + nSize++; + } + else + { + pEnd->pNext = new Item; + pEnd = pEnd->pNext; + pEnd->pData = pData; + pEnd->pNext = NULL; + nSize++; + } + + cBlock.signal(); + + mOperate.unlock(); + } + + /** + * Dequeue the first item from the queue. This function can operate in two + * different modes, blocking and non-blocking. In non-blocking mode it will + * return immediately weather there was data in the queue or not. If there + * was data it will remove it from the queue and return it to the caller. + * In blocking mode it will block forever wating for data to be enqueued. + * When data finally is enqueued this function will return immediately with + * the new data. The only way this function should ever return a null in + * blocking mode is if the calling thread was cancelled. It's probably a + * good idea to check for NULL return values even if you use blocking, just + * to be on the safe side. + *@param bBlock Set to true to enable blocking, leave as false to work in + * non-blocking mode. + *@returns The next piece of data in the queue, or NULL if no data was in + * the queue. + */ + T dequeue( bool bBlock=false ) + { + mOperate.lock(); + if( pStart == NULL ) + { + mOperate.unlock(); + + if( bBlock ) + { + cBlock.lock(); + + while( pStart == NULL ) + cBlock.wait(); + + T tmp = dequeue( false ); + + cBlock.unlock(); + return tmp; + + } + + return NULL; + } + else + { + T pTmp = pStart->pData; + Item *pDel = pStart; + pStart = pStart->pNext; + delete pDel; + nSize--; + + mOperate.unlock(); + return pTmp; + } + } + + /** + * Operates just like the other dequeue function in blocking mode with one + * twist. This function will block for at most nSec seconds and nUSec + * micro-seconds. If the timer is up and no data is available, this will + * just return NULL. If data is enqueued before the timeout expires, it + * will dequeue and exit immediately. + *@param nSec The number of seconds to wait, max. + *@param nUSec The number of micro-seconds to wait, max. + *@returns The next piece of data in the queue, or NULL if the timeout was + * exceeded. + */ + T dequeue( int nSec, int nUSec ) + { + mOperate.lock(); + if( pStart == NULL ) + { + mOperate.unlock(); + + cBlock.lock(); + + cBlock.wait( nSec, nUSec ); + + if( pStart == NULL ) + { + cBlock.unlock(); + return NULL; + } + + mOperate.lock(); + T pTmp = pStart->pData; + Item *pDel = pStart; + pStart = pStart->pNext; + delete pDel; + nSize--; + mOperate.unlock(); + + cBlock.unlock(); + return pTmp; + } + else + { + T pTmp = pStart->pData; + Item *pDel = pStart; + pStart = pStart->pNext; + delete pDel; + nSize--; + + mOperate.unlock(); + return pTmp; + } + } + + /** + * Checks to see if the queue has data in it or not. Note that there is no + * function to determine the length of the queue. This data isn't kept + * track of. If you really need to know, fix this. + *@returns True if the queue is empty, false if it has data in it. + */ + bool isEmpty() + { + mOperate.lock(); + bool bEmpty = (pStart == NULL ); + mOperate.unlock(); + + return bEmpty; + } + + long getSize() + { + mOperate.lock(); + long nRet = nSize; + mOperate.unlock(); + + return nRet; + } + + private: + Item *pStart; /**< The start of the queue, the next element to dequeue. */ + Item *pEnd; /**< The end of the queue, the last element to dequeue. */ + long nSize; /**< The number of items in the queue. */ + + ItoMutex mOperate; /**< The master mutex, used on all operations. */ + ItoCondition cBlock; /**< The condition for blocking dequeues. */ + }; +} + +#endif diff --git a/src/main.dox b/src/main.dox new file mode 100644 index 0000000..668d2e3 --- /dev/null +++ b/src/main.dox @@ -0,0 +1,14 @@ +/** + *@mainpage libbu++ utility library + * + *@section secIntro Introduction + * + * Libbu++ is a C++ library of general utility classes and functions. They + * cover a wide range of topics from streams and sockets to data structures to + * data serialization and xml handling to threading. + * + */ + +/** + *@namespace Bu The core libbu++ namespace, to ensure things don't get muddied. + */ diff --git a/src/serversocket.cpp b/src/serversocket.cpp new file mode 100644 index 0000000..c53c80d --- /dev/null +++ b/src/serversocket.cpp @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "serversocket.h" +#include "exceptions.h" + +Bu::ServerSocket::ServerSocket( int nPort, int nPoolSize ) : + nPort( nPort ) +{ + /* Create the socket and set it up to accept connections. */ + struct sockaddr_in name; + + /* Give the socket a name. */ + name.sin_family = AF_INET; + name.sin_port = htons( nPort ); + + // I think this specifies who we will accept connections from, + // a good thing to make configurable later on + name.sin_addr.s_addr = htonl( INADDR_ANY ); + + startServer( name, nPoolSize ); +} + +Bu::ServerSocket::ServerSocket(const FString &sAddr,int nPort, int nPoolSize) : + nPort( nPort ) +{ + /* Create the socket and set it up to accept connections. */ + struct sockaddr_in name; + + /* Give the socket a name. */ + name.sin_family = AF_INET; + name.sin_port = htons( nPort ); + + inet_aton( sAddr.getStr(), &name.sin_addr ); + + startServer( name, nPoolSize ); +} + +Bu::ServerSocket::~ServerSocket() +{ +} + +void Bu::ServerSocket::startServer( struct sockaddr_in &name, int nPoolSize ) +{ + /* Create the socket. */ + nServer = socket( PF_INET, SOCK_STREAM, 0 ); + if( nServer < 0 ) + { + throw Bu::SocketException("Couldn't create a listen socket."); + } + + int opt = 1; + setsockopt( + nServer, + SOL_SOCKET, + SO_REUSEADDR, + (char *)&opt, + sizeof( opt ) + ); + + if( bind( nServer, (struct sockaddr *) &name, sizeof(name) ) < 0 ) + { + throw Bu::SocketException("Couldn't bind to the listen socket."); + } + + if( listen( nServer, nPoolSize ) < 0 ) + { + throw Bu::SocketException( + "Couldn't begin listening to the server socket." + ); + } + + FD_ZERO( &fdActive ); + /* Initialize the set of active sockets. */ + FD_SET( nServer, &fdActive ); +} + +int Bu::ServerSocket::accept( int nTimeoutSec, int nTimeoutUSec ) +{ + fd_set fdRead = fdActive; + + struct timeval xT; + + xT.tv_sec = nTimeoutSec; + xT.tv_usec = nTimeoutUSec; + + if( TEMP_FAILURE_RETRY(select( nServer+1, &fdRead, NULL, NULL, &xT )) < 0 ) + { + throw SocketException( + "Error scanning for new connections: %s", strerror( errno ) + ); + } + + if( FD_ISSET( nServer, &fdRead ) ) + { + struct sockaddr_in clientname; + size_t size; + int nClient; + + size = sizeof( clientname ); +#ifdef __CYGWIN__ + nClient = ::accept( nServer, (struct sockaddr *)&clientname, + (int *)&size + ); +#else + nClient = ::accept( nServer, (struct sockaddr *)&clientname, &size ); +#endif + if( nClient < 0 ) + { + throw SocketException( + "Error accepting a new connection: %s", strerror( errno ) + ); + } + char tmpa[20]; + inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 ); + //"New connection from host %s, port %hd.", + // tmpa, ntohs (clientname.sin_port) ); + + { + int flags; + + flags = fcntl( nClient, F_GETFL, 0 ); + flags |= O_NONBLOCK; + if( fcntl( nClient, F_SETFL, flags ) < 0) + { + throw SocketException( + "Error setting option on client socket: %s", + strerror( errno ) + ); + } + } + + return nClient; + } + + return -1; +} + diff --git a/src/serversocket.h b/src/serversocket.h new file mode 100644 index 0000000..9a26e2d --- /dev/null +++ b/src/serversocket.h @@ -0,0 +1,31 @@ +#ifndef SERVER_SOCKET_H +#define SERVER_SOCKET_H + +#include +#include "fstring.h" +#include "socket.h" + +namespace Bu +{ + /** + * + */ + class ServerSocket + { + public: + ServerSocket( int nPort, int nPoolSize=40 ); + ServerSocket( const FString &sAddr, int nPort, int nPoolSize=40 ); + virtual ~ServerSocket(); + + int accept( int nTimeoutSec, int nTimeoutUSec ); + + private: + void startServer( struct sockaddr_in &name, int nPoolSize ); + + fd_set fdActive; + int nServer; + int nPort; + }; +} + +#endif diff --git a/src/socket.cpp b/src/socket.cpp index c4f914b..455b5c8 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -118,6 +118,7 @@ void Bu::Socket::close() //} } +/* void Bu::Socket::read() { char buffer[RBS]; @@ -132,7 +133,6 @@ void Bu::Socket::read() if( nbytes < 0 && errno != 0 && errno != EAGAIN ) { //printf("errno: %d, %s\n", errno, strerror( errno ) ); - /* Read error. */ //perror("readInput"); throw ConnectionException( excodeReadError, @@ -146,15 +146,13 @@ void Bu::Socket::read() break; nTotalRead += nbytes; sReadBuf.append( buffer, nbytes ); - /* Data read. */ if( nbytes < RBS ) { break; } - /* New test, if data is divisible by RBS bytes on some libs the - * read could block, this keeps it from happening. - */ + // New test, if data is divisible by RBS bytes on some libs the + // read could block, this keeps it from happening. { fd_set rfds; FD_ZERO(&rfds); @@ -171,13 +169,7 @@ void Bu::Socket::read() } } } - - /* - if( pProtocol != NULL && nTotalRead > 0 ) - { - pProtocol->onNewData(); - }*/ -} +}*/ size_t Bu::Socket::read( void *pBuf, size_t nBytes ) { diff --git a/src/socket.h b/src/socket.h index 3d0125d..568cad6 100644 --- a/src/socket.h +++ b/src/socket.h @@ -19,7 +19,7 @@ namespace Bu virtual ~Socket(); virtual void close(); - virtual void read(); + //virtual void read(); virtual size_t read( void *pBuf, size_t nBytes ); virtual size_t write( const void *pBuf, size_t nBytes ); @@ -33,6 +33,8 @@ namespace Bu virtual bool canWrite(); virtual bool canSeek(); + + private: int nSocket; bool bActive; diff --git a/src/tests/itoqueue1.cpp b/src/tests/itoqueue1.cpp new file mode 100644 index 0000000..f73f4d3 --- /dev/null +++ b/src/tests/itoqueue1.cpp @@ -0,0 +1,110 @@ +#include +#include "bu/ito.h" +#include "bu/itoqueue.h" + +class Reader : public Bu::Ito +{ +public: + Reader( Bu::ItoQueue &q, int id ) : + q( q ), + id( id ) + { + } + + void *run() + { + for( int i = 0; i < 10; i++ ) + { + std::string *pStr = q.dequeue( true ); + if( pStr == NULL ) + { + printf("Null received...\n"); + } + else + { + printf("[%d] read: %s\n", id, pStr->c_str() ); + delete pStr; + } + usleep( (int)(((double)rand())/((double)RAND_MAX)*2000000.0) ); + } + + return NULL; + } + +private: + Bu::ItoQueue &q; + int id; +}; + +class Writer : public Bu::Ito +{ +public: + Writer( Bu::ItoQueue &q, int id, const char *strbase ) : + q( q ), + strbase( strbase ), + id( id ) + { + } + + void *run() + { + for( int i = 0; i < 11; i++ ) + { + usleep( (int)(((double)rand())/((double)RAND_MAX)*2000000.0) ); + q.enqueue( new std::string( strbase ) ); + printf("[%d] write: %s\n", id, strbase ); + } + + return NULL; + } + +private: + Bu::ItoQueue &q; + const char *strbase; + int id; +}; + +int main() +{ + Writer *wr[5]; + Reader *rd[5]; + const char bob[][7]={ + {"Test 1"}, + {"Test 2"}, + {"Test 3"}, + {"Test 4"}, + {"Test 5"} + }; + + Bu::ItoQueue q; + + for( int j = 0; j < 5; j++ ) + { + wr[j] = new Writer( q, j, bob[j] ); + rd[j] = new Reader( q, j ); + } + + for( int j = 0; j < 5; j++ ) + { + rd[j]->start(); + } + + for( int j = 0; j < 5; j++ ) + { + wr[j]->start(); + } + + for( int j = 0; j < 5; j++ ) + { + rd[j]->join(); + } + + for( int j = 0; j < 5; j++ ) + { + delete wr[j]; + delete rd[j]; + } + + return 0; +} + diff --git a/src/tests/itoqueue2.cpp b/src/tests/itoqueue2.cpp new file mode 100644 index 0000000..f4b5e19 --- /dev/null +++ b/src/tests/itoqueue2.cpp @@ -0,0 +1,83 @@ +#include +#include "bu/ito.h" +#include "bu/itoqueue.h" +#include + +class Reader : public Bu::Ito +{ +public: + Reader( Bu::ItoQueue &q, int id ) : + q( q ), + id( id ) + { + } + + void *run() + { + for( int i = 0; i < 10; i++ ) + { + std::string *pStr = q.dequeue( 0, 500000 ); + if( pStr == NULL ) + { + printf("Null received...\n"); + i--; + } + else + { + printf("[%d] read: %s\n", id, pStr->c_str() ); + delete pStr; + } + } + + return NULL; + } + +private: + Bu::ItoQueue &q; + int id; +}; + +class Writer : public Bu::Ito +{ +public: + Writer( Bu::ItoQueue &q, int id, const char *strbase ) : + q( q ), + strbase( strbase ), + id( id ) + { + } + + void *run() + { + for( int i = 0; i < 11; i++ ) + { + sleep( 2 ); + printf("[%d] write: %s\n", id, strbase ); + q.enqueue( new std::string( strbase ) ); + } + + return NULL; + } + +private: + Bu::ItoQueue &q; + const char *strbase; + int id; +}; + +int main() +{ + printf("ETIMEDOUT: %d\n", ETIMEDOUT ); + Bu::ItoQueue q; + Writer wr( q, 0, "writer" ); + Reader rd( q, 0 ); + + rd.start(); + wr.start(); + + rd.join(); + wr.join(); + + return 0; +} + -- cgit v1.2.3 From e0e7932a122614a0ff566fbfd8de5776de8b9f6d Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 17 May 2007 05:56:26 +0000 Subject: Lots of cool new stuff, the Server class actually works for everything except actually interacting with clients, and the Client class is almost there, except that it doesn't really do anything yet. --- src/client.cpp | 9 +++++++ src/client.h | 23 +++++++++++++++++ src/file.cpp | 10 +++++++ src/file.h | 3 +++ src/list.h | 5 ++++ src/old/singleton.h | 59 ------------------------------------------ src/server.cpp | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/server.h | 49 +++++++++++++++++++++++++++++++++++ src/serversocket.cpp | 5 ++++ src/serversocket.h | 3 ++- src/singleton.h | 62 ++++++++++++++++++++++++++++++++++++++++++++ src/socket.cpp | 9 +++++++ src/socket.h | 3 ++- src/stream.h | 3 +++ src/tests/hash.cpp | 24 +++++++++++++++++ 15 files changed, 279 insertions(+), 61 deletions(-) create mode 100644 src/client.cpp create mode 100644 src/client.h delete mode 100644 src/old/singleton.h create mode 100644 src/server.cpp create mode 100644 src/server.h create mode 100644 src/singleton.h create mode 100644 src/tests/hash.cpp (limited to 'src/socket.h') diff --git a/src/client.cpp b/src/client.cpp new file mode 100644 index 0000000..a048ca3 --- /dev/null +++ b/src/client.cpp @@ -0,0 +1,9 @@ +#include "client.h" + +Bu::Client::Client() +{ +} + +Bu::Client::~Client() +{ +} diff --git a/src/client.h b/src/client.h new file mode 100644 index 0000000..27fbad4 --- /dev/null +++ b/src/client.h @@ -0,0 +1,23 @@ +#ifndef CLIENT_H +#define CLIENT_H + +#include +#include "bu/socket.h" + +namespace Bu +{ + /** + * + */ + class Client + { + public: + Client(); + virtual ~Client(); + + private: + + }; +} + +#endif diff --git a/src/file.cpp b/src/file.cpp index 5de5f6c..26986a5 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -98,3 +98,13 @@ bool Bu::File::canSeek() return true; } +bool Bu::File::isBlocking() +{ + return true; +} + +void Bu::File::setBlocking( bool bBlocking ) +{ + return; +} + diff --git a/src/file.h b/src/file.h index bbc620c..ee3fdb3 100644 --- a/src/file.h +++ b/src/file.h @@ -27,6 +27,9 @@ namespace Bu virtual bool canWrite(); virtual bool canSeek(); + virtual bool isBlocking(); + virtual void setBlocking( bool bBlocking=true ); + private: FILE *fh; diff --git a/src/list.h b/src/list.h index 4d16872..6081ea5 100644 --- a/src/list.h +++ b/src/list.h @@ -217,6 +217,11 @@ namespace Bu { } + const_iterator( const iterator &i ) : + pLink( i.pLink ) + { + } + public: bool operator==( const const_iterator &oth ) const { diff --git a/src/old/singleton.h b/src/old/singleton.h deleted file mode 100644 index 47adbd5..0000000 --- a/src/old/singleton.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef SINGLETON_H -#define SINGLETON_H - -#include - -/** - * Provides singleton functionality in a modular sort of way. Make this the - * base class of any other class and you immediately gain singleton - * functionality. Be sure to make your constructor and various functions use - * intellegent scoping. Cleanup and instantiation are performed automatically - * for you at first use and program exit. There are two things that you must - * do when using this template, first is to inherit from it with the name of - * your class filling in for T and then make this class a friend of your class. - *@code - * // Making the Single Singleton: - * class Single : public Singleton - * { - * friend class Singleton; - * protected: - * Single(); - * ... - * }; - @endcode - * You can still add public functions and variables to your new Singleton child - * class, but your constructor should be protected (hence the need for the - * friend decleration). - *@author Mike Buland - */ -template -class Singleton -{ -protected: - /** - * Private constructor. This constructor is empty but has a body so that - * you can make your own override of it. Be sure that you're override is - * also protected. - */ - Singleton() {}; - -private: - /** - * Copy constructor, defined so that you could write your own as well. - */ - Singleton( const Singleton& ); - -public: - /** - * Get a handle to the contained instance of the contained class. It is - * a reference. - *@returns A reference to the contained object. - */ - static T &getInstance() - { - static T i; - return i; - } -}; - -#endif diff --git a/src/server.cpp b/src/server.cpp new file mode 100644 index 0000000..f93238c --- /dev/null +++ b/src/server.cpp @@ -0,0 +1,73 @@ +#include "server.h" +#include + +Bu::Server::Server() : + nTimeoutSec( 0 ), + nTimeoutUSec( 0 ) +{ + FD_ZERO( &fdActive ); +} + +Bu::Server::~Server() +{ +} + +void Bu::Server::addPort( int nPort, int nPoolSize ) +{ + ServerSocket *s = new ServerSocket( nPort, nPoolSize ); + int nSocket = s->getSocket(); + FD_SET( nSocket, &fdActive ); + hServers.insert( nSocket, s ); +} + +void Bu::Server::addPort( const FString &sAddr, int nPort, int nPoolSize ) +{ + ServerSocket *s = new ServerSocket( sAddr, nPort, nPoolSize ); + int nSocket = s->getSocket(); + FD_SET( nSocket, &fdActive ); + hServers.insert( nSocket, s ); +} + +void Bu::Server::setTimeout( int nTimeoutSec, int nTimeoutUSec ) +{ + this->nTimeoutSec = nTimeoutSec; + this->nTimeoutUSec = nTimeoutUSec; +} + +void Bu::Server::scan() +{ + struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec }; + + fd_set fdRead = fdActive; + fd_set fdWrite = fdActive; + fd_set fdException = fdActive; + + if( TEMP_FAILURE_RETRY( select( FD_SETSIZE, &fdRead, NULL, &fdException, &xTimeout ) ) < 0 ) + { + throw ExceptionBase("Error attempting to scan open connections."); + } + + for( int j = 0; j < FD_SETSIZE; j++ ) + { + if( FD_ISSET( j, &fdRead ) ) + { + if( hServers.has( j ) ) + { + addClient( hServers.get( j )->accept() ); + } + else + { + + } + } + } +} + +void Bu::Server::addClient( int nSocket ) +{ + FD_SET( nSocket, &fdActive ); + + Client *c = new Client(); + hClients.insert( nSocket, c ); +} + diff --git a/src/server.h b/src/server.h new file mode 100644 index 0000000..9f4f459 --- /dev/null +++ b/src/server.h @@ -0,0 +1,49 @@ +#ifndef SERVER_H +#define SERVER_H + +#include +#include "bu/serversocket.h" +#include "bu/list.h" +#include "bu/client.h" + +namespace Bu +{ + /** + * Core of a network server. This class is distinct from a ServerSocket in + * that a ServerSocket is one listening socket, nothing more. Socket will + * manage a pool of both ServerSockets and connected Sockets along with + * their protocols and buffers. + * + * To start serving on a new port, use the addPort functions. Each call to + * addPort creates a new ServerSocket, starts it listening, and adds it to + * the server pool. + * + * All of the real work is done by scan, which will wait for up + * to the timeout set by setTimeout before returning if there is no data + * pending. scan should probably be called in some sort of tight + * loop, possibly in it's own thread, or in the main control loop. + */ + class Server + { + public: + Server(); + virtual ~Server(); + + void addPort( int nPort, int nPoolSize=40 ); + void addPort( const FString &sAddr, int nPort, int nPoolSize=40 ); + + void scan(); + void setTimeout( int nTimeoutSec, int nTimeoutUSec=0 ); + + void addClient( int nSocket ); + + private: + int nTimeoutSec; + int nTimeoutUSec; + fd_set fdActive; + Hash hServers; + Hash hClients; + }; +} + +#endif diff --git a/src/serversocket.cpp b/src/serversocket.cpp index c53c80d..9c8f743 100644 --- a/src/serversocket.cpp +++ b/src/serversocket.cpp @@ -85,6 +85,11 @@ void Bu::ServerSocket::startServer( struct sockaddr_in &name, int nPoolSize ) FD_SET( nServer, &fdActive ); } +int Bu::ServerSocket::getSocket() +{ + return nServer; +} + int Bu::ServerSocket::accept( int nTimeoutSec, int nTimeoutUSec ) { fd_set fdRead = fdActive; diff --git a/src/serversocket.h b/src/serversocket.h index f146d91..d2601e4 100644 --- a/src/serversocket.h +++ b/src/serversocket.h @@ -23,7 +23,8 @@ namespace Bu ServerSocket( const FString &sAddr, int nPort, int nPoolSize=40 ); virtual ~ServerSocket(); - int accept( int nTimeoutSec, int nTimeoutUSec ); + int accept( int nTimeoutSec=0, int nTimeoutUSec=0 ); + int getSocket(); private: void startServer( struct sockaddr_in &name, int nPoolSize ); diff --git a/src/singleton.h b/src/singleton.h new file mode 100644 index 0000000..4976a61 --- /dev/null +++ b/src/singleton.h @@ -0,0 +1,62 @@ +#ifndef SINGLETON_H +#define SINGLETON_H + +#include + +namespace Bu +{ + /** + * Provides singleton functionality in a modular sort of way. Make this the + * base class of any other class and you immediately gain singleton + * functionality. Be sure to make your constructor and various functions use + * intellegent scoping. Cleanup and instantiation are performed automatically + * for you at first use and program exit. There are two things that you must + * do when using this template, first is to inherit from it with the name of + * your class filling in for T and then make this class a friend of your class. + *@code + * // Making the Single Singleton: + * class Single : public Singleton + * { + * friend class Singleton; + * protected: + * Single(); + * ... + * }; + @endcode + * You can still add public functions and variables to your new Singleton child + * class, but your constructor should be protected (hence the need for the + * friend decleration). + *@author Mike Buland + */ + template + class Singleton + { + protected: + /** + * Private constructor. This constructor is empty but has a body so that + * you can make your own override of it. Be sure that you're override is + * also protected. + */ + Singleton() {}; + + private: + /** + * Copy constructor, defined so that you could write your own as well. + */ + Singleton( const Singleton& ); + + public: + /** + * Get a handle to the contained instance of the contained class. It is + * a reference. + *@returns A reference to the contained object. + */ + static T &getInstance() + { + static T i; + return i; + } + }; +} + +#endif diff --git a/src/socket.cpp b/src/socket.cpp index 455b5c8..441678a 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -231,3 +231,12 @@ bool Bu::Socket::canSeek() return false; } +bool Bu::Socket::isBlocking() +{ + return false; +} + +void Bu::Socket::setBlocking( bool bBlocking ) +{ +} + diff --git a/src/socket.h b/src/socket.h index 568cad6..e65eb74 100644 --- a/src/socket.h +++ b/src/socket.h @@ -33,7 +33,8 @@ namespace Bu virtual bool canWrite(); virtual bool canSeek(); - + virtual bool isBlocking(); + virtual void setBlocking( bool bBlocking=true ); private: int nSocket; diff --git a/src/stream.h b/src/stream.h index e640959..5f586e6 100644 --- a/src/stream.h +++ b/src/stream.h @@ -36,6 +36,9 @@ namespace Bu virtual bool canWrite() = 0; virtual bool canSeek() = 0; + virtual bool isBlocking() = 0; + virtual void setBlocking( bool bBlocking=true ) = 0; + private: }; diff --git a/src/tests/hash.cpp b/src/tests/hash.cpp new file mode 100644 index 0000000..73cfb27 --- /dev/null +++ b/src/tests/hash.cpp @@ -0,0 +1,24 @@ +#include "bu/hash.h" +#include "bu/sptr.h" + +typedef struct Bob +{ + int nID; +} Bob; + +int main() +{ + Bu::Hash > lb; + for( int j = 0; j < 10; j++ ) + { + Bob *b = new Bob; + b->nID = j; + lb.insert( j, b ); + } + + for( int j = 0; j < 10; j++ ) + { + printf("%d\n", lb[j].value()->nID ); + } +} + -- cgit v1.2.3 From 5f39066a4f561e9a94a6cc9293ab9b978ebf1f81 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sun, 10 Jun 2007 21:28:14 +0000 Subject: Bunch of maintenence type things. Minor tweaks and the like. The file class has a lot more helper functions and the like, the filters give more info back to the caller, minor updates to taf. --- src/bzip2.cpp | 41 ++++++++++++++++++++++++++++++++++------- src/bzip2.h | 2 +- src/file.cpp | 31 +++++++++++++++++++++++++++++++ src/file.h | 17 ++++++++++++++++- src/filter.cpp | 7 ++++++- src/filter.h | 4 +++- src/socket.cpp | 4 ++++ src/socket.h | 2 ++ src/stream.h | 2 ++ src/tafnode.cpp | 6 +++--- src/tafnode.h | 4 ++-- src/tests/taf.cpp | 2 +- 12 files changed, 105 insertions(+), 17 deletions(-) (limited to 'src/socket.h') diff --git a/src/bzip2.cpp b/src/bzip2.cpp index 433fc91..5423a10 100644 --- a/src/bzip2.cpp +++ b/src/bzip2.cpp @@ -26,16 +26,18 @@ void Bu::BZip2::start() pBuf = new char[nBufSize]; } -void Bu::BZip2::stop() +size_t Bu::BZip2::stop() { if( bzState.state ) { if( bReading ) { BZ2_bzDecompressEnd( &bzState ); + return 0; } else { + size_t sTotal = 0; for(;;) { bzState.next_in = NULL; @@ -45,14 +47,16 @@ void Bu::BZip2::stop() int res = BZ2_bzCompress( &bzState, BZ_FINISH ); if( bzState.avail_out < nBufSize ) { - rNext.write( pBuf, nBufSize-bzState.avail_out ); + sTotal += rNext.write( pBuf, nBufSize-bzState.avail_out ); } if( res == BZ_STREAM_END ) break; } BZ2_bzCompressEnd( &bzState ); + return sTotal; } } + return 0; } void Bu::BZip2::bzError( int code ) @@ -63,13 +67,35 @@ void Bu::BZip2::bzError( int code ) return; case BZ_CONFIG_ERROR: - throw ExceptionBase("The bzip2 library has been miscompiled."); + throw ExceptionBase("BZip2: Library configured improperly, reinstall."); + + case BZ_SEQUENCE_ERROR: + throw ExceptionBase("BZip2: Functions were called in an invalid sequence."); case BZ_PARAM_ERROR: - throw ExceptionBase("bzip2 parameter error."); + throw ExceptionBase("BZip2: Invalid parameter was passed into a function."); case BZ_MEM_ERROR: - throw ExceptionBase("Not enough memory available for bzip2."); + throw ExceptionBase("BZip2: Couldn't allocate sufficient memory."); + + case BZ_DATA_ERROR: + throw ExceptionBase("BZip2: Data was corrupted before decompression."); + + case BZ_DATA_ERROR_MAGIC: + throw ExceptionBase("BZip2: Stream does not appear to be bzip2 data."); + + case BZ_IO_ERROR: + throw ExceptionBase("BZip2: File couldn't be read from / written to."); + + case BZ_UNEXPECTED_EOF: + throw ExceptionBase("BZip2: End of file encountered before end of stream."); + + case BZ_OUTBUFF_FULL: + throw ExceptionBase("BZip2: Buffer not large enough to accomidate data."); + + default: + throw ExceptionBase("BZip2: Unknown error encountered."); + } } @@ -124,6 +150,7 @@ size_t Bu::BZip2::write( const void *pData, size_t nBytes ) if( bReading == true ) throw ExceptionBase("This bzip2 filter is in reading mode, you can't write."); + size_t sTotalOut = 0; bzState.next_in = (char *)pData; bzState.avail_in = nBytes; for(;;) @@ -135,12 +162,12 @@ size_t Bu::BZip2::write( const void *pData, size_t nBytes ) if( bzState.avail_out < nBufSize ) { - rNext.write( pBuf, nBufSize-bzState.avail_out ); + sTotalOut += rNext.write( pBuf, nBufSize-bzState.avail_out ); } if( bzState.avail_in == 0 ) break; } - return 0; + return sTotalOut; } diff --git a/src/bzip2.h b/src/bzip2.h index 056f336..a23f07a 100644 --- a/src/bzip2.h +++ b/src/bzip2.h @@ -18,7 +18,7 @@ namespace Bu virtual ~BZip2(); virtual void start(); - virtual void stop(); + virtual size_t stop(); virtual size_t read( void *pBuf, size_t nBytes ); virtual size_t write( const void *pBuf, size_t nBytes ); diff --git a/src/file.cpp b/src/file.cpp index 26986a5..14b6e54 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -1,6 +1,8 @@ #include "file.h" #include "exceptions.h" #include +#include +#include Bu::File::File( const char *sName, const char *sFlags ) { @@ -11,6 +13,20 @@ Bu::File::File( const char *sName, const char *sFlags ) } } +Bu::File::File( const Bu::FString &sName, const char *sFlags ) +{ + fh = fopen( sName.getStr(), sFlags ); + if( fh == NULL ) + { + throw Bu::FileException( errno, strerror(errno) ); + } +} + +Bu::File::File( int fd, const char *sFlags ) +{ + fh = fdopen( fd, sFlags ); +} + Bu::File::~File() { close(); @@ -108,3 +124,18 @@ void Bu::File::setBlocking( bool bBlocking ) return; } +void Bu::File::truncate( long nSize ) +{ + ftruncate( fileno( fh ), nSize ); +} + +void Bu::File::flush() +{ + fflush( fh ); +} + +void Bu::File::chmod( mode_t t ) +{ + fchmod( fileno( fh ), t ); +} + diff --git a/src/file.h b/src/file.h index ee3fdb3..8107a1b 100644 --- a/src/file.h +++ b/src/file.h @@ -3,7 +3,8 @@ #include -#include "stream.h" +#include "bu/stream.h" +#include "bu/fstring.h" namespace Bu { @@ -11,6 +12,8 @@ namespace Bu { public: File( const char *sName, const char *sFlags ); + File( const Bu::FString &sName, const char *sFlags ); + File( int fd, const char *sFlags ); virtual ~File(); virtual void close(); @@ -23,6 +26,8 @@ namespace Bu virtual void setPosEnd( long pos ); virtual bool isEOS(); + virtual void flush(); + virtual bool canRead(); virtual bool canWrite(); virtual bool canSeek(); @@ -30,6 +35,16 @@ namespace Bu virtual bool isBlocking(); virtual void setBlocking( bool bBlocking=true ); + inline static Bu::File tempFile( Bu::FString &sName, const char *sFlags ) + { + int afh_d = mkstemp( sName.getStr() ); + + return Bu::File( afh_d, sFlags ); + } + + void truncate( long nSize ); + void chmod( mode_t t ); + private: FILE *fh; diff --git a/src/filter.cpp b/src/filter.cpp index d3faa00..693fb9f 100644 --- a/src/filter.cpp +++ b/src/filter.cpp @@ -7,7 +7,7 @@ Bu::Filter::Filter( Bu::Stream &rNext ) : Bu::Filter::~Filter() { - printf("-> Bu::Filter::~Filter()\n"); + //printf("-> Bu::Filter::~Filter()\n"); } /* void Bu::Filter::start() @@ -75,3 +75,8 @@ void Bu::Filter::setBlocking( bool bBlocking ) rNext.setBlocking( bBlocking ); } +void Bu::Filter::flush() +{ + rNext.flush(); +} + diff --git a/src/filter.h b/src/filter.h index b068206..088d46e 100644 --- a/src/filter.h +++ b/src/filter.h @@ -33,7 +33,7 @@ namespace Bu virtual ~Filter(); virtual void start()=0; - virtual void stop()=0; + virtual size_t stop()=0; virtual void close(); virtual long tell(); virtual void seek( long offset ); @@ -41,6 +41,8 @@ namespace Bu virtual void setPosEnd( long pos ); virtual bool isEOS(); + virtual void flush(); + virtual bool canRead(); virtual bool canWrite(); virtual bool canSeek(); diff --git a/src/socket.cpp b/src/socket.cpp index 441678a..1832898 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -240,3 +240,7 @@ void Bu::Socket::setBlocking( bool bBlocking ) { } +void Bu::Socket::flush() +{ +} + diff --git a/src/socket.h b/src/socket.h index e65eb74..30a43fb 100644 --- a/src/socket.h +++ b/src/socket.h @@ -29,6 +29,8 @@ namespace Bu virtual void setPosEnd( long pos ); virtual bool isEOS(); + virtual void flush(); + virtual bool canRead(); virtual bool canWrite(); virtual bool canSeek(); diff --git a/src/stream.h b/src/stream.h index fa0a606..a80586b 100644 --- a/src/stream.h +++ b/src/stream.h @@ -32,6 +32,8 @@ namespace Bu virtual void setPosEnd( long pos ) = 0; virtual bool isEOS() = 0; + virtual void flush() = 0; + virtual bool canRead() = 0; virtual bool canWrite() = 0; virtual bool canSeek() = 0; diff --git a/src/tafnode.cpp b/src/tafnode.cpp index 3060606..b9a4a24 100644 --- a/src/tafnode.cpp +++ b/src/tafnode.cpp @@ -45,7 +45,7 @@ const Bu::TafNode::PropList &Bu::TafNode::getProperties( const Bu::FString &sNam return hProp.get( sName ); } -const Bu::TafNode::NodeList &Bu::TafNode::getNodes( const Bu::FString &sName ) const +const Bu::TafNode::NodeList &Bu::TafNode::getChildren( const Bu::FString &sName ) const { return hChildren.get( sName ); } @@ -55,9 +55,9 @@ const Bu::FString &Bu::TafNode::getProperty( const Bu::FString &sName ) const return getProperties( sName ).first(); } -const Bu::TafNode *Bu::TafNode::getNode( const Bu::FString &sName ) const +const Bu::TafNode *Bu::TafNode::getChild( const Bu::FString &sName ) const { - return getNodes( sName ).first(); + return getChildren( sName ).first(); } void Bu::TafNode::setName( const Bu::FString &sName ) diff --git a/src/tafnode.h b/src/tafnode.h index 10232d2..08f78e8 100644 --- a/src/tafnode.h +++ b/src/tafnode.h @@ -28,9 +28,9 @@ namespace Bu void setProperty( Bu::FString sName, Bu::FString sValue ); const Bu::FString &getProperty( const Bu::FString &sName ) const; - const TafNode *getNode( const Bu::FString &sName ) const; const PropList &getProperties( const Bu::FString &sName ) const; - const NodeList &getNodes( const Bu::FString &sName ) const; + const TafNode *getChild( const Bu::FString &sName ) const; + const NodeList &getChildren( const Bu::FString &sName ) const; void addChild( TafNode *pNode ); private: diff --git a/src/tests/taf.cpp b/src/tests/taf.cpp index e7bad52..d135e78 100644 --- a/src/tests/taf.cpp +++ b/src/tests/taf.cpp @@ -8,7 +8,7 @@ int main() Bu::TafNode *pNode = tr.getNode(); - const Bu::TafNode *pStats = pNode->getNode("stats"); + const Bu::TafNode *pStats = pNode->getChild("stats"); printf("%s\n", pStats->getName().getStr() ); printf(" str = %s\n", pStats->getProperty("str").getStr() ); -- cgit v1.2.3 From 8b12972092777af56ae21f65b41f4c40d52c2367 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Mon, 18 Jun 2007 19:42:34 +0000 Subject: Added the protocol class. servers work, but don't send data, updated the streams to include many more state indicators and caps queries, and everything is working better in general. --- src/bzip2.cpp | 7 +++++- src/bzip2.h | 2 ++ src/client.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/client.h | 20 +++++++++++++--- src/file.cpp | 17 +++++++++++++- src/file.h | 6 ++++- src/filter.cpp | 19 ++++++++++++++-- src/filter.h | 6 ++++- src/protocol.cpp | 12 ++++++++++ src/protocol.h | 26 +++++++++++++++++++++ src/server.cpp | 11 ++++++--- src/server.h | 8 +++++-- src/socket.cpp | 48 ++++++++++++++++++++++++++++++++------- src/socket.h | 6 ++++- src/stream.h | 35 +++++++++++++++++++++++++++- 15 files changed, 266 insertions(+), 26 deletions(-) create mode 100644 src/protocol.cpp create mode 100644 src/protocol.h (limited to 'src/socket.h') diff --git a/src/bzip2.cpp b/src/bzip2.cpp index d3f237a..66786e4 100644 --- a/src/bzip2.cpp +++ b/src/bzip2.cpp @@ -128,7 +128,7 @@ size_t Bu::BZip2::read( void *pData, size_t nBytes ) { if( bzState.avail_in > 0 ) { - if( rNext.canSeek() ) + if( rNext.isSeekable() ) { rNext.seek( -bzState.avail_in ); } @@ -185,3 +185,8 @@ size_t Bu::BZip2::write( const void *pData, size_t nBytes ) return sTotalOut; } +bool Bu::BZip2::isOpen() +{ + return (bzState.state != NULL); +} + diff --git a/src/bzip2.h b/src/bzip2.h index a23f07a..25f10c5 100644 --- a/src/bzip2.h +++ b/src/bzip2.h @@ -22,6 +22,8 @@ namespace Bu virtual size_t read( void *pBuf, size_t nBytes ); virtual size_t write( const void *pBuf, size_t nBytes ); + virtual bool isOpen(); + private: void bzError( int code ); bz_stream bzState; diff --git a/src/client.cpp b/src/client.cpp index a33cdc3..cf96424 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1,6 +1,16 @@ -#include "client.h" +#include "bu/client.h" +#include "bu/socket.h" +#include +#include +#include "bu/exceptions.h" +#include "bu/protocol.h" -Bu::Client::Client() +/** Read buffer size. */ +#define RBS (1024*2) + +Bu::Client::Client( Bu::Socket *pSocket ) : + pSocket( pSocket ), + pProto( NULL ) { } @@ -8,3 +18,58 @@ Bu::Client::~Client() { } +void Bu::Client::processInput() +{ + char buf[RBS]; + size_t nRead, nTotal=0; + + for(;;) + { + nRead = pSocket->read( buf, nRead ); + if( nRead < 0 ) + { + throw Bu::ConnectionException( + excodeReadError, + "Read error: %s", + strerror( errno ) + ); + } + else if( nRead == 0 ) + { + break; + } + else + { + nTotal += nRead; + sReadBuf.append( buf, nRead ); + if( !pSocket->canRead() ) + break; + } + } + + if( pProto && nTotal ) + { + pProto->onNewData( this ); + } +} + +void Bu::Client::setProtocol( Protocol *pProto ) +{ + this->pProto = pProto; +} + +Bu::Protocol *Bu::Client::getProtocol() +{ + return pProto; +} + +void Bu::Client::clearProtocol() +{ + pProto = NULL; +} + +Bu::FString &Bu::Client::getInput() +{ + return sReadBuf; +} + diff --git a/src/client.h b/src/client.h index 27fbad4..1a189e2 100644 --- a/src/client.h +++ b/src/client.h @@ -2,21 +2,35 @@ #define CLIENT_H #include -#include "bu/socket.h" + +#include "bu/fstring.h" namespace Bu { + class Protocol; + class Socket; + /** * */ class Client { public: - Client(); + Client( Bu::Socket *pSocket ); virtual ~Client(); - private: + void processInput(); + Bu::FString &getInput(); + + void setProtocol( Protocol *pProto ); + Bu::Protocol *getProtocol(); + void clearProtocol(); + + private: + Bu::Socket *pSocket; + Bu::Protocol *pProto; + Bu::FString sReadBuf; }; } diff --git a/src/file.cpp b/src/file.cpp index 2965afa..368b788 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -109,7 +109,17 @@ bool Bu::File::canWrite() return true; } -bool Bu::File::canSeek() +bool Bu::File::isReadable() +{ + return true; +} + +bool Bu::File::isWritable() +{ + return true; +} + +bool Bu::File::isSeekable() { return true; } @@ -139,3 +149,8 @@ void Bu::File::chmod( mode_t t ) fchmod( fileno( fh ), t ); } +bool Bu::File::isOpen() +{ + return (fh != NULL); +} + diff --git a/src/file.h b/src/file.h index 8107a1b..fe8dbda 100644 --- a/src/file.h +++ b/src/file.h @@ -25,12 +25,16 @@ namespace Bu virtual void setPos( long pos ); virtual void setPosEnd( long pos ); virtual bool isEOS(); + virtual bool isOpen(); virtual void flush(); virtual bool canRead(); virtual bool canWrite(); - virtual bool canSeek(); + + virtual bool isReadable(); + virtual bool isWritable(); + virtual bool isSeekable(); virtual bool isBlocking(); virtual void setBlocking( bool bBlocking=true ); diff --git a/src/filter.cpp b/src/filter.cpp index 693fb9f..96a8694 100644 --- a/src/filter.cpp +++ b/src/filter.cpp @@ -50,6 +50,11 @@ bool Bu::Filter::isEOS() return rNext.isEOS(); } +bool Bu::Filter::isOpen() +{ + return rNext.isOpen(); +} + bool Bu::Filter::canRead() { return rNext.canRead(); @@ -60,9 +65,19 @@ bool Bu::Filter::canWrite() return rNext.canWrite(); } -bool Bu::Filter::canSeek() +bool Bu::Filter::isReadable() +{ + return rNext.isReadable(); +} + +bool Bu::Filter::isWritable() +{ + return rNext.isWritable(); +} + +bool Bu::Filter::isSeekable() { - return rNext.canSeek(); + return rNext.isSeekable(); } bool Bu::Filter::isBlocking() diff --git a/src/filter.h b/src/filter.h index 088d46e..7bb04bc 100644 --- a/src/filter.h +++ b/src/filter.h @@ -40,12 +40,16 @@ namespace Bu virtual void setPos( long pos ); virtual void setPosEnd( long pos ); virtual bool isEOS(); + virtual bool isOpen(); virtual void flush(); virtual bool canRead(); virtual bool canWrite(); - virtual bool canSeek(); + + virtual bool isReadable(); + virtual bool isWritable(); + virtual bool isSeekable(); virtual bool isBlocking(); virtual void setBlocking( bool bBlocking=true ); diff --git a/src/protocol.cpp b/src/protocol.cpp new file mode 100644 index 0000000..0976b3b --- /dev/null +++ b/src/protocol.cpp @@ -0,0 +1,12 @@ +#include "bu/protocol.h" + +using namespace Bu; + +Bu::Protocol::Protocol() +{ +} + +Bu::Protocol::~Protocol() +{ +} + diff --git a/src/protocol.h b/src/protocol.h new file mode 100644 index 0000000..3accd99 --- /dev/null +++ b/src/protocol.h @@ -0,0 +1,26 @@ +#ifndef PROTOCOL_H +#define PROTOCOL_H + +#include + +namespace Bu +{ + class Client; + + /** + * + */ + class Protocol + { + public: + Protocol(); + virtual ~Protocol(); + + virtual void onNewData( Bu::Client *pClient )=0; + + private: + + }; +} + +#endif diff --git a/src/server.cpp b/src/server.cpp index abf4c5b..bceeb81 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1,5 +1,8 @@ -#include "server.h" +#include "bu/server.h" #include +#include "bu/serversocket.h" +#include "bu/client.h" +#include "bu/socket.h" Bu::Server::Server() : nTimeoutSec( 0 ), @@ -58,7 +61,7 @@ void Bu::Server::scan() } else { - + hClients.get( j )->processInput(); } } } @@ -68,7 +71,9 @@ void Bu::Server::addClient( int nSocket, int nPort ) { FD_SET( nSocket, &fdActive ); - Client *c = new Client(); + Client *c = new Client( + new Bu::Socket( nSocket ) + ); hClients.insert( nSocket, c ); onNewConnection( c, nPort ); diff --git a/src/server.h b/src/server.h index 942eb32..3331d2c 100644 --- a/src/server.h +++ b/src/server.h @@ -2,12 +2,16 @@ #define SERVER_H #include -#include "bu/serversocket.h" + +#include "bu/fstring.h" #include "bu/list.h" -#include "bu/client.h" namespace Bu { + class ServerSocket; + class Socket; + class Client; + /** * Core of a network server. This class is distinct from a ServerSocket in * that a ServerSocket is one listening socket, nothing more. Socket will diff --git a/src/socket.cpp b/src/socket.cpp index 1832898..bd05024 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -109,13 +109,6 @@ void Bu::Socket::close() ::close( nSocket ); } bActive = false; - //xInputBuf.clearData(); - //xOutputBuf.clearData(); - //if( pProtocol != NULL ) - //{ - // delete pProtocol; - // pProtocol = NULL; - //} } /* @@ -218,15 +211,49 @@ bool Bu::Socket::isEOS() bool Bu::Socket::canRead() { + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(nSocket, &rfds); + struct timeval tv = { 0, 0 }; + int retval = select( nSocket+1, &rfds, NULL, NULL, &tv ); + if( retval == -1 ) + throw ConnectionException( + excodeBadReadError, + "Bad Read error" + ); + if( !FD_ISSET( nSocket, &rfds ) ) + return false; return true; } bool Bu::Socket::canWrite() { + fd_set wfds; + FD_ZERO(&wfds); + FD_SET(nSocket, &wfds); + struct timeval tv = { 0, 0 }; + int retval = select( nSocket+1, NULL, &wfds, NULL, &tv ); + if( retval == -1 ) + throw ConnectionException( + excodeBadReadError, + "Bad Read error" + ); + if( !FD_ISSET( nSocket, &wfds ) ) + return false; return true; } -bool Bu::Socket::canSeek() +bool Bu::Socket::isReadable() +{ + return true; +} + +bool Bu::Socket::isWritable() +{ + return true; +} + +bool Bu::Socket::isSeekable() { return false; } @@ -244,3 +271,8 @@ void Bu::Socket::flush() { } +bool Bu::Socket::isOpen() +{ + return bActive; +} + diff --git a/src/socket.h b/src/socket.h index 30a43fb..c9dbd8d 100644 --- a/src/socket.h +++ b/src/socket.h @@ -28,12 +28,16 @@ namespace Bu virtual void setPos( long pos ); virtual void setPosEnd( long pos ); virtual bool isEOS(); + virtual bool isOpen(); virtual void flush(); virtual bool canRead(); virtual bool canWrite(); - virtual bool canSeek(); + + virtual bool isReadable(); + virtual bool isWritable(); + virtual bool isSeekable(); virtual bool isBlocking(); virtual void setBlocking( bool bBlocking=true ); diff --git a/src/stream.h b/src/stream.h index a80586b..ba070d3 100644 --- a/src/stream.h +++ b/src/stream.h @@ -31,12 +31,45 @@ namespace Bu virtual void setPos( long pos ) = 0; virtual void setPosEnd( long pos ) = 0; virtual bool isEOS() = 0; + virtual bool isOpen() = 0; virtual void flush() = 0; + /** + * In non-blocking streams this indicates if a read operation will + * return data at the moment or not. In blocking streams this should + * return the same value as isEOS(). + */ virtual bool canRead() = 0; + + /** + * In non-blocking streams this indicates if a write operation will + * succeed or fail. In some cases writing is not allowed (e.g. + * internal buffers are full) temporarilly. In blocking streams this + * should return the same value as isWritable. + */ virtual bool canWrite() = 0; - virtual bool canSeek() = 0; + + /** + * Indicates if the stream is capable of read operations. This does not + * indicate if such operations will return useful data, see canRead for + * that. + */ + virtual bool isReadable() = 0; + + /** + * Indicates if the stream is capable of write operations. This does + * not indicate if such operations will succeed or fail, see canWrite + * for that. + */ + virtual bool isWritable() = 0; + + /** + * Indicates if the stream is capable of seek operations. This is + * generally false for non-blocking streams. Some buffered streams may + * support limited in-buffer seeking. + */ + virtual bool isSeekable() = 0; virtual bool isBlocking() = 0; virtual void setBlocking( bool bBlocking=true ) = 0; -- cgit v1.2.3 From 932677862376e9642a496a15b7f09f1106f495a5 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 28 Jun 2007 20:49:39 +0000 Subject: Many minor changes, hopefully the header fixes will keep future header macro conflicts from happening. And, from now on, other projects should do -Ilibbu++ not -Ilibbu++/src so we can get ready for an installed version of libbu++. --- bu | 1 + src/archival.h | 4 ++-- src/archive.h | 4 ++-- src/atom.h | 4 ++-- src/bzip2.h | 4 ++-- src/client.h | 4 ++-- src/exceptionbase.h | 4 ++-- src/exceptions.h | 4 ++-- src/file.h | 4 ++-- src/filter.h | 4 ++-- src/fstring.h | 4 ++-- src/hash.h | 4 ++-- src/ito.h | 4 ++-- src/itoatom.h | 4 ++-- src/itocondition.h | 4 ++-- src/itomutex.h | 4 ++-- src/itoqueue.h | 4 ++-- src/linkmessage.h | 4 ++-- src/list.h | 4 ++-- src/membuf.h | 4 ++-- src/paramproc.h | 4 ++-- src/plugger.h | 4 ++-- src/programchain.h | 4 ++-- src/programlink.h | 4 ++-- src/protocol.h | 4 ++-- src/ringbuffer.h | 4 ++-- src/server.h | 4 ++-- src/serversocket.h | 4 ++-- src/singleton.h | 4 ++-- src/socket.h | 4 ++-- src/sptr.h | 4 ++-- src/stream.h | 4 ++-- src/unitsuite.h | 4 ++-- 33 files changed, 65 insertions(+), 64 deletions(-) create mode 120000 bu (limited to 'src/socket.h') diff --git a/bu b/bu new file mode 120000 index 0000000..02b8847 --- /dev/null +++ b/bu @@ -0,0 +1 @@ +src/bu/ \ No newline at end of file diff --git a/src/archival.h b/src/archival.h index e2c803c..8be3308 100644 --- a/src/archival.h +++ b/src/archival.h @@ -1,5 +1,5 @@ -#ifndef ARCHIVAL_H -#define ARCHIVAL_H +#ifndef BU_ARCHIVAL_H +#define BU_ARCHIVAL_H namespace Bu { diff --git a/src/archive.h b/src/archive.h index 05c6f57..6c0c1df 100644 --- a/src/archive.h +++ b/src/archive.h @@ -1,5 +1,5 @@ -#ifndef ARCHIVE_H -#define ARCHIVE_H +#ifndef BU_ARCHIVE_H +#define BU_ARCHIVE_H #include #include diff --git a/src/atom.h b/src/atom.h index a0469b6..fad47eb 100644 --- a/src/atom.h +++ b/src/atom.h @@ -1,5 +1,5 @@ -#ifndef ATOM_H -#define ATOM_H +#ifndef BU_ATOM_H +#define BU_ATOM_H #include #include diff --git a/src/bzip2.h b/src/bzip2.h index 25f10c5..0a111e8 100644 --- a/src/bzip2.h +++ b/src/bzip2.h @@ -1,5 +1,5 @@ -#ifndef B_ZIP2_H -#define B_ZIP2_H +#ifndef BU_BZIP2_H +#define BU_BZIP2_H #include #include diff --git a/src/client.h b/src/client.h index 02ba077..cee558d 100644 --- a/src/client.h +++ b/src/client.h @@ -1,5 +1,5 @@ -#ifndef CLIENT_H -#define CLIENT_H +#ifndef BU_CLIENT_H +#define BU_CLIENT_H #include diff --git a/src/exceptionbase.h b/src/exceptionbase.h index fd78089..24e4bbf 100644 --- a/src/exceptionbase.h +++ b/src/exceptionbase.h @@ -1,5 +1,5 @@ -#ifndef EXCEPTION_BASE_H -#define EXCEPTION_BASE_H +#ifndef BU_EXCEPTION_BASE_H +#define BU_EXCEPTION_BASE_H #include #include diff --git a/src/exceptions.h b/src/exceptions.h index d5a9d39..b824b91 100644 --- a/src/exceptions.h +++ b/src/exceptions.h @@ -1,5 +1,5 @@ -#ifndef EXCEPTIONS_H -#define EXCEPTIONS_H +#ifndef BU_EXCEPTIONS_H +#define BU_EXCEPTIONS_H #include "exceptionbase.h" #include diff --git a/src/file.h b/src/file.h index 0f638a7..d4e43eb 100644 --- a/src/file.h +++ b/src/file.h @@ -1,5 +1,5 @@ -#ifndef FILE_H -#define FILE_H +#ifndef BU_FILE_H +#define BU_FILE_H #include diff --git a/src/filter.h b/src/filter.h index 7bb04bc..bd557b2 100644 --- a/src/filter.h +++ b/src/filter.h @@ -1,5 +1,5 @@ -#ifndef FILTER_H -#define FILTER_H +#ifndef BU_FILTER_H +#define BU_FILTER_H #include diff --git a/src/fstring.h b/src/fstring.h index 7180f5f..bf6518b 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -1,5 +1,5 @@ -#ifndef F_STRING_H -#define F_STRING_H +#ifndef BU_F_STRING_H +#define BU_F_STRING_H #include #include diff --git a/src/hash.h b/src/hash.h index 6c4a443..0fa3af7 100644 --- a/src/hash.h +++ b/src/hash.h @@ -1,5 +1,5 @@ -#ifndef HASH_H -#define HASH_H +#ifndef BU_HASH_H +#define BU_HASH_H #include #include diff --git a/src/ito.h b/src/ito.h index 01253f5..c062052 100644 --- a/src/ito.h +++ b/src/ito.h @@ -1,5 +1,5 @@ -#ifndef ITO_H -#define ITO_H +#ifndef BU_ITO_H +#define BU_ITO_H #include diff --git a/src/itoatom.h b/src/itoatom.h index 96090f2..7fc9090 100644 --- a/src/itoatom.h +++ b/src/itoatom.h @@ -1,5 +1,5 @@ -#ifndef ITO_QUEUE_H -#define ITO_QUEUE_H +#ifndef BU_ITO_QUEUE_H +#define BU_ITO_QUEUE_H #include diff --git a/src/itocondition.h b/src/itocondition.h index 4771b22..1793f81 100644 --- a/src/itocondition.h +++ b/src/itocondition.h @@ -1,5 +1,5 @@ -#ifndef ITO_CONDITION_H -#define ITO_CONDITION_H +#ifndef BU_ITO_CONDITION_H +#define BU_ITO_CONDITION_H #include diff --git a/src/itomutex.h b/src/itomutex.h index 80956b8..9c9d205 100644 --- a/src/itomutex.h +++ b/src/itomutex.h @@ -1,5 +1,5 @@ -#ifndef ITO_MUTEX_H -#define ITO_MUTEX_H +#ifndef BU_ITO_MUTEX_H +#define BU_ITO_MUTEX_H #include diff --git a/src/itoqueue.h b/src/itoqueue.h index 322698d..75a2f27 100644 --- a/src/itoqueue.h +++ b/src/itoqueue.h @@ -1,5 +1,5 @@ -#ifndef ITO_QUEUE_H -#define ITO_QUEUE_H +#ifndef BU_ITO_QUEUE_H +#define BU_ITO_QUEUE_H #include diff --git a/src/linkmessage.h b/src/linkmessage.h index 64b8bc2..baa22a6 100644 --- a/src/linkmessage.h +++ b/src/linkmessage.h @@ -1,8 +1,8 @@ /**\file linkmessage.h */ -#ifndef LINKMESSAGE_H -#define LINKMESSAGE_H +#ifndef BU_LINKMESSAGE_H +#define BU_LINKMESSAGE_H namespace Bu { diff --git a/src/list.h b/src/list.h index 314459e..6235619 100644 --- a/src/list.h +++ b/src/list.h @@ -1,5 +1,5 @@ -#ifndef LIST_H -#define LIST_H +#ifndef BU_LIST_H +#define BU_LIST_H #include #include "bu/exceptionbase.h" diff --git a/src/membuf.h b/src/membuf.h index 877b35e..b82f943 100644 --- a/src/membuf.h +++ b/src/membuf.h @@ -1,5 +1,5 @@ -#ifndef MEM_BUF_H -#define MEM_BUF_H +#ifndef BU_MEM_BUF_H +#define BU_MEM_BUF_H #include diff --git a/src/paramproc.h b/src/paramproc.h index beee4a0..2bca588 100644 --- a/src/paramproc.h +++ b/src/paramproc.h @@ -1,5 +1,5 @@ -#ifndef PARAM_PROC_H -#define PARAM_PROC_H +#ifndef BU_PARAM_PROC_H +#define BU_PARAM_PROC_H #include #include diff --git a/src/plugger.h b/src/plugger.h index 4d2e7af..79a3271 100644 --- a/src/plugger.h +++ b/src/plugger.h @@ -1,5 +1,5 @@ -#ifndef PLUGGER_H -#define PLUGGER_H +#ifndef BU_PLUGGER_H +#define BU_PLUGGER_H #include "bu/hash.h" diff --git a/src/programchain.h b/src/programchain.h index e73d659..336a9f1 100644 --- a/src/programchain.h +++ b/src/programchain.h @@ -1,5 +1,5 @@ -#ifndef PROGRAMCHAIN_H -#define PROGRAMCHAIN_H +#ifndef BU_PROGRAMCHAIN_H +#define BU_PROGRAMCHAIN_H #include "bu/list.h" #include "bu/linkmessage.h" diff --git a/src/programlink.h b/src/programlink.h index 7c31a18..07d7489 100644 --- a/src/programlink.h +++ b/src/programlink.h @@ -1,5 +1,5 @@ -#ifndef PROGRAMLINK_H -#define PROGRAMLINK_H +#ifndef BU_PROGRAMLINK_H +#define BU_PROGRAMLINK_H #include "bu/linkmessage.h" #include "bu/programchain.h" diff --git a/src/protocol.h b/src/protocol.h index 3accd99..c7a9275 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -1,5 +1,5 @@ -#ifndef PROTOCOL_H -#define PROTOCOL_H +#ifndef BU_PROTOCOL_H +#define BU_PROTOCOL_H #include diff --git a/src/ringbuffer.h b/src/ringbuffer.h index 625f65b..be80e2f 100644 --- a/src/ringbuffer.h +++ b/src/ringbuffer.h @@ -1,5 +1,5 @@ -#ifndef RING_BUFFER_H -#define RING_BUFFER_H +#ifndef BU_RING_BUFFER_H +#define BU_RING_BUFFER_H #include #include "bu/exceptionbase.h" diff --git a/src/server.h b/src/server.h index 07eef95..302b6e3 100644 --- a/src/server.h +++ b/src/server.h @@ -1,5 +1,5 @@ -#ifndef SERVER_H -#define SERVER_H +#ifndef BU_SERVER_H +#define BU_SERVER_H #include diff --git a/src/serversocket.h b/src/serversocket.h index cb86078..b4ee247 100644 --- a/src/serversocket.h +++ b/src/serversocket.h @@ -1,5 +1,5 @@ -#ifndef SERVER_SOCKET_H -#define SERVER_SOCKET_H +#ifndef BU_SERVER_SOCKET_H +#define BU_SERVER_SOCKET_H #include #include "bu/fstring.h" diff --git a/src/singleton.h b/src/singleton.h index 4976a61..c43d71b 100644 --- a/src/singleton.h +++ b/src/singleton.h @@ -1,5 +1,5 @@ -#ifndef SINGLETON_H -#define SINGLETON_H +#ifndef BU_SINGLETON_H +#define BU_SINGLETON_H #include diff --git a/src/socket.h b/src/socket.h index c9dbd8d..0ccee3b 100644 --- a/src/socket.h +++ b/src/socket.h @@ -1,5 +1,5 @@ -#ifndef SOCKET_H -#define SOCKET_H +#ifndef BU_SOCKET_H +#define BU_SOCKET_H #include diff --git a/src/sptr.h b/src/sptr.h index 4baa697..75851a6 100644 --- a/src/sptr.h +++ b/src/sptr.h @@ -1,5 +1,5 @@ -#ifndef SPTR_H -#define SPTR_H +#ifndef BU_SPTR_H +#define BU_SPTR_H #include #include diff --git a/src/stream.h b/src/stream.h index 056de0c..1e236a6 100644 --- a/src/stream.h +++ b/src/stream.h @@ -1,5 +1,5 @@ -#ifndef STREAM_H -#define STREAM_H +#ifndef BU_STREAM_H +#define BU_STREAM_H #include #include diff --git a/src/unitsuite.h b/src/unitsuite.h index 6e9270a..578b4cc 100644 --- a/src/unitsuite.h +++ b/src/unitsuite.h @@ -1,5 +1,5 @@ -#ifndef UNIT_SUITE_H -#define UNIT_SUITE_H +#ifndef BU_UNIT_SUITE_H +#define BU_UNIT_SUITE_H #include #include -- cgit v1.2.3 From f896b0e207e0b656109ef0e9f721f27ce53a836e Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Thu, 28 Jun 2007 22:47:03 +0000 Subject: Client code is better, so is the socket, you can get addresses and other cool things from it. The plugger had yet another bugfix...plugger... --- src/client.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++- src/client.h | 10 +++++++++- src/plugger.h | 6 +++--- src/socket.cpp | 12 ++++++++++++ src/socket.h | 2 ++ 5 files changed, 79 insertions(+), 5 deletions(-) (limited to 'src/socket.h') diff --git a/src/client.cpp b/src/client.cpp index 0e48285..63822ba 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -10,7 +10,8 @@ Bu::Client::Client( Bu::Socket *pSocket ) : pSocket( pSocket ), - pProto( NULL ) + pProto( NULL ), + nRBOffset( 0 ) { } @@ -103,3 +104,54 @@ void Bu::Client::write( const char *pData, int nBytes ) sWriteBuf.append( pData, nBytes ); } +void Bu::Client::write( int8_t nData ) +{ + sWriteBuf.append( (const char *)&nData, sizeof(nData) ); +} + +void Bu::Client::write( int16_t nData ) +{ + sWriteBuf.append( (const char *)&nData, sizeof(nData) ); +} + +void Bu::Client::write( int32_t nData ) +{ + sWriteBuf.append( (const char *)&nData, sizeof(nData) ); +} + +void Bu::Client::write( int64_t nData ) +{ + sWriteBuf.append( (const char *)&nData, sizeof(nData) ); +} + +void Bu::Client::read( char *pData, int nBytes ) +{ + memcpy( pData, sReadBuf.getStr()+nRBOffset, nBytes ); + nRBOffset += nBytes; + if( sReadBuf.getSize()-nRBOffset == 0 ) + { + sReadBuf.clear(); + nRBOffset = 0; + } + // This is an experimental threshold, maybe I'll make this configurable + // later on. + else if( + (sReadBuf.getSize() >= 1024 && nRBOffset >= sReadBuf.getSize()/2) || + (nRBOffset >= sReadBuf.getSize()/4) + ) + { + sReadBuf.trimFront( nRBOffset ); + nRBOffset = 0; + } +} + +long Bu::Client::getInputSize() +{ + return sReadBuf.getSize()-nRBOffset; +} + +const Bu::Socket *Bu::Client::getSocket() const +{ + return pSocket; +} + diff --git a/src/client.h b/src/client.h index f228e96..b400bb3 100644 --- a/src/client.h +++ b/src/client.h @@ -25,7 +25,12 @@ namespace Bu Bu::FString &getInput(); Bu::FString &getOutput(); void write( const char *pData, int nBytes ); - void read( const char *pData, int nBytes ); + void write( int8_t nData ); + void write( int16_t nData ); + void write( int32_t nData ); + void write( int64_t nData ); + void read( char *pData, int nBytes ); + long getInputSize(); void setProtocol( Protocol *pProto ); Bu::Protocol *getProtocol(); @@ -33,10 +38,13 @@ namespace Bu bool isOpen(); + const Bu::Socket *getSocket() const; + private: Bu::Socket *pSocket; Bu::Protocol *pProto; Bu::FString sReadBuf; + int nRBOffset; Bu::FString sWriteBuf; }; } diff --git a/src/plugger.h b/src/plugger.h index 79a3271..615a662 100644 --- a/src/plugger.h +++ b/src/plugger.h @@ -37,7 +37,7 @@ namespace Bu { \ delete pCls; \ } \ - PluginInfo classname = { \ + Bu::PluginInfo classname = { \ #classname, name, ver, rev, \ create ##classname, destroy ##classname }; \ } @@ -52,7 +52,7 @@ namespace Bu { \ delete pCls; \ } \ - PluginInfo pluginname = { \ + Bu::PluginInfo pluginname = { \ #pluginname, name, ver, rev, \ (void *(*)())(create ##classname), \ (void (*)( void * ))(destroy ##classname) }; \ @@ -68,7 +68,7 @@ namespace Bu { \ delete pCls; \ } \ - PluginInfo structname = { \ + Bu::PluginInfo structname = { \ #pluginname, name, ver, rev, \ (void *(*)())(create ##classname), \ (void (*)( void * ))(destroy ##classname) }; \ diff --git a/src/socket.cpp b/src/socket.cpp index bd05024..5a3097c 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -276,3 +276,15 @@ bool Bu::Socket::isOpen() return bActive; } +Bu::FString Bu::Socket::getAddress() const +{ + struct sockaddr_in addr; + socklen_t len = sizeof(addr); + addr.sin_family = AF_INET; + getsockname( nSocket, (sockaddr *)(&addr), &len ); + char buf[150]; + sprintf( buf, "%s", inet_ntoa( addr.sin_addr ) ); + + return buf; +} + diff --git a/src/socket.h b/src/socket.h index 0ccee3b..9e36041 100644 --- a/src/socket.h +++ b/src/socket.h @@ -42,6 +42,8 @@ namespace Bu virtual bool isBlocking(); virtual void setBlocking( bool bBlocking=true ); + Bu::FString getAddress() const; + private: int nSocket; bool bActive; -- cgit v1.2.3 From bd865cee5f89116c1f054cd0e5c275e97c2d0a9b Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Mon, 2 Jul 2007 20:35:44 +0000 Subject: The list has an isEmpty funcion, and the socket may have a new read function soon, check it out...later... --- src/list.h | 5 +++++ src/socket.cpp | 4 ++++ src/socket.h | 1 + 3 files changed, 10 insertions(+) (limited to 'src/socket.h') diff --git a/src/list.h b/src/list.h index 6235619..e05ebbc 100644 --- a/src/list.h +++ b/src/list.h @@ -471,6 +471,11 @@ namespace Bu { return *pLast->pValue; } + + const bool isEmpty() const + { + return (nSize == 0); + } private: Link *pFirst; diff --git a/src/socket.cpp b/src/socket.cpp index 5a3097c..e567061 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -174,6 +174,10 @@ size_t Bu::Socket::read( void *pBuf, size_t nBytes ) return nRead; } +//size_t Bu::Socket::read( void *pBuf, size_t nBytes, uint32_t nTimeout ) +//{ +//} + size_t Bu::Socket::write( const void *pBuf, size_t nBytes ) { int nWrote = TEMP_FAILURE_RETRY( ::write( nSocket, pBuf, nBytes ) ); diff --git a/src/socket.h b/src/socket.h index 9e36041..c291549 100644 --- a/src/socket.h +++ b/src/socket.h @@ -21,6 +21,7 @@ namespace Bu virtual void close(); //virtual void read(); virtual size_t read( void *pBuf, size_t nBytes ); + virtual size_t read( void *pBuf, size_t nBytes, uint32_t nTimeout ); virtual size_t write( const void *pBuf, size_t nBytes ); virtual long tell(); -- cgit v1.2.3