예제 #1
0
 def test_simplePayload(self):
     m = WCMessage(WCMessage.TYPE_RESPONSE, 5, 7680, 1000, 2000, 3000)
     payload = m.pack()
     self.assertEqual(
         payload,
         "\x00\x01\x05\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x03\xe8\x00\x00\x00\x00\x00\x00\x07\xd0\x00\x00\x00\x00\x00\x00\x0b\xb8"
     )
예제 #2
0
 def test_simplePayloadOverridingOriginate(self):
     m = WCMessage(WCMessage.TYPE_RESPONSE, 5, 12160, 1000, 2000, 3000,
                   (0xaabbccdd, 0xeeff1122))
     payload = m.pack()
     self.assertEqual(
         payload,
         "\x00\x01\x05\x00\x00\x00\x2f\x80\xaa\xbb\xcc\xdd\xee\xff\x11\x22\x00\x00\x00\x00\x00\x00\x07\xd0\x00\x00\x00\x00\x00\x00\x0b\xb8"
     )
예제 #3
0
파일: wc.py 프로젝트: Omi-Jiang/pydvbcss
 def handle(self, socket, data, srcaddr):
     recv_ticks, tickrate=self.clock.ticks, self.clock.tickRate
     
     msg=WCMessage.unpack(data)
     reply=msg.copy()
     if msg.msgtype==WCMessage.TYPE_REQUEST:
         reply.receiveNanos = recv_ticks * 1000000000 / tickrate
     
         if self.followup:
             reply.msgtype = WCMessage.TYPE_RESPONSE_WITH_FOLLOWUP
         else:
             reply.msgtype = WCMessage.TYPE_RESPONSE
         reply.setPrecision(self.precision)
         reply.setMaxFreqError(self.maxFreqErrorPpm)
         reply.transmitNanos = self.clock.ticks * 1000000000 / tickrate
         socket.sendto(reply.pack(), srcaddr)
         
         if self.followup:
             followupReply = reply.copy()
             followupReply.transmitNanos = self.clock.ticks * 1000000000 / tickrate
             followupReply.msgtype = WCMessage.TYPE_FOLLOWUP
             socket.sendto(followupReply.pack(), srcaddr)
         
         self.log.debug("Received :"+str(msg)+"\n")
         self.log.info("Responding to request from %s port %d with originate time=%20d ns" % (srcaddr[0], srcaddr[1], msg.originateNanos))
         self.log.debug("Response :"+str(reply)+"\n")
         if self.followup:
             self.log.debug("Followed by:"+str(followupReply)+"\n")
     else:
         raise ValueError("Wall clock server received non request message")
예제 #4
0
    def handle(self, socket, data, srcaddr):
        recv_ticks, tickrate = self.clock.ticks, self.clock.tickRate

        msg = WCMessage.unpack(data)
        reply = msg.copy()
        if msg.msgtype == WCMessage.TYPE_REQUEST:
            reply.receiveNanos = recv_ticks * 1000000000 / tickrate

            if self.followup:
                reply.msgtype = WCMessage.TYPE_RESPONSE_WITH_FOLLOWUP
            else:
                reply.msgtype = WCMessage.TYPE_RESPONSE
            reply.setPrecision(self.precision if self.precision is not None
                               else self.clock.dispersionAtTime(recv_ticks))
            reply.setMaxFreqError(self.maxFreqErrorPpm if self.
                                  maxFreqErrorPpm is not None else self.clock.
                                  getRootMaxFreqError())
            reply.transmitNanos = self.clock.ticks * 1000000000 / tickrate
            socket.sendto(reply.pack(), srcaddr)

            if self.followup:
                followupReply = reply.copy()
                followupReply.transmitNanos = self.clock.ticks * 1000000000 / tickrate
                followupReply.msgtype = WCMessage.TYPE_FOLLOWUP
                socket.sendto(followupReply.pack(), srcaddr)

            self.log.debug("Received :" + str(msg) + "\n")
            self.log.info(
                "Responding to request from %s port %d with originate time=%20d ns"
                % (srcaddr[0], srcaddr[1], msg.originateNanos))
            self.log.debug("Response :" + str(reply) + "\n")
            if self.followup:
                self.log.debug("Followed by:" + str(followupReply) + "\n")
        else:
            raise ValueError("Wall clock server received non request message")
