Details | Last modification | View Log | SVN | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 736 | olof | 1 | #!/bin/env python |
| 2 | |||
| 3 | import os |
||
| 4 | import sys |
||
| 5 | import logging as log |
||
| 6 | import getopt |
||
| 7 | import atexit |
||
| 738 | olof | 8 | import time |
| 736 | olof | 9 | |
| 10 | from CanPktHandlerBase import CanPktHandlerBase |
||
| 11 | from CanPktHandler1 import CanPktHandler1 |
||
| 12 | |||
| 13 | from NodeIfBase import NodeIfBase |
||
| 14 | from NodeIfCanStim import NodeIfCanStim |
||
| 15 | from NodeIfSerial import NodeIfSerial |
||
| 16 | |||
| 17 | from DaemonConfig import DaemonConfig |
||
| 18 | |||
| 19 | daemonApp = None |
||
| 20 | |||
| 21 | class CanDaemon(): |
||
| 22 | |||
| 23 | nodeIf = None |
||
| 738 | olof | 24 | ifNotifier = None |
| 25 | terminated = False |
||
| 739 | olof | 26 | command_list = [] |
| 27 | |||
| 28 | def __init__ (self): |
||
| 29 | pass |
||
| 736 | olof | 30 | |
| 738 | olof | 31 | class IfNotifier(): |
| 739 | olof | 32 | """ Used by if threads to send messages to the main program thread """ |
| 738 | olof | 33 | UNDEFINED = 0 |
| 34 | TERMINATE = 1 |
||
| 35 | |||
| 36 | def notify(self, msg): |
||
| 37 | if msg == self.TERMINATE: |
||
| 38 | print 'Main terminate notify' |
||
| 39 | self.terminated = True |
||
| 40 | else: |
||
| 41 | print 'UNDEFINED NOTIFY' |
||
| 42 | |||
| 739 | olof | 43 | |
| 44 | def __rightAdjust(self, refstr, str): |
||
| 45 | spcstr = '' |
||
| 46 | endpos = 20-len(refstr) |
||
| 47 | for i in range(1,endpos): |
||
| 48 | if i == endpos-5: |
||
| 49 | spcstr += ':' |
||
| 50 | else: |
||
| 51 | spcstr += ' ' |
||
| 52 | return (spcstr+str) |
||
| 53 | |||
| 54 | def helpCmd(self, *args): |
||
| 55 | quitStr = 'quit, exit' |
||
| 56 | # print quitStr, self.__rightAdjust(quitStr, 'shutdown pyCanDaemon') |
||
| 57 | # for cmd in cmdNames: |
||
| 58 | # print cmd, self.__rightAdjust(cmd, command_map[cmd][1]) |
||
| 59 | |||
| 60 | def filterCmd(self, *args): |
||
| 736 | olof | 61 | pass |
| 62 | |||
| 739 | olof | 63 | def stateCmd(self, *args): |
| 64 | pass |
||
| 736 | olof | 65 | |
| 739 | olof | 66 | def ifAddCmd(self, *args): |
| 736 | olof | 67 | pass |
| 68 | |||
| 739 | olof | 69 | def ifRemCmd(self, *args): |
| 70 | pass |
||
| 736 | olof | 71 | |
| 739 | olof | 72 | def ifUpCmd(self, *args): |
| 73 | pass |
||
| 736 | olof | 74 | |
| 739 | olof | 75 | def ifDownCmd(self, *args): |
| 76 | pass |
||
| 736 | olof | 77 | |
| 739 | olof | 78 | def addBridgeCmd(self, *args): |
| 79 | pass |
||
| 80 | |||
| 81 | def remBridgeCmd(self, *args): |
||
| 82 | pass |
||
| 83 | |||
| 84 | def tcpdCmd(self, *args): |
||
| 85 | pass |
||
| 86 | |||
| 87 | def tlsdCmd(self, *args): |
||
| 88 | pass |
||
| 89 | |||
| 90 | def canCtldCmd(self, *args): |
||
| 91 | pass |
||
| 92 | |||
| 93 | def statusCmd(self, *args): |
||
| 94 | pass |
||
| 95 | |||
| 96 | def statsCmd(self, *args): |
||
| 97 | pass |
||
| 98 | |||
| 99 | def nodesCmd(self, *args): |
||
| 100 | pass |
||
| 101 | |||
| 102 | def filterlistCmd(self, *args): |
||
| 103 | pass |
||
| 104 | |||
| 105 | def simCmd(self, *args): |
||
| 106 | pass |
||
| 107 | |||
| 108 | def logCmd(self, *args): |
||
| 109 | pass |
||
| 110 | |||
| 111 | def execCmd(self, *args): |
||
| 112 | pass |
||
| 113 | |||
| 736 | olof | 114 | def exitHelper(self): |
| 737 | olof | 115 | if self.nodeIf is not None and self.nodeIf.running(): |
| 736 | olof | 116 | self.nodeIf.stop() |
| 739 | olof | 117 | |
| 118 | def exceptHelper(self, type, value, tb): |
||
| 119 | import traceback |
||
| 120 | traceback.print_exception(type, value, tb) |
||
| 121 | print '\nException in main program, shutting down threads' |
||
| 122 | self.terminated = True |
||
| 123 | self.exitHelper() |
||
| 124 | # sys.exit(-1) |
||
| 125 | |||
| 736 | olof | 126 | def run(self): |
| 127 | try: |
||
| 128 | demoPath = os.path.dirname(__file__) |
||
| 129 | os.chdir(demoPath) |
||
| 130 | except: |
||
| 131 | return |
||
| 132 | |||
| 737 | olof | 133 | print 'INIT: Start logging' |
| 736 | olof | 134 | log.basicConfig(level=log.DEBUG) |
| 135 | |||
| 737 | olof | 136 | print 'INIT: Get config options from command line / config file' |
| 736 | olof | 137 | cfg = DaemonConfig() |
| 138 | |||
| 139 | try: |
||
| 140 | opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="]) |
||
| 141 | except getopt.GetoptError: |
||
| 142 | print 'Invalid usage' |
||
| 143 | usage() |
||
| 144 | sys.exit(2) |
||
| 145 | # output = None |
||
| 146 | # verbose = False |
||
| 147 | for o, a in opts: |
||
| 148 | if o == "-v": |
||
| 149 | pass |
||
| 150 | # verbose = True |
||
| 151 | if o in ("-h", "--help"): |
||
| 152 | usage() |
||
| 153 | sys.exit() |
||
| 154 | if o in ("-o", "--output"): |
||
| 155 | pass |
||
| 156 | # output = a |
||
| 157 | |||
| 737 | olof | 158 | print 'INIT: Loading filters and spaces' |
| 738 | olof | 159 | # cfg.filterCfg.importFilter('DefaultFilter') |
| 160 | # cfg.stateSpaceCfg.importSpace('DefaultStateSpace') |
||
| 736 | olof | 161 | cfg.stateSpaceCfg.loadSpaces() |
| 162 | cfg.filterCfg.loadFilters() |
||
| 163 | cfg.setupFilterBindings() |
||
| 164 | cfg.setupFilterChain() |
||
| 737 | olof | 165 | |
| 166 | print 'INIT: Starting selected can interface' |
||
| 736 | olof | 167 | ''' nodeif thread launch ''' |
| 738 | olof | 168 | self.ifNotifier = self.IfNotifier() |
| 736 | olof | 169 | pktHandler = CanPktHandler1(cfg) |
| 170 | |||
| 738 | olof | 171 | ifConfig = NodeIfCanStim.DEFAULT_CONFIG |
| 172 | self.nodeIf = NodeIfCanStim(ifConfig, pktHandler, self.ifNotifier) |
||
| 173 | # ifConfig = NodeIfSerial.DEFAULT_CONFIG |
||
| 736 | olof | 174 | |
| 737 | olof | 175 | atexit.register(self.exitHelper) |
| 739 | olof | 176 | sys.excepthook = self.exceptHelper |
| 738 | olof | 177 | # self.nodeIf = NodeIfSerial(pktHandler, ifConfig) |
| 736 | olof | 178 | |
| 179 | if not self.nodeIf.start(): |
||
| 737 | olof | 180 | print 'FATAL: Failed to initialize node interface.' |
| 738 | olof | 181 | print 'This may indicate that the interface is unavailable, ' \ |
| 182 | 'or that you do not have permission to access it.' |
||
| 736 | olof | 183 | sys.exit(-1) |
| 184 | |||
| 185 | print 'Initialize/gather info on connected can nodes and load associated state' |
||
| 186 | print 'Start selected TCP and UDP server(s)' |
||
| 187 | # server threads launch |
||
| 188 | |||
| 189 | print 'CanDaemon v1 ready' |
||
| 190 | print 'Enter command or type \"help\" for a list of commands' |
||
| 739 | olof | 191 | |
| 192 | global command_map |
||
| 193 | command_map = {'help' : (self.helpCmd, 'display help'), |
||
| 194 | 'filter' : (self.filterCmd, 'filter commands: \"help filter\"'), |
||
| 195 | 'state' : (self.stateCmd, 'state commands: \"help state\"'), |
||
| 196 | 'addif' : (self.ifAddCmd, 'add interface: \"help addif\"'), |
||
| 197 | 'remif' : (self.ifRemCmd, 'remove interface <name>'), |
||
| 198 | 'ifup' : (self.ifUpCmd, 'bring up interface <name>'), |
||
| 199 | 'ifdown' : (self.ifDownCmd, 'bring down interface <name>'), |
||
| 200 | # 'addbrigde' : (self.addBridgeCmd, 'add bridge: \"help addbridge\"'), |
||
| 201 | # 'rembridge' : (self.remBridgeCmd, 'remove bridge <name>'), |
||
| 202 | 'tcpd' : (self.tcpdCmd, 'tcpd server control: \"help tcpd\"'), |
||
| 203 | # 'tlsd' : (self.tlsdCmd, 'tlsd server control: \"help tlsd\"'), |
||
| 204 | # 'canctld' : (self.canCtldCmd, 'canctld server control: \"help canctld\"'), |
||
| 205 | # 'status' : (self.statusCmd, 'show daemon status'), |
||
| 206 | # 'stats' : (self.statsCmd, 'show statistics'), |
||
| 207 | # 'nodelist' : (self.nodesCmd, 'list can nodes'), |
||
| 208 | # 'filterlist' : (self.filterlistCmd, 'list active filters'), |
||
| 209 | # 'sim' : (self.simCmd, 'simulator commands: \"help sim\"'), |
||
| 210 | # 'log' : (self.logCmd, 'log control: \"help log\"'), |
||
| 211 | # 'exec' : (self.execCmd, 'run command listing <filename>')} |
||
| 738 | olof | 212 | |
| 213 | while not self.terminated: |
||
| 736 | olof | 214 | input = raw_input('> ').strip().lower() |
| 739 | olof | 215 | cmd = input.split(' ') |
| 216 | if cmd[0] == 'quit' or cmd[0] == 'exit': |
||
| 738 | olof | 217 | self.terminated = True |
| 739 | olof | 218 | elif command_map.has_key(cmd[0]): |
| 219 | command_map[cmd[0]][0](cmd[1:]) |
||
| 738 | olof | 220 | else: |
| 739 | olof | 221 | print 'Unknown command: ' + cmd[0] |
| 222 | |||
| 223 | """ -- suggested commands -- p n = priority to implement (1 is highest) |
||
| 224 | base: (p 1) |
||
| 225 | filter add <name> |
||
| 226 | filter rem <name> |
||
| 227 | state add <name> |
||
| 228 | state rem <name> |
||
| 229 | state reset <name> |
||
| 230 | |||
| 231 | node interfaces: (p 1) |
||
| 232 | addif <serial/sim/udp/telnet> <options> (help protocol gives options) |
||
| 233 | remif <name> - delete an interface |
||
| 234 | ifup <name> - bring up an interface |
||
| 235 | ifdown <name> - bring down an interface |
||
| 236 | |||
| 237 | bridging: (p 2) |
||
| 238 | addbridge <name> <ifname1> <ifname2> <ifname3> ... - create if bridge |
||
| 239 | rembridge <name> |
||
| 240 | |||
| 241 | servers: |
||
| 242 | tcpd start [port] - raw tcp (telnet, compat) server, all pkts (p 1) |
||
| 243 | tcpd stop |
||
| 244 | tlsd start [port] - tcp+tls server, all pkts (p 2) |
||
| 245 | tlsd stop |
||
| 246 | canctld start [port] - pyCanGUI server (tcp/tls) (p 2) |
||
| 247 | canctld stop |
||
| 248 | |||
| 249 | info commands: (p 3) |
||
| 250 | status - shows active settings, interfaces, servers |
||
| 251 | stats - shows some traffic statistics |
||
| 252 | nodes - shows active nodes |
||
| 253 | filters - shows active filters |
||
| 254 | state [name] - shows active states, opt specific state info\ |
||
| 255 | log - log control (TBD) |
||
| 256 | |||
| 257 | simulator commands: (p 2) |
||
| 258 | simrecord <file> - record incoming packets |
||
| 259 | simplay <file> [timescale] - play recorded stream, opt accel time: |
||
| 260 | simadd <nodeid> (nodetype) |
||
| 261 | simrem <nodeid> |
||
| 262 | simsave <config> |
||
| 263 | simload <config> |
||
| 264 | """ |
||
| 265 | |||
| 266 | """ -- other features -- |
||
| 267 | startup.cfg - script to run at startup (command listing) |
||
| 268 | ie: ifup 0 |
||
| 269 | tlsd start |
||
| 270 | canguid start |
||
| 271 | config.cfg - last daemon config (param override) |
||
| 272 | default.cfg - default daemon config (only read if config.cfg does not exist) |
||
| 273 | """ |
||
| 274 | |||
| 736 | olof | 275 | print 'Shutdown' |
| 738 | olof | 276 | if self.nodeIf.running(): |
| 739 | olof | 277 | print 'Stopping If thread' |
| 738 | olof | 278 | self.nodeIf.stop() |
| 279 | |||
| 736 | olof | 280 | cfg.stateSpaceCfg.saveSpaces() |
| 281 | cfg.filterCfg.saveFilters() |
||
| 738 | olof | 282 | |
| 739 | olof | 283 | print 'Waiting 0.1..' |
| 738 | olof | 284 | time.sleep(0.1) # wait for threads |
| 739 | olof | 285 | print 'Terminating' |
| 738 | olof | 286 | sys.exit(0) # will except if there are threads remaining |
| 736 | olof | 287 | |
| 288 | #--------------------------------------------------------------------------- |
||
| 289 | |||
| 290 | def main(): |
||
| 291 | daemonApp = CanDaemon() |
||
| 737 | olof | 292 | # install_thread_excepthook() |
| 736 | olof | 293 | daemonApp.run() |
| 294 | |||
| 295 | #--------------------------------------------------------------------------- |
||
| 296 | |||
| 297 | if __name__ == '__main__': |
||
| 298 | __name__ = 'Main' |
||
| 299 | main() |