Cleaned up demos, various build fixes
[urisagit/Stem.git] / lib / Stem / Packet.pm
CommitLineData
4536f655 1# File: Stem/Packet.pm
2
3# This file is part of Stem.
4# Copyright (C) 1999, 2000, 2001 Stem Systems, Inc.
5
6# Stem is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10
11# Stem is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15
16# You should have received a copy of the GNU General Public License
17# along with Stem; if not, write to the Free Software
18# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20# For a license to use the Stem under conditions other than those
21# described here, to purchase support for this software, or to purchase a
22# commercial warranty contract, please contact Stem Systems at:
23
24# Stem Systems, Inc. 781-643-7504
25# 79 Everett St. info@stemsystems.com
26# Arlington, MA 02474
27# USA
28
29package Stem::Packet ;
30
31use strict ;
32
33use Stem::Class ;
34use Stem::Codec ;
35
36my $attr_spec = [
37
38 {
39 'name' => 'codec',
40 'env' => 'packet_codec',
41 'default' => 'Data::Dumper',
42 'help' => <<HELP,
43This is the name of the Codec:: subclass that will be used in this cell
44HELP
45 },
46 {
47 'name' => 'object',
48 'type' => 'object',
49 'help' => <<HELP,
50If an object is passed in, the filter will use it for callbacks
51HELP
52 },
53 {
54 'name' => 'packet_method',
55 'default' => 'packet_out',
56 'help' => <<HELP,
57This method is called on the object when a packet has encoded from
58internal data
59HELP
60 },
61
62 {
63 'name' => 'data_method',
64 'default' => 'packet_data',
65 'help' => <<HELP,
66This method is called on the object when a packet has been decoded
67from external data
68HELP
69 },
70
71] ;
72
73
74###########
75# This POD section is autoegenerated. Any edits to it will be lost.
76
77=head2 Constructor Attributes for Class Stem::Packet
78
79=over 4
80
81
82=item * Attribute - B<codec>
83
84=over 4
85
86
87=item Description:
88This is the name of the Codec:: subclass that will be used in this cell
89
90
91=item It B<defaults> to: Storable
92Unknown attribute env
93
94=back
95
96=item * Attribute - B<object>
97
98=over 4
99
100
101=item Description:
102If an object is passed in, the filter will use it for callbacks
103
104
105=item Its B<type> is: object
106
107=back
108
109=item * Attribute - B<packet_method>
110
111=over 4
112
113
114=item Description:
115This method is called on the object when a packet has encoded from
116internal data
117
118
119=item It B<defaults> to: packet_out
120
121=back
122
123=item * Attribute - B<data_method>
124
125=over 4
126
127
128=item Description:
129This method is called on the object when a packet has been decoded
130from external data
131
132
133=item It B<defaults> to: packet_data
134
135=back
136
137=back
138
139=cut
140
141# End of autogenerated POD
142###########
143
144sub new {
145
146 my( $class ) = shift ;
147
148
149 my $self = Stem::Class::parse_args( $attr_spec, @_ ) ;
150 return $self unless ref $self ;
151
152# my @codec_args = exists( $self->{codec} ) ?
153# ( codec => $self->{codec} ) : () ;
154
155#print "NEW PACKET CODEC $self->{codec}\n" ;
156
157 my $codec_obj = Stem::Codec->new( codec => $self->{codec} ) ;
158 return $codec_obj unless ref $codec_obj ;
159 $self->{'codec_obj'} = $codec_obj ;
160
161#print "CODEC OBJ [$codec_obj]\n" ;
162
163 return $self ;
164}
165
166my $END_MARK = "\012#END\012" ;
167my $end_mark_len = length $END_MARK ;
168
169
170sub to_packet {
171
172 my $self = shift ;
173
174 return unless @_ ;
175#use Data::Dumper ;
176#print Dumper $_[0] ;
177
178 my $codec_text = $self->{'codec_obj'}->encode( $_[0] ) ;
179
180#print Dumper $codec_text ;
181 my $size = length( ${$codec_text} ) ;
182
183# wrap the packet text with a size/codec/end pair of lines
184
185 my $packet_text = "#$size:$self->{'codec'}\012${$codec_text}$END_MARK" ;
186
187#print "PACKET TEXT [$packet_text]\n" ;
188
189 $self->_callback( 'packet_method', \$packet_text ) ;
190 return \$packet_text ;
191}
192
193sub to_data {
194
195 my( $self, $input ) = @_ ;
196
197#print "IN DATA [$input]\n" ;
198 my $buf_ref = \$self->{'buffer'} ;
199
200 ${$buf_ref} .= ( ref $input eq 'SCALAR' ) ? ${$input} : $input
201 if defined $input ;
202
203 my $codec = $self->{'codec'} ;
204
205 while( 1 ) {
206
207 unless ( $self->{'packet_len'} ) {
208
209# grab the packet_len if we can from the header line
210
211 return unless ${$buf_ref} =~
212 s/\A#(\d+):$self->{'codec'}\012// ;
213
214 $self->{'packet_len'} = $1 ;
215 }
216
217 my $packet_len = $self->{'packet_len'} || 0 ;
218
219#print "PACKET_LEN [$packet_len]\n" ;
220
221# see if we have a full packet with end line
222
223#print "IN BUF [${$buf_ref}]\n" ;
224
225 return if length( ${$buf_ref} ) < $packet_len ;
226
227# old regex method was limited to 64k bytes in a packet
228# return unless ${$buf_ref} =~ s/^(.{$packet_len})$END_MARK//s ;
229
230 return unless
231 substr( ${$buf_ref}, $packet_len, $end_mark_len ) eq $END_MARK ;
232
233# grab the packet data and end marker and delete it from the buffer
234 my $packet = substr( ${$buf_ref}, 0,
235 $packet_len + $end_mark_len, '' ) ;
236
237# delete the end marker from the packet
238
239 substr( $packet, $packet_len, $end_mark_len, '' ) ;
240
241#print "IN PACKET [$packet]\n" ;
242
243 my $decoded_data = $self->{'codec_obj'}->decode( $packet ) ;
244
245#use Data::Dumper ;
246#print "DECODED: ", Dumper( $decoded_data ) ;
247
248 $self->{'packet_len'} = 0 ;
249
250#local( $SIG{'__WARN__'} ) = sub {} ;
251
252 next if $self->_callback( 'data_method', $decoded_data ) ;
253 return( $decoded_data ) ;
254 }
255}
256
257sub _callback {
258
259 my ( $self, $method_attr, @data ) = @_ ;
260
261 my $obj = $self->{'object'} or return ;
262 my $method = $self->{$method_attr} ;
263 my $code = $obj->can( $method ) or return ;
264
265 $obj->$code( @data ) ;
266
267 return 1 ;
268}
269
2701 ;