blob: 0f6a3740c631feca4e80df2f0c52f24c72de288a [file] [log] [blame]
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001#!/usr/bin/python
2# Server that will accept connections from a Vim channel.
3# Run this server and then in Vim you can open the channel:
4# :let handle = connect('localhost:8765', 'json')
5#
6# Then Vim can send requests to the server:
7# :let response = sendexpr(handle, 'hello!')
8#
9# And you can control Vim by typing a JSON message here, e.g.:
10# ["ex","echo 'hi there'"]
11#
12# See ":help channel-demo" in Vim.
13
Bram Moolenaar488a1302016-02-01 22:01:10 +010014from __future__ import print_function
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010015import json
16import socket
17import sys
18import threading
19
Bram Moolenaar488a1302016-02-01 22:01:10 +010020try:
21 # Python 3
22 import socketserver
23except ImportError:
24 # Python 2
25 import SocketServer as socketserver
26
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010027thesocket = None
28
Bram Moolenaar488a1302016-02-01 22:01:10 +010029class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010030
31 def handle(self):
Bram Moolenaar488a1302016-02-01 22:01:10 +010032 print("=== socket opened ===")
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010033 global thesocket
34 thesocket = self.request
35 while True:
36 try:
Bram Moolenaar488a1302016-02-01 22:01:10 +010037 data = self.request.recv(4096).decode('utf-8')
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010038 except socket.error:
Bram Moolenaar488a1302016-02-01 22:01:10 +010039 print("=== socket error ===")
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010040 break
41 except IOError:
Bram Moolenaar488a1302016-02-01 22:01:10 +010042 print("=== socket closed ===")
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010043 break
44 if data == '':
Bram Moolenaar488a1302016-02-01 22:01:10 +010045 print("=== socket closed ===")
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010046 break
Bram Moolenaar488a1302016-02-01 22:01:10 +010047 print("received: {}".format(data))
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010048 try:
49 decoded = json.loads(data)
50 except ValueError:
Bram Moolenaar488a1302016-02-01 22:01:10 +010051 print("json decoding failed")
52 decoded = [-1, '']
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010053
Bram Moolenaar488a1302016-02-01 22:01:10 +010054 # 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 response = "got it"
59 else:
60 response = "what?"
61 encoded = json.dumps([decoded[0], response])
62 print("sending {}".format(encoded))
63 self.request.sendall(encoded.encode('utf-8'))
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010064 thesocket = None
65
Bram Moolenaar488a1302016-02-01 22:01:10 +010066class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010067 pass
68
69if __name__ == "__main__":
70 HOST, PORT = "localhost", 8765
71
72 server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
73 ip, port = server.server_address
74
75 # Start a thread with the server -- that thread will then start one
76 # more thread for each request
77 server_thread = threading.Thread(target=server.serve_forever)
78
79 # Exit the server thread when the main thread terminates
80 server_thread.daemon = True
81 server_thread.start()
Bram Moolenaar488a1302016-02-01 22:01:10 +010082 print("Server loop running in thread: ", server_thread.name)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010083
Bram Moolenaar488a1302016-02-01 22:01:10 +010084 print("Listening on port {}".format(PORT))
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010085 while True:
86 typed = sys.stdin.readline()
87 if "quit" in typed:
Bram Moolenaar488a1302016-02-01 22:01:10 +010088 print("Goodbye!")
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010089 break
90 if thesocket is None:
Bram Moolenaar488a1302016-02-01 22:01:10 +010091 print("No socket yet")
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010092 else:
Bram Moolenaar488a1302016-02-01 22:01:10 +010093 print("sending {}".format(typed))
94 thesocket.sendall(typed.encode('utf-8'))
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010095
96 server.shutdown()
97 server.server_close()