Ticket #983: vsock-v3.patch
File vsock-v3.patch, 17.3 KB (added by , 6 years ago) |
---|
-
setup.py
127 127 opengl_ENABLED = DEFAULT and client_ENABLED 128 128 html5_ENABLED = DEFAULT and not WIN32 and not OSX 129 129 130 vsock_ENABLED = sys.platform.startswith("linux") 130 131 bencode_ENABLED = DEFAULT 131 132 cython_bencode_ENABLED = DEFAULT 132 133 clipboard_ENABLED = DEFAULT and not PYTHON3 … … 201 202 "dec_avcodec2", "csc_swscale", 202 203 "csc_opencl", "csc_cython", "csc_opencv", "csc_libyuv", 203 204 "memoryview", 204 "bencode", "cython_bencode", 205 "bencode", "cython_bencode", "vsock", 205 206 "clipboard", 206 207 "server", "client", "dbus", "x11", "gtk_x11", 207 208 "gtk2", "gtk3", "html5", … … 2350 2351 ["xpra/net/bencode/cython_bencode.pyx", buffers_c], 2351 2352 **bencode_pkgconfig)) 2352 2353 2354 if vsock_ENABLED: 2355 vsock_pkgconfig = pkgconfig() 2356 cython_add(Extension("xpra.net.vsock", 2357 ["xpra/net/vsock.pyx"], 2358 **vsock_pkgconfig)) 2353 2359 2360 2354 2361 if ext_modules: 2355 2362 from Cython.Build import cythonize 2356 2363 #this causes Cython to fall over itself: -
xpra/scripts/config.py
273 273 "title" : str, 274 274 "username" : str, 275 275 "auth" : str, 276 "vsock-auth" : str, 276 277 "tcp-auth" : str, 277 278 "wm-name" : str, 278 279 "session-name" : str, … … 387 388 "start-on-connect" : list, 388 389 "start-child-on-connect" : list, 389 390 "bind" : list, 391 "bind-vsock" : list, 390 392 "bind-tcp" : list, 391 393 "env" : list, 392 394 } … … 452 454 "title" : "@title@ on @client-machine@", 453 455 "username" : username, 454 456 "auth" : "", 457 "vsock-auth" : "", 455 458 "tcp-auth" : "", 456 459 "wm-name" : DEFAULT_NET_WM_NAME, 457 460 "session-name" : "", … … 557 560 "packet-encoders" : ["all"], 558 561 "key-shortcut" : get_default_key_shortcuts(), 559 562 "bind" : bind_dirs, 563 "bind-vsock" : [], 560 564 "bind-tcp" : [], 561 565 "start" : [], 562 566 "start-child" : [], -
xpra/scripts/main.py
29 29 make_defaults_struct, parse_bool, print_bool, print_number, validate_config, has_sound_support, name_to_field 30 30 31 31 32 VSOCK_TIMEOUT = int(os.environ.get("XPRA_VSOCK_TIMEOUT", 5)) 32 33 SOCKET_TIMEOUT = int(os.environ.get("XPRA_SOCKET_TIMEOUT", 10)) 33 34 TCP_NODELAY = int(os.environ.get("XPRA_TCP_NODELAY", "1")) 34 35 NO_ROOT_WARNING = int(os.environ.get("XPRA_NO_ROOT_WARNING", "0")) … … 380 381 + " You may specify this option multiple times with different host and port combinations") 381 382 else: 382 383 ignore({"bind-tcp" : []}) 384 try: 385 from xpra.net import vsock 386 except: 387 vsock = None 388 if vsock: 389 group.add_option("--bind-vsock", action="append", 390 dest="bind_vsock", default=list(defaults.bind_vsock or []), 391 metavar="[CID]:[PORT]", 392 help="Listen for connections over VSOCK (use --password-file to secure it)." 393 + " You may specify this option multiple times with different CID and port combinations") 394 else: 395 ignore({"bind-vsock" : []}) 383 396 legacy_bool_parse("mdns") 384 397 if (supports_server or supports_shadow): 385 398 group.add_option("--mdns", action="store", metavar="yes|no", … … 674 687 group.add_option("--tcp-auth", action="store", 675 688 dest="tcp_auth", default=defaults.tcp_auth, 676 689 help="The authentication module to use for TCP sockets (default: '%default')") 690 if vsock: 691 group.add_option("--vsock-auth", action="store", 692 dest="vsock_auth", default=defaults.vsock_auth, 693 help="The authentication module to use for vsock sockets (default: '%default')") 694 else: 695 ignore({"vsock-auth" : ""}) 677 696 if os.name=="posix": 678 697 group.add_option("--mmap-group", action="store_true", 679 698 dest="mmap_group", default=defaults.mmap_group, … … 1009 1028 return 128+signal.SIGINT 1010 1029 1011 1030 1031 def parse_vsock(vsock_str): 1032 from xpra.net.vsock import STR_TO_CID, CID_ANY, PORT_ANY #@UnresolvedImport 1033 if not vsock_str.find(":")>=0: 1034 raise InitException("invalid vsocket format '%s'" % vsock_str) 1035 cid_str, port_str = vsock_str.split(":", 1) 1036 if cid_str.lower() in ("auto", "any"): 1037 cid = CID_ANY 1038 else: 1039 try: 1040 cid = int(cid_str) 1041 except ValueError: 1042 cid = STR_TO_CID.get(cid_str.upper()) 1043 if cid is None: 1044 raise InitException("invalid vsock cid '%s'" % cid_str) 1045 if port_str.lower() in ("auto", "any"): 1046 iport = PORT_ANY 1047 else: 1048 try: 1049 iport = int(port_str) 1050 except ValueError: 1051 raise InitException("invalid vsock port '%s'" % port_str) 1052 return cid, iport 1053 1012 1054 def parse_display_name(error_cb, opts, display_name): 1013 1055 desc = {"display_name" : display_name} 1014 1056 if display_name.lower().startswith("ssh:") or display_name.lower().startswith("ssh/"): … … 1172 1214 host = "127.0.0.1" 1173 1215 desc["host"] = host 1174 1216 return desc 1217 elif display_name.startswith("vsock:"): 1218 #use the vsock specified: 1219 vsock_str = display_name[len("vsock:"):] 1220 cid, iport = parse_vsock(vsock_str) 1221 desc.update({ 1222 "type" : "vsock", 1223 "local" : False, 1224 "display" : display_name, 1225 "vsock" : (cid, iport), 1226 }) 1227 opts.display = display_name 1228 return desc 1175 1229 elif sys.platform.startswith("win") or display_name.startswith("named-pipe:"): 1176 1230 pipe_name = display_name 1177 1231 if display_name.startswith("named-pipe:"): … … 1248 1302 except InitException: 1249 1303 raise 1250 1304 except Exception as e: 1251 raise1252 # traceback.print_stack()1253 1305 raise InitException("connection failed: %s" % e) 1254 1306 1255 1307 def ssh_connect_failed(message): … … 1391 1443 conn = NamedPipeConnection(pipe_name, pipe_handle) 1392 1444 conn.timeout = SOCKET_TIMEOUT 1393 1445 1446 elif dtype == "vsock": 1447 cid, iport = display_desc["vsock"] 1448 from xpra.net.vsock import connect_vsocket 1449 conn = connect_vsocket(cid=cid, port=iport) 1450 conn.timeout = VSOCK_TIMEOUT 1451 1394 1452 elif dtype == "tcp": 1395 1453 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 1396 1454 sock.settimeout(SOCKET_TIMEOUT) -
xpra/scripts/server.py
362 362 tcp_sockets.add((host, iport)) 363 363 return tcp_sockets 364 364 365 def setup_vsock_socket(cid, iport): 366 from xpra.log import Logger 367 log = Logger("network") 368 try: 369 from xpra.net.vsock import bind_vsocket #@UnresolvedImport 370 vsock_socket = bind_vsocket(cid=cid, port=iport) 371 except Exception as e: 372 raise InitException("failed to setup vsock socket on %s:%s %s" % (cid, iport, e)) 373 def cleanup_vsock_socket(): 374 log.info("closing vsock socket %s:%s", cid, iport) 375 try: 376 vsock_socket.close() 377 except: 378 pass 379 _cleanups.append(cleanup_vsock_socket) 380 return "vsock", vsock_socket, (cid, iport) 365 381 382 def parse_bind_vsock(bind_vsock): 383 vsock_sockets = set() 384 if bind_vsock: 385 from xpra.scripts.main import parse_vsock 386 for spec in bind_vsock: 387 vsock_sockets.add(parse_vsock(spec)) 388 return vsock_sockets 389 390 366 391 def normalize_local_display_name(local_display_name): 367 392 if not local_display_name.startswith(":"): 368 393 local_display_name = ":" + local_display_name … … 1046 1071 socket = setup_tcp_socket(host, iport) 1047 1072 sockets.append(socket) 1048 1073 if opts.mdns: 1049 mdns_recs.append(("tcp", bind_tcp)) 1074 rec = "tcp", [(host, iport)] 1075 mdns_recs.append(rec) 1050 1076 1077 bind_vsock = parse_bind_vsock(opts.bind_vsock) 1078 for cid, iport in bind_vsock: 1079 socket = setup_vsock_socket(cid, iport) 1080 sockets.append(socket) 1081 if opts.mdns: 1082 rec = "vsock", [("", iport)] 1083 mdns_recs.append(rec) 1084 1051 1085 # Do this after writing out the shell script: 1052 1086 if display_name[0] != 'S': 1053 1087 os.environ["DISPLAY"] = display_name -
xpra/net/vsock_client_test.py
1 # This file is part of Xpra. 2 # Copyright (C) 2016 Antoine Martin <antoine@devloop.org.uk> 3 # Xpra is released under the terms of the GNU GPL v2, or, at your option, any 4 # later version. See the file COPYING for details. 5 6 7 import sys 8 from xpra.net.vsock import connect_vsocket, CID_ANY, PORT_ANY #@UnresolvedImport 9 10 from xpra.log import Logger 11 log = Logger("network") 12 13 14 def main(args): 15 cid = CID_ANY 16 port = PORT_ANY 17 if len(args)>0: 18 cid = int(args[0]) 19 if len(args)>1: 20 port = int(args[1]) 21 22 vsock = connect_vsocket(cid=cid, port=port) 23 log("vsock=%s", vsock) 24 data = vsock.recv(1024) 25 log("recv()=%s", data) 26 27 if __name__ == "__main__": 28 sys.exit(main(sys.argv[1:])) -
xpra/net/vsock.pyx
1 # This file is part of Xpra. 2 # Copyright (C) 2016 Antoine Martin <antoine@devloop.org.uk> 3 # Xpra is released under the terms of the GNU GPL v2, or, at your option, any 4 # later version. See the file COPYING for details. 5 6 #cython: boundscheck=False, wraparound=False, cdivision=True 7 8 import socket as pysocket 9 import struct 10 from xpra.log import Logger 11 log = Logger("network") 12 13 14 cdef extern from "string.h": 15 void *memset(void * ptr, int value, size_t num) nogil 16 17 cdef extern from "unistd.h": 18 int close(int fd) 19 20 cdef extern from "sys/socket.h": 21 int AF_VSOCK 22 int SOCK_DGRAM 23 int SOCK_STREAM 24 cdef struct sockaddr: 25 pass 26 ctypedef int socklen_t 27 int socket(int socket_family, int socket_type, int protocol) 28 int bind(int sockfd, const sockaddr *addr, socklen_t addrlen) 29 int getsockname(int sockfd, sockaddr *addr, socklen_t *addrlen) 30 int accept(int sockfd, sockaddr *addr, socklen_t *addrlen) 31 int connect(int sockfd, const sockaddr *addr, socklen_t addrlen) 32 33 34 cdef extern from "linux/vm_sockets.h": 35 unsigned int VMADDR_CID_ANY 36 unsigned int VMADDR_CID_HYPERVISOR 37 unsigned int VMADDR_CID_HOST 38 unsigned int VMADDR_PORT_ANY 39 40 41 unsigned int SO_VM_SOCKETS_BUFFER_SIZE 42 unsigned int SO_VM_SOCKETS_BUFFER_MIN_SIZE 43 unsigned int SO_VM_SOCKETS_BUFFER_MAX_SIZE 44 unsigned int SO_VM_SOCKETS_PEER_HOST_VM_ID 45 unsigned int SO_VM_SOCKETS_TRUSTED 46 unsigned int SO_VM_SOCKETS_CONNECT_TIMEOUT 47 unsigned int SO_VM_SOCKETS_NONBLOCK_TXRX 48 49 ctypedef unsigned short __kernel_sa_family_t 50 cdef struct sockaddr_vm: 51 __kernel_sa_family_t svm_family 52 unsigned short svm_reserved1 53 unsigned int svm_port 54 unsigned int svm_cid 55 56 CID_ANY = VMADDR_CID_ANY 57 CID_HYPERVISOR = VMADDR_CID_HYPERVISOR 58 CID_HOST = VMADDR_CID_HOST 59 PORT_ANY = VMADDR_PORT_ANY 60 61 CID_TYPES = { 62 CID_ANY : "ANY", 63 CID_HYPERVISOR : "HYPERVISOR", 64 CID_HOST : "HOST", 65 } 66 STR_TO_CID = { 67 "ANY" : CID_ANY, 68 "HYPERVISOR" : CID_HYPERVISOR, 69 "HOST" : CID_HOST, 70 } 71 72 SOCK_TYPES = { 73 SOCK_STREAM : "STREAM", 74 SOCK_DGRAM : "DGRAM", 75 } 76 77 78 def bind_vsocket(sock_type=SOCK_STREAM, cid=VMADDR_CID_HOST, port=VMADDR_PORT_ANY): 79 log("server_socket(%s)", (SOCK_TYPES.get(sock_type, sock_type), CID_TYPES.get(cid, cid), port)) 80 assert sock_type in (SOCK_STREAM, SOCK_DGRAM), "invalid socket type %s" % sock_type 81 #assert cid in (VMADDR_CID_ANY, VMADDR_CID_HYPERVISOR, VMADDR_CID_HOST), "invalid cid %s" % cid 82 assert port==VMADDR_PORT_ANY or (port>0 and port<65536) 83 log("socket(AF_VSOCK, %s, 0)", SOCK_TYPES.get(sock_type, sock_type)) 84 cdef int sockfd = socket(AF_VSOCK, sock_type, 0) 85 log("socket(..)=%i", sockfd) 86 if sockfd<0: 87 raise Exception("AF_VSOCK not supported") 88 cdef sockaddr_vm vmsock 89 memset(&vmsock, 0, sizeof(sockaddr_vm)) 90 vmsock.svm_family = AF_VSOCK 91 vmsock.svm_cid = cid #VMADDR_CID_HOST 92 vmsock.svm_port = port 93 94 if bind(sockfd, <sockaddr*> &vmsock, sizeof(sockaddr_vm)): 95 close(sockfd) 96 raise Exception("failed to bind to AF_VSOCK socket %i:%i", cid, port) 97 98 cdef socklen_t socklen = sizeof(sockaddr_vm) 99 if getsockname(sockfd, <sockaddr *> &vmsock, &socklen): 100 close(sockfd) 101 raise Exception("getsockname failed") 102 log("cid=%s, port=%i", CID_TYPES.get(vmsock.svm_cid, vmsock.svm_cid), vmsock.svm_port) 103 vsock = VSocket(sockfd) 104 return vsock 105 106 class VSocket(object): 107 def __init__(self, sockfd): 108 self.sockfd = sockfd 109 self.sock = pysocket.fromfd(sockfd, AF_VSOCK, 0) 110 self.address = None 111 112 def __getattr__(self, attr): 113 return getattr(self.sock, attr) 114 115 def accept(self): 116 cdef sockaddr_vm vmsock 117 cdef socklen_t socklen = sizeof(sockaddr_vm) 118 memset(&vmsock, 0, socklen) 119 cdef int fd = accept(self.sockfd, <sockaddr*> &vmsock, &socklen) 120 if fd<0: 121 raise Exception("accept failed: %s" % fd) 122 conn = pysocket.fromfd(fd, AF_VSOCK, 0) 123 if getsockname(fd, <sockaddr *> &vmsock, &socklen): 124 close(fd) 125 raise Exception("getsockname failed") 126 self.address = (vmsock.svm_cid, vmsock.svm_port) 127 return VSocket(conn.fileno()), self.address 128 129 def getsockname(self): 130 return self.address 131 132 def __repr__(self): 133 return "VSocket(%s)" % self.sockfd 134 135 136 def connect_vsocket(sock_type=SOCK_STREAM, cid=VMADDR_CID_ANY, port=VMADDR_PORT_ANY): 137 log("connect_vsocket(%s)", (cid, port, sock_type)) 138 assert sock_type in (SOCK_STREAM, SOCK_DGRAM), "invalid socket type %s" % sock_type 139 #assert cid in (VMADDR_CID_ANY, VMADDR_CID_HYPERVISOR, VMADDR_CID_HOST), "invalid cid %s" % cid 140 assert port==VMADDR_PORT_ANY or (port>0 and port<65536) 141 log("socket(%i, %i, 0)", AF_VSOCK, sock_type) 142 cdef int sockfd = socket(AF_VSOCK, sock_type, 0) 143 log("socket(AF_VSOCK, SOCK_DGRAM, 0)=%i", sockfd) 144 if sockfd<0: 145 raise Exception("AF_VSOCK not supported") 146 147 cdef sockaddr_vm vmsock 148 memset(&vmsock, 0, sizeof(sockaddr_vm)) 149 vmsock.svm_family = AF_VSOCK 150 vmsock.svm_cid = cid 151 vmsock.svm_port = port 152 153 if connect(sockfd, <sockaddr *> &vmsock, sizeof(sockaddr_vm)): 154 raise Exception("failed to connect to server vsock %i:%i" % (cid, port)) 155 156 vsock = VSocket(sockfd) 157 return vsock -
xpra/net/vsock_server_test.py
1 # This file is part of Xpra. 2 # Copyright (C) 2016 Antoine Martin <antoine@devloop.org.uk> 3 # Xpra is released under the terms of the GNU GPL v2, or, at your option, any 4 # later version. See the file COPYING for details. 5 6 7 import sys 8 from xpra.net.vsock import bind_vsocket, CID_HOST, PORT_ANY #@UnresolvedImport 9 10 from xpra.log import Logger 11 log = Logger("network") 12 13 14 def main(args): 15 cid = CID_HOST 16 port = PORT_ANY 17 if len(args)>0: 18 cid = int(args[0]) 19 if len(args)>1: 20 port = int(args[1]) 21 #def server_vsocket(sock_type=SOCK_STREAM, cid=VMADDR_CID_HOST, port=VMADDR_PORT_ANY): 22 sock = bind_vsocket(cid=cid, port=port) 23 log("sock=%s", sock) 24 #import time 25 #time.sleep(10) 26 sock.listen(1) 27 log("listening") 28 while True: 29 connection, client_address = sock.accept() 30 log("new connection! %s", (connection, client_address)) 31 data = connection.recv(1024) 32 log("got data: %s" % data) 33 connection.send("hello") 34 return 0 35 36 if __name__ == "__main__": 37 sys.exit(main(sys.argv[1:]))