~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/xpinstall/wizard/libxpnet/GUSI/include/GUSISocketMixins.h

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
 
2
// % Project    :       GUSI                            -       Grand Unified Socket Interface                    
 
3
// % File               :       GUSISocketMixins.nw     -       Useful building blocks                  
 
4
// % Author     :       Matthias Neeracher                                           
 
5
// % Language   :       C++                                                        
 
6
// %                                                                       
 
7
// % $Log: GUSISocketMixins.h,v $
 
8
// % Revision 1.1  2001/03/11 22:38:21  sgehani%netscape.com
 
9
// % First Checked In.
 
10
// %                                         
 
11
// % Revision 1.11  2000/10/16 04:10:12  neeri                             
 
12
// % Add GUSISMProcess                                                     
 
13
// %                                                                       
 
14
// % Revision 1.10  2000/05/23 07:24:58  neeri                             
 
15
// % Improve formatting                                                    
 
16
// %                                                                       
 
17
// % Revision 1.9  1999/08/26 05:45:09  neeri                              
 
18
// % Fixes for literate edition of source code                             
 
19
// %                                                                       
 
20
// % Revision 1.8  1999/08/02 07:02:46  neeri                              
 
21
// % Support for asynchronous errors and other socket options              
 
22
// %                                                                       
 
23
// % Revision 1.7  1999/05/29 06:26:45  neeri                              
 
24
// % Fixed header guards                                                   
 
25
// %                                                                       
 
26
// % Revision 1.6  1999/04/29 05:33:18  neeri                              
 
27
// % Fix fcntl prototype                                                   
 
28
// %                                                                       
 
29
// % Revision 1.5  1999/03/17 09:05:13  neeri                              
 
30
// % Added GUSITimer, expanded docs                                        
 
31
// %                                                                       
 
32
// % Revision 1.4  1998/10/11 16:45:24  neeri                              
 
33
// % Ready to release 2.0a2                                                
 
34
// %                                                                       
 
35
// % Revision 1.3  1998/01/25 20:53:59  neeri                              
 
36
// % Engine implemented, except for signals & scheduling                   
 
37
// %                                                                       
 
38
// % Revision 1.2  1997/11/13 21:12:13  neeri                              
 
39
// % Fall 1997                                                             
 
40
// %                                                                       
 
41
// % Revision 1.1  1996/12/16 02:12:42  neeri                              
 
42
// % TCP Sockets sort of work                                              
 
43
// %                                                                       
 
44
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
 
45
//                                                                         
 
46
// \chapter{Mixin Classes for Sockets}                                     
 
47
//                                                                         
 
48
// This section contains some building block classes for sockets:          
 
49
//                                                                         
 
50
// \begin{itemize}                                                         
 
51
// \item [[GUSISMBlocking]] implements the blocking/nonblocking flag.      
 
52
// \item [[GUSISMState]] implements a state variable.                      
 
53
// \item [[GUSISMInputBuffer]] provides a [[GUSIBuffer]] for input.        
 
54
// \item [[GUSISMOutputBuffer]] provides a [[GUSIBuffer]] for output.      
 
55
// \item [[GUSISMAsyncError]] provides storage for asynchronous errors.    
 
56
// \item [[GUSISMProcess]] maintains a link to the process instance.       
 
57
// \end{itemize}                                                           
 
58
//                                                                         
 
59
//                                                                         
 
60
// <GUSISocketMixins.h>=                                                   
 
61
#ifndef _GUSISocketMixins_
 
62
#define _GUSISocketMixins_
 
63
 
 
64
#ifdef GUSI_INTERNAL
 
65
 
 
66
#include "GUSISocket.h"
 
67
#include "GUSIBuffer.h"
 
68
 
 
69
#include <fcntl.h>
 
70
#include <sys/ioctl.h>
 
71
 
 
72
// \section{Definition of [[GUSISocketMixins]]}                            
 
73
//                                                                         
 
74
// [[GUSISMBlocking]] implements the [[fBlocking]] flags and the [[DoIoctl]] and
 
75
// [[DoFcntl]] variants to manipulate it. These two functions work like their
 
76
// [[GUSISocket]] member function counterparts, but handle the return value 
 
77
// differently: The POSIX function result is stored in [[*result]], while the
 
78
// return value indicates whether the request was handled.                 
 
79
//                                                                         
 
80
// <Definition of class [[GUSISMBlocking]]>=                               
 