예제 #5
0
 def test_simpleParse(self):
     payload = "\x00\x01\x05\x00\x00\x01\xf4\x00\xaa\xbb\xcc\xdd\x3b\x9a\xc9\xff\x00\x00\x00\x00\x00\x00\x07\xd0\x00\x00\x00\x00\x00\x00\x0b\xb8"
     m = WCMessage.unpack(payload)
     self.assertEquals(m.msgtype, WCMessage.TYPE_RESPONSE)
     self.assertEquals(m.precision, 5)
     self.assertEquals(m.maxFreqError, 500 * 256)
     self.assertEquals(m.originateNanos, 2864434397999999999)
     self.assertEquals(m.receiveNanos, 2000)
     self.assertEquals(m.transmitNanos, 3000)
예제 #6
0
 def testSmokeTestCreate(self):
     m = WCMessage(WCMessage.TYPE_REQUEST, 1, 256, 2, 3, 4)
     self.assertEqual(m.msgtype, WCMessage.TYPE_REQUEST)
     self.assertEqual(m.precision, 1)
     self.assertEqual(m.maxFreqError, 256)
     self.assertEqual(m.originateNanos, 2)
     self.assertEqual(m.receiveNanos, 3)
     self.assertEqual(m.transmitNanos, 4)
     self.assertEqual(m.originalOriginate, None)
예제 #7
0
 def test_simpleParseWithUnusualOriginate(self):
     payload = "\x00\x01\x05\x00\x00\x01\xf4\x00\xaa\xbb\xcc\xdd\xee\xff\x11\x22\x00\x00\x00\x00\x00\x00\x07\xd0\x00\x00\x00\x00\x00\x00\x0b\xb8"
     m = WCMessage.unpack(payload)
     self.assertEquals(m.msgtype, WCMessage.TYPE_RESPONSE)
     self.assertEquals(m.precision, 5)
     self.assertEquals(m.maxFreqError, 500 * 256)
     self.assertEquals(m.originalOriginate, (0xaabbccdd, 0xeeff1122))
     self.assertEquals(m.receiveNanos, 2000)
     self.assertEquals(m.transmitNanos, 3000)
예제 #8
0
 def test_simpleParse(self):
     payload = "\x00\x01\x05\x00\x00\x01\xf4\x00\xaa\xbb\xcc\xdd\x3b\x9a\xc9\xff\x00\x00\x00\x00\x00\x00\x07\xd0\x00\x00\x00\x00\x00\x00\x0b\xb8"
     m=WCMessage.unpack(payload)
     self.assertEquals(m.msgtype, WCMessage.TYPE_RESPONSE)
     self.assertEquals(m.precision, 5)
     self.assertEquals(m.maxFreqError, 500*256)
     self.assertEquals(m.originateNanos, 2864434397999999999)
     self.assertEquals(m.receiveNanos, 2000)
     self.assertEquals(m.transmitNanos, 3000)
예제 #9
0
 def test_simpleParseWithUnusualOriginate(self):
     payload = "\x00\x01\x05\x00\x00\x01\xf4\x00\xaa\xbb\xcc\xdd\xee\xff\x11\x22\x00\x00\x00\x00\x00\x00\x07\xd0\x00\x00\x00\x00\x00\x00\x0b\xb8"
     m=WCMessage.unpack(payload)
     self.assertEquals(m.msgtype, WCMessage.TYPE_RESPONSE)
     self.assertEquals(m.precision, 5)
     self.assertEquals(m.maxFreqError, 500*256)
     self.assertEquals(m.originalOriginate, (0xaabbccdd, 0xeeff1122))
     self.assertEquals(m.receiveNanos, 2000)
     self.assertEquals(m.transmitNanos, 3000)
