<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[12104] twext/trunk/twext</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/12104">12104</a></dd>
<dt>Author</dt> <dd>wsanchez@apple.com</dd>
<dt>Date</dt> <dd>2013-12-13 20:18:37 -0800 (Fri, 13 Dec 2013)</dd>
</dl>
<h3>Log Message</h3>
<pre>Get rid of sendmsg; twisted has it</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#twexttrunktwextinternetsendfdportpy">twext/trunk/twext/internet/sendfdport.py</a></li>
<li><a href="#twexttrunktwextinternettesttest_fswatchpy">twext/trunk/twext/internet/test/test_fswatch.py</a></li>
<li><a href="#twexttrunktwextpythonsendfdpy">twext/trunk/twext/python/sendfd.py</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#twexttrunktwextpythonsendmsgc">twext/trunk/twext/python/sendmsg.c</a></li>
<li><a href="#twexttrunktwextpythontesttest_sendmsgpy">twext/trunk/twext/python/test/test_sendmsg.py</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="twexttrunktwextinternetsendfdportpy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/internet/sendfdport.py (12103 => 12104)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/internet/sendfdport.py        2013-12-14 04:04:50 UTC (rev 12103)
+++ twext/trunk/twext/internet/sendfdport.py        2013-12-14 04:18:37 UTC (rev 12104)
</span><span class="lines">@@ -16,24 +16,24 @@
</span><span class="cx"> ##
</span><span class="cx">
</span><span class="cx"> """
</span><del>-Implementation of a TCP/SSL port that uses sendmsg/recvmsg as implemented by
-L{twext.python.sendfd}.
</del><ins>+Implementation of a TCP/SSL port that uses send1msg/recv1msg as implemented by
+L{twisted.python.sendfd}.
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> from os import close
</span><span class="cx"> from errno import EAGAIN, ENOBUFS
</span><del>-from socket import (socketpair, fromfd, error as SocketError, AF_UNIX,
- SOCK_STREAM, SOCK_DGRAM)
</del><ins>+from socket import (
+ socketpair, fromfd, error as SocketError, AF_UNIX, SOCK_STREAM, SOCK_DGRAM
+)
</ins><span class="cx">
</span><span class="cx"> from zope.interface import Interface
</span><span class="cx">
</span><ins>+from twisted.python.sendmsg import send1msg, recv1msg, getsockfam
</ins><span class="cx"> from twisted.internet.abstract import FileDescriptor
</span><span class="cx"> from twisted.internet.protocol import Protocol, Factory
</span><span class="cx">
</span><span class="cx"> from twext.python.log import Logger
</span><del>-from twext.python.sendmsg import sendmsg, recvmsg
</del><span class="cx"> from twext.python.sendfd import sendfd, recvfd
</span><del>-from twext.python.sendmsg import getsockfam
</del><span class="cx">
</span><span class="cx"> log = Logger()
</span><span class="cx">
</span><span class="lines">@@ -94,7 +94,7 @@
</span><span class="cx"> A socket in the master process pointing at a file descriptor that can be
</span><span class="cx"> used to transmit sockets to a subprocess.
</span><span class="cx">
</span><del>- @ivar outSocket: the UNIX socket used as the sendmsg() transport.
</del><ins>+ @ivar outSocket: the UNIX socket used as the send1msg() transport.
</ins><span class="cx"> @type outSocket: L{socket.socket}
</span><span class="cx">
</span><span class="cx"> @ivar outgoingSocketQueue: an outgoing queue of sockets to send to the
</span><span class="lines">@@ -104,10 +104,11 @@
</span><span class="cx"> @ivar outgoingSocketQueue: a C{list} of 2-tuples of C{(socket-object,
</span><span class="cx"> bytes)}
</span><span class="cx">
</span><del>- @ivar status: a record of the last status message received (via recvmsg)
- from the subprocess: this is an application-specific indication of how
- ready this subprocess is to receive more connections. A typical usage
- would be to count the open connections: this is what is passed to
</del><ins>+ @ivar status: a record of the last status message received (via
+ L{recv1msg}) from the subprocess: this is an application-specific
+ indication of how ready this subprocess is to receive more connections.
+ A typical usage would be to count the open connections: this is what is
+ passed to
</ins><span class="cx"> @type status: See L{IStatusWatcher} for an explanation of which methods
</span><span class="cx"> determine this type.
</span><span class="cx">
</span><span class="lines">@@ -134,12 +135,14 @@
</span><span class="cx"> self.startWriting()
</span><span class="cx">
</span><span class="cx">
</span><del>- def doRead(self, recvmsg=recvmsg):
</del><ins>+ def doRead(self, recvmsg=recv1msg):
</ins><span class="cx"> """
</span><span class="cx"> Receive a status / health message and record it.
</span><span class="cx"> """
</span><span class="cx"> try:
</span><del>- data, _ignore_flags, _ignore_ancillary = recvmsg(self.outSocket.fileno())
</del><ins>+ data, _ignore_flags, _ignore_ancillary = recvmsg(
+ self.outSocket.fileno()
+ )
</ins><span class="cx"> except SocketError, se:
</span><span class="cx"> if se.errno not in (EAGAIN, ENOBUFS):
</span><span class="cx"> raise
</span><span class="lines">@@ -198,7 +201,7 @@
</span><span class="cx"> than the somewhat more abstract language that would be accurate.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- def initialStatus(): #@NoSelf
</del><ins>+ def initialStatus():
</ins><span class="cx"> """
</span><span class="cx"> A new socket was created and added to the dispatcher. Compute an
</span><span class="cx"> initial value for its status.
</span><span class="lines">@@ -207,7 +210,7 @@
</span><span class="cx"> """
</span><span class="cx">
</span><span class="cx">
</span><del>- def newConnectionStatus(previousStatus): #@NoSelf
</del><ins>+ def newConnectionStatus(previousStatus):
</ins><span class="cx"> """
</span><span class="cx"> A new connection was sent to a given socket. Compute its status based
</span><span class="cx"> on the previous status of that socket.
</span><span class="lines">@@ -219,7 +222,7 @@
</span><span class="cx"> """
</span><span class="cx">
</span><span class="cx">
</span><del>- def statusFromMessage(previousStatus, message): #@NoSelf
</del><ins>+ def statusFromMessage(previousStatus, message):
</ins><span class="cx"> """
</span><span class="cx"> A status message was received by a worker. Convert the previous status
</span><span class="cx"> value (returned from L{newConnectionStatus}, L{initialStatus}, or
</span><span class="lines">@@ -233,7 +236,7 @@
</span><span class="cx"> """
</span><span class="cx">
</span><span class="cx">
</span><del>- def closeCountFromStatus(previousStatus): #@NoSelf
</del><ins>+ def closeCountFromStatus(previousStatus):
</ins><span class="cx"> """
</span><span class="cx"> Based on a status previously returned from a method on this
</span><span class="cx"> L{IStatusWatcher}, determine how many sockets may be closed.
</span><span class="lines">@@ -332,7 +335,7 @@
</span><span class="cx">
</span><span class="cx"> def addSocket(self, socketpair=lambda: socketpair(AF_UNIX, SOCK_DGRAM)):
</span><span class="cx"> """
</span><del>- Add a C{sendmsg()}-oriented AF_UNIX socket to the pool of sockets being
</del><ins>+ Add a L{send1msg}-oriented AF_UNIX socket to the pool of sockets being
</ins><span class="cx"> used for transmitting file descriptors to child processes.
</span><span class="cx">
</span><span class="cx"> @return: a socket object for the receiving side; pass this object's
</span><span class="lines">@@ -367,13 +370,13 @@
</span><span class="cx"> """
</span><span class="cx"> An L{InheritedPort} is an L{IReadDescriptor}/L{IWriteDescriptor} created in
</span><span class="cx"> the I{worker process} to handle incoming connections dispatched via
</span><del>- C{sendmsg}.
</del><ins>+ L{send1msg}.
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> def __init__(self, fd, transportFactory, protocolFactory):
</span><span class="cx"> """
</span><span class="cx"> @param fd: the file descriptor representing a UNIX socket connected to
</span><del>- a I{master process}. We will call C{recvmsg} on this socket to
</del><ins>+ a I{master process}. We will call L{recv1msg} on this socket to
</ins><span class="cx"> receive file descriptors.
</span><span class="cx"> @type fd: C{int}
</span><span class="cx">
</span><span class="lines">@@ -434,7 +437,7 @@
</span><span class="cx"> while self.statusQueue:
</span><span class="cx"> msg = self.statusQueue.pop(0)
</span><span class="cx"> try:
</span><del>- sendmsg(self.fd, msg, 0)
</del><ins>+ send1msg(self.fd, msg, 0)
</ins><span class="cx"> except SocketError, se:
</span><span class="cx"> if se.errno in (EAGAIN, ENOBUFS):
</span><span class="cx"> self.statusQueue.insert(0, msg)
</span></span></pre></div>
<a id="twexttrunktwextinternettesttest_fswatchpy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/internet/test/test_fswatch.py (12103 => 12104)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/internet/test/test_fswatch.py        2013-12-14 04:04:50 UTC (rev 12103)
+++ twext/trunk/twext/internet/test/test_fswatch.py        2013-12-14 04:18:37 UTC (rev 12104)
</span><span class="lines">@@ -18,8 +18,9 @@
</span><span class="cx"> Tests for L{twext.internet.fswatch}.
</span><span class="cx"> """
</span><span class="cx">
</span><del>-from twext.internet.fswatch import DirectoryChangeListener, patchReactor, \
- IDirectoryChangeListenee
</del><ins>+from twext.internet.fswatch import (
+ DirectoryChangeListener, patchReactor, IDirectoryChangeListenee
+)
</ins><span class="cx"> from twisted.internet.kqreactor import KQueueReactor
</span><span class="cx"> from twisted.python.filepath import FilePath
</span><span class="cx"> from twisted.trial.unittest import TestCase
</span></span></pre></div>
<a id="twexttrunktwextpythonsendfdpy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/python/sendfd.py (12103 => 12104)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/python/sendfd.py        2013-12-14 04:04:50 UTC (rev 12103)
+++ twext/trunk/twext/python/sendfd.py        2013-12-14 04:18:37 UTC (rev 12104)
</span><span class="lines">@@ -18,15 +18,17 @@
</span><span class="cx"> from struct import pack, unpack, calcsize
</span><span class="cx"> from socket import SOL_SOCKET
</span><span class="cx">
</span><del>-from twext.python.sendmsg import sendmsg, recvmsg, SCM_RIGHTS
</del><ins>+from twisted.python.sendmsg import send1msg, recv1msg, SCM_RIGHTS
</ins><span class="cx">
</span><ins>+
+
</ins><span class="cx"> def sendfd(socketfd, fd, description):
</span><span class="cx"> """
</span><del>- Send the given FD to another process via L{sendmsg} on the given C{AF_UNIX}
- socket.
</del><ins>+ Send the given FD to another process via L{send1msg} on the given
+ C{AF_UNIX} socket.
</ins><span class="cx">
</span><span class="cx"> @param socketfd: An C{AF_UNIX} socket, attached to another process waiting
</span><del>- to receive sockets via the ancillary data mechanism in L{sendmsg}.
</del><ins>+ to receive sockets via the ancillary data mechanism in L{send1msg}.
</ins><span class="cx">
</span><span class="cx"> @type socketfd: C{int}
</span><span class="cx">
</span><span class="lines">@@ -38,7 +40,7 @@
</span><span class="cx">
</span><span class="cx"> @type description: C{str}
</span><span class="cx"> """
</span><del>- sendmsg(
</del><ins>+ send1msg(
</ins><span class="cx"> socketfd, description, 0, [(SOL_SOCKET, SCM_RIGHTS, pack("i", fd))]
</span><span class="cx"> )
</span><span class="cx">
</span><span class="lines">@@ -46,11 +48,11 @@
</span><span class="cx">
</span><span class="cx"> def recvfd(socketfd):
</span><span class="cx"> """
</span><del>- Receive a file descriptor from a L{sendmsg} message on the given C{AF_UNIX}
- socket.
</del><ins>+ Receive a file descriptor from a L{send1msg} message on the given
+ C{AF_UNIX} socket.
</ins><span class="cx">
</span><span class="cx"> @param socketfd: An C{AF_UNIX} socket, attached to another process waiting
</span><del>- to send sockets via the ancillary data mechanism in L{sendmsg}.
</del><ins>+ to send sockets via the ancillary data mechanism in L{send1msg}.
</ins><span class="cx">
</span><span class="cx"> @param fd: C{int}
</span><span class="cx">
</span><span class="lines">@@ -58,15 +60,18 @@
</span><span class="cx">
</span><span class="cx"> @rtype: 2-tuple of (C{int}, C{str})
</span><span class="cx"> """
</span><del>- data, _ignore_flags, ancillary = recvmsg(socketfd)
</del><ins>+ data, _ignore_flags, ancillary = recv1msg(socketfd)
</ins><span class="cx"> [(_ignore_cmsg_level, _ignore_cmsg_type, packedFD)] = ancillary
</span><ins>+
</ins><span class="cx"> # cmsg_level and cmsg_type really need to be SOL_SOCKET / SCM_RIGHTS, but
</span><span class="cx"> # since those are the *only* standard values, there's not much point in
</span><span class="cx"> # checking.
</span><span class="cx"> unpackedFD = 0
</span><span class="cx"> int_size = calcsize("i")
</span><del>- if len(packedFD) > int_size: # [ar]happens on 64 bit architecture (FreeBSD)
</del><ins>+
+ if len(packedFD) > int_size: # [ar]happens on 64 bit arch (FreeBSD)
</ins><span class="cx"> [unpackedFD] = unpack("i", packedFD[0:int_size])
</span><span class="cx"> else:
</span><span class="cx"> [unpackedFD] = unpack("i", packedFD)
</span><ins>+
</ins><span class="cx"> return (unpackedFD, data)
</span></span></pre></div>
<a id="twexttrunktwextpythonsendmsgc"></a>
<div class="delfile"><h4>Deleted: twext/trunk/twext/python/sendmsg.c (12103 => 12104)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/python/sendmsg.c        2013-12-14 04:04:50 UTC (rev 12103)
+++ twext/trunk/twext/python/sendmsg.c        2013-12-14 04:18:37 UTC (rev 12104)
</span><span class="lines">@@ -1,423 +0,0 @@
</span><del>-/*
- * Copyright (c) 2010-2013 Apple Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define PY_SSIZE_T_CLEAN 1
-#include <Python.h>
-
-#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
-/* This may cause some warnings, but if you want to get rid of them, upgrade
- * your Python version. */
-typedef int Py_ssize_t;
-#endif
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <signal.h>
-
-/*
- * As per
- * <http://pubs.opengroup.org/onlinepubs/007904875/basedefs/sys/socket.h.html
- * #tag_13_61_05>:
- *
- * "To forestall portability problems, it is recommended that applications
- * not use values larger than (2**31)-1 for the socklen_t type."
- */
-
-#define SOCKLEN_MAX 0x7FFFFFFF
-
-PyObject *sendmsg_socket_error;
-
-static PyObject *sendmsg_sendmsg(PyObject *self, PyObject *args, PyObject *keywds);
-static PyObject *sendmsg_recvmsg(PyObject *self, PyObject *args, PyObject *keywds);
-static PyObject *sendmsg_getsockfam(PyObject *self, PyObject *args, PyObject *keywds);
-
-static PyMethodDef sendmsg_methods[] = {
- {"sendmsg", (PyCFunction) sendmsg_sendmsg, METH_VARARGS | METH_KEYWORDS,
- NULL},
- {"recvmsg", (PyCFunction) sendmsg_recvmsg, METH_VARARGS | METH_KEYWORDS,
- NULL},
- {"getsockfam", (PyCFunction) sendmsg_getsockfam,
- METH_VARARGS | METH_KEYWORDS, NULL},
- {NULL, NULL, 0, NULL}
-};
-
-
-PyMODINIT_FUNC initsendmsg(void) {
- PyObject *module;
-
- sendmsg_socket_error = NULL; /* Make sure that this has a known value
- before doing anything that might exit. */
-
- module = Py_InitModule("sendmsg", sendmsg_methods);
-
- if (!module) {
- return;
- }
-
- /*
- The following is the only value mentioned by POSIX:
- http://www.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html
- */
-
- if (-1 == PyModule_AddIntConstant(module, "SCM_RIGHTS", SCM_RIGHTS)) {
- return;
- }
-
-
- /* BSD, Darwin, Hurd */
-#if defined(SCM_CREDS)
- if (-1 == PyModule_AddIntConstant(module, "SCM_CREDS", SCM_CREDS)) {
- return;
- }
-#endif
-
- /* Linux */
-#if defined(SCM_CREDENTIALS)
- if (-1 == PyModule_AddIntConstant(module, "SCM_CREDENTIALS", SCM_CREDENTIALS)) {
- return;
- }
-#endif
-
- /* Apparently everywhere, but not standardized. */
-#if defined(SCM_TIMESTAMP)
- if (-1 == PyModule_AddIntConstant(module, "SCM_TIMESTAMP", SCM_TIMESTAMP)) {
- return;
- }
-#endif
-
- module = PyImport_ImportModule("socket");
- if (!module) {
- return;
- }
-
- sendmsg_socket_error = PyObject_GetAttrString(module, "error");
- if (!sendmsg_socket_error) {
- return;
- }
-}
-
-static PyObject *sendmsg_sendmsg(PyObject *self, PyObject *args, PyObject *keywds) {
-
- int fd;
- int flags = 0;
- Py_ssize_t sendmsg_result, iovec_length;
- struct msghdr message_header;
- struct iovec iov[1];
- PyObject *ancillary = NULL;
- PyObject *ultimate_result = NULL;
- static char *kwlist[] = {"fd", "data", "flags", "ancillary", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(
- args, keywds, "it#|iO:sendmsg", kwlist,
- &fd,
- &iov[0].iov_base,
- &iovec_length,
- &flags,
- &ancillary)) {
- return NULL;
- }
-
- iov[0].iov_len = iovec_length;
-
- message_header.msg_name = NULL;
- message_header.msg_namelen = 0;
-
- message_header.msg_iov = iov;
- message_header.msg_iovlen = 1;
-
- message_header.msg_control = NULL;
- message_header.msg_controllen = 0;
-
- message_header.msg_flags = 0;
-
- if (ancillary) {
-
- if (!PyList_Check(ancillary)) {
- PyErr_Format(PyExc_TypeError,
- "sendmsg argument 3 expected list, got %s",
- ancillary->ob_type->tp_name);
- goto finished;
- }
-
- PyObject *iterator = PyObject_GetIter(ancillary);
- PyObject *item = NULL;
-
- if (iterator == NULL) {
- goto finished;
- }
-
- size_t all_data_len = 0;
-
- /* First we need to know how big the buffer needs to be in order to
- have enough space for all of the messages. */
- while ( (item = PyIter_Next(iterator)) ) {
- int type, level;
- Py_ssize_t data_len;
- size_t prev_all_data_len;
- char *data;
- if (!PyArg_ParseTuple(
- item, "iit#:sendmsg ancillary data (level, type, data)",
- &level, &type, &data, &data_len)) {
- Py_DECREF(item);
- Py_DECREF(iterator);
- goto finished;
- }
-
- prev_all_data_len = all_data_len;
- all_data_len += CMSG_SPACE(data_len);
-
- Py_DECREF(item);
-
- if (all_data_len < prev_all_data_len) {
- Py_DECREF(iterator);
- PyErr_Format(PyExc_OverflowError,
- "Too much msg_control to fit in a size_t: %zu",
- prev_all_data_len);
- goto finished;
- }
- }
-
- Py_DECREF(iterator);
- iterator = NULL;
-
- /* Allocate the buffer for all of the ancillary elements, if we have
- * any. */
- if (all_data_len) {
- if (all_data_len > SOCKLEN_MAX) {
- PyErr_Format(PyExc_OverflowError,
- "Too much msg_control to fit in a socklen_t: %zu",
- all_data_len);
- goto finished;
- }
- message_header.msg_control = malloc(all_data_len);
- if (!message_header.msg_control) {
- PyErr_NoMemory();
- goto finished;
- }
- }
- message_header.msg_controllen = (socklen_t) all_data_len;
-
- iterator = PyObject_GetIter(ancillary); /* again */
- item = NULL;
-
- if (!iterator) {
- goto finished;
- }
-
- /* Unpack the tuples into the control message. */
- struct cmsghdr *control_message = CMSG_FIRSTHDR(&message_header);
- while ( (item = PyIter_Next(iterator)) ) {
- int type, level;
- Py_ssize_t data_len;
- size_t data_size;
- unsigned char *data, *cmsg_data;
-
- /* We explicitly allocated enough space for all ancillary data
- above; if there isn't enough room, all bets are off. */
- assert(control_message);
-
- if (!PyArg_ParseTuple(item,
- "iit#:sendmsg ancillary data (level, type, data)",
- &level,
- &type,
- &data,
- &data_len)) {
- Py_DECREF(item);
- Py_DECREF(iterator);
- goto finished;
- }
-
- control_message->cmsg_level = level;
- control_message->cmsg_type = type;
- data_size = CMSG_LEN(data_len);
-
- if (data_size > SOCKLEN_MAX) {
- Py_DECREF(item);
- Py_DECREF(iterator);
- PyErr_Format(PyExc_OverflowError,
- "CMSG_LEN(%zd) > SOCKLEN_MAX", data_len);
- goto finished;
- }
-
- control_message->cmsg_len = (socklen_t) data_size;
-
- cmsg_data = CMSG_DATA(control_message);
- memcpy(cmsg_data, data, data_len);
-
- Py_DECREF(item);
-
- control_message = CMSG_NXTHDR(&message_header, control_message);
- }
-
- Py_DECREF(iterator);
-
- if (PyErr_Occurred()) {
- goto finished;
- }
- }
-
- sendmsg_result = sendmsg(fd, &message_header, flags);
-
- if (sendmsg_result < 0) {
- PyErr_SetFromErrno(sendmsg_socket_error);
- goto finished;
- } else {
- ultimate_result = Py_BuildValue("n", sendmsg_result);
- }
-
- finished:
- if (message_header.msg_control) {
- free(message_header.msg_control);
- }
- return ultimate_result;
-}
-
-static PyObject *sendmsg_recvmsg(PyObject *self, PyObject *args, PyObject *keywds) {
- int fd = -1;
- int flags = 0;
- int maxsize = 8192;
- int cmsg_size = 4*1024;
- size_t cmsg_space;
- Py_ssize_t recvmsg_result;
-
- struct msghdr message_header;
- struct cmsghdr *control_message;
- struct iovec iov[1];
- char *cmsgbuf;
- PyObject *ancillary;
- PyObject *final_result = NULL;
-
- static char *kwlist[] = {"fd", "flags", "maxsize", "cmsg_size", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|iii:recvmsg", kwlist,
- &fd, &flags, &maxsize, &cmsg_size)) {
- return NULL;
- }
-
- cmsg_space = CMSG_SPACE(cmsg_size);
-
- /* overflow check */
- if (cmsg_space > SOCKLEN_MAX) {
- PyErr_Format(PyExc_OverflowError,
- "CMSG_SPACE(cmsg_size) greater than SOCKLEN_MAX: %d",
- cmsg_size);
- return NULL;
- }
-
- message_header.msg_name = NULL;
- message_header.msg_namelen = 0;
-
- iov[0].iov_len = maxsize;
- iov[0].iov_base = malloc(maxsize);
-
- if (!iov[0].iov_base) {
- PyErr_NoMemory();
- return NULL;
- }
-
- message_header.msg_iov = iov;
- message_header.msg_iovlen = 1;
-
- cmsgbuf = malloc(cmsg_space);
-
- if (!cmsgbuf) {
- free(iov[0].iov_base);
- PyErr_NoMemory();
- return NULL;
- }
-
- memset(cmsgbuf, 0, cmsg_space);
- message_header.msg_control = cmsgbuf;
- /* see above for overflow check */
- message_header.msg_controllen = (socklen_t) cmsg_space;
-
- recvmsg_result = recvmsg(fd, &message_header, flags);
- if (recvmsg_result < 0) {
- PyErr_SetFromErrno(sendmsg_socket_error);
- goto finished;
- }
-
- ancillary = PyList_New(0);
- if (!ancillary) {
- goto finished;
- }
-
- for (control_message = CMSG_FIRSTHDR(&message_header);
- control_message;
- control_message = CMSG_NXTHDR(&message_header,
- control_message)) {
- PyObject *entry;
-
- /* Some platforms apparently always fill out the ancillary data
- structure with a single bogus value if none is provided; ignore it,
- if that is the case. */
-
- if ((!(control_message->cmsg_level)) &&
- (!(control_message->cmsg_type))) {
- continue;
- }
-
- entry = Py_BuildValue(
- "(iis#)",
- control_message->cmsg_level,
- control_message->cmsg_type,
- CMSG_DATA(control_message),
- (Py_ssize_t) (control_message->cmsg_len - sizeof(struct cmsghdr)));
-
- if (!entry) {
- Py_DECREF(ancillary);
- goto finished;
- }
-
- if (PyList_Append(ancillary, entry) < 0) {
- Py_DECREF(ancillary);
- Py_DECREF(entry);
- goto finished;
- } else {
- Py_DECREF(entry);
- }
- }
-
- final_result = Py_BuildValue(
- "s#iO",
- iov[0].iov_base,
- recvmsg_result,
- message_header.msg_flags,
- ancillary);
-
- Py_DECREF(ancillary);
-
- finished:
- free(iov[0].iov_base);
- free(cmsgbuf);
- return final_result;
-}
-
-static PyObject *sendmsg_getsockfam(PyObject *self, PyObject *args,
- PyObject *keywds) {
- int fd;
- struct sockaddr sa;
- static char *kwlist[] = {"fd", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, keywds, "i", kwlist, &fd)) {
- return NULL;
- }
- socklen_t sz = sizeof(sa);
- if (getsockname(fd, &sa, &sz)) {
- PyErr_SetFromErrno(sendmsg_socket_error);
- return NULL;
- }
- return Py_BuildValue("i", sa.sa_family);
-}
</del></span></pre></div>
<a id="twexttrunktwextpythontesttest_sendmsgpy"></a>
<div class="delfile"><h4>Deleted: twext/trunk/twext/python/test/test_sendmsg.py (12103 => 12104)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/python/test/test_sendmsg.py        2013-12-14 04:04:50 UTC (rev 12103)
+++ twext/trunk/twext/python/test/test_sendmsg.py        2013-12-14 04:18:37 UTC (rev 12104)
</span><span class="lines">@@ -1,172 +0,0 @@
</span><del>-##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-import socket
-from os import pipe, read, close, environ
-from twext.python.filepath import CachingFilePath as FilePath
-import sys
-
-from twisted.internet.defer import Deferred
-from twisted.internet.error import ProcessDone
-from twisted.trial.unittest import TestCase
-from twisted.internet.defer import inlineCallbacks
-from twisted.internet import reactor
-
-from twext.python.sendmsg import sendmsg, recvmsg
-from twext.python.sendfd import sendfd
-from twisted.internet.protocol import ProcessProtocol
-
-class ExitedWithStderr(Exception):
- """
- A process exited with some stderr.
- """
-
- def __str__(self):
- """
- Dump the errors in a pretty way in the event of a subprocess traceback.
- """
- return '\n'.join([''] + list(self.args))
-
-
-class StartStopProcessProtocol(ProcessProtocol):
- """
- An L{IProcessProtocol} with a Deferred for events where the subprocess
- starts and stops.
- """
-
- def __init__(self):
- self.started = Deferred()
- self.stopped = Deferred()
- self.output = ''
- self.errors = ''
-
- def connectionMade(self):
- self.started.callback(self.transport)
-
- def outReceived(self, data):
- self.output += data
-
- def errReceived(self, data):
- self.errors += data
-
- def processEnded(self, reason):
- if reason.check(ProcessDone):
- self.stopped.callback(self.output)
- else:
- self.stopped.errback(ExitedWithStderr(
- self.errors, self.output))
-
-
-
-def bootReactor():
- """
- Yield this from a trial test to bootstrap the reactor in order to avoid
- PotentialZombieWarning, for tests that use subprocesses. This hack will no
- longer be necessary in Twisted 10.1, since U{the underlying bug was fixed
- <http://twistedmatrix.com/trac/ticket/2078>}.
- """
- d = Deferred()
- reactor.callLater(0, d.callback, None)
- return d
-
-
-
-class SendmsgTestCase(TestCase):
- """
- Tests for sendmsg extension module and associated file-descriptor sending
- functionality in L{twext.python.sendfd}.
- """
-
- def setUp(self):
- """
- Create a pair of UNIX sockets.
- """
- self.input, self.output = socket.socketpair(socket.AF_UNIX)
-
-
- def tearDown(self):
- """
- Close the sockets opened by setUp.
- """
- self.input.close()
- self.output.close()
-
-
- def test_roundtrip(self):
- """
- L{recvmsg} will retrieve a message sent via L{sendmsg}.
- """
- sendmsg(self.input.fileno(), "hello, world!", 0)
-
- result = recvmsg(fd=self.output.fileno())
- self.assertEquals(result, ("hello, world!", 0, []))
-
-
- def test_wrongTypeAncillary(self):
- """
- L{sendmsg} will show a helpful exception message when given the wrong
- type of object for the 'ancillary' argument.
- """
- error = self.assertRaises(TypeError,
- sendmsg, self.input.fileno(),
- "hello, world!", 0, 4321)
- self.assertEquals(str(error),
- "sendmsg argument 3 expected list, got int")
-
-
- def spawn(self, script):
- """
- Start a script that is a peer of this test as a subprocess.
-
- @param script: the module name of the script in this directory (no
- package prefix, no '.py')
- @type script: C{str}
-
- @rtype: L{StartStopProcessProtocol}
- """
- sspp = StartStopProcessProtocol()
- reactor.spawnProcess(
- sspp, sys.executable, [
- sys.executable,
- FilePath(__file__).sibling(script + ".py").path,
- str(self.output.fileno()),
- ],
- environ,
- childFDs={0: "w", 1: "r", 2: "r",
- self.output.fileno(): self.output.fileno()}
- )
- return sspp
-
-
- @inlineCallbacks
- def test_sendSubProcessFD(self):
- """
- Calling L{sendsmsg} with SOL_SOCKET, SCM_RIGHTS, and a platform-endian
- packed file descriptor number should send that file descriptor to a
- different process, where it can be retrieved by using L{recvmsg}.
- """
- yield bootReactor()
- sspp = self.spawn("pullpipe")
- yield sspp.started
- pipeOut, pipeIn = pipe()
- self.addCleanup(close, pipeOut)
- sendfd(self.input.fileno(), pipeIn, "blonk")
- close(pipeIn)
- yield sspp.stopped
- self.assertEquals(read(pipeOut, 1024), "Test fixture data: blonk.\n")
- # Make sure that the pipe is actually closed now.
- self.assertEquals(read(pipeOut, 1024), "")
-
</del></span></pre>
</div>
</div>
</body>
</html>