blob: c701434b28a234fad62d6836f1c91b4ac68ed0e9 [file] [log] [blame]
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001#!/usr/bin/python
Bram Moolenaarf57969a2016-02-02 20:47:49 +01002#
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01003# Server that will accept connections from a Vim channel.
4# Run this server and then in Vim you can open the channel:
Bram Moolenaare0fa3742016-02-20 15:47:01 +01005# :let handle = ch_open('localhost:8765')
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01006#
7# Then Vim can send requests to the server:
Bram Moolenaarf57969a2016-02-02 20:47:49 +01008# :let response = ch_sendexpr(handle, 'hello!')
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01009#
10# And you can control Vim by typing a JSON message here, e.g.:
11# ["ex","echo 'hi there'"]
12#
Bram Moolenaarf57969a2016-02-02 20:47:49 +010013# There is no prompt, just type a line and press Enter.
14# To exit cleanly type "quit<Enter>".
15#
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010016# See ":help channel-demo" in Vim.
Bram Moolenaarf57969a2016-02-02 20:47:49 +010017#
18# This requires Python 2.6 or later.
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010019
Bram Moolenaar488a1302016-02-01 22:01:10 +010020from __future__ import print_function
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010021import json
22import socket
23import sys
24import threading
25
Bram Moolenaar488a1302016-02-01 22:01:10 +010026try:
27 # Python 3
28 import socketserver
29except ImportError:
30 # Python 2
31 import SocketServer as socketserver
32
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010033thesocket = None
34
Bram Moolenaar488a1302016-02-01 22:01:10 +010035class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010036
37 def handle(self):
Bram Moolenaar488a1302016-02-01 22:01:10 +010038 print("=== socket opened ===")
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010039 global thesocket
40 thesocket = self.request
41 while True:
42 try:
Bram Moolenaar488a1302016-02-01 22:01:10 +010043 data = self.request.recv(4096).decode('utf-8')
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010044 except socket.error:
Bram Moolenaar488a1302016-02-01 22:01:10 +010045 print("=== socket error ===")
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010046 break
47 except IOError:
Bram Moolenaar488a1302016-02-01 22:01:10 +010048 print("=== socket closed ===")
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010049 break
50 if data == '':
Bram Moolenaar488a1302016-02-01 22:01:10 +010051 print("=== socket closed ===")
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010052 break
Bram Moolenaar488a1302016-02-01 22:01:10 +010053 print("received: {}".format(data))
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010054 try:
55 decoded = json.loads(data)
56 except ValueError:
Bram Moolenaar488a1302016-02-01 22:01:10 +010057 print("json decoding failed")
58 decoded = [-1, '']
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010059
Bram Moolenaar488a1302016-02-01 22:01:10 +010060 # Send a response if the sequence number is positive.
61 # Negative numbers are used for "eval" responses.
62 if decoded[0] >= 0:
63 if decoded[1] == 'hello!':
64 response = "got it"
65 else:
66 response = "what?"
67 encoded = json.dumps([decoded[0], response])
68 print("sending {}".format(encoded))
69 self.request.sendall(encoded.encode('utf-8'))
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010070 thesocket = None
71
Bram Moolenaar488a1302016-02-01 22:01:10 +010072class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010073 pass
74
75if __name__ == "__main__":
76 HOST, PORT = "localhost", 8765
77
78 server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
79 ip, port = server.server_address
80
81 # Start a thread with the server -- that thread will then start one
82 # more thread for each request
83 server_thread = threading.Thread(target=server.serve_forever)
84
85 # Exit the server thread when the main thread terminates
86 server_thread.daemon = True
87 server_thread.start()
Bram Moolenaar488a1302016-02-01 22:01:10 +010088 print("Server loop running in thread: ", server_thread.name)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010089
Bram Moolenaar488a1302016-02-01 22:01:10 +010090 print("Listening on port {}".format(PORT))
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010091 while True:
92 typed = sys.stdin.readline()
93 if "quit" in typed:
Bram Moolenaar488a1302016-02-01 22:01:10 +010094 print("Goodbye!")
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010095 break
96 if thesocket is None:
Bram Moolenaar488a1302016-02-01 22:01:10 +010097 print("No socket yet")
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010098 else:
Bram Moolenaar488a1302016-02-01 22:01:10 +010099 print("sending {}".format(typed))
100 thesocket.sendall(typed.encode('utf-8'))
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100101
102 server.shutdown()
103 server.server_close()