#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
#
import xdrlib
class RecordMarkingSocket(object):
""" Implementation of XDR/RPC Record Marking """
def __init__(self, socket):
self._socket = socket
self._remaining = 0
self._atlast = True
self._eof = False
def __enter__(self):
return self
def __exit__(self, type, value, tb):
self.close()
return False
def really_read(self, n):
""" Internal: read n bytes or else (mark EOF) """
alldata = ''
remaining = n
while len(alldata) < n:
data = self._socket.recv(remaining)
l = len(data)
if l == 0:
self._eof = True
return ''
remaining -= l
alldata += data
return alldata
def read_header(self):
""" Internal: read a the next fragment header """
data = self.really_read(4)
if self._eof: return
assert len(data) == 4
acc = 0
for i in range(4):
acc = acc * 0x100 + ord(data[i])
self._atlast = (acc & 0x80000000) != 0
self._remaining = acc & 0x7fffffff
def skip_record(self):
""" Skip this record """
if self._remaining > 0: self.really_read(self._remaining)
while not self._atlast and not self._eof:
self.read_header()
if self._remaining > 0: self.really_read(self._remaining)
self._atlast = False
def read(self, n):
""" Read up to n bytes """
while self._eof or self._remaining == 0:
if self._eof or self._atlast:
return ''
self.read_header()
amt = min(self._remaining, n)
data = self._socket.recv(amt)
self._remaining -= len(data)
if len(data) == 0:
self._eof = True
return data
def read_record(self):
""" Read a whole record """
alldata = ''
while not self._atlast or self._remaining > 0:
if self._remaining > 0:
data = self.really_read(self._remaining)
alldata += data
self._remaining -= len(data)
else:
self.read_header()
if self._eof:
return ''
return alldata
def write(self, buffer, last):
""" Simple non-buffered write routine """
p = xdrlib.Packer()
if last:
p.pack_uint(len(buffer) | 0x80000000)
else:
p.pack_uint(len(buffer))
self._socket.sendall(p.get_buffer())
self._socket.sendall(buffer)
def end_record(self):
""" End a record """
p = xdrlib.Packer()
p.pack_uint(0x80000000)
self._socket.sendall(p.get_buffer())
def close(self):
""" Close the socket """
self._socket.close()