summaryrefslogtreecommitdiff
path: root/oslo_messaging/_drivers/zmq_driver/zmq_serializer.py
blob: 41663f63928db11e68e3baa6da7c8f718a08c61d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#    Copyright 2015 Mirantis, Inc.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import logging
import os
import re

import six

from oslo_messaging._drivers import common as rpc_common
from oslo_messaging._i18n import _LE, _LW

LOG = logging.getLogger(__name__)

MESSAGE_CALL_TYPE_POSITION = 1
MESSAGE_CALL_TARGET_POSITION = 2
MESSAGE_CALL_TOPIC_POSITION = 3

FIELD_FAILURE = 'failure'
FIELD_REPLY = 'reply'
FIELD_LOG_FAILURE = 'log_failure'

CALL_TYPE = 'call'
CAST_TYPE = 'cast'
FANOUT_TYPE = 'fanout'
NOTIFY_TYPE = 'notify'

MESSAGE_TYPES = (CALL_TYPE, CAST_TYPE, FANOUT_TYPE, NOTIFY_TYPE)


def get_msg_type(message):
    type = message[MESSAGE_CALL_TYPE_POSITION]
    if type not in MESSAGE_TYPES:
        errmsg = _LE("Unknown message type: %s") % str(type)
        LOG.error(errmsg)
        raise rpc_common.RPCException(errmsg)
    return type


def _get_topic_from_msg(message, position):
    pathsep = set((os.path.sep or '', os.path.altsep or '', '/', '\\'))
    badchars = re.compile(r'[%s]' % re.escape(''.join(pathsep)))

    if len(message) < position + 1:
        errmsg = _LE("Message did not contain a topic")
        LOG.error("%s: %s" % (errmsg, message))
        raise rpc_common.RPCException("%s: %s" % (errmsg, message))

    topic = message[position]

    if six.PY3:
        topic = topic.decode('utf-8')

    # The topic is received over the network, don't trust this input.
    if badchars.search(topic) is not None:
        errmsg = _LW("Topic contained dangerous characters")
        LOG.warn("%s: %s" % (errmsg, topic))
        raise rpc_common.RPCException("%s: %s" % (errmsg, topic))

    topic_items = topic.split('.', 1)

    if len(topic_items) != 2:
        errmsg = _LE("Topic was not formatted correctly")
        LOG.error("%s: %s" % (errmsg, topic))
        raise rpc_common.RPCException("%s: %s" % (errmsg, topic))

    return topic_items[0], topic_items[1]


def get_topic_from_call_message(message):
    """Extract topic and server from message.

    :param message: A message
    :type message: list

    :returns: (topic: str, server: str)
    """
    return _get_topic_from_msg(message, MESSAGE_CALL_TOPIC_POSITION)


def get_target_from_call_message(message):
    """Extract target from message.

    :param message: A message
    :type message: list

    :returns: target: Target
    """
    return message[MESSAGE_CALL_TARGET_POSITION]