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):
|
||||
allow_reuse_address = True
|
||||
|
||||
def serve_forever(self):
|
||||
while state.shutdown == 0:
|
||||
self.handle_request()
|
||||
|
|
|
@ -28,6 +28,7 @@ import ctypes
|
|||
from struct import pack
|
||||
from subprocess import call
|
||||
from time import sleep
|
||||
from random import randint
|
||||
|
||||
from api import MySimpleXMLRPCRequestHandler, StoppableXMLRPCServer
|
||||
from helper_startup import isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections
|
||||
|
@ -171,8 +172,25 @@ class singleAPI(threading.Thread, helper_threading.StoppableThread):
|
|||
pass
|
||||
|
||||
def run(self):
|
||||
se = StoppableXMLRPCServer((BMConfigParser().get('bitmessagesettings', 'apiinterface'), BMConfigParser().getint(
|
||||
'bitmessagesettings', 'apiport')), MySimpleXMLRPCRequestHandler, True, True)
|
||||
port = BMConfigParser().getint('bitmessagesettings', 'apiport')
|
||||
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.serve_forever()
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ import os
|
|||
from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, EINVAL, \
|
||||
ENOTCONN, ESHUTDOWN, EISCONN, EBADF, ECONNABORTED, EPIPE, EAGAIN, \
|
||||
ECONNREFUSED, EHOSTUNREACH, ENETUNREACH, ENOTSOCK, EINTR, ETIMEDOUT, \
|
||||
EADDRINUSE, \
|
||||
errorcode
|
||||
try:
|
||||
from errno import WSAEWOULDBLOCK
|
||||
|
@ -71,6 +72,10 @@ try:
|
|||
from errno import WSAECONNRESET
|
||||
except (ImportError, AttributeError):
|
||||
WSAECONNRESET = ECONNRESET
|
||||
try:
|
||||
from errno import WSAEADDRINUSE
|
||||
except (ImportError, AttributeError):
|
||||
WSAEADDRINUSE = EADDRINUSE
|
||||
|
||||
_DISCONNECTED = frozenset((ECONNRESET, ENOTCONN, ESHUTDOWN, ECONNABORTED, EPIPE,
|
||||
EBADF, ECONNREFUSED, EHOSTUNREACH, ENETUNREACH, ETIMEDOUT,
|
||||
|
|
|
@ -119,7 +119,9 @@ class BMConnectionPool(object):
|
|||
def startListening(self):
|
||||
host = self.getListeningIP()
|
||||
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):
|
||||
if bind is None:
|
||||
|
|
|
@ -252,10 +252,29 @@ class TCPServer(AdvancedDispatcher):
|
|||
AdvancedDispatcher.__init__(self)
|
||||
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.set_reuse_addr()
|
||||
self.bind((host, port))
|
||||
for attempt in range(50):
|
||||
try:
|
||||
if attempt > 0:
|
||||
port = random.randint(32767, 65535)
|
||||
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.bound = True
|
||||
self.listen(5)
|
||||
|
||||
def is_bound(self):
|
||||
try:
|
||||
return self.bound
|
||||
except AttributeError:
|
||||
return False
|
||||
|
||||
def handle_accept(self):
|
||||
pair = self.accept()
|
||||
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 time
|
||||
from bmconfigparser import BMConfigParser
|
||||
from network.connectionpool import BMConnectionPool
|
||||
from helper_threading import *
|
||||
import queues
|
||||
import shared
|
||||
|
@ -179,7 +180,6 @@ class uPnPThread(threading.Thread, StoppableThread):
|
|||
|
||||
def __init__ (self):
|
||||
threading.Thread.__init__(self, name="uPnPThread")
|
||||
self.localPort = BMConfigParser().getint('bitmessagesettings', 'port')
|
||||
try:
|
||||
self.extPort = BMConfigParser().getint('bitmessagesettings', 'extport')
|
||||
except:
|
||||
|
@ -199,6 +199,17 @@ class uPnPThread(threading.Thread, StoppableThread):
|
|||
logger.debug("Starting UPnP thread")
|
||||
logger.debug("Local IP: %s", self.localIP)
|
||||
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'):
|
||||
if time.time() - lastSent > self.sendSleep and len(self.routers) == 0:
|
||||
try:
|
||||
|
|
Reference in New Issue
Block a user