PublishRequest, TimeoutHint, and freeopcua
The TimeoutHint
field of the RequestHeader
of outgoing requests (client-side Toolkit) is set to a non-configurable value of 0 in message_out_bs__encode_msg
:
reqHeader->TimeoutHint = 0;
The OPC-UA specification states, in Part 4, §7.28:
The value of 0 indicates no timeout.
In the python implementation of freeopcua used in the validation test, such a Timeout is considered valid but null. As a consequence, a PublishRequest
sent with a null timeout times out instantly, effectively losing the PublishRequest
. This can be seen in our version of freeopcua, in uaprocessor.py
(Link) in the function that pops PublishRequests
:
def forward_publish_response(self, result):
self.logger.info("forward publish response %s", result)
with self._datalock:
while True:
if len(self._publishdata_queue) == 0:
self._publish_result_queue.append(result)
self.logger.info("Server wants to send publish answer but no publish request is available,"
"enqueing notification, length of result queue is %s",
len(self._publish_result_queue))
return
requestdata = self._publishdata_queue.pop(0)
if time.time() - requestdata.timestamp < requestdata.requesthdr.TimeoutHint / 1000:
break
response = ua.PublishResponse()
response.Parameters = result
self.send_response(requestdata.requesthdr.RequestHandle, requestdata.algohdr, requestdata.seqhdr, response)
This if
does not break on a null timeout hint. In more recent version of freeopcua, it does, effectively bypassing the timeout hint when the value is 0.
The question is to decide what to do now in one of the multiple options (not exhaustive):
- make
reqHeader->TimeoutHint
configurable instead of0
, - set
reqHeader->TimeoutHint
to the constantSOPC_REQUEST_TIMEOUT_MS
, - upgrade to a newer version of freeopcua, which might have other side-effects on tests.