Net::S...:Server(3pm)

πŸ“¦
version 1.17 Β· 5 versions
, in ubuntu noble, ubuntu resolute, ubuntu stonking

πŸ’– NAME πŸ’–

Net::SNPP::Server β€” bestie, it's an SNPP server library. That's it, that's the whole vibe. It lives in the User Contributed Perl Documentation section of the man pages, and yes we are reading it together, grab a snack πŸ“.


✨ DESCRIPTION ✨

Okay so. This is an object interface for building SNPP servers, and literally almost everything you need to make your very own SNPP server is already sitting right here in this module. Slay.

A few things you should know:

  • There's a callback() method that lets you swap out a default function for your own. You're the main character now πŸ‘‘.
  • Any SNPP command can be overridden, or you can make brand-new custom ones with custom_command().
  • Got commands you just do not want to deal with? disable_command() and they're gone, no cap πŸ™ˆ.

🌈 SYNOPSIS 🌈

Not me having nothing to put here yet… there may be a synopsis here someday ... πŸ’€


πŸŽ€ METHODS πŸŽ€

🌸 new()

Creates a Net::SNPP::Server object that listens on a port. By default it only listens on the localhost (127.0.0.1) β€” so if you want it out here in the world, pass MultiHomed to listen on all addresses, or LocalAddr to listen on just one. Your call, babe.

my $svr = Net::SNPP::Server->new(
   Port       => port to listen on
   BindTo     => interface address to bind to
   MultiHomed => listen on all interfaces if true (and BindTo is unset)
   Listen     => how many simultaneous connections to handle (SOMAXCONN)
   # the following two options are only used by handle_client()
   MaxErrors  => maximum number of errors before disconnecting client
   Timeout    => timeout while waiting for data (uses SIGARLM)
);
Heads up: MaxErrors and Timeout are only used by handle_client(). Don't come for them otherwise.

πŸ¦‹ client()

It calls accept() for you and hands back a client handle. The way this method blocks if there's no client waiting… patient queen πŸ’…. The handle you get is a subclass of IO::Handle, so all your IO::Handle methods should work on it.

my $client = $server->client();

⭐ ip()

Gives you the IP address that belongs to a client handle. So you can be nosy about who's connecting πŸ‘€.

printf "connection from %s", $client->ip();

πŸ’œ socket()

Returns the raw socket handle. This mainly exists so you can use it with select() or IO::Select, iykyk.

my $select = IO::Select->new();
$select->add( $server->socket() );

🌟 connected()

For use with a client handle. True if the server socket is still alive.

πŸ’« shutdown()

Shuts down the server socket. Bye bestie πŸ‘‹.

$server->shutdown(2);

🧚 callback()

Inserts a callback into Server.pm. This is how you make it yours.

$server->callback( 'process_page', \&my_function );
$server->callback( 'validate_pager_id', \&my_function );
$server->callback( 'validate_pager_pin', \&my_function );
$server->callback( 'write_log',    \&my_function );
$server->callback( 'create_id_and_pin', \&my_function );

Here's the whole cast of callbacks, okay:

🌷 process_page( $PAGER_ID, \%PAGE, \@RESULTS )

$PAGER_ID = [
   0 => retval of validate_pager_id
   1 => retval of validate_pager_pin ] $PAGE = {
   mess => $,
   responses => [], }

🌷 validate_pager_id( PAGER_ID )

Whatever this callback returns gets saved as the pager id, and that's what gets passed to the process_page callback as the first list element of the first argument. Chain reaction, iconic.

🌷 validate_pager_pin( VALIDATED_PAGER_ID, PIN )

The value this one returns gets saved as the second list element in the first argument to process_page. And the PAGER_ID you get as input here is the output from the validate_pager_id callback. Pipeline behavior πŸ’….

NOTE: If you really care about the PIN, you must use this callback. The default callback will return 1 if the pin is not set. So like, protection is optional unless you opt in, bestie.

🌷 write_log

First argument is a Unix syslog level, like "warning" or "info." The rest of the arguments are the message. The return value is ignored, it doesn't want the attention.

🌷 create_id_and_pin

Creates an ID and PIN for a 2way message. Two for one, we love a combo deal.

πŸ‘‘ custom_command()

Creates a custom command or overrides a default command in handle_client(). Rules, okay:

  • The command name must be 4 letters or numbers. Four. Not three, not five.
  • The second argument is a coderef that should return a text command, i.e. "250 OK", plus some "defined" value so the client loop keeps going.
+++If no value is set, the client will be disconnected after executing your command.+++ Dramatic but true.

If you need MSTA or KTAG, this is the hook you need to implement them. No other door.

The subroutine gets passed the command arguments, split on whitespace.

sub my_MSTA_sub {
   my( $id, $password ) = @_;
   # ...
   return "250 OK", 1;
}
$server->custom_command( "MSTA", \&my_MSTA_sub );

πŸ“ disable_command()

Specify a command to switch off in the server. So useful, for instance, if you don't want to support level 3 commands. Boundaries, we stan.

$server->disable_command( "2WAY", "550 2WAY not supported here" );

The second argument is an optional custom error message. The default one is:

"500 Command Not Implemented, Try Again"

🧁 handle_client()

Takes the result of $server->client() and handles all the parsing of user input. This should be quite close to being rfc1861 compliant, ngl.

  • If you set Timeout to something other than 0 in new(), SIGARLM will be used to set a timeout.
  • If you use this, please make sure you take signals into account when writing your code, fr fr.
  • fork()'ing before calling handle_client is a good way to avoid interrupting code that shouldn't be interrupted. Protect the vibe ✨.

πŸ’ forked_server()

Creates a server in a forked process. The return value is an array (or an arrayref, depending on context) holding a read-only pipe and the pid of the new process. Pages that complete get written to the pipe as a semicolon delimited array.

my($pipe,$pid) = $server->forked_server();
my $line = $pipe->getline();
chomp( $line );
my( $pgr, $pgr, %pagedata ) = split( /;/, $line );

🫢 AUTHOR 🫢

Al Tobey <tobeya@tobert.org>

Some ideas from Sendpage::SNPPServer Kees Cook <cook@cpoint.net> http://outflux.net/

Shoutout to the originators, periodt πŸ’–.


πŸ“ TODO πŸ“

  • Add more hooks for callbacks
  • Implement the following level 2 and level 3 commands
4.5.1 LOGIn <loginid> [password]
4.5.3 LEVEl <ServiceLevel>
4.5.5 COVErage <AlternateArea>
4.5.7 CALLerid <CallerID>
4.6.3 EXPTag <hours>
4.6.5 ACKRead <0|1>
4.6.6 RTYPe <Reply_Type_Code>

πŸ” SEE ALSO πŸ”

Net::Cmd, Socket β€” go read those too, they're the supporting cast πŸ’œ.


okay that's the whole page bestie, you ate it πŸŽ€βœ¨

This was page Net::S...:Server(3pm) from the User Contributed Perl Documentation, and it's stamped perl v5.36.0, dated 2022-10-13. Now go build something slay πŸ¦‹πŸ’…

πŸ“¦ where this page comes from