81
class GUSISMBlocking {
 
82
public:
 
83
        GUSISMBlocking();
 
84
        bool    fBlocking;
 
85
        bool    DoFcntl(int * result, int cmd, va_list arg);
 
86
        bool    DoIoctl(int * result, unsigned int request, va_list arg);
 
87
};
 
88
// [[GUSISMState]] captures the state of a socket over its lifetime. It starts out
 
89
// as [[Unbound]]. [[bind]] will put it into [[Unconnected]] state, though few
 
90
// socket classes care about this distinction. [[listen]] will put it into 
 
91
// [[Listening]] state. [[accept]] starts a [[Connected]] new socket.      
 
92
// [[connect]] puts an [[Unconnected]] socket into [[Connecting]] state from
 
93
// where it emerges [[Connected]]. [[fReadShutdown]] and [[fWriteShutdown]] record
 
94
// shutdown promises.                                                      
 
95
//                                                                         
 
96
// <Definition of class [[GUSISMState]]>=                                  
 
97
class GUSISMState {
 
98
public:
 
99
        enum State {
 
100
                Unbound,
 
101
                Unconnected,    
 
102
                Listening,
 
103
                Connecting,
 
104
                Connected,
 
105
                Closing
 
106
        };
 
107
        GUSISMState();
 
108
        State   fState;
 
109
        bool    fReadShutdown;
 
110
        bool    fWriteShutdown;
 
111
        void    Shutdown(int how);
 
112
};
 
113
// [[GUSISMInputBuffer]] defines the input buffer and some socket options that go
 
114
// with it. [[DoGetSockOpt]] and [[DoSetSockOpt]] work the same way as     
 
115
// [[DoFcntl]] and [[DoIoctl]] above.                                      
 
116
//                                                                         
 
117
// <Definition of class [[GUSISMInputBuffer]]>=                            
 
118
class GUSISMInputBuffer {
 
119
public:
 
120
        GUSIRingBuffer  fInputBuffer;
 
121
        GUSISMInputBuffer();
 
122
        bool                    DoGetSockOpt(
 
123
                                                int * result, int level, int optname, 
 
124
                                                void *optval, socklen_t * optlen);
 
125
        bool                    DoSetSockOpt(
 
126
                                                int * result, int level, int optname, 
 
127
                                                void *optval, socklen_t optlen);        
 
128
        bool                    DoIoctl(int * result, unsigned int request, va_list arg);
 
129
};
 
130
// [[GUSISMOutputBuffer]] defines the output buffer and some socket options that go
 
131
// with it.                                                                
 
132
//                                                                         
 
133
// <Definition of class [[GUSISMOutputBuffer]]>=                           
 
134
class GUSISMOutputBuffer {
 
135
public:
 
136
        GUSIRingBuffer  fOutputBuffer;
 
137
        GUSISMOutputBuffer();
 
138
        bool            DoGetSockOpt(
 
139
                                                int * result, int level, int optname, 
 
140
                                                void *optval, socklen_t * optlen);
 
141
        bool            DoSetSockOpt(
 
142
                                                int * result, int level, int optname, 
 
143
                                                void *optval, socklen_t optlen);        
 
144
};
 
145
// [[GUSISMAsyncError]] stores asynchronous errors and makes them available via
 
146
// [[getsockopt]]. [[GetAsyncError]] returns the error and resets the stored value.
 
147
//                                                                         
 
148
// <Definition of class [[GUSISMAsyncError]]>=                             
 
149
class GUSISMAsyncError {
 
150
public:
 
151
        GUSISMAsyncError();
 
152
        int                     fAsyncError;
 
153
        int                     SetAsyncPosixError(int error);
 
154
        int                     SetAsyncMacError(OSErr error);
 
155
        int                     GetAsyncError();
 
156
        bool            DoGetSockOpt(
 
157
                                                int * result, int level, int optname, 
 
158
                                                void *optval, socklen_t * optlen);
 
159
};
 
160
// [[GUSISMProcess]] stores a link to the global [[GUSIProcess]] instance, which is useful for completion routines.
 
161
//                                                                         
 
162
// <Definition of class [[GUSISMProcess]]>=                                
 
163
class GUSISMProcess {
 
164
public:
 
165
        GUSISMProcess();
 
166
        
 
167
        GUSIProcess * Process(); 
 
168
private:
 
169
        GUSIProcess *   fProcess;
 
170
};
 
171
 
 
172
// \section{Implementation of [[GUSISocketMixins]]}                        
 
