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