# Path: twimp/handshake.py
# class Handshaker(object):
#     """The handshake protocol.
# 
#     Interaction should go something like this:
#       * cl: ()->v+CLHS sent->(v+SVHS rcvd)->SVHS sent->(CLHS rcvd) OK!
#       * sv: ()->(v rcvd)->v+SVHS sent->(CLHS rcvd)->CLHS sent->(SVHS rcvd) OK!
# 
#     where:
#       * v    - version packet
#       * SVHS - server handshake packet
#       * CLHS - client handshake packet
#     """
# 
#     packet_bytes = 1536
#     protocol_version = 3
# 
#     def __init__(self, protocol, epoch_base, is_client=False):
#         self.epoch = epoch_base
#         self.version_packet = _s_uchar.pack(self.protocol_version)
#         self.protocol = protocol
#         self.is_client = is_client
# 
#     def epoch_time(self):
#         return time.time() - self.epoch
# 
# 
#     def defaultHandshakeFailed(self, msg=''):
#         self.protocol.handshakeFailed()
#         # raising exception should cause closing the connection eventually
#         raise HandshakeFailedError(string=msg)
# 
# 
#     def version_supported(self, version):
#         return version == self.protocol_version
# 
#     def generate_request(self, context=None):
#         return (_s_ts_simpver.pack(ms_time(self.epoch_time()), 0) +
#                 generate_random_bytes(self.packet_bytes - 8))
# 
#     def generate_response(self, request):
#         return (buffer(request, 0, 4) +
#                 (buffer(_s_ulong.pack(ms_time(self.epoch_time()))) +
#                  buffer(request, 8)))
# 
#     def verify_response(self, request, response):
#         return (buffer(request, 0, 4) == buffer(response, 0, 4) and
#                 buffer(request, 8) == buffer(response, 8))
# 
#     def gen_handler(self):
#         p = self.protocol
# 
#         if self.is_client:
#             ts_init = time.time()
#             hs_mine = self.generate_request()
#             p.transport.writeSequence((self.version_packet, hs_mine))
# 
#         # wait for the "version packet"
#         s = yield 1
#         version_other, = _s_uchar.unpack(s.read(1))
# 
#         if not self.version_supported(version_other):
#             self.defaultHandshakeFailed('protocol version mismatch')
#             return
# 
#         # now, the primary handshake packet
#         s = yield self.packet_bytes
# 
#         hs_other = s.read(self.packet_bytes)
# 
#         if not self.is_client:
#             ts_init = time.time()
#             hs_mine = self.generate_request(context=hs_other)
#             p.transport.writeSequence((self.version_packet, hs_mine))
# 
#         p.transport.write(self.generate_response(hs_other))
# 
#         # and now, the handshake response
#         s = yield self.packet_bytes
# 
#         hs_response = buffer(s.read(self.packet_bytes))
#         ts_received_back = time.time()
# 
#         if not self.verify_response(hs_mine, hs_response):
#             self.defaultHandshakeFailed('response verification failed')
#             return
# 
#         p.handshakeSucceeded(ts_init - self.epoch, ts_received_back - ts_init)
# 
# class HandshakeFailedError(ConnectError):
#     """Handshake failed"""
# 
# Path: twimp/utils.py
# class GeneratorWrapperProtocol(protocol.Protocol):
#     def __init__(self, proto=None):
#         self._buf = vecbuf.VecBuf()
#         self._toread = 0
# 
#         self._handler_changed = False
# 
#         self._handler = proto
#         if proto:
#             self._toread = self._handler.send(None)
# 
#     def init_handler(self, proto=None, do_init=True):
#         if proto:
#             if self._handler:
#                 # need to indicate we should retry on StopIteration...
#                 self._handler_changed = True
#             self._handler = proto
#         if do_init:
#             self._toread = self._handler.send(None)
# 
#     def connectionLost(self, reason=protocol.connectionDone):
#         # clean up
#         self._buf.read(len(self._buf))
#         self._handler = None
#         self._toread = None
# 
#     def dataReceived(self, data):
#         self._buf.write(data)
# 
#         while 1: # need to be able to retry immediately when handlers change
#             try:
#                 while len(self._buf) >= self._toread:
#                     self._toread = self._handler.send(self._buf)
#                 break           # no data, no retry
#             except StopIteration:
#                 if self._handler_changed:
#                     self._handler_changed = False
#                 else:
#                     self._toread = None
#                     self._handler = None
#                     break
#             except:
#                 # undocumented, but real; this way we can signal
#                 # protocol errors directly, and by not passing/raising
#                 # directly we avoid a stack trace log, with the same
#                 # effect - connectionLost
#                 f = failure.Failure()
#                 log.info(f.value, exc_info=log.isEnabledFor(logging.DEBUG))
#                 return f


import struct
import time
from twisted.python import failure
from twisted.trial import unittest
from twimp.handshake import Handshaker, HandshakeFailedError
from twimp.utils import GeneratorWrapperProtocol
from helpers import StringTransport
#   Copyright (c) 2010 Arek Korbik
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.


# from cStringIO import StringIO





class TestHandshakeProtocol(GeneratorWrapperProtocol):
    def __init__(self, *a, **kw):
        GeneratorWrapperProtocol.__init__(self, *a, **kw)
        self.handshake_status = None

    def handshakeSucceeded(self, init_ts, hs_delay):