예제 #10
0
 def test_encodeMaxFreqError(self):
     self.assertEquals(WCMessage.encodeMaxFreqError(50), 12800)
     self.assertEquals(WCMessage.encodeMaxFreqError(1900), 486400)
     self.assertEquals(WCMessage.encodeMaxFreqError(0.01), 3)
     self.assertEquals(WCMessage.encodeMaxFreqError(28), 7168)
     self.assertEquals(WCMessage.encodeMaxFreqError(100000), 25600000)
     self.assertEquals(WCMessage.encodeMaxFreqError(0), 0)
예제 #11
0
 def test_decodeMaxFreqError(self):
     self.assertEquals(WCMessage.decodeMaxFreqError(12800),    50        )
     self.assertEquals(WCMessage.decodeMaxFreqError(486400),   1900      )
     self.assertEquals(WCMessage.decodeMaxFreqError(3),        0.01171875)
     self.assertEquals(WCMessage.decodeMaxFreqError(7168),     28        )
     self.assertEquals(WCMessage.decodeMaxFreqError(25600000), 100000    )
     self.assertEquals(WCMessage.decodeMaxFreqError(0),        0         )
예제 #12
0
 def test_encodeMaxFreqError(self):
     self.assertEquals(WCMessage.encodeMaxFreqError(50), 12800)
     self.assertEquals(WCMessage.encodeMaxFreqError(1900), 486400)
     self.assertEquals(WCMessage.encodeMaxFreqError(0.01), 3)
     self.assertEquals(WCMessage.encodeMaxFreqError(28), 7168)
     self.assertEquals(WCMessage.encodeMaxFreqError(100000), 25600000)
     self.assertEquals(WCMessage.encodeMaxFreqError(0), 0)
예제 #13
0
 def test_decodeMaxFreqError(self):
     self.assertEquals(WCMessage.decodeMaxFreqError(12800), 50)
     self.assertEquals(WCMessage.decodeMaxFreqError(486400), 1900)
     self.assertEquals(WCMessage.decodeMaxFreqError(3), 0.01171875)
     self.assertEquals(WCMessage.decodeMaxFreqError(7168), 28)
     self.assertEquals(WCMessage.decodeMaxFreqError(25600000), 100000)
     self.assertEquals(WCMessage.decodeMaxFreqError(0), 0)
예제 #14
0
 def test_decodePrecision(self):
     self.assertEquals(WCMessage.decodePrecision(-128), 2**-128)
     self.assertEquals(WCMessage.decodePrecision(-16), 2**-16)
     self.assertEquals(WCMessage.decodePrecision(127), 2**127)
     self.assertEquals(WCMessage.decodePrecision(-10), 2**-10)
     self.assertEquals(WCMessage.decodePrecision(-9), 2**-9)
예제 #15
0
 def test_encodePrecision(self):
     self.assertEquals(WCMessage.encodePrecision(2**-128), -128)
     self.assertEquals(WCMessage.encodePrecision(0.00001), -16)
     self.assertEquals(WCMessage.encodePrecision(2**127), 127)
     self.assertEquals(WCMessage.encodePrecision(0.0007), -10)
     self.assertEquals(WCMessage.encodePrecision(0.001), -9)
예제 #16
0
 def test_simplePayload(self):
     m=WCMessage(WCMessage.TYPE_RESPONSE, 5, 7680, 1000, 2000, 3000)
     payload=m.pack()
     self.assertEqual(payload, "\x00\x01\x05\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x03\xe8\x00\x00\x00\x00\x00\x00\x07\xd0\x00\x00\x00\x00\x00\x00\x0b\xb8")
