error.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Exceptions and errors for use in twisted.internet modules.
  5. """
  6. from __future__ import division, absolute_import
  7. import socket
  8. from twisted.python import deprecate
  9. from incremental import Version
  10. class BindError(Exception):
  11. """An error occurred binding to an interface"""
  12. def __str__(self):
  13. s = self.__doc__
  14. if self.args:
  15. s = '%s: %s' % (s, ' '.join(self.args))
  16. s = '%s.' % s
  17. return s
  18. class CannotListenError(BindError):
  19. """
  20. This gets raised by a call to startListening, when the object cannotstart
  21. listening.
  22. @ivar interface: the interface I tried to listen on
  23. @ivar port: the port I tried to listen on
  24. @ivar socketError: the exception I got when I tried to listen
  25. @type socketError: L{socket.error}
  26. """
  27. def __init__(self, interface, port, socketError):
  28. BindError.__init__(self, interface, port, socketError)
  29. self.interface = interface
  30. self.port = port
  31. self.socketError = socketError
  32. def __str__(self):
  33. iface = self.interface or 'any'
  34. return "Couldn't listen on %s:%s: %s." % (iface, self.port,
  35. self.socketError)
  36. class MulticastJoinError(Exception):
  37. """
  38. An attempt to join a multicast group failed.
  39. """
  40. class MessageLengthError(Exception):
  41. """Message is too long to send"""
  42. def __str__(self):
  43. s = self.__doc__
  44. if self.args:
  45. s = '%s: %s' % (s, ' '.join(self.args))
  46. s = '%s.' % s
  47. return s
  48. class DNSLookupError(IOError):
  49. """DNS lookup failed"""
  50. def __str__(self):
  51. s = self.__doc__
  52. if self.args:
  53. s = '%s: %s' % (s, ' '.join(self.args))
  54. s = '%s.' % s
  55. return s
  56. class ConnectInProgressError(Exception):
  57. """A connect operation was started and isn't done yet."""
  58. # connection errors
  59. class ConnectError(Exception):
  60. """An error occurred while connecting"""
  61. def __init__(self, osError=None, string=""):
  62. self.osError = osError
  63. Exception.__init__(self, string)
  64. def __str__(self):
  65. s = self.__doc__ or self.__class__.__name__
  66. if self.osError:
  67. s = '%s: %s' % (s, self.osError)
  68. if self.args[0]:
  69. s = '%s: %s' % (s, self.args[0])
  70. s = '%s.' % s
  71. return s
  72. class ConnectBindError(ConnectError):
  73. """Couldn't bind"""
  74. class UnknownHostError(ConnectError):
  75. """Hostname couldn't be looked up"""
  76. class NoRouteError(ConnectError):
  77. """No route to host"""
  78. class ConnectionRefusedError(ConnectError):
  79. """Connection was refused by other side"""
  80. class TCPTimedOutError(ConnectError):
  81. """TCP connection timed out"""
  82. class BadFileError(ConnectError):
  83. """File used for UNIX socket is no good"""
  84. class ServiceNameUnknownError(ConnectError):
  85. """Service name given as port is unknown"""
  86. class UserError(ConnectError):
  87. """User aborted connection"""
  88. class TimeoutError(UserError):
  89. """User timeout caused connection failure"""
  90. class SSLError(ConnectError):
  91. """An SSL error occurred"""
  92. class VerifyError(Exception):
  93. """Could not verify something that was supposed to be signed.
  94. """
  95. class PeerVerifyError(VerifyError):
  96. """The peer rejected our verify error.
  97. """
  98. class CertificateError(Exception):
  99. """
  100. We did not find a certificate where we expected to find one.
  101. """
  102. try:
  103. import errno
  104. errnoMapping = {
  105. errno.ENETUNREACH: NoRouteError,
  106. errno.ECONNREFUSED: ConnectionRefusedError,
  107. errno.ETIMEDOUT: TCPTimedOutError,
  108. }
  109. if hasattr(errno, "WSAECONNREFUSED"):
  110. errnoMapping[errno.WSAECONNREFUSED] = ConnectionRefusedError
  111. errnoMapping[errno.WSAENETUNREACH] = NoRouteError
  112. except ImportError:
  113. errnoMapping = {}
  114. def getConnectError(e):
  115. """Given a socket exception, return connection error."""
  116. if isinstance(e, Exception):
  117. args = e.args
  118. else:
  119. args = e
  120. try:
  121. number, string = args
  122. except ValueError:
  123. return ConnectError(string=e)
  124. if hasattr(socket, 'gaierror') and isinstance(e, socket.gaierror):
  125. # Only works in 2.2 in newer. Really that means always; #5978 covers
  126. # this and other weirdnesses in this function.
  127. klass = UnknownHostError
  128. else:
  129. klass = errnoMapping.get(number, ConnectError)
  130. return klass(number, string)
  131. class ConnectionClosed(Exception):
  132. """
  133. Connection was closed, whether cleanly or non-cleanly.
  134. """
  135. class ConnectionLost(ConnectionClosed):
  136. """Connection to the other side was lost in a non-clean fashion"""
  137. def __str__(self):
  138. s = self.__doc__.strip().splitlines()[0]
  139. if self.args:
  140. s = '%s: %s' % (s, ' '.join(self.args))
  141. s = '%s.' % s
  142. return s
  143. class ConnectionAborted(ConnectionLost):
  144. """
  145. Connection was aborted locally, using
  146. L{twisted.internet.interfaces.ITCPTransport.abortConnection}.
  147. @since: 11.1
  148. """
  149. class ConnectionDone(ConnectionClosed):
  150. """Connection was closed cleanly"""
  151. def __str__(self):
  152. s = self.__doc__
  153. if self.args:
  154. s = '%s: %s' % (s, ' '.join(self.args))
  155. s = '%s.' % s
  156. return s
  157. class FileDescriptorOverrun(ConnectionLost):
  158. """
  159. A mis-use of L{IUNIXTransport.sendFileDescriptor} caused the connection to
  160. be closed.
  161. Each file descriptor sent using C{sendFileDescriptor} must be associated
  162. with at least one byte sent using L{ITransport.write}. If at any point
  163. fewer bytes have been written than file descriptors have been sent, the
  164. connection is closed with this exception.
  165. """
  166. class ConnectionFdescWentAway(ConnectionLost):
  167. """Uh""" #TODO
  168. class AlreadyCalled(ValueError):
  169. """Tried to cancel an already-called event"""
  170. def __str__(self):
  171. s = self.__doc__
  172. if self.args:
  173. s = '%s: %s' % (s, ' '.join(self.args))
  174. s = '%s.' % s
  175. return s
  176. class AlreadyCancelled(ValueError):
  177. """Tried to cancel an already-cancelled event"""
  178. def __str__(self):
  179. s = self.__doc__
  180. if self.args:
  181. s = '%s: %s' % (s, ' '.join(self.args))
  182. s = '%s.' % s
  183. return s
  184. class PotentialZombieWarning(Warning):
  185. """
  186. Emitted when L{IReactorProcess.spawnProcess} is called in a way which may
  187. result in termination of the created child process not being reported.
  188. Deprecated in Twisted 10.0.
  189. """
  190. MESSAGE = (
  191. "spawnProcess called, but the SIGCHLD handler is not "
  192. "installed. This probably means you have not yet "
  193. "called reactor.run, or called "
  194. "reactor.run(installSignalHandler=0). You will probably "
  195. "never see this process finish, and it may become a "
  196. "zombie process.")
  197. deprecate.deprecatedModuleAttribute(
  198. Version("Twisted", 10, 0, 0),
  199. "There is no longer any potential for zombie process.",
  200. __name__,
  201. "PotentialZombieWarning")
  202. class ProcessDone(ConnectionDone):
  203. """A process has ended without apparent errors"""
  204. def __init__(self, status):
  205. Exception.__init__(self, "process finished with exit code 0")
  206. self.exitCode = 0
  207. self.signal = None
  208. self.status = status
  209. class ProcessTerminated(ConnectionLost):
  210. """
  211. A process has ended with a probable error condition
  212. @ivar exitCode: See L{__init__}
  213. @ivar signal: See L{__init__}
  214. @ivar status: See L{__init__}
  215. """
  216. def __init__(self, exitCode=None, signal=None, status=None):
  217. """
  218. @param exitCode: The exit status of the process. This is roughly like
  219. the value you might pass to L{os.exit}. This is L{None} if the
  220. process exited due to a signal.
  221. @type exitCode: L{int} or L{None}
  222. @param signal: The exit signal of the process. This is L{None} if the
  223. process did not exit due to a signal.
  224. @type signal: L{int} or L{None}
  225. @param status: The exit code of the process. This is a platform
  226. specific combination of the exit code and the exit signal. See
  227. L{os.WIFEXITED} and related functions.
  228. @type status: L{int}
  229. """
  230. self.exitCode = exitCode
  231. self.signal = signal
  232. self.status = status
  233. s = "process ended"
  234. if exitCode is not None: s = s + " with exit code %s" % exitCode
  235. if signal is not None: s = s + " by signal %s" % signal
  236. Exception.__init__(self, s)
  237. class ProcessExitedAlready(Exception):
  238. """
  239. The process has already exited and the operation requested can no longer
  240. be performed.
  241. """
  242. class NotConnectingError(RuntimeError):
  243. """The Connector was not connecting when it was asked to stop connecting"""
  244. def __str__(self):
  245. s = self.__doc__
  246. if self.args:
  247. s = '%s: %s' % (s, ' '.join(self.args))
  248. s = '%s.' % s
  249. return s
  250. class NotListeningError(RuntimeError):
  251. """The Port was not listening when it was asked to stop listening"""
  252. def __str__(self):
  253. s = self.__doc__
  254. if self.args:
  255. s = '%s: %s' % (s, ' '.join(self.args))
  256. s = '%s.' % s
  257. return s
  258. class ReactorNotRunning(RuntimeError):
  259. """
  260. Error raised when trying to stop a reactor which is not running.
  261. """
  262. class ReactorNotRestartable(RuntimeError):
  263. """
  264. Error raised when trying to run a reactor which was stopped.
  265. """
  266. class ReactorAlreadyRunning(RuntimeError):
  267. """
  268. Error raised when trying to start the reactor multiple times.
  269. """
  270. class ReactorAlreadyInstalledError(AssertionError):
  271. """
  272. Could not install reactor because one is already installed.
  273. """
  274. class ConnectingCancelledError(Exception):
  275. """
  276. An C{Exception} that will be raised when an L{IStreamClientEndpoint} is
  277. cancelled before it connects.
  278. @ivar address: The L{IAddress} that is the destination of the
  279. cancelled L{IStreamClientEndpoint}.
  280. """
  281. def __init__(self, address):
  282. """
  283. @param address: The L{IAddress} that is the destination of the
  284. L{IStreamClientEndpoint} that was cancelled.
  285. """
  286. Exception.__init__(self, address)
  287. self.address = address
  288. class NoProtocol(Exception):
  289. """
  290. An C{Exception} that will be raised when the factory given to a
  291. L{IStreamClientEndpoint} returns L{None} from C{buildProtocol}.
  292. """
  293. class UnsupportedAddressFamily(Exception):
  294. """
  295. An attempt was made to use a socket with an address family (eg I{AF_INET},
  296. I{AF_INET6}, etc) which is not supported by the reactor.
  297. """
  298. class UnsupportedSocketType(Exception):
  299. """
  300. An attempt was made to use a socket of a type (eg I{SOCK_STREAM},
  301. I{SOCK_DGRAM}, etc) which is not supported by the reactor.
  302. """
  303. class AlreadyListened(Exception):
  304. """
  305. An attempt was made to listen on a file descriptor which can only be
  306. listened on once.
  307. """
  308. class InvalidAddressError(ValueError):
  309. """
  310. An invalid address was specified (i.e. neither IPv4 or IPv6, or expected
  311. one and got the other).
  312. @ivar address: See L{__init__}
  313. @ivar message: See L{__init__}
  314. """
  315. def __init__(self, address, message):
  316. """
  317. @param address: The address that was provided.
  318. @type address: L{bytes}
  319. @param message: A native string of additional information provided by
  320. the calling context.
  321. @type address: L{str}
  322. """
  323. self.address = address
  324. self.message = message
  325. __all__ = [
  326. 'BindError', 'CannotListenError', 'MulticastJoinError',
  327. 'MessageLengthError', 'DNSLookupError', 'ConnectInProgressError',
  328. 'ConnectError', 'ConnectBindError', 'UnknownHostError', 'NoRouteError',
  329. 'ConnectionRefusedError', 'TCPTimedOutError', 'BadFileError',
  330. 'ServiceNameUnknownError', 'UserError', 'TimeoutError', 'SSLError',
  331. 'VerifyError', 'PeerVerifyError', 'CertificateError',
  332. 'getConnectError', 'ConnectionClosed', 'ConnectionLost',
  333. 'ConnectionDone', 'ConnectionFdescWentAway', 'AlreadyCalled',
  334. 'AlreadyCancelled', 'PotentialZombieWarning', 'ProcessDone',
  335. 'ProcessTerminated', 'ProcessExitedAlready', 'NotConnectingError',
  336. 'NotListeningError', 'ReactorNotRunning', 'ReactorAlreadyRunning',
  337. 'ReactorAlreadyInstalledError', 'ConnectingCancelledError',
  338. 'UnsupportedAddressFamily', 'UnsupportedSocketType', 'InvalidAddressError']