mayuresh bharmoria / Mbed OS mbed-os-example-wifi
Committer:
mayur098
Date:
Thu Jun 21 17:50:21 2018 +0000
Revision:
0:8f8e8f3cbd1c
first commit;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mayur098 0:8f8e8f3cbd1c 1 # Copyright 2015 ARM Limited, All rights reserved
mayur098 0:8f8e8f3cbd1c 2 #
mayur098 0:8f8e8f3cbd1c 3 # Licensed under the Apache License, Version 2.0 (the "License");
mayur098 0:8f8e8f3cbd1c 4 # you may not use this file except in compliance with the License.
mayur098 0:8f8e8f3cbd1c 5 # You may obtain a copy of the License at
mayur098 0:8f8e8f3cbd1c 6 #
mayur098 0:8f8e8f3cbd1c 7 # http://www.apache.org/licenses/LICENSE-2.0
mayur098 0:8f8e8f3cbd1c 8 #
mayur098 0:8f8e8f3cbd1c 9 # Unless required by applicable law or agreed to in writing, software
mayur098 0:8f8e8f3cbd1c 10 # distributed under the License is distributed on an "AS IS" BASIS,
mayur098 0:8f8e8f3cbd1c 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mayur098 0:8f8e8f3cbd1c 12 # See the License for the specific language governing permissions and
mayur098 0:8f8e8f3cbd1c 13 # limitations under the License.
mayur098 0:8f8e8f3cbd1c 14
mayur098 0:8f8e8f3cbd1c 15 import sys
mayur098 0:8f8e8f3cbd1c 16 import select
mayur098 0:8f8e8f3cbd1c 17 import socket
mayur098 0:8f8e8f3cbd1c 18 import logging
mayur098 0:8f8e8f3cbd1c 19 from threading import Thread
mayur098 0:8f8e8f3cbd1c 20 from sys import stdout
mayur098 0:8f8e8f3cbd1c 21 from SocketServer import BaseRequestHandler, TCPServer
mayur098 0:8f8e8f3cbd1c 22 from mbed_host_tests import BaseHostTest, event_callback
mayur098 0:8f8e8f3cbd1c 23
mayur098 0:8f8e8f3cbd1c 24
mayur098 0:8f8e8f3cbd1c 25 class TCPEchoClientHandler(BaseRequestHandler):
mayur098 0:8f8e8f3cbd1c 26 def handle(self):
mayur098 0:8f8e8f3cbd1c 27 """
mayur098 0:8f8e8f3cbd1c 28 Handles a connection. Test starts by client(i.e. mbed) connecting to server.
mayur098 0:8f8e8f3cbd1c 29 This connection handler receives data and echoes back to the client util
mayur098 0:8f8e8f3cbd1c 30 {{end}} is received. Then it sits on recv() for client to terminate the
mayur098 0:8f8e8f3cbd1c 31 connection.
mayur098 0:8f8e8f3cbd1c 32
mayur098 0:8f8e8f3cbd1c 33 Note: reason for not echoing data back after receiving {{end}} is that send
mayur098 0:8f8e8f3cbd1c 34 fails raising a SocketError as client closes connection.
mayur098 0:8f8e8f3cbd1c 35 """
mayur098 0:8f8e8f3cbd1c 36 while self.server.isrunning():
mayur098 0:8f8e8f3cbd1c 37 try:
mayur098 0:8f8e8f3cbd1c 38 data = self.recv()
mayur098 0:8f8e8f3cbd1c 39 if not data: break
mayur098 0:8f8e8f3cbd1c 40 except Exception as e:
mayur098 0:8f8e8f3cbd1c 41 break
mayur098 0:8f8e8f3cbd1c 42
mayur098 0:8f8e8f3cbd1c 43 try:
mayur098 0:8f8e8f3cbd1c 44 # echo data back to the client
mayur098 0:8f8e8f3cbd1c 45 self.send(data)
mayur098 0:8f8e8f3cbd1c 46 except Exception as e:
mayur098 0:8f8e8f3cbd1c 47 break
mayur098 0:8f8e8f3cbd1c 48
mayur098 0:8f8e8f3cbd1c 49 def recv(self):
mayur098 0:8f8e8f3cbd1c 50 """
mayur098 0:8f8e8f3cbd1c 51 Try to receive until server is shutdown
mayur098 0:8f8e8f3cbd1c 52 """
mayur098 0:8f8e8f3cbd1c 53 while self.server.isrunning():
mayur098 0:8f8e8f3cbd1c 54 rl, wl, xl = select.select([self.request], [], [], 1)
mayur098 0:8f8e8f3cbd1c 55 if len(rl):
mayur098 0:8f8e8f3cbd1c 56 return self.request.recv(1024)
mayur098 0:8f8e8f3cbd1c 57
mayur098 0:8f8e8f3cbd1c 58 def send(self, data):
mayur098 0:8f8e8f3cbd1c 59 """
mayur098 0:8f8e8f3cbd1c 60 Try to send until server is shutdown
mayur098 0:8f8e8f3cbd1c 61 """
mayur098 0:8f8e8f3cbd1c 62 while self.server.isrunning():
mayur098 0:8f8e8f3cbd1c 63 rl, wl, xl = select.select([], [self.request], [], 1)
mayur098 0:8f8e8f3cbd1c 64 if len(wl):
mayur098 0:8f8e8f3cbd1c 65 self.request.sendall(data)
mayur098 0:8f8e8f3cbd1c 66 break
mayur098 0:8f8e8f3cbd1c 67
mayur098 0:8f8e8f3cbd1c 68
mayur098 0:8f8e8f3cbd1c 69 class TCPServerWrapper(TCPServer):
mayur098 0:8f8e8f3cbd1c 70 """
mayur098 0:8f8e8f3cbd1c 71 Wrapper over TCP server to implement server initiated shutdown.
mayur098 0:8f8e8f3cbd1c 72 Adds a flag:= running that a request handler can check and come out of
mayur098 0:8f8e8f3cbd1c 73 recv loop when shutdown is called.
mayur098 0:8f8e8f3cbd1c 74 """
mayur098 0:8f8e8f3cbd1c 75
mayur098 0:8f8e8f3cbd1c 76 def __init__(self, addr, request_handler):
mayur098 0:8f8e8f3cbd1c 77 # hmm, TCPServer is not sub-classed from object!
mayur098 0:8f8e8f3cbd1c 78 if issubclass(TCPServer, object):
mayur098 0:8f8e8f3cbd1c 79 super(TCPServerWrapper, self).__init__(addr, request_handler)
mayur098 0:8f8e8f3cbd1c 80 else:
mayur098 0:8f8e8f3cbd1c 81 TCPServer.__init__(self, addr, request_handler)
mayur098 0:8f8e8f3cbd1c 82 self.running = False
mayur098 0:8f8e8f3cbd1c 83
mayur098 0:8f8e8f3cbd1c 84 def serve_forever(self):
mayur098 0:8f8e8f3cbd1c 85 self.running = True
mayur098 0:8f8e8f3cbd1c 86 if issubclass(TCPServer, object):
mayur098 0:8f8e8f3cbd1c 87 super(TCPServerWrapper, self).serve_forever()
mayur098 0:8f8e8f3cbd1c 88 else:
mayur098 0:8f8e8f3cbd1c 89 TCPServer.serve_forever(self)
mayur098 0:8f8e8f3cbd1c 90
mayur098 0:8f8e8f3cbd1c 91 def shutdown(self):
mayur098 0:8f8e8f3cbd1c 92 self.running = False
mayur098 0:8f8e8f3cbd1c 93 if issubclass(TCPServer, object):
mayur098 0:8f8e8f3cbd1c 94 super(TCPServerWrapper, self).shutdown()
mayur098 0:8f8e8f3cbd1c 95 else:
mayur098 0:8f8e8f3cbd1c 96 TCPServer.shutdown(self)
mayur098 0:8f8e8f3cbd1c 97
mayur098 0:8f8e8f3cbd1c 98 def isrunning(self):
mayur098 0:8f8e8f3cbd1c 99 return self.running
mayur098 0:8f8e8f3cbd1c 100
mayur098 0:8f8e8f3cbd1c 101
mayur098 0:8f8e8f3cbd1c 102 class TCPEchoClientTest(BaseHostTest):
mayur098 0:8f8e8f3cbd1c 103
mayur098 0:8f8e8f3cbd1c 104 def __init__(self):
mayur098 0:8f8e8f3cbd1c 105 """
mayur098 0:8f8e8f3cbd1c 106 Initialise test parameters.
mayur098 0:8f8e8f3cbd1c 107
mayur098 0:8f8e8f3cbd1c 108 :return:
mayur098 0:8f8e8f3cbd1c 109 """
mayur098 0:8f8e8f3cbd1c 110 BaseHostTest.__init__(self)
mayur098 0:8f8e8f3cbd1c 111 self.SERVER_IP = None # Will be determined after knowing the target IP
mayur098 0:8f8e8f3cbd1c 112 self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port
mayur098 0:8f8e8f3cbd1c 113 self.server = None
mayur098 0:8f8e8f3cbd1c 114 self.server_thread = None
mayur098 0:8f8e8f3cbd1c 115 self.target_ip = None
mayur098 0:8f8e8f3cbd1c 116
mayur098 0:8f8e8f3cbd1c 117 @staticmethod
mayur098 0:8f8e8f3cbd1c 118 def find_interface_to_target_addr(target_ip):
mayur098 0:8f8e8f3cbd1c 119 """
mayur098 0:8f8e8f3cbd1c 120 Finds IP address of the interface through which it is connected to the target.
mayur098 0:8f8e8f3cbd1c 121
mayur098 0:8f8e8f3cbd1c 122 :return:
mayur098 0:8f8e8f3cbd1c 123 """
mayur098 0:8f8e8f3cbd1c 124 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
mayur098 0:8f8e8f3cbd1c 125 try:
mayur098 0:8f8e8f3cbd1c 126 s.connect((target_ip, 0)) # Target IP, any port
mayur098 0:8f8e8f3cbd1c 127 except socket.error:
mayur098 0:8f8e8f3cbd1c 128 s.connect((target_ip, 8000)) # Target IP, 'random' port
mayur098 0:8f8e8f3cbd1c 129 ip = s.getsockname()[0]
mayur098 0:8f8e8f3cbd1c 130 s.close()
mayur098 0:8f8e8f3cbd1c 131 return ip
mayur098 0:8f8e8f3cbd1c 132
mayur098 0:8f8e8f3cbd1c 133 def setup_tcp_server(self):
mayur098 0:8f8e8f3cbd1c 134 """
mayur098 0:8f8e8f3cbd1c 135 sets up a TCP server for target to connect and send test data.
mayur098 0:8f8e8f3cbd1c 136
mayur098 0:8f8e8f3cbd1c 137 :return:
mayur098 0:8f8e8f3cbd1c 138 """
mayur098 0:8f8e8f3cbd1c 139 # !NOTE: There should mechanism to assert in the host test
mayur098 0:8f8e8f3cbd1c 140 if self.SERVER_IP is None:
mayur098 0:8f8e8f3cbd1c 141 self.log("setup_tcp_server() called before determining server IP!")
mayur098 0:8f8e8f3cbd1c 142 self.notify_complete(False)
mayur098 0:8f8e8f3cbd1c 143
mayur098 0:8f8e8f3cbd1c 144 # Returning none will suppress host test from printing success code
mayur098 0:8f8e8f3cbd1c 145 self.server = TCPServerWrapper((self.SERVER_IP, self.SERVER_PORT), TCPEchoClientHandler)
mayur098 0:8f8e8f3cbd1c 146 ip, port = self.server.server_address
mayur098 0:8f8e8f3cbd1c 147 self.SERVER_PORT = port
mayur098 0:8f8e8f3cbd1c 148 self.server.allow_reuse_address = True
mayur098 0:8f8e8f3cbd1c 149 self.log("HOST: Listening for TCP connections: " + self.SERVER_IP + ":" + str(self.SERVER_PORT))
mayur098 0:8f8e8f3cbd1c 150 self.server_thread = Thread(target=TCPEchoClientTest.server_thread_func, args=(self,))
mayur098 0:8f8e8f3cbd1c 151 self.server_thread.start()
mayur098 0:8f8e8f3cbd1c 152
mayur098 0:8f8e8f3cbd1c 153 @staticmethod
mayur098 0:8f8e8f3cbd1c 154 def server_thread_func(this):
mayur098 0:8f8e8f3cbd1c 155 """
mayur098 0:8f8e8f3cbd1c 156 Thread function to run TCP server forever.
mayur098 0:8f8e8f3cbd1c 157
mayur098 0:8f8e8f3cbd1c 158 :param this:
mayur098 0:8f8e8f3cbd1c 159 :return:
mayur098 0:8f8e8f3cbd1c 160 """
mayur098 0:8f8e8f3cbd1c 161 this.server.serve_forever()
mayur098 0:8f8e8f3cbd1c 162
mayur098 0:8f8e8f3cbd1c 163 @event_callback("target_ip")
mayur098 0:8f8e8f3cbd1c 164 def _callback_target_ip(self, key, value, timestamp):
mayur098 0:8f8e8f3cbd1c 165 """
mayur098 0:8f8e8f3cbd1c 166 Callback to handle reception of target's IP address.
mayur098 0:8f8e8f3cbd1c 167
mayur098 0:8f8e8f3cbd1c 168 :param key:
mayur098 0:8f8e8f3cbd1c 169 :param value:
mayur098 0:8f8e8f3cbd1c 170 :param timestamp:
mayur098 0:8f8e8f3cbd1c 171 :return:
mayur098 0:8f8e8f3cbd1c 172 """
mayur098 0:8f8e8f3cbd1c 173 self.target_ip = value
mayur098 0:8f8e8f3cbd1c 174 self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip)
mayur098 0:8f8e8f3cbd1c 175 self.setup_tcp_server()
mayur098 0:8f8e8f3cbd1c 176
mayur098 0:8f8e8f3cbd1c 177 @event_callback("host_ip")
mayur098 0:8f8e8f3cbd1c 178 def _callback_host_ip(self, key, value, timestamp):
mayur098 0:8f8e8f3cbd1c 179 """
mayur098 0:8f8e8f3cbd1c 180 Callback for request for host IP Addr
mayur098 0:8f8e8f3cbd1c 181
mayur098 0:8f8e8f3cbd1c 182 """
mayur098 0:8f8e8f3cbd1c 183 self.send_kv("host_ip", self.SERVER_IP)
mayur098 0:8f8e8f3cbd1c 184
mayur098 0:8f8e8f3cbd1c 185 @event_callback("host_port")
mayur098 0:8f8e8f3cbd1c 186 def _callback_host_port(self, key, value, timestamp):
mayur098 0:8f8e8f3cbd1c 187 """
mayur098 0:8f8e8f3cbd1c 188 Callback for request for host port
mayur098 0:8f8e8f3cbd1c 189 """
mayur098 0:8f8e8f3cbd1c 190 self.send_kv("host_port", self.SERVER_PORT)
mayur098 0:8f8e8f3cbd1c 191
mayur098 0:8f8e8f3cbd1c 192 def teardown(self):
mayur098 0:8f8e8f3cbd1c 193 if self.server:
mayur098 0:8f8e8f3cbd1c 194 self.server.shutdown()
mayur098 0:8f8e8f3cbd1c 195 self.server_thread.join()