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

Last change on this file since eb36081 was eb36081, checked in by Chris Johns <chrisj@…>, on 08/26/20 at 03:38:54

tester: Change to a simpler TFTP server

  • Add a simpler TFTP to allow parallel test hardware
  • Remove the imported tftpy server

Closes #4063

  • Property mode set to 100644
File size: 6.2 KB
Line 
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
46import tftpserver
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()
92            self.finished = True
93        except:
94            pass
95
96    def _kill(self):
97        self._stop()
98        while self.running or not self.finished:
99            self._unlock('_kill')
100            time.sleep(0.1)
101            self._lock('_kill')
102
103    def _timeout(self):
104        self._stop()
105        while self.running or not self.finished:
106            self._unlock('_timeout')
107            time.sleep(0.1)
108            self._lock('_timeout')
109        if self.timeout is not None:
110            self.timeout()
111
112    def _exe_handle(self, req_file, raddress, rport):
113        self._lock('_exe_handle')
114        exe = self.exe
115        self.exe = None
116        self._unlock('_exe_handle')
117        if exe is not None:
118            if self.console:
119                self.console('tftp: %s' % (exe))
120            return open(exe, "rb")
121        if self.console:
122            self.console('tftp: re-requesting exe; target must have reset')
123        self._stop()
124        return None
125
126    def _listener(self):
127        self._lock('_listener')
128        exe = self.exe
129        self.exe = None
130        self._unlock('_listener')
131        self.server = tftpserver.tftp_server(host = 'all',
132                                             port = self.port,
133                                             timeout = 1,
134                                             forced_file = exe,
135                                             sessions = 1)
136        try:
137            self.server.start()
138            self.server.run()
139        except:
140            self.server.stop()
141            raise
142
143    def _runner(self):
144        self._lock('_runner')
145        self.running = True
146        self._unlock('_runner')
147        caught = None
148        try:
149            self._listener()
150        except:
151            caught = sys.exc_info()
152        self._lock('_runner')
153        self.running = False
154        self.caught = caught
155        self._unlock('_runner')
156
157    def open(self, executable, port, output_length, console, timeout):
158        self._lock('_open')
159        if self.exe is not None:
160            self._unlock('_open')
161            raise error.general('tftp: already running')
162        self._init()
163        self.output_length = output_length
164        self.console = console
165        self.port = port
166        self.exe = executable
167        if self.console:
168            self.console('tftp: exe: %s' % (executable))
169        self.timeout = timeout[1]
170        self.listener = threading.Thread(target = self._runner,
171                                         name = 'tftp-listener')
172        self.listener.start()
173        step = 0.5
174        period = timeout[0]
175        output_len = self.output_length()
176        while not self.finished and period > 0:
177            current_length = self.output_length()
178            if output_length != current_length:
179                period = timeout[0]
180            output_length = current_length
181            if period < step:
182                period = 0
183            else:
184                period -= step
185            self._unlock('_open')
186            time.sleep(step)
187            self._lock('_open')
188        if not self.finished and period == 0:
189            self._timeout()
190        caught = self.caught
191        self.caught = None
192        self._init()
193        self._unlock('_open')
194        if caught is not None:
195            reraise.reraise(*caught)
196
197    def kill(self):
198        self._lock('kill')
199        self._kill()
200        self._unlock('kill')
201
202if __name__ == "__main__":
203    import sys
204    if len(sys.argv) > 1:
205        executable = sys.argv[1]
206    else:
207        executable = None
208    t = tftp('arm', 'beagleboneblack')
209    t.open(executable)
Note: See TracBrowser for help on using the repository browser.