This avoids a handful of failures due to missing str and bytes.
- skip-blame: just a bunch of b'' prefixes
| hg-reviewers |
This avoids a handful of failures due to missing str and bytes.
| Automatic diff as part of commit; lint not applicable. |
| Automatic diff as part of commit; unit tests not applicable. |
| configtable = {} | configtable = {} | ||||
| configitem = registrar.configitem(configtable) | configitem = registrar.configitem(configtable) | ||||
| configitem(b'badserver', b'closeafteraccept', | configitem(b'badserver', b'closeafteraccept', | ||||
| default=False, | default=False, | ||||
| ) | ) | ||||
| configitem(b'badserver', b'closeafterrecvbytes', | configitem(b'badserver', b'closeafterrecvbytes', | ||||
| default='0', | default=b'0', | ||||
| ) | ) | ||||
| configitem(b'badserver', b'closeaftersendbytes', | configitem(b'badserver', b'closeaftersendbytes', | ||||
| default='0', | default=b'0', | ||||
| ) | ) | ||||
| configitem(b'badserver', b'closebeforeaccept', | configitem(b'badserver', b'closebeforeaccept', | ||||
| default=False, | default=False, | ||||
| ) | ) | ||||
| # We can't adjust __class__ on a socket instance. So we define a proxy type. | # We can't adjust __class__ on a socket instance. So we define a proxy type. | ||||
| class socketproxy(object): | class socketproxy(object): | ||||
| __slots__ = ( | __slots__ = ( | ||||
| def __delattr__(self, name): | def __delattr__(self, name): | ||||
| delattr(object.__getattribute__(self, '_orig'), name) | delattr(object.__getattribute__(self, '_orig'), name) | ||||
| def __setattr__(self, name, value): | def __setattr__(self, name, value): | ||||
| setattr(object.__getattribute__(self, '_orig'), name, value) | setattr(object.__getattribute__(self, '_orig'), name, value) | ||||
| def _writelog(self, msg): | def _writelog(self, msg): | ||||
| msg = msg.replace('\r', '\\r').replace('\n', '\\n') | msg = msg.replace(b'\r', b'\\r').replace(b'\n', b'\\n') | ||||
| object.__getattribute__(self, '_logfp').write(msg) | object.__getattribute__(self, '_logfp').write(msg) | ||||
| object.__getattribute__(self, '_logfp').write('\n') | object.__getattribute__(self, '_logfp').write(b'\n') | ||||
| object.__getattribute__(self, '_logfp').flush() | object.__getattribute__(self, '_logfp').flush() | ||||
| def read(self, size=-1): | def read(self, size=-1): | ||||
| remaining = object.__getattribute__(self, '_closeafterrecvbytes') | remaining = object.__getattribute__(self, '_closeafterrecvbytes') | ||||
| # No read limit. Call original function. | # No read limit. Call original function. | ||||
| if not remaining: | if not remaining: | ||||
| result = object.__getattribute__(self, '_orig').read(size) | result = object.__getattribute__(self, '_orig').read(size) | ||||
| self._writelog('read(%d) -> (%d) (%s) %s' % (size, | self._writelog(b'read(%d) -> (%d) (%s) %s' % (size, | ||||
| len(result), | len(result), | ||||
| result)) | result)) | ||||
| return result | return result | ||||
| origsize = size | origsize = size | ||||
| if size < 0: | if size < 0: | ||||
| size = remaining | size = remaining | ||||
| else: | else: | ||||
| size = min(remaining, size) | size = min(remaining, size) | ||||
| result = object.__getattribute__(self, '_orig').read(size) | result = object.__getattribute__(self, '_orig').read(size) | ||||
| remaining -= len(result) | remaining -= len(result) | ||||
| self._writelog('read(%d from %d) -> (%d) %s' % ( | self._writelog(b'read(%d from %d) -> (%d) %s' % ( | ||||
| size, origsize, len(result), result)) | size, origsize, len(result), result)) | ||||
| object.__setattr__(self, '_closeafterrecvbytes', remaining) | object.__setattr__(self, '_closeafterrecvbytes', remaining) | ||||
| if remaining <= 0: | if remaining <= 0: | ||||
| self._writelog('read limit reached, closing socket') | self._writelog(b'read limit reached, closing socket') | ||||
| self._sock.close() | self._sock.close() | ||||
| # This is the easiest way to abort the current request. | # This is the easiest way to abort the current request. | ||||
| raise Exception('connection closed after receiving N bytes') | raise Exception('connection closed after receiving N bytes') | ||||
| return result | return result | ||||
| def readline(self, size=-1): | def readline(self, size=-1): | ||||
| remaining = object.__getattribute__(self, '_closeafterrecvbytes') | remaining = object.__getattribute__(self, '_closeafterrecvbytes') | ||||
| # No read limit. Call original function. | # No read limit. Call original function. | ||||
| if not remaining: | if not remaining: | ||||
| result = object.__getattribute__(self, '_orig').readline(size) | result = object.__getattribute__(self, '_orig').readline(size) | ||||
| self._writelog('readline(%d) -> (%d) %s' % ( | self._writelog(b'readline(%d) -> (%d) %s' % ( | ||||
| size, len(result), result)) | size, len(result), result)) | ||||
| return result | return result | ||||
| origsize = size | origsize = size | ||||
| if size < 0: | if size < 0: | ||||
| size = remaining | size = remaining | ||||
| else: | else: | ||||
| size = min(remaining, size) | size = min(remaining, size) | ||||
| result = object.__getattribute__(self, '_orig').readline(size) | result = object.__getattribute__(self, '_orig').readline(size) | ||||
| remaining -= len(result) | remaining -= len(result) | ||||
| self._writelog('readline(%d from %d) -> (%d) %s' % ( | self._writelog(b'readline(%d from %d) -> (%d) %s' % ( | ||||
| size, origsize, len(result), result)) | size, origsize, len(result), result)) | ||||
| object.__setattr__(self, '_closeafterrecvbytes', remaining) | object.__setattr__(self, '_closeafterrecvbytes', remaining) | ||||
| if remaining <= 0: | if remaining <= 0: | ||||
| self._writelog('read limit reached; closing socket') | self._writelog(b'read limit reached; closing socket') | ||||
| self._sock.close() | self._sock.close() | ||||
| # This is the easiest way to abort the current request. | # This is the easiest way to abort the current request. | ||||
| raise Exception('connection closed after receiving N bytes') | raise Exception('connection closed after receiving N bytes') | ||||
| return result | return result | ||||
| def write(self, data): | def write(self, data): | ||||
| remaining = object.__getattribute__(self, '_closeaftersendbytes') | remaining = object.__getattribute__(self, '_closeaftersendbytes') | ||||
| # No byte limit on this operation. Call original function. | # No byte limit on this operation. Call original function. | ||||
| if not remaining: | if not remaining: | ||||
| self._writelog('write(%d) -> %s' % (len(data), data)) | self._writelog(b'write(%d) -> %s' % (len(data), data)) | ||||
| result = object.__getattribute__(self, '_orig').write(data) | result = object.__getattribute__(self, '_orig').write(data) | ||||
| return result | return result | ||||
| if len(data) > remaining: | if len(data) > remaining: | ||||
| newdata = data[0:remaining] | newdata = data[0:remaining] | ||||
| else: | else: | ||||
| newdata = data | newdata = data | ||||
| remaining -= len(newdata) | remaining -= len(newdata) | ||||
| self._writelog('write(%d from %d) -> (%d) %s' % ( | self._writelog(b'write(%d from %d) -> (%d) %s' % ( | ||||
| len(newdata), len(data), remaining, newdata)) | len(newdata), len(data), remaining, newdata)) | ||||
| result = object.__getattribute__(self, '_orig').write(newdata) | result = object.__getattribute__(self, '_orig').write(newdata) | ||||
| object.__setattr__(self, '_closeaftersendbytes', remaining) | object.__setattr__(self, '_closeaftersendbytes', remaining) | ||||
| if remaining <= 0: | if remaining <= 0: | ||||
| self._writelog('write limit reached; closing socket') | self._writelog(b'write limit reached; closing socket') | ||||
| self._sock.close() | self._sock.close() | ||||
| raise Exception('connection closed after sending N bytes') | raise Exception('connection closed after sending N bytes') | ||||
| return result | return result | ||||
| def extsetup(ui): | def extsetup(ui): | ||||
| # Change the base HTTP server class so various events can be performed. | # Change the base HTTP server class so various events can be performed. | ||||
| # See SocketServer.BaseServer for how the specially named methods work. | # See SocketServer.BaseServer for how the specially named methods work. | ||||
| class badserver(server.MercurialHTTPServer): | class badserver(server.MercurialHTTPServer): | ||||
| def __init__(self, ui, *args, **kwargs): | def __init__(self, ui, *args, **kwargs): | ||||
| self._ui = ui | self._ui = ui | ||||
| super(badserver, self).__init__(ui, *args, **kwargs) | super(badserver, self).__init__(ui, *args, **kwargs) | ||||
| recvbytes = self._ui.config(b'badserver', b'closeafterrecvbytes') | recvbytes = self._ui.config(b'badserver', b'closeafterrecvbytes') | ||||
| recvbytes = recvbytes.split(',') | recvbytes = recvbytes.split(b',') | ||||
| self.closeafterrecvbytes = [int(v) for v in recvbytes if v] | self.closeafterrecvbytes = [int(v) for v in recvbytes if v] | ||||
| sendbytes = self._ui.config(b'badserver', b'closeaftersendbytes') | sendbytes = self._ui.config(b'badserver', b'closeaftersendbytes') | ||||
| sendbytes = sendbytes.split(',') | sendbytes = sendbytes.split(b',') | ||||
| self.closeaftersendbytes = [int(v) for v in sendbytes if v] | self.closeaftersendbytes = [int(v) for v in sendbytes if v] | ||||
| # Need to inherit object so super() works. | # Need to inherit object so super() works. | ||||
| class badrequesthandler(self.RequestHandlerClass, object): | class badrequesthandler(self.RequestHandlerClass, object): | ||||
| def send_header(self, name, value): | def send_header(self, name, value): | ||||
| # Make headers deterministic to facilitate testing. | # Make headers deterministic to facilitate testing. | ||||
| if name.lower() == 'date': | if name.lower() == 'date': | ||||
| value = 'Fri, 14 Apr 2017 00:00:00 GMT' | value = 'Fri, 14 Apr 2017 00:00:00 GMT' | ||||
| self.socket.close() | self.socket.close() | ||||
| # Tells the server to stop processing more requests. | # Tells the server to stop processing more requests. | ||||
| self.__shutdown_request = True | self.__shutdown_request = True | ||||
| # Simulate failure to stop processing this request. | # Simulate failure to stop processing this request. | ||||
| raise socket.error('close before accept') | raise socket.error('close before accept') | ||||
| if self._ui.configbool('badserver', 'closeafteraccept'): | if self._ui.configbool(b'badserver', b'closeafteraccept'): | ||||
| request, client_address = super(badserver, self).get_request() | request, client_address = super(badserver, self).get_request() | ||||
| request.close() | request.close() | ||||
| raise socket.error('close after accept') | raise socket.error('close after accept') | ||||
| return super(badserver, self).get_request() | return super(badserver, self).get_request() | ||||
| # Does heavy lifting of processing a request. Invokes | # Does heavy lifting of processing a request. Invokes | ||||
| # self.finish_request() which calls self.RequestHandlerClass() which | # self.finish_request() which calls self.RequestHandlerClass() which | ||||