Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the XML-Stream CPAN distribution.

Report information
The Basics
Id: 75660
Status: new
Priority: 0/
Queue: XML-Stream

People
Owner: Nobody in particular
Requestors: whynot [...] pozharski.name
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 1.23_06
Fixed in: (no value)



Subject: UNIX sockets, plz
$Subject. I can't say if encryption works. I don't need it, and writing SSL enabled XMPP server for just one test unit is out of my time resources. As a side note, your server code, in XML::Stream, is FUBAR.
Subject: unix-sockets.diff
diff -urN backup-1.23_06/lib/XML/Stream.pm unix-sockets/lib/XML/Stream.pm --- backup-1.23_06/lib/XML/Stream.pm 2011-07-19 19:49:32.000000000 +0300 +++ unix-sockets/lib/XML/Stream.pm 2012-03-04 22:50:48.000000000 +0200 @@ -216,6 +216,7 @@ #--------------------------------------------------------------------------- $self->{SIDS}->{default}->{hostname} = ""; $self->{SIDS}->{default}->{port} = ""; + $self->{SIDS}->{default}->{socket} = ""; $self->{SIDS}->{default}->{sock} = 0; $self->{SIDS}->{default}->{ssl} = 0; $self->{SIDS}->{default}->{_tls} = 0; @@ -489,6 +490,7 @@ Connect(hostname=>string, port=>integer, + socket=>string, to=>string, from=>string, myhostname=>string, @@ -503,7 +505,10 @@ Opens a tcp connection to the specified server and sends the proper opening XML Stream tag. C<hostname>, -C<port>, and C<namespace> are required. +and C<namespace> are required. +C<port> is required for any C<connectiontype> except C<socket> and +C<stdinout>. +C<socket> is required for C<connectiontype> C<socket>. namespaces allows you to use XML::Stream::Namespace objects. @@ -524,11 +529,12 @@ this to the correct value, or if you want the other side of the stream to think that you are someone else. The -type determines the kind of +C<connectiontype> determines the kind of connection that is made: "tcpip" - TCP/IP (default) "stdinout" - STDIN/STDOUT + "socket" - UNIX socket "http" - HTTP HTTP recognizes proxies if the ENV @@ -538,6 +544,7 @@ C<ssl> specifies whether an SSL socket should be used for encrypted co- mmunications. +It's unknown for now if encryption works with C<connectiontype> C<socket>. C<ssl_verify> determines whether peer certificate verification takes place. @@ -706,6 +713,38 @@ } #--------------------------------------------------------------------------- + # UNIX Sockets + #--------------------------------------------------------------------------- + if ($self->{SIDS}->{newconnection}->{connectiontype} eq "socket") + { + #----------------------------------------------------------------------- + # We still need hostnames for handshake. + #----------------------------------------------------------------------- + if ($self->{SIDS}->{newconnection}->{hostname} eq "") + { + $self->SetErrorCode("newconnection","Server hostname not specified"); + return; + } + if ($self->{SIDS}->{newconnection}->{socket} eq "") + { + $self->SetErrorCode("newconnection","Socket filename not specified"); + return; + } + if ($self->{SIDS}->{newconnection}->{myhostname} eq "") + { + $self->{SIDS}->{newconnection}->{myhostname} = $self->{SIDS}->{newconnection}->{derivedhostname}; + } + + $self->{SIDS}->{newconnection}->{sock} = + IO::Socket::UNIX->new(Peer=>$self->{SIDS}->{newconnection}->{socket}, + Type=>SOCK_STREAM, + (($timeout ne "") ? ( Timeout=>$timeout ) : ()), + ); + return unless $self->{SIDS}->{newconnection}->{sock}; + + } + + #--------------------------------------------------------------------------- # STDIN/OUT #--------------------------------------------------------------------------- if ($self->{SIDS}->{newconnection}->{connectiontype} eq "stdinout") @@ -979,6 +1018,7 @@ my %stream_args; if (($self->{SIDS}->{$currsid}->{connectiontype} eq "tcpip") || + ($self->{SIDS}->{$currsid}->{connectiontype} eq "socket") || ($self->{SIDS}->{$currsid}->{connectiontype} eq "http")) { $stream_args{to}= $self->{SIDS}->{$currsid}->{hostname} @@ -1031,6 +1071,7 @@ IO::Select->new($self->{SIDS}->{$currsid}->{sock}); if (($self->{SIDS}->{$currsid}->{connectiontype} eq "tcpip") || + ($self->{SIDS}->{$currsid}->{connectiontype} eq "socket") || ($self->{SIDS}->{$currsid}->{connectiontype} eq "http")) { $self->{SELECT} = IO::Select->new($self->{SIDS}->{$currsid}->{sock}); @@ -1099,6 +1140,7 @@ $self->{SIDS}->{$sid}->{parser}->setSID($sid); if (($self->{SIDS}->{$sid}->{connectiontype} eq "tcpip") || + ($self->{SIDS}->{$sid}->{connectiontype} eq "socket") || ($self->{SIDS}->{$sid}->{connectiontype} eq "http")) { $self->{SOCKETS}->{$self->{SIDS}->{$currsid}->{sock}} = $sid; @@ -1263,6 +1305,7 @@ $self->Send($sid,"</stream:stream>"); close($self->{SIDS}->{$sid}->{sock}) if (($self->{SIDS}->{$sid}->{connectiontype} eq "tcpip") || + ($self->{SIDS}->{$sid}->{connectiontype} eq "socket") || ($self->{SIDS}->{$sid}->{connectiontype} eq "http")); delete($self->{SOCKETS}->{$self->{SIDS}->{$sid}->{sock}}); foreach my $key (keys(%{$self->{SIDS}->{$sid}})) @@ -1622,6 +1665,7 @@ $status = $self->{SIDS}->{$sid}->{sock}->sysread($buff,4*POSIX::BUFSIZ) if (($self->{SIDS}->{$sid}->{connectiontype} eq "tcpip") || + ($self->{SIDS}->{$sid}->{connectiontype} eq "socket") || ($self->{SIDS}->{$sid}->{connectiontype} eq "http") || ($self->{SIDS}->{$sid}->{connectiontype} eq "file")); $status = sysread(STDIN,$buff,1024) @@ -1698,6 +1742,7 @@ while ($self->{SENDLENGTH}) { $self->{SENDWRITTEN} = $self->{SIDS}->{$sid}->{sock}->syswrite($self->{SENDSTRING},$self->{SENDLENGTH},$self->{SENDOFFSET}); + $self->{SIDS}->{$sid}->{sock}->sync(); if (!defined($self->{SENDWRITTEN})) { diff -urN backup-1.23_06/t/unixsocket.t unix-sockets/t/unixsocket.t --- backup-1.23_06/t/unixsocket.t 1970-01-01 03:00:00.000000000 +0300 +++ unix-sockets/t/unixsocket.t 2012-03-01 21:59:02.000000000 +0200 @@ -0,0 +1,110 @@ +use strict; +use warnings; + +package main; + +use Test::More tests => 9; +use File::Temp qw{ tempfile }; +use IO::Socket; +use POSIX qw{ :sys_wait_h }; + +BEGIN{ use_ok("XML::Stream","Node"); } + +my $sfn = ( tempfile 'socket_XXXX', DIR => 't' )[-1]; +unlink $sfn; + +END { unlink $sfn } + +my $pid = fork(); +defined $pid or die "fork: $!"; +unless( $pid ) +{ + my $socket = IO::Socket::UNIX->new( Local=>$sfn, Listen=>5, Type => + SOCK_STREAM, Timeout => 600 ) or die "# new socket: $!"; + my $conn = $socket->accept; + $conn->autoflush( 1 ); + $conn->flush; + #my $buf = [ $conn->getlines ]; + my $buf; + $conn->sysread( $buf, 4096 ) or die "1\n"; + $buf =~ m{^\s*<\?xml\s+version}s or die "# 2\n"; + $buf = <<'END_OF_REPLY'; +<?xml version='1.0'?> +<stream:stream version='1.0' + xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' + to='client@example.org' from='example.org' xml:lang='en' + id='0123456789abcdef'> +END_OF_REPLY + $conn->syswrite( $buf, 4096 ) or die "# 4\n"; + sleep 2; + $buf = <<'END_OF_REPLY'; +<stream:features/> +END_OF_REPLY + $conn->syswrite( $buf, 4096 ) or die "# 5\n"; + $conn->sysread( $buf, 4096 ) or die "# 6\n"; + $buf =~ m{<iq\s+} or die "# 7\n"; + $buf = <<'END_OF_REPLY'; +<iq type='result' id='0123'/> +END_OF_REPLY + $conn->syswrite( $buf, 4096 ) or die "# 8\n"; + $conn->sysread( $buf, 4096 ) or die "# 9\n"; + $buf =~ m{</stream:stream>} or die "# 10\n"; + sleep 3; + $buf = <<'END_OF_REPLY'; +</stream:stream> +END_OF_REPLY +# client disconnects without proper closing in-stream, thus socket is already closed + $conn->syswrite( $buf, 4096 ) and die "# 11\n"; + sleep 4; + exit 0; +} + +my $stream = XML::Stream->new(style=>"node"); +ok( defined($stream), "new()" ); +isa_ok( $stream, "XML::Stream" ); + +my %nodes; +$stream->SetCallBacks( node => sub { push @{$nodes{shift @_}}, shift @_ }); + +sleep 2; +my $client = $stream->Connect( socket => $sfn, hostname => 'example.org', + from => 'client@example.org', to => 'example@org', + connectiontype => 'socket', namespace => 'jabber:client', timeout => 60 ); +sleep 2; +if( waitpid $pid, WNOHANG ) +{ + fail 'server died'; + exit; +} +is_deeply $client, { version => '1.0', + 'xmlns:stream' => 'http://etherx.jabber.org/streams', xmlns => 'jabber:client', + to => 'client@example.org', from => 'example.org', 'xml:lang' => 'en', + id => '0123456789abcdef', }, 'connection'; + +$stream->Send( '0123456789abcdef', '<iq type="set" id="0123"><quit/></iq>' ); +sleep 2; +if( waitpid $pid, WNOHANG ) +{ + fail 'server died'; + exit; +} +my $status = { $stream->Process( 60 ) }; +is_deeply $status, { '0123456789abcdef' => 1 }, 'ping'; +is_deeply { + tag => $nodes{'0123456789abcdef'}[0]->get_tag, + id => $nodes{'0123456789abcdef'}[0]->get_attrib( 'id' ), + type => $nodes{'0123456789abcdef'}[0]->get_attrib( 'type' ) }, { + tag => 'iq', id => '0123', type => 'result' }, 'pong'; + +$status = $stream->Disconnect( '0123456789abcdef' ); +sleep 2; +if( waitpid $pid, WNOHANG ) +{ + fail 'server died'; + exit; +} +is_deeply $status, { }, 'disconnection'; + +is waitpid( $pid, 0 ), $pid, 'server exited'; +is $?, 0, 'ok exit'; +