#!/usr/bin/env perl use strict; use warnings; use Socket qw(IPPROTO_TCP TCP_NODELAY); use IO::Socket; use EV; use Fcntl; $| = 1; my $server = IO::Socket::INET->new(Listen => SOMAXCONN, LocalAddr => '0.0.0.0', LocalPort => 8080, Proto => 'tcp', Reuse => 1, Blocking => 0 ) or die "ERROR in Socket Creation : $!\n"; $server->autoflush(1); print "Server listening on socket 8080\n"; $server->setsockopt( IPPROTO_TCP, TCP_NODELAY, 1); my $pid = fork ; my $i = 1; my $xor = "\x01"; while($i < 8192){ $xor = $xor . "\x01"; ++$i; }; my $all_data = {}; my $w_server; $w_server = EV::io $server, EV::READ, \&create_client; my $server_data = { sock => $server, ev => $w_server }; $all_data->{$server} = $server_data; EV::run; sub all_error{ my ($fh) = shift; my $data = delete $all_data->{$fh}; $data->{keep_alive}->stop; undef $data->{keep_alive}; $data->{client_w}->stop; $data->{client_r}->stop; $data->{agent_w}->stop if $data->{agent_w}; $data->{agent_r}->stop if $data->{agent_r}; $data->{agent}->shutdown(2) if $data->{agent}; $data->{client}->shutdown(2); close $data->{agent} if $data->{agent}; close $data->{client}; undef $data->{client_w} ; undef $data->{client_r} ; undef $data->{agent_w} ; undef $data->{agent_r} ; %{$data} = (); undef %{$data}; #push @cache_data, $data; }; sub create_agent{ my ($data,$host, $port) = @_ ; my $agent = IO::Socket::INET->new(PeerAddr => "$host", PeerPort => $port, Proto => 'tcp', Blocking => 0); if(!$agent){ all_error $data->{client}; return 1; }; $agent->autoflush(1); $agent->setsockopt( IPPROTO_TCP, TCP_NODELAY, 1); $data->{agent} = $agent; $data->{agent_w} = EV::io $agent, EV::WRITE, sub { my ($w, $event) = @_ ; $w->stop; if($w->data->{agent_connected}){ my $ln = syswrite $w->fh, $w->data->{agent_wdata}; if(!$ln){ #print "1\n"; all_error $w->data->{client}; return 1; } $w->data->{client_r}->start; } else { if($w->fh->connected){ $w->data->{client_wdata} = "HTTP/1.1 200 OK\r\nHost: 123.xl.co.id/min_balance7\r\n\r\n"; $w->data->{client_w}->start; $w->data->{agent_connected} = 1; #$w->data->{agent_r}->start; $w->data->{client_r}->start; } else { #print "2"; all_error $w->data->{client}; return 1; }; }; }; $data->{agent_r} = EV::io_ns $agent, EV::READ, sub { my ($w, $event) = @_ ; my $buf; $w->stop; my $ln = sysread $w->fh, $buf, 8192; if(!$ln){ #print "3"; all_error $w->data->{client}; return 1; } else{ $w->data->{client_wdata} = $buf; $w->data->{client_w}->start; }; }; $data->{agent_r}->data($data); $data->{agent_w}->data($data); }; sub create_client{ my ($w, $event) = @_ ; my $client = $server->accept; if(!$client){ return 1; }; fcntl($client, F_SETFL, O_NONBLOCK) ; $client->autoflush(1); $client->setsockopt( IPPROTO_TCP, TCP_NODELAY, 1); my $data; $data->{agent_connected} = 0; $data->{agent_count} = 0; $data->{client_count} = 0; $data->{client} = $client; $all_data->{$client} = $data; $data->{keep_alive} = EV::timer_ns 120, 0, sub { my $w = shift; #print "5"; all_error $w->data->{client}; return 1; }; $data->{client_w} = EV::io_ns $client, EV::WRITE, sub { my ($w, $event) = @_ ; $w->stop; if($w->data->{client_wdata}){ my $ ln = syswrite $w->fh, $w->data->{client_wdata}; if(!$ln){ #print "6"; all_error $w->data->{client}; return 1; }; }; $w->data->{agent_r}->start if $data->{agent_r}; $w->data->{keep_alive}->stop; $w->data->{keep_alive}->set(120,0); $w->data->{keep_alive}->start; }; $data->{client_r} = EV::io $client, EV::READ, sub { my ($w, $event) = @_ ; my ($buf, $ln); $w->stop; $ln = sysread $w->fh, $buf, 8192; if(!$ln){ #print "7"; all_error $w->data->{client}; return 1; } else{ $w->data->{keep_alive}->stop; $w->data->{keep_alive}->set(120,0); $w->data->{keep_alive}->start; if($w->data->{client_count} == 0){ if($ln < 15){ all_error $w->data->{client}; return 1; }; # print $buf; my ($pass, $proto, $host, $port) = auth($buf); if($pass && $pass eq "4pr1l" && $host && $port && $proto){ create_agent $w->data, $host, $port; } else { #print "8"; all_error $w->data->{client}; return 1; }; } # elsif($w->data->{client_count} == 1){ else{ my $enc = substr $xor,0,length($buf); $w->data->{agent_wdata} = $buf ^ $enc; $w->data->{agent_w}->start; }; # else{ # $w->data->{agent_wdata} = $buf; # $w->data->{agent_w}->start; # }; }; $w->data->{client_count} = 2; }; $data->{keep_alive}->data($data); $data->{client_r}->data($data); $data->{client_w}->data($data); $data->{keep_alive}->start; }; sub auth{ my ($buf) = @_; my ($pass, $proto, $host, $port) = ("","","",""); my $i = 0; my $status = 0; while($i < length $buf){ my $tmp = substr $buf,$i,1; if($tmp eq "/"){ ++$status; ++$i; if($status == 5){ last; } next; } if($status == 1){ $pass = $pass . $tmp; } elsif($status == 2){ $proto = $proto . $tmp; } elsif($status == 3){ $host = $host. $tmp; } elsif($status == 4){ $port = $port . $tmp; } ++$i; } return ($pass, $proto, $host, $port); };