Limit the number of simultaneous connect attempts passed to libpurple.
[thrasher.git] / perl / lib / Net / REPL / Server.pm
blobec61fb7f0dd5b3ff5865ee247cccbffc8420c4a8
1 package Net::REPL::Server;
2 use strict;
3 use warnings;
5 =pod
7 =head1 NAME
9 Net::REPL::Server - Eval + Socket = interactive development
11 =head1 DESCRIPTION
13 Perl processes running Server objects accept and run code
14 interactively from remote clients. Perl code is received over a
15 socket, eval'd, and the Dumper'd result(s) are sent back.
17 This class can be used as-is or superclassed to plug into an event
18 loop or provide additional capabilities like Devel::REPL integration
19 or serializing results so that usuable Perl data structures can be
20 exchanged bidirectionally.
22 =head2 Methods
24 =cut
26 use base qw(Net::REPL::Base);
28 use Data::Dumper;
30 =head3 new(argument => value...)
32 Arguments:
34 =over
36 =item C<socket_class>
38 E.g. L<IO::Socket::UNIX> (the default) or L<IO::Socket::INET>.
40 =item C<socket_args>
42 Hashref of arguments for the socket class.
44 =item C<debug>
46 Debug level (refer to L<Net::REPL::Base>).
48 =back
50 =cut
52 sub new {
53 my $proto = shift;
54 my $class = ref($proto) || $proto;
55 my $self = {
56 'socket_class' => 'IO::Socket::UNIX',
57 'socket_args' => {},
58 @_,
60 bless($self, $class);
62 $self->debug('Server starting:', Dumper($self->{'socket_args'}));
64 my $server = $self->_create_socket(
65 'Proto' => 'SOCK_STREAM',
66 'Reuse' => 1,
67 'Listen' => 1,
68 %{$self->{'socket_args'}},
70 if (not $server) {
71 die("Couldn't start server: $!\n");
73 $self->{'server'} = $server;
74 $self->cb_listen();
76 $self->{'fh'} = undef;
78 return $self;
81 sub DESTROY {
82 my ($self) = @_;
84 if ($self->{'server'}) {
85 $self->{'server'}->close();
86 $self->{'server'} = undef;
88 $self->close_fh();
91 sub close_fh {
92 my ($self) = @_;
94 if ($self->{'fh'}) {
95 $self->{'fh'}->close();
96 $self->{'fh'} = undef;
97 $self->cb_disconnect();
101 =head3 interact()
103 Run one iteration of the REPL. Returns true if the socket remains open
104 for further iterations.
106 Blocks until a line of input can be read from the client socket and
107 the result flushed out to it.
109 =cut
111 sub interact {
112 my ($self) = @_;
114 if (not $self->{'fh'}) {
115 $self->{'fh'} = $self->{'server'}->accept();
116 if ($self->{'fh'}) {
117 $self->cb_connect();
119 else {
120 # Accept didn't.
121 $self->{'fh'} = undef;
122 return;
126 my $input = $self->lv_receive();
127 if (not $input) {
128 $self->close_fh();
129 return 0;
131 my @output = $self->formatted_eval($input);
132 my $output_s = "@output";
133 $self->lv_send($output_s);
134 return 1;
137 =head2 Callback Methods
139 =over
141 =item C<cb_listen()>
143 Called when the Server begins to listen for client connections.
145 =item C<cb_connect()>
147 Called whenever a client connection is accepted.
149 =item C<cb_disconnect()>
151 Called whenever a client disconnects.
153 =back
155 =cut
157 sub cb_listen {
158 my ($self) = @_;
159 $self->debug("Server PID $$ listening.");
162 sub cb_connect {
163 my ($self) = @_;
165 if (not $self->{'fh'}) {
166 return;
168 my $client_details = '';
169 if ($self->{'fh'}->can('peerhost')) {
170 $client_details = ' '
171 . $self->{'fh'}->peerhost()
172 . ':'
173 . $self->{'fh'}->peerport();
176 $self->debug("Server PID $$ connected" . $client_details);
179 sub cb_disconnect {
180 my ($self) = @_;