1999-09-27 18:44:28 +00:00
|
|
|
// -*- C++ -*-
|
2003-08-23 00:17:00 +00:00
|
|
|
/**
|
2007-04-29 16:22:46 +00:00
|
|
|
* \file Server.h
|
2003-08-23 00:17:00 +00:00
|
|
|
* This file is part of LyX, the document processor.
|
|
|
|
* Licence details can be found in the file COPYING.
|
|
|
|
*
|
2008-11-14 15:58:50 +00:00
|
|
|
* \author Lars Gullik Bjønnes
|
2003-08-23 00:17:00 +00:00
|
|
|
* \author Jean-Marc Lasgouttes
|
2009-08-21 22:58:38 +00:00
|
|
|
* \author Enrico Forestieri
|
2003-08-23 00:17:00 +00:00
|
|
|
*
|
|
|
|
* Full author contact details are available in file CREDITS.
|
|
|
|
*/
|
1999-09-27 18:44:28 +00:00
|
|
|
|
2007-04-29 16:22:46 +00:00
|
|
|
#ifndef SERVER_H
|
|
|
|
#define SERVER_H
|
1999-09-27 18:44:28 +00:00
|
|
|
|
2002-07-14 01:44:15 +00:00
|
|
|
#include <boost/signals/trackable.hpp>
|
2002-12-01 22:59:25 +00:00
|
|
|
|
2009-08-21 22:58:38 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
#include <windows.h>
|
|
|
|
#include <QObject>
|
|
|
|
#include <QEvent>
|
|
|
|
#endif
|
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
|
|
|
namespace lyx {
|
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
class LyXFunc;
|
2007-04-29 16:22:46 +00:00
|
|
|
class Server;
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
/** This class managed the pipes used for communicating with clients.
|
|
|
|
Usage: Initialize with pipe-filename-base, client class to receive
|
|
|
|
messages, and callback-function that will be called with the messages.
|
|
|
|
When you want to send, use "send()".
|
|
|
|
This class encapsulates all the dirty communication and thus provides
|
1999-10-02 16:21:10 +00:00
|
|
|
a clean string interface.
|
1999-09-27 18:44:28 +00:00
|
|
|
*/
|
2009-08-21 22:58:38 +00:00
|
|
|
#ifndef _WIN32
|
2002-07-14 01:44:15 +00:00
|
|
|
class LyXComm : public boost::signals::trackable {
|
2009-08-21 22:58:38 +00:00
|
|
|
#else
|
|
|
|
class LyXComm : public QObject {
|
|
|
|
Q_OBJECT
|
2009-08-29 23:42:06 +00:00
|
|
|
|
2009-09-05 23:06:24 +00:00
|
|
|
friend DWORD WINAPI pipeServerWrapper(void *);
|
2009-09-05 16:39:33 +00:00
|
|
|
|
2009-08-31 23:32:46 +00:00
|
|
|
public:
|
|
|
|
/// Max number of clients
|
|
|
|
enum { MAX_CLIENTS = 10 };
|
|
|
|
|
|
|
|
private:
|
|
|
|
/// Max number of pipe instances
|
|
|
|
enum { MAX_PIPES = 2 * MAX_CLIENTS };
|
2009-08-29 23:42:06 +00:00
|
|
|
|
|
|
|
/// I/O buffer size
|
|
|
|
enum { PIPE_BUFSIZE = 512 };
|
|
|
|
|
|
|
|
/// Pipe client time-out
|
|
|
|
enum { PIPE_TIMEOUT = 5000 };
|
|
|
|
|
|
|
|
/// Pipe states
|
|
|
|
enum PipeState {
|
|
|
|
CONNECTING_STATE,
|
|
|
|
READING_STATE,
|
|
|
|
WRITING_STATE
|
|
|
|
};
|
|
|
|
|
2009-08-31 23:32:46 +00:00
|
|
|
/// Pipe instances
|
2009-08-29 23:42:06 +00:00
|
|
|
typedef struct {
|
|
|
|
OVERLAPPED overlap;
|
|
|
|
HANDLE handle;
|
2009-08-31 23:32:46 +00:00
|
|
|
std::string iobuf;
|
|
|
|
char readbuf[PIPE_BUFSIZE];
|
2009-08-29 23:42:06 +00:00
|
|
|
DWORD nbytes;
|
|
|
|
PipeState state;
|
|
|
|
bool pending_io;
|
|
|
|
} PipeInst;
|
2009-08-21 22:58:38 +00:00
|
|
|
#endif
|
1999-09-27 18:44:28 +00:00
|
|
|
public:
|
|
|
|
/** When we receive a message, we send it to a client.
|
|
|
|
This is one of the small things that would have been a lot
|
|
|
|
cleaner with a Signal/Slot thing.
|
|
|
|
*/
|
2007-04-29 16:22:46 +00:00
|
|
|
typedef void (*ClientCallbackfct)(Server *, std::string const &);
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
/// Construct with pipe-basename and callback to receive messages
|
2007-09-16 20:58:22 +00:00
|
|
|
LyXComm(std::string const & pip, Server * cli, ClientCallbackfct ccb = 0);
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
///
|
2007-04-29 16:22:46 +00:00
|
|
|
~LyXComm() { closeConnection(); }
|
1999-09-27 18:44:28 +00:00
|
|
|
|
2001-10-19 15:13:49 +00:00
|
|
|
/// clean up in emergency
|
|
|
|
void emergencyCleanup();
|
2002-03-21 17:27:08 +00:00
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
/// Send message
|
2003-10-06 15:43:21 +00:00
|
|
|
void send(std::string const &);
|
1999-10-25 14:18:30 +00:00
|
|
|
|
2002-07-14 01:44:15 +00:00
|
|
|
/// asynch ready-to-be-read notification
|
2009-08-21 22:58:38 +00:00
|
|
|
#ifndef _WIN32
|
2002-07-14 01:44:15 +00:00
|
|
|
void read_ready();
|
2009-08-21 22:58:38 +00:00
|
|
|
#else
|
2009-08-29 23:42:06 +00:00
|
|
|
void read_ready(DWORD);
|
2009-08-21 22:58:38 +00:00
|
|
|
#endif
|
1999-10-25 14:18:30 +00:00
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
private:
|
2001-11-12 17:43:21 +00:00
|
|
|
/// the filename of the in pipe
|
2005-01-20 15:07:36 +00:00
|
|
|
std::string const inPipeName() const;
|
2001-11-12 17:43:21 +00:00
|
|
|
|
|
|
|
/// the filename of the out pipe
|
2005-01-20 15:07:36 +00:00
|
|
|
std::string const outPipeName() const;
|
2001-11-12 17:43:21 +00:00
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
/// Open pipes
|
|
|
|
void openConnection();
|
2002-03-21 17:27:08 +00:00
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
/// Close pipes
|
|
|
|
void closeConnection();
|
|
|
|
|
2009-08-21 22:58:38 +00:00
|
|
|
#ifndef _WIN32
|
2001-10-19 15:13:49 +00:00
|
|
|
/// start a pipe
|
2003-10-06 15:43:21 +00:00
|
|
|
int startPipe(std::string const &, bool);
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2001-10-19 15:13:49 +00:00
|
|
|
/// finish a pipe
|
2003-10-06 15:43:21 +00:00
|
|
|
void endPipe(int &, std::string const &, bool);
|
2002-03-21 17:27:08 +00:00
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
/// This is -1 if not open
|
2007-09-16 20:58:22 +00:00
|
|
|
int infd_;
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
/// This is -1 if not open
|
2007-09-16 20:58:22 +00:00
|
|
|
int outfd_;
|
2009-08-21 22:58:38 +00:00
|
|
|
#else
|
2009-09-05 16:39:33 +00:00
|
|
|
/// The pipe server returns false when exiting due to an error
|
|
|
|
bool pipeServer();
|
|
|
|
|
2009-08-29 23:42:06 +00:00
|
|
|
/// Start an overlapped connection
|
2009-09-05 16:39:33 +00:00
|
|
|
bool startPipe(DWORD);
|
2009-08-29 23:42:06 +00:00
|
|
|
|
|
|
|
/// Reset an overlapped connection
|
2009-09-05 16:39:33 +00:00
|
|
|
bool resetPipe(DWORD, bool close_handle = false);
|
2009-08-29 23:42:06 +00:00
|
|
|
|
|
|
|
/// Close event and pipe handles
|
2009-09-05 16:39:33 +00:00
|
|
|
void closeHandles();
|
2009-08-29 23:42:06 +00:00
|
|
|
|
2009-08-31 23:32:46 +00:00
|
|
|
/// Catch pipe ready-to-be-read notification
|
|
|
|
bool event(QEvent *);
|
|
|
|
|
|
|
|
/// Check whether the pipe server must be stopped
|
2009-09-06 13:49:34 +00:00
|
|
|
bool checkStopServer(DWORD timeout = 0);
|
2009-08-31 23:32:46 +00:00
|
|
|
|
2009-08-29 23:42:06 +00:00
|
|
|
/// The filename of a (in or out) pipe instance
|
|
|
|
std::string const pipeName(DWORD) const;
|
|
|
|
|
|
|
|
/// Pipe instances
|
2009-08-31 23:32:46 +00:00
|
|
|
PipeInst pipe_[MAX_PIPES];
|
2009-08-29 23:42:06 +00:00
|
|
|
|
|
|
|
/// Pipe server control events
|
2009-08-31 23:32:46 +00:00
|
|
|
HANDLE event_[MAX_PIPES + 1];
|
2009-08-29 23:42:06 +00:00
|
|
|
|
|
|
|
/// Reply buffer
|
2009-08-31 23:32:46 +00:00
|
|
|
std::string outbuf_;
|
|
|
|
|
|
|
|
/// Synchronize access to outbuf_
|
|
|
|
HANDLE outbuf_mutex_;
|
|
|
|
|
|
|
|
/// Windows event for stopping the pipe server
|
|
|
|
HANDLE stopserver_;
|
|
|
|
|
|
|
|
/// Pipe server thread handle
|
|
|
|
HANDLE server_thread_;
|
2009-08-21 22:58:38 +00:00
|
|
|
#endif
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
/// Are we up and running?
|
2007-09-16 20:58:22 +00:00
|
|
|
bool ready_;
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
/// Base of pipename including path
|
2007-09-16 20:58:22 +00:00
|
|
|
std::string pipename_;
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
/// The client
|
2007-09-16 20:58:22 +00:00
|
|
|
Server * client_;
|
1999-09-27 18:44:28 +00:00
|
|
|
|
|
|
|
/// The client callback function
|
2007-09-16 20:58:22 +00:00
|
|
|
ClientCallbackfct clientcb_;
|
1999-09-27 18:44:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2000-08-07 20:58:24 +00:00
|
|
|
///
|
2007-04-29 16:22:46 +00:00
|
|
|
class Server {
|
1999-09-27 18:44:28 +00:00
|
|
|
public:
|
|
|
|
// FIXME IN 0.13
|
|
|
|
// Hack! This should be changed in 0.13
|
|
|
|
|
2000-08-07 20:58:24 +00:00
|
|
|
// The lyx server should not take an argument "LyXFunc" but this is
|
1999-09-27 18:44:28 +00:00
|
|
|
// how it will be done for 0.12. In 0.13 we must write a non-gui
|
|
|
|
// bufferview.
|
2002-03-21 17:27:08 +00:00
|
|
|
// IMO lyxserver is atypical, and for the moment the only one, non-gui
|
|
|
|
// bufferview. We just have to find a way to handle situations like if
|
|
|
|
// lyxserver is using a buffer that is being edited with a bufferview.
|
|
|
|
// With a common buffer list this is not a problem, maybe. (Alejandro)
|
2000-08-07 20:58:24 +00:00
|
|
|
///
|
2007-09-16 20:58:22 +00:00
|
|
|
Server(LyXFunc * f, std::string const & pip);
|
2002-03-21 17:27:08 +00:00
|
|
|
///
|
2007-04-29 16:22:46 +00:00
|
|
|
~Server();
|
1999-09-27 18:44:28 +00:00
|
|
|
///
|
2003-10-06 15:43:21 +00:00
|
|
|
void notifyClient(std::string const &);
|
2002-03-21 17:27:08 +00:00
|
|
|
|
2001-10-19 15:13:49 +00:00
|
|
|
/// whilst crashing etc.
|
2007-09-16 20:58:22 +00:00
|
|
|
void emergencyCleanup() { pipes_.emergencyCleanup(); }
|
|
|
|
///
|
|
|
|
void callback(std::string const & msg);
|
2002-03-21 17:27:08 +00:00
|
|
|
|
1999-09-27 18:44:28 +00:00
|
|
|
private:
|
|
|
|
/// Names and number of current clients
|
2009-08-31 23:32:46 +00:00
|
|
|
#ifndef _WIN32
|
2007-09-16 20:58:22 +00:00
|
|
|
enum { MAX_CLIENTS = 10 };
|
2009-08-31 23:32:46 +00:00
|
|
|
#else
|
|
|
|
enum { MAX_CLIENTS = LyXComm::MAX_CLIENTS };
|
|
|
|
#endif
|
2000-08-07 20:58:24 +00:00
|
|
|
///
|
2007-09-16 20:58:22 +00:00
|
|
|
std::string clients_[MAX_CLIENTS];
|
2000-08-07 20:58:24 +00:00
|
|
|
///
|
2007-09-16 20:58:22 +00:00
|
|
|
int numclients_;
|
1999-09-27 18:44:28 +00:00
|
|
|
///
|
2007-09-16 20:58:22 +00:00
|
|
|
LyXFunc * func_;
|
1999-09-27 18:44:28 +00:00
|
|
|
///
|
2007-09-16 20:58:22 +00:00
|
|
|
LyXComm pipes_;
|
1999-09-27 18:44:28 +00:00
|
|
|
};
|
|
|
|
|
2007-04-26 04:41:58 +00:00
|
|
|
/// Implementation is in LyX.cpp
|
2007-04-29 16:22:46 +00:00
|
|
|
extern Server & theServer();
|
2006-10-19 07:20:32 +00:00
|
|
|
|
2006-10-21 00:16:43 +00:00
|
|
|
|
|
|
|
} // namespace lyx
|
|
|
|
|
2007-05-28 22:27:45 +00:00
|
|
|
#endif // SERVER_H
|