##// END OF EJS Templates
serve: use chunked encoding in hgweb responses...
serve: use chunked encoding in hgweb responses 'hg serve' used to close connections when sending a response with unknown length ... such as a bundle or archive. Now chunked encoding will be used for responses with unknown length, and the connection do thus not have to be closed to indicate the end of the response. Chunked encoding is only used if the length is unknown, if the connection wouldn't be closed for other reasons, AND if it is a HTTP 1.1 request. This will not benefit other users of hgweb ... but it can serve as an example that it can be done.

File last commit:

r17563:46db0ec6 default
r18354:cf5c7601 default
Show More
sshserver.py
152 lines | 4.2 KiB | text/x-python | PythonLexer
Vadim Gelfer
fix comment.
r2399 # sshserver.py - ssh protocol server support for mercurial
Vadim Gelfer
refactor ssh server.
r2396 #
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
Vadim Gelfer
update copyrights.
r2859 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
Vadim Gelfer
refactor ssh server.
r2396 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Vadim Gelfer
refactor ssh server.
r2396
Matt Mackall
bundle: encapsulate all bundle streams in unbundle class
r12337 import util, hook, wireproto, changegroup
Matt Mackall
ssh: drop some old imports
r11596 import os, sys
Vadim Gelfer
refactor ssh server.
r2396
class sshserver(object):
def __init__(self, ui, repo):
self.ui = ui
self.repo = repo
self.lock = None
Idan Kamara
ui: use I/O descriptors internally...
r14614 self.fin = ui.fin
self.fout = ui.fout
Vadim Gelfer
refactor ssh server.
r2396
Matt Mackall
hook: redirect stdout to stderr for ssh and http servers
r5833 hook.redirect(True)
Idan Kamara
ui: use I/O descriptors internally...
r14614 ui.fout = repo.ui.fout = ui.ferr
Vadim Gelfer
refactor ssh server.
r2396
# Prevent insertion/deletion of CRs
Adrian Buehlmann
rename util.set_binary to setbinary
r14233 util.setbinary(self.fin)
util.setbinary(self.fout)
Vadim Gelfer
refactor ssh server.
r2396
Matt Mackall
protocol: add ssh getargs...
r11579 def getargs(self, args):
data = {}
keys = args.split()
for n in xrange(len(keys)):
argline = self.fin.readline()[:-1]
arg, l = argline.split()
if arg not in keys:
raise util.Abort("unexpected parameter %r" % arg)
if arg == '*':
star = {}
Peter Arrenbrecht
wireproto: fix handling of '*' args for HTTP and SSH
r13721 for k in xrange(int(l)):
argline = self.fin.readline()[:-1]
Matt Mackall
protocol: add ssh getargs...
r11579 arg, l = argline.split()
val = self.fin.read(int(l))
star[arg] = val
data['*'] = star
else:
Peter Arrenbrecht
wireproto: fix handling of '*' args for HTTP and SSH
r13721 val = self.fin.read(int(l))
Matt Mackall
protocol: add ssh getargs...
r11579 data[arg] = val
return [data[k] for k in keys]
def getarg(self, name):
return self.getargs(name)[0]
Vadim Gelfer
refactor ssh server.
r2396
Dirkjan Ochtman
protocol: shuffle server methods to group send methods
r11621 def getfile(self, fpout):
Dirkjan Ochtman
protocol: rename send methods to get grouping by prefix
r11622 self.sendresponse('')
Dirkjan Ochtman
protocol: shuffle server methods to group send methods
r11621 count = int(self.fin.readline())
while count:
fpout.write(self.fin.read(count))
count = int(self.fin.readline())
def redirect(self):
pass
Dirkjan Ochtman
protocol: extract compression from streaming mechanics
r11623 def groupchunks(self, changegroup):
Matt Mackall
protocol: unify changegroup commands...
r11584 while True:
d = changegroup.read(4096)
if not d:
break
Dirkjan Ochtman
protocol: extract compression from streaming mechanics
r11623 yield d
Matt Mackall
protocol: unify changegroup commands...
r11584
Dirkjan Ochtman
protocol: extract compression from streaming mechanics
r11623 def sendresponse(self, v):
self.fout.write("%d\n" % len(v))
self.fout.write(v)
Matt Mackall
protocol: unify changegroup commands...
r11584 self.fout.flush()
Matt Mackall
protocol: unify stream_out command
r11585 def sendstream(self, source):
Bryan O'Sullivan
sshserver: avoid a multi-dot attribute lookup in a hot loop...
r17563 write = self.fout.write
Dirkjan Ochtman
protocol: wrap non-string protocol responses in classes
r11625 for chunk in source.gen:
Bryan O'Sullivan
sshserver: avoid a multi-dot attribute lookup in a hot loop...
r17563 write(chunk)
Matt Mackall
protocol: unify stream_out command
r11585 self.fout.flush()
Dirkjan Ochtman
protocol: wrap non-string protocol responses in classes
r11625 def sendpushresponse(self, rsp):
Dirkjan Ochtman
protocol: rename send methods to get grouping by prefix
r11622 self.sendresponse('')
Dirkjan Ochtman
protocol: wrap non-string protocol responses in classes
r11625 self.sendresponse(str(rsp.res))
Matt Mackall
protocol: unify unbundle on the server side
r11593
Benoit Boissinot
wireproto: introduce pusherr() to deal with "unsynced changes" error...
r12703 def sendpusherror(self, rsp):
self.sendresponse(rsp.res)
Andrew Pritchard
wireproto: add out-of-band error class to allow remote repo to report errors...
r15017 def sendooberror(self, rsp):
self.ui.ferr.write('%s\n-\n' % rsp.message)
self.ui.ferr.flush()
self.fout.write('\n')
self.fout.flush()
Vadim Gelfer
refactor ssh server.
r2396 def serve_forever(self):
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 try:
Matt Mackall
many, many trivial check-code fixups
r10282 while self.serve_one():
pass
Ronny Pfannschmidt
switch lock releasing in the core from gc to explicit
r8109 finally:
if self.lock is not None:
self.lock.release()
Vadim Gelfer
refactor ssh server.
r2396 sys.exit(0)
Dirkjan Ochtman
protocol: wrap non-string protocol responses in classes
r11625 handlers = {
str: sendresponse,
wireproto.streamres: sendstream,
wireproto.pushres: sendpushresponse,
Benoit Boissinot
wireproto: introduce pusherr() to deal with "unsynced changes" error...
r12703 wireproto.pusherr: sendpusherror,
Andrew Pritchard
wireproto: add out-of-band error class to allow remote repo to report errors...
r15017 wireproto.ooberror: sendooberror,
Dirkjan Ochtman
protocol: wrap non-string protocol responses in classes
r11625 }
Vadim Gelfer
refactor ssh server.
r2396 def serve_one(self):
cmd = self.fin.readline()[:-1]
Dirkjan Ochtman
protocol: command must be checked before passing in
r11618 if cmd and cmd in wireproto.commands:
Dirkjan Ochtman
protocol: wrap non-string protocol responses in classes
r11625 rsp = wireproto.dispatch(self.repo, self, cmd)
self.handlers[rsp.__class__](self, rsp)
Dirkjan Ochtman
protocol: command must be checked before passing in
r11618 elif cmd:
Vadim Gelfer
refactor ssh server.
r2396 impl = getattr(self, 'do_' + cmd, None)
Matt Mackall
many, many trivial check-code fixups
r10282 if impl:
Matt Mackall
protocol: move most ssh responses to returns
r11580 r = impl()
if r is not None:
Dirkjan Ochtman
protocol: rename send methods to get grouping by prefix
r11622 self.sendresponse(r)
else: self.sendresponse("")
Vadim Gelfer
refactor ssh server.
r2396 return cmd != ''
def do_lock(self):
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439 '''DEPRECATED - allowing remote client to lock repo is not safe'''
Vadim Gelfer
refactor ssh server.
r2396 self.lock = self.repo.lock()
Matt Mackall
protocol: move most ssh responses to returns
r11580 return ""
Vadim Gelfer
refactor ssh server.
r2396
def do_unlock(self):
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439 '''DEPRECATED'''
Vadim Gelfer
refactor ssh server.
r2396 if self.lock:
self.lock.release()
self.lock = None
Matt Mackall
protocol: move most ssh responses to returns
r11580 return ""
Vadim Gelfer
refactor ssh server.
r2396
def do_addchangegroup(self):
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439 '''DEPRECATED'''
Vadim Gelfer
refactor ssh server.
r2396 if not self.lock:
Dirkjan Ochtman
protocol: rename send methods to get grouping by prefix
r11622 self.sendresponse("not locked")
Vadim Gelfer
refactor ssh server.
r2396 return
Dirkjan Ochtman
protocol: rename send methods to get grouping by prefix
r11622 self.sendresponse("")
Matt Mackall
bundle: encapsulate all bundle streams in unbundle class
r12337 cg = changegroup.unbundle10(self.fin, "UN")
Pierre-Yves David
addchangegroup: remove the lock argument on the addchangegroup methods...
r15585 r = self.repo.addchangegroup(cg, 'serve', self._client())
self.lock.release()
Matt Mackall
protocol: move most ssh responses to returns
r11580 return str(r)
Vadim Gelfer
extend network protocol to stop clients from locking servers...
r2439
Matt Mackall
protocol: unify unbundle on the server side
r11593 def _client(self):
Vadim Gelfer
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks...
r2673 client = os.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
return 'remote:ssh:' + client