diff --git a/apps/enclave/Makefile b/apps/enclave/Makefile.cygwin similarity index 96% rename from apps/enclave/Makefile rename to apps/enclave/Makefile.cygwin index 948eaa9aa..351b31575 100644 --- a/apps/enclave/Makefile +++ b/apps/enclave/Makefile.cygwin @@ -57,7 +57,8 @@ OBJS = $(OBJDIR)/bigint.o \ $(OBJDIR)/random.o \ $(OBJDIR)/rpc.o \ $(OBJDIR)/sam.o \ - $(OBJDIR)/sha1.o + $(OBJDIR)/sha1.o \ + $(OBJDIR)/thread.o # # Build rules diff --git a/apps/enclave/Makefile.linux b/apps/enclave/Makefile.linux new file mode 100644 index 000000000..218ef7b6f --- /dev/null +++ b/apps/enclave/Makefile.linux @@ -0,0 +1,88 @@ +# +# This Makefile is compatible with GNU Make and should work on Linux +# (Tested on Debian 3.0) +# + +# +# Your operating environment +# + +OS = LINUX + +# +# Directories +# + +BINDIR = bin +LOGDIR = log +OBJDIR = obj +SRCDIR = src + +SAMINCDIR = ../sam/c/inc +SAMLIBDIR = ../sam/c/lib +TOMCRYPTDIR = $(HOME)/libtomcrypt-0.96 + +# +# Programs +# + +CC = g++ + +# +# Flags +# + +CFLAGS = -g -march=i486 -pipe -Wall +CFLAGS += -DOS=$(OS) + +# +# Libraries +# + +CFLAGS += -I$(SAMINCDIR) -I$(TOMCRYPTDIR) +LDFLAGS = -L$(SAMLIBDIR) -L$(TOMCRYPTDIR) +LIBS = -lsam -ltomcrypt -lpthread + +# +# Object files +# + +OBJS = $(OBJDIR)/bigint.o \ + $(OBJDIR)/chk.o \ + $(OBJDIR)/config.o \ + $(OBJDIR)/logger.o \ + $(OBJDIR)/main.o \ + $(OBJDIR)/mutex.o \ + $(OBJDIR)/peers.o \ + $(OBJDIR)/random.o \ + $(OBJDIR)/rpc.o \ + $(OBJDIR)/sam.o \ + $(OBJDIR)/sha1.o \ + $(OBJDIR)/thread.o + +# +# Build rules +# + +all: depend enclave + +depend: + $(CC) $(CFLAGS) -MM $(SRCDIR)/*.cpp > .depend + +$(OBJDIR)/%.o: $(SRCDIR)/%.cpp + $(CC) $(CFLAGS) -o $@ -c $< + +enclave: $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(BINDIR)/enclave $(OBJS) $(LIBS) + +# +# Cleanup rules +# + +clean: + -rm -f $(BINDIR)/* $(OBJDIR)/* .depend + +clean-logs: + -rm -f $(LOGDIR)/* + +tidy: clean clean-logs diff --git a/apps/enclave/Makefile.mingw b/apps/enclave/Makefile.mingw new file mode 100644 index 000000000..50268e2ed --- /dev/null +++ b/apps/enclave/Makefile.mingw @@ -0,0 +1,88 @@ +# +# This Makefile is compatible with GNU Make and should work on Linux +# (Tested on Debian 3.0) +# + +# +# Your operating environment +# + +OS = MINGW + +# +# Directories +# + +BINDIR = bin +LOGDIR = log +OBJDIR = obj +SRCDIR = src + +SAMINCDIR = C:\cygwin\home\Administrator\cvs\i2p\apps\sam\c\inc +SAMLIBDIR = C:\cygwin\home\Administrator\cvs\i2p\apps\sam\c\lib +TOMCRYPTDIR = C:\cygwin\home\Administrator\libtomcrypt-0.96 + +# +# Programs +# + +CC = C:\Dev-Cpp\bin\g++ + +# +# Flags +# + +CFLAGS = -g -march=i486 -pipe -Wall +CFLAGS += -DOS=$(OS) + +# +# Libraries +# + +CFLAGS += -I$(SAMINCDIR) -I$(TOMCRYPTDIR) +LDFLAGS = -L$(SAMLIBDIR) -L$(TOMCRYPTDIR) +LIBS = -lsam -ltomcrypt + +# +# Object files +# + +OBJS = $(OBJDIR)/bigint.o \ + $(OBJDIR)/chk.o \ + $(OBJDIR)/config.o \ + $(OBJDIR)/logger.o \ + $(OBJDIR)/main.o \ + $(OBJDIR)/mutex.o \ + $(OBJDIR)/peers.o \ + $(OBJDIR)/random.o \ + $(OBJDIR)/rpc.o \ + $(OBJDIR)/sam.o \ + $(OBJDIR)/sha1.o \ + $(OBJDIR)/thread.o + +# +# Build rules +# + +all: depend enclave + +depend: + $(CC) $(CFLAGS) -MM $(SRCDIR)/*.cpp > .depend + +$(OBJDIR)/%.o: $(SRCDIR)/%.cpp + $(CC) $(CFLAGS) -o $@ -c $< + +enclave: $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(BINDIR)/enclave $(OBJS) $(LIBS) + +# +# Cleanup rules +# + +clean: + -rm -f $(BINDIR)/* $(OBJDIR)/* .depend + +clean-logs: + -rm -f $(LOGDIR)/* + +tidy: clean clean-logs diff --git a/apps/enclave/src/mutex.cpp b/apps/enclave/src/mutex.cpp index 8d8d2cc3a..f4a123e92 100644 --- a/apps/enclave/src/mutex.cpp +++ b/apps/enclave/src/mutex.cpp @@ -34,7 +34,7 @@ Mutex::Mutex(void) { #ifdef WINTHREADS - mutex = CreateMutex(NULL, false, NULL); + mutex = CreateMutex(NULL, FALSE, NULL); if (mutex == NULL) { LERROR << strerror(rc) << '\n'; throw runtime_error(strerror(rc)); @@ -65,6 +65,9 @@ Mutex::~Mutex(void) #endif } +/* + * Locks the mutex + */ void Mutex::lock(void) { #ifdef WINTHREADS @@ -82,6 +85,9 @@ void Mutex::lock(void) #endif } +/* + * Unlocks the mutex + */ void Mutex::unlock(void) { #ifdef WINTHREADS diff --git a/apps/enclave/src/platform.hpp b/apps/enclave/src/platform.hpp index d4a8a201a..d9b32f768 100644 --- a/apps/enclave/src/platform.hpp +++ b/apps/enclave/src/platform.hpp @@ -81,6 +81,8 @@ using namespace std; /* * Local includes */ +#include "mutex.hpp" // Mutex (for thread.hpp) +#include "thread.hpp" // Thread #include "logger.hpp" // Logger #include "config.hpp" // Config #include "sam_error.hpp" // for sam.hpp diff --git a/apps/enclave/src/sam.cpp b/apps/enclave/src/sam.cpp index 8df1f7f61..052748f46 100644 --- a/apps/enclave/src/sam.cpp +++ b/apps/enclave/src/sam.cpp @@ -71,7 +71,7 @@ Sam::Sam(const string& samhost, uint16_t samport, const string& destname, Sam::~Sam(void) { delete peers; // this must be before set_connected(false)! - if (get_connected()) { + if (is_connected()) { sam_close(); set_connected(false); } @@ -89,7 +89,7 @@ Sam::~Sam(void) void Sam::connect(const char* samhost, uint16_t samport, const char* destname, uint_t tunneldepth) { - assert(!get_connected()); + assert(!is_connected()); LMINOR << "Connecting to SAM as '" << destname << "'\n"; samerr_t rc = sam_connect(samhost, samport, destname, SAM_DGRAM, tunneldepth); if (rc == SAM_OK) @@ -114,7 +114,7 @@ void Sam::load_peers(void) */ void Sam::naming_lookup(const string& name) const { - assert(get_connected()); + assert(is_connected()); sam_naming_lookup(name.c_str()); } @@ -127,7 +127,7 @@ void Sam::naming_lookup(const string& name) const */ void Sam::parse_dgram(const string& dest, void* data, size_t size) { - assert(get_connected()); + assert(is_connected()); Peer* peer = peers->new_peer(dest); Rpc rpc(peer); rpc.parse(data, size); @@ -140,7 +140,7 @@ void Sam::parse_dgram(const string& dest, void* data, size_t size) */ void Sam::read_buffer(void) { - assert(get_connected()); + assert(is_connected()); sam_read_buffer(); } @@ -153,6 +153,7 @@ void Sam::read_buffer(void) */ void Sam::send_dgram(const string& dest, uchar_t *data, size_t size) { + assert(is_connected()); samerr_t rc = sam_dgram_send(dest.c_str(), data, size); assert(rc == SAM_OK); // i.e. not SAM_TOO_BIG } @@ -189,10 +190,10 @@ bool Sam::valid_dest(const string& dest) { if (dest.size() != 516) return false; - if (dest.substr(512, 4) == "AAAA") // note this AAAA signifies a null - return true; // certificate - may not be true in the - else // future - return false; + if (dest.substr(512, 4) == "AAAA") // Note this AAAA signifies a null + return true; // certificate and doesn't actually have + else // any bearing on validity, but we'll + return false; // keep this check here for now anyway } /* diff --git a/apps/enclave/src/sam.hpp b/apps/enclave/src/sam.hpp index cff2f3f80..87b74ec78 100644 --- a/apps/enclave/src/sam.hpp +++ b/apps/enclave/src/sam.hpp @@ -55,7 +55,7 @@ class Sam { private: void connect(const char* samhost, uint16_t samport, const char* destname, uint_t tunneldepth); - bool get_connected(void) const { return connected; } + bool is_connected(void) const { return connected; } bool connected; static bool exists; diff --git a/apps/enclave/src/thread.cpp b/apps/enclave/src/thread.cpp new file mode 100644 index 000000000..832420c1c --- /dev/null +++ b/apps/enclave/src/thread.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2004, Matthew P. Cashdollar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the author nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Based on JThread by Jori Liesenborgs (MIT License) and SAM Threads (public +// domain) by Nickster + +// JThread license: (just in case this is necessary) +/* + + This file is a part of the JThread package, which contains some object- + oriented thread wrappers for different thread implementations. + + Copyright (c) 2000-2001 Jori Liesenborgs (jori@lumumba.luc.ac.be) + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +*/ + +#include "platform.hpp" +#include "mutex.hpp" +#include "thread.hpp" + +Thread::Thread(void) +{ + retval = 0; + running = false; +} + +Thread::~Thread(void) +{ + kill(); +} + +/* + * Gets the return value of a finished thread + */ +void* Thread::get_retval(void) +{ + void* val; + running_m.lock(); + if (running) + val = 0; + else + val = retval; + running_m.unlock(); + return val; +} + +/* + * Checks if the thread is running + * + * Returns: true if it is running, false if it isn't + */ +bool Thread::is_running(void) +{ + running_m.lock(); + bool r = running; + running_m.unlock(); + return r; +} + +/* + * Stops the thread + * Generally NOT a good idea + */ +void Thread::kill(void) +{ + running_m.lock(); + assert(running); +#ifdef WINTHREADS + if (!TerminateThread(handle, 0)) { + TCHAR str[80]; + LERROR << win_strerror(str, sizeof str) << '\n'; + throw runtime_error(str); + } +#else + int rc = pthread_cancel(id); + if (rc != 0) { + LERROR << strerror(rc); + throw runtime_error(strerror(rc)); + } +#endif + running = false; + running_m.unlock(); +} + +/* + * Starts the thread + */ +void Thread::start(void) +{ + #ifndef NDEBUG + // check whether the thread is already running + running_m.lock(); + assert(!running); + running_m.unlock(); + #endif + continue_m.lock(); +#ifdef WINTHREADS + handle = CreateThread(NULL, 0, &the_thread, this, 0, &id); + if (handle == NULL) { + TCHAR str[80]; + LERROR << win_strerror(str, sizeof str) << '\n'; + throw runtime_error(str); + } +#else + int rc = pthread_create(&id, NULL, &the_thread, this); + if (rc != 0) { + continue_m.unlock(); + LERROR << strerror(rc) << '\n'; + throw runtime_error(strerror(rc)); + } +#endif + // Wait until `running' is set + running_m.lock(); + while (!running) { + running_m.unlock(); + running_m.lock(); + } + running_m.unlock(); + continue_m.unlock(); +} + +/* + * Wrapper for the thread + */ +void* Thread::the_thread(void *param) +{ + Thread* t = static_cast(param); + t->running_m.lock(); + t->running = true; + t->running_m.unlock(); + // wait until we can continue + t->continue_m.lock(); + t->continue_m.unlock(); + void* ret = t->execute(); + t->running_m.lock(); + t->running = false; + t->retval = ret; + t->running_m.unlock(); + return 0; +} diff --git a/apps/enclave/src/thread.hpp b/apps/enclave/src/thread.hpp new file mode 100644 index 000000000..f69c52901 --- /dev/null +++ b/apps/enclave/src/thread.hpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2004, Matthew P. Cashdollar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the author nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef THREAD_HPP +#define THREAD_HPP + +class Thread { + public: + Thread(void); + virtual ~Thread(void); + + virtual void *execute(void) = 0; + void* get_retval(void); + bool is_running(void); + void kill(void); + void start(void); + + private: +#ifdef WINTHREADS + static DWORD WINAPI the_thread(void* param); + HANDLE handle; + DWORD id; +#else + static void* the_thread(void* param); + pthread_t id; +#endif + void *retval; + bool running; + Mutex running_m; + Mutex continue_m; +}; + +#endif // THREAD_HPP