+ """In a sync call, wait for the reply
+
+ The context ID is used to pair reply to request.
+ """
+
+ # Results is filled by the background callback. It will
+ # raise the event when the context receives a response.
+ # Given there are two threads we have to be careful with the
+ # use of results and the structures under it, hence the lock.
+ with self.results_lock:
+ result = self.results[context]
+ ev = result['e']
+
+ timed_out = not ev.wait(self.timeout)
+
+ if timed_out:
+ raise IOError(3, 'Waiting for reply timed out')
+ else:
+ with self.results_lock:
+ result = self.results[context]
+ del self.results[context]
+ return result['r']
+
+ def results_prepare(self, context, multi=False):
+ """Prep for receiving a result in response to a request msg
+
+ context - unique context number sent in request and
+ returned in reply or replies
+ multi - true if we expect multiple messages from this
+ reply.
+ """
+
+ # The event is used to indicate that all results are in
+ new_result = {
+ 'e': threading.Event(),
+ }
+ if multi:
+ # Make it clear to the BG thread it's going to see several
+ # messages; messages are stored in a results array
+ new_result['m'] = True
+ new_result['r'] = []
+
+ new_result['e'].clear()
+
+ # Put the prepped result structure into results, at which point
+ # the bg thread can also access it (hence the thread lock)
+ with self.results_lock:
+ self.results[context] = new_result
+
+ def msg_handler_sync(self, msg):
+ """Process an incoming message from VPP in sync mode.
+
+ The message may be a reply or it may be an async notification.
+ """
+ r = self.decode_incoming_msg(msg)
+ if r is None:
+ return
+
+ # If we have a context, then use the context to find any
+ # request waiting for a reply
+ context = 0
+ if hasattr(r, 'context') and r.context > 0:
+ context = r.context