summaryrefslogtreecommitdiffstats
path: root/core/modules/remote-access/data/etc/X11/Xsetup.d/50-launch-vncserver
blob: bc4ab82c7e84a3bdca132ef4fa113a1615b80692 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/bin/sh sourced

[ -z "$SLX_KCL_SERVERS" ] && . /opt/openslx/config

[ "$DISPLAY" = :0 ] && [ -n "$SLX_REMOTE_VNC" ] && bash <<"BLUBB" &
	. /opt/openslx/config
	# TODO If we support multiple parallel sessions in the future, we need dedicated
	# ports for each session for both, the VNC and the RPC port.
	vnc_port="${SLX_REMOTE_VNC_PORT:-5900}"
	if ! [ "$vnc_port" -gt 0 ] || ! [ "$vnc_port" -lt 65535 ]; then
		vnc_port=5900
	fi
	srchost="$SLX_REMOTE_HOST_ACCESS"
	if [ -n "$srchost" ]; then
		# IPTABLES
		rule="/opt/openslx/iptables/rules.d/80-remote-access"
		if ! [ -e "$rule" ]; then
			(
				echo "#!/bin/sh"
				echo "iptables -A INPUT -s "'"'"$srchost"'"'" -p tcp --dport $vnc_port -j ACCEPT"
				echo "iptables -A INPUT -s "'"'"$srchost"'"'" -p tcp --dport 7551 -j ACCEPT"
				echo "iptables -A INPUT -p tcp --dport $vnc_port -j DROP"
				echo "iptables -A INPUT -p tcp --dport 7551 -j DROP"
			) > "$rule"
			chmod +x "$rule"
		fi
	fi
	#set -x
	#exec &> /tmp/fooooooooooooo
	# dd since busybox head doesn't know -c
	passwd="$( < /dev/urandom  tr -c -d 'a-zA-Z0-9#&/=()[]{}' | dd bs=8 count=1 status=none )"
	printf "%s" "$passwd" > "/tmp/vnc-passwd"
	(
		# Make a copy of xauth, so if the xserver restarts, we'll use the old one and fail to connect
		if [ -n "$XAUTHORITY" ]; then
			copy="$( mktemp )"
			cat "$XAUTHORITY" > "$copy"
			export XAUTHORITY="$copy"
			trap 'exit 1' INT TERM
			trap 'rm -f -- "$copy"' EXIT
		fi
		fails=0
		while true; do
			s="$( date +%s )"
			# skip keycode stuff fixes altgr for vmware
			x11vnc -rfbport "$vnc_port" -shared -forever -noxrecord -xkb -capslock -skip_keycodes 92,187,188 -remap DEAD=gac,U20AC-EuroSign -passwd "$passwd"
			e="$( date +%s )"
			d="$(( e - s ))"
			if [ "$d" -gt 5 ]; then
				fails=0
			else
				fails="$(( fails + 1 ))"
				[ "$fails" -gt 10 ] && break
				[ "$fails" -gt 3 ] && usleep 333333
			fi
		done
	) &> "/tmp/x11vnc-log-$$" &
	vncpid=$!
	# Delay this a bit until x11vnc is ready, and since we might potentially have had a race
	# with the ~poweron event, which would reset the password in the database.
	(
		url="http://${SLX_PXE_SERVER_IP}/slx-admin/api.php?do=remoteaccess"
		for _ in {1..20}; do
			sleep 1
			[ -e "/etc/cron.d/usage_stats" ] && break
		done
		[ -d "/proc/${vncpid}" ] || exit 1 # Something is wrong, bail
		curl -s -S -L --retry 4 --retry-connrefused --max-time 3 --retry-max-time 10 \
			--data-urlencode "password=$passwd" \
			--data-urlencode "vncport=$vnc_port" \
			"$url" > /dev/null
	) &
	gotone=false
	vmvnc=false
	idle=0
	stepcount=0
	# In case of stale entry
	# TODO: This sucks anyways performance-wise for VMware, maybe remove?
	iptables -t nat -D PREROUTING -p tcp --dport "$vnc_port" -j REDIRECT --to-ports 5901
	while [ -d "/proc/${vncpid}" ]; do
		sleep 5
		if netstat -tn | awk 'BEGIN{ e=1 } { if ($4 ~ /:590[0123]$/) e=0 } END{ exit e }'; then
			gotone=true
			idle=0
		else
			idle=$(( idle + 1 ))
		fi
		if $gotone; then
			# As soon as someone is connected, "blank" the screen by setting brightness to zero.
			# This doesn't seem to affect the framebuffer, luckily
			# Let's see how well this works in practice. :-(
			if (( stepcount == 0 )); then
				declare -a args
				args=()
				for o in $( xrandr | grep -E '^[A-Z0-9-]+ connected.*[0-9]+x[0-9]+' | awk '{print $1}' ); do
					args+=( "--output" "$o" "--brightness" "0" )
				done
				xrandr "${args[@]}"
			fi
			if (( stepcount++ > 3 )); then
				stepcount=0
			fi
		fi
		if $gotone && [ "$idle" -gt 120 ]; then # 120 * 5 = 10 mins
			kill "$vncpid"
			break
		fi
		# In case we access vmplayer via x11vnc; vmplayer won't leave the keymap alone >:(
		# TODO: Currently everything needs to be set to DE for this to work - X11 and
		# the OS in the VM.
		#setxkbmap -query | grep -q '^layout:\s*de$' || \ # NO, always reports 'de'
		setxkbmap de
		# Check if we should redirect to vmware
		if netstat -tnl | awk 'BEGIN{ e=1 } { if ($4 ~ /:5901$/) e=0 } END{ exit e }'; then
			#enable
			if ! $vmvnc; then
				killall x11vnc
				usleep 10000
				iptables -t nat -I PREROUTING 1 -p tcp --dport "$vnc_port" -j REDIRECT --to-ports 5901
			fi
			vmvnc=true
		else
			# disable
			if $vmvnc; then
				iptables -t nat -D PREROUTING -p tcp --dport "$vnc_port" -j REDIRECT --to-ports 5901
			fi
			vmvnc=false
		fi
	done
	systemctl restart lightdm
BLUBB