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