root/1.8.3/tags/p6/test/MUSHConnection.pm

Revision 439, 3.7 KB (checked in by pennmush, 2 years ago)

PennMUSH 1.7.7p20 Archival

Line 
1package MUSHConnection;
2
3# use strict;
4use IO::Poll;
5use IO::Socket::INET;
6
7my $nextpat = "PATTERN000000001";
8
9sub new {
10  my $proto = shift;
11  my $class = ref($proto) || $proto;
12  my $self = [];
13  $self->[0] = IO::Socket::INET->new();
14  $self->[1] = {};
15  $self->[1]->{PREFIX} = '=-=-= OUTPUTPREFIX =-=-=';
16  $self->[1]->{SUFFIX} = '=-=-= OUTPUTSUFFIX =-=-=';
17  $self->[1]->{MATCHER} = {};
18  bless($self, $class);
19  $self->connect(@_) if @_;
20  return $self;
21}
22
23sub connected {
24  my $self = shift;
25
26  my $socket = $self->[0];
27  return $socket->connected();
28}
29
30sub connect {
31  my $self = shift;
32  my $addr = shift;
33  my $port = shift;
34  my $name = shift;
35  my $passwd = shift;
36
37  my $socket = $self->[0];
38  $socket->close if $socket->connected();
39  $self->[0] = IO::Socket::INET->new(PeerAddr => $addr, PeerPort => $port,
40                                     Proto => "tcp");
41  $socket = $self->[0];
42#  $socket->connect(PeerAddr => $addr, PeerPort => $port, Proto => "tcp");
43  $socket->autoflush(1);
44  $socket->timeout(30);
45
46  $self->read_to_pattern('.') || return;
47  $self->read_to_empty();
48  $socket->print("connect $name $passwd\r\n");
49  $socket->flush();
50  $self->read_to_pattern('.') || return;
51  $self->read_to_empty();
52  sleep(1);
53  $socket->print("OUTPUTPREFIX " . $self->[1]->{PREFIX} . "\r\n");
54  $socket->print("OUTPUTSUFFIX " . $self->[1]->{SUFFIX} . "\r\n");
55  $socket->print("say CodeMUSH $$\r\n");
56  $self->read_to_pattern("CodeMUSH $$") || return;
57}
58
59sub disconnect {
60  my $self = shift;
61
62  my $socket = $self->[0];
63  $socket->close if $socket->connected();
64}
65
66sub read_to_pattern {
67  my $self = shift;
68  my $pattern = shift;
69
70# warn "Looking for pattern $pattern\n";
71  my $matcher = $self->[1]->{MATCHER}->{$pattern};
72  unless ($matcher) {
73    my $patsub = $pattern;
74#    $patsub =~ s/(\W)/\\$1/go;
75    my $sub = <<EOT;
76sub $nextpat {
77  return (\$`, \$&, \$') if \$_[\$[] =~ /$patsub/o;
78  return undef;
79}
801;
81EOT
82# warn "Building matcher $nextpat:\n$sub";
83    eval($sub);
84    $matcher = $nextpat++;
85    $self->[1]->{MATCHER}->{$pattern} = $matcher;
86  }
87# warn "Using matcher $matcher\n";
88
89  my $socket = $self->[0];
90  my $buffer = $self->[1]->{BUFFER};
91  my @match = &$matcher($buffer);
92  my $poll = new IO::Poll;
93  $poll->mask($socket => POLLIN | POLLERR | POLLHUP);
94  until (@match > 1) {
95# warn "Looping...\n";
96    my $buf;
97    my $amount = $socket->sysread($buf, 1024);
98# warn "Read $amount: $buf...\n";
99    $amount || ($self->disconnect(), return);
100    $buffer .= $buf;
101  } continue {
102    @match = &$matcher($buffer);
103  }
104  $self->[1]->{BUFFER} = $match[2];
105
106# warn "Found match: ".join(",", @match)."\n";
107# warn "Returning: ".join(",",@match[0,1])."\n";
108  return (@match[0,1]);
109}
110
111sub read_to_empty {
112  my $self = shift;
113
114# warn "Emptying input...\n";
115  my $socket = $self->[0];
116  my $poll = new IO::Poll;
117  $poll->mask($socket => POLLIN | POLLERR | POLLHUP);
118  my $result = $self->[1]->{BUFFER};
119  my $buf;
120  while ($poll->poll(0) && !($poll->events($socket) & POLLERR | POLLHUP)) {
121    $socket->read($buf, 1024, 0);
122    $result .= $buf;
123  }
124  $self->[1]->{BUFFER} = "";
125# warn "Have result: $result\n";
126  return $result;
127}
128
129sub command {
130  my $self = shift;
131  my $command = shift;
132  my $socket = $self->[0];
133  my $noise = $self->read_to_empty();
134  $socket->print($command."\r\n");
135  my @result = $self->read_to_pattern($self->[1]->{PREFIX});
136  $noise .= $result[0];
137  $self->[1]->{NOISE} = $noise;
138  @result = $self->read_to_pattern($self->[1]->{SUFFIX});
139  $result[0] =~ s/^[\r\n]+//o;
140# warn "Noise: $noise\n";
141  return $result[0];
142}
143
144sub noise {
145  my $self = shift;
146  return $self->[1]->{NOISE};
147}
148
149sub listen {
150  my $self = shift;
151  $self->command("think Listening!");
152  $self->[1]->{NOISE} =~ s/^\r?\n//o;
153# warn "LISTENING!: ".$self->[1]->{NOISE}."\n";
154  return $self->[1]->{NOISE};
155}
156
1571;
Note: See TracBrowser for help on using the browser.