#!/usr/bin/perl ########################################## # #

by phil on Wednesday Jul 30, 2003 12:29 AM

#!/usr/bin/perl

##########################################
#
# Flash sometimes has problems communicating
# to traditional TCP/IP XML servers. This is
# is because each packet that the Flash clients
# print to servers are ended by a "\0" while as
# server's traditionally recognize "\n" as the
# end. Example, in Perl, if you go $line =
# $line will usually contain one line of the file
# where a line is whatever's delimited by \n's.
# Also, when reading data back, Flash only
# recognizes data if it's delimited by "\0"'s as
# well. Lame, I know.
#
# This program relays communication back
# and forth between flash clients and standard
# servers. There is an XML parsing issue that
# also has to be taken into account as each
# XML packet that comes from the server needs
# to be delimited with \0's. I've attempted
# to take care of this as you'll see below..
# it hasn't been rigorously tested though
# so use at your own risk...
#
# I'm not the greatest programmer, and there
# may be blocking issues... so, please improve.
#
# I got most of this junk from Advanced Perl
# Programming by O'Reilly.
#
# - Philip Dhingra (philipd@stanford.edu)
# http://www.philosophistry.com/
#
# Keywords: XMLSocket
###########################################

use IO::Socket;
use IO::Select;

$remote_rs = "\n";
$flash_rs = "\0";

# XML tags that I want to be sent to Flash
@root_headers = ('Q','O','M');

# $/ denotes the input record separator (default: '\n')
# $\ denotes the output record separater (default: null)
# Flash separates records with a \0
# Standard TCP/IP servers use the default, \n

close STDOUT; # if you don't want to see what's going on

$remote_host = 'whatever.com';
$remote_port = '6969';

$local_port = '9696';


$flash_sock = new IO::Socket::INET (Listen => SOMAXCONN,
Proto => 'tcp',
Reuse => 1,
LocalPort => $local_port)
or die ("**STATUS: Flash Listening Server could not start");

sub open_remote_sock {

return new IO::Socket::INET (Proto => 'tcp',
PeerAddr => $remote_host,
PeerPort => $remote_port)
or die ("**STATUS: Cannot Connect to Remote Server (" . $remote_host . ":" . $remote_port);

}

print "**STATUS: Flash Listening Server started\n" if ($flash_sock);

$read_set = new IO::Select;
$read_set->add($flash_sock);

while(1) {
($new_readable) = IO::Select->select($read_set, undef, undef, undef);

foreach $readable (@$new_readable) {
if ($readable == $flash_sock) {
$flash_client = $flash_sock->accept();

$read_set->add($flash_client);

print "**STATUS: Flash connection from: " . $flash_client->peerhost . "\n";

$read_set->add($remote_sock = &open_remote_sock);
print "**STATUS: Connected to Remote Server\n" if ($remote_sock);

} elsif ($readable == $remote_sock) {
$/ = $remote_rs;
$from_remote = <$remote_sock>;
chomp $from_remote;


if ($from_remote eq '') {
print "**STATUS: Remote Server connection lost**";
$remote_sock->close;
exit;
} else {
print "(-): " . $from_remote . "\n";

# BEGIN XML parsing..

if ($waiting_for) {
$queue .= $from_remote;
} else {
$queue = $from_remote;
}

$waiting_for = hasRootHeaders($from_remote) unless ($waiting_for);

if ($waiting_for) {
if ($queue =~ s/(<$waiting_for>.*?<\/$waiting_for>)//s) {

print $flash_client $1 . $flash_rs;
$flash_client->flush();

$waiting_for = hasRootHeaders($queue);
}
}

# END XML parsing

}

# Flash client is trying to speak...
} elsif ($readable == $flash_client) {
$/ = $flash_rs;
$from_flash = <$readable>;
chomp($from_flash);

if ($from_flash eq '') {
print "**STATUS: Connection to Flash Client (" . $flash_client->peerhost . ") lost\n";
$read_set->remove($readable);
$readable->close;

# closing remote socket
$read_set->remove($remote_sock);
$remote_sock->close;
} else {

print "(+): " . $from_flash . "\n";
print $remote_sock $from_flash . $remote_rs;
$remote_sock->flush();

}

# Dead client is trying to speak
} else {
print "**STATUS: Connection to Flash Client (" . $readable->peerhost . ") lost\n";
$read_set->remove($readable);
$readable->close;

# closing remote socket
$read_set->remove($remote_sock);
$remote_sock->close;
}
}
}


sub hasRootHeaders {
my $snippet = shift;
my @matches;

foreach $key (@root_headers) {
if ($snippet =~ m##) {
$tail_key = $key;
}
}

foreach $key (@root_headers) {
if ($snippet =~ m#<$key>#) {
push @matches, $key;
}
}
foreach $match (@matches) {
return $match if ($match eq $tail_key);
}

return pop(@matches) if (@matches);

return '';
}

sub drainReadBuffer {
my $sock = shift;
my $bytes_to_read = 1024;
my $msg;

}


Keywords: flash, record separator, null terminator, xmlsocket, xml server, relay

Comments

majid khossravi said on February 22, 2004 6:49 AM:

how swf file within a html can communicate this server , i mean XMLSocket connection doesnt work if i wont execute perl file befor


Creative Commons License