'Event handler for reception of an Iq with set req - this is a
control request.
Verifies that
- all the requested nodes are available
(if no nodes are specified in the request, assume all nodes)
- all the control fields are available from all requested nodes
(if no nodes are specified in the request, assume all nodes)
If the request passes verification, the control request is passed
to the devices (in a separate thread).
If the verification fails, a setResponse with error indication
is sent.'

def _handle_set_req(self, iq):

    error_msg = ''
    req_ok = True
    missing_node = None
    missing_field = None
    if ((len(self.test_authenticated_from) > 0) and (not (iq['from'] == self.test_authenticated_from))):
        req_ok = False
        error_msg = 'Access    denied'
    if (len(iq['set']['nodes']) > 0):
        for n in iq['set']['nodes']:
            if (not (n['nodeId'] in self.nodes)):
                req_ok = False
                missing_node = n['nodeId']
                error_msg = ('Invalid    nodeId    ' + n['nodeId'])
        process_nodes = [n['nodeId'] for n in iq['set']['nodes']]
    else:
        process_nodes = self.nodes.keys()
    process_fields = []
    if (len(iq['set']['datas']) > 0):
        for f in iq['set']['datas']:
            for node in self.nodes:
                if (not self.nodes[node]['device'].has_control_field(f['name'], f._get_typename())):
                    req_ok = False
                    missing_field = f['name']
                    error_msg = ('Invalid    field    ' + f['name'])
                    break
        process_fields = [(f['name'], f._get_typename(), f['value']) for f in iq['set']['datas']]
    if req_ok:
        session = self._new_session()
        self.sessions[session] = {'from': iq['from'], 'to': iq['to'], 'seqnr': iq['id']}
        self.sessions[session]['commTimers'] = {}
        self.sessions[session]['nodeDone'] = {}
        self.sessions[session]['reply'] = True
        self.sessions[session]['node_list'] = process_nodes
        if self.threaded:
            tr_req = Thread(target=self._threaded_node_request, args=(session, process_fields))
            tr_req.start()
        else:
            self._threaded_node_request(session, process_fields)
    else:
        iq.reply()
        iq['type'] = 'error'
        iq['setResponse']['responseCode'] = 'NotFound'
        if (missing_node is not None):
            iq['setResponse'].add_node(missing_node)
        if (missing_field is not None):
            iq['setResponse'].add_data(missing_field)
        iq['setResponse']['error']['var'] = 'Output'
        iq['setResponse']['error']['text'] = error_msg
        iq.send(block=False)
