NAME

POE::Component::Lightspeed - The romping grounds of IKC2

SYNOPSIS

use POE;
use POE::Component::Lightspeed::Client;

# Create a new client session
POE::Component::Lightspeed::Client->spawn(
	'KERNEL'	=>	'testbox',
	'ADDRESS'	=>	'192.168.1.100',
);

# Create our own session to communicate with Lightspeed
POE::Session->create(
	inline_states => {
		_start		=> sub {
			$_[KERNEL]->alias_set( 'mysession' );

			# Yes, a better way to "monitor" Lightspeed is on the way...
			# For now, just give POE some time to connect
			$_[KERNEL]->delay_set( 'do_stuff', 5 );

			# Demonstration of Lightspeed hackery
			$_[KERNEL]->delay_set( 'confused', 1 );
		},
		'do_stuff'	=> sub {
			# Perfect
			$_[KERNEL]->post( 'poe://otherbox/mysession/ping', 'how are you?' );

			# Wrong
			#$_[KERNEL]->post( 'poe://otherbox/mysession', 'ping', 'how are you?' );
		},
		'pong'		=> sub {
			print "Received 'pong' from " . $_[SENDER]->ID . "\n";
		},
		'confused'	=> sub {
			# Is this a lightspeed session?
			if ( $_[SENDER]->is_lightspeed ) {
				# Yay!
				print "Received Lightspeed request from: '";
			} else {
				print "Received regular request from: '";
			}

			print $_[SENDER]->ID . "' State '" . $_[CALLER_STATE] . "' File '" . $_[CALLER_FILE] . "' Line '" . $_[CALLER_LINE] . "'\n";
	},
);

--------

use POE;
use POE::Component::Lightspeed::Server;

# Create a new server session
POE::Component::Lightspeed::Server->spawn(
	'KERNEL'	=>	'otherbox',
	'ADDRESS'	=>	'192.168.1.100',
);

# Create our own session to listen for requests from Lightspeed
POE::Session->create(
	inline_states => {
		_start		=> sub {
			$_[KERNEL]->alias_set( 'mysession' );
		},
		'ping'	=> sub {
			print "Received 'ping' from " . $_[SENDER]->ID . " -> " . $_[ARG0] . "\n";

			# Perfect
			$_[KERNEL]->post( $_[SENDER], 'pong', 'wassup!' );
			$_[KERNEL]->post( $_[SENDER]->ID, 'pong', 'wazzup!' );

			# Wrong
			#$_[KERNEL]->post( "$_[SENDER]", 'ping', 'wassup!' );

			# Demonstration of Lightspeed hackery
			$_[KERNEL]->post( 'poe://testbox/mysession/confused', 'huH!' );
		},
	},
);

ABSTRACT

This module aims to connect POE kernels into a network, a "botnet" of sorts.

Furthermore, the venerable IKC is now under design & development towards IKC2.
Think of this module as a playground for IKC2 ideas, so don't do any serious development around this unless I tell you it's ok!

CHANGES

0.05

- Added POE-0.3101 support
- Bumped versions of modules so the PAUSE indexer won't complain about it being a lower version

0.04

- Added SSL to server/client connections
- Added passwords to server/client connections
- Documentation tweaks, as usual
- Added the AUTHCLIENT parameter to Lightspeed::Server as a hook for accepting connections
- Added Lightspeed::Authentication to have authentication hooks on the local kernel

0.03

- A lot of internal cleanups and tweaks
- Added the Introspection module

0.02

- Documentation cleanups ( I am always a POD newbie )

0.01

- Initial release to public :)

DESCRIPTION

In the Lightspeed world, you have either a server or a client. Obviously, the clients connect to servers. In order for server kernels to connect to other kernels, you can run a client and a server session in the same process.

Please familiarize yourself with the concepts of IKC, especially it's "destination specifier" stuff.

The big difference between Lightspeed and IKC is that a lot of the bookkeeping stuff has been automated. You no longer have to publish sessions, nor register for remote sessions. Sending messages is a snap, using the normal $_[KERNEL]->post() interface everyone is accustomed to, instead of sending to a session to do the work.

Lightspeed goes a step beyond IKC, it does not create "proxy" sessions to relay data back to the remote kernel. Instead, it hacks into POE::Kernel, POE::Session, and POE::Resource::Events to get them to recognize the destination specifiers and act upon them.

DESTINATION SPECIFIER

The IKC destination specifier has been expanded a little, now you can send to multiple kernels/sessions at the same time.

'poe://kernel1,kernel2/session1,session2/state'

Furthermore, the special character '*' signifies "broadcast"

'poe://*/session1/state'	->	Every kernel in the network ( excludes the current kernel )
'poe://kernel1/*/state'		-> 	Every session in kernel1 with an alias
'poe://kernel1/session1/*'	->	Just posts to the state named '*', nothing special here
'poe://*/*/state'		->	A whole lot of fun!

Also, it's possible to pass the specifier as an arrayref or hashref

ARRAYREF:

[ kernel, session, state ]

HASHREF:

{
	'KERNEL'	=>	kernel,
	'SESSION'	=>	session,
	'STATE'		=>	state,
}

POST

To post to a remote kernel, there are a few formats allowed.

