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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.9  
changed lines
  Added in v.37

  ViewVC Help
Powered by ViewVC 1.1.26