diff Modules/socketmodule.c @ 32213:70dee2b193f7 legacy-trunk

Patch #929192: Improvements to bluetooth support. Added setbdaddr and makebdaddr. Extended makesockaddr to understand Bluetooth addresses. Changed getsockaddr to expect the Bluetooth addresses as a string, not a six element tuple. Reformatted some of the Bluetooth code to be more consistent with PEP 7.
author Martin v. Löwis <martin@v.loewis.de>
date Thu, 03 Jun 2004 09:24:42 +0000
parents a799b0d1c568
children d8abf582f893
line wrap: on
line diff
--- a/Modules/socketmodule.c	Thu Jun 03 09:18:35 2004 +0000
+++ b/Modules/socketmodule.c	Thu Jun 03 09:24:42 2004 +0000
@@ -858,6 +858,51 @@
 }
 
 
+#ifdef USE_BLUETOOTH
+/* Convert a string representation of a Bluetooth address into a numeric
+   address.  Returns the length (6), or raises an exception and returns -1 if
+   an error occurred. */
+
+static int
+setbdaddr(char *name, bdaddr_t *bdaddr)
+{
+	unsigned int b0, b1, b2, b3, b4, b5;
+	char ch;
+	int n;
+
+	n = sscanf(name, "%X:%X:%X:%X:%X:%X%c",
+		   &b5, &b4, &b3, &b2, &b1, &b0, &ch);
+	if (n == 6 && (b0 | b1 | b2 | b3 | b4 | b5) < 256) {
+		bdaddr->b[0] = b0;
+		bdaddr->b[1] = b1;
+		bdaddr->b[2] = b2;
+		bdaddr->b[3] = b3;
+		bdaddr->b[4] = b4;
+		bdaddr->b[5] = b5;
+		return 6;
+	} else {
+		PyErr_SetString(socket_error, "bad bluetooth address");
+		return -1;
+	}
+}
+
+/* Create a string representation of the Bluetooth address.  This is always a
+   string of the form 'XX:XX:XX:XX:XX:XX' where XX is a two digit hexadecimal
+   value (zero padded if necessary). */
+
+static PyObject *
+makebdaddr(bdaddr_t *bdaddr)
+{
+	char buf[(6 * 2) + 5 + 1];
+
+	sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
+		bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
+		bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
+	return PyString_FromString(buf);
+}
+#endif
+
+
 /* Create an object representing the given socket address,
    suitable for passing it back to bind(), connect() etc.
    The family field of the sockaddr structure is inspected
@@ -865,7 +910,7 @@
 
 /*ARGSUSED*/
 static PyObject *
