1#
2#   Copyright 2018 - The Android Open Source Project
3#
4#   Licensed under the Apache License, Version 2.0 (the "License");
5#   you may not use this file except in compliance with the License.
6#   You may obtain a copy of the License at
7#
8#       http://www.apache.org/licenses/LICENSE-2.0
9#
10#   Unless required by applicable law or agreed to in writing, software
11#   distributed under the License is distributed on an "AS IS" BASIS,
12#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13#   See the License for the specific language governing permissions and
14#   limitations under the License.
15
16import queue
17import re
18import threading
19import time
20
21from acts.test_utils.net import connectivity_const as cconst
22from acts import asserts
23
24MSG = "Test message "
25PKTS = 5
26
27""" Methods for android.system.Os based sockets """
28def open_android_socket(ad, domain, sock_type, ip, port):
29    """ Open TCP or UDP using android.system.Os class
30
31    Args:
32      1. ad - android device object
33      2. domain - IPv4 or IPv6 type
34      3. sock_type - UDP or TCP socket
35      4. ip - IP addr on the device
36      5. port - open socket on port
37
38    Returns:
39      File descriptor key
40    """
41    fd_key = ad.droid.openSocket(domain, sock_type, ip, port)
42    ad.log.info("File descriptor: %s" % fd_key)
43    asserts.assert_true(fd_key, "Failed to open socket")
44    return fd_key
45
46def close_android_socket(ad, fd_key):
47    """ Close socket
48
49    Args:
50      1. ad - android device object
51      2. fd_key - file descriptor key
52    """
53    status = ad.droid.closeSocket(fd_key)
54    asserts.assert_true(status, "Failed to close socket")
55
56def listen_accept_android_socket(client,
57                                 server,
58                                 client_fd,
59                                 server_fd,
60                                 server_ip,
61                                 server_port):
62    """ Listen, accept TCP sockets
63
64    Args:
65      1. client : ad object for client device
66      2. server : ad object for server device
67      3. client_fd : client's socket handle
68      4. server_fd : server's socket handle
69      5. server_ip : send data to this IP
70      6. server_port : send data to this port
71    """
72    server.droid.listenSocket(server_fd)
73    client.droid.connectSocket(client_fd, server_ip, server_port)
74    sock = server.droid.acceptSocket(server_fd)
75    asserts.assert_true(sock, "Failed to accept socket")
76    return sock
77
78def send_recv_data_android_sockets(client,
79                                   server,
80                                   client_fd,
81                                   server_fd,
82                                   server_ip,
83                                   server_port):
84    """ Send TCP or UDP data over android os sockets from client to server.
85        Verify that server received the data.
86
87    Args:
88      1. client : ad object for client device
89      2. server : ad object for server device
90      3. client_fd : client's socket handle
91      4. server_fd : server's socket handle
92      5. server_ip : send data to this IP
93      6. server_port : send data to this port
94    """
95    send_list = []
96    recv_list = []
97
98    for _ in range(1, PKTS+1):
99        msg = MSG + " %s" % _
100        send_list.append(msg)
101        client.log.info("Sending message: %s" % msg)
102        client.droid.sendDataOverSocket(server_ip, server_port, msg, client_fd)
103        recv_msg = server.droid.recvDataOverSocket(server_fd)
104        server.log.info("Received message: %s" % recv_msg)
105        recv_list.append(recv_msg)
106
107    recv_list = [x.rstrip('\x00') if x else x for x in recv_list]
108    asserts.assert_true(send_list and recv_list and send_list == recv_list,
109                        "Send and recv information is incorrect")
110
111""" Methods for java.net.DatagramSocket based sockets """
112def open_datagram_socket(ad, ip, port):
113    """ Open datagram socket
114
115    Args:
116      1. ad : android device object
117      2. ip : IP addr on the device
118      3. port : socket port
119
120    Returns:
121      Hash key of the datagram socket
122    """
123    socket_key = ad.droid.openDatagramSocket(ip, port)
124    ad.log.info("Datagram socket: %s" % socket_key)
125    asserts.assert_true(socket_key, "Failed to open datagram socket")
126    return socket_key
127
128def close_datagram_socket(ad, socket_key):
129    """ Close datagram socket
130
131    Args:
132      1. socket_key : hash key of datagram socket
133    """
134    status = ad.droid.closeDatagramSocket(socket_key)
135    asserts.assert_true(status, "Failed to close datagram socket")
136
137def send_recv_data_datagram_sockets(client,
138                                    server,
139                                    client_sock,
140                                    server_sock,
141                                    server_ip,
142                                    server_port):
143    """ Send data over datagram socket from dut_a to dut_b.
144        Verify that dut_b received the data.
145
146    Args:
147      1. client : ad object for client device
148      2. server : ad object for server device
149      3. client_sock : client's socket handle
150      4. server_sock : server's socket handle
151      5. server_ip : send data to this IP
152      6. server_port : send data to this port
153    """
154    send_list = []
155    recv_list = []
156
157    for _ in range(1, PKTS+1):
158        msg = MSG + " %s" % _
159        send_list.append(msg)
160        client.log.info("Sending message: %s" % msg)
161        client.droid.sendDataOverDatagramSocket(client_sock,
162                                                msg,
163                                                server_ip,
164                                                server_port)
165        recv_msg = server.droid.recvDataOverDatagramSocket(server_sock)
166        server.log.info("Received message: %s" % recv_msg)
167        recv_list.append(recv_msg)
168
169    recv_list = [x.rstrip('\x00') if x else x for x in recv_list]
170    asserts.assert_true(send_list and recv_list and send_list == recv_list,
171                        "Send and recv information is incorrect")
172
173""" Utils methods for java.net.Socket based sockets """
174def _accept_socket(server, server_ip, server_port, server_sock, q):
175    sock = server.droid.acceptTcpSocket(server_sock)
176    server.log.info("Server socket: %s" % sock)
177    q.put(sock)
178
179def _client_socket(client, server_ip, server_port, client_ip, client_port, q):
180    time.sleep(0.5)
181    sock = client.droid.openTcpSocket(server_ip,
182                                      server_port,
183                                      client_ip,
184                                      client_port)
185    client.log.info("Client socket: %s" % sock)
186    q.put(sock)
187
188def open_connect_socket(client,
189                        server,
190                        client_ip,
191                        server_ip,
192                        client_port,
193                        server_port,
194                        server_sock):
195    """ Open tcp socket and connect to server
196
197    Args:
198      1. client : ad object for client device
199      2. server : ad object for server device
200      3. client_ip : client's socket handle
201      4. server_ip : send data to this IP
202      5. client_port : port on client socket
203      6. server_port : port on server socket
204      7. server_sock : server socket
205
206    Returns:
207      client and server socket from successful connect
208    """
209    sq = queue.Queue()
210    cq = queue.Queue()
211    s = threading.Thread(target = _accept_socket,
212                         args = (server, server_ip, server_port, server_sock,
213                                 sq))
214    c = threading.Thread(target = _client_socket,
215                         args = (client, server_ip, server_port, client_ip,
216                                 client_port, cq))
217    s.start()
218    c.start()
219    c.join()
220    s.join()
221
222    client_sock = cq.get()
223    server_sock = sq.get()
224    asserts.assert_true(client_sock and server_sock, "Failed to open sockets")
225
226    return client_sock, server_sock
227
228def open_server_socket(server, server_ip, server_port):
229    """ Open tcp server socket
230
231    Args:
232      1. server : ad object for server device
233      2. server_ip : send data to this IP
234      3. server_port : send data to this port
235    """
236    sock = server.droid.openTcpServerSocket(server_ip, server_port)
237    server.log.info("Server Socket: %s" % sock)
238    asserts.assert_true(sock, "Failed to open server socket")
239    return sock
240
241def close_socket(ad, socket):
242    """ Close socket
243
244    Args:
245      1. ad - android device object
246      2. socket - socket key
247    """
248    status = ad.droid.closeTcpSocket(socket)
249    asserts.assert_true(status, "Failed to socket")
250
251def close_server_socket(ad, socket):
252    """ Close server socket
253
254    Args:
255      1. ad - android device object
256      2. socket - server socket key
257    """
258    status = ad.droid.closeTcpServerSocket(socket)
259    asserts.assert_true(status, "Failed to socket")
260
261def shutdown_socket(ad, socket):
262    """ Shutdown socket
263
264    Args:
265      1. ad - androidandroid device object
266      2. socket - socket key
267    """
268    fd = ad.droid.getFileDescriptorOfSocket(socket)
269    asserts.assert_true(fd, "Failed to get FileDescriptor key")
270    status = ad.droid.shutdownFileDescriptor(fd)
271    asserts.assert_true(status, "Failed to shutdown socket")
272
273def send_recv_data_sockets(client, server, client_sock, server_sock):
274    """ Send data over TCP socket from client to server.
275        Verify that server received the data
276
277    Args:
278      1. client : ad object for client device
279      2. server : ad object for server device
280      3. client_sock : client's socket handle
281      4. server_sock : server's socket handle
282    """
283    send_list = []
284    recv_list = []
285
286    for _ in range(1, PKTS+1):
287        msg = MSG + " %s" % _
288        send_list.append(msg)
289        client.log.info("Sending message: %s" % msg)
290        client.droid.sendDataOverTcpSocket(client_sock, msg)
291        recv_msg = server.droid.recvDataOverTcpSocket(server_sock)
292        server.log.info("Received message: %s" % recv_msg)
293        recv_list.append(recv_msg)
294
295    recv_list = [x.rstrip('\x00') if x else x for x in recv_list]
296    asserts.assert_true(send_list and recv_list and send_list == recv_list,
297                        "Send and recv information is incorrect")
298