# Path: twimp/handshake.py
# class Handshaker(object):
#     """The handshake protocol.
# 
#     Interaction should go something like this:
#       * cl: ()->v+CLHS sent->(v+SVHS rcvd)->SVHS sent->(CLHS rcvd) OK!
#       * sv: ()->(v rcvd)->v+SVHS sent->(CLHS rcvd)->CLHS sent->(SVHS rcvd) OK!
# 
#     where:
#       * v    - version packet
#       * SVHS - server handshake packet
#       * CLHS - client handshake packet
#     """
# 
#     packet_bytes = 1536
#     protocol_version = 3
# 
#     def __init__(self, protocol, epoch_base, is_client=False):
#         self.epoch = epoch_base
#         self.version_packet = _s_uchar.pack(self.protocol_version)
#         self.protocol = protocol
#         self.is_client = is_client
# 
#     def epoch_time(self):
#         return time.time() - self.epoch
# 
# 
#     def defaultHandshakeFailed(self, msg=''):
#         self.protocol.handshakeFailed()
#         # raising exception should cause closing the connection eventually
#         raise HandshakeFailedError(string=msg)
# 
# 
#     def version_supported(self, version):
#         return version == self.protocol_version
# 
#     def generate_request(self, context=None):
#         return (_s_ts_simpver.pack(ms_time(self.epoch_time()), 0) +
#                 generate_random_bytes(self.packet_bytes - 8))
# 
#     def generate_response(self, request):
#         return (buffer(request, 0, 4) +
#                 (buffer(_s_ulong.pack(ms_time(self.epoch_time()))) +
#                  buffer(request, 8)))
# 
#     def verify_response(self, request, response):
#         return (buffer(request, 0, 4) == buffer(response, 0, 4) and
#                 buffer(request, 8) == buffer(response, 8))
# 
#     def gen_handler(self):
#         p = self.protocol
# 
#         if self.is_client:
#             ts_init = time.time()
#             hs_mine = self.generate_request()
#             p.transport.writeSequence((self.version_packet, hs_mine))
# 
#         # wait for the "version packet"
#         s = yield 1
#         version_other, = _s_uchar.unpack(s.read(1))
# 
#         if not self.version_supported(version_other):
#             self.defaultHandshakeFailed('protocol version mismatch')
#             return
# 
#         # now, the primary handshake packet
#         s = yield self.packet_bytes
# 
#         hs_other = s.read(self.packet_bytes)
# 
#         if not self.is_client:
#             ts_init = time.time()
#             hs_mine = self.generate_request(context=hs_other)
#             p.transport.writeSequence((self.version_packet, hs_mine))
# 
#         p.transport.write(self.generate_response(hs_other))
# 
#         # and now, the handshake response
#         s = yield self.packet_bytes
# 
#         hs_response = buffer(s.read(self.packet_bytes))
#         ts_received_back = time.time()
# 
#         if not self.verify_response(hs_mine, hs_response):
#             self.defaultHandshakeFailed('response verification failed')
#             return
# 
#         p.handshakeSucceeded(ts_init - self.epoch, ts_received_back - ts_init)
# 
# class HandshakeFailedError(ConnectError):
#     """Handshake failed"""
# 
# Path: twimp/utils.py
# class GeneratorWrapperProtocol(protocol.Protocol):
#     def __init__(self, proto=None):
#         self._buf = vecbuf.VecBuf()
#         self._toread = 0
# 
#         self._handler_changed = False
# 
#         self._handler = proto
#         if proto:
#             self._toread = self._handler.send(None)
# 
#     def init_handler(self, proto=None, do_init=True):
#         if proto:
#             if self._handler:
#                 # need to indicate we should retry on StopIteration...
#                 self._handler_changed = True
#             self._handler = proto
#         if do_init:
#             self._toread = self._handler.send(None)
# 
#     def connectionLost(self, reason=protocol.connectionDone):
#         # clean up
#         self._buf.read(len(self._buf))
#         self._handler = None
#         self._toread = None
# 
#     def dataReceived(self, data):
#         self._buf.write(data)
# 
#         while 1: # need to be able to retry immediately when handlers change
#             try:
#                 while len(self._buf) >= self._toread:
#                     self._toread = self._handler.send(self._buf)
#                 break           # no data, no retry
#             except StopIteration:
#                 if self._handler_changed:
#                     self._handler_changed = False
#                 else:
#                     self._toread = None
#                     self._handler = None
#                     break
#             except:
#                 # undocumented, but real; this way we can signal
#                 # protocol errors directly, and by not passing/raising
#                 # directly we avoid a stack trace log, with the same
#                 # effect - connectionLost
#                 f = failure.Failure()
#                 log.info(f.value, exc_info=log.isEnabledFor(logging.DEBUG))
#                 return f


# Path: test/test_handshake.py
import struct
import time
from twisted.python import failure
from twisted.trial import unittest
from twimp.handshake import Handshaker, HandshakeFailedError
from twimp.utils import GeneratorWrapperProtocol
from helpers import StringTransport

#   Copyright (c) 2010 Arek Korbik
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.


# from cStringIO import StringIO





class TestHandshakeProtocol(GeneratorWrapperProtocol):
    def __init__(self, *a, **kw):
        GeneratorWrapperProtocol.__init__(self, *a, **kw)
        self.handshake_status = None

    def handshakeSucceeded(self, init_ts, hs_delay):

        self.handshake_status = 'ok'