예제 #17
0
def algorithmWrapper(dest,clock,algorithm):
    """\
    UdpRequestResponseClient handler function that wraps up the act of sending and receiving a WallClockMessage.
    Also handles the optional "follow-up" response type of message. If a response is received that indicates
    a follow-up is due, it will also wait for the follow-up. However the total time it will wait since the
    original request will not exceed the specified timeout. If only a response-promising-follow-up is received
    then that is what shall be returned.
    
    In turn, you plug an algorithm into it that is also a generator function. However that algorithm
    need only yield the timeout, and the return value will be a dict containing 2 candidate objects. One in
    nanoseconds, and the other the same but converted to tick units according to the tick rate of the
    supplied clock object. If timeout occurs the return value is None instead of a dict.
    
    Arguments:
    dest = ("<ip-addr>",port)
    clock = clock that will be used for tick rate conversion
    algorithm = a generator that yields to request a WallClock request be sent, and supplies the timeout
                for waiting for a response as the yield value
                then expects to be sent the candidate object representing the result of the request response
                
    Example algorithm:
    
      def algorithm():
          timeoutSecs=0.2
          while True:
              candidate=(yield timeoutSecs)
              if candidate is not None:
                  print "Candidate received! ",candidate["ticks"]
              else:
                  print "Timeout"
              print "Now waiting 1 second"
              time.sleep(1)
    """
    try:
        # hand control to the algorithm. when it wants a request sent, it will
        # return and supply the timeout for waiting for a response
        timeoutSecs = algorithm.next()
        while True:
            # assemble a request
            reqMsg=WCMessage(WCMessage.TYPE_REQUEST, 0, 0, clock.nanos, 0, 0)
            toSend=reqMsg.pack(), dest
            
            # we'll send the request then seek the best quality response
            # until timeout, or terminating early if we get a quality > 2
            # response (meaning that it was a non-followed-up response or a
            # follow-up response). A lower quality response is one where
            # a follow-up is expected or if it related to a previous request
            
            # this design means it will pick the best response, but in the
            # absence of a reasonable one, it will still make do with whatever
            # it can get (e.g. a response relating to an earlier request)  
             
            responseQuality   = -999
            responseMsg       = None
            responseRecvNanos = None

            timeoutBy     = time.time() + timeoutSecs
            remainingTime = timeoutBy - time.time()

            while responseQuality < 3 and remainingTime > 0:
                # wait for a response. if first time round, send the request too
                latestResponse,src = (yield toSend,remainingTime)
                toSend=None      
                
                # note when response was received
                latestResponseNanos=clock.nanos
                
                
                # did we get a response? did it come from the server we sent
                # the request to?
                if latestResponse is not None and src == dest:

                    # assess the response and work out if better than any previous
                    # response we're received
                    latestResponseMsg = WCMessage.unpack(latestResponse)
                    newQuality=calcQuality(reqMsg, latestResponseMsg) 
                    if newQuality >= responseQuality:
                        responseQuality=newQuality
                        responseMsg=latestResponseMsg
                        responseRecvNanos=latestResponseNanos
                        
                # work out how long left until timeout
                remainingTime=timeoutBy - time.time()
                        

            if responseMsg is not None:
                candidate=Candidate(responseMsg,responseRecvNanos)
                candidate={"nanos":candidate, "ticks":candidate.toTicks(clock)}
            else:
                # no message, no candidate
                candidate=None
            # pass the result to the algorithm, and wait for it to return when it
            # next wants a request to be sent (again supplying the response timeout)
            timeoutSecs=algorithm.send(candidate)
    except StopIteration:
        pass
예제 #18
0
 def test_decodePrecision(self):
     self.assertEquals(WCMessage.decodePrecision(-128), 2**-128)
     self.assertEquals(WCMessage.decodePrecision(-16),  2**-16 )
     self.assertEquals(WCMessage.decodePrecision(127),  2**127 )
     self.assertEquals(WCMessage.decodePrecision(-10),  2**-10 )
     self.assertEquals(WCMessage.decodePrecision(-9),   2**-9  )
예제 #19
0
 def test_encodePrecision(self):
     self.assertEquals(WCMessage.encodePrecision(2**-128), -128)
     self.assertEquals(WCMessage.encodePrecision(0.00001), -16 )
     self.assertEquals(WCMessage.encodePrecision(2**127),   127)
     self.assertEquals(WCMessage.encodePrecision(0.0007),  -10 )
     self.assertEquals(WCMessage.encodePrecision(0.001),   -9  )
