ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Event/Socket.pm
(Generate patch)

Comparing Coro/Event/Socket.pm (file contents):
Revision 1.39 by root, Sat Nov 4 01:31:57 2006 UTC vs.
Revision 1.40 by root, Sun Nov 5 02:01:24 2006 UTC

70 $port or $host =~ s/:([^:]+)$// and $port = $1; 70 $port or $host =~ s/:([^:]+)$// and $port = $1;
71 my $_proto = _proto($proto); 71 my $_proto = _proto($proto);
72 my $_port = _port($port, $proto); 72 my $_port = _port($port, $proto);
73 73
74 # optimize this a bit for a common case 74 # optimize this a bit for a common case
75 if ($host =~ /^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?) 75 if (Coro::Util::dotted_quad $host) {
76 \.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?)
77 \.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?)
78 \.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9][0-9]?)$/) {
79 return pack_sockaddr_in($_port, inet_aton $host); 76 return pack_sockaddr_in ($_port, inet_aton $host);
80 } else { 77 } else {
81 my (undef, undef, undef, undef, @host) = Coro::Util::gethostbyname $host 78 my (undef, undef, undef, undef, @host) = Coro::Util::gethostbyname $host
82 or croak "unknown host: $host"; 79 or croak "unknown host: $host";
83 map pack_sockaddr_in($_port,$_), @host; 80 map pack_sockaddr_in ($_port,$_), @host;
84 } 81 }
85} 82}
86 83
87=item $fh = new Coro::Socket param => value, ... 84=item $fh = new Coro::Socket param => value, ...
88 85
98 $fh = new Coro::Socket PeerHost => "localhost", PeerPort => 'finger'; 95 $fh = new Coro::Socket PeerHost => "localhost", PeerPort => 'finger';
99 96
100=cut 97=cut
101 98
102sub _prepare_socket { 99sub _prepare_socket {
103 my ($class, $arg) = @_; 100 my ($self, $arg) = @_;
104 my $fh;
105 101
106 socket $fh, PF_INET, $arg->{Type}, _proto($arg->{Proto}) 102 $self
107 or return;
108
109 $fh = bless Coro::Handle->new_from_fh (
110 $fh,
111 timeout => $arg->{Timeout},
112 forward_class => $arg->{forward_class},
113 ), $class
114 or return;
115
116 if ($arg->{ReuseAddr}) {
117 $fh->setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
118 or croak "setsockopt(SO_REUSEADDR): $!";
119 }
120
121 if ($arg->{ReusePort}) {
122 $fh->setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
123 or croak "setsockopt(SO_REUSEPORT): $!";
124 }
125
126 if ($arg->{LocalPort} || $arg->{LocalHost}) {
127 my @sa = _sa($arg->{LocalHost} || "0.0.0.0", $arg->{LocalPort} || 0, $arg->{Proto});
128 $fh->bind($sa[0])
129 or croak "bind($arg->{LocalHost}:$arg->{LocalPort}): $!";
130 }
131
132 $fh;
133} 103}
134 104
135sub new { 105sub new {
136 my $class = shift;
137 my %arg = @_; 106 my ($class, %arg) = @_;
138 my $fh;
139 107
140 $arg{Proto} ||= 'tcp'; 108 $arg{Proto} ||= 'tcp';
141 $arg{LocalHost} ||= delete $arg{LocalAddr}; 109 $arg{LocalHost} ||= delete $arg{LocalAddr};
142 $arg{PeerHost} ||= delete $arg{PeerAddr}; 110 $arg{PeerHost} ||= delete $arg{PeerAddr};
143 defined ($arg{Type}) or $arg{Type} = $arg{Proto} eq "tcp" ? SOCK_STREAM : SOCK_DGRAM; 111 defined ($arg{Type}) or $arg{Type} = $arg{Proto} eq "tcp" ? SOCK_STREAM : SOCK_DGRAM;
144 112
113 socket my $fh, PF_INET, $arg{Type}, _proto ($arg{Proto})
114 or return;
115
116 my $self = bless Coro::Handle->new_from_fh (
117 $fh,
118 timeout => $arg{Timeout},
119 forward_class => $arg{forward_class},
120 ), $class
121 or return;
122
123 $self->configure (\%arg)
124}
125
126sub configure {
127 my ($self, $arg) = @_;
128
129 if ($arg->{ReuseAddr}) {
130 $self->setsockopt (SOL_SOCKET, SO_REUSEADDR, 1)
131 or croak "setsockopt(SO_REUSEADDR): $!";
132 }
133
134 if ($arg->{ReusePort}) {
135 $self->setsockopt (SOL_SOCKET, SO_REUSEPORT, 1)
136 or croak "setsockopt(SO_REUSEPORT): $!";
137 }
138
139 if ($arg->{LocalPort} || $arg->{LocalHost}) {
140 my @sa = _sa($arg->{LocalHost} || "0.0.0.0", $arg->{LocalPort} || 0, $arg->{Proto});
141 $self->bind ($sa[0])
142 or croak "bind($arg->{LocalHost}:$arg->{LocalPort}): $!";
143 }
144
145 if ($arg{PeerHost}) { 145 if ($arg->{PeerHost}) {
146 my @sa = _sa($arg{PeerHost}, $arg{PeerPort}, $arg{Proto}); 146 my @sa = _sa($arg->{PeerHost}, $arg->{PeerPort}, $arg->{Proto});
147 147
148 for (@sa) { 148 for (@sa) {
149 $fh = $class->_prepare_socket(\%arg)
150 or return;
151
152 $! = 0; 149 $! = 0;
153 150
154 if ($fh->connect($_)) { 151 if ($self->connect ($_)) {
155 next unless writable $fh; 152 next unless writable $self;
156 $! = unpack "i", $fh->getsockopt(SOL_SOCKET, SO_ERROR); 153 $! = unpack "i", $self->getsockopt(SOL_SOCKET, SO_ERROR);
157 } 154 }
158 155
159 $! or last; 156 $! or last;
160 157
161 $!{ECONNREFUSED} or $!{ENETUNREACH} or $!{ETIMEDOUT} or $!{EHOSTUNREACH} 158 $!{ECONNREFUSED} or $!{ENETUNREACH} or $!{ETIMEDOUT} or $!{EHOSTUNREACH}
162 or return; 159 or return;
163
164 undef $fh;
165 } 160 }
166 } else { 161 } else {
167 $fh = $class->_prepare_socket(\%arg)
168 or return;
169 if (exists $arg{Listen}) { 162 if (exists $arg->{Listen}) {
170 $fh->listen($arg{Listen}) 163 $self->listen ($arg->{Listen})
171 or return; 164 or return;
172 } 165 }
173 } 166 }
174 167
175 $fh; 168 $self
176} 169}
177 170
178=item connect, listen, bind, getsockopt, setsockopt, 171=item connect, listen, bind, getsockopt, setsockopt,
179send, recv, peername, sockname, shutdown 172send, recv, peername, sockname, shutdown
180 173

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines