Welcome, guest | Sign In | My Account | Store | Cart
#!/usr/bin/python
import struct, socket, sys, time
# Working: nbd protocol, read/write serving up files, error handling, file size detection, in theory, large file support... not really, so_reuseaddr, nonforking

def recvall(sock, length):
  rv
= []
 
while sum(map(len, rv)) < length:
    rv
.append(sock.recv(length-sum(map(len, rv))))
   
assert rv[-1], "no more data to read"
 
return ''.join(rv)

def serveclient():
    READ
, WRITE, CLOSE = 0,1,2
   
"Serves a single client until it exits."
    afile
.seek(0, 2)
    asock
.send('NBDMAGIC\x00\x00\x42\x02\x81\x86\x12\x53' + struct.pack('>Q', afile.tell()) + '\0'*128);
   
while True:
        header
= recvall(asock, struct.calcsize('>LL8sQL'))
        magic
, request, handle, offset, dlen = struct.unpack('>LL8sQL', header)
       
assert magic == 0x25609513
       
if request == READ:
            afile
.seek(offset)
            asock
.send('gDf\x98\0\0\0\0'+handle)
            asock
.send(afile.read(dlen))
           
print "read\t0x%08x\t0x%08x" % (offset, dlen), time.time()
       
elif request == WRITE:
            afile
.seek(offset)
            afile
.write(recvall(asock, dlen))
            afile
.flush()
            asock
.send('gDf\x98\0\0\0\0'+handle)
           
print "write\t0x%08x\t0x%08x" % (offset, dlen), time.time()
       
elif request == CLOSE:
            asock
.close()
           
print "closed"
           
return
       
else:
           
print "ignored request", request

if __name__ == '__main__':
   
"Given a port and a filename, serves up the file."
    afile
= file(sys.argv[2], 'rb+')
    lsock
= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    lsock
.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    lsock
.bind(('', int(sys.argv[1])))
    lsock
.listen(5)
   
while True:
       
(asock, addr) = lsock.accept()
       
print "connection from", addr
        serveclient
()

History