diff -u -r -x *.o -x *.a -x *.la -x .DS* -x *.pyc -x Make* -x setup* python-orig/dist/src/Modules/socketmodule.c python/dist/src/Modules/socketmodule.c --- python-orig/dist/src/Modules/socketmodule.c Sun Mar 30 14:31:52 2003 +++ python/dist/src/Modules/socketmodule.c Fri Apr 4 06:52:10 2003 @@ -305,6 +305,7 @@ some of which call new_sockobject(), which uses sock_type, so there has to be a circular reference. */ static PyTypeObject sock_type; +static PyTypeObject sockaddr_type; /* Convenience function to raise an error according to errno and return a NULL pointer from a function. */ @@ -835,6 +836,18 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, struct sockaddr **addr_ret, int *len_ret) { + if (args->ob_type==&sockaddr_type) { + PySocketSockAddrObject *sa=(PySocketSockAddrObject *)args; + /*handle pre-parsed sockaddr addresses*/ + if (sa->sock_family!=s->sock_family) { + PyErr_SetString(PyExc_ValueError,"Socket and address family mismatch"); + return 0; + } + *addr_ret=sa->addr; + *len_ret=sa->addrlen; + return 1; + } + switch (s->sock_family) { #if defined(AF_UNIX) && !defined(PYOS_OS2) @@ -1940,6 +1953,76 @@ of the socket (flag == 1), or both ends (flag == 2)."); + +/* Create a new socket binary address object. This is ready to pass to internal_connect. + This just creates the object and initializes it. + If the creation fails, return NULL and set an exception (implicit + in NEWOBJ()). */ + +/* Initialize a new sockaddr object. */ +static int +sockaddr_initobj(PyObject *self, PyObject *args, PyObject *kwargs) +{ + PySocketSockObject tempsock; + PySocketSockAddrObject *sa = (PySocketSockAddrObject *)self; + PyObject *address=NULL; + int family, addrlen; + static char *keywords[] = {"family", "data", "address", 0}; + struct sockaddr *data=NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "i|s#O:sockaddr", keywords, &family, &data, &addrlen, &address)) return -1; + + if (data==NULL && address==NULL) { + PyErr_SetString(PyExc_AssertionError, "No data or address provided to sockaddr(family, {data= | address=})"); + return -1; + } + if (address != NULL) { /* if addr (a normal socket address) is present, parse it */ + int res; + tempsock.sock_family=family; + res=getsockaddrarg(&tempsock, address, &data, &addrlen); + if (!res) return -1; /*address couldn't be parsed, and has set its own error code */ + } + /* now we should have a valid address object, either directly from data or from a parsed address */ + sa->sock_family=family; /* tag it with the right family */ + sa->addr=PyMem_Malloc(addrlen); + sa->addrlen=addrlen; /*and save it internally*/ + memcpy(sa->addr,data,addrlen); + return 0; +} + +PyDoc_STRVAR(sockaddr_doc, +"=sockaddr(family, {data= | address=})\n\ +\n\ +Convert address string appropriate to the socket's AF into a binary sockaddr object, \n\ +or, take an already converted binary string (obtained by converting an address, and then using\n\ +sockaddr.to_tuple() to get the family and string) and re-wrap it.\n\ +The sockaddr object can be used as an argument to socket.connect() to allow connecting quickly,\n\ +without any re-parsing of the address.\n"); + +static void +sockaddr_dealloc(PySocketSockAddrObject *sa) +{ + PyMem_Free(sa->addr); + sa->ob_type->tp_free((PyObject *)sa); +} + +static PyObject * +sockaddr_repr(PySocketSockAddrObject *sa) +{ + return PyString_FromString(".to_tuple() to get contents>"); +} + +static PyObject * +sockaddr_to_tuple(PySocketSockAddrObject *sa) +{ + return Py_BuildValue("is#", sa->sock_family, sa->addr, sa->addrlen); +} + +PyDoc_STRVAR(sockaddr_to_tuple_doc, +"sockaddr.to_tuple()\n\ +\n\ +Convert sockaddr to a tuple of (
, )\n"); /* List of methods for socket objects */ static PyMethodDef sock_methods[] = { @@ -2000,6 +2083,12 @@ {NULL, NULL} /* sentinel */ }; +static PyMethodDef sockaddr_methods[] = { + {"to_tuple", (PyCFunction)sockaddr_to_tuple, METH_NOARGS, + sockaddr_to_tuple_doc}, + {NULL, NULL} /* sentinel */ +}; + /* Deallocate a socket object in response to the last Py_DECREF(). First close the file description. */ @@ -2141,6 +2230,51 @@ PyObject_Del, /* tp_free */ }; +/* Type object for sockaddr objects. */ + +static PyTypeObject sockaddr_type = { + PyObject_HEAD_INIT(0) /* Must fill in type value later */ + 0, /* ob_size */ + "_socket.sockaddr", /* tp_name */ + sizeof(PySocketSockAddrObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)sockaddr_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)sockaddr_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + sockaddr_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + sockaddr_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + sockaddr_initobj, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ + PyObject_Del, /* tp_free */ +}; + /* Python interface to gethostname(). */ @@ -3164,6 +3298,7 @@ return; sock_type.ob_type = &PyType_Type; + sockaddr_type.ob_type = &PyType_Type; m = Py_InitModule3(PySocket_MODULE_NAME, socket_methods, socket_doc); @@ -3193,6 +3328,18 @@ if (PyModule_AddObject(m, "socket", (PyObject *)&sock_type) != 0) return; +#if 1 + /* new wrappers for parsed socket addresses */ + Py_INCREF((PyObject *)&sockaddr_type); + if (PyModule_AddObject(m, "SockAddrType", + (PyObject *)&sockaddr_type) != 0) + return; + + Py_INCREF((PyObject *)&sockaddr_type); + if (PyModule_AddObject(m, "sockaddr", + (PyObject *)&sockaddr_type) != 0) + return; +#endif /* Export C API */ if (PyModule_AddObject(m, PySocket_CAPI_NAME, diff -u -r -x *.o -x *.a -x *.la -x .DS* -x *.pyc -x Make* -x setup* python-orig/dist/src/Modules/socketmodule.h python/dist/src/Modules/socketmodule.h --- python-orig/dist/src/Modules/socketmodule.h Sun Mar 30 14:31:52 2003 +++ python/dist/src/Modules/socketmodule.h Sun Mar 30 20:09:57 2003 @@ -87,6 +87,14 @@ 0.0 means non-blocking */ } PySocketSockObject; +typedef struct { + PyObject_HEAD + int sock_family; /* Address family, e.g., AF_INET */ + void *addr; /* pointer to object data */ + int addrlen; /* length of object data */ + +} PySocketSockAddrObject; + /* --- C API ----------------------------------------------------*/ /* Short explanation of what this C API export mechanism does