]> Dogcows Code - chaz/chatty/blobdiff - extra/cometd/Meteor/Socket.pm
import meteord-1.06
[chaz/chatty] / extra / cometd / Meteor / Socket.pm
diff --git a/extra/cometd/Meteor/Socket.pm b/extra/cometd/Meteor/Socket.pm
new file mode 100644 (file)
index 0000000..19de6cf
--- /dev/null
@@ -0,0 +1,289 @@
+#!/usr/bin/perl -w
+###############################################################################
+#   Meteor
+#   An HTTP server for the 2.0 web
+#   Copyright (c) 2006 contributing authors
+#
+#   Subscriber.pm
+#
+#      Description:
+#      Meteor socket additions
+#
+###############################################################################
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the Free
+#   Software Foundation; either version 2 of the License, or (at your option)
+#   any later version.
+#
+#   This program is distributed in the hope that it will be useful, but WITHOUT
+#   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+#   FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+#   more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program; if not, write to the Free Software Foundation, Inc.,
+#   59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+#   For more information visit www.meteorserver.org
+#
+###############################################################################
+
+package Meteor::Socket;
+###############################################################################
+# Configuration
+###############################################################################
+       
+       use strict;
+       
+       use Socket;
+       use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
+       use Errno qw(EINTR);
+       
+       BEGIN {
+               $Meteor::Socket::handleNum=0;
+               
+               # Cache getprotobyname result as on some systems it is slow.
+               $Meteor::Socket::TCP_PROTO_NAME=getprotobyname('tcp');
+               $Meteor::Socket::UDP_PROTO_NAME=getprotobyname('udp');
+       }
+
+###############################################################################
+# Factory methods
+###############################################################################
+sub new {
+       my $class=shift;
+       
+       my $self=$class;
+       
+       unless(ref($class))
+       {
+               $self={};
+               bless($self,$class);
+       }
+       
+       $self->{'timeout'}=0;
+       $self->{'buffer'}='';
+       
+       return $self;
+}
+
+sub newWithHandle {
+       my $class=shift;
+       
+       my $self=$class->new;
+       $self->{'handle'}=shift;
+       
+       my $vec='';
+       vec($vec,CORE::fileno($self->{'handle'}),1)=1;
+       $self->{'handleVec'}=$vec;
+       
+       my $timeout=shift;
+       ($timeout) && ($self->{'timeout'}=$timeout);
+       
+       return $self;
+}
+
+sub newServer {
+       my($class,$port,$queueSize,$srcIP)=@_;
+       
+       ($port) || die("$class: port undefined!");
+       
+       $queueSize||=5;
+       
+       my $self=$class->new;
+       
+       my $localAdr=INADDR_ANY;
+       $localAdr=inet_aton($srcIP) if(defined($srcIP) && $srcIP ne '');
+       
+       my $local;
+       my $sockType=AF_INET;
+       my $proto=$Meteor::Socket::TCP_PROTO_NAME;
+       
+       $self->{'port'}=$port;
+       ($local=sockaddr_in($port,$localAdr))
+               || die("$class: sockaddr_in for port '$port' failed");
+       
+       $self->{'handle'}=$self->nextHandle();
+       $self->{'socketType'}=$sockType;
+       
+       socket($self->{'handle'},$sockType,SOCK_STREAM,$proto)
+               || die("$class socket: $!");
+       
+       setsockopt($self->{'handle'},SOL_SOCKET,SO_REUSEADDR,1);
+       
+       bind($self->{'handle'},$local)
+               || die("$class bind: $!");
+       listen($self->{'handle'},$queueSize)
+               || die("$class listen: $!");
+               
+       select((select($self->{'handle'}),$|=1)[0]);
+       
+       my $vec='';
+       vec($vec,CORE::fileno($self->{'handle'}),1)=1;
+       $self->{'handleVec'}=$vec;
+       
+       return $self;
+}
+
+sub newUDPServer {
+       my($class,$port,$srcIP)=@_;
+       
+       ($port) || die("$class: port undefined!");
+       
+       my $self=$class->new;
+       
+       my $localAdr=INADDR_ANY;
+       $localAdr=inet_aton($srcIP) if(defined($srcIP) && $srcIP ne '');
+       
+       my $local;
+       my $sockType=PF_INET;
+       my $proto=$Meteor::Socket::UDP_PROTO_NAME;
+       
+       $self->{'port'}=$port;
+       ($local=sockaddr_in($port,$localAdr))
+               || die("$class: sockaddr_in for port '$port' failed");
+       
+       $self->{'handle'}=$self->nextHandle();
+       $self->{'socketType'}=$sockType;
+       
+       socket($self->{'handle'},$sockType,SOCK_DGRAM,$proto)
+               || die("$class socket: $!");
+       
+       setsockopt($self->{'handle'},SOL_SOCKET,SO_REUSEADDR,pack("l", 1))
+               || die("setsockopt: $!");
+       
+       bind($self->{'handle'},$local)
+               || die("$class bind: $!");
+               
+       select((select($self->{'handle'}),$|=1)[0]);
+       
+       my $vec='';
+       vec($vec,CORE::fileno($self->{'handle'}),1)=1;
+       $self->{'handleVec'}=$vec;
+       
+       return $self;
+}
+
+###############################################################################
+# Instance methods
+###############################################################################
+sub DESTROY {
+       my $self=shift;
+       
+       if(exists($self->{'handle'}))
+       {
+               warn("$self->DESTROY caught unclosed socket")
+                       unless($Meteor::Socket::NO_WARN_ON_CLOSE);
+               $self->close();
+       }
+}
+
+sub conSocket {
+       my $self=shift;
+       
+       my $handle=$self->nextHandle();
+       
+       my $paddr;
+       $paddr=&saccept($handle,$self->{'handle'}) || die($!);
+       
+       select((select($handle),$|=1)[0]);
+       
+       my $newSock=Meteor::Socket->newWithHandle($handle,20);
+       $newSock->{'socketType'}=$self->{'socketType'};
+       if($self->{'socketType'}==AF_INET)
+       {
+               my($port,$iaddr)=unpack_sockaddr_in($paddr);
+               
+               $newSock->{'connection'}->{'port'}=$port;
+               $newSock->{'connection'}->{'remoteIP'}=inet_ntoa($iaddr);
+       }
+       
+       return $newSock;
+}
+
+sub setNonBlocking {
+       my $self=shift;
+       
+       my $flags=fcntl($self->{'handle'},F_GETFL,0)
+               or die("Can't get flags for the socket: $!");
+       fcntl($self->{'handle'},F_SETFL,$flags|O_NONBLOCK)
+               or die("Can't set flags for the socket: $!");
+}
+
+sub close {
+       my $self=shift;
+       
+       if(exists($self->{'handle'}))
+       {
+               close($self->{'handle'});
+               delete($self->{'handle'});
+       }
+}
+
+###############################################################################
+# Utility functions
+###############################################################################
+sub nextHandle {
+       no strict 'refs';
+       
+       my $name='MSHandle'.$Meteor::Socket::handleNum++;
+       my $pack='Meteor::Socket::';
+               my $handle=\*{$pack.$name};
+       delete $$pack{$name};
+       
+       $handle;
+}      
+
+sub sselect {
+       my $result;
+       my $to=$_[3];
+       my $time=time;
+       while(1)
+       {
+               $result=CORE::select($_[0],$_[1],$_[2],$to);
+               if($result<0)
+               {
+                       last unless(${!}==EINTR);
+                       return 0 if($::HUP || $::TERM || $::USR1 || $::USR2);
+                       my $tn=time;
+                       $to-=($tn-$time);
+                       $time=$tn;
+                       $to=1 if($to<1);
+               }
+               else
+               {
+                       last;
+               }
+       }
+       
+       $result;
+}
+
+sub saccept {
+       my($dhandle,$shandle)=@_;
+       
+       my $result;
+       while(1)
+       {
+               $result=CORE::accept($dhandle,$shandle);
+               unless($result)
+               {
+                       last unless(${!}==EINTR);
+                       return 0 if($::HUP || $::TERM || $::USR1 || $::USR2);
+               }
+               else
+               {
+                       last;
+               }
+       }
+       
+       $result;
+}
+
+sub fileno {
+       CORE::fileno(shift->{'handle'});
+}
+
+1;
+############################################################################EOF
\ No newline at end of file
This page took 0.020996 seconds and 4 git commands to generate.