├── LICENSE.txt
├── README.md
├── conf
└── app.ini
├── linux_ip.go
├── main.go
├── middleware
└── jwt.go
├── pkg
├── app
│ └── response.go
├── logging
│ ├── file.go
│ └── log.go
└── setting
│ └── setting.go
├── qzcloud
├── definexml.go
├── paramstruct.go
├── qzcloud.go
├── qzcloudlib.go
├── setting.go
└── tool.go
├── routers
└── router.go
├── runtime
└── logs
│ ├── log20200711.log
│ ├── log20200717.log
│ ├── log20200806.log
│ ├── log20200807.log
│ ├── log20200809.log
│ └── log20200822.log
└── vnc
├── token
└── token.conf
└── utils
├── .eslintrc
└── websockify
├── .gitignore
├── .gitmodules
├── .travis.yml
├── CHANGES.txt
├── LICENSE.txt
├── MANIFEST.in
├── Makefile
├── README.md
├── Windows
├── Windows Service Readme.txt
└── noVNC Websocket Service Project
│ ├── Program.cs
│ ├── ProjectInstaller.Designer.cs
│ ├── ProjectInstaller.cs
│ ├── ProjectInstaller.resx
│ ├── Properties
│ └── AssemblyInfo.cs
│ ├── Service1.Designer.cs
│ ├── Service1.cs
│ ├── noVNC Websocket.csproj
│ └── noVNC Websocket.sln
├── include
├── VT100.js
├── keysym.js
├── util.js
├── websock.js
├── webutil.js
├── wsirc.js
└── wstelnet.js
├── other
├── Makefile
├── README.md
├── js
│ ├── README.md
│ ├── package.json
│ └── websockify.js
├── launch.sh
├── project.clj
├── websocket.c
├── websocket.h
├── websocket.rb
├── websockify.c
├── websockify.clj
├── websockify.rb
└── wswrap
├── rebind
├── rebind.c
├── run
├── setup.py
├── test-requirements.txt
├── tox.ini
├── websockify.py
├── websockify
├── __init__.py
├── auth_plugins.py
├── sysloghandler.py
├── token_plugins.py
├── websocket.py
├── websocketproxy.py
├── websocketserver.py
└── websockifyserver.py
├── wsirc.html
└── wstelnet.html
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
2 |
3 | 1. Definitions.
4 |
5 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
6 |
7 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
8 |
9 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
10 |
11 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
12 |
13 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
14 |
15 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
16 |
17 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
18 |
19 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
20 |
21 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
22 |
23 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
24 |
25 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
26 |
27 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
28 |
29 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
30 |
31 | You must give any other recipients of the Work or Derivative Works a copy of this License; and
32 | You must cause any modified files to carry prominent notices stating that You changed the files; and
33 | You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
34 | If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
35 |
36 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
37 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
38 |
39 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
40 |
41 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
42 |
43 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
44 |
45 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
46 |
47 | END OF TERMS AND CONDITIONS
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | "# qzkvm"
2 | "# qzkvm"
3 |
4 | 轻舟云kvm云主机管理系统,受控完全开源,主控也是开源的,可在官网下载主控
5 | 开源代码仅供学习使用,不可作为商业产品,
6 | 轻舟云官网[www.qzsystem.com](http://www.qzsystem.com)
7 | 轻舟云 kvm+hyper-v全方位虚拟化系统提供商,香港 美国 韩国 大陆 一手机房服务器提供
8 |
9 |
10 |
11 | License
12 | qzkvm is licensed under the [Apache Licence, Version 2.0.](https://www.apache.org/licenses/LICENSE-2.0.html)
--------------------------------------------------------------------------------
/conf/app.ini:
--------------------------------------------------------------------------------
1 | #debug or release
2 | RUN_MODE = debug
3 |
4 | [app]
5 | APIKEY = 123456
6 |
7 | [server]
8 | HTTP_PORT = 8000
9 | READ_TIMEOUT = 60
10 | WRITE_TIMEOUT = 60
11 |
--------------------------------------------------------------------------------
/linux_ip.go:
--------------------------------------------------------------------------------
1 | /*
2 | Package guest_set_user_password - sync host<->guest communication
3 |
4 | Example:
5 | { "execute": "guest-get-cloud-init", "arguments": {"cmd":"cloud_kvm 192.168.10.2 192.168.10.1 255.255.255.0 8.8.8.8 8.8.8.6 "} }
6 | */
7 | package main
8 |
9 | import (
10 | "bufio"
11 | "fmt"
12 | "html/template"
13 | "io/ioutil"
14 | "net"
15 | "os"
16 | "os/exec"
17 | "regexp"
18 | "strconv"
19 | "strings"
20 | )
21 | const (
22 | centos = "/etc/sysconfig/network-scripts/ifcfg-"
23 | ubuntu = "/etc/network/interfaces"
24 | ubuntu1 = "/etc/network/interfaces.d/cloud.cfg"
25 | ubuntu2 = "/etc/netplan/50-cloud-init.yaml"
26 | centos_network_conf = `TYPE=Ethernet
27 | BOOTPROTO=static
28 | HWADDR={{.mac}}
29 | IPADDR={{.ip}}
30 | NETMASK={{.mask}}
31 | GATEWAY={{.gateway}}
32 | DNS1={{.dns1}}
33 | DNS2={{.dns2}}
34 | DEFROUTE=yes
35 | IPV4_FAILURE_FATAL=yes
36 | IPV6INIT=no
37 | NAME={{.name}}
38 | DEVICE={{.name}}
39 | ONBOOT=yes`
40 | centos_network_conf1 = `TYPE=Ethernet
41 | BOOTPROTO=static
42 | IPADDR={{.ip1}}
43 | NETMASK={{.mask1}}
44 | DEFROUTE=yes
45 | IPV4_FAILURE_FATAL=yes
46 | NAME={{.name1}}
47 | DEVICE={{.name1}}
48 | ONBOOT=yes`
49 | ubuntu1_network_conf = `# This file describes the network interfaces available on your system
50 | # and how to activate them. For more information, see interfaces(5).
51 |
52 | source /etc/network/interfaces.d/*
53 | # The loopback network interface
54 | auto lo
55 | iface lo inet loopback
56 | `
57 | ubuntu2_network_conf1 = `auto {{.name}}
58 | iface {{.name}} inet static
59 | address {{.ip}}
60 | dns-nameservers {{.dns1}} {{.dns2}}
61 | netmask {{.mask}}
62 | gateway {{.gateway}}
63 | auto {{.name1}}
64 | iface {{.name1}} inet static
65 | address {{.ip1}}
66 | netmask {{.mask1}}`
67 | ubuntu2_network_conf2 = `network:
68 | renderer: networkd
69 | ethernets:
70 | {{.name}}:
71 | addresses: [{{.ip}}/{{.mask}}]
72 | gateway4: {{.gateway}}
73 | nameservers:
74 | addresses: [{{.dns1}}, {{.dns2}}]
75 | search: []
76 | optional: true
77 | {{.name1}}:
78 | addresses: [{{.ip1}}/{{.mask1}}]
79 | optional: true
80 | version: 2`
81 | )
82 |
83 | func main() {
84 | f, err := os.Open("/root/ip.txt")
85 | if err != nil {
86 | panic(err)
87 | }
88 | defer f.Close()
89 | ipInfo:=map[string]string{}
90 | scanner := bufio.NewScanner(f)
91 | os_,ver_:=OsAndVer()
92 | i:=0
93 | for scanner.Scan(){
94 | i+=1
95 | line:=scanner.Text() //以'\n'为结束符读入一行
96 | line = strings.Replace(line,"\n","",1)
97 | line = strings.Trim(line,"")
98 | //ip|gateway|mask|dns1|dns2|mac
99 | /**
100 | 192.168.10.1.2|192.168.10.1|255.255.255.0|8.8.8.8|8.8.8.6|mac
101 | 192.168.10.1.2|192.168.10.1|255.255.255.0|eth1
102 | hostname
103 | */
104 | ip:=strings.Split(line,"|")
105 | if i==1{
106 | ipInfo["ip"] = ip[0]
107 | ipInfo["gateway"] = ip[1]
108 | ipInfo["mask"] = ip[2]
109 | ipInfo["dns1"] = ip[3]
110 | ipInfo["dns2"] = ip[4]
111 | ipInfo["mac"] = ip[5]
112 | }else if(i==2){
113 | ipInfo["ip1"] = ip[0]
114 | ipInfo["gateway1"] = ip[1]
115 | ipInfo["mask1"] = ip[2]
116 | ipInfo["mac1"] = ip[3]
117 | }else{
118 | SetHostName(os_,line)
119 | }
120 |
121 | }
122 | SetIp(ipInfo,os_,ver_)
123 | }
124 | func SetIp(ipInfo map[string]string, os_, ver string) {
125 | tag := InterfacesTag(ipInfo["mac"])
126 | tag1 := InterfacesTag(ipInfo["mac1"])
127 | ipInfo["name"] = tag
128 | ipInfo["name1"] = tag1
129 | if strings.Index(strings.ToLower(os_),"centos")>-1 || strings.Index(strings.ToLower(os_),"fedora")>-1 {
130 | os.Remove(centos+"eth0")
131 | path := centos + tag
132 | os.Remove(path)
133 | file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644)
134 | if err != nil {
135 | panic(err)
136 | }
137 | defer file.Close()
138 | t := template.New("ipset")
139 | t.Parse(centos_network_conf)
140 | t.Execute(file, ipInfo)
141 |
142 | os.Remove(centos+"eth1")
143 | path1:= centos + tag1
144 | file1, err := os.OpenFile(path1, os.O_WRONLY|os.O_CREATE, 0644)
145 | if err != nil {
146 | //panic(err)
147 | }
148 | defer file1.Close()
149 | t = template.New("ipset1")
150 | t.Parse(centos_network_conf1)
151 | t.Execute(file1, ipInfo)
152 |
153 | var ver1 float64
154 | if ver != "" {
155 | ver1, _ = strconv.ParseFloat(ver, 10)
156 | }
157 | if strings.ToLower(os_) == "fedora" {
158 | cmd := exec.Command("bash", "-c", "nmcli con reload;nmcli con reload;nmcli con up "+tag+";systemctl restart network")
159 | cmd.Run()
160 | }
161 | if ver1 >= 7 && ver1<8{
162 | cmd := exec.Command("bash", "-c", "systemctl stop NetworkManager;systemctl disable NetworkManager")
163 | cmd.Run()
164 |
165 | com:=fmt.Sprintf("ifconfig %s down;ifconfig %s up;ifconfig %s down;ifconfig %s up",tag,tag,tag1,tag1)
166 | cmd = exec.Command("bash", "-c", com)
167 | cmd.Run()
168 |
169 | cmd = exec.Command("bash", "-c", "systemctl restart network")
170 | cmd.Run()
171 |
172 | }else if ver1 >= 8 && ver1<9{
173 | cmd := exec.Command("bash", "-c", "systemctl start NetworkManager;systemctl enable NetworkManager")
174 | cmd.Run()
175 |
176 | com:=fmt.Sprintf("ifdown %s;ifup %s;ifdown %s ;ifup %s up",tag,tag,tag1,tag1)
177 | cmd = exec.Command("bash", "-c", com)
178 | cmd.Run()
179 |
180 | cmd = exec.Command("bash", "-c", "systemctl restart NetworkManager")
181 | cmd.Run()
182 | } else {
183 | cmd := exec.Command("bash", "-c", "service NetworkManager stop;chkconfig NetworkManager off;service network restart")
184 | cmd.Run()
185 | }
186 | }
187 | if strings.ToLower(os_) == "ubuntu" || strings.ToLower(os_) == "debian" {
188 | if ver != "" {
189 | ver2, _ := strconv.ParseFloat(ver, 10)
190 | if ver2 <= 17 || strings.ToLower(os_) == "debian" {
191 | ioutil.WriteFile(ubuntu, []byte(ubuntu1_network_conf), 0666) //写入文件(字节数组)
192 | file, err := os.OpenFile(ubuntu1, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
193 | if err != nil {
194 | panic(err)
195 | }
196 | defer file.Close()
197 | t := template.New("ipset")
198 | t.Parse(ubuntu2_network_conf1)
199 | t.Execute(file, ipInfo)
200 |
201 | dns:=fmt.Sprintf(`echo nameserver %s > /etc/resolv.conf;echo nameserver %s >> /etc/resolv.conf`,ipInfo["dns1"],ipInfo["dns2"])
202 |
203 | cmd := exec.Command("bash", "-c", dns)
204 | cmd.Run()
205 | cmd = exec.Command("bash", "-c", "/etc/init.d/networking restart")
206 | cmd.Run()
207 | }
208 | if ver2 > 17 {
209 | cmd1 := exec.Command("bash", "-c", "sudo rm -r /etc/netplan/*.ymal")
210 | cmd1.Run()
211 | file, err := os.OpenFile(ubuntu2, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
212 | if err != nil {
213 | panic(err)
214 | }
215 | defer file.Close()
216 | t := template.New("ipset")
217 | t.Parse(ubuntu2_network_conf2)
218 | ipInfo["mask"] = MASK2CIDR(ipInfo["mask"])
219 | t.Execute(file, ipInfo)
220 | cmd := exec.Command("bash", "-c", "sudo netplan apply;sudo service network-manager stop")
221 | cmd.Run()
222 | }
223 | }
224 | }
225 | }
226 |
227 | func SetHostName(os_, newHostName string) {
228 | if strings.ToLower(os_) == "centos" {
229 | network_, _ := ioutil.ReadFile("/etc/sysconfig/network")
230 | osRegexp_ := regexp.MustCompile("[^_]HOSTNAME=\"?(.*)\"?")
231 | hostName := osRegexp_.FindSubmatch(network_)
232 | if len(hostName)>0{
233 | hostName_ := strings.Trim(string(hostName[1]), " ")
234 | hostName1_ := strings.Trim(string(hostName_), "\n")
235 | com1 := fmt.Sprintf(`sudo sed -i "s/%s/%s/g" /etc/sysconfig/network`, hostName1_, newHostName)
236 | com2 := fmt.Sprintf(`sudo sed -i "s/%s/%s/g" /etc/hosts`, hostName1_, newHostName)
237 | cmd1 := exec.Command("bash", "-c", com1+";"+com2+";hostname "+newHostName)
238 | cmd1.Run()
239 | }else{
240 | hostName_, _ := ioutil.ReadFile("/etc/hostname")
241 | hostName1_ := strings.Trim(string(hostName_), "\n")
242 | hostName1_ = strings.Trim(string(hostName1_), " ")
243 | com1 := fmt.Sprintf(`sed -i "s/%s/%s/g" /etc/hostname`, hostName1_, newHostName)
244 | com2 := fmt.Sprintf(`sed -i "s/%s/%s/g" /etc/hosts`, hostName1_, newHostName)
245 | cmd1 := exec.Command("bash", "-c", com1+";"+com2+";hostname "+newHostName)
246 | cmd1.Run()
247 | }
248 |
249 | } else if strings.ToLower(os_) == "debian" {
250 | hostName_, _ := ioutil.ReadFile("/etc/hostname")
251 | hostName1_ := strings.Trim(string(hostName_), "\n")
252 | hostName1_ = strings.Trim(string(hostName1_), " ")
253 | com1 := fmt.Sprintf(`sed -i "s/%s/%s/g" /etc/hostname`, hostName1_, newHostName)
254 | com2 := fmt.Sprintf(`sed -i "s/%s/%s/g" /etc/hosts`, hostName1_, newHostName)
255 | cmd1 := exec.Command("bash", "-c", com1+";"+com2+";hostname "+newHostName)
256 | cmd1.Run()
257 | }else if strings.ToLower(os_) == "fedora" {
258 | hostName_, _ := ioutil.ReadFile("/etc/hostname")
259 | hostName1_ := strings.Trim(string(hostName_), "\n")
260 | hostName1_ = strings.Trim(string(hostName1_), " ")
261 | if len(strings.Trim(hostName1_,""))<2{
262 | network_, _ := ioutil.ReadFile("/etc/sysconfig/network")
263 | osRegexp_ := regexp.MustCompile("[^_]HOSTNAME=\"?(.*)\"?")
264 | hostName := osRegexp_.FindSubmatch(network_)
265 | if len(hostName)>0{
266 | hostName_ := strings.Trim(string(hostName[1]), " ")
267 | hostName1_ = strings.Trim(string(hostName_), "\n")
268 | }
269 | }
270 | com1 := fmt.Sprintf(`sed -i "s/%s/%s/g" /etc/hostname`, hostName1_, newHostName)
271 | com2 := fmt.Sprintf(`sed -i "s/%s/%s/g" /etc/hosts`, hostName1_, newHostName)
272 | cmd1 := exec.Command("bash", "-c", com1+";"+com2+";hostname "+newHostName)
273 | cmd1.Run()
274 | } else {
275 | hostName_, _ := ioutil.ReadFile("/etc/hostname")
276 | hostName1_ := strings.Trim(string(hostName_), "\n")
277 | hostName1_ = strings.Trim(string(hostName1_), " ")
278 | com1 := fmt.Sprintf(`sudo sed -i "s/%s/%s/g" /etc/hostname`, hostName1_, newHostName)
279 | com2 := fmt.Sprintf(`sudo sed -i "s/%s/%s/g" /etc/hosts`, hostName1_, newHostName)
280 | cmd1 := exec.Command("bash", "-c", com1+";"+com2+";sudo hostname "+newHostName)
281 | cmd1.Run()
282 | }
283 | }
284 |
285 | func OsAndVer() (string, string) {
286 | var osStr, verStr string
287 | if IsFileExist("/etc/os-release") {
288 | release, _ := ioutil.ReadFile("/etc/os-release")
289 | osRegexp := regexp.MustCompile("[^_]ID=\"?(.*)\"?")
290 | os_ := osRegexp.FindSubmatch(release)
291 | verRegexp := regexp.MustCompile("VERSION_ID=\"(.*)\"")
292 | ver := verRegexp.FindSubmatch(release)
293 | if len(os_) > 0 {
294 | osStr = string(os_[1])
295 | }
296 | if len(ver) > 0 {
297 | verStr = string(ver[1])
298 | }
299 | } else if IsFileExist("/etc/centos-release") {
300 | release, _ := ioutil.ReadFile("/etc/centos-release")
301 | osRegexp := regexp.MustCompile("(CentOS)")
302 | releaseInfo := osRegexp.FindSubmatch(release)
303 | osStr = string(releaseInfo[1])
304 | } else {
305 | return "", ""
306 | }
307 | return strings.Trim(osStr,`"`),strings.Trim(verStr,`"`)
308 | }
309 |
310 | func InterfacesTag(name string) string {
311 | name = strings.Replace(name,"\n","",1)
312 | name = strings.Trim(name,"")
313 | tag, err := net.Interfaces()
314 | if err!=nil{
315 | return "eth0"
316 | }
317 | for k, t := range tag {
318 | if k==0{
319 | continue
320 | }
321 | if strings.EqualFold(t.HardwareAddr.String(),name){
322 | return t.Name
323 | }
324 | if strings.EqualFold(t.Name,name){
325 | return t.Name
326 | }
327 | }
328 | return "eth0"
329 | }
330 |
331 | func IsFileExist(filename string) bool {
332 | if _, err := os.Stat(filename); os.IsNotExist(err) {
333 | return false
334 | }
335 | return true
336 | }
337 |
338 | func MASK2CIDR(mask string) string {
339 | masks := strings.Split(mask, ".")
340 | mask1, _ := strconv.ParseInt(masks[0], 10, 64)
341 | mask2, _ := strconv.ParseInt(masks[1], 10, 64)
342 | mask3, _ := strconv.ParseInt(masks[2], 10, 64)
343 | mask4, _ := strconv.ParseInt(masks[3], 10, 64)
344 | ones, _ := net.IPv4Mask(byte(mask1), byte(mask2), byte(mask3), byte(mask4)).Size()
345 | return strconv.FormatInt(int64(ones), 10)
346 | }
347 |
348 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 | "qzkvm/src/pkg/logging"
7 | "qzkvm/src/pkg/setting"
8 | "qzkvm/src/qzcloud"
9 | "qzkvm/src/routers"
10 | )
11 |
12 | func init() {
13 | qzcloud.Setup()
14 | }
15 | func main() {
16 | router := routers.InitRouter()
17 |
18 | s := &http.Server{
19 | Addr: fmt.Sprintf(":%d", setting.HTTPPort),
20 | Handler: router,
21 | ReadTimeout: setting.ReadTimeout,
22 | WriteTimeout: setting.WriteTimeout,
23 | MaxHeaderBytes: 1 << 20,
24 | }
25 | logging.Info("[info] start http server listening %s", setting.HTTPPort)
26 | s.ListenAndServe()
27 | }
--------------------------------------------------------------------------------
/middleware/jwt.go:
--------------------------------------------------------------------------------
1 | package jwt
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 | "net/http"
6 | "qzkvm/src/pkg/setting"
7 | "qzkvm/src/qzcloud"
8 | "strings"
9 | )
10 |
11 | func JWT() gin.HandlerFunc {
12 | err:=qzcloud.ConnError
13 | return func(c *gin.Context) {
14 | var data interface{}
15 | if(strings.Trim(c.GetHeader("apikey"),"")!=""&&strings.Trim(c.GetHeader("apikey"),"")==strings.Trim(setting.APIKEY,"")){
16 | if err!=nil{
17 | c.JSON(http.StatusUnauthorized, gin.H{
18 | "code" : 0,
19 | "msg" :err.Error(),
20 | "data" :"",
21 | })
22 |
23 | c.Abort()
24 | return
25 | }
26 | c.Next()
27 | }else{
28 | c.JSON(http.StatusUnauthorized, gin.H{
29 | "code" : 0,
30 | "msg" :"apikey error",
31 | "data" : data,
32 | })
33 | c.Abort()
34 | return
35 | }
36 |
37 | }
38 | }
--------------------------------------------------------------------------------
/pkg/app/response.go:
--------------------------------------------------------------------------------
1 | package app
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 | "net/http"
6 | )
7 |
8 | type Gin struct {
9 | C *gin.Context
10 | }
11 |
12 | type Response struct {
13 | Code int `json:"code"`
14 | Msg string `json:"msg"`
15 | Data interface{} `json:"data"`
16 | }
17 |
18 | // Response setting gin.JSON
19 | func (g *Gin) Response(errCode int, msg string,data interface{}) {
20 | g.C.JSON(http.StatusOK, Response{
21 | Code: errCode,
22 | Msg: msg,
23 | Data: data,
24 | })
25 | return
26 | }
--------------------------------------------------------------------------------
/pkg/logging/file.go:
--------------------------------------------------------------------------------
1 | package logging
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "os"
7 | "time"
8 | )
9 |
10 | var (
11 | LogSavePath = "runtime/logs/"
12 | LogSaveName = "log"
13 | LogFileExt = "log"
14 | TimeFormat = "20060102"
15 | )
16 |
17 | func getLogFilePath() string {
18 | return fmt.Sprintf("%s", LogSavePath)
19 | }
20 |
21 | func getLogFileFullPath() string {
22 | prefixPath := getLogFilePath()
23 | suffixPath := fmt.Sprintf("%s%s.%s", LogSaveName, time.Now().Format(TimeFormat), LogFileExt)
24 |
25 | return fmt.Sprintf("%s%s", prefixPath, suffixPath)
26 | }
27 |
28 | func openLogFile(filePath string) *os.File {
29 | _, err := os.Stat(filePath)
30 | switch {
31 | case os.IsNotExist(err):
32 | mkDir(getLogFilePath())
33 | case os.IsPermission(err):
34 | log.Fatalf("Permission :%v", err)
35 | }
36 |
37 | handle, err := os.OpenFile(filePath, os.O_APPEND | os.O_CREATE | os.O_WRONLY, 0644)
38 | if err != nil {
39 | log.Fatalf("Fail to OpenFile :%v", err)
40 | }
41 |
42 | return handle
43 | }
44 |
45 | func mkDir(filePath string) {
46 | dir, _ := os.Getwd()
47 | err := os.MkdirAll(dir + "/" + getLogFilePath(), os.ModePerm)
48 | if err != nil {
49 | panic(err)
50 | }
51 | }
--------------------------------------------------------------------------------
/pkg/logging/log.go:
--------------------------------------------------------------------------------
1 | package logging
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "os"
7 | "path/filepath"
8 | "runtime"
9 | )
10 |
11 | type Level int
12 |
13 | var (
14 | F *os.File
15 |
16 | DefaultPrefix = ""
17 | DefaultCallerDepth = 2
18 |
19 | logger *log.Logger
20 | logPrefix = ""
21 | levelFlags = []string{"DEBUG", "INFO", "WARN", "ERROR", "FATAL"}
22 | )
23 |
24 | const (
25 | DEBUG Level = iota
26 | INFO
27 | WARNING
28 | ERROR
29 | FATAL
30 | )
31 |
32 | func init() {
33 | filePath := getLogFileFullPath()
34 | F = openLogFile(filePath)
35 |
36 | logger = log.New(F, DefaultPrefix, log.LstdFlags)
37 | }
38 |
39 | func Debug(v ...interface{}) {
40 | setPrefix(DEBUG)
41 | logger.Println(v)
42 | }
43 |
44 | func Info(v ...interface{}) {
45 | setPrefix(INFO)
46 | logger.Println(v)
47 | }
48 |
49 | func Warn(v ...interface{}) {
50 | setPrefix(WARNING)
51 | logger.Println(v)
52 | }
53 |
54 | func Error(v ...interface{}) {
55 | setPrefix(ERROR)
56 | logger.Println(v)
57 | }
58 |
59 | func Fatal(v ...interface{}) {
60 | setPrefix(FATAL)
61 | logger.Fatalln(v)
62 | }
63 |
64 | func setPrefix(level Level) {
65 | _, file, line, ok := runtime.Caller(DefaultCallerDepth)
66 | if ok {
67 | logPrefix = fmt.Sprintf("[%s][%s:%d]", levelFlags[level], filepath.Base(file), line)
68 | } else {
69 | logPrefix = fmt.Sprintf("[%s]", levelFlags[level])
70 | }
71 |
72 | logger.SetPrefix(logPrefix)
73 | }
--------------------------------------------------------------------------------
/pkg/setting/setting.go:
--------------------------------------------------------------------------------
1 | package setting
2 |
3 | import (
4 | "log"
5 | "time"
6 |
7 | "github.com/go-ini/ini"
8 | )
9 |
10 | var (
11 | Cfg *ini.File
12 |
13 | RunMode string
14 |
15 | HTTPPort int
16 | ReadTimeout time.Duration
17 | WriteTimeout time.Duration
18 | APIKEY string
19 |
20 | JwtSecret string
21 | )
22 |
23 | func init() {
24 | var err error
25 | Cfg, err = ini.Load("conf/app.ini")
26 | if err != nil {
27 | log.Fatal(2, "Fail to parse 'conf/app.ini': %v", err)
28 | }
29 |
30 | LoadBase()
31 | LoadServer()
32 | LoadApp()
33 | }
34 |
35 | func LoadBase() {
36 | RunMode = Cfg.Section("").Key("RUN_MODE").MustString("debug")
37 | APIKEY = Cfg.Section("app").Key("APIKEY").MustString("")
38 | }
39 |
40 | func LoadServer() {
41 | sec, err := Cfg.GetSection("server")
42 | if err != nil {
43 | log.Fatal(2, "Fail to get section 'server': %v", err)
44 | }
45 |
46 | RunMode = Cfg.Section("").Key("RUN_MODE").MustString("debug")
47 |
48 | HTTPPort = sec.Key("HTTP_PORT").MustInt(8000)
49 | ReadTimeout = time.Duration(sec.Key("READ_TIMEOUT").MustInt(60)) * time.Second
50 | WriteTimeout = time.Duration(sec.Key("WRITE_TIMEOUT").MustInt(60)) * time.Second
51 | }
52 |
53 | func LoadApp() {
54 | sec, err := Cfg.GetSection("app")
55 | if err != nil {
56 | log.Fatal(2, "Fail to get section 'app': %v", err)
57 | }
58 |
59 | JwtSecret = sec.Key("JWT_SECRET").MustString("!@)*#)!@U#@*!@!)")
60 | }
--------------------------------------------------------------------------------
/qzcloud/definexml.go:
--------------------------------------------------------------------------------
1 | package qzcloud
2 |
3 | func GetCreateDomainXml() string {
4 | xml := `
5 |
6 | {{.host_name}}
7 | {{.host_uuid}}
8 | {{.max_ram}}
9 | {{.min_ram}}
10 | {{.cpu}}
11 |
12 |
13 | hvm
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | destroy
26 | restart
27 | destroy
28 |
29 |
30 |
31 |
32 |
33 | /usr/libexec/qemu-kvm
34 |
35 |
36 |
37 |
38 |
39 |
40 | {{.os_read}}
41 | {{.os_write}}
42 | {{.os_iops}}
43 | {{.os_iops}}
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | {{.data_read}}
52 | {{.data_write}}
53 | {{.data_iops}}
54 | {{.data_iops}}
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 | {{.filterip|unescaped}}
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 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 | `
145 | return xml
146 | //cpu model host-model host-passthrough
147 | //限制ip策略模板
148 | //
149 | //
150 | //
151 | //
152 | //
153 | }
154 |
155 | func GetCreateVolumeXml() string {
156 | xmldesc := `
157 |
158 | {{.name}}
159 | {{.capacity}}
160 |
161 | {{.path}}/{{.name}}
162 |
163 |
164 | `
165 | //{{.allocation}} qcow2 raw
166 | return xmldesc
167 | }
168 |
169 | func GetCreatePoolXml() string {
170 | xmldesc := `
171 |
172 | {{.name}}
173 |
174 | {{.path}}
175 |
176 | `
177 | return xmldesc
178 | }
179 |
180 | func GetSnapshotXml()string{
181 | xml:=`
182 |
183 | {{.name}}
184 |
185 |
186 |
187 |
188 |
189 | `
190 | return xml
191 | }
192 |
--------------------------------------------------------------------------------
/qzcloud/paramstruct.go:
--------------------------------------------------------------------------------
1 | package qzcloud
2 |
3 | type CreateStruct struct {
4 | HostName string `json:"host_name" binding:"required"`
5 | HostUuid string `json:"host_uuid" `
6 | MaxRam string `json:"max_ram" binding:"required"`
7 | MinRam string `json:"min_ram" binding:"required"`
8 | Cpu string `json:"cpu" binding:"required"`
9 | CpuModel string `json:"cpu_model" binding:"required"`
10 | OsType string `json:"os_type" binding:"required"`
11 | Bandwidth string `json:"bandwidth" binding:"required"`
12 | Otherip string `json:"otherip" `
13 | IP string `json:"ip" binding:"required"`
14 | Gateway string `json:"gateway" binding:"required"`
15 | Netmask string `json:"netmask" binding:"required"`
16 | DNS1 string `json:"dns1" binding:"required"`
17 | DNS2 string `json:"dns2" binding:"required"`
18 | MAC string `json:"mac" binding:"required"`
19 | ReCreate string `json:"re_create" `
20 |
21 | IP1 string `json:"ip1" binding:"required"`
22 | Gateway1 string `json:"gateway1" `
23 | Netmask1 string `json:"netmask1" binding:"required"`
24 | MAC1 string `json:"mac1" binding:"required"`
25 | TemplatePath string `json:"template_path" binding:"required"`
26 | DataPath string `json:"data_path" binding:"required"`
27 | OsName string `json:"os_name" binding:"required"`
28 | HostData string `json:"host_data" binding:"required"`
29 |
30 | DataRead string `json:"data_read" binding:"required"`
31 | DataWrite string `json:"data_write" binding:"required"`
32 | OsRead string `json:"os_read" binding:"required"`
33 | OsWrite string `json:"os_write" binding:"required"`
34 | DataIops string `json:"data_iops" binding:"required"`
35 | OsIops string `json:"os_iops" binding:"required"`
36 |
37 | VncPort string `json:"vnc_port" binding:"required"`
38 | VncPassword string `json:"vnc_password" binding:"required"`
39 | Password string `json:"password" binding:"required"`
40 |
41 | }
42 |
43 | type RemoveStruct struct {
44 | HostName string `json:"host_name" binding:"required"`
45 | DataPath string `json:"data_path" binding:"required"`
46 | BackupPath string `json:"backup_path" binding:"required"`
47 | }
48 |
49 | type ReinstallStruct struct {
50 | HostName string `json:"host_name" binding:"required"`
51 | OsType string `json:"os_type" binding:"required"`
52 | IP string `json:"ip" binding:"required"`
53 | Gateway string `json:"gateway" binding:"required"`
54 | Netmask string `json:"netmask" binding:"required"`
55 | DNS1 string `json:"dns1" binding:"required"`
56 | DNS2 string `json:"dns2" binding:"required"`
57 | MAC string `json:"mac" binding:"required"`
58 |
59 | IP1 string `json:"ip1" binding:"required"`
60 | Gateway1 string `json:"gateway1"`
61 | Netmask1 string `json:"netmask1" binding:"required"`
62 | MAC1 string `json:"mac1" binding:"required"`
63 | Password string `json:"password" binding:"required"`
64 |
65 | TemplatePath string `json:"template_path" binding:"required"`
66 | DataPath string `json:"data_path" binding:"required"`
67 | OsName string `json:"os_name" binding:"required"`
68 |
69 | }
70 |
71 | type UpdateSystemPasswordStruct struct {
72 | HostName string `json:"host_name" binding:"required"`
73 | Username string `json:"username" binding:"required"`
74 | Password string `json:"password" binding:"required"`
75 | }
76 |
77 | type CreateSnapshotStruct struct {
78 | HostName string `json:"host_name" binding:"required"`
79 | Name string `json:"name" binding:"required"`
80 | }
81 |
82 | type RestoreSnapshotStruct struct {
83 | HostName string `json:"host_name" binding:"required"`
84 | Name string `json:"name" binding:"required"`
85 | }
86 |
87 | type RemoveSnapshotStruct struct {
88 | HostName string `json:"host_name" binding:"required"`
89 | Name string `json:"name" binding:"required"`
90 | }
91 |
92 | type UpdateIPStruct struct {
93 | HostName string `json:"host_name" binding:"required"`
94 | Otherip string `json:"otherip" `
95 | IP string `json:"ip" binding:"required"`
96 | }
97 |
98 | type RemoveNWFilterStruct struct {
99 | HostName string `json:"host_name" binding:"required"`
100 | Name string `json:"name" binding:"required"`
101 | }
102 |
103 | type AddNWFilterStruct struct {
104 | HostName string `json:"host_name" binding:"required"`
105 | Name string `json:"name" binding:"required"`
106 | Protocol string `json:"protocol" binding:"required"`
107 | Action string `json:"action" binding:"required"`
108 | Direction string `json:"direction" binding:"required"`
109 | Priority string `json:"priority" binding:"required"`
110 | Port string `json:"port" binding:"required"`
111 | StartIp string `json:"start_ip" binding:"required"`
112 | EndIp string `json:"end_ip"`
113 | }
114 |
115 | type UpdateIsoStruct struct {
116 | HostName string `json:"host_name" binding:"required"`
117 | IsoPath string `json:"iso_path" `
118 | }
119 |
120 | type BackupStruct struct {
121 | HostName string `json:"host_name" binding:"required"`
122 | BackupPath string `json:"backup_path" binding:"required"`
123 | Name string `json:"name" binding:"required"`
124 | }
125 |
126 | type DomainMemoryStats struct{
127 | Actual uint64 //是启动虚机时设置的最大内存
128 | Swap_out uint64
129 | Swap_in uint64
130 | Major_fault uint64
131 | Minor_fault uint64
132 | Unused uint64 //虚拟机未被使用内存
133 | Available uint64 //虚拟机内存
134 | Last_update uint64
135 | Rss uint64 //在宿主机上所占用的内存
136 | }
137 |
138 | type MonitorStruct struct {
139 | HostName string `json:"host_name" binding:"required"`
140 | NetworkName string `json:"network_name" binding:"required"`
141 | DiskDev string `json:"disk_dev" `
142 | }
143 |
144 | type BootOrderStruct struct {
145 | HostName string `json:"host_name" binding:"required"`
146 | NetworkName string `json:"network_name" binding:"required"`
147 | DiskDev string `json:"disk_dev" `
148 | }
149 |
150 | type HostNameStruct struct {
151 | HostName string `json:"host_name" binding:"required"`
152 | }
153 |
154 | type SetStatusStruct struct {
155 | HostName string `json:"host_name" binding:"required"`
156 | State string `json:"state" binding:"required"`
157 | }
158 |
159 | type GetIsoListStruct struct {
160 | IsoPath string `json:"iso_path" binding:"required"`
161 | }
162 |
163 |
164 |
--------------------------------------------------------------------------------
/qzcloud/setting.go:
--------------------------------------------------------------------------------
1 | package qzcloud
2 |
3 | import "github.com/libvirt/libvirt-go"
4 |
5 | var Conn *libvirt.Connect
6 | var ConnError error
7 | func Setup(){
8 | Conn, ConnError = libvirt.NewConnect("qemu:///system")
9 | }
10 |
--------------------------------------------------------------------------------
/qzcloud/tool.go:
--------------------------------------------------------------------------------
1 | package qzcloud
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | uuid "github.com/satori/go.uuid"
7 | "html/template"
8 | "io"
9 | "os"
10 | "os/exec"
11 | "strconv"
12 | "strings"
13 | )
14 |
15 | func isDirExits(path string) bool {
16 | _, err := os.Stat(path)
17 | if err != nil {
18 | return os.IsExist(err)
19 | }
20 | return true
21 | }
22 |
23 | func mkdir(path string) error {
24 | er := isDirExits(path)
25 | if er==false {
26 | err := os.MkdirAll(path, os.ModePerm)
27 | return err
28 | }
29 | return nil
30 | }
31 | func RemoveFile(path string)error{
32 | path1:=strings.ReplaceAll(path,"\\","/")
33 | path1 = strings.ReplaceAll(path1,"//","/")
34 | path1 = strings.ReplaceAll(path1,"//","/")
35 |
36 | if path1 =="/"{
37 | return nil
38 | }
39 | if path1 ==""{
40 | return nil
41 | }
42 | pathSlice:=strings.Split(path1,"/")
43 | if len(pathSlice)<2{
44 | return nil
45 | }
46 | if path1 =="/root"{
47 | return nil
48 | }
49 | if path1 =="/root/"{
50 | return nil
51 | }
52 |
53 | err:=os.RemoveAll(path)
54 | return err
55 | }
56 |
57 | func Absum(param ...string)string{
58 | var count int64 =1
59 | for _,val:=range param {
60 | intval,err:=strconv.ParseInt(val,10,64)
61 | if err!=nil{
62 | intval=0
63 | }
64 | count=count*intval
65 | }
66 |
67 | d:=strconv.FormatInt(count,10)
68 | return d
69 | }
70 |
71 | func CopyFile(dstName, srcName string) (written int64, err error) {
72 | src, err := os.Open(srcName)
73 | if err != nil {
74 | return
75 | }
76 | defer src.Close()
77 | dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0777)
78 | if err != nil {
79 | return
80 | }
81 | defer dst.Close()
82 | return io.Copy(dst, src)
83 | }
84 |
85 | func unescaped (content string) interface{} { return template.HTML(content) }
86 |
87 | func formatFloat(value float64) float64 {
88 | value,_=strconv.ParseFloat(fmt.Sprintf("%.2f",value),64)
89 | return value
90 |
91 | }
92 |
93 | func GetUUIDBuild() string {
94 | u, _ := uuid.NewV4()
95 | return u.String()
96 | }
97 |
98 | func Exec_shell(shellstring string) (string, error) {
99 | //函数返回一个*Cmd,用于使用给出的参数执行name指定的程序
100 | cmd := exec.Command("/bin/bash", "-c", shellstring)
101 |
102 | //读取io.Writer类型的cmd.Stdout,再通过bytes.Buffer(缓冲byte类型的缓冲器)将byte类型转化为string类型(out.String():这是bytes类型提供的接口)
103 | var out bytes.Buffer
104 | cmd.Stdout = &out
105 |
106 | //Run执行c包含的命令,并阻塞直到完成。 这里stdout被取出,cmd.Wait()无法正确获取stdin,stdout,stderr,则阻塞在那了
107 | err := cmd.Run()
108 |
109 | return out.String(), err
110 | }
--------------------------------------------------------------------------------
/routers/router.go:
--------------------------------------------------------------------------------
1 | package routers
2 |
3 | import (
4 | "github.com/gin-gonic/gin"
5 | jwt "qzkvm/src/middleware"
6 | setting2 "qzkvm/src/pkg/setting"
7 | "qzkvm/src/qzcloud"
8 | )
9 |
10 | func InitRouter() *gin.Engine {
11 | r := gin.New()
12 |
13 | r.Use(gin.Logger())
14 |
15 | r.Use(gin.Recovery())
16 |
17 | gin.SetMode(setting2.RunMode)
18 | r.Use(jwt.JWT())
19 | r.GET("/test", func(c *gin.Context) {
20 | c.JSON(200, gin.H{
21 | "message": "test",
22 | })
23 | })
24 | apiv1:=r.Group("/api/v1")
25 | apiv1.POST("/create_kvm",qzcloud.CreateKvm)
26 | apiv1.POST("/update_kvm",qzcloud.UpdateKvm)
27 | apiv1.POST("/remove_kvm",qzcloud.RemoveKvm)
28 | apiv1.POST("/reinstall_kvm",qzcloud.ReinstallKvm)
29 | apiv1.POST("/update_system_password",qzcloud.UpdateSystemPassword)
30 | apiv1.POST("/create_snapshot_kvm",qzcloud.CreateSnapshotkvm)
31 | apiv1.POST("/restore_snapshot_kvm",qzcloud.RestoreSnapshotKvm)
32 | apiv1.POST("/remove_snapshot_kvm",qzcloud.RemoveSnapshotKvm)
33 | apiv1.POST("/update_ip_kvm",qzcloud.UpdateIPKvm)
34 | apiv1.POST("/add_firewall_kvm",qzcloud.AddNWFilterKvm)
35 | apiv1.POST("/remove_firewall_kvm",qzcloud.RemoveNWFilterKvm)
36 | apiv1.POST("/update_iso_kvm",qzcloud.UpdateIsoKvm)
37 | apiv1.POST("/get_screenshot_kvm",qzcloud.GetScreenshotKvm)
38 | apiv1.POST("/create_backup_kvm",qzcloud.CreateBackupKvm)
39 | apiv1.POST("/restore_backup_kvm",qzcloud.RestoreBackupKvm)
40 | apiv1.POST("/remove_backup_kvm",qzcloud.RemoveBackupKvm)
41 | apiv1.POST("/monitor_kvm",qzcloud.MonitorKvm)
42 | apiv1.POST("/boot_order",qzcloud.BootOrderKvm)
43 | apiv1.POST("/get_network_flow_kvm",qzcloud.GetNetworkFlowKvm)
44 | apiv1.POST("/get_status_kvm",qzcloud.GetStatusKvm)
45 | apiv1.POST("/set_status_kvm",qzcloud.SetStatusKvm)
46 | apiv1.POST("/get_isolist_kvm",qzcloud.GetIsoListKvm)
47 | apiv1.POST("/set_network_state",qzcloud.NetworkCloseOrOpenKvm)
48 | apiv1.POST("/count_flow_kvm",qzcloud.CountFlowKvm)
49 |
50 | return r
51 | }
--------------------------------------------------------------------------------
/runtime/logs/log20200711.log:
--------------------------------------------------------------------------------
1 | [INFO][main.go:25]2020/07/11 15:18:57 [[info] start http server listening %s 8000]
2 | [INFO][main.go:25]2020/07/11 15:24:04 [[info] start http server listening %s 8000]
3 | [INFO][main.go:25]2020/07/11 15:41:56 [[info] start http server listening %s 8000]
4 | [INFO][main.go:25]2020/07/11 15:46:50 [[info] start http server listening %s 8000]
5 |
--------------------------------------------------------------------------------
/runtime/logs/log20200717.log:
--------------------------------------------------------------------------------
1 | [INFO][main.go:25]2020/07/17 21:42:51 [[info] start http server listening %s 8000]
2 | [INFO][main.go:25]2020/07/17 21:43:19 [[info] start http server listening %s 8000]
3 |
--------------------------------------------------------------------------------
/runtime/logs/log20200806.log:
--------------------------------------------------------------------------------
1 | [INFO][main.go:25]2020/08/06 20:01:44 [[info] start http server listening %s 8000]
2 |
--------------------------------------------------------------------------------
/runtime/logs/log20200807.log:
--------------------------------------------------------------------------------
1 | [INFO][main.go:25]2020/08/07 12:56:30 [[info] start http server listening %s 8000]
2 | [INFO][main.go:25]2020/08/07 12:56:39 [[info] start http server listening %s 8000]
3 |
--------------------------------------------------------------------------------
/runtime/logs/log20200809.log:
--------------------------------------------------------------------------------
1 | [INFO][main.go:25]2020/08/09 00:05:34 [[info] start http server listening %s 8000]
2 | [INFO][main.go:25]2020/08/09 00:05:48 [[info] start http server listening %s 8000]
3 | [INFO][main.go:25]2020/08/09 00:09:48 [[info] start http server listening %s 8000]
4 | [INFO][main.go:25]2020/08/09 00:15:27 [[info] start http server listening %s 8000]
5 | [INFO][main.go:25]2020/08/09 17:59:10 [[info] start http server listening %s 8000]
6 | [INFO][main.go:25]2020/08/09 17:59:27 [[info] start http server listening %s 8000]
7 | [INFO][main.go:25]2020/08/09 18:06:21 [[info] start http server listening %s 8000]
8 | [INFO][main.go:25]2020/08/09 18:19:34 [[info] start http server listening %s 8000]
9 | [INFO][main.go:25]2020/08/09 18:25:44 [[info] start http server listening %s 8000]
10 | [INFO][main.go:25]2020/08/09 18:32:59 [[info] start http server listening %s 8000]
11 | [INFO][main.go:25]2020/08/09 18:40:30 [[info] start http server listening %s 8000]
12 | [INFO][main.go:25]2020/08/09 18:44:16 [[info] start http server listening %s 8000]
13 | [INFO][main.go:25]2020/08/09 18:53:47 [[info] start http server listening %s 8000]
14 | [INFO][main.go:25]2020/08/09 18:56:10 [[info] start http server listening %s 8000]
15 | [INFO][main.go:25]2020/08/09 19:00:01 [[info] start http server listening %s 8000]
16 | [INFO][main.go:25]2020/08/09 19:03:30 [[info] start http server listening %s 8000]
17 |
--------------------------------------------------------------------------------
/runtime/logs/log20200822.log:
--------------------------------------------------------------------------------
1 | [INFO][main.go:25]2020/08/22 10:11:54 [[info] start http server listening %s 8000]
2 |
--------------------------------------------------------------------------------
/vnc/token/token.conf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qzsystem/qzkvm/1441d7825e0f80470f65db6bbac2ce0d43192744/vnc/token/token.conf
--------------------------------------------------------------------------------
/vnc/utils/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "node": true
4 | },
5 | "rules": {
6 | "no-console": 0
7 | }
8 | }
--------------------------------------------------------------------------------
/vnc/utils/websockify/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.o
3 | *.so
4 | other/.lein-deps-sum
5 | other/classes
6 | other/lib
7 | other/js/node_modules
8 | .project
9 | .pydevproject
10 | target.cfg
11 | target.cfg.d
12 | .tox
13 | *.egg-info
14 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/.gitmodules:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qzsystem/qzkvm/1441d7825e0f80470f65db6bbac2ce0d43192744/vnc/utils/websockify/.gitmodules
--------------------------------------------------------------------------------
/vnc/utils/websockify/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | python:
3 | - 2.6
4 | - 2.7
5 | - 3.3
6 | - 3.4
7 |
8 | install:
9 | - pip install 'setuptools>=18.5,<=39.0.0'
10 | - pip install -r test-requirements.txt
11 |
12 | script: python setup.py nosetests --verbosity=3
13 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/CHANGES.txt:
--------------------------------------------------------------------------------
1 | Changes
2 | =======
3 |
4 | 0.8.0
5 | -----
6 |
7 | * Make websockify properly terminate children on SIGTERM (#226)
8 | * Remove logging in signal handlers (this can cause Python to hang under certain conditions) (#219)
9 | * Make it easier to log to a file (#205)
10 | * Add support for IPv6 addresses in tokens in the TokenFile token plugins (#197)
11 | * Improve auth plugin framework to enable better support for HTTP auth (#194, #201)
12 | * Fix bug in JSONTokenAPI token plugin (#192)
13 | * Fix a missing variable in the exception handler (#178)
14 |
15 | 0.7.0
16 | -----
17 |
18 | * Python 3 support fixes (#140, #155, #159)
19 | * Generic token-parsing plugins support (#162)
20 | * Generic authentication plugins support (#172)
21 | * Fixed frame corruption on big-endian systems (#161)
22 | * Support heartbeats (via PING) and automatic responses to PONG (#169)
23 | * Automatically reject unmasked client frames by default (strict mode) (#174)
24 | * Automatically restart interrupted select calls (#175)
25 | * Make 'run' respect environment settings (including virtualenv) (#176)
26 |
27 | 0.6.1 - May 11, 2015
28 | --------------------
29 |
30 | * **PATCH RELEASE**: Fixes a bug causing file_only to not be passed properly
31 |
32 | 0.6.0 - Feb 18, 2014
33 | --------------------
34 |
35 | * **NOTE** : 0.6.0 will break existing code that sub-classes WebsocketProxy
36 | * Refactor to use standard SocketServer RequestHandler design
37 | * Fix zombie process bug on certain systems when using multiprocessing
38 | * Add better unit tests
39 | * Log information via python `logging` module
40 |
41 | 0.5.1 - Jun 27, 2013
42 | --------------------
43 |
44 | * use upstream einaros/ws (>=0.4.27) with websockify.js
45 | * file_only and no_parent security options for WSRequestHandler
46 | * Update build of web-socket-js (c0855c6cae)
47 | * add include/web-socket-js-project submodule to gimite/web-socket-js
48 | for DSFG compliance.
49 | * drop Hixie protocol support
50 |
51 | 0.4.1 - Mar 12, 2013
52 | --------------------
53 |
54 | * ***NOTE*** : 0.5.0 will drop Hixie protocol support
55 | * add include/ directory and remove some dev files from source
56 | distribution.
57 |
58 | 0.4.0 - Mar 12, 2013
59 | --------------------
60 |
61 | * ***NOTE*** : 0.5.0 will drop Hixie protocol support
62 | * use Buffer base64 support in Node.js implementation
63 |
64 | 0.3.0 - Jan 15, 2013
65 | --------------------
66 |
67 | * refactor into modules: websocket, websocketproxy
68 | * switch to web-socket-js that uses IETF 6455
69 | * change to MPL 2.0 license for include/*.js
70 | * fix session recording
71 |
72 | 0.2.1 - Oct 15, 2012
73 | --------------------
74 |
75 | * re-released with updated version number
76 |
77 | 0.2.0 - Sep 17, 2012
78 | --------------------
79 |
80 | * Binary data support in websock.js
81 | * Target config file/dir and multiple targets with token selector
82 | * IPv6 fixes
83 | * SSL target support
84 | * Proxy to/from unix socket
85 |
86 |
87 | 0.1.0 - May 11, 2012
88 | --------------------
89 |
90 | * Initial versioned release.
91 |
92 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/LICENSE.txt:
--------------------------------------------------------------------------------
1 | websockify is licensed under the LGPL version 3 (see docs/LICENSE.GPL-3 and
2 | docs/LICENSE.LGPL-3) with the following exceptions:
3 |
4 | include/websock.js : MPL 2.0
5 |
6 | include/des.js : Various BSD style licenses
7 |
8 | include/web-socket-js/ : New BSD license (3-clause). Source code at
9 | https://github.com/gimite/web-socket-js
10 |
11 | other/kumina.c : Simplified BSD license (2 clause).
12 | Original source at
13 | https://github.com/kumina/wsproxy
14 |
15 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include CHANGES.txt README.md LICENSE.txt
2 | graft include
3 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/Makefile:
--------------------------------------------------------------------------------
1 | TARGETS=rebind.so
2 | CFLAGS += -fPIC
3 |
4 | all: $(TARGETS)
5 |
6 | rebind.so: rebind.o
7 | $(CC) $(LDFLAGS) $^ -shared -fPIC -ldl -o $@
8 |
9 | clean:
10 | rm -f rebind.o rebind.so
11 |
12 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/README.md:
--------------------------------------------------------------------------------
1 | ## websockify: WebSockets support for any application/server
2 |
3 | websockify was formerly named wsproxy and was part of the
4 | [noVNC](https://github.com/kanaka/noVNC) project.
5 |
6 | At the most basic level, websockify just translates WebSockets traffic
7 | to normal socket traffic. Websockify accepts the WebSockets handshake,
8 | parses it, and then begins forwarding traffic between the client and
9 | the target in both directions.
10 |
11 | ### News/help/contact
12 |
13 | Notable commits, announcements and news are posted to
14 | @noVNC
15 |
16 | If you are a websockify developer/integrator/user (or want to be)
17 | please join the noVNC/websockify
19 | discussion group
20 |
21 | Bugs and feature requests can be submitted via [github
22 | issues](https://github.com/kanaka/websockify/issues).
23 |
24 | If you want to show appreciation for websockify you could donate to a great
25 | non-profits such as: [Compassion
26 | International](http://www.compassion.com/), [SIL](http://www.sil.org),
27 | [Habitat for Humanity](http://www.habitat.org), [Electronic Frontier
28 | Foundation](https://www.eff.org/), [Against Malaria
29 | Foundation](http://www.againstmalaria.com/), [Nothing But
30 | Nets](http://www.nothingbutnets.net/), etc. Please tweet @noVNC if you do.
32 |
33 | ### WebSockets binary data
34 |
35 | Starting with websockify 0.5.0, only the HyBi / IETF
36 | 6455 WebSocket protocol is supported. There is no support for the older
37 | Base64 encoded data format.
38 |
39 |
40 | ### Encrypted WebSocket connections (wss://)
41 |
42 | To encrypt the traffic using the WebSocket 'wss://' URI scheme you need to
43 | generate a certificate and key for Websockify to load. By default, Websockify
44 | loads a certificate file name `self.pem` but the `--cert=CERT` and `--key=KEY`
45 | options can override the file name. You can generate a self-signed certificate
46 | using openssl. When asked for the common name, use the hostname of the server
47 | where the proxy will be running:
48 |
49 | ```
50 | openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem
51 | ```
52 |
53 | For a self-signed certificate to work, you need to make your client/browser
54 | understand it. You can do this by installing it as accepted certificate, or by
55 | using that same certificate for a HTTPS connection to which you navigate first
56 | and approve. Browsers generally don't give you the "trust certificate?" prompt
57 | by opening a WSS socket with invalid certificate, hence you need to have it
58 | acccept it by either of those two methods.
59 |
60 | If you have a commercial/valid SSL certificate with one ore more intermediate
61 | certificates, concat them into one file, server certificate first, then the
62 | intermediate(s) from the CA, etc. Point to this file with the `--cert` option
63 | and then also to the key with `--key`. Finally, use `--ssl-only` as needed.
64 |
65 |
66 | ### Websock Javascript library
67 |
68 |
69 | The `include/websock.js` Javascript library library provides a Websock
70 | object that is similar to the standard WebSocket object but Websock
71 | enables communication with raw TCP sockets (i.e. the binary stream)
72 | via websockify.
73 |
74 | Websock has built-in receive queue buffering; the message event
75 | does not contain actual data but is simply a notification that
76 | there is new data available. Several rQ* methods are available to
77 | read binary data off of the receive queue.
78 |
79 | The Websock API is documented on the [websock.js API wiki page](https://github.com/kanaka/websockify/wiki/websock.js)
80 |
81 | See the "Wrap a Program" section below for an example of using Websock
82 | and websockify as a browser telnet client (`wstelnet.html`).
83 |
84 |
85 | ### Additional websockify features
86 |
87 | These are not necessary for the basic operation.
88 |
89 | * Daemonizing: When the `-D` option is specified, websockify runs
90 | in the background as a daemon process.
91 |
92 | * SSL (the wss:// WebSockets URI): This is detected automatically by
93 | websockify by sniffing the first byte sent from the client and then
94 | wrapping the socket if the data starts with '\x16' or '\x80'
95 | (indicating SSL).
96 |
97 | * Session recording: This feature that allows recording of the traffic
98 | sent and received from the client to a file using the `--record`
99 | option.
100 |
101 | * Mini-webserver: websockify can detect and respond to normal web
102 | requests on the same port as the WebSockets proxy. This functionality
103 | is activated with the `--web DIR` option where DIR is the root of the
104 | web directory to serve.
105 |
106 | * Wrap a program: see the "Wrap a Program" section below.
107 |
108 | * Log files: websockify can save all logging information in a file.
109 | This functionality is activated with the `--log-file FILE` option
110 | where FILE is the file where the logs should be saved.
111 |
112 | * Authentication plugins: websockify can demand authentication for
113 | websocket connections and, if you use `--web-auth`, also for normal
114 | web requests. This functionality is activated with the
115 | `--auth-plugin CLASS` and `--auth-source ARG` options, where CLASS is
116 | usually one from auth_plugins.py and ARG is the plugin's configuration.
117 |
118 | * Token plugins: a single instance of websockify can connect clients to
119 | multiple different pre-configured targets, depending on the token sent
120 | by the client using the `token` URL parameter, or the hostname used to
121 | reach websockify, if you use `--host-token`. This functionality is
122 | activated with the `--token-plugin CLASS` and `--token-source ARG`
123 | options, where CLASS is usually one from token_plugins.py and ARG is
124 | the plugin's configuration.
125 |
126 | ### Implementations of websockify
127 |
128 | The primary implementation of websockify is in python. There are
129 | several alternate implementations in other languages (C, Node.js,
130 | Clojure, Ruby) in the `other/` subdirectory (with varying levels of
131 | functionality).
132 |
133 | In addition there are several other external projects that implement
134 | the websockify "protocol". See the alternate implementation [Feature
135 | Matrix](https://github.com/kanaka/websockify/wiki/Feature_Matrix) for
136 | more information.
137 |
138 |
139 | ### Wrap a Program
140 |
141 | In addition to proxying from a source address to a target address
142 | (which may be on a different system), websockify has the ability to
143 | launch a program on the local system and proxy WebSockets traffic to
144 | a normal TCP port owned/bound by the program.
145 |
146 | The is accomplished with a small LD_PRELOAD library (`rebind.so`)
147 | which intercepts bind() system calls by the program. The specified
148 | port is moved to a new localhost/loopback free high port. websockify
149 | then proxies WebSockets traffic directed to the original port to the
150 | new (moved) port of the program.
151 |
152 | The program wrap mode is invoked by replacing the target with `--`
153 | followed by the program command line to wrap.
154 |
155 | `./run 2023 -- PROGRAM ARGS`
156 |
157 | The `--wrap-mode` option can be used to indicate what action to take
158 | when the wrapped program exits or daemonizes.
159 |
160 | Here is an example of using websockify to wrap the vncserver command
161 | (which backgrounds itself) for use with
162 | [noVNC](https://github.com/kanaka/noVNC):
163 |
164 | `./run 5901 --wrap-mode=ignore -- vncserver -geometry 1024x768 :1`
165 |
166 | Here is an example of wrapping telnetd (from krb5-telnetd). telnetd
167 | exits after the connection closes so the wrap mode is set to respawn
168 | the command:
169 |
170 | `sudo ./run 2023 --wrap-mode=respawn -- telnetd -debug 2023`
171 |
172 | The `wstelnet.html` page demonstrates a simple WebSockets based telnet
173 | client (use 'localhost' and '2023' for the host and port
174 | respectively).
175 |
176 |
177 | ### Installing the Python implementation of websockify
178 |
179 | Download one of the releases or the latest development version, extract
180 | it and run `python setup.py install` as root in the directory where you
181 | extracted the files. Normally, this will also install numpy for better
182 | performance, if you don't have it installed already. However, numpy is
183 | optional. If you don't want to install numpy or if you can't compile it,
184 | you can edit setup.py and remove the `install_requires=['numpy'],` line
185 | before running `python setup.py install`.
186 |
187 | Afterwards, websockify should be available in your path. Run
188 | `websockify --help` to confirm it's installed correctly.
189 |
190 |
191 | ### Building the Python ssl module (for python 2.5 and older)
192 |
193 | * Install the build dependencies. On Ubuntu use this command:
194 |
195 | `sudo aptitude install python-dev bluetooth-dev`
196 |
197 | * At the top level of the websockify repostory, download, build and
198 | symlink the ssl module:
199 |
200 | `wget --no-check-certificate http://pypi.python.org/packages/source/s/ssl/ssl-1.15.tar.gz`
201 |
202 | `tar xvzf ssl-1.15.tar.gz`
203 |
204 | `cd ssl-1.15`
205 |
206 | `make`
207 |
208 | `cd ../`
209 |
210 | `ln -sf ssl-1.15/build/lib.linux-*/ssl ssl`
211 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/Windows/Windows Service Readme.txt:
--------------------------------------------------------------------------------
1 | -----------------------------------
2 | Windows noVNC Websockify Service
3 | -----------------------------------
4 |
5 | The "noVNC Websocket Service.exe" file is a windows service wrapper created with Visual Studio 2010 to create a windows service to start stop the noVNC Websocket Server. All files used to create the wrapper can be found in 'noVNC Websocket Service Project' folder.
6 |
7 | To download the precompiled executables please grab the zip in the downloads section of websockify project:
8 | https://github.com/kanaka/websockify
9 |
10 | ---------------------------
11 | Installation
12 | ---------------------------
13 |
14 | 1. This service requires websockify.exe be in the same directory. Instructions on how to compile websockify python script as a windows executable can be found here:
15 | https://github.com/kanaka/websockify/wiki/Compiling-Websockify-as-Windows-Executable
16 |
17 | 2.To add this service to a Windows PC you need to run the commandline as administrator and then run this line:
18 |
19 | sc create "noVNC Websocket Server" binPath= "PATH TO noVNC eg C:\noVNC\utils\Windows\Websocket Service.exe" DisplayName= "noVNC Websocket Server"
20 |
21 | 3 .Once this is run you will be able to access the service via Control Panel > Admin Tools > Services. In here you can specify whether you want the service to run automatically and start at stop the service.
22 |
23 | ---------------------------
24 | Configuration
25 | ---------------------------
26 | The file noVNCConfig.ini must be in the same directory as "noVNC Websocket Service.exe".
27 |
28 | This file contains a single line which is the websockify.exe statup arguements. An example is:
29 | 192.168.0.1:5901 192.168.0.1:5900
30 |
31 | All websockify supported arguements will work if added here.
32 |
33 | ---------------------------
34 | Deletion
35 | ---------------------------
36 |
37 | You can delete the service at any time by running the commandline as admin and using this command:
38 | sc delete "noVNC Websocket Server".
39 |
40 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/Windows/noVNC Websocket Service Project/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.ServiceProcess;
5 | using System.Text;
6 |
7 | namespace MELT_Command_Websocket
8 | {
9 | static class Program
10 | {
11 | ///
12 | /// The main entry point for the application.
13 | ///
14 | static void Main()
15 | {
16 | ServiceBase[] ServicesToRun;
17 | ServicesToRun = new ServiceBase[]
18 | {
19 | new Service1()
20 | };
21 | ServiceBase.Run(ServicesToRun);
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/Windows/noVNC Websocket Service Project/ProjectInstaller.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace MELT_Command_Websocket
2 | {
3 | partial class ProjectInstaller
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Component Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
32 | this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();
33 | //
34 | // serviceProcessInstaller1
35 | //
36 | this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.NetworkService;
37 | this.serviceProcessInstaller1.Installers.AddRange(new System.Configuration.Install.Installer[] {
38 | this.serviceInstaller1});
39 | this.serviceProcessInstaller1.Password = null;
40 | this.serviceProcessInstaller1.Username = null;
41 | //
42 | // serviceInstaller1
43 | //
44 | this.serviceInstaller1.Description = "noVNC Websocket Service";
45 | this.serviceInstaller1.DisplayName = "noVNC Websocket Service";
46 | this.serviceInstaller1.ServiceName = "noVNC Websocket Service";
47 | this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
48 | //
49 | // ProjectInstaller
50 | //
51 | this.Installers.AddRange(new System.Configuration.Install.Installer[] {
52 | this.serviceProcessInstaller1});
53 |
54 | }
55 |
56 | #endregion
57 |
58 | private System.ServiceProcess.ServiceProcessInstaller serviceProcessInstaller1;
59 | private System.ServiceProcess.ServiceInstaller serviceInstaller1;
60 | }
61 | }
--------------------------------------------------------------------------------
/vnc/utils/websockify/Windows/noVNC Websocket Service Project/ProjectInstaller.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Configuration.Install;
6 | using System.Linq;
7 |
8 |
9 | namespace MELT_Command_Websocket
10 | {
11 | [RunInstaller(true)]
12 | public partial class ProjectInstaller : System.Configuration.Install.Installer
13 | {
14 | public ProjectInstaller()
15 | {
16 | InitializeComponent();
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/Windows/noVNC Websocket Service Project/ProjectInstaller.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 56
122 |
123 |
124 | 196, 17
125 |
126 |
127 | False
128 |
129 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/Windows/noVNC Websocket Service Project/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("MELT Command Websocket")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Microsoft")]
12 | [assembly: AssemblyProduct("MELT Command Websocket")]
13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("5ab831cb-6852-4ce1-849c-b26725b0e10b")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/Windows/noVNC Websocket Service Project/Service1.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace MELT_Command_Websocket
2 | {
3 | partial class Service1
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Component Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | components = new System.ComponentModel.Container();
32 | this.ServiceName = "Service1";
33 | }
34 |
35 | #endregion
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/Windows/noVNC Websocket Service Project/Service1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Diagnostics;
6 | using System.Linq;
7 | using System.ServiceProcess;
8 | using System.Text;
9 | using System.IO;
10 |
11 | namespace MELT_Command_Websocket
12 | {
13 | public partial class Service1 : ServiceBase
14 | {
15 | Process websockify;
16 | public Service1()
17 | {
18 | InitializeComponent();
19 | }
20 |
21 | protected override void OnStart(string[] args)
22 | {
23 |
24 | string configpath = AppDomain.CurrentDomain.BaseDirectory + "\\noVNCConfig.ini";
25 | string sockifypath = AppDomain.CurrentDomain.BaseDirectory + "\\websockify.exe";
26 | //Load commandline arguements from config file.
27 | StreamReader streamReader = new StreamReader(configpath);
28 | string arguements = streamReader.ReadLine();
29 | streamReader.Close();
30 |
31 | //Start websockify.
32 | websockify = System.Diagnostics.Process.Start(sockifypath, arguements);
33 | }
34 |
35 | protected override void OnStop()
36 | {
37 | //Service stopped. Close websockify.
38 | websockify.Kill();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/Windows/noVNC Websocket Service Project/noVNC Websocket.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {6B86AE7B-6BBD-4E74-8802-5995E8B6D27D}
9 | WinExe
10 | Properties
11 | noVNC_Websocket_Service
12 | noVNC Websocket Service
13 | v3.5
14 | 512
15 |
16 |
17 | x86
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | x86
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | Component
49 |
50 |
51 | ProjectInstaller.cs
52 |
53 |
54 | Component
55 |
56 |
57 | Service1.cs
58 |
59 |
60 |
61 |
62 |
63 |
64 | ProjectInstaller.cs
65 |
66 |
67 |
68 |
75 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/Windows/noVNC Websocket Service Project/noVNC Websocket.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual Studio 2010
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "noVNC Websocket", "noVNC Websocket.csproj", "{6B86AE7B-6BBD-4E74-8802-5995E8B6D27D}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|x86 = Debug|x86
9 | Release|x86 = Release|x86
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {6B86AE7B-6BBD-4E74-8802-5995E8B6D27D}.Debug|x86.ActiveCfg = Debug|x86
13 | {6B86AE7B-6BBD-4E74-8802-5995E8B6D27D}.Debug|x86.Build.0 = Debug|x86
14 | {6B86AE7B-6BBD-4E74-8802-5995E8B6D27D}.Release|x86.ActiveCfg = Release|x86
15 | {6B86AE7B-6BBD-4E74-8802-5995E8B6D27D}.Release|x86.Build.0 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/include/keysym.js:
--------------------------------------------------------------------------------
1 | /*
2 | * from noVNC: HTML5 VNC client
3 | * Copyright (C) 2010 Joel Martin
4 | * Licensed under LGPL-3 (see LICENSE.txt)
5 | */
6 |
7 | /* Translate DOM key down/up event to keysym value */
8 | function getKeysym(e) {
9 | var evt, keysym;
10 | evt = (e ? e : window.event);
11 |
12 | /* Remap modifier and special keys */
13 | switch ( evt.keyCode ) {
14 | case 8 : keysym = 0xFF08; break; // BACKSPACE
15 | case 9 : keysym = 0xFF09; break; // TAB
16 | case 13 : keysym = 0xFF0D; break; // ENTER
17 | case 27 : keysym = 0xFF1B; break; // ESCAPE
18 | case 45 : keysym = 0xFF63; break; // INSERT
19 | case 46 : keysym = 0xFFFF; break; // DELETE
20 | case 36 : keysym = 0xFF50; break; // HOME
21 | case 35 : keysym = 0xFF57; break; // END
22 | case 33 : keysym = 0xFF55; break; // PAGE_UP
23 | case 34 : keysym = 0xFF56; break; // PAGE_DOWN
24 | case 37 : keysym = 0xFF51; break; // LEFT
25 | case 38 : keysym = 0xFF52; break; // UP
26 | case 39 : keysym = 0xFF53; break; // RIGHT
27 | case 40 : keysym = 0xFF54; break; // DOWN
28 | case 112 : keysym = 0xFFBE; break; // F1
29 | case 113 : keysym = 0xFFBF; break; // F2
30 | case 114 : keysym = 0xFFC0; break; // F3
31 | case 115 : keysym = 0xFFC1; break; // F4
32 | case 116 : keysym = 0xFFC2; break; // F5
33 | case 117 : keysym = 0xFFC3; break; // F6
34 | case 118 : keysym = 0xFFC4; break; // F7
35 | case 119 : keysym = 0xFFC5; break; // F8
36 | case 120 : keysym = 0xFFC6; break; // F9
37 | case 121 : keysym = 0xFFC7; break; // F10
38 | case 122 : keysym = 0xFFC8; break; // F11
39 | case 123 : keysym = 0xFFC9; break; // F12
40 | case 16 : keysym = 0xFFE1; break; // SHIFT
41 | case 17 : keysym = 0xFFE3; break; // CONTROL
42 | //case 18 : keysym = 0xFFE7; break; // Left Meta (Mac Option)
43 | case 18 : keysym = 0xFFE9; break; // Left ALT (Mac Command)
44 | default : keysym = evt.keyCode; break;
45 | }
46 |
47 | /* Remap symbols */
48 | switch (keysym) {
49 | case 186 : keysym = 59; break; // ; (IE)
50 | case 187 : keysym = 61; break; // = (IE)
51 | case 188 : keysym = 44; break; // , (Mozilla, IE)
52 | case 109 : // - (Mozilla)
53 | if (Util.Engine.gecko) {
54 | keysym = 45; }
55 | break;
56 | case 189 : keysym = 45; break; // - (IE)
57 | case 190 : keysym = 46; break; // . (Mozilla, IE)
58 | case 191 : keysym = 47; break; // / (Mozilla, IE)
59 | case 192 : keysym = 96; break; // ` (Mozilla, IE)
60 | case 219 : keysym = 91; break; // [ (Mozilla, IE)
61 | case 220 : keysym = 92; break; // \ (Mozilla, IE)
62 | case 221 : keysym = 93; break; // ] (Mozilla, IE)
63 | case 222 : keysym = 39; break; // ' (Mozilla, IE)
64 | }
65 |
66 | /* Remap shifted and unshifted keys */
67 | if (!!evt.shiftKey) {
68 | switch (keysym) {
69 | case 48 : keysym = 41 ; break; // ) (shifted 0)
70 | case 49 : keysym = 33 ; break; // ! (shifted 1)
71 | case 50 : keysym = 64 ; break; // @ (shifted 2)
72 | case 51 : keysym = 35 ; break; // # (shifted 3)
73 | case 52 : keysym = 36 ; break; // $ (shifted 4)
74 | case 53 : keysym = 37 ; break; // % (shifted 5)
75 | case 54 : keysym = 94 ; break; // ^ (shifted 6)
76 | case 55 : keysym = 38 ; break; // & (shifted 7)
77 | case 56 : keysym = 42 ; break; // * (shifted 8)
78 | case 57 : keysym = 40 ; break; // ( (shifted 9)
79 |
80 | case 59 : keysym = 58 ; break; // : (shifted `)
81 | case 61 : keysym = 43 ; break; // + (shifted ;)
82 | case 44 : keysym = 60 ; break; // < (shifted ,)
83 | case 45 : keysym = 95 ; break; // _ (shifted -)
84 | case 46 : keysym = 62 ; break; // > (shifted .)
85 | case 47 : keysym = 63 ; break; // ? (shifted /)
86 | case 96 : keysym = 126; break; // ~ (shifted `)
87 | case 91 : keysym = 123; break; // { (shifted [)
88 | case 92 : keysym = 124; break; // | (shifted \)
89 | case 93 : keysym = 125; break; // } (shifted ])
90 | case 39 : keysym = 34 ; break; // " (shifted ')
91 | }
92 | } else if ((keysym >= 65) && (keysym <=90)) {
93 | /* Remap unshifted A-Z */
94 | keysym += 32;
95 | }
96 |
97 | return keysym;
98 | }
99 |
100 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/include/util.js:
--------------------------------------------------------------------------------
1 | /*
2 | * from noVNC: HTML5 VNC client
3 | * Copyright (C) 2012 Joel Martin
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | */
8 |
9 | "use strict";
10 | /*jslint bitwise: false, white: false */
11 | /*global window, console, document, navigator, ActiveXObject */
12 |
13 | // Globals defined here
14 | var Util = {};
15 |
16 |
17 | /*
18 | * Make arrays quack
19 | */
20 |
21 | Array.prototype.push8 = function (num) {
22 | this.push(num & 0xFF);
23 | };
24 |
25 | Array.prototype.push16 = function (num) {
26 | this.push((num >> 8) & 0xFF,
27 | (num ) & 0xFF );
28 | };
29 | Array.prototype.push32 = function (num) {
30 | this.push((num >> 24) & 0xFF,
31 | (num >> 16) & 0xFF,
32 | (num >> 8) & 0xFF,
33 | (num ) & 0xFF );
34 | };
35 |
36 | // IE does not support map (even in IE9)
37 | //This prototype is provided by the Mozilla foundation and
38 | //is distributed under the MIT license.
39 | //http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
40 | if (!Array.prototype.map)
41 | {
42 | Array.prototype.map = function(fun /*, thisp*/)
43 | {
44 | var len = this.length;
45 | if (typeof fun != "function")
46 | throw new TypeError();
47 |
48 | var res = new Array(len);
49 | var thisp = arguments[1];
50 | for (var i = 0; i < len; i++)
51 | {
52 | if (i in this)
53 | res[i] = fun.call(thisp, this[i], i, this);
54 | }
55 |
56 | return res;
57 | };
58 | }
59 |
60 | //
61 | // requestAnimationFrame shim with setTimeout fallback
62 | //
63 |
64 | window.requestAnimFrame = (function(){
65 | return window.requestAnimationFrame ||
66 | window.webkitRequestAnimationFrame ||
67 | window.mozRequestAnimationFrame ||
68 | window.oRequestAnimationFrame ||
69 | window.msRequestAnimationFrame ||
70 | function(callback){
71 | window.setTimeout(callback, 1000 / 60);
72 | };
73 | })();
74 |
75 | /*
76 | * ------------------------------------------------------
77 | * Namespaced in Util
78 | * ------------------------------------------------------
79 | */
80 |
81 | /*
82 | * Logging/debug routines
83 | */
84 |
85 | Util._log_level = 'warn';
86 | Util.init_logging = function (level) {
87 | if (typeof level === 'undefined') {
88 | level = Util._log_level;
89 | } else {
90 | Util._log_level = level;
91 | }
92 | if (typeof window.console === "undefined") {
93 | if (typeof window.opera !== "undefined") {
94 | window.console = {
95 | 'log' : window.opera.postError,
96 | 'warn' : window.opera.postError,
97 | 'error': window.opera.postError };
98 | } else {
99 | window.console = {
100 | 'log' : function(m) {},
101 | 'warn' : function(m) {},
102 | 'error': function(m) {}};
103 | }
104 | }
105 |
106 | Util.Debug = Util.Info = Util.Warn = Util.Error = function (msg) {};
107 | switch (level) {
108 | case 'debug': Util.Debug = function (msg) { console.log(msg); };
109 | case 'info': Util.Info = function (msg) { console.log(msg); };
110 | case 'warn': Util.Warn = function (msg) { console.warn(msg); };
111 | case 'error': Util.Error = function (msg) { console.error(msg); };
112 | case 'none':
113 | break;
114 | default:
115 | throw("invalid logging type '" + level + "'");
116 | }
117 | };
118 | Util.get_logging = function () {
119 | return Util._log_level;
120 | };
121 | // Initialize logging level
122 | Util.init_logging();
123 |
124 |
125 | // Set configuration default for Crockford style function namespaces
126 | Util.conf_default = function(cfg, api, defaults, v, mode, type, defval, desc) {
127 | var getter, setter;
128 |
129 | // Default getter function
130 | getter = function (idx) {
131 | if ((type in {'arr':1, 'array':1}) &&
132 | (typeof idx !== 'undefined')) {
133 | return cfg[v][idx];
134 | } else {
135 | return cfg[v];
136 | }
137 | };
138 |
139 | // Default setter function
140 | setter = function (val, idx) {
141 | if (type in {'boolean':1, 'bool':1}) {
142 | if ((!val) || (val in {'0':1, 'no':1, 'false':1})) {
143 | val = false;
144 | } else {
145 | val = true;
146 | }
147 | } else if (type in {'integer':1, 'int':1}) {
148 | val = parseInt(val, 10);
149 | } else if (type === 'str') {
150 | val = String(val);
151 | } else if (type === 'func') {
152 | if (!val) {
153 | val = function () {};
154 | }
155 | }
156 | if (typeof idx !== 'undefined') {
157 | cfg[v][idx] = val;
158 | } else {
159 | cfg[v] = val;
160 | }
161 | };
162 |
163 | // Set the description
164 | api[v + '_description'] = desc;
165 |
166 | // Set the getter function
167 | if (typeof api['get_' + v] === 'undefined') {
168 | api['get_' + v] = getter;
169 | }
170 |
171 | // Set the setter function with extra sanity checks
172 | if (typeof api['set_' + v] === 'undefined') {
173 | api['set_' + v] = function (val, idx) {
174 | if (mode in {'RO':1, 'ro':1}) {
175 | throw(v + " is read-only");
176 | } else if ((mode in {'WO':1, 'wo':1}) &&
177 | (typeof cfg[v] !== 'undefined')) {
178 | throw(v + " can only be set once");
179 | }
180 | setter(val, idx);
181 | };
182 | }
183 |
184 | // Set the default value
185 | if (typeof defaults[v] !== 'undefined') {
186 | defval = defaults[v];
187 | } else if ((type in {'arr':1, 'array':1}) &&
188 | (! (defval instanceof Array))) {
189 | defval = [];
190 | }
191 | // Coerce existing setting to the right type
192 | //Util.Debug("v: " + v + ", defval: " + defval + ", defaults[v]: " + defaults[v]);
193 | setter(defval);
194 | };
195 |
196 | // Set group of configuration defaults
197 | Util.conf_defaults = function(cfg, api, defaults, arr) {
198 | var i;
199 | for (i = 0; i < arr.length; i++) {
200 | Util.conf_default(cfg, api, defaults, arr[i][0], arr[i][1],
201 | arr[i][2], arr[i][3], arr[i][4]);
202 | }
203 | };
204 |
205 |
206 | /*
207 | * Cross-browser routines
208 | */
209 |
210 |
211 | // Dynamically load scripts without using document.write()
212 | // Reference: http://unixpapa.com/js/dyna.html
213 | //
214 | // Handles the case where load_scripts is invoked from a script that
215 | // itself is loaded via load_scripts. Once all scripts are loaded the
216 | // window.onscriptsloaded handler is called (if set).
217 | Util.get_include_uri = function() {
218 | return (typeof INCLUDE_URI !== "undefined") ? INCLUDE_URI : "include/";
219 | }
220 | Util._loading_scripts = [];
221 | Util._pending_scripts = [];
222 | Util.load_scripts = function(files) {
223 | var head = document.getElementsByTagName('head')[0], script,
224 | ls = Util._loading_scripts, ps = Util._pending_scripts;
225 | for (var f=0; f 0 && (ls[0].readyState === 'loaded' ||
232 | ls[0].readyState === 'complete')) {
233 | // For IE, append the script to trigger execution
234 | var s = ls.shift();
235 | //console.log("loaded script: " + s.src);
236 | head.appendChild(s);
237 | }
238 | if (!this.readyState ||
239 | (Util.Engine.presto && this.readyState === 'loaded') ||
240 | this.readyState === 'complete') {
241 | if (ps.indexOf(this) >= 0) {
242 | this.onload = this.onreadystatechange = null;
243 | //console.log("completed script: " + this.src);
244 | ps.splice(ps.indexOf(this), 1);
245 |
246 | // Call window.onscriptsload after last script loads
247 | if (ps.length === 0 && window.onscriptsload) {
248 | window.onscriptsload();
249 | }
250 | }
251 | }
252 | };
253 | // In-order script execution tricks
254 | if (Util.Engine.trident) {
255 | // For IE wait until readyState is 'loaded' before
256 | // appending it which will trigger execution
257 | // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
258 | ls.push(script);
259 | } else {
260 | // For webkit and firefox set async=false and append now
261 | // https://developer.mozilla.org/en-US/docs/HTML/Element/script
262 | script.async = false;
263 | head.appendChild(script);
264 | }
265 | ps.push(script);
266 | }
267 | }
268 |
269 | // Get DOM element position on page
270 | Util.getPosition = function (obj) {
271 | var x = 0, y = 0;
272 | if (obj.offsetParent) {
273 | do {
274 | x += obj.offsetLeft;
275 | y += obj.offsetTop;
276 | obj = obj.offsetParent;
277 | } while (obj);
278 | }
279 | return {'x': x, 'y': y};
280 | };
281 |
282 | // Get mouse event position in DOM element
283 | Util.getEventPosition = function (e, obj, scale) {
284 | var evt, docX, docY, pos;
285 | //if (!e) evt = window.event;
286 | evt = (e ? e : window.event);
287 | evt = (evt.changedTouches ? evt.changedTouches[0] : evt.touches ? evt.touches[0] : evt);
288 | if (evt.pageX || evt.pageY) {
289 | docX = evt.pageX;
290 | docY = evt.pageY;
291 | } else if (evt.clientX || evt.clientY) {
292 | docX = evt.clientX + document.body.scrollLeft +
293 | document.documentElement.scrollLeft;
294 | docY = evt.clientY + document.body.scrollTop +
295 | document.documentElement.scrollTop;
296 | }
297 | pos = Util.getPosition(obj);
298 | if (typeof scale === "undefined") {
299 | scale = 1;
300 | }
301 | return {'x': (docX - pos.x) / scale, 'y': (docY - pos.y) / scale};
302 | };
303 |
304 |
305 | // Event registration. Based on: http://www.scottandrew.com/weblog/articles/cbs-events
306 | Util.addEvent = function (obj, evType, fn){
307 | if (obj.attachEvent){
308 | var r = obj.attachEvent("on"+evType, fn);
309 | return r;
310 | } else if (obj.addEventListener){
311 | obj.addEventListener(evType, fn, false);
312 | return true;
313 | } else {
314 | throw("Handler could not be attached");
315 | }
316 | };
317 |
318 | Util.removeEvent = function(obj, evType, fn){
319 | if (obj.detachEvent){
320 | var r = obj.detachEvent("on"+evType, fn);
321 | return r;
322 | } else if (obj.removeEventListener){
323 | obj.removeEventListener(evType, fn, false);
324 | return true;
325 | } else {
326 | throw("Handler could not be removed");
327 | }
328 | };
329 |
330 | Util.stopEvent = function(e) {
331 | if (e.stopPropagation) { e.stopPropagation(); }
332 | else { e.cancelBubble = true; }
333 |
334 | if (e.preventDefault) { e.preventDefault(); }
335 | else { e.returnValue = false; }
336 | };
337 |
338 |
339 | // Set browser engine versions. Based on mootools.
340 | Util.Features = {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)};
341 |
342 | Util.Engine = {
343 | // Version detection break in Opera 11.60 (errors on arguments.callee.caller reference)
344 | //'presto': (function() {
345 | // return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925)); }()),
346 | 'presto': (function() { return (!window.opera) ? false : true; }()),
347 |
348 | 'trident': (function() {
349 | return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4); }()),
350 | 'webkit': (function() {
351 | try { return (navigator.taintEnabled) ? false : ((Util.Features.xpath) ? ((Util.Features.query) ? 525 : 420) : 419); } catch (e) { return false; } }()),
352 | //'webkit': (function() {
353 | // return ((typeof navigator.taintEnabled !== "unknown") && navigator.taintEnabled) ? false : ((Util.Features.xpath) ? ((Util.Features.query) ? 525 : 420) : 419); }()),
354 | 'gecko': (function() {
355 | return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false : ((document.getElementsByClassName) ? 19 : 18); }())
356 | };
357 | if (Util.Engine.webkit) {
358 | // Extract actual webkit version if available
359 | Util.Engine.webkit = (function(v) {
360 | var re = new RegExp('WebKit/([0-9\.]*) ');
361 | v = (navigator.userAgent.match(re) || ['', v])[1];
362 | return parseFloat(v, 10);
363 | })(Util.Engine.webkit);
364 | }
365 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/include/webutil.js:
--------------------------------------------------------------------------------
1 | /*
2 | * from noVNC: HTML5 VNC client
3 | * Copyright (C) 2012 Joel Martin
4 | * Licensed under MPL 2.0 (see LICENSE.txt)
5 | *
6 | * See README.md for usage and integration instructions.
7 | */
8 |
9 | "use strict";
10 | /*jslint bitwise: false, white: false */
11 | /*global Util, window, document */
12 |
13 | // Globals defined here
14 | var WebUtil = {}, $D;
15 |
16 | /*
17 | * Simple DOM selector by ID
18 | */
19 | if (!window.$D) {
20 | window.$D = function (id) {
21 | if (document.getElementById) {
22 | return document.getElementById(id);
23 | } else if (document.all) {
24 | return document.all[id];
25 | } else if (document.layers) {
26 | return document.layers[id];
27 | }
28 | return undefined;
29 | };
30 | }
31 |
32 |
33 | /*
34 | * ------------------------------------------------------
35 | * Namespaced in WebUtil
36 | * ------------------------------------------------------
37 | */
38 |
39 | // init log level reading the logging HTTP param
40 | WebUtil.init_logging = function(level) {
41 | if (typeof level !== "undefined") {
42 | Util._log_level = level;
43 | } else {
44 | Util._log_level = (document.location.href.match(
45 | /logging=([A-Za-z0-9\._\-]*)/) ||
46 | ['', Util._log_level])[1];
47 | }
48 | Util.init_logging();
49 | };
50 |
51 |
52 | WebUtil.dirObj = function (obj, depth, parent) {
53 | var i, msg = "", val = "";
54 | if (! depth) { depth=2; }
55 | if (! parent) { parent= ""; }
56 |
57 | // Print the properties of the passed-in object
58 | for (i in obj) {
59 | if ((depth > 1) && (typeof obj[i] === "object")) {
60 | // Recurse attributes that are objects
61 | msg += WebUtil.dirObj(obj[i], depth-1, parent + "." + i);
62 | } else {
63 | //val = new String(obj[i]).replace("\n", " ");
64 | if (typeof(obj[i]) === "undefined") {
65 | val = "undefined";
66 | } else {
67 | val = obj[i].toString().replace("\n", " ");
68 | }
69 | if (val.length > 30) {
70 | val = val.substr(0,30) + "...";
71 | }
72 | msg += parent + "." + i + ": " + val + "\n";
73 | }
74 | }
75 | return msg;
76 | };
77 |
78 | // Read a query string variable
79 | WebUtil.getQueryVar = function(name, defVal) {
80 | var re = new RegExp('[?][^#]*' + name + '=([^]*)'),
81 | match = document.location.href.match(re);
82 | if (typeof defVal === 'undefined') { defVal = null; }
83 | if (match) {
84 | return decodeURIComponent(match[1]);
85 | } else {
86 | return defVal;
87 | }
88 | };
89 |
90 |
91 | /*
92 | * Cookie handling. Dervied from: http://www.quirksmode.org/js/cookies.html
93 | */
94 |
95 | // No days means only for this browser session
96 | WebUtil.createCookie = function(name,value,days) {
97 | var date, expires;
98 | if (days) {
99 | date = new Date();
100 | date.setTime(date.getTime()+(days*24*60*60*1000));
101 | expires = "; expires="+date.toGMTString();
102 | }
103 | else {
104 | expires = "";
105 | }
106 | document.cookie = name+"="+value+expires+"; path=/";
107 | };
108 |
109 | WebUtil.readCookie = function(name, defaultValue) {
110 | var i, c, nameEQ = name + "=", ca = document.cookie.split(';');
111 | for(i=0; i < ca.length; i += 1) {
112 | c = ca[i];
113 | while (c.charAt(0) === ' ') { c = c.substring(1,c.length); }
114 | if (c.indexOf(nameEQ) === 0) { return c.substring(nameEQ.length,c.length); }
115 | }
116 | return (typeof defaultValue !== 'undefined') ? defaultValue : null;
117 | };
118 |
119 | WebUtil.eraseCookie = function(name) {
120 | WebUtil.createCookie(name,"",-1);
121 | };
122 |
123 | /*
124 | * Setting handling.
125 | */
126 |
127 | WebUtil.initSettings = function(callback) {
128 | var callbackArgs = Array.prototype.slice.call(arguments, 1);
129 | if (window.chrome && window.chrome.storage) {
130 | window.chrome.storage.sync.get(function (cfg) {
131 | WebUtil.settings = cfg;
132 | console.log(WebUtil.settings);
133 | if (callback) {
134 | callback.apply(this, callbackArgs);
135 | }
136 | });
137 | } else {
138 | // No-op
139 | if (callback) {
140 | callback.apply(this, callbackArgs);
141 | }
142 | }
143 | };
144 |
145 | // No days means only for this browser session
146 | WebUtil.writeSetting = function(name, value) {
147 | if (window.chrome && window.chrome.storage) {
148 | //console.log("writeSetting:", name, value);
149 | if (WebUtil.settings[name] !== value) {
150 | WebUtil.settings[name] = value;
151 | window.chrome.storage.sync.set(WebUtil.settings);
152 | }
153 | } else {
154 | localStorage.setItem(name, value);
155 | }
156 | };
157 |
158 | WebUtil.readSetting = function(name, defaultValue) {
159 | var value;
160 | if (window.chrome && window.chrome.storage) {
161 | value = WebUtil.settings[name];
162 | } else {
163 | value = localStorage.getItem(name);
164 | }
165 | if (typeof value === "undefined") {
166 | value = null;
167 | }
168 | if (value === null && typeof defaultValue !== undefined) {
169 | return defaultValue;
170 | } else {
171 | return value;
172 | }
173 | };
174 |
175 | WebUtil.eraseSetting = function(name) {
176 | if (window.chrome && window.chrome.storage) {
177 | window.chrome.storage.sync.remove(name);
178 | delete WebUtil.settings[name];
179 | } else {
180 | localStorage.removeItem(name);
181 | }
182 | };
183 |
184 | /*
185 | * Alternate stylesheet selection
186 | */
187 | WebUtil.getStylesheets = function() { var i, links, sheets = [];
188 | links = document.getElementsByTagName("link");
189 | for (i = 0; i < links.length; i += 1) {
190 | if (links[i].title &&
191 | links[i].rel.toUpperCase().indexOf("STYLESHEET") > -1) {
192 | sheets.push(links[i]);
193 | }
194 | }
195 | return sheets;
196 | };
197 |
198 | // No sheet means try and use value from cookie, null sheet used to
199 | // clear all alternates.
200 | WebUtil.selectStylesheet = function(sheet) {
201 | var i, link, sheets = WebUtil.getStylesheets();
202 | if (typeof sheet === 'undefined') {
203 | sheet = 'default';
204 | }
205 | for (i=0; i < sheets.length; i += 1) {
206 | link = sheets[i];
207 | if (link.title === sheet) {
208 | Util.Debug("Using stylesheet " + sheet);
209 | link.disabled = false;
210 | } else {
211 | //Util.Debug("Skipping stylesheet " + link.title);
212 | link.disabled = true;
213 | }
214 | }
215 | return sheet;
216 | };
217 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/include/wsirc.js:
--------------------------------------------------------------------------------
1 | /*
2 | * WebSockets IRC client
3 | * Copyright (C) 2011 Joel Martin
4 | * Licensed under LGPL-3 (see LICENSE.txt)
5 | *
6 | * Includes VT100.js from:
7 | * http://code.google.com/p/sshconsole
8 | * Which was modified from:
9 | * http://fzort.org/bi/o.php#vt100_js
10 |
11 | * IRC Client protocol:
12 | * http://www.faqs.org/rfcs/rfc2812.html
13 | */
14 |
15 |
16 | function IRC(target, connect_callback, disconnect_callback) {
17 |
18 | var that = {}, // Public API interface
19 | vt100, ws, sQ = [],
20 | state = "unconnected",
21 | irc_nick, irc_channel,
22 | termType = "VT100";
23 |
24 |
25 | Array.prototype.pushStr = function (str) {
26 | var n = str.length;
27 | for (var i=0; i < n; i++) {
28 | this.push(str.charCodeAt(i));
29 | }
30 | }
31 |
32 | function do_send() {
33 | if (sQ.length > 0) {
34 | Util.Debug("Sending " + sQ);
35 | ws.send(sQ);
36 | sQ = [];
37 | }
38 | }
39 |
40 | function do_recv() {
41 | console.log(">> do_recv");
42 | var rQ, rQi, i;
43 |
44 | while (ws.rQlen() > 1) {
45 | rQ = ws.get_rQ();
46 | rQi = ws.get_rQi();
47 | for (i = rQi; i < rQ.length; i++) {
48 | if (rQ[i] === 10) {
49 | break;
50 | }
51 | }
52 | if (i >= rQ.length) {
53 | // No line break found
54 | break;
55 | }
56 | recvMsg(ws.rQshiftStr((i-rQi) + 1));
57 | }
58 | //console.log("<< do_recv");
59 | }
60 |
61 | // Handle an IRC message
62 | function recvMsg(msg) {
63 | Util.Debug(">> recvMsg('" + msg + "')");
64 |
65 | var tokens = msg.split(' '), in_params = true,
66 | prefix, command, params = [], trailing = [];
67 |
68 | Util.Info(" tokens: " + tokens);
69 |
70 | if (tokens[0].charAt(0) === ":") {
71 | prefix = tokens.shift();
72 | }
73 |
74 | command = tokens.shift();
75 |
76 | while (tokens.length > 0) {
77 | if (tokens[0].charAt(0) === ":") {
78 | in_params = false;
79 | }
80 | if (in_params) {
81 | params.push(tokens.shift());
82 | } else {
83 | trailing.push(tokens.shift());
84 | }
85 | }
86 |
87 | Util.Info(" prefix: " + prefix);
88 | Util.Info(" command: " + command);
89 | Util.Info(" params: " + params);
90 | Util.Info(" trailing: " + trailing);
91 |
92 | // Show raw received
93 | vt100.write(msg);
94 |
95 | switch (command) {
96 | case "004":
97 | state = "registered";
98 | vt100.write("Joining channel #" + irc_channel);
99 | sendCmd("JOIN #" + irc_channel);
100 | break;
101 | case "JOIN":
102 | state = "joined";
103 | vt100.write("Joined channel #" + irc_channel);
104 | break;
105 |
106 | }
107 |
108 | Util.Debug("<< recvMsg('" + msg + "')");
109 | }
110 |
111 | function sendCmd(msg) {
112 | Util.Info("Sending: " + msg);
113 | sQ.pushStr(msg + "\r\n");
114 | do_send();
115 | }
116 |
117 | that.sendMsg = function(msg) {
118 | // TODO parse into message
119 | sendCmd("PRIVMSG #" + irc_channel + " :" + msg);
120 | }
121 |
122 |
123 | that.connect = function(host, port, encrypt, nick, channel) {
124 | var host = host,
125 | port = port,
126 | scheme = "ws://", uri;
127 |
128 | irc_nick = nick;
129 | irc_channel = channel;
130 |
131 | Util.Debug(">> connect");
132 | if ((!host) || (!port)) {
133 | alert("must set host and port");
134 | return false;
135 | }
136 |
137 | if (ws) {
138 | ws.close();
139 | }
140 |
141 | if (encrypt) {
142 | scheme = "wss://";
143 | }
144 | uri = scheme + host + ":" + port;
145 | Util.Info("connecting to " + uri);
146 |
147 | ws.open(uri);
148 |
149 | Util.Debug("<< connect");
150 |
151 | return true;
152 | }
153 |
154 | that.disconnect = function() {
155 | Util.Debug(">> disconnect");
156 | if (ws) {
157 | ws.close();
158 | }
159 |
160 | disconnect_callback();
161 | Util.Debug("<< disconnect");
162 | }
163 |
164 |
165 | function constructor() {
166 | /* Initialize Websock object */
167 | ws = new Websock();
168 |
169 | ws.on('message', do_recv);
170 | ws.on('open', function(e) {
171 | Util.Info(">> WebSockets.onopen");
172 | // Send registration commands
173 | state = "connected";
174 | sendCmd("NICK " + irc_nick);
175 | // TODO: how to determine this?
176 | sendCmd("USER joelm 0 * :Joel Martin");
177 | connect_callback();
178 | Util.Info("<< WebSockets.onopen");
179 | });
180 | ws.on('close', function(e) {
181 | Util.Info(">> WebSockets.onclose");
182 | that.disconnect();
183 | Util.Info("<< WebSockets.onclose");
184 | });
185 | ws.on('error', function(e) {
186 | Util.Info(">> WebSockets.onerror");
187 | that.disconnect();
188 | Util.Info("<< WebSockets.onerror");
189 | });
190 |
191 | /* Initialize the terminal emulator/renderer */
192 |
193 | vt100 = new VT100(80, 24, target);
194 |
195 | // Show cursor
196 | vt100.curs_set(true, false);
197 |
198 | /*
199 | * Override VT100 I/O routines
200 | */
201 |
202 | // Set handler for sending characters
203 | vt100.getch(
204 | function send_chr(chr, vt) {
205 | var i;
206 | Util.Debug(">> send_chr: " + chr);
207 | for (i = 0; i < chr.length; i++) {
208 | sQ.push(chr.charCodeAt(i));
209 | }
210 | do_send();
211 | vt100.getch(send_chr);
212 | }
213 | );
214 |
215 | vt100.debug = function(message) {
216 | Util.Debug(message + "\n");
217 | }
218 |
219 | vt100.warn = function(message) {
220 | Util.Warn(message + "\n");
221 | }
222 |
223 | vt100.curs_set = function(vis, grab, eventist)
224 | {
225 | this.debug("curs_set:: vis: " + vis + ", grab: " + grab);
226 | if (vis !== undefined)
227 | this.cursor_vis_ = (vis > 0);
228 | }
229 |
230 | return that;
231 | }
232 |
233 | return constructor(); // Return the public API interface
234 |
235 | } // End of Telnet()
236 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/include/wstelnet.js:
--------------------------------------------------------------------------------
1 | /*
2 | * WebSockets telnet client
3 | * Copyright (C) 2011 Joel Martin
4 | * Licensed under LGPL-3 (see LICENSE.txt)
5 | *
6 | * Includes VT100.js from:
7 | * http://code.google.com/p/sshconsole
8 | * Which was modified from:
9 | * http://fzort.org/bi/o.php#vt100_js
10 | *
11 | * Telnet protocol:
12 | * http://www.networksorcery.com/enp/protocol/telnet.htm
13 | * http://www.networksorcery.com/enp/rfc/rfc1091.txt
14 | *
15 | * ANSI escape sequeneces:
16 | * http://en.wikipedia.org/wiki/ANSI_escape_code
17 | * http://ascii-table.com/ansi-escape-sequences-vt-100.php
18 | * http://www.termsys.demon.co.uk/vtansi.htm
19 | * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
20 | *
21 | * ASCII codes:
22 | * http://en.wikipedia.org/wiki/ASCII
23 | * http://www.hobbyprojects.com/ascii-table/ascii-table.html
24 | *
25 | * Other web consoles:
26 | * http://stackoverflow.com/questions/244750/ajax-console-window-with-ansi-vt100-support
27 | */
28 |
29 |
30 |
31 |
32 | function Telnet(target, connect_callback, disconnect_callback) {
33 |
34 | var that = {}, // Public API interface
35 | vt100, ws, sQ = [];
36 | termType = "VT100";
37 |
38 |
39 | Array.prototype.pushStr = function (str) {
40 | var n = str.length;
41 | for (var i=0; i < n; i++) {
42 | this.push(str.charCodeAt(i));
43 | }
44 | }
45 |
46 | function do_send() {
47 | if (sQ.length > 0) {
48 | Util.Debug("Sending " + sQ);
49 | ws.send(sQ);
50 | sQ = [];
51 | }
52 | }
53 |
54 | function do_recv() {
55 | //console.log(">> do_recv");
56 | var arr = ws.rQshiftBytes(ws.rQlen()), str = "",
57 | chr, cmd, code, value;
58 |
59 | Util.Debug("Received array '" + arr + "'");
60 | while (arr.length > 0) {
61 | chr = arr.shift();
62 | switch (chr) {
63 | case 255: // IAC
64 | cmd = chr;
65 | code = arr.shift();
66 | value = arr.shift();
67 | switch (code) {
68 | case 254: // DONT
69 | Util.Debug("Got Cmd DONT '" + value + "', ignoring");
70 | break;
71 | case 253: // DO
72 | Util.Debug("Got Cmd DO '" + value + "'");
73 | if (value === 24) {
74 | // Terminal type
75 | Util.Info("Send WILL '" + value + "' (TERM-TYPE)");
76 | sQ.push(255, 251, value);
77 | } else {
78 | // Refuse other DO requests with a WONT
79 | Util.Debug("Send WONT '" + value + "'");
80 | sQ.push(255, 252, value);
81 | }
82 | break;
83 | case 252: // WONT
84 | Util.Debug("Got Cmd WONT '" + value + "', ignoring");
85 | break;
86 | case 251: // WILL
87 | Util.Debug("Got Cmd WILL '" + value + "'");
88 | if (value === 1) {
89 | // Server will echo, turn off local echo
90 | vt100.noecho();
91 | // Affirm echo with DO
92 | Util.Info("Send Cmd DO '" + value + "' (echo)");
93 | sQ.push(255, 253, value);
94 | } else {
95 | // Reject other WILL offers with a DONT
96 | Util.Debug("Send Cmd DONT '" + value + "'");
97 | sQ.push(255, 254, value);
98 | }
99 | break;
100 | case 250: // SB (subnegotiation)
101 | if (value === 24) {
102 | Util.Info("Got IAC SB TERM-TYPE SEND(1) IAC SE");
103 | // TERM-TYPE subnegotiation
104 | if (arr[0] === 1 &&
105 | arr[1] === 255 &&
106 | arr[2] === 240) {
107 | arr.shift(); arr.shift(); arr.shift();
108 | Util.Info("Send IAC SB TERM-TYPE IS(0) '" +
109 | termType + "' IAC SE");
110 | sQ.push(255, 250, 24, 0);
111 | sQ.pushStr(termType);
112 | sQ.push(255, 240);
113 | } else {
114 | Util.Info("Invalid subnegotiation received" + arr);
115 | }
116 | } else {
117 | Util.Info("Ignoring SB " + value);
118 | }
119 | break;
120 | default:
121 | Util.Info("Got Cmd " + cmd + " " + value + ", ignoring"); }
122 | continue;
123 | case 242: // Data Mark (Synch)
124 | cmd = chr;
125 | code = arr.shift();
126 | value = arr.shift();
127 | Util.Info("Ignoring Data Mark (Synch)");
128 | break;
129 | default: // everything else
130 | str += String.fromCharCode(chr);
131 | }
132 | }
133 |
134 | if (sQ) {
135 | do_send();
136 | }
137 |
138 | if (str) {
139 | vt100.write(str);
140 | }
141 |
142 | //console.log("<< do_recv");
143 | }
144 |
145 |
146 |
147 | that.connect = function(host, port, encrypt) {
148 | var host = host,
149 | port = port,
150 | scheme = "ws://", uri;
151 |
152 | Util.Debug(">> connect");
153 | if ((!host) || (!port)) {
154 | console.log("must set host and port");
155 | return;
156 | }
157 |
158 | if (ws) {
159 | ws.close();
160 | }
161 |
162 | if (encrypt) {
163 | scheme = "wss://";
164 | }
165 | uri = scheme + host + ":" + port;
166 | Util.Info("connecting to " + uri);
167 |
168 | ws.open(uri);
169 |
170 | Util.Debug("<< connect");
171 | }
172 |
173 | that.disconnect = function() {
174 | Util.Debug(">> disconnect");
175 | if (ws) {
176 | ws.close();
177 | }
178 | vt100.curs_set(true, false);
179 |
180 | disconnect_callback();
181 | Util.Debug("<< disconnect");
182 | }
183 |
184 |
185 | function constructor() {
186 | /* Initialize Websock object */
187 | ws = new Websock();
188 |
189 | ws.on('message', do_recv);
190 | ws.on('open', function(e) {
191 | Util.Info(">> WebSockets.onopen");
192 | vt100.curs_set(true, true);
193 | connect_callback();
194 | Util.Info("<< WebSockets.onopen");
195 | });
196 | ws.on('close', function(e) {
197 | Util.Info(">> WebSockets.onclose");
198 | that.disconnect();
199 | Util.Info("<< WebSockets.onclose");
200 | });
201 | ws.on('error', function(e) {
202 | Util.Info(">> WebSockets.onerror");
203 | that.disconnect();
204 | Util.Info("<< WebSockets.onerror");
205 | });
206 |
207 | /* Initialize the terminal emulator/renderer */
208 |
209 | vt100 = new VT100(80, 24, target);
210 |
211 |
212 | /*
213 | * Override VT100 I/O routines
214 | */
215 |
216 | // Set handler for sending characters
217 | vt100.getch(
218 | function send_chr(chr, vt) {
219 | var i;
220 | Util.Debug(">> send_chr: " + chr);
221 | for (i = 0; i < chr.length; i++) {
222 | sQ.push(chr.charCodeAt(i));
223 | }
224 | do_send();
225 | vt100.getch(send_chr);
226 | }
227 | );
228 |
229 | vt100.debug = function(message) {
230 | Util.Debug(message + "\n");
231 | }
232 |
233 | vt100.warn = function(message) {
234 | Util.Warn(message + "\n");
235 | }
236 |
237 | vt100.curs_set = function(vis, grab, eventist)
238 | {
239 | this.debug("curs_set:: vis: " + vis + ", grab: " + grab);
240 | if (vis !== undefined)
241 | this.cursor_vis_ = (vis > 0);
242 | if (eventist === undefined)
243 | eventist = window;
244 | if (grab === true || grab === false) {
245 | if (grab === this.grab_events_)
246 | return;
247 | if (grab) {
248 | this.grab_events_ = true;
249 | VT100.the_vt_ = this;
250 | Util.addEvent(eventist, 'keydown', vt100.key_down);
251 | Util.addEvent(eventist, 'keyup', vt100.key_up);
252 | } else {
253 | Util.removeEvent(eventist, 'keydown', vt100.key_down);
254 | Util.removeEvent(eventist, 'keyup', vt100.key_up);
255 | this.grab_events_ = false;
256 | VT100.the_vt_ = undefined;
257 | }
258 | }
259 | }
260 |
261 | vt100.key_down = function(e) {
262 | var vt = VT100.the_vt_, keysym, ch, str = "";
263 |
264 | if (vt === undefined)
265 | return true;
266 |
267 | keysym = getKeysym(e);
268 |
269 | if (keysym < 128) {
270 | if (e.ctrlKey) {
271 | if (keysym == 64) {
272 | // control 0
273 | ch = 0;
274 | } else if ((keysym >= 97) && (keysym <= 122)) {
275 | // control codes 1-26
276 | ch = keysym - 96;
277 | } else if ((keysym >= 91) && (keysym <= 95)) {
278 | // control codes 27-31
279 | ch = keysym - 64;
280 | } else {
281 | Util.Info("Debug unknown control keysym: " + keysym);
282 | }
283 | } else {
284 | ch = keysym;
285 | }
286 | str = String.fromCharCode(ch);
287 | } else {
288 | switch (keysym) {
289 | case 65505: // Shift, do not send directly
290 | break;
291 | case 65507: // Ctrl, do not send directly
292 | break;
293 | case 65293: // Carriage return, line feed
294 | str = '\n'; break;
295 | case 65288: // Backspace
296 | str = '\b'; break;
297 | case 65289: // Tab
298 | str = '\t'; break;
299 | case 65307: // Escape
300 | str = '\x1b'; break;
301 | case 65361: // Left arrow
302 | str = '\x1b[D'; break;
303 | case 65362: // Up arrow
304 | str = '\x1b[A'; break;
305 | case 65363: // Right arrow
306 | str = '\x1b[C'; break;
307 | case 65364: // Down arrow
308 | str = '\x1b[B'; break;
309 | default:
310 | Util.Info("Unrecoginized keysym " + keysym);
311 | }
312 | }
313 |
314 | if (str) {
315 | vt.key_buf_.push(str);
316 | setTimeout(VT100.go_getch_, 0);
317 | }
318 |
319 | Util.stopEvent(e);
320 | return false;
321 | }
322 |
323 | vt100.key_up = function(e) {
324 | var vt = VT100.the_vt_;
325 | if (vt === undefined)
326 | return true;
327 | Util.stopEvent(e);
328 | return false;
329 | }
330 |
331 |
332 | return that;
333 | }
334 |
335 | return constructor(); // Return the public API interface
336 |
337 | } // End of Telnet()
338 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/other/Makefile:
--------------------------------------------------------------------------------
1 | TARGETS=websockify
2 | CFLAGS += -fPIC
3 |
4 | all: $(TARGETS)
5 |
6 | websockify: websockify.o websocket.o
7 | $(CC) $(LDFLAGS) $^ -lssl -lcrypto -o $@
8 |
9 | websocket.o: websocket.c websocket.h
10 | websockify.o: websockify.c websocket.h
11 |
12 | clean:
13 | rm -f websockify *.o
14 |
15 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/other/README.md:
--------------------------------------------------------------------------------
1 | This directory contain alternate implementations of
2 | WebSockets-to-TCP-Socket proxies (for noVNC).
3 |
4 | ## websockify.c (C)
5 |
6 | ### Description
7 |
8 | This is a C version of the original websockify. It is more limited in
9 | functionality than the original.
10 |
11 |
12 | ## websockify.js
13 |
14 | ### Description
15 |
16 | This is a Node.JS (server-side event driven Javascript) implementation
17 | of websockify.
18 |
19 |
20 | ## kumina.c (C)
21 |
22 | ### Description
23 |
24 | The upstream source of the kumina proxy is [here](https://github.com/kumina/wsproxy).
25 |
26 | [This article](http://blog.kumina.nl/2011/06/proxying-and-multiplexing-novnc-using-wsproxy/)
27 | describes the kumina proxy.
28 |
29 | kumina is an application that is run from inetd, which allows noVNC
30 | to connect to an unmodified VNC server. Furthermore, it makes use of
31 | the recently added support in noVNC for file names. The file name is
32 | used to denote the port number. Say, you connect to:
33 |
34 | ws://host:41337/25900
35 |
36 | The kumina proxy opens a connection to:
37 |
38 | vnc://host:25900/
39 |
40 | The address to which kumina connects, is the same as the address to
41 | which the client connected (using getsockname()).
42 |
43 | ### Configuration
44 |
45 | kumina can be enabled by adding the following line to inetd.conf:
46 |
47 | 41337 stream tcp nowait nobody /usr/sbin/kumina kumina 25900 25909
48 |
49 | The two parameters of kumina denote the minimum and the maximum allowed
50 | port numbers. This allows a single kumina instance to multiplex
51 | connections to multiple VNC servers.
52 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/other/js/README.md:
--------------------------------------------------------------------------------
1 | A JavaScript implementation of the websockify WebSocket-to-TCP bridge/proxy.
2 |
3 | Copyright (C) 2013 - Joel Martin (github.com/kanaka)
4 |
5 | Licensed under LGPL-3.
6 |
7 | See http://github.com/kanaka/websockify for more info.
8 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/other/js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": "Joel Martin (http://github.com/kanaka)",
3 | "name": "websockify",
4 | "description": "websockify is a WebSocket-to-TCP proxy/bridge",
5 | "license": "LGPL-3.0",
6 | "version": "0.8.0",
7 | "repository": {
8 | "type": "git",
9 | "url": "git://github.com/kanaka/websockify.git"
10 | },
11 | "files": ["../../docs/LICENSE.LGPL-3","websockify.js"],
12 | "bin": {
13 | "websockify": "./websockify.js"
14 | },
15 | "engines": {
16 | "node": ">=0.8.9"
17 | },
18 | "dependencies": {
19 | "ws": ">=0.4.27",
20 | "optimist": "latest",
21 | "mime-types" : "latest"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/other/js/websockify.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | // A WebSocket to TCP socket proxy
4 | // Copyright 2012 Joel Martin
5 | // Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
6 |
7 | // Known to work with node 0.8.9
8 | // Requires node modules: ws and optimist
9 | // npm install ws optimist
10 |
11 |
12 | var argv = require('optimist').argv,
13 | net = require('net'),
14 | http = require('http'),
15 | https = require('https'),
16 | url = require('url'),
17 | path = require('path'),
18 | fs = require('fs'),
19 | mime = require('mime-types'),
20 |
21 | Buffer = require('buffer').Buffer,
22 | WebSocketServer = require('ws').Server,
23 |
24 | webServer, wsServer,
25 | source_host, source_port, target_host, target_port,
26 | web_path = null;
27 |
28 |
29 | // Handle new WebSocket client
30 | new_client = function(client, req) {
31 | var clientAddr = client._socket.remoteAddress, log;
32 | var start_time = new Date().getTime();
33 |
34 | console.log(req ? req.url : client.upgradeReq.url);
35 | log = function (msg) {
36 | console.log(' ' + clientAddr + ': '+ msg);
37 | };
38 | log('WebSocket connection');
39 | log('Version ' + client.protocolVersion + ', subprotocol: ' + client.protocol);
40 |
41 | if (argv.record) {
42 | var rs = fs.createWriteStream(argv.record + '/' + new Date().toISOString().replace(/:/g, "_"));
43 | rs.write('var VNC_frame_data = [\n');
44 | } else {
45 | var rs = null;
46 | }
47 |
48 | var target = net.createConnection(target_port,target_host, function() {
49 | log('connected to target');
50 | });
51 | target.on('data', function(data) {
52 | //log("sending message: " + data);
53 |
54 | if (rs) {
55 | var tdelta = Math.floor(new Date().getTime()) - start_time;
56 | var rsdata = '\'{' + tdelta + '{' + decodeBuffer(data) + '\',\n';
57 | rs.write(rsdata);
58 | }
59 |
60 | try {
61 | client.send(data);
62 | } catch(e) {
63 | log("Client closed, cleaning up target");
64 | target.end();
65 | }
66 | });
67 | target.on('end', function() {
68 | log('target disconnected');
69 | client.close();
70 | if (rs) {
71 | rs.end('\'EOF\'];\n');
72 | }
73 | });
74 | target.on('error', function() {
75 | log('target connection error');
76 | target.end();
77 | client.close();
78 | if (rs) {
79 | rs.end('\'EOF\'];\n');
80 | }
81 | });
82 |
83 | client.on('message', function(msg) {
84 | //log('got message: ' + msg);
85 |
86 | if (rs) {
87 | var rdelta = Math.floor(new Date().getTime()) - start_time;
88 | var rsdata = ('\'}' + rdelta + '}' + decodeBuffer(msg) + '\',\n');
89 | ~ rs.write(rsdata);
90 | }
91 |
92 | target.write(msg);
93 | });
94 | client.on('close', function(code, reason) {
95 | log('WebSocket client disconnected: ' + code + ' [' + reason + ']');
96 | target.end();
97 | });
98 | client.on('error', function(a) {
99 | log('WebSocket client error: ' + a);
100 | target.end();
101 | });
102 | };
103 |
104 | function decodeBuffer(buf) {
105 | var returnString = '';
106 | for (var i = 0; i < buf.length; i++) {
107 | if (buf[i] >= 48 && buf[i] <= 90) {
108 | returnString += String.fromCharCode(buf[i]);
109 | } else if (buf[i] === 95) {
110 | returnString += String.fromCharCode(buf[i]);
111 | } else if (buf[i] >= 97 && buf[i] <= 122) {
112 | returnString += String.fromCharCode(buf[i]);
113 | } else {
114 | var charToConvert = buf[i].toString(16);
115 | if (charToConvert.length === 0) {
116 | returnString += '\\x00';
117 | } else if (charToConvert.length === 1) {
118 | returnString += '\\x0' + charToConvert;
119 | } else {
120 | returnString += '\\x' + charToConvert;
121 | }
122 | }
123 | }
124 | return returnString;
125 | }
126 |
127 | // Send an HTTP error response
128 | http_error = function (response, code, msg) {
129 | response.writeHead(code, {"Content-Type": "text/plain"});
130 | response.write(msg + "\n");
131 | response.end();
132 | return;
133 | }
134 |
135 | // Process an HTTP static file request
136 | http_request = function (request, response) {
137 | // console.log("pathname: " + url.parse(req.url).pathname);
138 | // res.writeHead(200, {'Content-Type': 'text/plain'});
139 | // res.end('okay');
140 |
141 | if (! argv.web) {
142 | return http_error(response, 403, "403 Permission Denied");
143 | }
144 |
145 | var uri = url.parse(request.url).pathname
146 | , filename = path.join(argv.web, uri);
147 |
148 | fs.exists(filename, function(exists) {
149 | if(!exists) {
150 | return http_error(response, 404, "404 Not Found");
151 | }
152 |
153 | if (fs.statSync(filename).isDirectory()) {
154 | filename += '/index.html';
155 | }
156 |
157 | fs.readFile(filename, "binary", function(err, file) {
158 | if(err) {
159 | return http_error(response, 500, err);
160 | }
161 |
162 | var headers = {};
163 | var contentType = mime.contentType(path.extname(filename));
164 | if (contentType !== false) {
165 | headers['Content-Type'] = contentType;
166 | }
167 |
168 | response.writeHead(200, headers);
169 | response.write(file, "binary");
170 | response.end();
171 | });
172 | });
173 | };
174 |
175 | // parse source and target arguments into parts
176 | try {
177 | source_arg = argv._[0].toString();
178 | target_arg = argv._[1].toString();
179 |
180 | var idx;
181 | idx = source_arg.indexOf(":");
182 | if (idx >= 0) {
183 | source_host = source_arg.slice(0, idx);
184 | source_port = parseInt(source_arg.slice(idx+1), 10);
185 | } else {
186 | source_host = "";
187 | source_port = parseInt(source_arg, 10);
188 | }
189 |
190 | idx = target_arg.indexOf(":");
191 | if (idx < 0) {
192 | throw("target must be host:port");
193 | }
194 | target_host = target_arg.slice(0, idx);
195 | target_port = parseInt(target_arg.slice(idx+1), 10);
196 |
197 | if (isNaN(source_port) || isNaN(target_port)) {
198 | throw("illegal port");
199 | }
200 | } catch(e) {
201 | console.error("websockify.js [--web web_dir] [--cert cert.pem [--key key.pem]] [--record dir] [source_addr:]source_port target_addr:target_port");
202 | process.exit(2);
203 | }
204 |
205 | console.log("WebSocket settings: ");
206 | console.log(" - proxying from " + source_host + ":" + source_port +
207 | " to " + target_host + ":" + target_port);
208 | if (argv.web) {
209 | console.log(" - Web server active. Serving: " + argv.web);
210 | }
211 |
212 | if (argv.cert) {
213 | argv.key = argv.key || argv.cert;
214 | var cert = fs.readFileSync(argv.cert),
215 | key = fs.readFileSync(argv.key);
216 | console.log(" - Running in encrypted HTTPS (wss://) mode using: " + argv.cert + ", " + argv.key);
217 | webServer = https.createServer({cert: cert, key: key}, http_request);
218 | } else {
219 | console.log(" - Running in unencrypted HTTP (ws://) mode");
220 | webServer = http.createServer(http_request);
221 | }
222 | webServer.listen(source_port, function() {
223 | wsServer = new WebSocketServer({server: webServer});
224 | wsServer.on('connection', new_client);
225 | });
226 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/other/launch.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | usage() {
4 | if [ "$*" ]; then
5 | echo "$*"
6 | echo
7 | fi
8 | echo "Usage: ${NAME} [--listen PORT] [--vnc VNC_HOST:PORT] [--cert CERT]"
9 | echo
10 | echo "Starts the WebSockets proxy and a mini-webserver and "
11 | echo "provides a cut-and-paste URL to go to."
12 | echo
13 | echo " --listen PORT Port for proxy/webserver to listen on"
14 | echo " Default: 6080"
15 | echo " --vnc VNC_HOST:PORT VNC server host:port proxy target"
16 | echo " Default: localhost:5900"
17 | echo " --cert CERT Path to combined cert/key file"
18 | echo " Default: self.pem"
19 | echo " --web WEB Path to web files (e.g. vnc.html)"
20 | echo " Default: ./"
21 | exit 2
22 | }
23 |
24 | NAME="$(basename $0)"
25 | HERE="$(cd "$(dirname "$0")" && pwd)"
26 | PORT="6080"
27 | VNC_DEST="localhost:5900"
28 | CERT=""
29 | WEB=""
30 | proxy_pid=""
31 |
32 | die() {
33 | echo "$*"
34 | exit 1
35 | }
36 |
37 | cleanup() {
38 | trap - TERM QUIT INT EXIT
39 | trap "true" CHLD # Ignore cleanup messages
40 | echo
41 | if [ -n "${proxy_pid}" ]; then
42 | echo "Terminating WebSockets proxy (${proxy_pid})"
43 | kill ${proxy_pid}
44 | fi
45 | }
46 |
47 | # Process Arguments
48 |
49 | # Arguments that only apply to chrooter itself
50 | while [ "$*" ]; do
51 | param=$1; shift; OPTARG=$1
52 | case $param in
53 | --listen) PORT="${OPTARG}"; shift ;;
54 | --vnc) VNC_DEST="${OPTARG}"; shift ;;
55 | --cert) CERT="${OPTARG}"; shift ;;
56 | --web) WEB="${OPTARG}"; shift ;;
57 | -h|--help) usage ;;
58 | -*) usage "Unknown chrooter option: ${param}" ;;
59 | *) break ;;
60 | esac
61 | done
62 |
63 | # Sanity checks
64 | which netstat >/dev/null 2>&1 \
65 | || die "Must have netstat installed"
66 |
67 | netstat -ltn | grep -qs "${PORT} .*LISTEN" \
68 | && die "Port ${PORT} in use. Try --listen PORT"
69 |
70 | trap "cleanup" TERM QUIT INT EXIT
71 |
72 | # Find vnc.html
73 | if [ -n "${WEB}" ]; then
74 | if [ ! -e "${WEB}/vnc.html" ]; then
75 | die "Could not find ${WEB}/vnc.html"
76 | fi
77 | elif [ -e "$(pwd)/vnc.html" ]; then
78 | WEB=$(pwd)
79 | elif [ -e "${HERE}/../vnc.html" ]; then
80 | WEB=${HERE}/../
81 | elif [ -e "${HERE}/vnc.html" ]; then
82 | WEB=${HERE}
83 | elif [ -e "${HERE}/../share/novnc/vnc.html" ]; then
84 | WEB=${HERE}/../share/novnc/
85 | else
86 | die "Could not find vnc.html"
87 | fi
88 |
89 | # Find self.pem
90 | if [ -n "${CERT}" ]; then
91 | if [ ! -e "${CERT}" ]; then
92 | die "Could not find ${CERT}"
93 | fi
94 | elif [ -e "$(pwd)/self.pem" ]; then
95 | CERT="$(pwd)/self.pem"
96 | elif [ -e "${HERE}/../self.pem" ]; then
97 | CERT="${HERE}/../self.pem"
98 | elif [ -e "${HERE}/self.pem" ]; then
99 | CERT="${HERE}/self.pem"
100 | else
101 | echo "Warning: could not find self.pem"
102 | fi
103 |
104 | echo "Starting webserver and WebSockets proxy on port ${PORT}"
105 | ${HERE}/websockify --web ${WEB} ${CERT:+--cert ${CERT}} ${PORT} ${VNC_DEST} &
106 | proxy_pid="$!"
107 | sleep 1
108 | if ! ps -p ${proxy_pid} >/dev/null; then
109 | proxy_pid=
110 | echo "Failed to start WebSockets proxy"
111 | exit 1
112 | fi
113 |
114 | echo -e "\n\nNavigate to this URL:\n"
115 | echo -e " http://$(hostname):${PORT}/vnc.html?host=$(hostname)&port=${PORT}\n"
116 | echo -e "Press Ctrl-C to exit\n\n"
117 |
118 | wait ${proxy_pid}
119 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/other/project.clj:
--------------------------------------------------------------------------------
1 | (defproject websockify "1.0.0-SNAPSHOT"
2 | :description "Clojure implementation of Websockify"
3 | :url "https://github.com/kanaka/websockify"
4 | :dependencies [[org.clojure/clojure "1.2.1"]
5 | [org.clojure/tools.cli "0.2.1"]
6 | [ring/ring-jetty-adapter "1.0.0-beta2"]
7 | [org.eclipse.jetty/jetty-websocket "7.5.4.v20111024"]
8 | [org.eclipse.jetty/jetty-server "7.5.4.v20111024"]
9 | [org.eclipse.jetty/jetty-servlet "7.5.4.v20111024"]
10 | [org.jboss.netty/netty "3.2.5.Final"]]
11 | ;:dev-dependencies [[swank-clojure "1.3.0-SNAPSHOT"]]
12 | :main websockify
13 | )
14 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/other/websocket.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #define BUFSIZE 65536
4 | #define DBUFSIZE (BUFSIZE * 3) / 4 - 20
5 |
6 | #define SERVER_HANDSHAKE_HIXIE "HTTP/1.1 101 Web Socket Protocol Handshake\r\n\
7 | Upgrade: WebSocket\r\n\
8 | Connection: Upgrade\r\n\
9 | %sWebSocket-Origin: %s\r\n\
10 | %sWebSocket-Location: %s://%s%s\r\n\
11 | %sWebSocket-Protocol: %s\r\n\
12 | \r\n%s"
13 |
14 | #define SERVER_HANDSHAKE_HYBI "HTTP/1.1 101 Switching Protocols\r\n\
15 | Upgrade: websocket\r\n\
16 | Connection: Upgrade\r\n\
17 | Sec-WebSocket-Accept: %s\r\n\
18 | Sec-WebSocket-Protocol: %s\r\n\
19 | \r\n"
20 |
21 | #define HYBI_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
22 |
23 | #define HYBI10_ACCEPTHDRLEN 29
24 |
25 | #define HIXIE_MD5_DIGEST_LENGTH 16
26 |
27 | #define POLICY_RESPONSE "\n"
28 |
29 | #define OPCODE_TEXT 0x01
30 | #define OPCODE_BINARY 0x02
31 |
32 | typedef struct {
33 | char path[1024+1];
34 | char host[1024+1];
35 | char origin[1024+1];
36 | char version[1024+1];
37 | char connection[1024+1];
38 | char protocols[1024+1];
39 | char key1[1024+1];
40 | char key2[1024+1];
41 | char key3[8+1];
42 | } headers_t;
43 |
44 | typedef struct {
45 | int sockfd;
46 | SSL_CTX *ssl_ctx;
47 | SSL *ssl;
48 | int hixie;
49 | int hybi;
50 | int opcode;
51 | headers_t *headers;
52 | char *cin_buf;
53 | char *cout_buf;
54 | char *tin_buf;
55 | char *tout_buf;
56 | } ws_ctx_t;
57 |
58 | typedef struct {
59 | int verbose;
60 | char listen_host[256];
61 | int listen_port;
62 | void (*handler)(ws_ctx_t*);
63 | int handler_id;
64 | char *cert;
65 | char *key;
66 | int ssl_only;
67 | int daemon;
68 | int run_once;
69 | } settings_t;
70 |
71 |
72 | int resolve_host(struct in_addr *sin_addr, const char *hostname);
73 |
74 | ssize_t ws_recv(ws_ctx_t *ctx, void *buf, size_t len);
75 |
76 | ssize_t ws_send(ws_ctx_t *ctx, const void *buf, size_t len);
77 |
78 | /* base64.c declarations */
79 | //int b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize);
80 | //int b64_pton(char const *src, u_char *target, size_t targsize);
81 |
82 | #define gen_handler_msg(stream, ...) \
83 | if (! settings.daemon) { \
84 | fprintf(stream, " %d: ", settings.handler_id); \
85 | fprintf(stream, __VA_ARGS__); \
86 | }
87 |
88 | #define handler_msg(...) gen_handler_msg(stdout, __VA_ARGS__);
89 | #define handler_emsg(...) gen_handler_msg(stderr, __VA_ARGS__);
90 |
91 | void traffic(const char * token);
92 |
93 | int encode_hixie(u_char const *src, size_t srclength,
94 | char *target, size_t targsize);
95 | int decode_hixie(char *src, size_t srclength,
96 | u_char *target, size_t targsize,
97 | unsigned int *opcode, unsigned int *left);
98 | int encode_hybi(u_char const *src, size_t srclength,
99 | char *target, size_t targsize, unsigned int opcode);
100 | int decode_hybi(unsigned char *src, size_t srclength,
101 | u_char *target, size_t targsize,
102 | unsigned int *opcode, unsigned int *left);
103 |
104 | void start_server();
105 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/other/websocket.rb:
--------------------------------------------------------------------------------
1 |
2 | # Python WebSocket library with support for "wss://" encryption.
3 | # Copyright 2011 Joel Martin
4 | # Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
5 | #
6 | # Supports following protocol versions:
7 | # - http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75
8 | # - http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
9 | # - http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10
10 |
11 | require 'gserver'
12 | require 'openssl'
13 | require 'stringio'
14 | require 'digest/md5'
15 | require 'digest/sha1'
16 |
17 | unless OpenSSL::SSL::SSLSocket.instance_methods.index("read_nonblock")
18 | module OpenSSL
19 | module SSL
20 | class SSLSocket
21 | alias :read_nonblock :readpartial
22 | end
23 | end
24 | end
25 | end
26 |
27 | class EClose < Exception
28 | end
29 |
30 | class WebSocketServer < GServer
31 | @@Buffer_size = 65536
32 |
33 | #
34 | # WebSocket constants
35 | #
36 | @@Server_handshake_hixie = "HTTP/1.1 101 Web Socket Protocol Handshake\r
37 | Upgrade: WebSocket\r
38 | Connection: Upgrade\r
39 | %sWebSocket-Origin: %s\r
40 | %sWebSocket-Location: %s://%s%s\r
41 | "
42 |
43 | @@Server_handshake_hybi = "HTTP/1.1 101 Switching Protocols\r
44 | Upgrade: websocket\r
45 | Connection: Upgrade\r
46 | Sec-WebSocket-Accept: %s\r
47 | "
48 | @@GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
49 |
50 |
51 | def initialize(opts)
52 | vmsg "in WebSocketServer.initialize"
53 | port = opts['listen_port']
54 | host = opts['listen_host'] || GServer::DEFAULT_HOST
55 |
56 | super(port, host)
57 | msg opts.inspect
58 | if opts['server_cert']
59 | msg "creating ssl context"
60 | @sslContext = OpenSSL::SSL::SSLContext.new
61 | @sslContext.cert = OpenSSL::X509::Certificate.new(File.open(opts['server_cert']))
62 | @sslContext.key = OpenSSL::PKey::RSA.new(File.open(opts['server_key']))
63 | @sslContext.ca_file = opts['server_cert']
64 | @sslContext.verify_mode = OpenSSL::SSL::VERIFY_NONE
65 | @sslContext.verify_depth = 0
66 | end
67 |
68 | @@client_id = 0 # Track client number total on class
69 |
70 | @verbose = opts['verbose']
71 | @opts = opts
72 | end
73 |
74 | def serve(io)
75 | @@client_id += 1
76 | msg self.inspect
77 | if @sslContext
78 | msg "Enabling SSL context"
79 | ssl = OpenSSL::SSL::SSLSocket.new(io, @sslContext)
80 | #ssl.sync_close = true
81 | #ssl.sync = true
82 | msg "SSL accepting"
83 | ssl.accept
84 | io = ssl # replace the unencrypted handle with the encrypted one
85 | end
86 |
87 | msg "initializing thread"
88 |
89 | # Initialize per thread state
90 | t = Thread.current
91 | t[:my_client_id] = @@client_id
92 | t[:send_parts] = []
93 | t[:recv_part] = nil
94 |
95 | puts "in serve, client: #{t[:my_client_id].inspect}"
96 |
97 | begin
98 | t[:client] = do_handshake(io)
99 | new_websocket_client(t[:client])
100 | rescue EClose => e
101 | msg "Client closed: #{e.message}"
102 | return
103 | rescue Exception => e
104 | msg "Uncaught exception: #{e.message}"
105 | msg "Trace: #{e.backtrace}"
106 | return
107 | end
108 |
109 | msg "Client disconnected"
110 | end
111 |
112 | #
113 | # WebSocketServer logging/output functions
114 | #
115 | def traffic(token)
116 | if @verbose then print token; STDOUT.flush; end
117 | end
118 |
119 | def msg(m)
120 | printf("% 3d: %s\n", Thread.current[:my_client_id] || 0, m)
121 | end
122 |
123 | def vmsg(m)
124 | if @verbose then msg(m) end
125 | end
126 |
127 | #
128 | # WebSocketServer general support routines
129 | #
130 | def gen_md5(h)
131 | key1 = h['sec-websocket-key1']
132 | key2 = h['sec-websocket-key2']
133 | key3 = h['key3']
134 | spaces1 = key1.count(" ")
135 | spaces2 = key2.count(" ")
136 | num1 = key1.scan(/[0-9]/).join('').to_i / spaces1
137 | num2 = key2.scan(/[0-9]/).join('').to_i / spaces2
138 |
139 | return Digest::MD5.digest([num1, num2, key3].pack('NNa8'))
140 | end
141 |
142 | def unmask(buf, hlen, length)
143 | pstart = hlen + 4
144 | mask = buf[hlen...hlen+4].each_byte.map{|b|b}
145 | data = buf[pstart...pstart+length]
146 | #data = data.bytes.zip(mask.bytes.cycle(length)).map { |d,m| d^m }
147 | i=-1
148 | data = data.each_byte.map{|b| i+=1; (b ^ mask[i % 4]).chr}.join("")
149 | return data
150 | end
151 |
152 | def encode_hybi(buf, opcode)
153 | b1 = 0x80 | (opcode & 0x0f) # FIN + opcode
154 | payload_len = buf.length
155 | if payload_len <= 125
156 | header = [b1, payload_len].pack('CC')
157 | elsif payload_len > 125 && payload_len < 65536
158 | header = [b1, 126, payload_len].pack('CCn')
159 | elsif payload_len >= 65536
160 | header = [b1, 127, payload_len >> 32,
161 | payload_len & 0xffffffff].pack('CCNN')
162 | end
163 |
164 | return [header + buf, header.length, 0]
165 | end
166 |
167 | def decode_hybi(buf)
168 | f = {'fin' => 0,
169 | 'opcode' => 0,
170 | 'hlen' => 2,
171 | 'length' => 0,
172 | 'payload' => nil,
173 | 'left' => 0,
174 | 'close_code' => nil,
175 | 'close_reason' => nil}
176 |
177 | blen = buf.length
178 | f['left'] = blen
179 |
180 | if blen < f['hlen'] then return f end # incomplete frame
181 |
182 | b1, b2 = buf.unpack('CC')
183 | f['opcode'] = b1 & 0x0f
184 | f['fin'] = (b1 & 0x80) >> 7
185 | has_mask = (b2 & 0x80) >> 7
186 |
187 | f['length'] = b2 & 0x7f
188 |
189 | if f['length'] == 126
190 | f['hlen'] = 4
191 | if blen < f['hlen'] then return f end # incomplete frame
192 | f['length'] = buf.unpack('xxn')[0]
193 | elsif f['length'] == 127
194 | f['hlen'] = 10
195 | if blen < f['hlen'] then return f end # incomplete frame
196 | top, bottom = buf.unpack('xxNN')
197 | f['length'] = (top << 32) & bottom
198 | end
199 |
200 | full_len = f['hlen'] + has_mask * 4 + f['length']
201 |
202 | if blen < full_len then return f end # incomplete frame
203 |
204 | # number of bytes that are part of the next frame(s)
205 | f['left'] = blen - full_len
206 |
207 | if has_mask > 0
208 | f['payload'] = unmask(buf, f['hlen'], f['length'])
209 | else
210 | f['payload'] = buf[f['hlen']...full_len]
211 | end
212 |
213 | # close frame
214 | if f['opcode'] == 0x08
215 | if f['length'] >= 2
216 | f['close_code'] = f['payload'].unpack('n')
217 | end
218 | if f['length'] > 3
219 | f['close_reason'] = f['payload'][2...f['payload'].length]
220 | end
221 | end
222 |
223 | return f
224 | end
225 |
226 | def encode_hixie(buf)
227 | return ["\x00" + Base64.encode64(buf).gsub(/\n/, '') + "\xff", 1, 1]
228 | end
229 |
230 | def decode_hixie(buf)
231 | last = buf.index("\377")
232 | return {'payload' => Base64.decode64(buf[1...last]),
233 | 'hlen' => 1,
234 | 'length' => last - 1,
235 | 'left' => buf.length - (last + 1)}
236 | end
237 |
238 | def send_frames(bufs)
239 | t = Thread.current
240 | if bufs.length > 0
241 | encbuf = ""
242 | bufs.each do |buf|
243 | if t[:version].start_with?("hybi")
244 | encbuf, lenhead, lentail = encode_hybi(
245 | buf, opcode=2)
246 | else
247 | encbuf, lenhead, lentail = encode_hixie(buf)
248 | end
249 |
250 | t[:send_parts] << encbuf
251 | end
252 |
253 | end
254 |
255 | while t[:send_parts].length > 0
256 | buf = t[:send_parts].shift
257 | sent = t[:client].write(buf)
258 |
259 | if sent == buf.length
260 | traffic "<"
261 | else
262 | traffic "<."
263 | t[:send_parts].unshift(buf[sent...buf.length])
264 | end
265 | end
266 |
267 | return t[:send_parts].length
268 | end
269 |
270 | # Receive and decode Websocket frames
271 | # Returns: [bufs_list, closed_string]
272 | def recv_frames()
273 | t = Thread.current
274 | closed = false
275 | bufs = []
276 |
277 | buf = t[:client].read_nonblock(@@Buffer_size)
278 |
279 | if buf.length == 0
280 | return bufs, "Client closed abrubtly"
281 | end
282 |
283 | if t[:recv_part]
284 | buf = t[:recv_part] + buf
285 | t[:recv_part] = nil
286 | end
287 |
288 | while buf.length > 0
289 | if t[:version].start_with?("hybi")
290 | frame = decode_hybi(buf)
291 |
292 | if frame['payload'] == nil
293 | traffic "}."
294 | if frame['left'] > 0
295 | t[:recv_part] = buf[-frame['left']...buf.length]
296 | end
297 | break
298 | else
299 | if frame['opcode'] == 0x8
300 | closed = "Client closed, reason: %s - %s" % [
301 | frame['close_code'], frame['close_reason']]
302 | break
303 | end
304 | end
305 | else
306 | if buf[0...2] == "\xff\x00"
307 | closed = "Client sent orderly close frame"
308 | break
309 | elsif buf[0...2] == "\x00\xff"
310 | buf = buf[2...buf.length]
311 | continue # No-op frame
312 | elsif buf.count("\xff") == 0
313 | # Partial frame
314 | traffic "}."
315 | t[:recv_part] = buf
316 | break
317 | end
318 |
319 | frame = decode_hixie(buf)
320 | end
321 |
322 | #msg "Receive frame: #{frame.inspect}"
323 |
324 | traffic "}"
325 |
326 | bufs << frame['payload']
327 |
328 | if frame['left'] > 0
329 | buf = buf[-frame['left']...buf.length]
330 | else
331 | buf = ''
332 | end
333 | end
334 |
335 | return bufs, closed
336 | end
337 |
338 |
339 | def send_close(code=nil, reason='')
340 | t = Thread.current
341 | if t[:version].start_with?("hybi")
342 | msg = ''
343 | if code
344 | msg = [reason.length, code].pack("na8")
345 | end
346 |
347 | buf, lenh, lent = encode_hybi(msg, opcode=0x08)
348 | t[:client].write(buf)
349 | elsif t[:version] == "hixie-76"
350 | buf = "\xff\x00"
351 | t[:client].write(buf)
352 | end
353 | end
354 |
355 | def do_handshake(sock)
356 |
357 | t = Thread.current
358 | stype = ""
359 |
360 | if !IO.select([sock], nil, nil, 3)
361 | raise EClose, "ignoring socket not ready"
362 | end
363 |
364 | handshake = ""
365 | msg "About to read from sock [#{sock.inspect}]"
366 | handshake = sock.read_nonblock(1024)
367 | msg "Handshake [#{handshake.inspect}]"
368 |
369 | if handshake == nil or handshake == ""
370 | raise(EClose, "ignoring empty handshake")
371 | else
372 | stype = "Plain non-SSL (ws://)"
373 | scheme = "ws"
374 | if sock.class == OpenSSL::SSL::SSLSocket
375 | stype = "SSL (wss://)"
376 | scheme = "wss"
377 | end
378 | retsock = sock
379 | end
380 |
381 | h = t[:headers] = {}
382 | hlines = handshake.split("\r\n")
383 | req_split = hlines.shift.match(/^(\w+) (\/[^\s]*) HTTP\/1\.1$/)
384 | t[:path] = req_split[2].strip
385 | hlines.each do |hline|
386 | break if hline == ""
387 | hsplit = hline.match(/^([^:]+):\s*(.+)$/)
388 | h[hsplit[1].strip.downcase] = hsplit[2]
389 | end
390 | puts "Headers: #{h.inspect}"
391 |
392 | unless h.has_key?('upgrade') &&
393 | h['upgrade'].downcase == 'websocket'
394 | raise EClose, "Non-WebSocket connection"
395 | end
396 |
397 | protocols = h.fetch("sec-websocket-protocol", h["websocket-protocol"])
398 | ver = h.fetch('sec-websocket-version', nil)
399 |
400 | # HyBi/IETF vesrion of the protocol
401 |
402 | # HyBi 07 reports version 7
403 | # HyBi 08 - 12 report version 8
404 | # HyBi 13 and up report version 13
405 | if ['7', '8', '13'].include?(ver)
406 | t[:version] = "hybi-%02d" % [ver.to_i]
407 | else
408 | raise EClose, "Unsupported protocol version %s" % [ver]
409 | end
410 |
411 | key = h['sec-websocket-key']
412 |
413 | # Generate the hash value for the accpet header
414 | accept = Base64.encode64(
415 | Digest::SHA1.digest(key + @@GUID)).gsub(/\n/, '')
416 |
417 | response = @@Server_handshake_hybi % [accept]
418 |
419 | response += "\r\n"
420 |
421 | msg "%s WebSocket connection" % [stype]
422 | msg "Version %s" % [t[:version]]
423 | if t[:path] then msg "Path: '%s'" % [t[:path]] end
424 |
425 | #puts "sending reponse #{response.inspect}"
426 | retsock.write(response)
427 |
428 | # Return the WebSocket socket which may be SSL wrapped
429 | return retsock
430 | end
431 |
432 | end
433 |
434 | # vim: sw=2
435 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/other/websockify.c:
--------------------------------------------------------------------------------
1 | /*
2 | * A WebSocket to TCP socket proxy with support for "wss://" encryption.
3 | * Copyright 2010 Joel Martin
4 | * Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
5 | *
6 | * You can make a cert/key with openssl using:
7 | * openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem
8 | * as taken from http://docs.python.org/dev/library/ssl.html#certificates
9 | */
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include "websocket.h"
23 |
24 | char traffic_legend[] = "\n\
25 | Traffic Legend:\n\
26 | } - Client receive\n\
27 | }. - Client receive partial\n\
28 | { - Target receive\n\
29 | \n\
30 | > - Target send\n\
31 | >. - Target send partial\n\
32 | < - Client send\n\
33 | <. - Client send partial\n\
34 | ";
35 |
36 | char USAGE[] = "Usage: [options] " \
37 | "[source_addr:]source_port target_addr:target_port\n\n" \
38 | " --verbose|-v verbose messages and per frame traffic\n" \
39 | " --daemon|-D become a daemon (background process)\n" \
40 | " --run-once handle a single WebSocket connection and exit\n" \
41 | " --cert CERT SSL certificate file\n" \
42 | " --key KEY SSL key file (if separate from cert)\n" \
43 | " --ssl-only disallow non-encrypted connections";
44 |
45 | #define usage(fmt, args...) \
46 | fprintf(stderr, "%s\n\n", USAGE); \
47 | fprintf(stderr, fmt , ## args); \
48 | exit(1);
49 |
50 | char target_host[256];
51 | int target_port;
52 |
53 | extern int pipe_error;
54 | extern settings_t settings;
55 |
56 | void do_proxy(ws_ctx_t *ws_ctx, int target) {
57 | fd_set rlist, wlist, elist;
58 | struct timeval tv;
59 | int i, maxfd, client = ws_ctx->sockfd;
60 | unsigned int opcode, left, ret;
61 | unsigned int tout_start, tout_end, cout_start, cout_end;
62 | unsigned int tin_start, tin_end;
63 | ssize_t len, bytes;
64 |
65 | tout_start = tout_end = cout_start = cout_end;
66 | tin_start = tin_end = 0;
67 | maxfd = client > target ? client+1 : target+1;
68 |
69 | while (1) {
70 | tv.tv_sec = 1;
71 | tv.tv_usec = 0;
72 |
73 | FD_ZERO(&rlist);
74 | FD_ZERO(&wlist);
75 | FD_ZERO(&elist);
76 |
77 | FD_SET(client, &elist);
78 | FD_SET(target, &elist);
79 |
80 | if (tout_end == tout_start) {
81 | // Nothing queued for target, so read from client
82 | FD_SET(client, &rlist);
83 | } else {
84 | // Data queued for target, so write to it
85 | FD_SET(target, &wlist);
86 | }
87 | if (cout_end == cout_start) {
88 | // Nothing queued for client, so read from target
89 | FD_SET(target, &rlist);
90 | } else {
91 | // Data queued for client, so write to it
92 | FD_SET(client, &wlist);
93 | }
94 |
95 | ret = select(maxfd, &rlist, &wlist, &elist, &tv);
96 | if (pipe_error) { break; }
97 |
98 | if (FD_ISSET(target, &elist)) {
99 | handler_emsg("target exception\n");
100 | break;
101 | }
102 | if (FD_ISSET(client, &elist)) {
103 | handler_emsg("client exception\n");
104 | break;
105 | }
106 |
107 | if (ret == -1) {
108 | handler_emsg("select(): %s\n", strerror(errno));
109 | break;
110 | } else if (ret == 0) {
111 | //handler_emsg("select timeout\n");
112 | continue;
113 | }
114 |
115 | if (FD_ISSET(target, &wlist)) {
116 | len = tout_end-tout_start;
117 | bytes = send(target, ws_ctx->tout_buf + tout_start, len, 0);
118 | if (pipe_error) { break; }
119 | if (bytes < 0) {
120 | handler_emsg("target connection error: %s\n",
121 | strerror(errno));
122 | break;
123 | }
124 | tout_start += bytes;
125 | if (tout_start >= tout_end) {
126 | tout_start = tout_end = 0;
127 | traffic(">");
128 | } else {
129 | traffic(">.");
130 | }
131 | }
132 |
133 | if (FD_ISSET(client, &wlist)) {
134 | len = cout_end-cout_start;
135 | bytes = ws_send(ws_ctx, ws_ctx->cout_buf + cout_start, len);
136 | if (pipe_error) { break; }
137 | if (len < 3) {
138 | handler_emsg("len: %d, bytes: %d: %d\n",
139 | (int) len, (int) bytes,
140 | (int) *(ws_ctx->cout_buf + cout_start));
141 | }
142 | cout_start += bytes;
143 | if (cout_start >= cout_end) {
144 | cout_start = cout_end = 0;
145 | traffic("<");
146 | } else {
147 | traffic("<.");
148 | }
149 | }
150 |
151 | if (FD_ISSET(target, &rlist)) {
152 | bytes = recv(target, ws_ctx->cin_buf, DBUFSIZE , 0);
153 | if (pipe_error) { break; }
154 | if (bytes <= 0) {
155 | handler_emsg("target closed connection\n");
156 | break;
157 | }
158 | cout_start = 0;
159 | if (ws_ctx->hybi) {
160 | cout_end = encode_hybi(ws_ctx->cin_buf, bytes,
161 | ws_ctx->cout_buf, BUFSIZE, ws_ctx->opcode);
162 | } else {
163 | cout_end = encode_hixie(ws_ctx->cin_buf, bytes,
164 | ws_ctx->cout_buf, BUFSIZE);
165 | }
166 | /*
167 | printf("encoded: ");
168 | for (i=0; i< cout_end; i++) {
169 | printf("%u,", (unsigned char) *(ws_ctx->cout_buf+i));
170 | }
171 | printf("\n");
172 | */
173 | if (cout_end < 0) {
174 | handler_emsg("encoding error\n");
175 | break;
176 | }
177 | traffic("{");
178 | }
179 |
180 | if (FD_ISSET(client, &rlist)) {
181 | bytes = ws_recv(ws_ctx, ws_ctx->tin_buf + tin_end, BUFSIZE-1);
182 | if (pipe_error) { break; }
183 | if (bytes <= 0) {
184 | handler_emsg("client closed connection\n");
185 | break;
186 | }
187 | tin_end += bytes;
188 | /*
189 | printf("before decode: ");
190 | for (i=0; i< bytes; i++) {
191 | printf("%u,", (unsigned char) *(ws_ctx->tin_buf+i));
192 | }
193 | printf("\n");
194 | */
195 | if (ws_ctx->hybi) {
196 | len = decode_hybi(ws_ctx->tin_buf + tin_start,
197 | tin_end-tin_start,
198 | ws_ctx->tout_buf, BUFSIZE-1,
199 | &opcode, &left);
200 | } else {
201 | len = decode_hixie(ws_ctx->tin_buf + tin_start,
202 | tin_end-tin_start,
203 | ws_ctx->tout_buf, BUFSIZE-1,
204 | &opcode, &left);
205 | }
206 |
207 | if (opcode == 8) {
208 | handler_msg("client sent orderly close frame\n");
209 | break;
210 | }
211 |
212 | /*
213 | printf("decoded: ");
214 | for (i=0; i< len; i++) {
215 | printf("%u,", (unsigned char) *(ws_ctx->tout_buf+i));
216 | }
217 | printf("\n");
218 | */
219 | if (len < 0) {
220 | handler_emsg("decoding error\n");
221 | break;
222 | }
223 | if (left) {
224 | tin_start = tin_end - left;
225 | //printf("partial frame from client");
226 | } else {
227 | tin_start = 0;
228 | tin_end = 0;
229 | }
230 |
231 | traffic("}");
232 | tout_start = 0;
233 | tout_end = len;
234 | }
235 | }
236 | }
237 |
238 | void proxy_handler(ws_ctx_t *ws_ctx) {
239 | int tsock = 0;
240 | struct sockaddr_in taddr;
241 |
242 | handler_msg("connecting to: %s:%d\n", target_host, target_port);
243 |
244 | tsock = socket(AF_INET, SOCK_STREAM, 0);
245 | if (tsock < 0) {
246 | handler_emsg("Could not create target socket: %s\n",
247 | strerror(errno));
248 | return;
249 | }
250 | bzero((char *) &taddr, sizeof(taddr));
251 | taddr.sin_family = AF_INET;
252 | taddr.sin_port = htons(target_port);
253 |
254 | /* Resolve target address */
255 | if (resolve_host(&taddr.sin_addr, target_host) < -1) {
256 | handler_emsg("Could not resolve target address: %s\n",
257 | strerror(errno));
258 | }
259 |
260 | if (connect(tsock, (struct sockaddr *) &taddr, sizeof(taddr)) < 0) {
261 | handler_emsg("Could not connect to target: %s\n",
262 | strerror(errno));
263 | close(tsock);
264 | return;
265 | }
266 |
267 | if ((settings.verbose) && (! settings.daemon)) {
268 | printf("%s", traffic_legend);
269 | }
270 |
271 | do_proxy(ws_ctx, tsock);
272 |
273 | shutdown(tsock, SHUT_RDWR);
274 | close(tsock);
275 | }
276 |
277 | int main(int argc, char *argv[])
278 | {
279 | int fd, c, option_index = 0;
280 | static int ssl_only = 0, daemon = 0, run_once = 0, verbose = 0;
281 | char *found;
282 | static struct option long_options[] = {
283 | {"verbose", no_argument, &verbose, 'v'},
284 | {"ssl-only", no_argument, &ssl_only, 1 },
285 | {"daemon", no_argument, &daemon, 'D'},
286 | /* ---- */
287 | {"run-once", no_argument, 0, 'r'},
288 | {"cert", required_argument, 0, 'c'},
289 | {"key", required_argument, 0, 'k'},
290 | {0, 0, 0, 0}
291 | };
292 |
293 | settings.cert = realpath("self.pem", NULL);
294 | if (!settings.cert) {
295 | /* Make sure it's always set to something */
296 | settings.cert = "self.pem";
297 | }
298 | settings.key = "";
299 |
300 | while (1) {
301 | c = getopt_long (argc, argv, "vDrc:k:",
302 | long_options, &option_index);
303 |
304 | /* Detect the end */
305 | if (c == -1) { break; }
306 |
307 | switch (c) {
308 | case 0:
309 | break; // ignore
310 | case 1:
311 | break; // ignore
312 | case 'v':
313 | verbose = 1;
314 | break;
315 | case 'D':
316 | daemon = 1;
317 | break;
318 | case 'r':
319 | run_once = 1;
320 | break;
321 | case 'c':
322 | settings.cert = realpath(optarg, NULL);
323 | if (! settings.cert) {
324 | usage("No cert file at %s\n", optarg);
325 | }
326 | break;
327 | case 'k':
328 | settings.key = realpath(optarg, NULL);
329 | if (! settings.key) {
330 | usage("No key file at %s\n", optarg);
331 | }
332 | break;
333 | default:
334 | usage("");
335 | }
336 | }
337 | settings.verbose = verbose;
338 | settings.ssl_only = ssl_only;
339 | settings.daemon = daemon;
340 | settings.run_once = run_once;
341 |
342 | if ((argc-optind) != 2) {
343 | usage("Invalid number of arguments\n");
344 | }
345 |
346 | found = strstr(argv[optind], ":");
347 | if (found) {
348 | memcpy(settings.listen_host, argv[optind], found-argv[optind]);
349 | settings.listen_port = strtol(found+1, NULL, 10);
350 | } else {
351 | settings.listen_host[0] = '\0';
352 | settings.listen_port = strtol(argv[optind], NULL, 10);
353 | }
354 | optind++;
355 | if (settings.listen_port == 0) {
356 | usage("Could not parse listen_port\n");
357 | }
358 |
359 | found = strstr(argv[optind], ":");
360 | if (found) {
361 | memcpy(target_host, argv[optind], found-argv[optind]);
362 | target_port = strtol(found+1, NULL, 10);
363 | } else {
364 | usage("Target argument must be host:port\n");
365 | }
366 | if (target_port == 0) {
367 | usage("Could not parse target port\n");
368 | }
369 |
370 | if (ssl_only) {
371 | if (access(settings.cert, R_OK) != 0) {
372 | usage("SSL only and cert file '%s' not found\n", settings.cert);
373 | }
374 | } else if (access(settings.cert, R_OK) != 0) {
375 | fprintf(stderr, "Warning: '%s' not found\n", settings.cert);
376 | }
377 |
378 | //printf(" verbose: %d\n", settings.verbose);
379 | //printf(" ssl_only: %d\n", settings.ssl_only);
380 | //printf(" daemon: %d\n", settings.daemon);
381 | //printf(" run_once: %d\n", settings.run_once);
382 | //printf(" cert: %s\n", settings.cert);
383 | //printf(" key: %s\n", settings.key);
384 |
385 | settings.handler = proxy_handler;
386 | start_server();
387 |
388 | }
389 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/other/websockify.clj:
--------------------------------------------------------------------------------
1 | (ns websockify
2 | ;(:use ring.adapter.jetty)
3 | (:require [clojure.tools.cli :as cli]
4 | [clojure.string :as string])
5 |
6 | (:import
7 |
8 | ;; Netty TCP Client
9 | [java.util.concurrent Executors]
10 | [java.net InetSocketAddress]
11 | [org.jboss.netty.channel
12 | Channels SimpleChannelHandler ChannelPipelineFactory]
13 | [org.jboss.netty.buffer ChannelBuffers]
14 | [org.jboss.netty.channel.socket.nio NioClientSocketChannelFactory]
15 | [org.jboss.netty.bootstrap ClientBootstrap]
16 | [org.jboss.netty.handler.codec.base64 Base64]
17 | [org.jboss.netty.util CharsetUtil]
18 |
19 | ;; Jetty WebSocket Server
20 | [org.eclipse.jetty.server Server]
21 | [org.eclipse.jetty.server.nio BlockingChannelConnector]
22 | [org.eclipse.jetty.servlet
23 | ServletContextHandler ServletHolder DefaultServlet]
24 | [org.eclipse.jetty.websocket
25 | WebSocket WebSocket$OnTextMessage
26 | WebSocketClientFactory WebSocketClient WebSocketServlet]))
27 |
28 |
29 | ;; TCP / NIO
30 |
31 | ;; (defn tcp-channel [host port]
32 | ;; (try
33 | ;; (let [address (InetSocketAddress. host port)
34 | ;; channel (doto (SocketChannel/open)
35 | ;; (.connect address))]
36 | ;; channel)
37 | ;; (catch Exception e
38 | ;; (println (str "Failed to connect to'" host ":" port "':" e))
39 | ;; nil)))
40 |
41 | ;; http://docs.jboss.org/netty/3.2/guide/html/start.html#d0e51
42 | ;; http://stackoverflow.com/questions/5453602/highly-concurrent-http-with-netty-and-nio
43 | ;; https://github.com/datskos/ring-netty-adapter/blob/master/src/ring/adapter/netty.clj
44 |
45 |
46 | (defn netty-client [host port open close message]
47 | (let [handler (proxy [SimpleChannelHandler] []
48 | (channelConnected [ctx e] (open ctx e))
49 | (channelDisconnected [ctx e] (close ctx e))
50 | (messageReceived [ctx e] (message ctx e))
51 | (exceptionCaught [ctx e]
52 | (println "exceptionCaught:" e)))
53 | pipeline (proxy [ChannelPipelineFactory] []
54 | (getPipeline []
55 | (doto (Channels/pipeline)
56 | (.addLast "handler" handler))))
57 | bootstrap (doto (ClientBootstrap.
58 | (NioClientSocketChannelFactory.
59 | (Executors/newCachedThreadPool)
60 | (Executors/newCachedThreadPool)))
61 | (.setPipelineFactory pipeline)
62 | (.setOption "tcpNoDelay" true)
63 | (.setOption "keepAlive" true))
64 | channel-future (.connect bootstrap (InetSocketAddress. host port))
65 | channel (.. channel-future (awaitUninterruptibly) (getChannel))]
66 | channel))
67 |
68 |
69 |
70 | ;; WebSockets
71 |
72 | ;; http://wiki.eclipse.org/Jetty/Feature/WebSockets
73 | (defn make-websocket-servlet [open close message]
74 | (proxy [WebSocketServlet] []
75 | (doGet [request response]
76 | ;;(println "doGet" request)
77 | (.. (proxy-super getServletContext)
78 | (getNamedDispatcher (proxy-super getServletName))
79 | (forward request response)))
80 | (doWebSocketConnect [request response]
81 | (println "doWebSocketConnect")
82 | (reify WebSocket$OnTextMessage
83 | (onOpen [this connection] (open this connection))
84 | (onClose [this code message] (close this code message))
85 | (onMessage [this data] (message this data))))))
86 |
87 | (defn websocket-server
88 | [port & {:keys [open close message ws-path web]
89 | :or {open (fn [_ conn]
90 | (println "New websocket client:" conn))
91 | close (fn [_ code reason]
92 | (println "Websocket client closed:" code reason))
93 | message (fn [_ data]
94 | (println "Websocket message:" data))
95 |
96 | ws-path "/websocket"}}]
97 | (let [http-servlet (doto (ServletHolder. (DefaultServlet.))
98 | (.setInitParameter "dirAllowed" "true")
99 | (.setInitParameter "resourceBase" web))
100 | ws-servlet (ServletHolder.
101 | (make-websocket-servlet open close message))
102 | context (doto (ServletContextHandler.)
103 | (.setContextPath "/")
104 | (.addServlet ws-servlet ws-path))
105 | connector (doto (BlockingChannelConnector.)
106 | (.setPort port)
107 | (.setMaxIdleTime Integer/MAX_VALUE))
108 | server (doto (Server.)
109 | (.setHandler context)
110 | (.addConnector connector))]
111 |
112 | (when web (.addServlet context http-servlet "/"))
113 | server))
114 |
115 |
116 |
117 | ;; Websockify
118 |
119 | (defonce settings (atom {}))
120 |
121 | ;; WebSocket client to TCP target mappings
122 |
123 | (defonce clients (atom {}))
124 | (defonce targets (atom {}))
125 |
126 |
127 | (defn target-open [ctx e]
128 | (println "Connected to target")
129 | #_(println "channelConnected:" e))
130 |
131 | (defn target-close [ctx e]
132 | #_(println "channelDisconnected:" e)
133 | (println "Target closed")
134 | (when-let [channel (get @targets (.getChannel ctx))]
135 | (.disconnect channel)))
136 |
137 | (defn target-message [ctx e]
138 | (let [channel (.getChannel ctx)
139 | client (get @targets channel)
140 | msg (.getMessage e)
141 | len (.readableBytes msg)
142 | b64 (Base64/encode msg false)
143 | blen (.readableBytes b64)]
144 | #_(println "received" len "bytes from target")
145 | #_(println "target receive:" (.toString msg 0 len CharsetUtil/UTF_8))
146 | #_(println "sending to client:" (.toString b64 0 blen CharsetUtil/UTF_8))
147 | (.sendMessage client (.toString b64 0 blen CharsetUtil/UTF_8))))
148 |
149 | (defn client-open [this connection]
150 | #_(println "Got WebSocket connection:" connection)
151 | (println "New client")
152 | (let [target (netty-client
153 | (:target-host @settings)
154 | (:target-port @settings)
155 | target-open target-close target-message)]
156 | (swap! clients assoc this {:client connection
157 | :target target})
158 | (swap! targets assoc target connection)))
159 |
160 | (defn client-close [this code message]
161 | (println "WebSocket connection closed")
162 | (when-let [target (:target (get @clients this))]
163 | (println "Closing target")
164 | (.close target)
165 | (println "Target closed")
166 | (swap! targets dissoc target))
167 | (swap! clients dissoc this))
168 |
169 | (defn client-message [this data]
170 | #_(println "WebSocket onMessage:" data)
171 | (let [target (:target (get @clients this))
172 | cbuf (ChannelBuffers/copiedBuffer data CharsetUtil/UTF_8)
173 | decbuf (Base64/decode cbuf)
174 | rlen (.readableBytes decbuf)]
175 | #_(println "Sending" rlen "bytes to target")
176 | #_(println "Sending to target:" (.toString decbuf 0 rlen CharsetUtil/UTF_8))
177 | (.write target decbuf)))
178 |
179 | (defn start-websockify
180 | [& {:keys [listen-port target-host target-port web]
181 | :or {listen-port 6080
182 | target-host "localhost"
183 | target-port 5900
184 | }}]
185 |
186 | (reset! clients {})
187 | (reset! targets {})
188 |
189 | (reset! settings {:target-host target-host
190 | :target-port target-port})
191 | (let [server (websocket-server listen-port
192 | :web web
193 | :ws-path "/websockify"
194 | :open client-open
195 | :close client-close
196 | :message client-message)]
197 |
198 | (.start server)
199 |
200 | (if web
201 | (println "Serving web requests from:" web)
202 | (println "Not serving web requests"))
203 |
204 | (defn stop-websockify []
205 | (doseq [client (vals @clients)]
206 | (.disconnect (:client client))
207 | (.close (:target client)))
208 | (.stop server)
209 | (reset! clients {})
210 | (reset! targets {})
211 | nil)))
212 |
213 | (defn -main [& args]
214 | (let [[options args banner]
215 | (cli/cli
216 | args
217 | ["-v" "--[no-]verbose" "Verbose output"]
218 | ["--web" "Run webserver with root at given location"]
219 | ["-h" "--help" "Show help" :default false :flag true]
220 | )]
221 | (when (or (:help options)
222 | (not= 2 (count args)))
223 | (println banner)
224 | (System/exit 0))
225 | (println options)
226 | (println args)
227 | (let [target (second args)
228 | [target-host target-port] (string/split target #":")]
229 | (start-websockify :listen-port (Integer/parseInt (first args))
230 | :target-host target-host
231 | :target-port (Integer/parseInt target-port)
232 | :web (:web options))))
233 | nil)
--------------------------------------------------------------------------------
/vnc/utils/websockify/other/websockify.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | # A WebSocket to TCP socket proxy
4 | # Copyright 2011 Joel Martin
5 | # Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
6 |
7 | require 'socket'
8 | $: << "other"
9 | $: << "../other"
10 | require 'websocket'
11 | require 'optparse'
12 |
13 | # Proxy traffic to and from a WebSockets client to a normal TCP
14 | # socket server target. All traffic to/from the client is base64
15 | # encoded/decoded to allow binary data to be sent/received to/from
16 | # the target.
17 | class WebSocketProxy < WebSocketServer
18 |
19 | @@Traffic_legend = "
20 | Traffic Legend:
21 | } - Client receive
22 | }. - Client receive partial
23 | { - Target receive
24 |
25 | > - Target send
26 | >. - Target send partial
27 | < - Client send
28 | <. - Client send partial
29 | "
30 |
31 |
32 | def initialize(opts)
33 | vmsg "in WebSocketProxy.initialize"
34 |
35 | super(opts)
36 |
37 | @target_host = opts["target_host"]
38 | @target_port = opts["target_port"]
39 | end
40 |
41 | # Echo back whatever is received
42 | def new_websocket_client(client)
43 |
44 | msg "connecting to: %s:%s" % [@target_host, @target_port]
45 | tsock = TCPSocket.open(@target_host, @target_port)
46 |
47 | if @verbose then puts @@Traffic_legend end
48 |
49 | begin
50 | do_proxy(client, tsock)
51 | rescue
52 | tsock.shutdown(Socket::SHUT_RDWR)
53 | tsock.close
54 | raise
55 | end
56 | end
57 |
58 | # Proxy client WebSocket to normal target socket.
59 | def do_proxy(client, target)
60 | cqueue = []
61 | c_pend = 0
62 | tqueue = []
63 | rlist = [client, target]
64 |
65 | loop do
66 | wlist = []
67 |
68 | if tqueue.length > 0
69 | wlist << target
70 | end
71 | if cqueue.length > 0 || c_pend > 0
72 | wlist << client
73 | end
74 |
75 | ins, outs, excepts = IO.select(rlist, wlist, nil, 0.001)
76 | if excepts && excepts.length > 0
77 | raise Exception, "Socket exception"
78 | end
79 |
80 | # Send queued client data to the target
81 | if outs && outs.include?(target)
82 | dat = tqueue.shift
83 | sent = target.send(dat, 0)
84 | if sent == dat.length
85 | traffic ">"
86 | else
87 | tqueue.unshift(dat[sent...dat.length])
88 | traffic ".>"
89 | end
90 | end
91 |
92 | # Receive target data and queue for the client
93 | if ins && ins.include?(target)
94 | buf = target.recv(@@Buffer_size)
95 | if buf.length == 0
96 | raise EClose, "Target closed"
97 | end
98 |
99 | cqueue << buf
100 | traffic "{"
101 | end
102 |
103 | # Encode and send queued data to the client
104 | if outs && outs.include?(client)
105 | c_pend = send_frames(cqueue)
106 | cqueue = []
107 | end
108 |
109 | # Receive client data, decode it, and send it back
110 | if ins && ins.include?(client)
111 | frames, closed = recv_frames
112 | tqueue += frames
113 |
114 | if closed
115 | send_close
116 | raise EClose, closed
117 | end
118 | end
119 |
120 | end # loop
121 | end
122 | end
123 |
124 | # Parse parameters
125 | opts = {}
126 | parser = OptionParser.new do |o|
127 | o.on('--verbose', '-v') { |b| opts['verbose'] = b }
128 | o.parse!
129 | end
130 |
131 | if ARGV.length < 2
132 | puts "Too few arguments"
133 | exit 2
134 | end
135 |
136 | # Parse host:port and convert ports to numbers
137 | if ARGV[0].count(":") > 0
138 | opts['listen_host'], _, opts['listen_port'] = ARGV[0].rpartition(':')
139 | else
140 | opts['listen_host'], opts['listen_port'] = nil, ARGV[0]
141 | end
142 |
143 | begin
144 | opts['listen_port'] = opts['listen_port'].to_i
145 | rescue
146 | puts "Error parsing listen port"
147 | exit 2
148 | end
149 |
150 | if ARGV[1].count(":") > 0
151 | opts['target_host'], _, opts['target_port'] = ARGV[1].rpartition(':')
152 | else
153 | puts "Error parsing target"
154 | exit 2
155 | end
156 |
157 | begin
158 | opts['target_port'] = opts['target_port'].to_i
159 | rescue
160 | puts "Error parsing target port"
161 | exit 2
162 | end
163 |
164 | puts "Starting server on #{opts['listen_host']}:#{opts['listen_port']}"
165 | server = WebSocketProxy.new(opts)
166 | server.start(100)
167 | server.join
168 |
169 | puts "Server has been terminated"
170 |
171 | # vim: sw=2
172 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/other/wswrap:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | usage() {
4 | echo "Usage: $(basename $0) PORT CMDLINE"
5 | echo
6 | echo " PORT Port to wrap with WebSockets support"
7 | echo " CMDLINE Command line to wrap"
8 | exit 2
9 | }
10 |
11 | # Parameter defaults
12 | mydir=$(readlink -f $(dirname ${0}))
13 |
14 | # Process parameters
15 | #while [ "${1}" != "${1#-}" ]; do
16 | # param=$1; shift
17 | #done
18 |
19 | export WSWRAP_PORT="${1}"; shift
20 |
21 | LD_PRELOAD=${mydir}/wswrapper.so "${@}"
22 |
23 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/rebind:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | usage() {
4 | echo "Usage: $(basename $0) OLD_PORT NEW_PORT COMMAND_LINE"
5 | echo
6 | echo "Launch COMMAND_LINE, but intercept system calls to bind"
7 | echo "to OLD_PORT and instead bind them to localhost:NEW_PORT"
8 | exit 2
9 | }
10 |
11 | # Parameter defaults
12 | mydir=$(readlink -f $(dirname ${0}))
13 |
14 | export REBIND_PORT_OLD="${1}"; shift
15 | export REBIND_PORT_NEW="${1}"; shift
16 |
17 | LD_PRELOAD=${mydir}/rebind.so "${@}"
18 |
19 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/rebind.c:
--------------------------------------------------------------------------------
1 | /*
2 | * rebind: Intercept bind calls and bind to a different port
3 | * Copyright 2010 Joel Martin
4 | * Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
5 | *
6 | * Overload (LD_PRELOAD) bind system call. If REBIND_PORT_OLD and
7 | * REBIND_PORT_NEW environment variables are set then bind on the new
8 | * port (of localhost) instead of the old port.
9 | *
10 | * This allows a bridge/proxy (such as websockify) to run on the old port and
11 | * translate traffic to/from the new port.
12 | *
13 | * Usage:
14 | * LD_PRELOAD=./rebind.so \
15 | * REBIND_PORT_OLD=23 \
16 | * REBIND_PORT_NEW=2023 \
17 | * program
18 | */
19 |
20 | //#define DO_DEBUG 1
21 |
22 | #include
23 | #include
24 |
25 | #define __USE_GNU 1 // Pull in RTLD_NEXT
26 | #include
27 |
28 | #include
29 | #include
30 |
31 |
32 | #if defined(DO_DEBUG)
33 | #define DEBUG(...) \
34 | fprintf(stderr, "rebind: "); \
35 | fprintf(stderr, __VA_ARGS__);
36 | #else
37 | #define DEBUG(...)
38 | #endif
39 |
40 |
41 | int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
42 | {
43 | static void * (*func)();
44 | int do_move = 0;
45 | struct sockaddr_in * addr_in = (struct sockaddr_in *)addr;
46 | struct sockaddr_in addr_tmp;
47 | socklen_t addrlen_tmp;
48 | char * PORT_OLD, * PORT_NEW, * end1, * end2;
49 | int ret, oldport, newport, askport = htons(addr_in->sin_port);
50 | uint32_t askaddr = htons(addr_in->sin_addr.s_addr);
51 | if (!func) func = (void *(*)()) dlsym(RTLD_NEXT, "bind");
52 |
53 | DEBUG(">> bind(%d, _, %d), askaddr %d, askport %d\n",
54 | sockfd, addrlen, askaddr, askport);
55 |
56 | /* Determine if we should move this socket */
57 | if (addr_in->sin_family == AF_INET) {
58 | // TODO: support IPv6
59 | PORT_OLD = getenv("REBIND_OLD_PORT");
60 | PORT_NEW = getenv("REBIND_NEW_PORT");
61 | if (PORT_OLD && (*PORT_OLD != '\0') &&
62 | PORT_NEW && (*PORT_NEW != '\0')) {
63 | oldport = strtol(PORT_OLD, &end1, 10);
64 | newport = strtol(PORT_NEW, &end2, 10);
65 | if (oldport && (*end1 == '\0') &&
66 | newport && (*end2 == '\0') &&
67 | (oldport == askport)) {
68 | do_move = 1;
69 | }
70 | }
71 | }
72 |
73 | if (! do_move) {
74 | /* Just pass everything right through to the real bind */
75 | ret = (long) func(sockfd, addr, addrlen);
76 | DEBUG("<< bind(%d, _, %d) ret %d\n", sockfd, addrlen, ret);
77 | return ret;
78 | }
79 |
80 | DEBUG("binding fd %d on localhost:%d instead of 0x%x:%d\n",
81 | sockfd, newport, ntohl(addr_in->sin_addr.s_addr), oldport);
82 |
83 | /* Use a temporary location for the new address information */
84 | addrlen_tmp = sizeof(addr_tmp);
85 | memcpy(&addr_tmp, addr, addrlen_tmp);
86 |
87 | /* Bind to other port on the loopback instead */
88 | addr_tmp.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
89 | addr_tmp.sin_port = htons(newport);
90 | ret = (long) func(sockfd, &addr_tmp, addrlen_tmp);
91 |
92 | DEBUG("<< bind(%d, _, %d) ret %d\n", sockfd, addrlen, ret);
93 | return ret;
94 | }
95 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/run:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import websockify
4 |
5 | if __name__ == '__main__':
6 | websockify.websocketproxy.websockify_init()
7 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 |
3 | version = '0.8.0'
4 | name = 'websockify'
5 | long_description = open("README.md").read() + "\n" + \
6 | open("CHANGES.txt").read() + "\n"
7 |
8 | setup(name=name,
9 | version=version,
10 | description="Websockify.",
11 | long_description=long_description,
12 | classifiers=[
13 | "Programming Language :: Python",
14 | "Programming Language :: Python :: 2",
15 | "Programming Language :: Python :: 2.6",
16 | "Programming Language :: Python :: 2.7",
17 | "Programming Language :: Python :: 3",
18 | "Programming Language :: Python :: 3.3",
19 | "Programming Language :: Python :: 3.4"
20 | ],
21 | data_files=[('share/websockify/include',
22 | ['include/util.js',
23 | 'include/websock.js'])],
24 | keywords='noVNC websockify',
25 | license='LGPLv3',
26 | url="https://github.com/kanaka/websockify",
27 | author="Joel Martin",
28 | author_email="github@martintribe.org",
29 |
30 | packages=['websockify'],
31 | include_package_data=True,
32 | install_requires=['numpy'],
33 | zip_safe=False,
34 | entry_points={
35 | 'console_scripts': [
36 | 'websockify = websockify.websocketproxy:websockify_init',
37 | ]
38 | },
39 | )
40 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/test-requirements.txt:
--------------------------------------------------------------------------------
1 | mox3
2 | nose
3 | jwcrypto;python_version>="2.7"
4 | enum34;python_version=="3.3"
5 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/tox.ini:
--------------------------------------------------------------------------------
1 | # Tox (http://tox.testrun.org/) is a tool for running tests
2 | # in multiple virtualenvs. This configuration file will run the
3 | # test suite on all supported python versions. To use it, "pip install tox"
4 | # and then run "tox" from this directory.
5 |
6 | [tox]
7 | envlist = py24,py26,py27,py33,py34
8 |
9 | [testenv]
10 | commands = nosetests {posargs}
11 | deps = -r{toxinidir}/test-requirements.txt
12 |
13 | # At some point we should enable this since tox expects it to exist but
14 | # the code will need pep8ising first.
15 | #[testenv:pep8]
16 | #commands = flake8
17 | #dep = flake8
18 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/websockify.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import websockify
4 |
5 | if __name__ == '__main__':
6 | websockify.websocketproxy.websockify_init()
7 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/websockify/__init__.py:
--------------------------------------------------------------------------------
1 | from websockify.websocket import *
2 | from websockify.websocketproxy import *
3 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/websockify/auth_plugins.py:
--------------------------------------------------------------------------------
1 | class BasePlugin(object):
2 | def __init__(self, src=None):
3 | self.source = src
4 |
5 | def authenticate(self, headers, target_host, target_port):
6 | pass
7 |
8 |
9 | class AuthenticationError(Exception):
10 | def __init__(self, log_msg=None, response_code=403, response_headers={}, response_msg=None):
11 | self.code = response_code
12 | self.headers = response_headers
13 | self.msg = response_msg
14 |
15 | if log_msg is None:
16 | log_msg = response_msg
17 |
18 | super(AuthenticationError, self).__init__('%s %s' % (self.code, log_msg))
19 |
20 |
21 | class InvalidOriginError(AuthenticationError):
22 | def __init__(self, expected, actual):
23 | self.expected_origin = expected
24 | self.actual_origin = actual
25 |
26 | super(InvalidOriginError, self).__init__(
27 | response_msg='Invalid Origin',
28 | log_msg="Invalid Origin Header: Expected one of "
29 | "%s, got '%s'" % (expected, actual))
30 |
31 |
32 | class BasicHTTPAuth(object):
33 | """Verifies Basic Auth headers. Specify src as username:password"""
34 |
35 | def __init__(self, src=None):
36 | self.src = src
37 |
38 | def authenticate(self, headers, target_host, target_port):
39 | import base64
40 | auth_header = headers.get('Authorization')
41 | if auth_header:
42 | if not auth_header.startswith('Basic '):
43 | self.auth_error()
44 |
45 | try:
46 | user_pass_raw = base64.b64decode(auth_header[6:])
47 | except TypeError:
48 | self.auth_error()
49 |
50 | try:
51 | # http://stackoverflow.com/questions/7242316/what-encoding-should-i-use-for-http-basic-authentication
52 | user_pass_as_text = user_pass_raw.decode('ISO-8859-1')
53 | except UnicodeDecodeError:
54 | self.auth_error()
55 |
56 | user_pass = user_pass_as_text.split(':', 1)
57 | if len(user_pass) != 2:
58 | self.auth_error()
59 |
60 | if not self.validate_creds(*user_pass):
61 | self.demand_auth()
62 |
63 | else:
64 | self.demand_auth()
65 |
66 | def validate_creds(self, username, password):
67 | if '%s:%s' % (username, password) == self.src:
68 | return True
69 | else:
70 | return False
71 |
72 | def auth_error(self):
73 | raise AuthenticationError(response_code=403)
74 |
75 | def demand_auth(self):
76 | raise AuthenticationError(response_code=401,
77 | response_headers={'WWW-Authenticate': 'Basic realm="Websockify"'})
78 |
79 | class ExpectOrigin(object):
80 | def __init__(self, src=None):
81 | if src is None:
82 | self.source = []
83 | else:
84 | self.source = src.split()
85 |
86 | def authenticate(self, headers, target_host, target_port):
87 | origin = headers.get('Origin', None)
88 | if origin is None or origin not in self.source:
89 | raise InvalidOriginError(expected=self.source, actual=origin)
90 |
91 | class ClientCertCNAuth(object):
92 | """Verifies client by SSL certificate. Specify src as whitespace separated list of common names."""
93 |
94 | def __init__(self, src=None):
95 | if src is None:
96 | self.source = []
97 | else:
98 | self.source = src.split()
99 |
100 | def authenticate(self, headers, target_host, target_port):
101 | if headers.get('SSL_CLIENT_S_DN_CN', None) not in self.source:
102 | raise AuthenticationError(response_code=403)
103 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/websockify/sysloghandler.py:
--------------------------------------------------------------------------------
1 | import logging.handlers as handlers, socket, os, time
2 |
3 |
4 | class WebsockifySysLogHandler(handlers.SysLogHandler):
5 | """
6 | A handler class that sends proper Syslog-formatted messages,
7 | as defined by RFC 5424.
8 | """
9 |
10 | _legacy_head_fmt = '<{pri}>{ident}[{pid}]: '
11 | _rfc5424_head_fmt = '<{pri}>1 {timestamp} {hostname} {ident} {pid} - - '
12 | _head_fmt = _rfc5424_head_fmt
13 | _legacy = False
14 | _timestamp_fmt = '%Y-%m-%dT%H:%M:%SZ'
15 | _max_hostname = 255
16 | _max_ident = 24 #safer for old daemons
17 | _send_length = False
18 | _tail = '\n'
19 |
20 |
21 | ident = None
22 |
23 |
24 | def __init__(self, address=('localhost', handlers.SYSLOG_UDP_PORT),
25 | facility=handlers.SysLogHandler.LOG_USER,
26 | socktype=None, ident=None, legacy=False):
27 | """
28 | Initialize a handler.
29 |
30 | If address is specified as a string, a UNIX socket is used. To log to a
31 | local syslogd, "WebsockifySysLogHandler(address="/dev/log")" can be
32 | used. If facility is not specified, LOG_USER is used. If socktype is
33 | specified as socket.SOCK_DGRAM or socket.SOCK_STREAM, that specific
34 | socket type will be used. For Unix sockets, you can also specify a
35 | socktype of None, in which case socket.SOCK_DGRAM will be used, falling
36 | back to socket.SOCK_STREAM. If ident is specified, this string will be
37 | used as the application name in all messages sent. Set legacy to True
38 | to use the old version of the protocol.
39 | """
40 |
41 | self.ident = ident
42 |
43 | if legacy:
44 | self._legacy = True
45 | self._head_fmt = self._legacy_head_fmt
46 |
47 | handlers.SysLogHandler.__init__(self, address, facility, socktype)
48 |
49 |
50 | def emit(self, record):
51 | """
52 | Emit a record.
53 |
54 | The record is formatted, and then sent to the syslog server. If
55 | exception information is present, it is NOT sent to the server.
56 | """
57 |
58 | try:
59 | # Gather info.
60 | text = self.format(record).replace(self._tail, ' ')
61 | if not text: # nothing to log
62 | return
63 |
64 | pri = self.encodePriority(self.facility,
65 | self.mapPriority(record.levelname))
66 |
67 | timestamp = time.strftime(self._timestamp_fmt, time.gmtime());
68 |
69 | hostname = socket.gethostname()[:self._max_hostname]
70 |
71 | if self.ident:
72 | ident = self.ident[:self._max_ident]
73 | else:
74 | ident = ''
75 |
76 | pid = os.getpid() # shouldn't need truncation
77 |
78 | # Format the header.
79 | head = {
80 | 'pri': pri,
81 | 'timestamp': timestamp,
82 | 'hostname': hostname,
83 | 'ident': ident,
84 | 'pid': pid,
85 | }
86 | msg = self._head_fmt.format(**head).encode('ascii', 'ignore')
87 |
88 | # Encode text as plain ASCII if possible, else use UTF-8 with BOM.
89 | try:
90 | msg += text.encode('ascii')
91 | except UnicodeEncodeError:
92 | msg += text.encode('utf-8-sig')
93 |
94 | # Add length or tail character, if necessary.
95 | if self.socktype != socket.SOCK_DGRAM:
96 | if self._send_length:
97 | msg = ('%d ' % len(msg)).encode('ascii') + msg
98 | else:
99 | msg += self._tail.encode('ascii')
100 |
101 | # Send the message.
102 | if self.unixsocket:
103 | try:
104 | self.socket.send(msg)
105 | except socket.error:
106 | self._connect_unixsocket(self.address)
107 | self.socket.send(msg)
108 |
109 | else:
110 | if self.socktype == socket.SOCK_DGRAM:
111 | self.socket.sendto(msg, self.address)
112 | else:
113 | self.socket.sendall(msg)
114 |
115 | except (KeyboardInterrupt, SystemExit):
116 | raise
117 | except:
118 | self.handleError(record)
119 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/websockify/token_plugins.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function
2 | import os
3 | import sys
4 |
5 | class BasePlugin(object):
6 | def __init__(self, src):
7 | self.source = src
8 |
9 | def lookup(self, token):
10 | return None
11 |
12 |
13 | class ReadOnlyTokenFile(BasePlugin):
14 | # source is a token file with lines like
15 | # token: host:port
16 | # or a directory of such files
17 | def __init__(self, *args, **kwargs):
18 | super(ReadOnlyTokenFile, self).__init__(*args, **kwargs)
19 | self._targets = None
20 |
21 | def _load_targets(self):
22 | if os.path.isdir(self.source):
23 | cfg_files = [os.path.join(self.source, f) for
24 | f in os.listdir(self.source)]
25 | else:
26 | cfg_files = [self.source]
27 |
28 | self._targets = {}
29 | index = 1
30 | for f in cfg_files:
31 | for line in [l.strip() for l in open(f).readlines()]:
32 | if line and not line.startswith('#'):
33 | try:
34 | tok, target = line.split(': ')
35 | self._targets[tok] = target.strip().rsplit(':', 1)
36 | except ValueError:
37 | print >>sys.stderr, "Syntax error in %s on line %d" % (self.source, index)
38 | index += 1
39 |
40 | def lookup(self, token):
41 | if self._targets is None:
42 | self._load_targets()
43 |
44 | if token in self._targets:
45 | return self._targets[token]
46 | else:
47 | return None
48 |
49 |
50 | # the above one is probably more efficient, but this one is
51 | # more backwards compatible (although in most cases
52 | # ReadOnlyTokenFile should suffice)
53 | class TokenFile(ReadOnlyTokenFile):
54 | # source is a token file with lines like
55 | # token: host:port
56 | # or a directory of such files
57 | def lookup(self, token):
58 | self._load_targets()
59 |
60 | return super(TokenFile, self).lookup(token)
61 |
62 |
63 | class BaseTokenAPI(BasePlugin):
64 | # source is a url with a '%s' in it where the token
65 | # should go
66 |
67 | # we import things on demand so that other plugins
68 | # in this file can be used w/o unecessary dependencies
69 |
70 | def process_result(self, resp):
71 | return resp.text.split(':')
72 |
73 | def lookup(self, token):
74 | import requests
75 |
76 | resp = requests.get(self.source % token)
77 |
78 | if resp.ok:
79 | return self.process_result(resp)
80 | else:
81 | return None
82 |
83 |
84 | class JSONTokenApi(BaseTokenAPI):
85 | # source is a url with a '%s' in it where the token
86 | # should go
87 |
88 | def process_result(self, resp):
89 | resp_json = resp.json()
90 | return (resp_json['host'], resp_json['port'])
91 |
92 |
93 | class JWTTokenApi(BasePlugin):
94 | # source is a JWT-token, with hostname and port included
95 | # Both JWS as JWE tokens are accepted. With regards to JWE tokens, the key is re-used for both validation and decryption.
96 |
97 | def lookup(self, token):
98 | try:
99 | from jwcrypto import jwt
100 | import json
101 |
102 | key = jwt.JWK()
103 |
104 | try:
105 | with open(self.source, 'rb') as key_file:
106 | key_data = key_file.read()
107 | except Exception as e:
108 | print("Error loading key file: %s" % str(e), file=sys.stderr)
109 | return None
110 |
111 | try:
112 | key.import_from_pem(key_data)
113 | except:
114 | try:
115 | key.import_key(k=key_data.decode('utf-8'),kty='oct')
116 | except:
117 | print('Failed to correctly parse key data!', file=sys.stderr)
118 | return None
119 |
120 | try:
121 | token = jwt.JWT(key=key, jwt=token)
122 | parsed_header = json.loads(token.header)
123 |
124 | if 'enc' in parsed_header:
125 | # Token is encrypted, so we need to decrypt by passing the claims to a new instance
126 | token = jwt.JWT(key=key, jwt=token.claims)
127 |
128 | parsed = json.loads(token.claims)
129 |
130 | return (parsed['host'], parsed['port'])
131 | except Exception as e:
132 | print("Failed to parse token: %s" % str(e), file=sys.stderr)
133 | return None
134 | except ImportError as e:
135 | print("package jwcrypto not found, are you sure you've installed it correctly?", file=sys.stderr)
136 | return None
137 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/websockify/websocketserver.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | '''
4 | Python WebSocket server base
5 | Copyright 2011 Joel Martin
6 | Copyright 2016-2018 Pierre Ossman
7 | Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
8 | '''
9 |
10 | import sys
11 |
12 | # python 3.0 differences
13 | try:
14 | from http.server import BaseHTTPRequestHandler, HTTPServer
15 | except ImportError:
16 | from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
17 |
18 | from websockify.websocket import WebSocket, WebSocketWantReadError, WebSocketWantWriteError
19 |
20 | class WebSocketRequestHandlerMixIn:
21 | """WebSocket request handler mix-in class
22 |
23 | This class modifies and existing request handler to handle
24 | WebSocket requests. The request handler will continue to function
25 | as before, except that WebSocket requests are intercepted and the
26 | methods handle_upgrade() and handle_websocket() are called. The
27 | standard do_GET() will be called for normal requests.
28 |
29 | The class instance SocketClass can be overridden with the class to
30 | use for the WebSocket connection.
31 | """
32 |
33 | SocketClass = WebSocket
34 |
35 | def handle_one_request(self):
36 | """Extended request handler
37 |
38 | This is where WebSocketRequestHandler redirects requests to the
39 | new methods. Any sub-classes must call this method in order for
40 | the calls to function.
41 | """
42 | self._real_do_GET = self.do_GET
43 | self.do_GET = self._websocket_do_GET
44 | try:
45 | # super() only works for new style classes
46 | if issubclass(WebSocketRequestHandlerMixIn, object):
47 | super(WebSocketRequestHandlerMixIn, self).handle_one_request()
48 | else:
49 | # Assume handle_one_request() hasn't been overriden
50 | BaseHTTPRequestHandler.handle_one_request(self)
51 | finally:
52 | self.do_GET = self._real_do_GET
53 |
54 | def _websocket_do_GET(self):
55 | # Checks if it is a websocket request and redirects
56 | self.do_GET = self._real_do_GET
57 |
58 | if (self.headers.get('upgrade') and
59 | self.headers.get('upgrade').lower() == 'websocket'):
60 | self.handle_upgrade()
61 | else:
62 | self.do_GET()
63 |
64 | def handle_upgrade(self):
65 | """Initial handler for a WebSocket request
66 |
67 | This method is called when a WebSocket is requested. By default
68 | it will create a WebSocket object and perform the negotiation.
69 | The WebSocket object will then replace the request object and
70 | handle_websocket() will be called.
71 | """
72 | websocket = self.SocketClass()
73 | try:
74 | websocket.accept(self.request, self.headers)
75 | except Exception:
76 | exc = sys.exc_info()[1]
77 | self.send_error(400, str(exc))
78 | return
79 |
80 | self.log_request(101)
81 |
82 | self.request = websocket
83 |
84 | # Other requests cannot follow Websocket data
85 | self.close_connection = True
86 |
87 | self.handle_websocket()
88 |
89 | def handle_websocket(self):
90 | """Handle a WebSocket connection.
91 |
92 | This is called when the WebSocket is ready to be used. A
93 | sub-class should perform the necessary communication here and
94 | return once done.
95 | """
96 | pass
97 |
98 | # Convenient ready made classes
99 |
100 | class WebSocketRequestHandler(WebSocketRequestHandlerMixIn,
101 | BaseHTTPRequestHandler):
102 | pass
103 |
104 | class WebSocketServer(HTTPServer):
105 | pass
106 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/wsirc.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | IRC Client using WebSockets
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Host:
23 | Port:
24 | Encrypt:
25 |
26 |
27 | Nick:
28 |
29 | Channel: #
30 |
31 |
32 |
33 |
34 | >
35 |
36 |
37 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/vnc/utils/websockify/wstelnet.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Telnet client using WebSockets
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Host:
23 | Port:
24 | Encrypt:
25 |
27 |
28 |
29 |
30 |
31 |
32 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------