ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Linux-NBD/lib/Linux/NBD/Server.pm
Revision: 1.10
Committed: Tue Sep 21 11:51:55 2010 UTC (16 years ago) by root
Branch: MAIN
CVS Tags: rel-1_0, HEAD
Changes since 1.9: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 Linux::NBD::Server - server (data provider) side of a network block device
4
5 =head1 SYNOPSIS
6
7 use Linux::NBD::Server;
8
9 =head1 DESCRIPTION
10
11 You must subclass C<Linux::NBD::Server> to get meaningful results. You
12 should overwrite C<req_read> and/or C<req_write>. The default
13 implementations just return EIO.
14
15 =head1 METHODS
16
17 =over 4
18
19 =cut
20
21 package Linux::NBD::Server;
22
23 $VERSION = 0.21;
24
25 use Linux::NBD ();
26
27 use Carp qw(croak);
28 use Errno ();
29
30 =item $server = new Linux::NBD::Server socket => $fh, ...;
31
32 Create a new server. All arguments are put into a hashref which is blessed
33 and returned. The only required argument is C<socket> which should be
34 connected to a C<Linux::NBD::Client>.
35
36 =cut
37
38 sub new {
39 my $class = shift;
40 bless { @_ }, ref $class || $class;
41 }
42
43 =item $server->run
44
45 Enters a server loop, serving requests. Only returns when the socket is closed
46 or a disconnect message is received.
47
48 If you need non-blocking access your best bet is to use C<<
49 $server->one_request >> after you detected readability on the file
50 descriptor, but note that it still might block to read the write data from
51 the socket.
52
53 =item $server->one_request
54
55 Waits for and handles a single request and returns, returning true if a
56 request could be handled, false (but defined) if no full request could be
57 received yet (in which case the partial request will be buffered), and
58 C<undef> if there was an error or eof.
59
60 On blockign sockets, this will read one full request and handle it. On
61 non-blocking sockets it will try to do the same, but if not enough data is
62 available, it will return false (but defined) and buffer th already-read
63 data for the next invocation.
64
65 =item $server->format_reply ($handle[, $error, [, $read_data]])
66
67 Formats (and returns as a string) a reply message. If the request was a
68 read request and C<$error> is zero (or missing, both meaning no error),
69 you should append the read data to it (or let the method do it by
70 specifying the C<$read_data> argument, which is automatically appended
71 unless C<$error> is true).
72
73 =item $server->reply ($handle[, $error[, $read_data]])
74
75 Formats and sends a reply to the server. Only works on blocking
76 sockets. For non-blocking sockets, you have to use C<format_reply> and
77 manage the send buffer yourself.
78
79 =cut
80
81 sub run {
82 my $self = shift;
83
84 1 while defined _one_request $self, fileno $self->{socket};
85 }
86
87 sub one_request {
88 my $self = shift;
89
90 _one_request $self, fileno $self->{socket}
91 }
92
93 sub reply {
94 $_[0]->_send (&format_reply)
95 }
96
97 #TODO: does not work on non-blocking sockets
98 sub _send {
99 syswrite $_[0]->{socket}, $_[1]
100 }
101
102 =item $server->req_read ($handle, $offset, $length)
103
104 This callback is called for every read request. It should send
105 back a reply and the requested number of bytes, e.g.:
106
107 sub req_read {
108 my ($self, $handle, $ofs, $len) = @_;
109 $self->reply ($handle, 0, "\xff" x $len);
110 }
111
112 The default implementation will reply with an error.
113
114 =item $server->req_write ($handle, $offset, $data)
115
116 Same as C<req_read>, but is called for writes: instead of a length the
117 write data is passed directly.
118
119 sub req_write {
120 my ($self, $handle, $ofs, $data) = @_;
121 $self->reply ($handle, 0); # OK
122 }
123
124 You can avoid copying the (potentially large) data argument by refering to
125 it directly, e.g.:
126
127 sub req_write {
128 my ($self, $handle, $ofs) = @_;
129 # do something with $_[3] directly
130 $self->reply ($handle, 0); # OK
131 }
132
133 The default implementation will reply with an error.
134
135 =item $server->req_disc
136
137 A disconnect request was received - what you do with it is up to you, the
138 kernel driver is a bit confused - you can still have outstanding requests,
139 and you can still receive further requests, so it's not clear what this
140 request is intended to achieve, and it's probably best not to override it.
141
142 =cut
143
144 # =item $server->req_error
145 #
146 # A read or write error occured, you can look at C<$!> to see what it is
147 # about, or simply ignore it. In all cases this error is fatal, i.e. no
148 # further request will be handled.
149 #
150 # =item $server->req_eof
151 #
152 # The socket
153 #
154 # =cut
155
156 sub req_read {
157 my ($self, $handle, $ofs, $len) = @_;
158
159 $self->reply ($handle, 1);
160 }
161
162 sub req_write {
163 my ($self, $handle, $ofs, $data) = @_;
164
165 $self->reply ($handle, 1);
166 }
167
168 sub req_disc {
169 # nop
170 }
171
172 1;
173
174 =back
175
176 =head1 NBD TOOL NEGOTIATION PROTOCOL
177
178 Standard NBD tools add a handshake phase before starting to serve/send
179 requests. The server-side implementation looks like this:
180
181 $size = new Math::BigInt $size;
182 my $size_hi = $size->copy->brsft(32)->blsft(32);
183 my $size_lo = $size->copy->bsub($size_hi)->numify;
184 $size_hi = $size_hi->brsft(32)->numify;
185
186 $s->send ("NBDMAGIC\x00\x00\x42\x02\x81\x86\x12\x53");
187 $s->send (pack "NN", $size_hi, $size_lo);
188 $s->send ("\x00" x 128);
189
190 # now serve
191 my $server = new ServerClass socket => $s;
192 $server->run;
193
194 =head1 AUTHOR
195
196 Marc Lehmann <schmorp@schmorp.de>
197 http://home.schmorp.de/
198
199 =cut
200