The unified diff between revisions [c49ffbac..] and [f14eeb09..] is displayed below. It can also be downloaded as a raw diff.
#
#
# patch "CMakeLists.txt"
# from [18636ea3906b9ed2f5f5a743e4f56de17dd5527c]
# to [78742225b5b8ab63006a5fba774babcc9621f217]
#
# patch "fritz.cc"
# from [233ddad13ebbc258c71edd11ef663d61fb8e1f4a]
# to [2d49a74e4937692d814a6a833af55df52f1af0f9]
#
# patch "fritz.hh"
# from [8e3312ac5309aafc33e25d03671eea7ed1db4a5c]
# to [0a09a9981868e04ed9e93bab0af8a66c79f87559]
#
============================================================
--- CMakeLists.txt 18636ea3906b9ed2f5f5a743e4f56de17dd5527c
+++ CMakeLists.txt 78742225b5b8ab63006a5fba774babcc9621f217
@@ -1,4 +1,10 @@
project (fritz.it)
+add_executable (fritz_server fritz.cc fritz_server.cc)
+target_link_libraries (fritz_server rt dl)
+
+add_library (fritz_client SHARED fritz_client.cc fritz.cc)
+target_link_libraries (fritz_client rt dl)
+
+add_executable (fritz_this fritz_this.cc)
-add_executable (fritz.it fritz.cc)
============================================================
--- fritz.cc 233ddad13ebbc258c71edd11ef663d61fb8e1f4a
+++ fritz.cc 2d49a74e4937692d814a6a833af55df52f1af0f9
@@ -7,134 +7,282 @@
* All rights reserved.
*/
-#include <sys/errno.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <semaphore.h>
-#include <fcntl.h>
-#include <unistd.h>
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <exception>
+#include <dlfcn.h>
+/* some general design notes:
+ * data is exchanged via a shared memory page
+ * a pair of semaphores are used to hand control of the page between
+ * the client and the server; a normal sequence is
+ *
+ * client server
+ ******************************************
+ * [ create semaphores, shared memory ]
+ * sem_wait (client)
+ * sem_post (client)
+ * sem_wait (server)
+ * sem_post (server)
+ * [ copy data into shm ]
+ */
+
+
#include "fritz.hh"
-class fritz_exception: public std::exception
+/*** Fritzer ***/
+
+Fritzer::Fritzer (void)
{
-private:
- const char *err;
-
-public:
- fritz_exception (const char *e)
- {
- err = e;
+ client_sem = server_sem = NULL;
+ initialise_from_environ ();
+}
+
+void
+Fritzer::initialise_from_environ (void)
+{
+ my_pid = getpid ();
+ shm_name = getenv ("FRITZ_SHM");
+ client_sem_name = getenv ("FRITZ_CLIENT_SEM");
+ server_sem_name = getenv ("FRITZ_SERVER_SEM");
+ if (!shm_name || !server_sem_name || !client_sem_name ) {
+ throw fritz_exception ("FRITZ_SHM, FRITZ_CLIENT)SEM and FRITZ_SERVER_SEM must be set.");
}
- virtual const char* what() const throw()
- {
- char *s_err;
-
- s_err = strerror (errno);
- std::cout << "from errno: " << s_err << std::endl;
- return err;
+}
+
+void
+Fritzer::map_the_shm (void)
+{
+ shm_mem = mmap ((void *)NULL, shm_size, PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, (off_t)0);
+ if (shm_mem <= 0) {
+ throw fritz_exception("Unable to map shared memory.");
}
-};
+ fritz_params = (struct fritz_params *)shm_mem;
+}
-class FritzServer {
-private:
- static const int shm_size=(1024*16);
- const char *shm_name;
- int shm_fd;
- void *shm_mem;
- struct fritz_params *fritz_params;
- pid_t my_pid;
+void
+Fritzer::update_params (void)
+{
+ fritz_params->buffer_size = shm_size;
+ fritz_params->pid = my_pid;
+}
+
+sem_t *
+Fritzer::open_semaphore (const char *name)
+{
+ sem_t *rv;
- const char *sem_name;
- sem_t *sem;
+ rv = sem_open (name, 0);
+ if ((rv == SEM_FAILED) || (!rv)) {
+ throw fritz_exception ("Unable top open semaphore.");
+ }
+ return rv;
+}
- void wait_for_request ();
+sem_t *
+Fritzer::create_semaphore (const char *name)
+{
+ sem_t *rv;
+
+ /* a bit brutal */
+ sem_unlink (name);
+ rv = sem_open (name, O_CREAT|O_EXCL, 0600, 0);
+ if ((rv == SEM_FAILED) || (!rv)) {
+ throw fritz_exception ("Unable to create semaphore.");
+ }
+ return rv;
+}
-public:
- FritzServer (const char *, const char *);
- ~FritzServer (void);
- void run (void);
-};
+void
+Fritzer::close_semaphores (void)
+{
+ sem_close (client_sem);
+ sem_close (server_sem);
+ client_sem = server_sem = NULL;
+}
-FritzServer::FritzServer (const char *a_shm_name, const char *a_sem_name)
+size_t
+Fritzer::get_message_id (void)
{
- std::cout << "Fritz starting up." << std::endl;
-
- my_pid = getpid ();
- shm_name = a_shm_name;
- /* the fruncate will fail if we're not creating the file from scratch */
+ return fritz_params->message_id;
+}
+
+/*** FritzServer ***/
+
+void
+FritzServer::create_shared_memory (void)
+{
shm_fd = 0;
- for (int i=0;i<2;i++) {
- shm_fd = shm_open (shm_name, O_RDWR|O_CREAT|O_EXCL, 0600);
- if (shm_fd < 0) {
- std::cout << "Unlinking old shared memory segment." << std::endl;
- shm_unlink (shm_name);
- } else {
- break;
- }
- }
+ /* a bit brutal */
+ shm_unlink (shm_name);
+ shm_fd = shm_open (shm_name, O_RDWR|O_CREAT|O_EXCL, 0600);
if (shm_fd < 0) {
throw fritz_exception ("Unable to open shared memory segment.");
}
if (ftruncate (shm_fd, shm_size) == -1) {
throw fritz_exception ("Unable to truncate shared memory segment.");
}
- shm_mem = mmap ((void *)NULL, shm_size, PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, (off_t)0);
- if (shm_mem <= 0) {
- throw fritz_exception("Unable to map shared memory.");
+}
+
+void
+FritzServer::wait_for_client (void)
+{
+ if (sem_wait (client_sem) == -1) {
+ throw fritz_exception ("Error waiting on semaphore for control.");
}
- fritz_params = (struct fritz_params *)shm_mem;
- memset (fritz_params, 0, sizeof (struct fritz_params));
- sem_name = a_sem_name;
- sem = sem_open (sem_name, O_CREAT, 0600, 0);
- if ((int)sem == SEM_FAILED) {
- throw fritz_exception ("Unable to open semaphore.");
- }
}
+void
+FritzServer::create_semaphores (void)
+{
+ server_sem = create_semaphore (server_sem_name);
+ client_sem = create_semaphore (client_sem_name);
+}
+
+FritzServer::FritzServer (void)
+{
+ mode = "server";
+ create_semaphores ();
+ create_shared_memory ();
+ map_the_shm ();
+ fritz_params->message_id = 0;
+}
+
FritzServer::~FritzServer (void)
{
- std::cout << "Fritz is terminating." << std::endl;
shm_unlink (shm_name);
- sem_close (sem);
- sem_unlink (sem_name);
+ close_semaphores ();
+ sem_unlink (client_sem_name);
+ sem_unlink (server_sem_name);
}
void
-FritzServer::wait_for_request (void)
+FritzServer::signal_client (void)
{
- fritz_params->buffer_size = shm_size;
- fritz_params->pid = my_pid;
- fritz_params->message_id++;
- std::cout << "Waiting to acquire semaphore." << std::endl;
- if (sem_wait (sem) == -1) {
- throw fritz_exception ("Error waiting on semaphore.");
+ if (sem_post (server_sem) == -1) {
+ throw fritz_exception ("Unable to sem_post");
+ }
+}
+
+void
+FritzServer::rewrite (void)
+{
+ for (size_t i=0;i<fritz_params->contents_size;i++) {
+ ((char *)&(fritz_params->contents))[i]++;
}
+// std::cerr << "rewrote " << fritz_params->contents_size << " bytes." << std::endl;
}
void
FritzServer::run (void)
{
for (;;) {
- wait_for_request ();
+ wait_for_client ();
+ update_params ();
+ fritz_params->message_id++;
+ rewrite ();
+ signal_client ();
}
}
-int
-main (int argc, char *argv[])
+/*** FritzClient ***/
+
+void
+FritzClient::open_semaphores ()
{
- if (argc == 3) {
- FritzServer f (argv[1], argv[2]);
- f.run ();
- return 0;
- } else {
- std::cerr << "usage: " << argv[0] << " <shm_name> <sem_name>" << std::endl;
- return -1;
+ server_sem = open_semaphore (server_sem_name);
+ client_sem = open_semaphore (client_sem_name);
+}
+
+void
+FritzClient::open_shared_memory (void)
+{
+ shm_fd = shm_open (shm_name, O_RDWR, 0600);
+ if (shm_fd < 0) {
+ throw fritz_exception ("Unable to open shared memory segment.");
}
}
+
+void
+FritzClient::wait_for_server (void)
+{
+ if (sem_wait (server_sem) == -1) {
+ throw fritz_exception ("Error waiting on semaphore for control.");
+ }
+}
+
+void
+FritzClient::signal_server (void)
+{
+ if (sem_post (client_sem) == -1) {
+ throw fritz_exception ("Unable to sem_post");
+ }
+}
+
+FritzClient::FritzClient (void)
+{
+ mode = "client";
+ open_semaphores ();
+ open_shared_memory ();
+ map_the_shm ();
+}
+
+FritzClient::~FritzClient (void)
+{
+ close_semaphores ();
+}
+
+void
+FritzClient::pass_to_server (void)
+{
+ signal_server ();
+ wait_for_server ();
+}
+
+void *
+FritzClient::grab_symbol_from (const char *lib_env, const char *sym)
+{
+ void *dl, *rv;
+ char *dl_file, *error;
+
+ dl_file = getenv (lib_env);
+ if (!dl_file) {
+ throw fritz_exception ("Can't fritz library, as environment variable is not present.");
+ }
+ dl = dlopen (dl_file, RTLD_LAZY);
+ dlerror ();
+ rv = dlsym (dl, sym);
+ if ((error = dlerror()) != NULL) {
+ std::cerr << "error loading symbol: " << error << std::endl;
+ throw fritz_exception ("Error grabbing symbol.");
+ }
+ std::cerr << "got the symbol \"" << sym << "\" from \"" << dl_file << "\" at " << rv << std::endl;
+ dlclose (dl);
+ return rv;
+}
+
+void
+FritzClient::copy_data (size_t nbytes, void *from)
+{
+ update_params ();
+ int mbytes = fritz_params->buffer_size - \
+ ((char *)fritz_params - (char *)&(fritz_params->contents));
+ if (nbytes > mbytes) {
+ throw fritz_exception ("buffer overrun; can't copy this many bytes!");
+ }
+ fritz_params->contents_size = nbytes;
+ memcpy (&(fritz_params->contents), from, nbytes);
+}
+
+size_t
+FritzClient::copy_back (size_t maxbytes, void *buf)
+{
+ if (fritz_params->contents_size > maxbytes) {
+ throw fritz_exception ("buffer overrun; can't copy this many bytes back!");
+ }
+ memcpy (buf, &(fritz_params->contents), fritz_params->contents_size);
+ return fritz_params->contents_size;
+}
+
============================================================
--- fritz.hh 8e3312ac5309aafc33e25d03671eea7ed1db4a5c
+++ fritz.hh 0a09a9981868e04ed9e93bab0af8a66c79f87559
@@ -5,6 +5,13 @@
* common data structures
*/
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <semaphore.h>
+#include <fcntl.h>
+#include <unistd.h>
+
enum fritz_message {
FRITZ_MESG_SYSCALL_OPEN,
FRITZ_MESG_SYSCALL_READ,
@@ -12,12 +19,91 @@ enum fritz_message {
FRITZ_MESG_SYSCALL_CLOSE
};
+class fritz_exception: public std::exception
+{
+private:
+ const char *err;
+
+public:
+ fritz_exception (const char *e)
+ {
+ err = e;
+ }
+ virtual const char* what() const throw()
+ {
+ char *s_err;
+
+ s_err = strerror (errno);
+ std::cout << "from errno: " << s_err << std::endl;
+ return err;
+ }
+};
+
struct fritz_params {
- size_t buffer_size; /* size of the shared memory segment, including this struct */
+ size_t buffer_size; /* total size of the shared memory segment */
pid_t pid; /* process ID sending this message */
size_t message_id; /* monotonically increasing message ID */
- enum fritz_message message_type; /* type of message */
- void *contents; /* contents (descripted by message_type) */
+ int fd; /* file descriptor from which data was gathered */
+ size_t contents_size; /* size of contents */
+ void *contents; /* contents */
};
+class Fritzer {
+protected:
+ const char *mode; /* used in debugging messages, eg. "client" or "server" */
+ static const int shm_size=(1024*16);
+ pid_t my_pid;
+
+ /* semaphores */
+ const char *server_sem_name, *client_sem_name;
+ sem_t *server_sem, *client_sem;
+ /* shared memory */
+ const char *shm_name;
+ int shm_fd;
+ void *shm_mem;
+ struct fritz_params *fritz_params;
+
+ void initialise_from_environ (void);
+ sem_t *open_semaphore (const char *);
+ sem_t *create_semaphore (const char *);
+ void close_semaphores (void);
+ void map_the_shm (void);
+ void update_params (void);
+public:
+ Fritzer (void);
+ size_t get_message_id (void);
+};
+
+class FritzServer : public Fritzer {
+private:
+ void wait_for_request (void);
+ void create_semaphores ();
+ void create_shared_memory (void);
+ void wait_for_client (void);
+ void signal_client (void);
+ void rewrite (void);
+
+public:
+ FritzServer (void);
+ ~FritzServer (void);
+ void run (void);
+};
+
+class FritzClient : public Fritzer {
+private:
+ void open_semaphores (void);
+ void open_shared_memory (void);
+ void wait_for_server (void);
+ void signal_server (void);
+ void sync (void);
+public:
+ FritzClient (void);
+ ~FritzClient (void);
+ const char *Hello(void);
+ void pass_to_server (void);
+ void *grab_symbol_from (const char *, const char *);
+ void copy_data (size_t, void *);
+ size_t copy_back (size_t, void *);
+};
+
#endif