161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#!/usr/bin/python
261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt# Tests p2p_invite
361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt######### MAY NEED TO RUN AS SUDO #############
461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport dbus
661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport sys, os
761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport time
861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport gobject
961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport getopt
1061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport threading
1161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtfrom dbus.mainloop.glib import DBusGMainLoop
1261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtdef usage():
1461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "Usage:"
1561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "  %s -i <interface_name> -a <addr> \ " \
1661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		% sys.argv[0]
1761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "		[-o <persistent_group_object>] [-w <wpas_dbus_interface>]"
1861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "Options:"
1961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "  -i = interface name"
2061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "  -a = address of peer"
2161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "  -o = persistent group object path"
2261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "  -w = wpas dbus interface = fi.w1.wpa_supplicant1"
2361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "Example:"
2461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "  %s -i p2p-wlan0-0 -a 00150083523c" % sys.argv[0]
2561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt# Required Signals
2761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtdef InvitationResult(invite_result):
2861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "Inviation Result signal :"
2961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	status = invite_result['status']
3061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "status = ", status
3161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if invite_result.has_key('BSSID'):
3261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		bssid = invite_result['BSSID']
3361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		print "BSSID = ", hex(bssid[0]) , ":" , \
3461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		 hex(bssid[1]) , ":" , hex(bssid[2]) , ":", \
3561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		 hex(bssid[3]) , ":" , hex(bssid[4]) , ":" , \
3661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		hex(bssid[5])
3761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os._exit(0)
3861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
3961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtclass P2P_Invite (threading.Thread):
4061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Needed Variables
4161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global bus
4261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global wpas_object
4361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global interface_object
4461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global p2p_interface
4561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global interface_name
4661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global wpas
4761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global wpas_dbus_interface
4861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global path
4961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global addr
5061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global persistent_group_object
5161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
5261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Dbus Paths
5361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global wpas_dbus_opath
5461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global wpas_dbus_interfaces_opath
5561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global wpas_dbus_interfaces_interface
5661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global wpas_dbus_interfaces_p2pdevice
5761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
5861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Arguements
5961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global P2PDictionary
6061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Constructor
6261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	def __init__(self,interface_name,wpas_dbus_interface,addr,
6361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						persistent_group_object):
6461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Initializes variables and threads
6561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.interface_name = interface_name
6661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.wpas_dbus_interface = wpas_dbus_interface
6761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.addr = addr
6861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.persistent_group_object = persistent_group_object
6961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
7061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Initializes thread and daemon allows for ctrl-c kill
7161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		threading.Thread.__init__(self)
7261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.daemon = True
7361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
7461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Generating interface/object paths
7561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.wpas_dbus_opath = "/" + \
7661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_interface.replace(".","/")
7761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.wpas_wpas_dbus_interfaces_opath = self.wpas_dbus_opath + \
7861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				"/Interfaces"
7961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.wpas_dbus_interfaces_interface = \
8061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_interface + ".Interface"
8161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.wpas_dbus_interfaces_p2pdevice = \
8261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_interfaces_interface \
8361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				+ ".P2PDevice"
8461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
8561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Getting interfaces and objects
8661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		DBusGMainLoop(set_as_default=True)
8761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.bus = dbus.SystemBus()
8861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.wpas_object = self.bus.get_object(
8961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_interface,
9061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_opath)
9161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.wpas = dbus.Interface(self.wpas_object,
9261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_interface)
9361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
9461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Try to see if supplicant knows about interface
9561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# If not, throw an exception
9661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		try:
9761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			self.path = self.wpas.GetInterface(
9861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					self.interface_name)
9961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		except dbus.DBusException, exc:
10061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			error = 'Error:\n  Interface ' + self.interface_name \
10161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				+ ' was not found'
10261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			print error
10361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			usage()
10461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			os._exit(0)
10561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
10661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.interface_object = self.bus.get_object(
10761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_interface, self.path)
10861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.p2p_interface = dbus.Interface(self.interface_object,
10961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_interfaces_p2pdevice)
11061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
11161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		#Adds listeners
11261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.bus.add_signal_receiver(InvitationResult,
11361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			dbus_interface=self.wpas_dbus_interfaces_p2pdevice,
11461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			signal_name="InvitationResult")
11561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
11661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Sets up p2p_invite dictionary
11761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	def constructArguements(self):
11861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.P2PDictionary = \
11961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			{'peer':dbus.ObjectPath(self.path+'/Peers/'+self.addr)}
12061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (self.persistent_group_object != None):
12161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			self.P2PDictionary.update({"persistent_group_object":
12261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					self.persistent_group_object})
12361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
12461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Run p2p_invite
12561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	def run(self):
12661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		try:
12761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			self.p2p_interface.Invite(self.P2PDictionary)
12861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
12961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		except:
13061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			print "Error:\n  Invalid Arguements"
13161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			usage()
13261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			os._exit(0)
13361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
13461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Allows other threads to keep working while MainLoop runs
13561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Required for timeout implementation
13661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gobject.MainLoop().get_context().iteration(True)
13761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gobject.threads_init()
13861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gobject.MainLoop().run()
13961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
14061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtif __name__ == "__main__":
14161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Defaults for optional inputs
14261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	addr = None
14361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	persistent_group_object = None
14461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpas_dbus_interface = 'fi.w1.wpa_supplicant1'
14561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
14661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# interface_name is required
14761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interface_name = None
14861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
14961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Using getopts to handle options
15061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	try:
15161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		options, args = getopt.getopt(sys.argv[1:],"hi:o:w:a:")
15261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
15361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	except getopt.GetoptError:
15461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		usage()
15561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		quit()
15661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
15761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# If theres a switch, override default option
15861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	for key, value in options:
15961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Help
16061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (key == "-h"):
16161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			usage()
16261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			quit()
16361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Interface Name
16461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		elif (key == "-i"):
16561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			interface_name = value
16661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		elif (key == "-a"):
16761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			addr = value
16861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Persistent group object path
16961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		elif (key == "-o"):
17061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			persistent_group_object = value
17161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Dbus interface
17261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		elif (key == "-w"):
17361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpas_dbus_interface = value
17461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		else:
17561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			assert False, "unhandled option"
17661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
17761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Interface name is required and was not given
17861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (interface_name == None):
17961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		print "Error:\n  interface_name is required"
18061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		usage()
18161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		quit()
18261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
18361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (addr == None):
18461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		print "Error:\n  peer address is required"
18561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		usage()
18661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		quit()
18761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
18861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	try:
18961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_invite_test = \
19061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			P2P_Invite(interface_name,wpas_dbus_interface,
19161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					addr,persistent_group_object)
19261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	except:
19361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		print "Error:\n  Invalid Arguements"
19461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		usage()
19561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		os._exit(1)
19661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_invite_test.constructArguements()
19861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_invite_test.start()
19961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	time.sleep(10)
20061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "Error:\n  p2p_invite timed out"
20161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	os._exit(0)
202