Ticket #5248: port-from-fd-5248-1.patch
| File port-from-fd-5248-1.patch, 12.1 KB (added by rwall, 21 months ago) |
|---|
-
fake_inetd.py
=== added file 'fake_inetd.py'
1 #!/usr/bin/env python 2 3 if __name__ == '__main__': 4 import fake_inetd 5 raise SystemExit(fake_inetd.main()) 6 7 from select import select 8 from socket import socket, SOL_SOCKET, SO_REUSEADDR 9 from subprocess import Popen 10 11 def main(): 12 s = socket() 13 s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) 14 s.bind(('127.0.0.1', 1080)) 15 s.listen(0) 16 while True: 17 r, w, e = select([s], [], []) 18 if r: 19 p = Popen(['python', 'line_reflector.py'], stdin=s.fileno()) 20 p.wait() -
inetd.conf
=== added file 'inetd.conf'
1 1080 stream tcp wait richard /home/richard/Projects/Twisted/branches/port-from-fd-5248/line_reflector.py -
line_reflector.py
=== added file 'line_reflector.py'
1 #!/usr/bin/env python 2 3 if __name__ == '__main__': 4 import line_reflector 5 raise SystemExit(line_reflector.main()) 6 7 """ 8 9 """ 10 11 from twisted.internet import reactor 12 from twisted.internet.tcp import SharedPort 13 from twisted.internet.protocol import ServerFactory 14 from twisted.protocols.basic import LineReceiver 15 16 17 class LineReflector(LineReceiver): 18 def lineReceived(self, line): 19 msg = 'LINE: %r' % (line,) 20 print msg 21 self.sendLine(msg) 22 if line == 'QUIT': 23 self.transport.loseConnection() 24 if line == 'SHUTDOWN': 25 reactor.stop() 26 27 28 def main(): 29 f = ServerFactory() 30 f.protocol = LineReflector 31 p = SharedPort(0, f, reactor=reactor) 32 p.startListening() 33 34 reactor.run() -
twisted/internet/base.py
=== modified file 'twisted/internet/base.py'
1082 1082 addressFamily = None 1083 1083 socketType = None 1084 1084 1085 def createInternetSocket(self): 1086 s = socket.socket(self.addressFamily, self.socketType) 1085 def createInternetSocket(self, fd=None): 1086 """ 1087 @param fd: Optional filedescriptor number of an existing socket fd. 1088 """ 1089 if fd is None: 1090 s = socket.socket(self.addressFamily, self.socketType) 1091 fdesc._setCloseOnExec(s.fileno()) 1092 else: 1093 s = socket.fromfd(fd, self.addressFamily, self.socketType) 1094 1087 1095 s.setblocking(0) 1088 fdesc._setCloseOnExec(s.fileno()) 1096 1089 1097 return s 1090 1098 1091 1099 -
twisted/internet/tcp.py
=== modified file 'twisted/internet/tcp.py'
489 489 return address.IPv4Address('TCP', *self.client) 490 490 491 491 492 493 class Port(base.BasePort, _SocketCloser): 492 class BaseTcpPort(base.BasePort): 494 493 """ 495 494 A TCP server port, listening for connections. 496 495 … … 530 529 # value when we are actually listening. 531 530 _realPortNumber = None 532 531 533 def __init__(self, port, factory, backlog=50, interface='', reactor=None):534 """Initialize with a numeric port to listen on.535 """536 base.BasePort.__init__(self, reactor=reactor)537 self.port = port538 self.factory = factory539 self.backlog = backlog540 self.interface = interface541 542 532 def __repr__(self): 543 533 if self._realPortNumber is not None: 544 534 return "<%s of %s on %s>" % (self.__class__, self.factory.__class__, … … 546 536 else: 547 537 return "<%s of %s (not listening)>" % (self.__class__, self.factory.__class__) 548 538 549 def createInternetSocket(self):550 s = base.BasePort.createInternetSocket(self)551 if platformType == "posix" and sys.platform != "cygwin":552 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)553 return s554 555 539 556 540 def startListening(self): 557 541 """Create and bind my socket, and begin listening on it. … … 559 543 This is called on unserialization, and must be called after creating a 560 544 server to begin listening on the specified port. 561 545 """ 562 try: 563 skt = self.createInternetSocket() 564 skt.bind((self.interface, self.port)) 565 except socket.error, le: 566 raise CannotListenError, (self.interface, self.port, le) 546 skt = self.createInternetSocket() 567 547 568 548 # Make sure that if we listened on port 0, we update that to 569 549 # reflect what the OS actually assigned us. … … 658 638 # and return, so handling it here works just as well. 659 639 log.deferr() 660 640 641 661 642 def loseConnection(self, connDone=failure.Failure(main.CONNECTION_DONE)): 662 643 """ 663 644 Stop accepting connections on this port. … … 707 688 """ 708 689 return reflect.qual(self.factory.__class__) 709 690 691 710 692 def getHost(self): 711 693 """Returns an IPv4Address. 712 694 … … 714 696 """ 715 697 return address.IPv4Address('TCP', *self.socket.getsockname()) 716 698 699 700 class Port(BaseTcpPort, _SocketCloser): 701 """ 702 A TCP server port, listening for connections. 703 704 When a connection is accepted, this will call a factory's buildProtocol 705 with the incoming address as an argument, according to the specification 706 described in L{twisted.internet.interfaces.IProtocolFactory}. 707 708 If you wish to change the sort of transport that will be used, the 709 C{transport} attribute will be called with the signature expected for 710 C{Server.__init__}, so it can be replaced. 711 712 @ivar deferred: a deferred created when L{stopListening} is called, and 713 that will fire when connection is lost. This is not to be used it 714 directly: prefer the deferred returned by L{stopListening} instead. 715 @type deferred: L{defer.Deferred} 716 717 @ivar disconnecting: flag indicating that the L{stopListening} method has 718 been called and that no connections should be accepted anymore. 719 @type disconnecting: C{bool} 720 721 @ivar connected: flag set once the listen has successfully been called on 722 the socket. 723 @type connected: C{bool} 724 """ 725 726 def __init__(self, port, factory, backlog=50, interface='', reactor=None): 727 """Initialize with a numeric port to listen on. 728 """ 729 BaseTcpPort.__init__(self, reactor=reactor) 730 self.port = port 731 self.factory = factory 732 self.backlog = backlog 733 self.interface = interface 734 735 736 def createInternetSocket(self): 737 try: 738 s = BaseTcpPort.createInternetSocket(self) 739 if platformType == "posix" and sys.platform != "cygwin": 740 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 741 s.bind((self.interface, self.port)) 742 return s 743 except socket.error, le: 744 raise CannotListenError, (self.interface, self.port, le) 745 746 747 class SharedPort(BaseTcpPort): 748 """ 749 A TCP server port for which a listening socket already exists. eg 750 a socket may have been setup by a parent process such as inetd or 751 systemd. 752 753 The socket will not be destroyed when this Port stops listening or 754 is destroyed. 755 """ 756 757 def __init__(self, fd, factory, backlog=50, reactor=None): 758 """ 759 Initialize with the file descriptor number of an existing 760 listening socket. 761 """ 762 BaseTcpPort.__init__(self, reactor=reactor) 763 self.fd = fd 764 self.factory = factory 765 self.backlog = backlog 766 767 768 def createInternetSocket(self): 769 try: 770 s = BaseTcpPort.createInternetSocket(self, fd=self.fd) 771 if platformType == "posix" and sys.platform != "cygwin": 772 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 773 return s 774 except socket.error, le: 775 raise CannotListenError, (self.interface, self.fd, le) 776 777 778 def _closeSocket(self): 779 pass 780 781 717 782 class Connector(base.BaseConnector): 718 783 def __init__(self, host, port, factory, timeout, bindAddress, reactor=None): 719 784 self.host = host -
twisted/internet/test/test_unix.py
=== modified file 'twisted/internet/test/test_unix.py'
159 159 """ 160 160 Get the expected connection lost message for a UNIX port 161 161 """ 162 return "(UNIX Port %s Closed)" % (repr(port. port),)162 return "(UNIX Port %s Closed)" % (repr(port.fileName),) 163 163 164 164 165 165 -
twisted/internet/unix.py
=== modified file 'twisted/internet/unix.py'
67 67 68 68 69 69 70 class Port(_UNIXPort, tcp. Port):70 class Port(_UNIXPort, tcp.BaseTcpPort): 71 71 addressFamily = socket.AF_UNIX 72 72 socketType = socket.SOCK_STREAM 73 73 … … 75 75 lockFile = None 76 76 77 77 def __init__(self, fileName, factory, backlog=50, mode=0666, reactor=None, wantPID = 0): 78 tcp.Port.__init__(self, fileName, factory, backlog, reactor=reactor) 78 tcp.BaseTcpPort.__init__(self, reactor=reactor) 79 self.fileName = fileName 80 self.factory = factory 81 self.backlog = backlog 82 79 83 self.mode = mode 80 84 self.wantPID = wantPID 81 85 82 86 def __repr__(self): 83 87 factoryName = reflect.qual(self.factory.__class__) 84 88 if hasattr(self, 'socket'): 85 return '<%s on %r>' % (factoryName, self. port)89 return '<%s on %r>' % (factoryName, self.fileName) 86 90 else: 87 91 return '<%s (not listening)>' % (factoryName,) 88 92 … … 96 100 This is called on unserialization, and must be called after creating a 97 101 server to begin listening on the specified port. 98 102 """ 99 log.msg("%s starting on %r" % (self.factory.__class__, repr(self. port)))103 log.msg("%s starting on %r" % (self.factory.__class__, repr(self.fileName))) 100 104 if self.wantPID: 101 self.lockFile = lockfile.FilesystemLock(self. port+ ".lock")105 self.lockFile = lockfile.FilesystemLock(self.fileName + ".lock") 102 106 if not self.lockFile.lock(): 103 raise CannotListenError, (None, self. port, "Cannot acquire lock")107 raise CannotListenError, (None, self.fileName, "Cannot acquire lock") 104 108 else: 105 109 if not self.lockFile.clean: 106 110 try: … … 109 113 # If it fails, there's not much else we can 110 114 # do. The bind() below will fail with an 111 115 # exception that actually propagates. 112 if stat.S_ISSOCK(os.stat(self. port).st_mode):113 os.remove(self. port)116 if stat.S_ISSOCK(os.stat(self.fileName).st_mode): 117 os.remove(self.fileName) 114 118 except: 115 119 pass 116 120 117 121 self.factory.doStart() 118 122 try: 119 123 skt = self.createInternetSocket() 120 skt.bind(self. port)124 skt.bind(self.fileName) 121 125 except socket.error, le: 122 raise CannotListenError, (None, self. port, le)126 raise CannotListenError, (None, self.fileName, le) 123 127 else: 124 if _inFilesystemNamespace(self. port):128 if _inFilesystemNamespace(self.fileName): 125 129 # Make the socket readable and writable to the world. 126 os.chmod(self. port, self.mode)130 os.chmod(self.fileName, self.mode) 127 131 skt.listen(self.backlog) 128 132 self.connected = True 129 133 self.socket = skt … … 136 140 """ 137 141 Log message for closing socket 138 142 """ 139 log.msg('(UNIX Port %s Closed)' % (repr(self. port),))140 141 142 def connectionLost(self, reason):143 if _inFilesystemNamespace(self. port):144 os.unlink(self. port)143 log.msg('(UNIX Port %s Closed)' % (repr(self.fileName),)) 144 145 146 def _closeSocket(self): 147 if _inFilesystemNamespace(self.fileName): 148 os.unlink(self.fileName) 145 149 if self.lockFile is not None: 146 150 self.lockFile.unlock() 147 tcp.Port.connectionLost(self, reason)148 151 149 152 150 153