-makesockaddr(int sockfd, struct sockaddr *addr, int addrlen)
+makesockaddr(int sockfd, struct sockaddr *addr, int addrlen, int proto)
 {
 	if (addrlen == 0) {
 		/* No address -- may be recvfrom() from known socket */
@@ -920,6 +965,49 @@
 	}
 #endif
 
+#ifdef USE_BLUETOOTH
+	case AF_BLUETOOTH:
+		switch (proto) {
+
+		case BTPROTO_L2CAP:
+		{
+			struct sockaddr_l2 *a = (struct sockaddr_l2 *) addr;
+			PyObject *addrobj = makebdaddr(&_BT_L2_MEMB(a, bdaddr));
+			PyObject *ret = NULL;
+			if (addrobj) {
+				ret = Py_BuildValue("Oi",
+						    addrobj,
+						    _BT_L2_MEMB(a, psm));
+				Py_DECREF(addrobj);
+			}
+			return ret;
+		}
+
+		case BTPROTO_RFCOMM:
+		{
+			struct sockaddr_rc *a = (struct sockaddr_rc *) addr;
+			PyObject *addrobj = makebdaddr(&_BT_RC_MEMB(a, bdaddr));
+			PyObject *ret = NULL;
+			if (addrobj) {
+				ret = Py_BuildValue("Oi",
+						    addrobj,
+						    _BT_RC_MEMB(a, channel));
+				Py_DECREF(addrobj);
+			}
+			return ret;
+		}
+
+#if !defined(__FreeBSD__)
+		case BTPROTO_SCO:
+		{
+			struct sockaddr_sco *a = (struct sockaddr_sco *) addr;
+			return makebdaddr(&_BT_SCO_MEMB(a, bdaddr));
+		}
+#endif
+
+		}
+#endif
+
 #ifdef HAVE_NETPACKET_PACKET_H
 	case AF_PACKET:
 	{
@@ -1054,63 +1142,69 @@
 #ifdef USE_BLUETOOTH
 	case AF_BLUETOOTH:
 	{
-		switch( s->sock_proto )
+		switch (s->sock_proto) {
+		case BTPROTO_L2CAP:
 		{
-			case BTPROTO_L2CAP:
-			{
-				struct sockaddr_l2* addr = (struct sockaddr_l2*)_BT_SOCKADDR_MEMB(s, l2);
-				bdaddr_t* bdaddr = &_BT_L2_MEMB(addr, bdaddr);
-
-				_BT_L2_MEMB(addr, family) = AF_BLUETOOTH;
-				if( !PyArg_ParseTuple(args, "(iiiiii)i", &bdaddr->b[0], &bdaddr->b[1], &bdaddr->b[2], &bdaddr->b[3], &bdaddr->b[4], &bdaddr->b[5], &_BT_L2_MEMB(addr, psm)) )
-				{
-					PyErr_SetString(socket_error, "getsockaddrarg: wrong format");
-					return 0;
-				}
-
-				*addr_ret = (struct sockaddr *) addr;
-				*len_ret = sizeof *addr;
-				return 1;
+			struct sockaddr_l2 *addr = (struct sockaddr_l2 *) _BT_SOCKADDR_MEMB(s, l2);
+			char *straddr;
+
+			_BT_L2_MEMB(addr, family) = AF_BLUETOOTH;
+			if (!PyArg_ParseTuple(args, "si", &straddr,
+					      &_BT_L2_MEMB(addr, psm))) {
+				PyErr_SetString(socket_error, "getsockaddrarg: "
+						"wrong format");
+				return 0;
 			}
-			case BTPROTO_RFCOMM:
-			{
-				struct sockaddr_rc* addr = (struct sockaddr_rc*)_BT_SOCKADDR_MEMB(s, rc);
-				bdaddr_t* bdaddr = &_BT_RC_MEMB(addr, bdaddr);
-
-				_BT_RC_MEMB(addr, family) = AF_BLUETOOTH;
-				if( !PyArg_ParseTuple(args, "(iiiiii)i", &bdaddr->b[0], &bdaddr->b[1], &bdaddr->b[2], &bdaddr->b[3], &bdaddr->b[4], &bdaddr->b[5], &_BT_RC_MEMB(addr, channel)) )
-				{
-					PyErr_SetString(socket_error, "getsockaddrarg: wrong format");
-					return 0;
-				}
-
-				*addr_ret = (struct sockaddr *) addr;
-				*len_ret = sizeof *addr;
-				return 1;
-			}
-#if !defined(__FreeBSD__)
-			case BTPROTO_SCO:
-			{
-				struct sockaddr_sco* addr = (struct sockaddr_sco*)_BT_SOCKADDR_MEMB(s, sco);
-				bdaddr_t* bdaddr = &_BT_SCO_MEMB(addr, bdaddr);
-
-				_BT_SCO_MEMB(addr, family) = AF_BLUETOOTH;
-				if( !PyArg_ParseTuple(args, "iiiiii", &bdaddr->b[0], &bdaddr->b[1], &bdaddr->b[2], &bdaddr->b[3], &bdaddr->b[4], &bdaddr->b[5]) )
-				{
-					PyErr_SetString(socket_error, "getsockaddrarg: wrong format");
-					return 0;
-				}
-
-				*addr_ret = (struct sockaddr *) addr;
-				*len_ret = sizeof *addr;
-				return 1;
-			}
-#endif
-			default:
-			{
-				PyErr_SetString(socket_error, "getsockaddrarg: unknown Bluetooth protocol");
+			if (setbdaddr(straddr, &_BT_L2_MEMB(addr, bdaddr)) < 0)
+				return 0;
+
+			*addr_ret = (struct sockaddr *) addr;
+			*len_ret = sizeof *addr;
+			return 1;
+		}
+		case BTPROTO_RFCOMM:
+		{
+			struct sockaddr_rc *addr = (struct sockaddr_rc *) _BT_SOCKADDR_MEMB(s, rc);
+			char *straddr;
+
+			_BT_RC_MEMB(addr, family) = AF_BLUETOOTH;
+			if (!PyArg_ParseTuple(args, "si", &straddr,
+					      &_BT_RC_MEMB(addr, channel))) {
+				PyErr_SetString(socket_error, "getsockaddrarg: "
+						"wrong format");
 				return 0;
 			}
+			if (setbdaddr(straddr, &_BT_RC_MEMB(addr, bdaddr)) < 0)
+				return 0;
+
+			*addr_ret = (struct sockaddr *) addr;
+			*len_ret = sizeof *addr;
+			return 1;
+		}
+#if !defined(__FreeBSD__)
+		case BTPROTO_SCO:
+		{
+			struct sockaddr_sco *addr = (struct sockaddr_sco *) _BT_SOCKADDR_MEMB(s, sco);
+			char *straddr;
+
+			_BT_SCO_MEMB(addr, family) = AF_BLUETOOTH;
+			straddr = PyString_AsString(args);
+			if (straddr == NULL) {
+				PyErr_SetString(socket_error, "getsockaddrarg: "
+						"wrong format");
+				return 0;
+			}
+			if (setbdaddr(straddr, &_BT_SCO_MEMB(addr, bdaddr)) < 0)
+				return 0;
+
+			*addr_ret = (struct sockaddr *) addr;
+			*len_ret = sizeof *addr;
+			return 1;
+		}
+#endif
+		default:
+			PyErr_SetString(socket_error, "getsockaddrarg: unknown Bluetooth protocol");
+			return 0;
 		}
 	}
 #endif
@@ -1193,28 +1287,23 @@
 	{
 		switch(s->sock_proto)
 		{
-			case BTPROTO_L2CAP:
-			{
-				*len_ret = sizeof (struct sockaddr_l2);
-				return 1;
-			}
-			case BTPROTO_RFCOMM:
-			{
-				*len_ret = sizeof (struct sockaddr_rc);
-				return 1;
-			}
+
+		case BTPROTO_L2CAP:
+			*len_ret = sizeof (struct sockaddr_l2);
+			return 1;
+		case BTPROTO_RFCOMM:
+			*len_ret = sizeof (struct sockaddr_rc);
+			return 1;
 #if !defined(__FreeBSD__)
-			case BTPROTO_SCO:
-			{
-				*len_ret = sizeof (struct sockaddr_sco);
-				return 1;
-			}
-#endif
-			default:
-			{
-				PyErr_SetString(socket_error, "getsockaddrlen: unknown BT protocol");
-				return 0;
-			}
+		case BTPROTO_SCO:
+			*len_ret = sizeof (struct sockaddr_sco);
+			return 1;
+#endif
+		default:
+			PyErr_SetString(socket_error, "getsockaddrlen: "
+					"unknown BT protocol");
+			return 0;
+
 		}
 	}
 #endif
@@ -1291,7 +1380,7 @@
 		goto finally;
 	}
 	addr = makesockaddr(s->sock_fd, (struct sockaddr *)addrbuf,
-			    addrlen);
+			    addrlen, s->sock_proto);
 	if (addr == NULL)
 		goto finally;
 
@@ -1754,7 +1843,8 @@
 	Py_END_ALLOW_THREADS
 	if (res < 0)
 		return s->errorhandler();
-	return makesockaddr(s->sock_fd, (struct sockaddr *) addrbuf, addrlen);
+	return makesockaddr(s->sock_fd, (struct sockaddr *) addrbuf, addrlen,
+			    s->sock_proto);
 }
 
 PyDoc_STRVAR(getsockname_doc,
@@ -1782,7 +1872,8 @@
 	Py_END_ALLOW_THREADS
 	if (res < 0)
 		return s->errorhandler();
-	return makesockaddr(s->sock_fd, (struct sockaddr *) addrbuf, addrlen);
+	return makesockaddr(s->sock_fd, (struct sockaddr *) addrbuf, addrlen,
+			    s->sock_proto);
 }
 
 PyDoc_STRVAR(getpeername_doc,
@@ -2037,7 +2128,7 @@
 		return NULL;
 
 	if (!(addr = makesockaddr(s->sock_fd, (struct sockaddr *)addrbuf,
-				  addrlen)))
+				  addrlen, s->sock_proto)))
 		goto finally;
 
 	ret = PyTuple_Pack(2, buf, addr);
