summaryrefslogtreecommitdiffstats
path: root/kpf/src/WebServer.h
blob: c2479f2248954320ee5087393fb4ea9d9d26e524 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
/*
  KPF - Public fileserver for KDE

  Copyright 2001 Rik Hemsley (rikkus) <rik@kde.org>

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to
  deal in the Software without restriction, including without limitation the
  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  sell copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
  AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#ifndef KPF_WEB_SERVER_H
#define KPF_WEB_SERVER_H

#include <dcopobject.h>
#include <tqserversocket.h>

#include "Defaults.h"
#include "Request.h"
#include "Response.h"

namespace KPF
{
  class Server;

  /**
   * Listens on a port for incoming connections.
   * Creates and manages Server objects.
   * Manages bandwidth limit, dealing out bandwidth to Server objects.
   * Maintains concurrent connection limit, using a backlog to queue incoming
   * connections which cannot be served immediately.
   */
  class WebServer : public TQObject, virtual public DCOPObject
  {
    K_DCOP
    Q_OBJECT
//    

    public:

      /**
       * Only root dir specified - this causes an immediate loadConfig.
       *
       * @param root Virtual root directory for servers. Passed to all created
       *             Server objects, which much ensure that only files from the root and
       *             its child directories are served.
       */
      WebServer(const TQString & root);

      /**
       * @param root Virtual root directory for servers. Passed to all created
       *             Server objects, which much ensure that only files from the root and
       *             its child directories are served.
       */
      WebServer
        (
          const TQString  & root,
          uint             listenPort,
          uint             bandwidthLimit,
          uint             connectionLimit,
          bool             followSymlinks,
          const TQString &  serverName
        );

      virtual ~WebServer();

      /**
       * Load the configuration, but do not kill existing connections even if
       * listen port is changed. Do not change listen port yet - only when
       * asked to restart.
       */
      void loadConfig();

    k_dcop:

      /**
       * @return virtual root.
       */
      TQString root();

      /**
       * @return server name
       */
      TQString serverName();
      
      /**
       * @return amount of bytes that may be sent out per second, in total
       * (adding the output of all contained Server objects.)
       */
      ulong   bandwidthLimit();

      /**
       * @return number of concurrent connections that will be served (by
       * creating Server objects. More connections may wait in a backlog.)
       */
      uint    connectionLimit();

      /**
       * @return port on which to listen for incoming connections.
       */
      uint    listenPort();

      /**
       * @return true if requests may include symbolic links in their path.
       */
      bool    followSymlinks();

      /**
       * @return true if custom error messages (set by the user) should be
       * sent.
       */
      bool    customErrorMessages();

      /**
       * Set the maximum amount of bytes that may be sent out per second, in
       * total (adding the output of all contained Server objects.)
       */
      void setBandwidthLimit      (ulong);

      /**
       * Set the number of concurrent connections that will be served (by
       * creating Server objects. More connections may wait in a backlog.)
       */
      void setConnectionLimit     (uint);

      /**
       * Set the port on which to listen for incoming connections. Does not
       * take effect until restart() is called. 
       */
      void setListenPort          (uint);

      /**
       * Set server name
       */
      void setServerName          (const TQString&);
         
      /**
       * Set whether requests may include symbolic links in their path.
       */
      void setFollowSymlinks      (bool);

      /**
       * Set whether custom error messages (set by the user) should be
       * sent.
       */
      void setCustomErrorMessages (bool);

      /**
       * Convenience method for setting many attributes at once.
       */
      void set
        (
         uint   listenPort,
         ulong  bandwidthLimit,
         uint   connectionLimit,
         bool   followSymlinks,
	 const TQString& serverName
        );

      /**
       * Kill all connections, stop listening on port, and start listening on
       * (possibly different) port.
       */
      void restart();

      /**
       * Start / stop accepting new connections.
       */
      void pause(bool);

      /**
       * @return true if no new connections are accepted.
       */
      bool paused();

      /**
       * @return true if this WebServer is unable to listen on the requested
       * port.
       */
      bool portContention();

      /**
       * @return number of Server objects serving requests.
       */
      uint connectionCount();

    protected slots:

      /**
       * Called repeatedly by a timer when this WebServer is in contention for
       * its listen port.
       */
      void slotBind           ();

      /**
       * Called by contained socket object when a new incoming connection is
       * made.
       */
      void slotConnection     (int);

      /**
       * Called by a Server when it has finished all transactions and is ready
       * to die.
       */
      void slotFinished       (Server *);

      /**
       * Called by a Server when it has sent data to the remote client.
       */
      void slotOutput         (Server *, ulong);

      /**
       * Called by a Server when it wishes to send data to the remote client.
       */
      void slotReadyToWrite   (Server *);

      /**
       * Called regularly by a timer to start output allocation (to Server
       * objects.)
       */
      void slotWrite          ();

      /**
       * Called regularly by a timer to check output for current time slice.
       */
      void slotCheckOutput    ();

      /**
       * Called regularly by a timer to handle connections queued in the
       * backlog.
       */
      void slotClearBacklog   ();

      /**
       * Called when this succesfully publishes via zeroconf, or there was an
       * error doing so.
       */
      void wasPublished(bool ok);
      
    protected:

      /**
       * Attempt to create a Server to handle a new connection.
       * @param fd file descriptor.
       */
      bool handleConnection(int fd);

      void saveConfig();

    signals:

      /**
       * @param bytes number of bytes sent by this server during the last
       * time slice.
       */
      void wholeServerOutput  (ulong bytes);

      /**
       * Emitted when a Server object has received a request from its remote
       * client.
       */
      void request            (Server *);

      /**
       * Emitted when a Server object has created a response which it wishes
       * to send to its remote client.
       */
      void response           (Server *);

      /**
       * Emitted when a Server object when data has been send to remote client.
       * @param bytes number of bytes sent to remote client.
       */
      void output             (Server *, ulong bytes);

      /**
       * Emitted when a new Server has been created.
       */
      void connection         (Server *);

      /**
       * Emitted when a Server has finished all transactions.
       */
      void finished           (Server *);

      /**
       * Emitted when this WebServer is now contending, or has stopped
       * contending, its listen port.
       */
      void contentionChange   (bool);

      /**
       * Emitted when this WebServer is now accepting, or has stopped
       * accepting, incoming connections.
       */
      void pauseChange        (bool);

      /**
       * Emitted when the number active Server objects (served connections)
       * changes.
       */
      void connectionCount    (uint);

    private:

      /**
       * @return number of bytes that may be sent out. Changes over time,
       * depending on bandwidth limit.
       */
      ulong bytesLeft()           const;

      /**
       * @return number of bytes that may be sent out by each Server, with the
       * total split between the existing Server objects.
       */
      ulong bandwidthPerClient()  const;


      /** publish this to dns-sd (zeroconf)
       */
      void publish();
      /**
       * Cause all existing Server objects to close their connections by
       * calling Server::cancel.
       */
      void killAllConnections();

      class Private;
      Private * d;
  };

} // End namespace KPF

#endif // WEB_SERVER_H
// vim:ts=2:sw=2:tw=78:et