Skip to content

Instantly share code, notes, and snippets.

@dex4er
Created March 29, 2015 09:38
Show Gist options
  • Select an option

  • Save dex4er/175471dd187a230b6077 to your computer and use it in GitHub Desktop.

Select an option

Save dex4er/175471dd187a230b6077 to your computer and use it in GitHub Desktop.
Mojo and UDP packages
#!/usr/bin/env perl
package My::Mojo::IOLoop;
use Mojo::Base 'Mojo::IOLoop';
use Scalar::Util 'weaken';
sub client {
my ($self, $cb) = (_instance(shift), pop);
my $id = $self->_id;
my $client = $self->{connections}{$id}{client} = My::Mojo::IOLoop::Client->new;
weaken $client->reactor($self->reactor)->{reactor};
weaken $self;
$client->on(
connect => sub {
delete $self->{connections}{$id}{client};
my $stream = Mojo::IOLoop::Stream->new(pop);
$self->_stream($stream => $id);
$self->$cb(undef, $stream);
}
);
$client->on(error => sub { $self->_remove($id); $self->$cb(pop, undef) });
$client->connect(@_);
return $id;
}
sub _instance { ref $_[0] ? $_[0] : $_[0]->singleton }
package My::Mojo::IOLoop::Client;
use Mojo::Base 'Mojo::IOLoop::Client';
use Errno 'EINPROGRESS';
sub _connect {
my ($self, $args) = @_;
my $handle;
my $address = $args->{socks_address} || $args->{address};
unless ($handle = $self->{handle} = $args->{handle}) {
my %options = (PeerAddr => $address, PeerPort => $args->{socks_port} || $args->{port}, Proto => 'udp');
%options = (PeerAddrInfo => $args->{addr_info}) if $args->{addr_info};
$options{Blocking} = 0;
$options{LocalAddr} = $args->{local_address} if $args->{local_address};
return $self->emit(error => "Can't connect: $@")
unless $self->{handle} = $handle = IO::Socket::IP->new(%options);
}
$handle->blocking(0);
# Wait for handle to become writable
weaken $self;
$self->reactor->io($handle => sub { $self->_ready($args) })
->watch($handle, 0, 1);
}
sub _ready {
my ($self, $args) = @_;
# Retry or handle exceptions
my $handle = $self->{handle};
return $! == EINPROGRESS ? undef : $self->emit(error => $!)
if $handle->isa('IO::Socket::IP') && !$handle->connect;
return $self->emit(error => $! || 'Not connected') unless $handle->connected;
return $self->_cleanup->emit(connect => $handle);
}
package main;
use Net::DNS::Packet;
my $address = $ARGV[0] || 'mojolicio.us';
My::Mojo::IOLoop->client({address => '8.8.8.8', port => 53} => sub {
my ($loop, $err, $stream) = @_;
$stream->on('read' => sub {
my ($stream, $bytes) = @_;
my $ans = Net::DNS::Packet->new(\$bytes, 1);
$stream->close;
});
my $packet = Net::DNS::Packet->new($address);
$stream->write($packet->data);
});
Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment