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

# User Rev Content
1 root 1.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 root 1.4 $VERSION = 0.21;
24 root 1.1
25     use Linux::NBD ();
26    
27     use Carp qw(croak);
28     use Errno ();
29    
30 root 1.8 =item $server = new Linux::NBD::Server socket => $fh, ...;
31 root 1.1
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 root 1.8 If you need non-blocking access your best bet is to use C<<
49 root 1.9 $server->one_request >> after you detected readability on the file
50 root 1.8 descriptor, but note that it still might block to read the write data from
51     the socket.
52 root 1.1
53     =item $server->one_request
54    
55 root 1.9 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 root 1.1
65 root 1.9 =item $server->format_reply ($handle[, $error, [, $read_data]])
66 root 1.1
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 root 1.9 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 root 1.1
79     =cut
80    
81     sub run {
82     my $self = shift;
83    
84 root 1.10 1 while defined _one_request $self, fileno $self->{socket};
85 root 1.1 }
86    
87     sub one_request {
88     my $self = shift;
89    
90 root 1.9 _one_request $self, fileno $self->{socket}
91 root 1.1 }
92    
93 root 1.9 sub reply {
94     $_[0]->_send (&format_reply)
95 root 1.1 }
96    
97 root 1.9 #TODO: does not work on non-blocking sockets
98     sub _send {
99     syswrite $_[0]->{socket}, $_[1]
100     }
101 root 1.1
102 root 1.9 =item $server->req_read ($handle, $offset, $length)
103 root 1.1
104 root 1.9 This callback is called for every read request. It should send
105     back a reply and the requested number of bytes, e.g.:
106 root 1.1
107 root 1.9 sub req_read {
108     my ($self, $handle, $ofs, $len) = @_;
109     $self->reply ($handle, 0, "\xff" x $len);
110     }
111 root 1.1
112 root 1.9 The default implementation will reply with an error.
113 root 1.6
114 root 1.9 =item $server->req_write ($handle, $offset, $data)
115 root 1.6
116 root 1.9 Same as C<req_read>, but is called for writes: instead of a length the
117     write data is passed directly.
118 root 1.1
119 root 1.9 sub req_write {
120     my ($self, $handle, $ofs, $data) = @_;
121     $self->reply ($handle, 0); # OK
122     }
123 root 1.1
124 root 1.9 You can avoid copying the (potentially large) data argument by refering to
125     it directly, e.g.:
126 root 1.1
127 root 1.9 sub req_write {
128     my ($self, $handle, $ofs) = @_;
129     # do something with $_[3] directly
130     $self->reply ($handle, 0); # OK
131     }
132 root 1.1
133 root 1.9 The default implementation will reply with an error.
134 root 1.1
135 root 1.9 =item $server->req_disc
136 root 1.1
137 root 1.9 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 root 1.1
142     =cut
143    
144 root 1.9 # =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 root 1.1 sub req_read {
157     my ($self, $handle, $ofs, $len) = @_;
158    
159 root 1.6 $self->reply ($handle, 1);
160 root 1.1 }
161    
162     sub req_write {
163 root 1.9 my ($self, $handle, $ofs, $data) = @_;
164 root 1.1
165 root 1.6 $self->reply ($handle, 1);
166 root 1.1 }
167    
168 root 1.9 sub req_disc {
169     # nop
170     }
171    
172 root 1.1 1;
173    
174     =back
175    
176 root 1.6 =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 root 1.1 =head1 AUTHOR
195    
196 root 1.5 Marc Lehmann <schmorp@schmorp.de>
197     http://home.schmorp.de/
198 root 1.1
199     =cut
200