source: rtems-tools/tester/rt/tftp.py @ e058db0

5
Last change on this file since e058db0 was e058db0, checked in by Chris Johns <chrisj@…>, on 11/07/18 at 03:55:20

python: Provide support to select a valid python version.

  • Update imports after wrapping the code.
  • Fix python3 issues.
  • Fix config path issues for in repo and install runs.

Closes #3537

  • Property mode set to 100644
File size: 6.2 KB
RevLine 
[3a867a4]1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2013-2017 Chris Johns (chrisj@rtems.org)
4# All rights reserved.
5#
6# This file is part of the RTEMS Tools package in 'rtems-tools'.
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions are met:
10#
11# 1. Redistributions of source code must retain the above copyright notice,
12# this list of conditions and the following disclaimer.
13#
14# 2. Redistributions in binary form must reproduce the above copyright notice,
15# this list of conditions and the following disclaimer in the documentation
16# and/or other materials provided with the distribution.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28# POSSIBILITY OF SUCH DAMAGE.
29#
30
31#
32# RTEMS Testing TFTP Interface
33#
34
35from __future__ import print_function
36
37import errno
38import logging
39import threading
40import time
41import sys
42
43from rtemstoolkit import error
44from rtemstoolkit import reraise
45
[e058db0]46import tftpy
[3a867a4]47
48class tftp(object):
49    '''RTEMS Testing TFTP base.'''
50
51    def __init__(self, bsp_arch, bsp, trace = False):
52        self.trace = trace
53        self.lock_trace = False
54        self.lock = threading.RLock()
55        self.bsp = bsp
56        self.bsp_arch = bsp_arch
57        self._init()
58
59    def __del__(self):
60        self.kill()
61
62    def _init(self):
63        self.output_length = None
64        self.console = None
65        self.server = None
66        self.port = 0
67        self.exe = None
68        self.timeout = None
69        self.timer = None
70        self.running = False
71        self.finished = False
72        self.caught = None
73
74    def _lock(self, msg):
75        if self.lock_trace:
76            print('|[   LOCK:%s ]|' % (msg))
77        self.lock.acquire()
78
79    def _unlock(self, msg):
80        if self.lock_trace:
81            print('|] UNLOCK:%s [|' % (msg))
82        self.lock.release()
83
84    def _finished(self):
85        self.server = None
86        self.exe = None
87
88    def _stop(self):
89        try:
90            if self.server:
91                self.server.stop(now = True)
92        except:
93            pass
94
95    def _kill(self):
96        self._stop()
97        while self.running or not self.finished:
98            self._unlock('_kill')
99            time.sleep(0.1)
100            self._lock('_kill')
101
102    def _timeout(self):
103        self._stop()
104        if self.timeout is not None:
105            self.timeout()
106
107    def _exe_handle(self, req_file, raddress, rport):
108        self._lock('_exe_handle')
109        exe = self.exe
110        self.exe = None
111        self._unlock('_exe_handle')
112        if exe is not None:
113            if self.console:
114                self.console('tftp: %s' % (exe))
115            return open(exe, "rb")
[4b76b8e]116        if self.console:
117            self.console('tftp: re-requesting exe; target must have reset')
[3a867a4]118        self._stop()
119        return None
120
121    def _listener(self):
122        tftpy.log.setLevel(100)
123        try:
124            self.server = tftpy.TftpServer(tftproot = '.',
125                                           dyn_file_func = self._exe_handle)
126        except tftpy.TftpException as te:
127            raise error.general('tftp: %s' % (str(te)))
128        if self.server is not None:
129            try:
130                self.server.listen('0.0.0.0', self.port, 0.5)
131            except tftpy.TftpException as te:
132                raise error.general('tftp: %s' % (str(te)))
133            except IOError as ie:
134                if ie.errno == errno.EACCES:
135                    raise error.general('tftp: permissions error: check tftp server port')
136                raise error.general('tftp: io error: %s' % (str(ie)))
137
138    def _runner(self):
139        self._lock('_runner')
140        self.running = True
141        self._unlock('_runner')
142        caught = None
143        try:
144            self._listener()
145        except:
146            caught = sys.exc_info()
147        self._lock('_runner')
148        self._init()
149        self.running = False
150        self.finished = True
151        self.caught = caught
152        self._unlock('_runner')
153
154    def open(self, executable, port, output_length, console, timeout):
155        self._lock('_open')
156        if self.exe is not None:
157            self._unlock('_open')
158            raise error.general('tftp: already running')
159        self._init()
160        self.output_length = output_length
161        self.console = console
162        self.port = port
163        self.exe = executable
164        self.timeout = timeout[1]
165        self.listener = threading.Thread(target = self._runner,
166                                         name = 'tftp-listener')
167        self.listener.start()
[3ed65c0]168        step = 0.5
[3a867a4]169        period = timeout[0]
170        output_len = self.output_length()
171        while not self.finished and period > 0:
172            current_length = self.output_length()
173            if output_length != current_length:
174                period = timeout[0]
175            output_length = current_length
176            if period < step:
177                period = 0
178            else:
179                period -= step
180            self._unlock('_open')
181            time.sleep(step)
182            self._lock('_open')
183        if not self.finished and period == 0:
184            self._timeout()
185        caught = self.caught
186        self.caught = None
187        self._unlock('_open')
188        if caught is not None:
189            reraise.reraise(*caught)
190
191    def kill(self):
192        self._lock('kill')
193        self._kill()
194        self._unlock('kill')
195
196if __name__ == "__main__":
197    import sys
198    if len(sys.argv) > 1:
199        executable = sys.argv[1]
200    else:
201        executable = None
202    t = tftp('arm', 'beagleboneblack')
203    t.open(executable)
Note: See TracBrowser for help on using the repository browser.