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