Author: ArcRiley Date: 2009-01-30 23:23:14 -0500 (Fri, 30 Jan 2009) New Revision: 1509
Modified: trunk/concordance/src/sockets/Client.c trunk/concordance/src/sockets/Socket.c Log: work in progress Modified: trunk/concordance/src/sockets/Client.c =================================================================== --- trunk/concordance/src/sockets/Client.c 2009-01-26 20:31:29 UTC (rev 1508) +++ trunk/concordance/src/sockets/Client.c 2009-01-31 04:23:14 UTC (rev 1509) @@ -33,7 +33,28 @@ /* first inherit base type */ self = (socketsClient_Object*) socketsSocket_new(type, args, kwds); + if (!self) + return NULL; + /* set default for client port + + xmpp-client 5222/tcp # XMPP Client Connection + + XEP-0035 (SSL/TLS Integration) : + Traditionally, Jabber servers has supported TLS by utilising a + "wrapper" around the standard protocol stream. This wrapper usually + listens on a port other than those listed in the IANA registry + (commonly 5223 for client-to-server communications and 5270 for + server-to-server communications). In the case of client-to-server + communications, clients must initiate a TLS session immediately after + connecting, before beginning the normal XML stream. This method of + utilising TLS is typical of many servers that implement stream-based + protocols, but has a number of flaws, which are outlined in section 7 + of RFC 2595. Accordingly, the use of port 5223 and port 5270 for + secure sessions is deprecated. + */ + self->port = 5222; + /* return self */ return (PyObject*) self; } Modified: trunk/concordance/src/sockets/Socket.c =================================================================== --- trunk/concordance/src/sockets/Socket.c 2009-01-26 20:31:29 UTC (rev 1508) +++ trunk/concordance/src/sockets/Socket.c 2009-01-31 04:23:14 UTC (rev 1509) @@ -33,8 +33,16 @@ /* first inherit base type */ self = (socketsSocket_Object*) PyType_GenericNew(type, args, kwds); + if (!self) + return NULL; - /* start with closed socket */ + /* set addr, port, and sock to default values + + 0.0.0.0 = listen to every available interface + port is overridden by child class + */ + self->addr = "0.0.0.0"; + self->port = 0; self->sock = -1; /* Get a reference to our local module @@ -68,8 +76,149 @@ socketsSocket_init(PyObject* s, PyObject* args, PyObject* kwds) { /*\ cdef : \*/ socketsSocket_Object* self = (socketsSocket_Object*) s; - - return 0; + int ret; + struct addrinfo* resinfo = NULL; + + /* parse arguments and keywords + + From http://docs.python.org/3.0/c-api/arg.html : + | Indicates that the remaining arguments in the Python argument list + are optional. The C variables corresponding to optional arguments + should be initialized to their default value — when an optional + argument is not specified, PyArg_ParseTuple does not touch the + contents of the corresponding C variable(s). + s Convert a Python string or Unicode object to a C pointer to a + character string. You must not provide storage for the string + itself; a pointer to an existing string is stored into the + character pointer variable whose address you pass. The C string is + NUL-terminated. The Python string must not contain embedded NUL + bytes; if it does, a TypeError exception is raised. Unicode + objects are converted to C strings using the default encoding. If + this conversion fails, a UnicodeError is raised. + H Convert a Python integer to a C unsigned short int, without + overflow checking. + : The list of format units ends here; the string after the colon is + used as the function name in error messages (the “associated + value” of the exception that PyArg_ParseTuple raises). + */ + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sH:Socket", kwlist, + &self->addr, &self->port)) + return -1; + + if (self->port == 0) { + PyErr_SetString(PyExc_AttributeError, "invalid port"); + return -1; + } + + /* Get address family and struct + + int getaddrinfo(const char *node, const char *service, + const struct addrinfo *hints, + struct addrinfo **res); + getaddrinfo() returns 0 if it succeeds, or non-zero on failure. + */ + ret = getaddrinfo(self->addr, NULL, NULL, &resinfo); + if (ret != 0) { + switch (ret) { + case EAI_AGAIN : { + /* EAI_AGAIN + The name server returned a temporary failure indication. + Try again later. */ + PyErr_SetString(PyExc_OSError, "temporary dns failure"); + break; + } + case EAI_FAIL : { + /* EAI_FAIL + The name server returned a permanent failure indication. */ + PyErr_SetString(PyExc_OSError, "permanent dns failure"); + break; + } + case EAI_FAMILY : { + /* EAI_FAMILY + The requested address family is not supported. */ + PyErr_SetString(PyExc_OSError, "address family not supported"); + break; + } + case EAI_MEMORY : { + /* EAI_MEMORY + Out of memory. */ + PyErr_SetString(PyExc_MemoryError, "out of memory on getaddrinfo"); + break; + } + case EAI_NODATA : { + /* EAI_NODATA + The specified network host exists, but does not have any + network addresses defined. */ + PyErr_SetString(PyExc_AttributeError, "host lacks IP address"); + break; + } + default : { + PyErr_SetString(PyExc_AttributeError, "invalid address/hostname"); + break; + } + } + return -1; + } + + /* Copy port into sockaddr struct + + uint16_t htons(uint16_t hostshort); + The htons() function converts the unsigned short integer hostshort + from host byte order to network byte order. + */ + ((struct sockaddr_in*) resinfo->ai_addr)->sin_port = htons(self->port); + + /* Open new socket of the appropriate family (AF_INET or AF_INET6) + + int socket(int domain, int type, int protocol); + */ + self->sock = socket(resinfo->ai_family, SOCK_STREAM, 0); + + /* If successful continue to bind/listen, else set error message */ + if (self->sock > -1) { + /* Bind and Listen to opened socket + + int bind(int fd, const struct sockaddr *addr, + socklen_t addrlen); + On success, zero is returned. On error, -1 is returned. + + int listen(int fd, int backlog); + On success, zero is returned. On error, -1 is returned. + */ + if (bind(self->sock, resinfo->ai_addr, resinfo->ai_addrlen) == 0 && + listen(self->sock, 16) == 0 ) { + + /* create channel and add it to our context watchlist + + GIOChannel* concordAddSocket (gint fd, + GIOCondition condition, + GSourceFunc callback, + gpointer data, + GMainContext* context); + */ + self->chan = concordAddSocket(self->sock, G_IO_IN, + (GSourceFunc) concordCore_listenNew, + (gpointer) self, self->context); + ret = 0; + } + else { + PyErr_SetString(PyExc_OSError, "unable to bind listening socket"); + ret = -1; + } + } + else { + PyErr_SetString(PyExc_OSError, "unable to bind listening socket"); + ret = -1; + } + + /* before returning, free the previously created resinfo struct + + void freeaddrinfo(struct addrinfo *res); + */ + if (resinfo) + freeaddrinfo(resinfo); + + return ret; } _______________________________________________ PySoy-SVN mailing list PySoy-SVN@pysoy.org http://www.pysoy.org/mailman/listinfo/pysoy-svn