/[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 10 by andrew.betts, Fri Dec 8 16:52:58 2006 UTC revision 11 by knops.gerd, Thu Dec 14 16:29:42 2006 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;          map {$_->addHandleBits($rVecRef,$wVecRef,$eVecRef)} @Connections;
57  }  }
58    
59  sub checkAllHandleBits {  sub checkAllHandleBits {
60          my $class=shift;          my $class=shift;
61                    
62          my $rVec=shift;          my $rVec=shift;
63          my $wVec=shift;          my $wVec=shift;
64          my $eVec=shift;          my $eVec=shift;
65                    
66          map {$_->checkHandleBits($rVec,$wVec,$eVec)} @Connections;          map {$_->checkHandleBits($rVec,$wVec,$eVec)} @Connections;
67  }  }
68    
69  sub connectionCount {  sub connectionCount {
70          scalar(@Connections);          scalar(@Connections);
71  }  }
72    
73  sub closeAllConnections {  sub closeAllConnections {
74          my @cons=@Connections;          my @cons=@Connections;
75                    
76          map { $_->close(); } @cons;          map { $_->close(); } @cons;
77  }  }
78    
79  ###############################################################################  ###############################################################################
80  # Factory methods  # Factory methods
81  ###############################################################################  ###############################################################################
82  sub new {  sub new {
83          #          #
84          # Create a new empty instance          # Create a new empty instance
85          #          #
86          my $class=shift;          my $class=shift;
87                    
88          my $obj={};          my $obj={};
89                    
90          bless($obj,$class);          bless($obj,$class);
91  }  }
92    
93  sub newFromServer {  sub newFromServer {
94          #          #
95          # new instance from new server connection          # new instance from new server connection
96          #          #
97          my $self=shift->new();          my $self=shift->new();
98                    
99          my $server=shift;          my $server=shift;
100          my $socket=$server->conSocket();          my $socket=$server->conSocket();
101                    
102          $self->{'socket'}=$socket;                $self->{'socket'}=$socket;      
103          $self->{'socketFN'}=$socket->fileno();          $self->{'socketFN'}=$socket->fileno();
104                    
105          $socket->setNonBlocking();          $socket->setNonBlocking();
106                    
107          $self->{'writeBuffer'}='';          $self->{'writeBuffer'}='';
108          $self->{'readBuffer'}='';          $self->{'readBuffer'}='';
109                    
110          push(@Connections,$self);          push(@Connections,$self);
111                    
112          &::syslog('debug',"New %s for %s",ref($self),$socket->{'connection'}->{'remoteIP'});          &::syslog('debug',"New %s for %s",ref($self),$socket->{'connection'}->{'remoteIP'});
113                    
114          $self;          $self;
115  }  }
116    
117  ###############################################################################  ###############################################################################
118  # Instance methods  # Instance methods
119  ###############################################################################  ###############################################################################
120  sub write {  sub write {
121          my $self=shift;          my $self=shift;
122                    
123          $self->{'writeBuffer'}.=shift;          $self->{'writeBuffer'}.=shift;
124          $self->{'writeBufferTimestamp'}=time unless(exists($self->{'writeBufferTimestamp'}));          $self->{'writeBufferTimestamp'}=time unless(exists($self->{'writeBufferTimestamp'}));
125  }  }
126    
127  sub addHandleBits {  sub addHandleBits {
128          my $self=shift;          my $self=shift;
129                    
130          my $rVecRef=shift;          my $rVecRef=shift;
131          my $wVecRef=shift;          my $wVecRef=shift;
132          my $eVecRef=shift;          my $eVecRef=shift;
133                    
134          my $fno=$self->{'socketFN'};          my $fno=$self->{'socketFN'};
135                    
136          if($self->{'writeBuffer'} ne '')          if($self->{'writeBuffer'} ne '')
137          {          {
138                  if(exists($self->{'writeBufferTimestamp'}) && $self->{'writeBufferTimestamp'}+$CONNECTION_WRITE_TIMEOUT<time)                  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'});                          &::syslog('debug',"%s for %s: write timed out",ref($self),$self->{'socket'}->{'connection'}->{'remoteIP'});
141                                                    
142                          $self->{'writeBuffer'}='';                          $self->{'writeBuffer'}='';
143                          $self->close();                          $self->close();
144                          return;                          return;
145                  }                  }
146                  vec($$wVecRef,$fno,1)=1;                  vec($$wVecRef,$fno,1)=1;
147          }          }
148    
149          vec($$rVecRef,$fno,1)=1;          vec($$rVecRef,$fno,1)=1;
150          vec($$eVecRef,$fno,1)=1;          vec($$eVecRef,$fno,1)=1;
151  }  }
152    
153  sub checkHandleBits {  sub checkHandleBits {
154          my $self=shift;          my $self=shift;
155                    
156          my $rVec=shift;          my $rVec=shift;
157          my $wVec=shift;          my $wVec=shift;
158          my $eVec=shift;          my $eVec=shift;
159                    
160          my $fno=$self->{'socketFN'};          my $fno=$self->{'socketFN'};
161                    
162          if(vec($eVec,$fno,1))          if(vec($eVec,$fno,1))
163          {          {
164                  #                  #
165                  # Something went wrong!                  # Something went wrong!
166                  #                  #
167                  $self->exceptionReceived();                  $self->exceptionReceived();
168                                    
169                  return;                  return;
170          }          }
171                    
172          if(vec($rVec,$fno,1))          if(vec($rVec,$fno,1))
173          {          {
174                  #                  #
175                  # Data available for read                  # Data available for read
176                  #                  #
177                  my $socket=$self->{'socket'};                  my $socket=$self->{'socket'};
178                                    
179                  my $buffer='';                  my $buffer='';
180                  my $bytesRead=sysread($socket->{'handle'},$buffer,$MAX_READ_SIZE);                  my $bytesRead=sysread($socket->{'handle'},$buffer,$MAX_READ_SIZE);
181                  if(defined($bytesRead) && $bytesRead>0)                  if(defined($bytesRead) && $bytesRead>0)
182                  {                  {
183                          $self->{'readBuffer'}.=$buffer;                          $self->{'readBuffer'}.=$buffer;
184                          while($self->{'readBuffer'}=~s/^([^\r\n]*)\r?\n//)                          while($self->{'readBuffer'}=~s/^([^\r\n]*)\r?\n//)
185                          {                          {
186                                  $self->processLine($1);                                  $self->processLine($1);
187                          }                          }
188                  }                  }
189                  elsif(defined($bytesRead) && $bytesRead==0)                  elsif(defined($bytesRead) && $bytesRead==0)
190                  {                  {
191                          # Connection closed                          # Connection closed
192                          $self->{'remoteClosed'}=1;                          $self->{'remoteClosed'}=1;
193                          $self->close();                          $self->close();
194                                                    
195                          return;                          return;
196                  }                  }
197                  else                  else
198                  {                  {
199                          unless(${!}==EAGAIN)                          unless(${!}==EAGAIN)
200                          {                          {
201                                  &::syslog('notice',"Connection closed: $!");                                  &::syslog('notice',"Connection closed: $!");
202                                  $self->{'remoteClosed'}=1;                                  $self->{'remoteClosed'}=1;
203                                  $self->close();                                  $self->close();
204                                                                    
205                                  return;                                  return;
206                          }                          }
207                  }                  }
208          }          }
209                    
210          if(vec($wVec,$fno,1) && $self->{'writeBuffer'} ne '')          if(vec($wVec,$fno,1) && $self->{'writeBuffer'} ne '')
211          {          {
212                  #                  #
213                  # Can write                  # Can write
214                  #                  #
215                  my $socket=$self->{'socket'};                  my $socket=$self->{'socket'};
216                                    
217                  my $bytesWritten=syswrite($socket->{'handle'},$self->{'writeBuffer'});                  my $bytesWritten=syswrite($socket->{'handle'},$self->{'writeBuffer'});
218                                    
219                  if(defined($bytesWritten) && $bytesWritten>0)                  if(defined($bytesWritten) && $bytesWritten>0)
220                  {                  {
221                          $self->{'writeBuffer'}=substr($self->{'writeBuffer'},$bytesWritten);                          $self->{'writeBuffer'}=substr($self->{'writeBuffer'},$bytesWritten);
222                          if(length($self->{'writeBuffer'})==0)                          if(length($self->{'writeBuffer'})==0)
223                          {                          {
224                                  delete($self->{'writeBufferTimestamp'});                                  delete($self->{'writeBufferTimestamp'});
225                                  $self->close() if(exists($self->{'autoClose'}));                                  $self->close() if(exists($self->{'autoClose'}));
226                          }                          }
227                          else                          else
228                          {                          {
229                                  $self->{'writeBufferTimestamp'}=time;                                  $self->{'writeBufferTimestamp'}=time;
230                          }                          }
231                  }                  }
232                  else                  else
233                  {                  {
234                          unless(${!}==EAGAIN)                          unless(${!}==EAGAIN)
235                          {                          {
236                                  &::syslog('notice',"Connection closed: $!");                                  &::syslog('notice',"Connection closed: $!");
237                                  $self->{'remoteClosed'}=1;                                  $self->{'remoteClosed'}=1;
238                                  $self->close();                                  $self->close();
239                                                                    
240                                  return;                                  return;
241                          }                          }
242                  }                  }
243          }          }
244  }  }
245    
246  sub exceptionReceived {  sub exceptionReceived {
247          my $self=shift;          my $self=shift;
248                    
249          $self->{'writeBuffer'}='';          $self->{'writeBuffer'}='';
250                    
251          $self->close();          $self->close();
252  }  }
253    
254  sub close {  sub close {
255          my $self=shift;          my $self=shift;
256                    
257          #&::syslog('debug',"Close called for %s for %s when write buffer empty",ref($self),$self->{'socket'}->{'connection'}->{'remoteIP'});          #&::syslog('debug',"Close called for %s for %s when write buffer empty",ref($self),$self->{'socket'}->{'connection'}->{'remoteIP'});
258                    
259          unless($self->{'remoteClosed'})          unless($self->{'remoteClosed'})
260          {          {
261                  if(!exists($self->{'autoClose'}) && length($self->{'writeBuffer'})>0)                  if(!exists($self->{'autoClose'}) && length($self->{'writeBuffer'})>0)
262                  {                  {
263                          $self->{'autoClose'}=1;                          $self->{'autoClose'}=1;
264                                    
265                          &::syslog('debug',"Will close %s for %s when write buffer empty",ref($self),$self->{'socket'}->{'connection'}->{'remoteIP'});                          &::syslog('debug',"Will close %s for %s when write buffer empty",ref($self),$self->{'socket'}->{'connection'}->{'remoteIP'});
266                                    
267                          return;                          return;
268                  }                  }
269          }          }
270                    
271          eval {          eval {
272                  $self->{'socket'}->close();                  $self->{'socket'}->close();
273          };          };
274                    
275          #          #
276          # Remove connection from list of connections          # Remove connection from list of connections
277          #          #
278          my $idx=undef;          my $idx=undef;
279          for(my $i=0;$i<scalar(@Connections);$i++)          for(my $i=0;$i<scalar(@Connections);$i++)
280          {          {
281                  if($Connections[$i]==$self)                  if($Connections[$i]==$self)
282                  {                  {
283                          $idx=$i;                          $idx=$i;
284                          last;                          last;
285                  }                  }
286          }          }
287                    
288          if(defined($idx))          if(defined($idx))
289          {          {
290                  splice(@Connections,$idx,1);                  splice(@Connections,$idx,1);
291          }          }
292                    
293          &::syslog('debug',"Closed %s for %s",ref($self),$self->{'socket'}->{'connection'}->{'remoteIP'});          &::syslog('debug',"Closed %s for %s",ref($self),$self->{'socket'}->{'connection'}->{'remoteIP'});
294  }  }
295    
296  1;  1;
297  ############################################################################EOF  ############################################################################EOF

Legend:
Removed from v.10  
changed lines
  Added in v.11

  ViewVC Help
Powered by ViewVC 1.1.26