]> git.lyx.org Git - lyx.git/blob - src/Server.h
On Windows, use the same number of output pipe instances as that of
[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 public:
46         /// Max number of clients
47         enum { MAX_CLIENTS = 10 };
48
49 private:
50         /// Max number of pipe instances
51         enum { MAX_PIPES = 2 * MAX_CLIENTS };
52
53         /// I/O buffer size
54         enum { PIPE_BUFSIZE = 512 };
55
56         /// Pipe client time-out
57         enum { PIPE_TIMEOUT = 5000 };
58
59         /// Pipe states
60         enum PipeState {
61                 CONNECTING_STATE,
62                 READING_STATE,
63                 WRITING_STATE
64         };
65
66         /// Pipe instances
67         typedef struct {
68                 OVERLAPPED overlap;
69                 HANDLE handle;
70                 std::string iobuf;
71                 char readbuf[PIPE_BUFSIZE];
72                 DWORD nbytes;
73                 PipeState state;
74                 bool pending_io;
75         } PipeInst;
76 #endif
77 public:
78         /** When we receive a message, we send it to a client.
79           This is one of the small things that would have been a lot
80           cleaner with a Signal/Slot thing.
81          */
82         typedef void (*ClientCallbackfct)(Server *, std::string const &);
83
84         /// Construct with pipe-basename and callback to receive messages
85         LyXComm(std::string const & pip, Server * cli, ClientCallbackfct ccb = 0);
86
87         ///
88         ~LyXComm() { closeConnection(); }
89
90         /// clean up in emergency
91         void emergencyCleanup();
92
93         /// Send message
94         void send(std::string const &);
95
96         /// asynch ready-to-be-read notification
97 #ifndef _WIN32
98         void read_ready();
99 #else
100         void read_ready(DWORD);
101
102         /// The pipe server
103         void pipeServer();
104 #endif
105
106 private:
107         /// the filename of the in pipe
108         std::string const inPipeName() const;
109
110         /// the filename of the out pipe
111         std::string const outPipeName() const;
112
113         /// Open pipes
114         void openConnection();
115
116         /// Close pipes
117         void closeConnection();
118
119 #ifndef _WIN32
120         /// start a pipe
121         int startPipe(std::string const &, bool);
122
123         /// finish a pipe
124         void endPipe(int &, std::string const &, bool);
125
126         /// This is -1 if not open
127         int infd_;
128
129         /// This is -1 if not open
130         int outfd_;
131 #else
132         /// Start an overlapped connection
133         void startPipe(DWORD);
134
135         /// Reset an overlapped connection
136         void resetPipe(DWORD, bool close_handle = false);
137
138         /// Close event and pipe handles
139         void closeHandles(DWORD);
140
141         /// Catch pipe ready-to-be-read notification
142         bool event(QEvent *);
143
144         /// Check whether the pipe server must be stopped
145         BOOL checkStopServer();
146
147         /// The filename of a (in or out) pipe instance
148         std::string const pipeName(DWORD) const;
149
150         /// Pipe instances
151         PipeInst pipe_[MAX_PIPES];
152
153         /// Pipe server control events
154         HANDLE event_[MAX_PIPES + 1];
155
156         /// Reply buffer
157         std::string outbuf_;
158
159         /// Synchronize access to outbuf_
160         HANDLE outbuf_mutex_;
161
162         /// Windows event for stopping the pipe server
163         HANDLE stopserver_;
164
165         /// Pipe server thread handle
166         HANDLE server_thread_;
167 #endif
168
169         /// Are we up and running?
170         bool ready_;
171
172         /// Base of pipename including path
173         std::string pipename_;
174
175         /// The client
176         Server * client_;
177
178         /// The client callback function
179         ClientCallbackfct clientcb_;
180 };
181
182
183 ///
184 class Server {
185 public:
186         // FIXME IN 0.13
187         // Hack! This should be changed in 0.13
188
189         // The lyx server should not take an argument "LyXFunc" but this is
190         // how it will be done for 0.12. In 0.13 we must write a non-gui
191         // bufferview.
192         // IMO lyxserver is atypical, and for the moment the only one, non-gui
193         // bufferview. We just have to find a way to handle situations like if
194         // lyxserver is using a buffer that is being edited with a bufferview.
195         // With a common buffer list this is not a problem, maybe. (Alejandro)
196         ///
197         Server(LyXFunc * f, std::string const & pip);
198         ///
199         ~Server();
200         ///
201         void notifyClient(std::string const &);
202
203         /// whilst crashing etc.
204         void emergencyCleanup() { pipes_.emergencyCleanup(); }
205         ///
206         void callback(std::string const & msg);
207
208 private:
209         /// Names and number of current clients
210 #ifndef _WIN32
211         enum { MAX_CLIENTS = 10 };
212 #else
213         enum { MAX_CLIENTS = LyXComm::MAX_CLIENTS };
214 #endif
215         ///
216         std::string clients_[MAX_CLIENTS];
217         ///
218         int numclients_;
219         ///
220         LyXFunc * func_;
221         ///
222         LyXComm pipes_;
223 };
224
225 /// Implementation is in LyX.cpp
226 extern Server & theServer();
227
228
229 } // namespace lyx
230
231 #endif // SERVER_H