X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Flyxsocket.C;h=bade99cb65d34267409c7c9fadc1fd9ed6671067;hb=2486c96b8d9086471299bf207b85b1ce848246aa;hp=429d6ee2e8e79686c16f4d8bc977b87f92dfc9f1;hpb=dab52aa183cf704ca33ad878728c0b6839486c86;p=lyx.git diff --git a/src/lyxsocket.C b/src/lyxsocket.C index 429d6ee2e8..bade99cb65 100644 --- a/src/lyxsocket.C +++ b/src/lyxsocket.C @@ -12,6 +12,8 @@ * Full author contact details are available in file CREDITS. */ +#include + #include "lyxsocket.h" #include "debug.h" @@ -21,12 +23,21 @@ #include "frontends/lyx_gui.h" +#include "support/environment.h" #include "support/lyxlib.h" #include "support/socktools.h" -#include +#include + #include +#if defined (_WIN32) +# include +#endif + +using boost::shared_ptr; + +using std::auto_ptr; using std::endl; using std::string; @@ -36,14 +47,25 @@ 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) { lyxerr << "lyx: Disabling LyX socket." << endl; return; } - lyx_gui::set_serversocket_callback(this); + + // These env vars are used by DVI inverse search + // Needed by xdvi + lyx::support::setEnv("XEDITOR", "lyxclient -g %f %l"); + // Needed by lyxclient + lyx::support::setEnv("LYXSOCKET", address_); + + lyx_gui::register_socket_callback( + fd_, + boost::bind(&LyXServerSocket::serverCallback, this) + ); + lyxerr[Debug::LYXSERVER] << "lyx: New server socket " << fd_ << ' ' << address_ << endl; } @@ -52,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_; @@ -75,24 +91,36 @@ string const & LyXServerSocket::address() const // is OK and if the number of clients does not exceed MAX_CLIENTS void LyXServerSocket::serverCallback() { - LyXDataSocket * client = new LyXDataSocket(this); - if (client->connected()) { - if (clients.size() == MAX_CLIENTS) { - client->writeln("BYE:Too many clients connected"); - } else { - clients.insert(client); - lyx_gui::set_datasocket_callback(client); - return; - } + int const client_fd = lyx::support::socktools::accept(fd_); + + if (fd_ == -1) { + lyxerr[Debug::LYXSERVER] << "lyx: Failed to accept new client" + << endl; + return; } - delete client; + + if (clients.size() >= MAX_CLIENTS) { + writeln("BYE:Too many clients connected"); + return; + } + + // Register the new client. + clients[client_fd] = + shared_ptr(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 client = clients[fd]; + string line; string::size_type pos; bool saidbye = false; @@ -125,63 +153,59 @@ 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 // void LyXServerSocket::dump() const // { -// lyxerr << "LyXServerSocket debug dump.\n" -// << "fd = " << fd_ << ", address = " << address_ << ".\n" -// << "Clients: " << clients.size() << ".\n"; -// if (!clients.empty()) { -// std::set::const_iterator client = clients.begin(); -// std::set::const_iterator end = clients.end(); -// for (; client != end; ++client) -// lyxerr << "fd = " << (*client)->fd() << "\n"; -// } +// lyxerr << "LyXServerSocket debug dump.\n" +// << "fd = " << fd_ << ", address = " << address_ << ".\n" +// << "Clients: " << clients.size() << ".\n"; +// std::map >::const_iterator client = clients.begin(); +// std::map >::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; } @@ -197,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 @@ -218,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; } @@ -232,10 +255,10 @@ bool LyXDataSocket::readln(string & line) // Write a line of the form : 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