blob: 236449483151696ee86f0e03cfbce2de41bd3c8c [file] [log] [blame]
Bram Moolenaard7ece102016-02-02 23:23:02 +01001#!/usr/bin/python
2#
3# Server that will accept connections from a Vim channel.
4# Run this server and then in Vim you can open the channel:
5# :let handle = ch_open('localhost:8765', 'json')
6#
7# Then Vim can send requests to the server:
8# :let response = ch_sendexpr(handle, 'hello!')
9#
Bram Moolenaard7ece102016-02-02 23:23:02 +010010# See ":help channel-demo" in Vim.
11#
12# This requires Python 2.6 or later.
13
14from __future__ import print_function
15import json
16import socket
17import sys
18import threading
19
20try:
21 # Python 3
22 import socketserver
23except ImportError:
24 # Python 2
25 import SocketServer as socketserver
26
27thesocket = None
28
29class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
30
31 def handle(self):
32 print("=== socket opened ===")
33 global thesocket
34 thesocket = self.request
35 while True:
36 try:
37 data = self.request.recv(4096).decode('utf-8')
38 except socket.error:
39 print("=== socket error ===")
40 break
41 except IOError:
42 print("=== socket closed ===")
43 break
44 if data == '':
45 print("=== socket closed ===")
46 break
47 print("received: {}".format(data))
48 try:
49 decoded = json.loads(data)
50 except ValueError:
51 print("json decoding failed")
52 decoded = [-1, '']
53
54 # Send a response if the sequence number is positive.
55 # Negative numbers are used for "eval" responses.
56 if decoded[0] >= 0:
57 if decoded[1] == 'hello!':
58 # simply send back a string
59 response = "got it"
60 elif decoded[1] == 'make change':
61 # Send two ex commands at the same time, before replying to
62 # the request.
63 cmd = '["ex","call append(\\"$\\",\\"added1\\")"]'
64 cmd += '["ex","call append(\\"$\\",\\"added2\\")"]'
65 print("sending: {}".format(cmd))
66 thesocket.sendall(cmd.encode('utf-8'))
67 response = "ok"
68 elif decoded[1] == '!quit!':
69 # we're done
70 sys.exit(0)
71 else:
72 response = "what?"
73
74 encoded = json.dumps([decoded[0], response])
75 print("sending: {}".format(encoded))
76 thesocket.sendall(encoded.encode('utf-8'))
77
78 thesocket = None
79
80class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
81 pass
82
83if __name__ == "__main__":
84 HOST, PORT = "localhost", 0
85
86 server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
87 ip, port = server.server_address
88
89 # Start a thread with the server -- that thread will then start one
90 # more thread for each request
91 server_thread = threading.Thread(target=server.serve_forever)
92
93 # Exit the server thread when the main thread terminates
94 server_thread.daemon = True
95 server_thread.start()
96
97 # Write the port number in Xportnr, so that the test knows it.
98 f = open("Xportnr", "w")
99 f.write("{}".format(port))
100 f.close()
101
102 # Block here
103 print("Listening on port {}".format(port))
104 server.serve_forever()