Exemple #1
0
    def on_message(self, message):
        # called in tornado's thread
        if self._writeable is None:
            ipv4_ip = self.request.remote_ip
            if ipv4_ip == "::1":
                # Special case IPV6 loopback
                ipv4_ip = "127.0.0.1"
            remoteaddr = struct.unpack("!I", socket.inet_aton(ipv4_ip))[0]
            if self._validators:
                # Work out if the remote ip is within the netmask of any of our
                # interfaces. If not, Put and Post are forbidden
                self._writeable = max(v(remoteaddr) for v in self._validators)
            else:
                self._writeable = True
            log.info(
                "Puts and Posts are %s from %s",
                "allowed" if self._writeable else "forbidden",
                self.request.remote_ip,
            )

        msg_id = -1
        try:
            d = json_decode(message)
            try:
                msg_id = d["id"]
            except KeyError:
                raise FieldError("id field not present in JSON message")
            request = deserialize_object(d, Request)
            request.set_callback(self.on_response)
            if isinstance(request, Subscribe):
                assert msg_id not in self._id_to_mri, (
                    "Duplicate subscription ID %d" % msg_id
                )
                self._id_to_mri[msg_id] = request.path[0]
            if isinstance(request, Unsubscribe):
                mri = self._id_to_mri[msg_id]
            else:
                mri = request.path[0]
            if isinstance(request, (Put, Post)) and not self._writeable:
                raise ValueError(
                    "Put/Post is forbidden from %s" % self.request.remote_ip
                )
            self._registrar.report(builtin.infos.RequestInfo(request, mri))
        except Exception as e:
            log.exception("Error handling message:\n%s", message)
            error = Error(msg_id, e)
            error_message = error.to_dict()
            self.write_message(json_encode(error_message))
Exemple #2
0
 def callback(value=None):
     # TODO: ordering is not maintained here...
     # TODO: should we strip_tuples here?
     d = value.toDict(True)
     if d.get("typeid", "") == Error.typeid:
         response = Error(request.id, d["message"])
         self._monitors.pop(request.generate_key())
         channel.unsubscribe("")
     else:
         # TODO: support Deltas properly
         if request.delta:
             response = Delta(request.id, [[[], d]])
         else:
             response = Update(request.id, d)
     request.callback(response)
Exemple #3
0
 def _report_fault(self):
     # Called in cothread thread
     with self._lock:
         if self.state.value != self.state_set.DISABLING:
             self.transition(self.state_set.FAULT, "Server disconnected")
     self._connected_queue.put(None)
     for id in list(self._request_lookup):
         request = self._request_lookup.pop(id)
         response = Error(id=request.id,
                          message=ResponseError("Server disconnected"))
         try:
             request.callback(response)
         except Exception:
             # Most things will error here, not really a problem
             self.log.debug("Callback %s raised", request.callback)
Exemple #4
0
 def recv_loop(self):
     url = "ws://%(hostname)s:%(port)d/ws" % self.params
     self._conn = yield websocket_connect(
         url, self.loop, connect_timeout=self.params.connectTimeout - 0.5)
     self._connected_queue.put(True)
     for request in self._subscription_keys.values():
         self._send_request(request)
     while True:
         message = yield self._conn.read_message()
         if message is None:
             for request, old_id in self._request_lookup.values():
                 if not isinstance(request, Subscribe):
                     # Respond with an error
                     response = Error(old_id, message="Server disconnected")
                     request.callback(response)
             self.spawn(self._report_fault)
             return
         self.on_message(message)
Exemple #5
0
 def _pv_error_structure(self, exception):
     """Make an error structure in lieu of actually being able to raise"""
     error = Error(message=str(exception)).to_dict()
     error.pop("id")
     return dict_to_pv_object(error)
Exemple #6
0
 def _response_from_dict(self, request, d):
     if d.get("typeid", "") == Error.typeid:
         response = Error(request.id, d["message"])
     else:
         response = Return(request.id, d)
     return response