/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9 - (hide annotations)
Fri Dec 8 16:52:58 2006 UTC (13 years, 4 months ago) by andrew.betts
File size: 6717 byte(s)


1 andrew.betts 9 #!/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 andrew.betts 3 ############################################################################EOF

  ViewVC Help
Powered by ViewVC 1.1.26