use IO::Socket;
use DXDebug;
use Timer;
-use Errno qw(EWOULDBLOCK EAGAIN EINPROGRESS);
-use POSIX qw(F_GETFL F_SETFL O_NONBLOCK);
use vars qw(%rd_callbacks %wt_callbacks %er_callbacks $rd_handles $wt_handles $er_handles $now %conns $noconns);
$er_handles = IO::Select->new();
$now = time;
+my $blocking_supported = 0;
+
+BEGIN {
+ # Checks if blocking is supported
+ eval {
+ require POSIX; POSIX->import(qw (F_SETFL F_GETFL O_NONBLOCK));
+ };
+ $blocking_supported = 1 unless $@;
+
+ # import as many of these errno values as are available
+ eval {
+ require Errno; Errno->import(qw(EAGAIN EINPROGRESS EWOULDBLOCK));
+ };
+}
+
+my $w = $^W;
+$^W = 0;
+my $eagain = eval {EAGAIN()};
+my $einprogress = eval {EINPROGRESS()};
+my $ewouldblock = eval {EWOULDBLOCK()};
+$^W = $w;
#
#-----------------------------------------------------------------
sub blocking
{
+ return unless $blocking_supported;
+
my $flags = fcntl ($_[0], F_GETFL, 0);
if ($_[1]) {
$flags &= ~O_NONBLOCK;
blocking($sock, 0);
my $ip = gethostbyname($to_host);
- my $r = $sock->connect($to_port, $ip);
- unless ($r) {
- return undef unless $! == EINPROGRESS;
- }
+# my $r = $sock->connect($to_port, $ip);
+ my $r = connect($sock, pack_sockaddr_in($to_port, $ip));
+ return undef unless $r || _err_will_block($!);
$conn->{sock} = $sock;
$call ||= 'unallocated';
dbg('connll', "Connection $call disconnected");
- set_event_handler ($sock, read => undef, write => undef, error => undef);
-
unless ($^O =~ /^MS/i) {
kill 'TERM', $conn->{pid} if exists $conn->{pid};
}
}
return unless defined($sock);
+ set_event_handler ($sock, read => undef, write => undef, error => undef);
shutdown($sock, 3);
close($sock);
}
1; # Success
}
+sub dup_sock
+{
+ my $conn = shift;
+ my $oldsock = $conn->{sock};
+ my $rc = $rd_callbacks{$oldsock};
+ my $wc = $wt_callbacks{$oldsock};
+ my $ec = $er_callbacks{$oldsock};
+ my $sock = $oldsock->new_from_fd($oldsock, "w+");
+ if ($sock) {
+ set_event_handler($oldsock, read=>undef, write=>undef, error=>undef);
+ $conn->{sock} = $sock;
+ set_event_handler($sock, read=>$rc, write=>$wc, error=>$ec);
+ $oldsock->close;
+ }
+}
+
sub _err_will_block {
- return ($_[0] == EAGAIN || $_[0] == EWOULDBLOCK || $_[0] == EINPROGRESS);
+ return 0 unless $blocking_supported;
+ return ($_[0] == $eagain || $_[0] == $ewouldblock || $_[0] == $einprogress);
}
sub close_on_empty