]> git.lyx.org Git - lyx.git/blob - src/Server.h
During an emergency cleanup, better to not indefinitely wait for
[lyx.git] / src / Server.h
1 // -*- C++ -*-
2 /**
3  * \file Server.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author Enrico Forestieri
10  *
11  * Full author contact details are available in file CREDITS.
12  */
13
14 #ifndef SERVER_H
15 #define SERVER_H
16
17 #include <boost/signals/trackable.hpp>
18
19 #ifdef _WIN32
20 #include <windows.h>
21 #include <QObject>
22 #include <QEvent>
23 #endif
24
25
26 namespace lyx {
27
28 class LyXFunc;
29 class Server;
30
31
32 /** This class managed the pipes used for communicating with clients.
33  Usage: Initialize with pipe-filename-base, client class to receive
34  messages, and callback-function that will be called with the messages.
35  When you want to send, use "send()".
36  This class encapsulates all the dirty communication and thus provides
37  a clean string interface.
38  */
39 #ifndef _WIN32
40 class LyXComm : public boost::signals::trackable {
41 #else
42 class LyXComm : public QObject {
43         Q_OBJECT
44
45         /// Max number of (read) pipe instances
46         enum { MAX_PIPES = 10 };
47
48         /// I/O buffer size
49         enum { PIPE_BUFSIZE = 512 };
50
51         /// Pipe client time-out
52         enum { PIPE_TIMEOUT = 5000 };
53
54         /// Pipe states
55         enum PipeState {
56                 CONNECTING_STATE,
57                 READING_STATE,
58                 WRITING_STATE
59         };
60
61         typedef struct {
62                 OVERLAPPED overlap;
63                 HANDLE handle;
64                 char pipebuf[PIPE_BUFSIZE];
65                 DWORD nbytes;
66                 PipeState state;
67                 bool pending_io;
68         } PipeInst;
69 #endif
70 public:
71         /** When we receive a message, we send it to a client.
72           This is one of the small things that would have been a lot
73           cleaner with a Signal/Slot thing.
74          */
75         typedef void (*ClientCallbackfct)(Server *, std::string const &);
76
77         /// Construct with pipe-basename and callback to receive messages
78         LyXComm(std::string const & pip, Server * cli, ClientCallbackfct ccb = 0);
79
80         ///
81         ~LyXComm() { closeConnection(); }
82
83         /// clean up in emergency
84         void emergencyCleanup();
85
86         /// Send message
87         void send(std::string const &);
88
89         /// asynch ready-to-be-read notification
90 #ifndef _WIN32
91         void read_ready();
92 #else
93         void read_ready(DWORD);
94
95         /// The pipe server
96         void pipeServer();
97 #endif
98
99 private:
100         /// the filename of the in pipe
101         std::string const inPipeName() const;
102
103         /// the filename of the out pipe
104         std::string const outPipeName() const;
105
106         /// Open pipes
107         void openConnection();
108
109         /// Close pipes
110         void closeConnection();
111
112 #ifndef _WIN32
113         /// start a pipe
114         int startPipe(std::string const &, bool);
115
116         /// finish a pipe
117         void endPipe(int &, std::string const &, bool);
118
119         /// This is -1 if not open
120         int infd_;
121
122         /// This is -1 if not open
123         int outfd_;
124 #else
125         /// Start an overlapped connection
126         void startPipe(DWORD);
127
128         /// Reset an overlapped connection
129         void resetPipe(DWORD, bool close_handle = false);
130
131         /// Close event and pipe handles
132         void closeHandles(DWORD);
133
134         /// The filename of a (in or out) pipe instance
135         std::string const pipeName(DWORD) const;
136
137         /// Pipe instances
138         PipeInst pipe_[MAX_PIPES + 1];
139
140         /// Pipe server control events
141         HANDLE event_[MAX_PIPES + 2];
142
143         /// Request buffers
144         std::string readbuf_[MAX_PIPES];
145
146         /// Reply buffer
147         std::string writebuf_;
148 #endif
149
150         /// Are we up and running?
151         bool ready_;
152
153         /// Base of pipename including path
154         std::string pipename_;
155
156         /// The client
157         Server * client_;
158
159         /// The client callback function
160         ClientCallbackfct clientcb_;
161
162 #ifdef _WIN32
163         /// Catch pipe ready-to-be-read notification
164         bool event(QEvent *);
165
166         /// Check whether the pipe server must be stopped
167         BOOL checkStopServer();
168
169         /// Windows event for stopping the pipe server
170         HANDLE stopserver_;
171
172         /// Pipe server thread handle
173         HANDLE server_thread_;
174 #endif
175 };
176
177
178 ///
179 class Server {
180 public:
181         // FIXME IN 0.13
182         // Hack! This should be changed in 0.13
183
184         // The lyx server should not take an argument "LyXFunc" but this is
185         // how it will be done for 0.12. In 0.13 we must write a non-gui
186         // bufferview.
187         // IMO lyxserver is atypical, and for the moment the only one, non-gui
188         // bufferview. We just have to find a way to handle situations like if
189         // lyxserver is using a buffer that is being edited with a bufferview.
190         // With a common buffer list this is not a problem, maybe. (Alejandro)
191         ///
192         Server(LyXFunc * f, std::string const & pip);
193         ///
194         ~Server();
195         ///
196         void notifyClient(std::string const &);
197
198         /// whilst crashing etc.
199         void emergencyCleanup() { pipes_.emergencyCleanup(); }
200         ///
201         void callback(std::string const & msg);
202
203 private:
204         /// Names and number of current clients
205         enum { MAX_CLIENTS = 10 };
206         ///
207         std::string clients_[MAX_CLIENTS];
208         ///
209         int numclients_;
210         ///
211         LyXFunc * func_;
212         ///
213         LyXComm pipes_;
214 };
215
216 /// Implementation is in LyX.cpp
217 extern Server & theServer();
218
219
220 } // namespace lyx
221
222 #endif // SERVER_H