/[pxelator]/lib/PXElator/tftpd.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /lib/PXElator/tftpd.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 545 - (show annotations)
Sat Oct 9 13:50:38 2010 UTC (13 years, 6 months ago) by dpavlin
File size: 2927 byte(s)
added forking on each tftp request

this allows faster booting of multiple clients
at the same time

1 package tftpd;
2
3 use warnings;
4 use strict;
5
6 use Net::TFTPd 0.03 qw(%OPCODES);
7 use IO::Socket::INET;
8 use Data::Dump qw/dump/;
9 use store;
10
11 use server;
12
13 our $debug = server::debug;
14
15 our $dir = "$server::base_dir/tftp";
16
17 sub path {
18 my $glob = shift;
19 my $path = (glob("$dir/$glob"))[0];
20 die "can't find anything for $dir/$glob" unless $path;
21 warn 'path ', $path if $debug;
22 $path =~ s{^$dir}{};
23 return $path;
24 }
25
26 use progress_bar;
27
28 sub transfer_status {
29 my $request = shift;
30 my $r = $request->{'_REQUEST_'} || die "no _REQUEST_ in ",dump( $request );
31
32 if( $r->{'OPCODE'} eq $OPCODES{'RRQ'} ) {
33 progress_bar::tick( $r->{FileName}, $r->{BlkSize} * $r->{LASTACK}, $r->{BlkSize} * $r->{LASTBLK} );
34 } elsif ( $r->{'OPCODE'} eq $OPCODES{'WRQ'} ) {
35 die "WRQ disabled";
36 } else {
37 warn "IGNORED: ", dump( $request );
38 }
39 }
40
41 use config;
42
43 sub tftp_request {
44 my $request = shift;
45
46 warn 'request: ', dump( $request ) if $debug;
47
48 if ( my $pid = fork ) {
49 # parent
50 warn "# forked $pid\n";
51 return;
52 }
53
54
55 my $ip = $request->{_REQUEST_}->{PeerAddr};
56 config::for_ip( $ip );
57
58 if ( $request->{RootDir} ne $dir ) {
59 $request->{RootDir} = $dir;
60 warn "new root: $dir";
61 }
62
63 my $file = $request->{'_REQUEST_'}{'FileName'};
64 my $opcode = $OPCODES{$request->{'_REQUEST_'}{'OPCODE'}};
65
66 my $audit = {
67 ip => $ip,
68 opcode => $opcode,
69 path => $file,
70 state => 'start',
71 };
72 store::audit( $opcode, $audit );
73
74 progress_bar::start;
75
76 # process the request
77 if( $request->processRQ() ) {
78 my $size = -s "$dir/$file";
79 $audit->{state} = 'finish';
80 $audit->{size} = $size;
81 store::audit( $opcode, $audit );
82 } else {
83 $audit->{state} = 'error';
84 $audit->{error} = Net::TFTPd->error;
85 store::audit( $opcode, $audit );
86 }
87
88 }
89
90 use server;
91
92 sub start {
93
94 warn 'start';
95
96 # XXX we need to setup listener ourselfs because we need Reuse
97 my %params = (
98 Proto => 'udp',
99 # LocalAddr => $server::ip,
100 # LocalAddr => '0.0.0.0',
101 LocalPort => 69,
102 Reuse => 1,
103 );
104
105 my $udpserver = IO::Socket::INET->new(%params);
106 die "can't start server ",dump( \%params ), " $!" unless $udpserver;
107
108 my $listener = bless {
109 RootDir => $dir,
110
111 ACKtimeout => 1, # 4
112 ACKretries => 2, # 4
113 Readable => 1,
114 Writable => 0,
115 Timeout => 3600,
116
117 CallBack => \&transfer_status,
118 # BlkSize => 8192,
119 BlkSize => 512, # Dell's RAC doesn't like bigger packets
120 # BlkSize => 1456, # IBM GE seems to be picky
121 Debug => 99,
122 %params, # merge user parameters
123 _UDPSERVER_ => $udpserver,
124 }, 'Net::TFTPd';
125
126 warn 'listener: ',dump( $listener ) if $debug;
127
128 store::audit( 'start', {
129 addr => $listener->{LocalAddr},
130 port => $listener->{LocalPort},
131 timeout => $listener->{Timeout},
132 params => { %params },
133 });
134
135 while(1) {
136
137 # wait for any request (RRQ or WRQ)
138 if(my $request = $listener->waitRQ()) {
139 server->refresh;
140 tftp_request $request;
141 } elsif ( my $error = Net::TFTPd->error ) {
142 warn $error;
143 }
144
145 }
146
147 }
148
149 warn "loaded";
150
151 1;

  ViewVC Help
Powered by ViewVC 1.1.26