]> git.lyx.org Git - lyx.git/blobdiff - src/lyxsocket.C
cleanup some debug messages
[lyx.git] / src / lyxsocket.C
index 3095d2bb31a8e8bfc2004ba1083aa08dd1079fa7..bade99cb65d34267409c7c9fadc1fd9ed6671067 100644 (file)
@@ -12,6 +12,8 @@
  * Full author contact details are available in file CREDITS.
  */
 
+#include <config.h>
+
 #include "lyxsocket.h"
 
 #include "debug.h"
 
 #include "frontends/lyx_gui.h"
 
+#include "support/environment.h"
 #include "support/lyxlib.h"
 #include "support/socktools.h"
 
-#include <iostream>
+#include <boost/bind.hpp>
+
 #include <cerrno>
 
+#if defined (_WIN32)
+# include <io.h>
+#endif
+
+using boost::shared_ptr;
 
 using std::auto_ptr;
 using std::endl;
@@ -38,7 +47,7 @@ using std::string;
 // that can connect at the same time.
 LyXServerSocket::LyXServerSocket(LyXFunc * f, string const & addr)
        : func(f),
-         fd_(lyx::support::socktools::listen(addr, MAX_CLIENTS)),
+         fd_(lyx::support::socktools::listen(addr, 3)),
          address_(addr)
 {
        if (fd_ == -1) {
@@ -48,11 +57,15 @@ LyXServerSocket::LyXServerSocket(LyXFunc * f, string const & addr)
 
        // These env vars are used by DVI inverse search
        // Needed by xdvi
-       lyx::support::putenv("XEDITOR", "lyxclient -g %f %l");
+       lyx::support::setEnv("XEDITOR", "lyxclient -g %f %l");
        // Needed by lyxclient
-       lyx::support::putenv("LYXSOCKET", address_);
+       lyx::support::setEnv("LYXSOCKET", address_);
+
+       lyx_gui::register_socket_callback(
+               fd_,
+               boost::bind(&LyXServerSocket::serverCallback, this)
+               );
 
-       lyx_gui::set_serversocket_callback(this);
        lyxerr[Debug::LYXSERVER] << "lyx: New server socket "
                                 << fd_ << ' ' << address_ << endl;
 }
@@ -61,19 +74,13 @@ LyXServerSocket::LyXServerSocket(LyXFunc * f, string const & addr)
 // Close the socket and remove the address of the filesystem.
 LyXServerSocket::~LyXServerSocket()
 {
+       lyx_gui::unregister_socket_callback(fd_);
        ::close(fd_);
        lyx::support::unlink(address_);
-       while (!clients.empty()) close(*clients.rbegin());
        lyxerr[Debug::LYXSERVER] << "lyx: Server socket quitting" << endl;
 }
 
 
-int LyXServerSocket::fd() const
-{
-       return fd_;
-}
-
-
 string const & LyXServerSocket::address() const
 {
        return address_;
@@ -84,23 +91,36 @@ string const & LyXServerSocket::address() const
 // is OK and if the number of clients does not exceed MAX_CLIENTS
 void LyXServerSocket::serverCallback()
 {
-       auto_ptr<LyXDataSocket> client(new LyXDataSocket(this));
-       if (client->connected()) {
-               if (clients.size() == MAX_CLIENTS) {
-                       client->writeln("BYE:Too many clients connected");
-               } else {
-                       lyx_gui::set_datasocket_callback(client.get());
-                       clients.insert(client.release());
-                       return;
-               }
+       int const client_fd = lyx::support::socktools::accept(fd_);
+
+       if (fd_ == -1) {
+               lyxerr[Debug::LYXSERVER] << "lyx: Failed to accept new client"
+                                        << endl;
+               return;
+       }
+
+       if (clients.size() >= MAX_CLIENTS) {
+               writeln("BYE:Too many clients connected");
+               return;
        }
+
+       // Register the new client.
+       clients[client_fd] =
+               shared_ptr<LyXDataSocket>(new LyXDataSocket(client_fd));
+       lyx_gui::register_socket_callback(
+               client_fd,
+               boost::bind(&LyXServerSocket::dataCallback,
+                           this, client_fd)
+               );
 }
 
 
 // Reads and processes input from client and check
 // if the connection has been closed
-void LyXServerSocket::dataCallback(LyXDataSocket * client)
+void LyXServerSocket::dataCallback(int fd)
 {
+       shared_ptr<LyXDataSocket> client = clients[fd];
+
        string line;
        string::size_type pos;
        bool saidbye = false;
@@ -133,17 +153,30 @@ void LyXServerSocket::dataCallback(LyXDataSocket * client)
        }
 
        if (saidbye || (!client->connected())) {
-               close(client);
+               clients.erase(fd);
        }
 }
 
 
-// Removes client callback and deletes client object
-void LyXServerSocket::close(LyXDataSocket * client)
+void LyXServerSocket::writeln(string const & line)
 {
-       lyx_gui::remove_datasocket_callback(client);
-       clients.erase(client);
-       delete client;
+       string const linen(line + '\n');
+       int const size = linen.size();
+       int const written = ::write(fd_, linen.c_str(), size);
+       if (written < size) { // Always mean end of connection.
+               if ((written == -1) && (errno == EPIPE)) {
+                       // The program will also receive a SIGPIPE
+                       // that must be caught
+                       lyxerr << "lyx: Server socket " << fd_
+                              << " connection closed while writing." << endl;
+               } else {
+                       // Anything else, including errno == EAGAIN, must be
+                       // considered IO error. EAGAIN should never happen
+                       // when line is small
+                       lyxerr << "lyx: Server socket " << fd_
+                            << " IO error: " << strerror(errno);
+               }
+       }
 }
 
 // Debug
@@ -152,44 +185,27 @@ void LyXServerSocket::close(LyXDataSocket * client)
 //     lyxerr << "LyXServerSocket debug dump.\n"
 //          << "fd = " << fd_ << ", address = " << address_ << ".\n"
 //          << "Clients: " << clients.size() << ".\n";
-//     if (!clients.empty()) {
-//             std::set<LyXDataSocket *>::const_iterator client = clients.begin();
-//             std::set<LyXDataSocket *>::const_iterator end = clients.end();
-//             for (; client != end; ++client)
-//                     lyxerr << "fd = " << (*client)->fd() << "\n";
-//     }
+//     std::map<int, shared_ptr<LyXDataSocket> >::const_iterator client = clients.begin();
+//     std::map<int, shared_ptr<LyXDataSocket> >::const_iterator end = clients.end();
+//     for (; client != end; ++client)
+//             lyxerr << "fd = " << client->first << '\n';
 // }
 
 
-LyXDataSocket::LyXDataSocket(LyXServerSocket * serv)
-       :server_(serv),
-        fd_(lyx::support::socktools::accept(serv->fd()))
+LyXDataSocket::LyXDataSocket(int fd)
+       : fd_(fd), connected_(true)
 {
-       if (fd_ == -1) {
-               connected_ = false;
-       } else {
-               lyxerr[Debug::LYXSERVER] << "lyx: New data socket " << fd_ << endl;
-               connected_ = true;
-       }
+       lyxerr[Debug::LYXSERVER] << "lyx: New data socket " << fd_ << endl;
 }
 
 
 LyXDataSocket::~LyXDataSocket()
 {
        ::close(fd_);
-       lyxerr[Debug::LYXSERVER] << "lyx: Data socket " << fd_ << " quitting." << endl;
-}
-
 
-LyXServerSocket * LyXDataSocket::server() const
-{
-       return server_;
-}
-
-
-int LyXDataSocket::fd() const
-{
-       return fd_;
+       lyx_gui::unregister_socket_callback(fd_);
+       lyxerr[Debug::LYXSERVER] << "lyx: Data socket " << fd_ << " quitting."
+                                << endl;
 }
 
 
@@ -205,12 +221,10 @@ bool LyXDataSocket::readln(string & line)
        int const charbuf_size = 100;
         char charbuf[charbuf_size]; // buffer for the ::read() system call
        int count;
-       string::size_type pos;
 
        // read and store characters in buffer
        while ((count = ::read(fd_, charbuf, charbuf_size - 1)) > 0) {
-               charbuf[count] = '\0'; // turn it into a c string
-               buffer += charbuf;
+               buffer_.append(charbuf, charbuf + count);
        }
 
        // Error conditions. The buffer must still be
@@ -226,13 +240,14 @@ bool LyXDataSocket::readln(string & line)
        }
 
        // Cut a line from buffer
-       if ((pos = buffer.find('\n')) == string::npos) {
+       string::size_type pos = buffer_.find('\n');
+       if (pos == string::npos) {
                lyxerr[Debug::LYXSERVER] << "lyx: Data socket " << fd_
                                         << ": line not completed." << endl;
                return false; // No complete line stored
        }
-       line = buffer.substr(0, pos);
-       buffer = buffer.substr(pos + 1);
+       line = buffer_.substr(0, pos);
+       buffer_.erase(0, pos + 1);
        return true;
 }
 
@@ -240,10 +255,10 @@ bool LyXDataSocket::readln(string & line)
 // Write a line of the form <key>:<value> to the socket
 void LyXDataSocket::writeln(string const & line)
 {
-       string linen(line + '\n');
-       int size = linen.size();
-       int written = ::write(fd_, linen.c_str(), size);
-       if (written < size) { // Allways mean end of connection.
+       string const linen(line + '\n');
+       int const size = linen.size();
+       int const written = ::write(fd_, linen.c_str(), size);
+       if (written < size) { // Always mean end of connection.
                if ((written == -1) && (errno == EPIPE)) {
                        // The program will also receive a SIGPIPE
                        // that must be catched