Ticket #4471: idatagram-endpoint-4471.patch

File idatagram-endpoint-4471.patch, 8.9 KB (added by Richard Wall, 3 years ago)
  • twisted/application/internet.py

    === modified file 'twisted/application/internet.py'
     
    398398
    399399
    400400
     401class DatagramEndpointService(StreamServerEndpointService):
     402    pass
     403
     404
     405
    401406__all__ = (['TimerService', 'CooperatorService', 'MulticastServer',
    402             'StreamServerEndpointService'] +
     407            'StreamServerEndpointService', 'DatagramEndpointService'] +
    403408           [tran+side
    404409            for tran in 'TCP UNIX SSL UDP UNIXDatagram'.split()
    405410            for side in 'Server Client'.split()])
  • twisted/application/strports.py

    === modified file 'twisted/application/strports.py'
     
    1111
    1212import warnings
    1313
    14 from twisted.internet import endpoints
     14from twisted.internet import endpoints, interfaces
    1515from twisted.python.deprecate import deprecatedModuleAttribute
    1616from twisted.python.versions import Version
    17 from twisted.application.internet import StreamServerEndpointService
     17from twisted.application.internet import StreamServerEndpointService, DatagramEndpointService
    1818
    1919
    2020
     
    3535
    3636_DEFAULT = object()
    3737
    38 def service(description, factory, default=_DEFAULT, reactor=None):
     38def service(description, factoryOrProtocol, default=_DEFAULT, reactor=None):
    3939    """
    4040    Return the service corresponding to a description.
    4141
     
    4444
    4545    @type description: C{str}
    4646
    47     @param factory: The protocol factory which will build protocols for
     47    @param factoryOrProtocol: The protocol factory which will build protocols for
    4848        connections to this service.
    4949
    50     @type factory: L{twisted.internet.interfaces.IProtocolFactory}
     50    @type factoryOrProtocol: L{twisted.internet.interfaces.IProtocolFactory}
    5151
    5252    @type default: C{str} or C{None}
    5353
     
    7373                "'tcp:%s'." % (description,))
    7474        warnings.warn(
    7575            message=message, category=DeprecationWarning, stacklevel=2)
    76     svc = StreamServerEndpointService(
    77         endpoints._serverFromStringLegacy(reactor, description, default),
    78         factory)
     76
     77    ep = endpoints._serverFromStringLegacy(reactor, description, default),
     78    if interfaces.IStreamServerEndpoint.providedBy(ep):
     79        svc = StreamServerEndpointService(ep, factoryOrProtocol)
     80    else:
     81        svc = DatagramEndpointService(ep, factoryOrProtocol)
     82
    7983    svc._raiseSynchronously = True
    8084    return svc
    8185
  • twisted/internet/endpoints.py

    === modified file 'twisted/internet/endpoints.py'
     
    1313"""
    1414
    1515from __future__ import division, absolute_import
    16 
     16from itertools import chain
    1717import os
    1818import re
    1919import socket
     
    2727        ClientFactory, Protocol, ProcessProtocol, Factory)
    2828from twisted.internet.interfaces import IStreamServerEndpointStringParser
    2929from twisted.internet.interfaces import IStreamClientEndpointStringParser
     30from twisted.internet.interfaces import IDatagramEndpointStringParser
    3031from twisted.python.filepath import FilePath
    3132from twisted.python.systemd import ListenFDs
    3233from twisted.internet.abstract import isIPv6Address
     
    3435from twisted.python import log
    3536from twisted.internet.address import _ProcessAddress
    3637from twisted.python.components import proxyForInterface
     38from twisted.python.util import socketTypeFromFd
    3739
    3840if not _PY3:
    3941    from twisted.plugin import IPlugin, getPlugins
     
    844846
    845847
    846848
     849@implementer(interfaces.IDatagramEndpoint)
     850class DatagramEndpoint(object):
     851    """
     852    A UDP endpoint interface
     853    """
     854
     855    def __init__(self, reactor, port, interface):
     856        """
     857        @param reactor: An L{IReactorTCP} provider.
     858
     859        @param port: The port number used for listening
     860        @type port: int
     861
     862        @param interface: The hostname to bind to
     863        @type interface: str
     864        """
     865        self._reactor = reactor
     866        self._port = port
     867        self._interface = interface
     868
     869
     870    def listen(self, protocol):
     871        """
     872        Implement L{IDatagramEndpoint.listen} to listen on a UDP
     873        socket
     874        """
     875        return defer.execute(self._reactor.listenUDP,
     876                             self._port,
     877                             protocol,
     878                             interface=self._interface)
     879
     880
     881
     882@implementer(interfaces.IDatagramEndpoint)
     883class AdoptedDatagramEndpoint(object):
     884    """
     885
     886    @ivar _used: A C{bool} indicating whether this endpoint has been used to
     887        listen with a factory yet.  C{True} if so.
     888    """
     889    _close = os.close
     890    _setNonBlocking = staticmethod(fdesc.setNonBlocking)
     891
     892    def __init__(self, reactor, fileno, addressFamily):
     893        """
     894        @param reactor: An L{IReactorSocket} provider.
     895
     896        @param fileno: An integer file descriptor corresponding to a listening
     897            I{SOCK_STREAM} socket.
     898
     899        @param addressFamily: The address family of the socket given by
     900            C{fileno}.
     901        """
     902        self.reactor = reactor
     903        self.fileno = fileno
     904        self.addressFamily = addressFamily
     905        self._used = False
     906
     907
     908    def listen(self, protocol):
     909        """
     910        Implement L{IStreamServerEndpoint.listen} to start listening on, and
     911        then close, C{self._fileno}.
     912        """
     913        if self._used:
     914            return defer.fail(error.AlreadyListened())
     915        self._used = True
     916
     917        try:
     918            self._setNonBlocking(self.fileno)
     919            port = self.reactor.adoptDatagramPort(
     920                self.fileno, self.addressFamily, protocol)
     921            self._close(self.fileno)
     922        except:
     923            return defer.fail()
     924        return defer.succeed(port)
     925
     926
     927
    847928def _parseTCP(factory, port, interface="", backlog=50):
    848929    """
    849930    Internal parser function for L{_parseServer} to convert the string
     
    9801061
    9811062
    9821063
     1064def _parseUDP(factory, port, interface=""):
     1065    """
     1066    Internal parser function for L{_parseServer} to convert the string
     1067    arguments for a TCP(IPv4) datagram endpoint into the structured arguments.
     1068
     1069    @param port: the integer port number to bind
     1070    @type port: C{str}
     1071
     1072    @param interface: the interface IP to listen on
     1073
     1074    @return: a 2-tuple of (args, kwargs), describing  the parameters to
     1075        L{IReactorTCP.listenTCP}.
     1076    """
     1077    return (int(port),), {'interface': interface,}
     1078
     1079
     1080
    9831081@implementer(IPlugin, IStreamServerEndpointStringParser)
    9841082class _StandardIOParser(object):
    9851083    """
     
    10961194_serverParsers = {"tcp": _parseTCP,
    10971195                  "unix": _parseUNIX,
    10981196                  "ssl": _parseSSL,
     1197                  "udp": _parseUDP,
    10991198                  }
    11001199
    11011200_OP, _STRING = range(2)
     
    11721271    'TCP': TCP4ServerEndpoint,
    11731272    'SSL': SSL4ServerEndpoint,
    11741273    'UNIX': UNIXServerEndpoint,
     1274    'UDP': DatagramEndpoint,
    11751275    }
    11761276
    11771277_endpointClientFactories = {
     
    12231323    if parser is None:
    12241324        # If the required parser is not found in _server, check if
    12251325        # a plugin exists for the endpointType
    1226         for plugin in getPlugins(IStreamServerEndpointStringParser):
     1326        for plugin in chain(getPlugins(IStreamServerEndpointStringParser), getPlugins(IDatagramEndpointStringParser)):
    12271327            if plugin.prefix == endpointType:
    12281328                return (plugin, args[1:], kw)
    12291329        raise ValueError("Unknown endpoint type: '%s'" % (endpointType,))
  • twisted/internet/interfaces.py

    === modified file 'twisted/internet/interfaces.py'
     
    24972497        @return: a client endpoint
    24982498        @rtype: L{IStreamClientEndpoint}
    24992499        """
     2500
     2501
     2502
     2503class IDatagramEndpoint(Interface):
     2504    """
     2505    A stream server endpoint is a place that a L{Factory} can listen for
     2506    incoming connections.
     2507
     2508    @since: 10.1
     2509    """
     2510
     2511    def listen(protocol):
     2512        """
     2513        Listen with C{protocolFactory} at the location specified by this
     2514        L{IStreamServerEndpoint} provider.
     2515
     2516        @param protocolFactory: A provider of L{IProtocolFactory}
     2517        @return: A L{Deferred} that results in an L{IListeningPort} or an
     2518            L{CannotListenError}
     2519        """
     2520
     2521
     2522
     2523class IDatagramEndpointStringParser(Interface):
     2524    """
     2525    An L{IStreamServerEndpointStringParser} is like an
     2526    L{IStreamClientEndpointStringParser}, except for L{IStreamServerEndpoint}s
     2527    instead of clients.  It integrates with L{endpoints.serverFromString} in
     2528    much the same way.
     2529    """
     2530
     2531    prefix = Attribute(
     2532        """
     2533        @see: L{IStreamClientEndpointStringParser.prefix}
     2534        """
     2535    )
     2536
     2537
     2538    def parseDatagram(reactor, *args, **kwargs):
     2539        """
     2540        Parse a stream server endpoint from a reactor and string-only arguments
     2541        and keyword arguments.
     2542
     2543        @see: L{IStreamClientEndpointStringParser.parseStreamClient}
     2544
     2545        @return: a stream server endpoint
     2546        @rtype: L{IStreamServerEndpoint}
     2547        """