ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Linux-NBD/lib/Linux/NBD/Server.pm
Revision: 1.7
Committed: Fri Sep 8 19:29:07 2006 UTC (20 years, 1 month ago) by root
Branch: MAIN
CVS Tags: rel-0_91
Changes since 1.6: +1 -1 lines
Log Message:
fix typo

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     =item $server = new Linux::NBD::Server socket => $fd, ...;
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
49     C<$server->one_request>, but note that it still might block to read the
50     write data from the socket.
51    
52     =item $server->one_request
53    
54     Waits for and handles a single request and returns, returning true if no
55     further requests will arrive.
56    
57     =item $server->format_reply ($handle[, $error, [, $data]])
58    
59     Formats (and returns as a string) a reply message. If the request was a
60     read request and C<$error> is zero (or missing, both meaning no error),
61     you should append the read data to it.
62    
63     If C<$data> is given and C<$error> is zero, it is appended to the string
64     before it is returned.
65    
66     =item $server->reply ($handle[, $error[, $data]])
67    
68     Formats and sends a reply to the server.
69    
70     =item $server->send ($data)
71    
72     Writes the given data to the client socket.
73    
74 root 1.6 =item $server->recv ($bytes)
75 root 1.1
76     Reads the specified number of bytes and returns them.
77    
78     =cut
79    
80     sub run {
81     my $self = shift;
82    
83     1 while not _one_request $self, fileno $self->{socket};
84     }
85    
86     sub one_request {
87     my $self = shift;
88    
89     _one_request $self, fileno $self->{socket};
90     }
91    
92     sub format_reply {
93     shift;
94     &_format_reply;
95     }
96    
97     sub reply {
98     my $self = shift;
99    
100     $self->send(&_format_reply);
101     }
102    
103     sub send {
104     syswrite $_[0]->{socket}, $_[1];
105     }
106    
107     sub recv {
108 root 1.6 my ($self, $len) = @_;
109 root 1.1
110 root 1.6 my ($buf, $todo);
111    
112     sysread $self->{socket}, $buf, $togo, length $buf
113 root 1.7 or die "error or eof while receiving from network: $!"
114 root 1.6 while $todo = $len - length $buf;
115    
116     $buf
117 root 1.1 }
118    
119 root 1.6 =item $server->req_read ($handle, $offset, $length)
120 root 1.1
121     This callback is called for every read request. It should send
122 root 1.6 back a reply and the requested number of bytes, e.g.:
123 root 1.1
124     my ($self, $handle, $ofs, $len) = @_;
125     $self->reply($handle, 0, "\xff" x $len);
126    
127 root 1.6 =item $server->req_write ($handle, $offset, $length)
128 root 1.1
129     Same as C<req_read>, but you should use C<recv> to read C<$len> bytes from
130     the socket (even if you intend to return an error, of course).
131    
132     my ($self, $handle, $ofs, $len) = @_;
133     my $data = $self->recv($len);
134     $self->reply($handle);
135    
136     =cut
137    
138     sub req_read {
139     my ($self, $handle, $ofs, $len) = @_;
140    
141 root 1.6 $self->reply ($handle, 1);
142 root 1.1 }
143    
144     sub req_write {
145     my ($self, $handle, $ofs, $len) = @_;
146    
147 root 1.6 $self->recv ($len);
148     $self->reply ($handle, 1);
149 root 1.1 }
150    
151     1;
152    
153     =back
154    
155 root 1.6 =head1 NBD TOOL NEGOTIATION PROTOCOL
156    
157     Standard NBD tools add a handshake phase before starting to serve/send
158     requests. The server-side implementation looks like this:
159    
160     $size = new Math::BigInt $size;
161     my $size_hi = $size->copy->brsft(32)->blsft(32);
162     my $size_lo = $size->copy->bsub($size_hi)->numify;
163     $size_hi = $size_hi->brsft(32)->numify;
164    
165     $s->send ("NBDMAGIC\x00\x00\x42\x02\x81\x86\x12\x53");
166     $s->send (pack "NN", $size_hi, $size_lo);
167     $s->send ("\x00" x 128);
168    
169     # now serve
170     my $server = new ServerClass socket => $s;
171     $server->run;
172    
173    
174     =head1 BUGS
175    
176     Should support AnyEvent or something similar for non-blocking behaviour.
177    
178 root 1.1 =head1 AUTHOR
179    
180 root 1.5 Marc Lehmann <schmorp@schmorp.de>
181     http://home.schmorp.de/
182 root 1.1
183     =cut
184