$kernel->post( 'poe://kernel/session/state', @args );	# The "Lightspeed" way to do it
$kernel->post( $_[SENDER], 'state', @args );		# Will work nicely too
$kernel->post( $_[SENDER]->ID, 'state', @args );	# Ditto
$kernel->post( [ qw( kernel session state ) ], @args );	# Alternate method of supplying the specifier
$kernel->post( $_[SENDER], $_[CALLER_STATE], @args )	# Yes, Lightspeed supplies this information too!

These ways will fail horrendously:

$kernel->post( $_[SENDER], @args );			# No, Lightspeed will not automatically send it back to the originating kernel/session/state!
$kernel->post( $_[SENDER]->ID, @args );			# Ditto.
$kernel->post( $_[SENDER]->ID . 'state', @args );	# This will fail if $_[SENDER] is not a remote kernel, but WILL WORK!

CALL

The concept of a call() cannot be really applied to remote kernels, so you have to supply a "RSVP" destination, the place where the resulting data from the call() should go.

To call a remote kernel, there are a few formats allowed.

$kernel->call( 'poe://kernel/session/state', 'poe://kernel/session/state', @args );	# The "Lightspeed" way to do it
$kernel->call( $_[SENDER], 'state', 'poe://kernel/session/state', @args );		# Will work nicely too
$kernel->call( $_[SENDER]->ID, 'state', 'poe://kernel/session/state', @args );		# Ditto
$kernel->call( $_[SENDER], 'state', [ qw( kernel session state ) ], @args );		# Alternate method of supplying the specifier
$kernel->call( $_[SENDER], $_[CALLER_STATE], 'poe://kernel/session/state', @args );	# Yes, Lightspeed supplies this information too!

These ways will fail horrendously:

$kernel->call( 'poe://kernel/session/state', @args );					# No RSVP specifier here!
$kernel->call( $_[SENDER], 'poe://kernel/session/state', @args );			# No remote state!
$kernel->call( $_[SENDER]->ID . 'state', 'poe://kernel/session/state', @args );		# This will fail if $_[SENDER] is not a remote kernel, but WILL WORK!

Lightspeed Extras

Being super-friendly as it is, Lightspeed gives the programmer a few extras to make their life easier!

The predefined event fields will give you the correct information:
	- SENDER
	- CALLER_STATE
	- CALLER_FILE
	- CALLER_LINE

A few methods has been added to POE::Session ( $_[SENDER] )
	- is_lightspeed
		It returns true if the calling session is on a remote kernel, false otherwise

	These methods are valid only if is_lightspeed() returns true:
		- remote_kernel
			Returns the name of the remote kernel

		- remote_session
			Returns the name of the remote session

		- remote_state
			Returns the name of the remote state

		- remote_file
			Returns the filename that initiated this request

		- remote_line
			Returns the line number that initiated this request

The $session->ID method returns the following string. This can be used freely as a session specifier, but you still
have to supply the state. So, it's very possible to do stuff like $_[SENDER]->ID . 'state' and get the right specifier
to supply.
	'poe://kernel/session/'

Lightspeed checks the POE Version and matches the appropriate hackery, so if you have an unsupported version
of POE, it won't work because I don't want to totally screw up POE by using the wrong data. If there's a reason you
absolutely must have support for POE version X, let me know and I can hack it up.

Postbacks/Callbacks work properly with $_[SENDER], even when it is a remote kernel :)

GOTCHAS

- If you're using a subclass of POE::Session that does not inherit from POE::Session, the lightspeed hackery won't work!

- The versions of the serializer on both the client/server MUST be the same, Storable is very picky about this!

- A client cannot connect to a server in the same process

- Every kernel name in the network must be unique, the default POE::Kernel->ID is useful for this

- This is not a spanning tree network, that means a cyclic network is allowed. This is the opposite of IRC networks.
	Spanning Tree:
		A - B - D
		    |
		    C

	Cyclic network:
		     /------\
		A - B - C - D
		 \------/

- Unlike IKC, there is no need to "publish" sessions

- You post events through the POE::Kernel instance, not to a special session
	$_[KERNEL]->post( 'poe://blah/blah/blah', @args );

- The characters '*', '/', and ',' is not allowed in kernel names and session aliases

- Keep in mind, when you are sending objects, that the appropriate modules are loaded in both the sender + receiver

KNOWN BUGS / TODO LIST

- Having 2 clients connecting at the same time causes the routing system to go snafu :(

- Argument parsing isn't as strict as it should be, and funky things will be allowed, like:
	$_[KERNEL]->post( 'poe://kernel1,kernel2,*/session1,session2,*/blah', @args );

- As of now, Lightspeed will silently drop messages destined towards unknown kernels/sessions

- Addition of a "monitor" system where you register for callbacks whenever specific things happen:
	- Client connect/disconnect
	- Messages leaving/arriving their destinations
	- General debugging junk

- Adding the local ip/port to bind to for clients

- Creating the ClientLite module, similar to the one found in IKC

- Would be nice for the Lightspeed router to "weigh" specific links and adjust priority to accomodate lag/load

- More documentation!

EXPORT

The only exportable stuff is in POE::Component::Lightspeed::Constants which isn't for general consumption.

SEE ALSO

POE

POE::Component::IKC

POE::TIKC

POE::Component::Lightspeed::Server

POE::Component::Lightspeed::Client

POE::Component::Lightspeed::Introspection

POE::Component::Lightspeed::Authentication

AUTHOR

Apocalypse <apocal@cpan.org>

COPYRIGHT AND LICENSE

Copyright 2005 by Apocalypse

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.