Added hidemmsi option for outpeers
[ais.git] / bin / inputs / config.py
1 # -*- coding: utf-8 -*-
2 '''
3 Peers definition
4 '''
5
6 from __future__ import division
7 import logging
8 import pprint
9 from ais.ntools import str_split_column_ipv6
10
11 __all__ = [
12     'peers_get_config',
13     'source_get_infoin']
14
15 CONFIG_FILENAME = '/etc/ais/config'
16
17 SOURCES = {}
18
19 __source_normalized__ = False
20 def peers_get_config():
21     '''
22     SOURCES normalization & checks
23     '''
24     global __source_normalized__
25     if __source_normalized__:
26         return SOURCES
27
28     config_file = file(CONFIG_FILENAME)
29     for lineno_e, line in enumerate(config_file.readlines()):
30         lineno = lineno_e + 1
31         #logging.debug('considering line #%s: %s', lineno, repr(line))
32         line = line.strip(' \r\n')
33         if len(line)==0 or line[0]=='#':
34             logging.debug('ignoring line #%s: %s', lineno, repr(line))
35             continue
36         spl = line.split(' ', 2)
37         assert len(spl) == 3, \
38             'line #%s: There should be at least 3 strings sepatated by spaces' % \
39             lineno
40         id4, io, definition = spl
41         assert len(id4)==4, 'source name (first parameter) must be 4 char long.'
42         logging.debug('%s %s %s', id4, io, definition)
43         if id4 not in SOURCES:
44             SOURCES[id4] = {}
45         if io == 'in':
46             assert len(spl)==3, \
47                 'line #%s: missing information after \'in\'' % \
48                 lineno
49             SOURCES[id4]['in'] = definition
50         elif io ==  'out':
51             assert len(spl)==3, \
52                 'line #%s: missing information after \'out\'' % \
53                 lineno
54             if not SOURCES[id4].has_key('out'):
55                 SOURCES[id4]['out'] = []
56             spl = definition.split(' ')
57             SOURCES[id4]['out'].append(spl)
58         elif io ==  'name':
59             SOURCES[id4]['name'] = definition
60         else:
61             raise AssertionError( \
62                 "line #%s: second parameter must be either 'in' or 'out'.\r%s" % \
63                 (lineno, line))
64
65     logging.debug('SOURCES \n%s', pprint.pformat(SOURCES))
66
67     logging.debug('SOURCES (raw):\n%s', pprint.pformat(SOURCES))
68     for id4, settings in SOURCES.iteritems():
69         assert len(id4) == 4, \
70             'Invalid ID %s in SOURCES. It should be 4 characters long.'
71
72         if 'name' not in settings:
73             settings['name'] =id4
74         try:
75             in_ = settings['in']
76         except KeyError:
77             continue
78     
79         assert type(in_) == str, \
80             "SOURCES['%s']['in'] should be of type str, not %s'." % \
81             (id4, type(in_))
82         in_ = settings.get('in')
83         spl = str_split_column_ipv6(in_)
84         protocol, parameters = spl[0], spl[1:]
85         assert parameters, \
86             "SOURCES['%s']['in'] should contain parameters after %s" % \
87             (id4, protocol)
88            
89         if protocol == 'udp':
90             assert len(parameters) == 4, \
91                 "SOURCES['%s']['in'] udp: protocol requires 4 parameters." % \
92                 id4
93             host_local = parameters[0]
94             if host_local == '*':
95                 host_local = ''
96             port_local = parameters[1]
97             assert port_local.isdigit(), \
98                 "SOURCES['%s']['in'] udp: illegal local port" % \
99                 id4
100             port_local = int(port_local)
101             host_remote = parameters[2]
102             if host_remote == '*':
103                 host_remote = ''
104             port_remote = parameters[3]
105             source_port_discreminate = False
106             if port_remote == '*':
107                 port_remote = ''
108             elif port_remote == '!':
109                 port_remote = ''
110                 source_port_discreminate = True
111             else:
112                 assert port_remote.isdigit(), \
113                     "SOURCES['%s']['in'] udp: illegal remote port" % \
114                     id4
115                 port_remote = int(port_remote)
116          
117             SOURCES[id4]['in'] = (protocol.title(), host_local, port_local, host_remote, port_remote, source_port_discreminate)
118
119         elif protocol == 'serial':
120             assert len(parameters) == 1, \
121                 "SOURCES['%s']['in'] serial: protocol requires 1 parameter." % \
122                 id4
123             SOURCES[id4]['in'] = tuple(['Serial'] + parameters)
124
125         elif protocol == 'tcpout':
126             assert len(parameters) == 2, \
127                 "SOURCES['%s']['in'] tcpout: protocol requires 2 parameters." % \
128                 id4
129             host = parameters[0]
130             port = int(parameters[1])
131             SOURCES[id4]['in'] = ('TcpOut', host, port)
132
133         else:
134             logging.error(
135                 "Unsupported source protocol '%s' for SOURCES['%s']: %s",
136                 protocol, id4, in_)
137     __source_normalized__ = True
138     logging.debug('SOURCES (normalised):\n%s', pprint.pformat(SOURCES))
139     return SOURCES
140
141
142
143 def source_get_infoin(*args):
144     '''
145     Gets a list of matching info in SOURCES[*]['in']:
146     example: get_source_infoin('Udp', '', 1234)
147       might return [ ['SRC1', '12.23.34.45', '', False],
148                      ['SRC2', '98.87.76.65', '', True]]
149     '''
150     result = []
151     for id4, source_info in peers_get_config().iteritems():
152         rawin = source_info.get('in', None)
153         if not rawin:
154             continue
155         if args == rawin[:len(args)]:
156             newmatch = [id4] + [rawin[i] for i in range(len(args), len(rawin))]
157             result.append(newmatch)
158     return result
159         
160