Try new ports of binding fails
- API and BM protocol will try random ports for binding if those configured are occupied
This commit is contained in:
parent
0324958e92
commit
cc955cd69d
|
@ -55,6 +55,8 @@ class APIError(Exception):
|
||||||
|
|
||||||
|
|
||||||
class StoppableXMLRPCServer(SimpleXMLRPCServer):
|
class StoppableXMLRPCServer(SimpleXMLRPCServer):
|
||||||
|
allow_reuse_address = True
|
||||||
|
|
||||||
def serve_forever(self):
|
def serve_forever(self):
|
||||||
while state.shutdown == 0:
|
while state.shutdown == 0:
|
||||||
self.handle_request()
|
self.handle_request()
|
||||||
|
|
|
@ -28,6 +28,7 @@ import ctypes
|
||||||
from struct import pack
|
from struct import pack
|
||||||
from subprocess import call
|
from subprocess import call
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
from random import randint
|
||||||
|
|
||||||
from api import MySimpleXMLRPCRequestHandler, StoppableXMLRPCServer
|
from api import MySimpleXMLRPCRequestHandler, StoppableXMLRPCServer
|
||||||
from helper_startup import isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections
|
from helper_startup import isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections
|
||||||
|
@ -171,8 +172,25 @@ class singleAPI(threading.Thread, helper_threading.StoppableThread):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
se = StoppableXMLRPCServer((BMConfigParser().get('bitmessagesettings', 'apiinterface'), BMConfigParser().getint(
|
port = BMConfigParser().getint('bitmessagesettings', 'apiport')
|
||||||
'bitmessagesettings', 'apiport')), MySimpleXMLRPCRequestHandler, True, True)
|
try:
|
||||||
|
from errno import WSAEADDRINUSE
|
||||||
|
except (ImportError, AttributeError):
|
||||||
|
errno.WSAEADDRINUSE = errno.EADDRINUSE
|
||||||
|
for attempt in range(50):
|
||||||
|
try:
|
||||||
|
if attempt > 0:
|
||||||
|
port = randint(32767, 65535)
|
||||||
|
se = StoppableXMLRPCServer((BMConfigParser().get('bitmessagesettings', 'apiinterface'), port),
|
||||||
|
MySimpleXMLRPCRequestHandler, True, True)
|
||||||
|
except socket.error as e:
|
||||||
|
if e.errno in (errno.EADDRINUSE, errno.WSAEADDRINUSE):
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if attempt > 0:
|
||||||
|
BMConfigParser().set("bitmessagesettings", "apiport", str(port))
|
||||||
|
BMConfigParser().save()
|
||||||
|
break
|
||||||
se.register_introspection_functions()
|
se.register_introspection_functions()
|
||||||
se.serve_forever()
|
se.serve_forever()
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ import os
|
||||||
from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, EINVAL, \
|
from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, EINVAL, \
|
||||||
ENOTCONN, ESHUTDOWN, EISCONN, EBADF, ECONNABORTED, EPIPE, EAGAIN, \
|
ENOTCONN, ESHUTDOWN, EISCONN, EBADF, ECONNABORTED, EPIPE, EAGAIN, \
|
||||||
ECONNREFUSED, EHOSTUNREACH, ENETUNREACH, ENOTSOCK, EINTR, ETIMEDOUT, \
|
ECONNREFUSED, EHOSTUNREACH, ENETUNREACH, ENOTSOCK, EINTR, ETIMEDOUT, \
|
||||||
|
EADDRINUSE, \
|
||||||
errorcode
|
errorcode
|
||||||
try:
|
try:
|
||||||
from errno import WSAEWOULDBLOCK
|
from errno import WSAEWOULDBLOCK
|
||||||
|
@ -71,6 +72,10 @@ try:
|
||||||
from errno import WSAECONNRESET
|
from errno import WSAECONNRESET
|
||||||
except (ImportError, AttributeError):
|
except (ImportError, AttributeError):
|
||||||
WSAECONNRESET = ECONNRESET
|
WSAECONNRESET = ECONNRESET
|
||||||
|
try:
|
||||||
|
from errno import WSAEADDRINUSE
|
||||||
|
except (ImportError, AttributeError):
|
||||||
|
WSAEADDRINUSE = EADDRINUSE
|
||||||
|
|
||||||
_DISCONNECTED = frozenset((ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED, EPIPE,
|
_DISCONNECTED = frozenset((ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED, EPIPE,
|
||||||
EBADF, ECONNREFUSED, EHOSTUNREACH, ENETUNREACH, ETIMEDOUT,
|
EBADF, ECONNREFUSED, EHOSTUNREACH, ENETUNREACH, ETIMEDOUT,
|
||||||
|
|
|
@ -119,7 +119,9 @@ class BMConnectionPool(object):
|
||||||
def startListening(self):
|
def startListening(self):
|
||||||
host = self.getListeningIP()
|
host = self.getListeningIP()
|
||||||
port = BMConfigParser().safeGetInt("bitmessagesettings", "port")
|
port = BMConfigParser().safeGetInt("bitmessagesettings", "port")
|
||||||
self.listeningSockets[state.Peer(host, port)] = network.tcp.TCPServer(host=host, port=port)
|
# correct port even if it changed
|
||||||
|
ls = network.tcp.TCPServer(host=host, port=port)
|
||||||
|
self.listeningSockets[ls.destination] = ls
|
||||||
|
|
||||||
def startUDPSocket(self, bind=None):
|
def startUDPSocket(self, bind=None):
|
||||||
if bind is None:
|
if bind is None:
|
||||||
|
|
|
@ -252,10 +252,29 @@ class TCPServer(AdvancedDispatcher):
|
||||||
AdvancedDispatcher.__init__(self)
|
AdvancedDispatcher.__init__(self)
|
||||||
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
self.set_reuse_addr()
|
self.set_reuse_addr()
|
||||||
|
for attempt in range(50):
|
||||||
|
try:
|
||||||
|
if attempt > 0:
|
||||||
|
port = random.randint(32767, 65535)
|
||||||
self.bind((host, port))
|
self.bind((host, port))
|
||||||
|
except socket.error as e:
|
||||||
|
if e.errno in (asyncore.EADDRINUSE, asyncore.WSAEADDRINUSE):
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if attempt > 0:
|
||||||
|
BMConfigParser().set("bitmessagesettings", "port", str(port))
|
||||||
|
BMConfigParser().save()
|
||||||
|
break
|
||||||
self.destination = state.Peer(host, port)
|
self.destination = state.Peer(host, port)
|
||||||
|
self.bound = True
|
||||||
self.listen(5)
|
self.listen(5)
|
||||||
|
|
||||||
|
def is_bound(self):
|
||||||
|
try:
|
||||||
|
return self.bound
|
||||||
|
except AttributeError:
|
||||||
|
return False
|
||||||
|
|
||||||
def handle_accept(self):
|
def handle_accept(self):
|
||||||
pair = self.accept()
|
pair = self.accept()
|
||||||
if pair is not None:
|
if pair is not None:
|
||||||
|
|
13
src/upnp.py
13
src/upnp.py
|
@ -7,6 +7,7 @@ from struct import unpack, pack
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
|
from network.connectionpool import BMConnectionPool
|
||||||
from helper_threading import *
|
from helper_threading import *
|
||||||
import queues
|
import queues
|
||||||
import shared
|
import shared
|
||||||
|
@ -179,7 +180,6 @@ class uPnPThread(threading.Thread, StoppableThread):
|
||||||
|
|
||||||
def __init__ (self):
|
def __init__ (self):
|
||||||
threading.Thread.__init__(self, name="uPnPThread")
|
threading.Thread.__init__(self, name="uPnPThread")
|
||||||
self.localPort = BMConfigParser().getint('bitmessagesettings', 'port')
|
|
||||||
try:
|
try:
|
||||||
self.extPort = BMConfigParser().getint('bitmessagesettings', 'extport')
|
self.extPort = BMConfigParser().getint('bitmessagesettings', 'extport')
|
||||||
except:
|
except:
|
||||||
|
@ -199,6 +199,17 @@ class uPnPThread(threading.Thread, StoppableThread):
|
||||||
logger.debug("Starting UPnP thread")
|
logger.debug("Starting UPnP thread")
|
||||||
logger.debug("Local IP: %s", self.localIP)
|
logger.debug("Local IP: %s", self.localIP)
|
||||||
lastSent = 0
|
lastSent = 0
|
||||||
|
|
||||||
|
# wait until asyncore binds so that we know the listening port
|
||||||
|
bound = False
|
||||||
|
while state.shutdown == 0 and not self._stopped and not bound:
|
||||||
|
for s in BMConnectionPool().listeningSockets.values():
|
||||||
|
if s.is_bound():
|
||||||
|
bound = True
|
||||||
|
if not bound:
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
self.localPort = BMConfigParser().getint('bitmessagesettings', 'port')
|
||||||
while state.shutdown == 0 and BMConfigParser().safeGetBoolean('bitmessagesettings', 'upnp'):
|
while state.shutdown == 0 and BMConfigParser().safeGetBoolean('bitmessagesettings', 'upnp'):
|
||||||
if time.time() - lastSent > self.sendSleep and len(self.routers) == 0:
|
if time.time() - lastSent > self.sendSleep and len(self.routers) == 0:
|
||||||
try:
|
try:
|
||||||
|
|
Reference in New Issue
Block a user