/[meteor]/googlecode.com/svn/trunk/Meteor/Connection.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /googlecode.com/svn/trunk/Meteor/Connection.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (show annotations)
Mon Nov 20 17:59:30 2006 UTC (17 years, 4 months ago) by andrew.betts
File size: 6421 byte(s)
Initial import
1 #!/usr/bin/perl -w
2 ###############################################################################
3 # Meteor
4 # An HTTP server for the 2.0 web
5 # Copyright (c) 2006 contributing authors
6 #
7 # Subscriber.pm
8 #
9 # Description:
10 # Common super-class for controller and subscriber
11 #
12 ###############################################################################
13 #
14 # This program is free software; you can redistribute it and/or modify it
15 # under the terms of the GNU General Public License as published by the Free
16 # Software Foundation; either version 2 of the License, or (at your option)
17 # any later version.
18 #
19 # This program is distributed in the hope that it will be useful, but WITHOUT
20 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
22 # more details.
23 #
24 # You should have received a copy of the GNU General Public License along
25 # with this program; if not, write to the Free Software Foundation, Inc.,
26 # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #
28 # For more information visit www.meteorserver.org
29 #
30 ###############################################################################
31
32 package Meteor::Connection;
33 ###############################################################################
34 # Configuration
35 ###############################################################################
36
37 use strict;
38
39 use Errno qw(EAGAIN);
40
41 our $MAX_READ_SIZE=8192;
42 our $CONNECTION_WRITE_TIMEOUT=120;
43
44 our @Connections=();
45
46 ###############################################################################
47 # Class methods
48 ###############################################################################
49 sub addAllHandleBits {
50 my $class=shift;
51
52 my $rVecRef=shift;
53 my $wVecRef=shift;
54 my $eVecRef=shift;
55
56 map {$_->addHandleBits($rVecRef,$wVecRef,$eVecRef)} @Connections;
57 }
58
59 sub checkAllHandleBits {
60 my $class=shift;
61
62 my $rVec=shift;
63 my $wVec=shift;
64 my $eVec=shift;
65
66 map {$_->checkHandleBits($rVec,$wVec,$eVec)} @Connections;
67 }
68
69 sub connectionCount {
70 scalar(@Connections);
71 }
72
73 sub closeAllConnections {
74 my @cons=@Connections;
75
76 map { $_->close(); } @cons;
77 }
78
79 ###############################################################################
80 # Factory methods
81 ###############################################################################
82 sub new {
83 #
84 # Create a new empty instance
85 #
86 my $class=shift;
87
88 my $obj={};
89
90 bless($obj,$class);
91 }
92
93 sub newFromServer {
94 #
95 # new instance from new server connection
96 #
97 my $self=shift->new();
98
99 my $server=shift;
100 my $socket=$server->conSocket();
101
102 $self->{'socket'}=$socket;
103 $self->{'socketFN'}=$socket->fileno();
104
105 $socket->setNonBlocking();
106
107 $self->{'writeBuffer'}='';
108 $self->{'readBuffer'}='';
109
110 push(@Connections,$self);
111
112 &::syslog('debug',"New %s for %s",ref($self),$socket->{'connection'}->{'remoteIP'});
113
114 $self;
115 }
116
117 ###############################################################################
118 # Instance methods
119 ###############################################################################
120 sub write {
121 my $self=shift;
122
123 $self->{'writeBuffer'}.=shift;
124 $self->{'writeBufferTimestamp'}=time unless(exists($self->{'writeBufferTimestamp'}));
125 }
126
127 sub addHandleBits {
128 my $self=shift;
129
130 my $rVecRef=shift;
131 my $wVecRef=shift;
132 my $eVecRef=shift;
133
134 my $fno=$self->{'socketFN'};
135
136 if($self->{'writeBuffer'} ne '')
137 {
138 if(exists($self->{'writeBufferTimestamp'}) && $self->{'writeBufferTimestamp'}+$CONNECTION_WRITE_TIMEOUT<time)
139 {
140 &::syslog('debug',"%s for %s: write timed out",ref($self),$self->{'socket'}->{'connection'}->{'remoteIP'});
141
142 $self->{'writeBuffer'}='';
143 $self->close();
144 return;
145 }
146 vec($$wVecRef,$fno,1)=1;
147 }
148
149 vec($$rVecRef,$fno,1)=1;
150 vec($$eVecRef,$fno,1)=1;
151 }
152
153 sub checkHandleBits {
154 my $self=shift;
155
156 my $rVec=shift;
157 my $wVec=shift;
158 my $eVec=shift;
159
160 my $fno=$self->{'socketFN'};
161
162 if(vec($eVec,$fno,1))
163 {
164 #
165 # Something went wrong!
166 #
167 $self->exceptionReceived();
168
169 return;
170 }
171
172 if(vec($rVec,$fno,1))
173 {
174 #
175 # Data available for read
176 #
177 my $socket=$self->{'socket'};
178
179 my $buffer='';
180 my $bytesRead=sysread($socket->{'handle'},$buffer,$MAX_READ_SIZE);
181 if(defined($bytesRead) && $bytesRead>0)
182 {
183 $self->{'readBuffer'}.=$buffer;
184 while($self->{'readBuffer'}=~s/^([^\r\n]*)\r?\n//)
185 {
186 $self->processLine($1);
187 }
188 }
189 elsif(defined($bytesRead) && $bytesRead==0)
190 {
191 # Connection closed
192 $self->{'remoteClosed'}=1;
193 $self->close();
194
195 return;
196 }
197 else
198 {
199 unless(${!}==EAGAIN)
200 {
201 &::syslog('notice',"Connection closed: $!");
202 $self->{'remoteClosed'}=1;
203 $self->close();
204
205 return;
206 }
207 }
208 }
209
210 if(vec($wVec,$fno,1) && $self->{'writeBuffer'} ne '')
211 {
212 #
213 # Can write
214 #
215 my $socket=$self->{'socket'};
216
217 my $bytesWritten=syswrite($socket->{'handle'},$self->{'writeBuffer'});
218
219 if(defined($bytesWritten) && $bytesWritten>0)
220 {
221 $self->{'writeBuffer'}=substr($self->{'writeBuffer'},$bytesWritten);
222 if(length($self->{'writeBuffer'})==0)
223 {
224 delete($self->{'writeBufferTimestamp'});
225 $self->close() if(exists($self->{'autoClose'}));
226 }
227 else
228 {
229 $self->{'writeBufferTimestamp'}=time;
230 }
231 }
232 else
233 {
234 unless(${!}==EAGAIN)
235 {
236 &::syslog('notice',"Connection closed: $!");
237 $self->{'remoteClosed'}=1;
238 $self->close();
239
240 return;
241 }
242 }
243 }
244 }
245
246 sub exceptionReceived {
247 my $self=shift;
248
249 $self->{'writeBuffer'}='';
250
251 $self->close();
252 }
253
254 sub close {
255 my $self=shift;
256
257 #&::syslog('debug',"Close called for %s for %s when write buffer empty",ref($self),$self->{'socket'}->{'connection'}->{'remoteIP'});
258
259 unless($self->{'remoteClosed'})
260 {
261 if(!exists($self->{'autoClose'}) && length($self->{'writeBuffer'})>0)
262 {
263 $self->{'autoClose'}=1;
264
265 &::syslog('debug',"Will close %s for %s when write buffer empty",ref($self),$self->{'socket'}->{'connection'}->{'remoteIP'});
266
267 return;
268 }
269 }
270
271 eval {
272 $self->{'socket'}->close();
273 };
274
275 #
276 # Remove connection from list of connections
277 #
278 my $idx=undef;
279 for(my $i=0;$i<scalar(@Connections);$i++)
280 {
281 if($Connections[$i]==$self)
282 {
283 $idx=$i;
284 last;
285 }
286 }
287
288 if(defined($idx))
289 {
290 splice(@Connections,$idx,1);
291 }
292
293 &::syslog('debug',"Closed %s for %s",ref($self),$self->{'socket'}->{'connection'}->{'remoteIP'});
294 }
295
296 1;
297 ############################################################################EOF

  ViewVC Help
Powered by ViewVC 1.1.26