"""Simple, blocking, socket-based transceiver."""

import socket

import avro.ipc

try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO


class SocketTransceiver(object):
    """Simple, blocking, socket-based transceiver."""

    def __init__(self, host, port):
        """Create and connect to the remote service."""

        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.connect((host, port))

    remote_name = property(lambda self: self.sock.getsockname())

    def transceive(self, request):
        """Write the request and read the response back."""

        self.write_framed_message(request)
        return self.read_framed_message()

    def write_framed_message(self, message):
        """Frame the message and send it over the wire."""

        req_buffer = avro.ipc.FramedWriter(StringIO())
        req_buffer.write_framed_message(message)
        req = req_buffer.writer.getvalue()

        self.sock.sendall(req)

    def read_framed_message(self):
        """Read the response from the wire and return it."""

        message = StringIO()
        buffer_length = ""

        while buffer_length != 0:
            buffer_header = self.sock.recv(avro.ipc.BUFFER_HEADER_LENGTH)
            buffer_length = \
                avro.ipc.BIG_ENDIAN_INT_STRUCT.unpack(buffer_header)[0]
            message.write(buffer_header)

            if buffer_length == "":
                raise avro.ipc.ConnectionClosedException("Reader read 0 bytes.")

            message.write(self.sock.recv(buffer_length))

        message.reset()
        reader = avro.ipc.FramedReader(message)
        framed_message = reader.read_framed_message()

        return framed_message

    def close(self):
        """Close this socket for both reading and writing."""

        self.sock.shutdown(socket.SHUT_RDWR)
        self.sock.close()

@@ -1123,24 +1123,25 @@
 ingIO()%0A
+%0A
         
 buffer_l
@@ -1136,61 +1136,49 @@
     
-buffer_length = %22%22%0A%0A        while buffer_length != 0:
+while True:%0A            buff = StringIO()
 %0A   
@@ -1353,49 +1353,8 @@
 )%5B0%5D
-%0A            message.write(buffer_header)
 %0A%0A  
@@ -1448,59 +1448,290 @@
 ion(
-%22Reader read 0 bytes.%22)%0A%0A            message.write(
+%0A                    %22Socket read 0 bytes.%22%0A                )%0A            elif buffer_length == 0:%0A                # A 0-length buffer indicates the end of the message%0A                return message.getvalue()%0A%0A            while buff.tell() %3C buffer_length:%0A                chunk = 
 self
@@ -1758,20 +1758,32 @@
 ngth
+ - buff.tell(
 ))%0A
-%0A
         
 mess
@@ -1782,24 +1782,44 @@
     
-message.reset()%0A
+        if chunk == %22%22:%0A            
     
@@ -1823,23 +1823,20 @@
        r
-eader =
+aise
  avro.ip
@@ -1841,114 +1841,181 @@
 ipc.
-FramedReader(message)%0A        framed_message = reader.read_framed_message()%0A%0A        return framed_message
+ConnectionClosedException(%0A                        %22Socket read 0 bytes.%22%0A                    )%0A                buff.write(chunk)%0A%0A            message.write(buff.getvalue())
 %0A%0A  

Clean up the Transceiver: * Fix bug where recv() would hang * Clean up and remove redundant FramedReader logic