##// END OF EJS Templates
protocol: declare transport protocol name...
Gregory Szorc -
r30562:b3a9ef3d default
parent child Browse files
Show More
@@ -1,124 +1,126 b''
1 1 #
2 2 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import cgi
11 11
12 12 from .common import (
13 13 HTTP_OK,
14 14 )
15 15
16 16 from .. import (
17 17 util,
18 18 wireproto,
19 19 )
20 20 stringio = util.stringio
21 21
22 22 urlerr = util.urlerr
23 23 urlreq = util.urlreq
24 24
25 25 HGTYPE = 'application/mercurial-0.1'
26 26 HGERRTYPE = 'application/hg-error'
27 27
28 28 class webproto(wireproto.abstractserverproto):
29 29 def __init__(self, req, ui):
30 30 self.req = req
31 31 self.response = ''
32 32 self.ui = ui
33 self.name = 'http'
34
33 35 def getargs(self, args):
34 36 knownargs = self._args()
35 37 data = {}
36 38 keys = args.split()
37 39 for k in keys:
38 40 if k == '*':
39 41 star = {}
40 42 for key in knownargs.keys():
41 43 if key != 'cmd' and key not in keys:
42 44 star[key] = knownargs[key][0]
43 45 data['*'] = star
44 46 else:
45 47 data[k] = knownargs[k][0]
46 48 return [data[k] for k in keys]
47 49 def _args(self):
48 50 args = self.req.form.copy()
49 51 postlen = int(self.req.env.get('HTTP_X_HGARGS_POST', 0))
50 52 if postlen:
51 53 args.update(cgi.parse_qs(
52 54 self.req.read(postlen), keep_blank_values=True))
53 55 return args
54 56 chunks = []
55 57 i = 1
56 58 while True:
57 59 h = self.req.env.get('HTTP_X_HGARG_' + str(i))
58 60 if h is None:
59 61 break
60 62 chunks += [h]
61 63 i += 1
62 64 args.update(cgi.parse_qs(''.join(chunks), keep_blank_values=True))
63 65 return args
64 66 def getfile(self, fp):
65 67 length = int(self.req.env['CONTENT_LENGTH'])
66 68 for s in util.filechunkiter(self.req, limit=length):
67 69 fp.write(s)
68 70 def redirect(self):
69 71 self.oldio = self.ui.fout, self.ui.ferr
70 72 self.ui.ferr = self.ui.fout = stringio()
71 73 def restore(self):
72 74 val = self.ui.fout.getvalue()
73 75 self.ui.ferr, self.ui.fout = self.oldio
74 76 return val
75 77
76 78 def compresschunks(self, chunks):
77 79 # Don't allow untrusted settings because disabling compression or
78 80 # setting a very high compression level could lead to flooding
79 81 # the server's network or CPU.
80 82 opts = {'level': self.ui.configint('server', 'zliblevel', -1)}
81 83 return util.compengines['zlib'].compressstream(chunks, opts)
82 84
83 85 def _client(self):
84 86 return 'remote:%s:%s:%s' % (
85 87 self.req.env.get('wsgi.url_scheme') or 'http',
86 88 urlreq.quote(self.req.env.get('REMOTE_HOST', '')),
87 89 urlreq.quote(self.req.env.get('REMOTE_USER', '')))
88 90
89 91 def iscmd(cmd):
90 92 return cmd in wireproto.commands
91 93
92 94 def call(repo, req, cmd):
93 95 p = webproto(req, repo.ui)
94 96 rsp = wireproto.dispatch(repo, p, cmd)
95 97 if isinstance(rsp, str):
96 98 req.respond(HTTP_OK, HGTYPE, body=rsp)
97 99 return []
98 100 elif isinstance(rsp, wireproto.streamres):
99 101 if rsp.reader:
100 102 gen = iter(lambda: rsp.reader.read(32768), '')
101 103 else:
102 104 gen = rsp.gen
103 105
104 106 if rsp.v1compressible:
105 107 gen = p.compresschunks(gen)
106 108
107 109 req.respond(HTTP_OK, HGTYPE)
108 110 return gen
109 111 elif isinstance(rsp, wireproto.pushres):
110 112 val = p.restore()
111 113 rsp = '%d\n%s' % (rsp.res, val)
112 114 req.respond(HTTP_OK, HGTYPE, body=rsp)
113 115 return []
114 116 elif isinstance(rsp, wireproto.pusherr):
115 117 # drain the incoming bundle
116 118 req.drain()
117 119 p.restore()
118 120 rsp = '0\n%s\n' % rsp.res
119 121 req.respond(HTTP_OK, HGTYPE, body=rsp)
120 122 return []
121 123 elif isinstance(rsp, wireproto.ooberror):
122 124 rsp = rsp.message
123 125 req.respond(HTTP_OK, HGERRTYPE, body=rsp)
124 126 return []
@@ -1,134 +1,135 b''
1 1 # sshserver.py - ssh protocol server support for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 from __future__ import absolute_import
10 10
11 11 import os
12 12 import sys
13 13
14 14 from .i18n import _
15 15 from . import (
16 16 error,
17 17 hook,
18 18 util,
19 19 wireproto,
20 20 )
21 21
22 22 class sshserver(wireproto.abstractserverproto):
23 23 def __init__(self, ui, repo):
24 24 self.ui = ui
25 25 self.repo = repo
26 26 self.lock = None
27 27 self.fin = ui.fin
28 28 self.fout = ui.fout
29 self.name = 'ssh'
29 30
30 31 hook.redirect(True)
31 32 ui.fout = repo.ui.fout = ui.ferr
32 33
33 34 # Prevent insertion/deletion of CRs
34 35 util.setbinary(self.fin)
35 36 util.setbinary(self.fout)
36 37
37 38 def getargs(self, args):
38 39 data = {}
39 40 keys = args.split()
40 41 for n in xrange(len(keys)):
41 42 argline = self.fin.readline()[:-1]
42 43 arg, l = argline.split()
43 44 if arg not in keys:
44 45 raise error.Abort(_("unexpected parameter %r") % arg)
45 46 if arg == '*':
46 47 star = {}
47 48 for k in xrange(int(l)):
48 49 argline = self.fin.readline()[:-1]
49 50 arg, l = argline.split()
50 51 val = self.fin.read(int(l))
51 52 star[arg] = val
52 53 data['*'] = star
53 54 else:
54 55 val = self.fin.read(int(l))
55 56 data[arg] = val
56 57 return [data[k] for k in keys]
57 58
58 59 def getarg(self, name):
59 60 return self.getargs(name)[0]
60 61
61 62 def getfile(self, fpout):
62 63 self.sendresponse('')
63 64 count = int(self.fin.readline())
64 65 while count:
65 66 fpout.write(self.fin.read(count))
66 67 count = int(self.fin.readline())
67 68
68 69 def redirect(self):
69 70 pass
70 71
71 72 def sendresponse(self, v):
72 73 self.fout.write("%d\n" % len(v))
73 74 self.fout.write(v)
74 75 self.fout.flush()
75 76
76 77 def sendstream(self, source):
77 78 write = self.fout.write
78 79
79 80 if source.reader:
80 81 gen = iter(lambda: source.reader.read(4096), '')
81 82 else:
82 83 gen = source.gen
83 84
84 85 for chunk in gen:
85 86 write(chunk)
86 87 self.fout.flush()
87 88
88 89 def sendpushresponse(self, rsp):
89 90 self.sendresponse('')
90 91 self.sendresponse(str(rsp.res))
91 92
92 93 def sendpusherror(self, rsp):
93 94 self.sendresponse(rsp.res)
94 95
95 96 def sendooberror(self, rsp):
96 97 self.ui.ferr.write('%s\n-\n' % rsp.message)
97 98 self.ui.ferr.flush()
98 99 self.fout.write('\n')
99 100 self.fout.flush()
100 101
101 102 def serve_forever(self):
102 103 try:
103 104 while self.serve_one():
104 105 pass
105 106 finally:
106 107 if self.lock is not None:
107 108 self.lock.release()
108 109 sys.exit(0)
109 110
110 111 handlers = {
111 112 str: sendresponse,
112 113 wireproto.streamres: sendstream,
113 114 wireproto.pushres: sendpushresponse,
114 115 wireproto.pusherr: sendpusherror,
115 116 wireproto.ooberror: sendooberror,
116 117 }
117 118
118 119 def serve_one(self):
119 120 cmd = self.fin.readline()[:-1]
120 121 if cmd and cmd in wireproto.commands:
121 122 rsp = wireproto.dispatch(self.repo, self, cmd)
122 123 self.handlers[rsp.__class__](self, rsp)
123 124 elif cmd:
124 125 impl = getattr(self, 'do_' + cmd, None)
125 126 if impl:
126 127 r = impl()
127 128 if r is not None:
128 129 self.sendresponse(r)
129 130 else: self.sendresponse("")
130 131 return cmd != ''
131 132
132 133 def _client(self):
133 134 client = os.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
134 135 return 'remote:ssh:' + client
General Comments 0
You need to be logged in to leave comments. Login now