@@ -3259,7 +3350,7 @@
 		goto err;
 	for (res = res0; res; res = res->ai_next) {
 		PyObject *addr =
-			makesockaddr(-1, res->ai_addr, res->ai_addrlen);
+			makesockaddr(-1, res->ai_addr, res->ai_addrlen, protocol);
 		if (addr == NULL)
 			goto err;
 		single = Py_BuildValue("iiisO", res->ai_family,
@@ -3717,8 +3808,8 @@
 	PyModule_AddIntConstant(m, "BTPROTO_SCO", BTPROTO_SCO);
 #endif
 	PyModule_AddIntConstant(m, "BTPROTO_RFCOMM", BTPROTO_RFCOMM);
-	PyModule_AddObject(m, "BDADDR_ANY", Py_BuildValue( "iiiiii", 0,0,0,0,0,0 ) );
-	PyModule_AddObject(m, "BDADDR_LOCAL", Py_BuildValue( "iiiiii", 0,0,0,0xff,0xff,0xff ) );
+	PyModule_AddObject(m, "BDADDR_ANY", Py_BuildValue("s", "00:00:00:00:00:00"));
+	PyModule_AddObject(m, "BDADDR_LOCAL", Py_BuildValue("s", "00:00:00:FF:FF:FF"));
 #endif
 
 #ifdef HAVE_NETPACKET_PACKET_H