173
//                                                                         
 
174
// Because all the member functions are simple and called in few places, it
 
175
// makes sense to inline them.                                             
 
176
//                                                                         
 
177
// All sockets start out blocking.                                         
 
178
//                                                                         
 
179
// <Inline member functions for class [[GUSISMBlocking]]>=                 
 
180
inline GUSISMBlocking::GUSISMBlocking() : fBlocking(true)       {}
 
181
// For historical reasons, there is both an [[ioctl]] and a [[fcntl]] interface
 
182
// to the blocking flag.                                                   
 
183
//                                                                         
 
184
// <Inline member functions for class [[GUSISMBlocking]]>=                 
 
185
inline bool GUSISMBlocking::DoFcntl(int * result, int cmd, va_list arg)
 
186
{
 
187
        switch(cmd) {
 
188
        case F_GETFL : 
 
189
                return (*result = fBlocking ? 0: FNDELAY), true;
 
190
        case F_SETFL : 
 
191
                fBlocking = !(va_arg(arg, int) & FNDELAY);
 
192
                
 
193
                return (*result = 0), true;
 
194
        }
 
195
        return false;
 
196
}
 
197
inline bool GUSISMBlocking::DoIoctl(int * result, unsigned int request, va_list arg)
 
198
{
 
199
        if (request == FIONBIO) {
 
200
                fBlocking = !*va_arg(arg, int *);
 
201
                return (*result = 0), true;
 
202
        }
 
203
        return false;
 
204
}
 
205
// Sockets start out as unconnected.                                       
 
206
//                                                                         
 
207
// <Inline member functions for class [[GUSISMState]]>=                    
 
208
inline GUSISMState::GUSISMState() : 
 
209
        fState(Unbound), fReadShutdown(false), fWriteShutdown(false)            {}
 
210
// <Inline member functions for class [[GUSISMState]]>=                    
 
211
inline void GUSISMState::Shutdown(int how)
 
212
{
 
213
        if (!(how & 1))
 
214
                fReadShutdown = true;
 
215
        if (how > 0)
 
216
                fWriteShutdown = true;
 
217
}
 
218
// Buffers initially are 8K.                                               
 
219
//                                                                         
 
220
// <Inline member functions for class [[GUSISMInputBuffer]]>=              
 
221
inline GUSISMInputBuffer::GUSISMInputBuffer() : fInputBuffer(8192)      {}
 
222
// [[getsockopt]] is used to obtain the buffer size.                       
 
223
//                                                                         
 
224
// <Inline member functions for class [[GUSISMInputBuffer]]>=              
 
225
inline bool GUSISMInputBuffer::DoGetSockOpt(
 
226
                                        int * result, int level, int optname, 
 
227
                                        void *optval, socklen_t *)
 
228
{
 
229
        if (level == SOL_SOCKET && optname == SO_RCVBUF) {
 
230
                *(int *)optval = (int)fInputBuffer.Size();
 
231
                
 
232
                return (*result = 0), true;
 
233
        }
 
234
        return false;
 
235
}
 
236
// [[setsockopt]] modifies the buffer size.                                
 
237
//                                                                         
 
238
// <Inline member functions for class [[GUSISMInputBuffer]]>=              
 
239
inline bool GUSISMInputBuffer::DoSetSockOpt(
 
240
                                        int * result, int level, int optname, 
 
241
                                        void *optval, socklen_t)
 
242
{
 
243
        if (level == SOL_SOCKET && optname == SO_RCVBUF) {
 
244
                fInputBuffer.SwitchBuffer(*(int *)optval);
 
245
                
 
246
                return (*result = 0), true;
 
247
        }
 
248
        return false;
 
249
}
 
250
// [[ioctl]] returns the number of available bytes.                        
 
251
//                                                                         
 
252
// <Inline member functions for class [[GUSISMInputBuffer]]>=              
 
253
inline bool GUSISMInputBuffer::DoIoctl(int * result, unsigned int request, va_list arg)
 
254
{
 
255
        if (request == FIONREAD) {
 
256
                *va_arg(arg, long *) = fInputBuffer.Valid();
 
257
                return (*result = 0), true;
 
258
        }
 
259
        return false;
 
260
}
 
261
// [[GUSISMOutputBuffer]] works identically to the input buffer.           
 
262
//                                                                         
 
263
// <Inline member functions for class [[GUSISMOutputBuffer]]>=             
 
