in reply to Re: Perl an array of sockets
in thread Perl an array of sockets

Perhaps people can help me with this code... it's much simpler than previous but I am unable to get ip, port and won't send message or close socket... seems like does nothing... maybe I am not saving socket correctly or not referencing correctly.

use EV; use Asterisk::AMI; use Data::Dumper; use Net::WebSocket::EV; use HTTP::Server::EV; use Digest::SHA1 qw(sha1_base64); use threads; use threads::shared; use strict; $|++; my ($rsv,$opcode,$msg, $status_code); our @users : shared; my @users =(); my $cgi ; my $astman = Asterisk::AMI->new(PeerAddr => '127.0.0.1', PeerPort => '5038', Username => 'admin', Secret => 'emel1t0', Events => 'on', Handlers => { default => \&eventhandler } ); die "Unable to connect to asterisk" unless ($astman); sub eventhandler { my ($ami, $event) = @_; if($event->{'Event'} eq "Dial"){ if($event->{'SubEvent'} eq "Begin"){ &buscar_exten($event->{'ConnectedLineName'}); } if($event->{'SubEvent'} eq "End"){ &buscar_exten($event->{'ConnectedLineName'}); } } } HTTP::Server::EV->new->listen(50080, sub { $cgi = $_[0]; $cgi->header({ STATUS => '101 Switching Protocols', Upgrade => "websocket", Connection => "Upgrade", "Sec-WebSocket-Accept" => scalar sha1_base64( $cgi->{headers}{"Sec-WebSocket-Key"} . "2 +58EAFA5-E914-47DA-95CA-C5AB0DC85B11" ).'=', }); $cgi->{self} = $cgi; $cgi->{buffer}->flush_wait(sub { $cgi->{websocket} = Net::WebSocket::EV::Server->new({ fh => $cgi->{buffer}->give_up_handle, on_msg_recv => sub { ($rsv,$opcode,$msg,$status_code) = @_; my @dlogin=split(":",$msg); if(@dlogin[1] eq ""){ print "no autenticado\n"; } else{ push (@users, $cgi->{websocket}) +; } }, on_close => sub { my($code) = @_; $cgi->{self} = undef; $cgi = undef; }, buffering => 1, }); }); }, { threading => 0 }); sub buscar_exten{ my $exten=@_[0]; my $href; my $role; my $some; print "buscando si <$exten> esta logueada-\n"; foreach my $fn (@users) { open my $fh, ">&=$fn" ;# or warn $! and die; send($fh,"evento llamada $exten\n",0) ; print "}\n"; } } EV::loop;

Replies are listed 'Best First'.
Re^3: Perl an array of sockets
by holli (Abbot) on Nov 21, 2017 at 12:21 UTC
    I'm quite unclear what you mean by
    unable to get ip, port and won't send message or close socket.
    What is the output when you run this? Is there an Asterisk server listening at the port/ip you provided?


    holli

    You can lead your users to water, but alas, you cannot drown them.

      It runs , When I open my webpage, websocket it's open... when I make a call, events are catched by eventhandler and call the subprocess "buscar_exten" but... no message is send to the clients "send($c,"mandando mensaje 1000\r\n",0)" connected to the websocket service, what I mean is the perl code at the top is similar but at least I can get the ip and port calling "peerhost()" and "peerport()" and when I open the socket in the "buscar_exten" at least close the socket, but the second code does nothing.

      I need when an event is received by eventhandler subprocess, send a message to the connected clients thru the websocket. The first perl code I use IO:Socket but harder to create websocket, second it's easier but still no luck.

      I need to create an array/hash of sockets and then when an event occurs in asterisk being able to send it thru sockets.

        suhijo:

        I've not used EV, and don't think I've used WebSockets in perl (other than a trivial demo). I looked over your code a bit anyway, and while comparing it with the documentation, it seems to me that one problem you may be having is the bit where you're trying to send the message to all your websockets.

        Since @users already contains your array of websockets, I think you need to change:

        sub buscar_exten{ my $exten=@_[0]; my $href; my $role; my $some; print "buscando si <$exten> esta logueada-\n"; foreach my $fn (@users) { open my $fh, ">&=$fn" ;# or warn $! and die; send($fh,"evento llamada $exten\n",0) ; print "}\n"; } }

        Into something more like:

        sub buscar_exten{ my $exten=@_[0]; print "buscando si <$exten> esta logueada-\n"; my $cnt=0; for my $websock (@users) { print "Sending message to socket in slot $cnt\n"; ++$cnt; $websock->queue_msg("evento llamada $exten\n"); } }

        You'll also want to remove the websocket from your @users list when the websocket closes. Perhaps something like:

        on_close => sub { my($code) = @_; # remove websocket from active list @users = grep { $_ ne $cgi } @users; $cgi->{self} = undef; $cgi = undef; },

        (In fact, the whole $cgi->{self} bit seems to exist simply to hold the websocket open, which ought to be handled just fine by @users, so you may be able to remove the $cgi->{self} creation and clearing bits.

        Take my notes with a rather large grain of salt: I've only used WebSockets a little (in C++), but it seems odd to me that you're doing an authentication check inside the websocket's message received hook, rather than checking the authentication before bothering to create the WebSocket.

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.