예제 #20
0
파일: __init__.py 프로젝트: bbc/pydvbcss
def algorithmWrapper(dest, measureClock, algorithm):
    """\
    UdpRequestResponseClient handler function that wraps up the act of sending and receiving a WallClockMessage.
    Also handles the optional "follow-up" response type of message. If a response is received that indicates
    a follow-up is due, it will also wait for the follow-up. However the total time it will wait since the
    original request will not exceed the specified timeout. If only a response-promising-follow-up is received
    then that is what shall be returned.
    
    In turn, you plug an algorithm into it that is also a generator function. However that algorithm
    need only yield the timeout, and the return value will be a :class:`~dvbcss.protocol.wc.Candidate`
    object in units of nanoseconds. If timeout occurs the return value is None instead of a dict.
    
    :param dest: ("<ip-addr>",port) The destination address of the server (to which the requests should be sent)
    :param measureClock: The :mod:`~dvbcss:Clock` from which the readings are taken (being `t1` and `t4` in the resulting candidate)
    :param algorithm: A generator that yields to request a WallClock request be sent, and acts on the responses.
    
    The generator function you provide, should use `yield` as follows:
    * to pass the timeout for waiting for a response as the yield value
    * to receive a :class:`~dvbcss.protocol.wc.Candidate` object representing the response.
                
    Example algorithm:
    
    .. code-block:: python
    
      def algorithm():
          timeoutSecs=0.2
          while True:
              candidate=(yield timeoutSecs)
              if candidate is not None:
                  print "Candidate received! ",candidate
              else:
                  print "Timeout"
              print "Now waiting 1 second"
              time.sleep(1)
              
       sysClock = SysClock()
       wallClock = CorrelatedClock(sysClock, tickRate=1000000000)
              
       algWrapper = algorithmWrapper(destIpPort, sysClock, wallClock, algorithm())
       
    """
    try:
        # hand control to the algorithm. when it wants a request sent, it will
        # return and supply the timeout for waiting for a response
        timeoutSecs = algorithm.next()
        while True:
            # assemble a request
            reqMsg = WCMessage(WCMessage.TYPE_REQUEST, 0, 0,
                               measureClock.nanos, 0, 0)
            toSend = reqMsg.pack(), dest

            # we'll send the request then seek the best quality response
            # until timeout, or terminating early if we get a quality > 2
            # response (meaning that it was a non-followed-up response or a
            # follow-up response). A lower quality response is one where
            # a follow-up is expected or if it related to a previous request

            # this design means it will pick the best response, but in the
            # absence of a reasonable one, it will still make do with whatever
            # it can get (e.g. a response relating to an earlier request)

            responseQuality = -999
            responseMsg = None
            responseRecvNanos = None

            timeoutBy = time.time() + timeoutSecs
            remainingTime = timeoutBy - time.time()

            while responseQuality < 3 and remainingTime > 0:
                # wait for a response. if first time round, send the request too
                latestResponse, src = (yield toSend, remainingTime)
                toSend = None

                # note when response was received
                latestResponseNanos = measureClock.nanos

                # did we get a response? did it come from the server we sent
                # the request to?
                if latestResponse is not None and src == dest:

                    # assess the response and work out if better than any previous
                    # response we're received
                    latestResponseMsg = WCMessage.unpack(latestResponse)
                    newQuality = calcQuality(reqMsg, latestResponseMsg)
                    if newQuality >= responseQuality:
                        responseQuality = newQuality
                        responseMsg = latestResponseMsg
                        responseRecvNanos = latestResponseNanos

                # work out how long left until timeout
                remainingTime = timeoutBy - time.time()

            if responseMsg is not None:
                candidate = Candidate(responseMsg, responseRecvNanos)
            else:
                # no message, no candidate
                candidate = None
            # pass the result to the algorithm, and wait for it to return when it
            # next wants a request to be sent (again supplying the response timeout)
            timeoutSecs = algorithm.send(candidate)
    except StopIteration:
        pass
예제 #21
0
 def test_simplePayloadOverridingOriginate(self):
     m=WCMessage(WCMessage.TYPE_RESPONSE, 5, 12160, 1000, 2000, 3000, (0xaabbccdd, 0xeeff1122))
     payload=m.pack()
     self.assertEqual(payload, "\x00\x01\x05\x00\x00\x00\x2f\x80\xaa\xbb\xcc\xdd\xee\xff\x11\x22\x00\x00\x00\x00\x00\x00\x07\xd0\x00\x00\x00\x00\x00\x00\x0b\xb8")