264
inline GUSISMOutputBuffer::GUSISMOutputBuffer() : fOutputBuffer(8192)   {}
 
265
// [[getsockopt]] is used to obtain the buffer size.                       
 
266
//                                                                         
 
267
// <Inline member functions for class [[GUSISMOutputBuffer]]>=             
 
268
inline bool GUSISMOutputBuffer::DoGetSockOpt(
 
269
                                        int * result, int level, int optname, 
 
270
                                        void *optval, socklen_t *)
 
271
{
 
272
        if (level == SOL_SOCKET && optname == SO_SNDBUF) {
 
273
                *(int *)optval = (int)fOutputBuffer.Size();
 
274
                
 
275
                return (*result = 0), true;
 
276
        }
 
277
        return false;
 
278
}
 
279
// [[setsockopt]] is modifies the buffer size.                             
 
280
//                                                                         
 
281
// <Inline member functions for class [[GUSISMOutputBuffer]]>=             
 
282
inline bool GUSISMOutputBuffer::DoSetSockOpt(
 
283
                                        int * result, int level, int optname, 
 
284
                                        void *optval, socklen_t)
 
285
{
 
286
        if (level == SOL_SOCKET && optname == SO_SNDBUF) {
 
287
                fOutputBuffer.SwitchBuffer(*(int *)optval);
 
288
                
 
289
                return (*result = 0), true;
 
290
        }
 
291
        return false;
 
292
}
 
293
// <Inline member functions for class [[GUSISMAsyncError]]>=               
 
294
inline GUSISMAsyncError::GUSISMAsyncError()
 
295
 : fAsyncError(0)
 
296
{
 
297
}
 
298
// The central member functions of [[GUSISMAsyncError]] are [[SetAsyncXXXError]] and
 
299
// [[GetAsyncError]].                                                      
 
300
//                                                                         
 
301
// <Inline member functions for class [[GUSISMAsyncError]]>=               
 
302
inline int GUSISMAsyncError::SetAsyncPosixError(int error)
 
303
{
 
304
        if (error) {
 
305
                fAsyncError = error;
 
306
                GUSI_MESSAGE(("GUSISMAsyncError::SetAsyncPosixError %d\n", fAsyncError));
 
307
                
 
308
                return -1;
 
309
        }
 
310
        return 0;
 
311
}
 
312
inline int GUSISMAsyncError::GetAsyncError()
 
313
{
 
314
        int err = fAsyncError;
 
315
        fAsyncError = 0;
 
316
        return err;
 
317
}
 
318
// For some reason, the CW Pro 4 compilers generated bad code for this in some combination, so
 
319
// we make it out of line.                                                 
 
320
//                                                                         
 
321
// <Inline member functions for class [[GUSISMAsyncError]]>=               
 
322
inline int GUSISMAsyncError::SetAsyncMacError(OSErr error)
 
323
{
 
324
        if (error) {
 
325
                fAsyncError = GUSIMapMacError(error);
 
326
                GUSI_MESSAGE(("GUSISMAsyncError::SetAsyncMacError %d -> %d\n", error, fAsyncError));
 
327
                
 
328
                return -1;
 
329
        }
 
330
        return 0;
 
331
}
 
332
// [[DoGetSockOpt]] only handles [[SO_ERROR]] (hi Philippe!).              
 
333
//                                                                         
 
334
// <Inline member functions for class [[GUSISMAsyncError]]>=               
 
335
inline bool GUSISMAsyncError::DoGetSockOpt(
 
336
                                                int * result, int level, int optname, 
 
337
                                                void *optval, socklen_t * optlen)
 
338
{
 
339
        if (level == SOL_SOCKET && optname == SO_ERROR) {
 
340
                *(int *)optval  = GetAsyncError();
 
341
                *optlen                 = sizeof(int);
 
342
                
 
343
                return (*result = 0), true;
 
344
        }
 
345
        return false;
 
346
}
 
347
// <Inline member functions for class [[GUSISMProcess]]>=                  
 
348
inline GUSISMProcess::GUSISMProcess()
 
349
 : fProcess(GUSIProcess::Instance())
 
350
{
 
351
}
 
352
 
 
353
inline GUSIProcess * GUSISMProcess::Process()
 
354
{
 
355
        return fProcess;
 
356
}
 
357
 
 
358
#endif /* GUSI_INTERNAL */
 
359
 
 
360
#endif /* _GUSISocketMixins_ */