diff --git a/.gitignore b/.gitignore
index 7840d7e..57726ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,5 @@ _testmain.go
*.test
*.bak
+
+cmd/gost
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 6c8bef2..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: go
-
-go:
- 1.6
- 1.7
\ No newline at end of file
diff --git a/README.md b/README.md
index c267885..56dfc5d 100644
--- a/README.md
+++ b/README.md
@@ -7,17 +7,20 @@ gost - GO Simple Tunnel
特性
------
-* 可同时监听多端口
+* 多端口监听
* 可设置转发代理,支持多级转发(代理链)
-* 支持标准HTTP/HTTPS/SOCKS5代理协议
+* 支持标准HTTP/HTTPS/HTTP2/SOCKS4(A)/SOCKS5代理协议
* SOCKS5代理支持TLS协商加密
* Tunnel UDP over TCP
-* 支持Shadowsocks协议 (OTA: 2.2+,UDP: 2.4+)
-* 支持本地/远程端口转发 (2.1+)
-* 支持HTTP 2.0 (2.2+)
-* 实验性支持QUIC (2.3+)
-* 支持KCP协议 (2.3+)
-* 透明代理 (2.3+)
+* 权限控制 (2.4+)
+* 本地/远程TCP/UDP端口转发 (2.1+)
+* Shadowsocks协议 (UDP: 2.4+)
+* KCP协议 (2.3+)
+* TCP透明代理 (2.3+)
+* HTTP2通道 (2.4+)
+* SSH通道 (2.4+)
+* QUIC通道 (2.4+)
+* obfs4通道 (2.4+)
二进制文件下载:https://github.com/ginuerzh/gost/releases
@@ -45,29 +48,40 @@ $ sudo snap install gost
```
scheme分为两部分: protocol+transport
-protocol: 代理协议类型(http, socks5, shadowsocks), transport: 数据传输方式(ws, wss, tls, http2, quic, kcp), 二者可以任意组合,或单独使用:
+protocol: 代理协议类型(http, socks4(a), socks5, ss), transport: 数据传输方式(ws, wss, tls, quic, kcp, ssh, h2, h2c, obfs4), 二者可以任意组合,或单独使用:
-> http - HTTP代理: http://:8080
+> http - 标准HTTP代理: http://:8080
-> http+tls - HTTPS代理(可能需要提供受信任的证书): http+tls://:443或https://:443
+> https - 标准HTTPS代理(可能需要提供受信任的证书): http+tls://:443或https://:443
-> http2 - HTTP2代理并向下兼容HTTPS代理: http2://:443
+> http2 - 标准HTTP2代理并向下兼容HTTPS: http2://:443
-> socks - 标准SOCKS5代理(支持tls协商加密): socks://:1080
+> h2 - HTTP2 h2通道: h2://:443
-> socks+wss - SOCKS5代理,使用websocket传输数据: socks+wss://:1080
+> h2c - HTTP2 h2c通道: h2c://:443
-> tls - HTTPS/SOCKS5代理,使用tls传输数据: tls://:443
+> socks4(a) - 标准SOCKS4(A)代理: socks4://:1080或socks4a://:1080
-> ss - Shadowsocks代理,ss://chacha20:123456@:8338
+> socks5 - 标准SOCKS5代理(支持TLS协商加密): socks5://:1080
-> ssu - Shadowsocks UDP relay,ssu://chacha20:123456@:8338
+> socks5+wss - SOCKS5代理,使用websocket传输数据: socks5+wss://:1080
-> quic - QUIC代理,quic://:6121
+> tls - HTTP/SOCKS4/SOCKS5代理,使用TLS传输数据: tls://:443
-> kcp - KCP代理,kcp://:8388或kcp://aes:123456@:8388
+> ss - Shadowsocks代理: ss://chacha20:123456@:8338
+
+> ssu - Shadowsocks UDP relay: ssu://chacha20:123456@:8338
+
+> quic - QUIC通道: quic://:6121
+
+> kcp - KCP通道: kcp://:8388或kcp://aes:123456@:8388
+
+> redirect - 透明代理: redirect://:12345
+
+> ssh - SSH代理通道: ssh://:2222,SSH转发通道: forward+ssh://:2222
+
+> obfs4 - obfs4通道: obfs4://:8080
-> redirect - 透明代理,redirect://:12345
#### 端口转发
@@ -84,6 +98,8 @@ scheme://[bind_address]:port/[host]:hostport
#### 配置文件
+此功能由[@septs](https://github.com/septs)贡献。
+
> -C : 指定配置文件路径
配置文件为标准json格式:
@@ -102,14 +118,6 @@ scheme://[bind_address]:port/[host]:hostport
ServeNodes等同于-L参数,ChainNodes等同于-F参数
-#### 开启日志
-
-> -logtostderr : 输出到控制台
-
-> -v=3 : 日志级别(1-5),级别越高,日志越详细(级别5将开启http2 debug)
-
-> -log_dir=/log/dir/path : 输出到目录/log/dir/path
-
使用方法
------
@@ -117,7 +125,7 @@ ServeNodes等同于-L参数,ChainNodes等同于-F参数
-* 作为标准HTTP/SOCKS5代理
+* 作为标准HTTP/SOCKS4/SOCKS5代理
```bash
gost -L=:8080
```
@@ -142,7 +150,7 @@ test002 12345678
* 多端口监听
```bash
-gost -L=http2://:443 -L=socks://:1080 -L=ss://aes-128-cfb:123456@:8338
+gost -L=http2://:443 -L=socks5://:1080 -L=ss://aes-128-cfb:123456@:8338
```
#### 设置转发代理
@@ -161,60 +169,76 @@ gost -L=:8080 -F=http://admin:123456@192.168.1.1:8081
```bash
-gost -L=:8080 -F=http+tls://192.168.1.1:443 -F=socks+ws://192.168.1.2:1080 -F=ss://aes-128-cfb:123456@192.168.1.3:8338 -F=a.b.c.d:NNNN
+gost -L=:8080 -F=quic://192.168.1.1:6121 -F=socks5+wss://192.168.1.2:1080 -F=http2://192.168.1.3:443 ... -F=a.b.c.d:NNNN
```
-gost按照-F设置的顺序通过代理链将请求最终转发给a.b.c.d:NNNN处理,每一个转发代理可以是任意HTTP/HTTPS/HTTP2/SOCKS5/Shadowsocks类型代理。
+gost按照-F设置的顺序通过代理链将请求最终转发给a.b.c.d:NNNN处理,每一个转发代理可以是任意HTTP/HTTPS/HTTP2/SOCKS4/SOCKS5/Shadowsocks类型代理。
#### 本地端口转发(TCP)
```bash
-gost -L=tcp://:2222/192.168.1.1:22 -F=...
+gost -L=tcp://:2222/192.168.1.1:22 [-F=...]
+```
+将本地TCP端口2222上的数据(通过代理链)转发到192.168.1.1:22上。当代理链末端(最后一个-F参数)为SSH转发通道类型时,gost会直接使用SSH的本地端口转发功能:
+
+```bash
+gost -L=tcp://:2222/192.168.1.1:22 -F forward+ssh://:2222
```
-将本地TCP端口2222上的数据(通过代理链)转发到192.168.1.1:22上。
#### 本地端口转发(UDP)
```bash
-gost -L=udp://:5353/192.168.1.1:53?ttl=60 -F=...
+gost -L=udp://:5353/192.168.1.1:53?ttl=60 [-F=...]
```
将本地UDP端口5353上的数据(通过代理链)转发到192.168.1.1:53上。
每条转发通道都有超时时间,当超过此时间,且在此时间段内无任何数据交互,则此通道将关闭。可以通过`ttl`参数来设置超时时间,默认值为60秒。
-**注:** 转发UDP数据时,如果有代理链,则代理链的末端(最后一个-F参数)必须是gost SOCKS5类型代理。
+**注:** 转发UDP数据时,如果有代理链,则代理链的末端(最后一个-F参数)必须是gost SOCKS5类型代理,gost会使用UDP over TCP方式进行转发。
#### 远程端口转发(TCP)
```bash
-gost -L=rtcp://:2222/192.168.1.1:22 -F=... -F=socks://172.24.10.1:1080
+gost -L=rtcp://:2222/192.168.1.1:22 [-F=...]
+```
+将172.24.10.1:2222上的数据(通过代理链)转发到192.168.1.1:22上。当代理链末端(最后一个-F参数)为SSH转发通道类型时,gost会直接使用SSH的远程端口转发功能:
+
+```bash
+gost -L=rtcp://:2222/192.168.1.1:22 -F forward+ssh://:2222
```
-将172.24.10.1:2222上的数据(通过代理链)转发到192.168.1.1:22上。
#### 远程端口转发(UDP)
```bash
-gost -L=rudp://:5353/192.168.1.1:53 -F=... -F=socks://172.24.10.1:1080
+gost -L=rudp://:5353/192.168.1.1:53 [-F=...]
```
将172.24.10.1:5353上的数据(通过代理链)转发到192.168.1.1:53上。
-**注:** 若要使用远程端口转发功能,代理链不能为空(至少要设置一个-F参数),且代理链的末端(最后一个-F参数)必须是gost SOCKS5类型代理。
+**注:** 转发UDP数据时,如果有代理链,则代理链的末端(最后一个-F参数)必须是gost SOCKS5类型代理,gost会使用UDP over TCP方式进行转发。
#### HTTP2
-gost的HTTP2支持两种模式并自适应:
-* 作为标准的HTTP2代理,并向下兼容HTTPS代理。
-* 作为transport(类似于wss),传输其他协议。
+gost的HTTP2支持两种模式:
+* 作为标准的HTTP2代理,并向下兼容HTTPS代理。
+* 作为通道传输其他协议。
+
+##### 代理模式
服务端:
```bash
gost -L=http2://:443
```
客户端:
```bash
-gost -L=:8080 -F=http2://server_ip:443?ping=30
+gost -L=:8080 -F=http2://server_ip:443
```
-客户端支持`ping`参数开启心跳检测(默认不开启),参数值代表心跳间隔秒数。
-
-**注:** gost的代理链仅支持一个HTTP2代理节点,采用就近原则,会将第一个遇到的HTTP2代理节点视为HTTP2代理,其他HTTP2代理节点则被视为HTTPS代理。
+##### 通道模式
+服务端:
+```bash
+gost -L=h2://:443
+```
+客户端:
+```bash
+gost -L=:8080 -F=h2://server_ip:443
+```
#### QUIC
gost对QUIC的支持是基于[quic-go](https://github.com/lucas-clemente/quic-go)库。
@@ -224,12 +248,12 @@ gost对QUIC的支持是基于[quic-go](https://github.com/lucas-clemente/quic-go
gost -L=quic://:6121
```
-客户端(Chrome):
+客户端:
```bash
-chrome --enable-quic --proxy-server=quic://server_ip:6121
+gost -L=:8080 -F=quic://server_ip:6121
```
-**注:** 由于Chrome自身的限制,目前只能通过QUIC访问HTTP网站,无法访问HTTPS网站。
+**注:** QUIC模式只能作为代理链的第一个节点。
#### KCP
gost对KCP的支持是基于[kcp-go](https://github.com/xtaci/kcp-go)和[kcptun](https://github.com/xtaci/kcptun)库。
@@ -244,24 +268,41 @@ gost -L=kcp://:8388
gost -L=:8080 -F=kcp://server_ip:8388
```
-或者手动指定加密方法和密码(手动指定的加密方法和密码会覆盖配置文件中的相应值)
-
-服务端:
-```bash
-gost -L=kcp://aes:123456@:8388
-```
-
-客户端:
-```bash
-gost -L=:8080 -F=kcp://aes:123456@server_ip:8388
-```
-
gost会自动加载当前工作目录中的kcp.json(如果存在)配置文件,或者可以手动通过参数指定配置文件路径:
```bash
gost -L=kcp://:8388?c=/path/to/conf/file
```
-**注:** 客户端若要开启KCP转发,当且仅当代理链不为空且首个代理节点(第一个-F参数)为kcp类型。
+**注:** KCP模式只能作为代理链的第一个节点。
+
+#### SSH
+
+gost的SSH支持两种模式:
+* 作为转发通道,配合本地/远程TCP端口转发使用。
+* 作为通道传输其他协议。
+
+##### 转发模式
+服务端:
+```bash
+gost -L=forward+ssh://:2222
+```
+客户端:
+```bash
+gost -L=rtcp://:1222/:22 -F=forward+ssh://server_ip:2222
+```
+
+##### 通道模式
+服务端:
+```bash
+gost -L=ssh://:2222
+```
+客户端:
+```bash
+gost -L=:8080 -F=ssh://server_ip:2222?ping=60
+```
+
+可以通过`ping`参数设置心跳包发送周期,单位为秒。默认不发送心跳包。
+
#### 透明代理
基于iptables的透明代理。
@@ -270,6 +311,24 @@ gost -L=kcp://:8388?c=/path/to/conf/file
gost -L=redirect://:12345 -F=http2://server_ip:443
```
+#### obfs4
+此功能由[@isofew](https://github.com/isofew)贡献。
+
+服务端:
+```bash
+gost -L=obfs4://:443
+```
+
+当服务端运行后会在控制台打印出连接地址供客户端使用:
+```
+obfs4://:443/?cert=4UbQjIfjJEQHPOs8vs5sagrSXx1gfrDCGdVh2hpIPSKH0nklv1e4f29r7jb91VIrq4q5Jw&iat-mode=0
+```
+
+客户端:
+```
+gost -L=:8888 -F='obfs4://server_ip:443?cert=4UbQjIfjJEQHPOs8vs5sagrSXx1gfrDCGdVh2hpIPSKH0nklv1e4f29r7jb91VIrq4q5Jw&iat-mode=0'
+```
+
加密机制
------
#### HTTP
@@ -277,7 +336,7 @@ gost -L=redirect://:12345 -F=http2://server_ip:443
服务端:
```bash
-gost -L=http+tls://:443
+gost -L=https://:443
```
客户端:
```bash
@@ -285,44 +344,43 @@ gost -L=:8080 -F=http+tls://server_ip:443
```
#### HTTP2
-gost仅支持使用TLS加密的HTTP2协议,不支持明文HTTP2传输。
+gost的HTTP2代理模式仅支持使用TLS加密的HTTP2协议,不支持明文HTTP2传输。
+gost的HTTP2通道模式支持加密(h2)和明文(h2c)两种模式。
#### SOCKS5
gost支持标准SOCKS5协议的no-auth(0x00)和user/pass(0x02)方法,并在此基础上扩展了两个:tls(0x80)和tls-auth(0x82),用于数据加密。
服务端:
```bash
-gost -L=socks://:1080
+gost -L=socks5://:1080
```
客户端:
```bash
-gost -L=:8080 -F=socks://server_ip:1080
+gost -L=:8080 -F=socks5://server_ip:1080
```
如果两端都是gost(如上)则数据传输会被加密(协商使用tls或tls-auth方法),否则使用标准SOCKS5进行通讯(no-auth或user/pass方法)。
-**注:** 如果transport已经支持加密(wss, tls, http2, kcp),则SOCKS5不会再使用加密方法,防止不必要的双重加密。
-
#### Shadowsocks
gost对shadowsocks的支持是基于[shadowsocks-go](https://github.com/shadowsocks/shadowsocks-go)库。
-服务端(可以通过ota参数开启OTA强制模式,开启后客户端必须使用OTA模式):
+服务端:
```bash
-gost -L=ss://aes-128-cfb:123456@:8338?ota=1
+gost -L=ss://chacha20:123456@:8338
```
-客户端(可以通过ota参数开启OTA模式):
+客户端:
```bash
-gost -L=:8080 -F=ss://aes-128-cfb:123456@server_ip:8338?ota=1
+gost -L=:8080 -F=ss://chacha20:123456@server_ip:8338
```
##### Shadowsocks UDP relay
-目前仅服务端支持UDP,且仅支持OTA模式。
+目前仅服务端支持UDP Relay。
服务端:
```bash
-gost -L=ssu://aes-128-cfb:123456@:8338
+gost -L=ssu://chacha20:123456@:8338
```
#### TLS
@@ -333,6 +391,12 @@ gost内置了TLS证书,如果需要使用其他TLS证书,有两种方法:
gost -L="http2://:443?cert=/path/to/my/cert/file&key=/path/to/my/key/file"
```
+对于客户端可以指定CA证书进行[证书锁定](https://en.wikipedia.org/wiki/Transport_Layer_Security#Certificate_pinning)(Certificate Pinning):
+```bash
+gost -L=:8080 -F="http2://:443?ca=ca.pem"
+```
+证书锁定功能由[@sheerun](https://github.com/sheerun)贡献
+
SOCKS5 UDP数据处理
------
#### 不设置转发代理
@@ -351,6 +415,38 @@ gost作为标准SOCKS5代理处理UDP数据
当设置转发代理时,gost会使用UDP-over-TCP方式转发UDP数据。proxy1 - proxyN可以为任意HTTP/HTTPS/HTTP2/SOCKS5/Shadowsocks类型代理。
+权限控制
+------
+此功能由[@sheerun](https://github.com/sheerun)贡献。
+
+服务端可以通过白名单(`whitelist`参数)和黑名单(`blacklist`参数)来控制客户端的请求是否允许被处理。
+参数格式为: `[actions]:[hosts]:[ports]`
+
+`[actions]`是一个由`,`分割的动作列表,可选值有: `tcp`(TCP转发), `udp`(UDP转发), `rtcp`(TCP远程转发), `rudp`(UDP远程转发), 或 `*`(所有动作)。
+
+`[hosts]`是一个由`,`分割的Host列表,代表可以绑定到(rtcp,rudp)或转发到(tcp,udp)的目的主机,支持通配符(*.google.com)和`*`(所有主机)。
+
+`[ports]`是一个由`,`分割的端口列表,代表可以绑定到(rtcp,rudp)或转发到(tcp,udp)的目的端口,可以是`*`(所有端口)。
+
+多组权限可以通过`+`进行连接:
+
+`whitelist=rtcp,rudp:localhost,127.0.0.1:2222,8000-9000+udp:8.8.8.8,8.8.4.4:53`(允许TCP/UDP远程端口转发绑定到localhost,127.0.0.1的2222端口和8000-9000端口范围,同时允许UDP转发到8.8.8.8:53和8.8.4.4:53)。
+
+SSH远程端口转发只能绑定到127.0.0.1:8000
+```bash
+gost -L=forward+ssh://localhost:8389?whitelist=rtcp:127.0.0.1:8000
+```
+
+SOCKS5的TCP/UDP远程端口转发只允许绑定到大于1000的端口
+```bash
+gost -L=socks://localhost:8389?blacklist=rtcp,rudp:*:0-1000
+```
+
+SOCKS5的UDP转发只能转发到8.8.8.8:53
+```bash
+gost -L=socks://localhost:8389?whitelist=udp:8.8.8.8:53
+```
+
限制条件
------
代理链中的HTTP代理节点必须支持CONNECT方法。
diff --git a/README_en.md b/README_en.md
index f748c73..1f0e9a9 100644
--- a/README_en.md
+++ b/README_en.md
@@ -7,15 +7,18 @@ Features
------
* Listening on multiple ports
* Multi-level forward proxy - proxy chain
-* Standard HTTP/HTTPS/SOCKS5 proxy protocols support
+* Standard HTTP/HTTPS/HTTP2/SOCKS4(A)/SOCKS5 proxy protocols support
* TLS encryption via negotiation support for SOCKS5 proxy
* Tunnel UDP over TCP
-* Shadowsocks protocol support (OTA: 2.2+, UDP: 2.4+)
-* Local/remote port forwarding (2.1+)
-* HTTP 2.0 support (2.2+)
-* Experimental QUIC support (2.3+)
-* KCP protocol support (2.3+)
-* Transparent proxy (2.3+)
+* Permission control
+* Local/remote TCP/UDP port forwarding (2.1+)
+* Shadowsocks protocol (UDP: 2.4+)
+* KCP protocol (2.3+)
+* Transparent TCP proxy (2.3+)
+* HTTP2 tunnel (2.4+)
+* SSH tunnel (2.4+)
+* QUIC tunnel (2.4+)
+* obfs4 tunnel (2.4+)
Binary file download:https://github.com/ginuerzh/gost/releases
@@ -45,30 +48,40 @@ Effective for the -L and -F parameters
```
scheme can be divided into two parts: protocol+transport
-protocol: proxy protocol types (http, socks5, shadowsocks),
-transport: data transmission mode (ws, wss, tls, http2, quic, kcp), may be used in any combination or individually:
+protocol: proxy protocol types (http, socks4(a), socks5, ss),
+transport: data transmission mode (ws, wss, tls, quic, kcp, ssh, h2, h2c, obfs4), may be used in any combination or individually:
> http - standard HTTP proxy: http://:8080
-> http+tls - standard HTTPS proxy (may need to provide a trusted certificate): http+tls://:443 or https://:443
+> https - standard HTTPS proxy (may need to provide a trusted certificate): http+tls://:443 or https://:443
> http2 - HTTP2 proxy and backwards-compatible with HTTPS proxy: http2://:443
-> socks - standard SOCKS5 proxy: socks://:1080
+> h2 - HTTP2 h2 tunnel: h2://:443
-> socks+wss - SOCKS5 over websocket: socks+wss://:1080
+> h2c - HTTP2 h2c tunnel: h2c://:443
-> tls - HTTPS/SOCKS5 over tls: tls://:443
+> socks4(a) - standard SOCKS4(A) proxy: socks4://:1080 or socks4a://:1080
-> ss - standard shadowsocks proxy, ss://chacha20:123456@:8338
+> socks5 - standard SOCKS5 proxy: socks5://:1080
-> ssu - shadowsocks UDP relay,ssu://chacha20:123456@:8338
+> socks5+wss - SOCKS5 over websocket: socks5+wss://:1080
-> quic - standard QUIC proxy, quic://:6121
+> tls - HTTPS/SOCKS4/SOCKS5 over TLS: tls://:443
-> kcp - standard KCP tunnel,kcp://:8388 or kcp://aes:123456@:8388
+> ss - standard shadowsocks proxy: ss://chacha20:123456@:8338
-> redirect - transparent proxy,redirect://:12345
+> ssu - shadowsocks UDP relay server: ssu://chacha20:123456@:8338
+
+> quic - QUIC tunnel: quic://:6121
+
+> kcp - KCP tunnel: kcp://:8388 or kcp://aes:123456@:8388
+
+> redirect - transparent proxy: redirect://:12345
+
+> ssh - SSH proxy tunnel: ssh://:2222, SSH forward tunnel: forward+ssh://:2222
+
+> obfs4 - obfs4 tunnel: obfs4://:8080
#### Port forwarding
@@ -85,6 +98,8 @@ scheme://[bind_address]:port/[host]:hostport
#### Configuration file
+Contributed by [@septs](https://github.com/septs).
+
> -C : specifies the configuration file path
The configuration file is in standard JSON format:
@@ -103,21 +118,13 @@ The configuration file is in standard JSON format:
ServeNodes is equivalent to the -L parameter, ChainNodes is equivalent to the -F parameter.
-#### Logging
-
-> -logtostderr : log to console
-
-> -v=3 : log level (1-5),The higher the level, the more detailed the log (level 5 will enable HTTP2 debug)
-
-> -log_dir=/log/dir/path : log to directory /log/dir/path
-
Usage
------
#### No forward proxy
-* Standard HTTP/SOCKS5 proxy
+* Standard HTTP/SOCKS4/SOCKS5 proxy
```bash
gost -L=:8080
```
@@ -142,7 +149,7 @@ test002 12345678
* Listen on multiple ports
```bash
-gost -L=http2://:443 -L=socks://:1080 -L=ss://aes-128-cfb:123456@:8338
+gost -L=http2://:443 -L=socks5://:1080 -L=ss://aes-128-cfb:123456@:8338
```
#### Forward proxy
@@ -161,50 +168,58 @@ gost -L=:8080 -F=http://admin:123456@192.168.1.1:8081
```bash
-gost -L=:8080 -F=http+tls://192.168.1.1:443 -F=socks+ws://192.168.1.2:1080 -F=ss://aes-128-cfb:123456@192.168.1.3:8338 -F=a.b.c.d:NNNN
+gost -L=:8080 -F=quic://192.168.1.1:6121 -F=socks5+wss://192.168.1.2:1080 -F=http2://192.168.1.3:443 ... -F=a.b.c.d:NNNN
```
Gost forwards the request to a.b.c.d:NNNN through the proxy chain in the order set by -F,
-each forward proxy can be any HTTP/HTTPS/HTTP2/SOCKS5/Shadowsocks type.
+each forward proxy can be any HTTP/HTTPS/HTTP2/SOCKS4/SOCKS5/Shadowsocks type.
#### Local TCP port forwarding
```bash
-gost -L=tcp://:2222/192.168.1.1:22 -F=...
+gost -L=tcp://:2222/192.168.1.1:22 [-F=...]
+```
+The data on the local TCP port 2222 is forwarded to 192.168.1.1:22 (through the proxy chain). If the last node of the chain (the last -F parameter) is a SSH forwad tunnel, then gost will use the local port forwarding function of SSH directly:
+
+```bash
+gost -L=tcp://:2222/192.168.1.1:22 -F forward+ssh://:2222
```
-The data on the local TCP port 2222 is forwarded to 192.168.1.1:22 (through the proxy chain).
#### Local UDP port forwarding
```bash
-gost -L=udp://:5353/192.168.1.1:53?ttl=60 -F=...
+gost -L=udp://:5353/192.168.1.1:53?ttl=60 [-F=...]
```
The data on the local UDP port 5353 is forwarded to 192.168.1.1:53 (through the proxy chain).
Each forwarding channel has a timeout period. When this time is exceeded and there is no data interaction during this time period, the channel will be closed. The timeout value can be set by the `ttl` parameter. The default value is 60 seconds.
-**NOTE:** When forwarding UDP data, if there is a proxy chain, the end of the chain (the last -F parameter) must be gost SOCKS5 proxy.
+**NOTE:** When forwarding UDP data, if there is a proxy chain, the end of the chain (the last -F parameter) must be gost SOCKS5 proxy, gost will use UDP-over-TCP to forward data.
#### Remote TCP port forwarding
```bash
-gost -L=rtcp://:2222/192.168.1.1:22 -F=... -F=socks://172.24.10.1:1080
+gost -L=rtcp://:2222/192.168.1.1:22 [-F=...]
+```
+The data on 172.24.10.1:2222 is forwarded to 192.168.1.1:22 (through the proxy chain). If the last node of the chain (the last -F parameter) is a SSH tunnel, then gost will use the remote port forwarding function of SSH directly:
+
+```bash
+gost -L=rtcp://:2222/192.168.1.1:22 -F forward+ssh://:2222
```
-The data on 172.24.10.1:2222 is forwarded to 192.168.1.1:22 (through the proxy chain).
#### Remote UDP port forwarding
```bash
-gost -L=rudp://:5353/192.168.1.1:53 -F=... -F=socks://172.24.10.1:1080
+gost -L=rudp://:5353/192.168.1.1:53 [-F=...]
```
The data on 172.24.10.1:5353 is forwarded to 192.168.1.1:53 (through the proxy chain).
-**NOTE:** To use the remote port forwarding feature, the proxy chain can not be empty (at least one -F parameter is set)
-and the end of the chain (last -F parameter) must be gost SOCKS5 proxy.
+**NOTE:** When forwarding UDP data, if there is a proxy chain, the end of the chain (the last -F parameter) must be gost SOCKS5 proxy, gost will use UDP-over-TCP to forward data.
#### HTTP2
-Gost HTTP2 supports two modes and self-adapting:
+Gost HTTP2 supports two modes:
* As a standard HTTP2 proxy, and backwards-compatible with the HTTPS proxy.
-* As transport (similar to wss), tunnel other protocol.
+* As a transport tunnel.
+##### Standard proxy
Server:
```bash
gost -L=http2://:443
@@ -214,11 +229,15 @@ Client:
gost -L=:8080 -F=http2://server_ip:443?ping=30
```
-The client supports the `ping` parameter to enable heartbeat detection (which is disabled by default).
-Parameter value represents heartbeat interval seconds.
-
-**NOTE:** The proxy chain of gost supports only one HTTP2 proxy node and the nearest rule applies,
-the first HTTP2 proxy node is treated as an HTTP2 proxy, and the other HTTP2 proxy nodes are treated as HTTPS proxies.
+##### Tunnel
+服务端:
+```bash
+gost -L=h2://:443
+```
+客户端:
+```bash
+gost -L=:8080 -F=h2://server_ip:443
+```
#### QUIC
Support for QUIC is based on library [quic-go](https://github.com/lucas-clemente/quic-go).
@@ -227,12 +246,12 @@ Server:
```bash
gost -L=quic://:6121
```
-Client(Chrome):
+Client:
```bash
-chrome --enable-quic --proxy-server=quic://server_ip:6121
+gost -L=:8080 -F=quic://server_ip:6121
```
-**NOTE:** Due to Chrome's limitations, it is currently only possible to access the HTTP (but not HTTPS) site through QUIC.
+**NOTE:** QUIC node can only be used as the first node of the proxy chain.
#### KCP
Support for KCP is based on libraries [kcp-go](https://github.com/xtaci/kcp-go) and [kcptun](https://github.com/xtaci/kcptun).
@@ -246,25 +265,41 @@ Client:
gost -L=:8080 -F=kcp://server_ip:8388
```
-Or manually specify the encryption method and password (Manually specifying the encryption method and password overwrites the corresponding value in the configuration file)
-
-Server:
-```bash
-gost -L=kcp://aes:123456@:8388
-```
-
-Client:
-```bash
-gost -L=:8080 -F=kcp://aes:123456@server_ip:8388
-```
-
Gost will automatically load kcp.json configuration file from current working directory if exists,
or you can use the parameter to specify the path to the file.
```bash
gost -L=kcp://:8388?c=/path/to/conf/file
```
-**NOTE:** KCP will be enabled if and only if the proxy chain is not empty and the first proxy node (the first -F parameter) is of type KCP.
+**NOTE:** KCP node can only be used as the first node of the proxy chain.
+
+#### SSH
+Gost SSH supports two modes:
+* As a forward tunnel, used by local/remote TCP port forwarding.
+* As a transport tunnel.
+
+
+##### Forward tunnel
+Server:
+```bash
+gost -L=forward+ssh://:2222
+```
+Client:
+```bash
+gost -L=rtcp://:1222/:22 -F=forward+ssh://server_ip:2222
+```
+
+##### Transport tunnel
+Server:
+```bash
+gost -L=ssh://:2222
+```
+Client:
+```bash
+gost -L=:8080 -F=ssh://server_ip:2222?ping=60
+```
+
+The client supports the ping parameter to enable heartbeat detection (which is disabled by default). Parameter value represents heartbeat interval seconds.
#### Transparent proxy
Iptables-based transparent proxy
@@ -273,6 +308,25 @@ Iptables-based transparent proxy
gost -L=redirect://:12345 -F=http2://server_ip:443
```
+
+#### obfs4
+Contributed by [@isofew](https://github.com/isofew).
+
+Server:
+```bash
+gost -L=obfs4://:443
+```
+
+When the server is running normally, the console prints out the connection address for the client to use:
+```
+obfs4://:443/?cert=4UbQjIfjJEQHPOs8vs5sagrSXx1gfrDCGdVh2hpIPSKH0nklv1e4f29r7jb91VIrq4q5Jw&iat-mode=0
+```
+
+Client:
+```
+gost -L=:8888 -F='obfs4://server_ip:443?cert=4UbQjIfjJEQHPOs8vs5sagrSXx1gfrDCGdVh2hpIPSKH0nklv1e4f29r7jb91VIrq4q5Jw&iat-mode=0'
+```
+
Encryption Mechanism
------
#### HTTP
@@ -288,8 +342,9 @@ gost -L=:8080 -F=http+tls://server_ip:443
```
#### HTTP2
-Gost supports only the HTTP2 protocol that uses TLS encryption (h2) and does not support plaintext HTTP2 (h2c) transport.
+Gost HTTP2 proxy mode only supports the use of TLS encrypted HTTP2 protocol, does not support plaintext HTTP2.
+Gost HTTP2 tunnel mode supports both encryption (h2) and plaintext (h2c) modes.
#### SOCKS5
Gost supports the standard SOCKS5 protocol methods: no-auth (0x00) and user/pass (0x02),
@@ -307,22 +362,20 @@ gost -L=:8080 -F=socks://server_ip:1080
If both ends are gosts (as example above), the data transfer will be encrypted (using tls or tls-auth).
Otherwise, use standard SOCKS5 for communication (no-auth or user/pass).
-**NOTE:** If transport already supports encryption (wss, tls, http2, kcp), SOCKS5 will no longer use the encryption method to prevent unnecessary double encryption.
-
#### Shadowsocks
Support for shadowsocks is based on library [shadowsocks-go](https://github.com/shadowsocks/shadowsocks-go).
-Server (The OTA mode can be enabled by the ota parameter. When enabled, the client must use OTA mode):
+Server:
```bash
-gost -L=ss://aes-128-cfb:123456@:8338?ota=1
+gost -L=ss://aes-128-cfb:123456@:8338
```
-Client (The OTA mode can be enabled by the ota parameter):
+Client:
```bash
-gost -L=:8080 -F=ss://aes-128-cfb:123456@server_ip:8338?ota=1
+gost -L=:8080 -F=ss://aes-128-cfb:123456@server_ip:8338
```
##### Shadowsocks UDP relay
-Currently, only the server supports UDP, and only OTA mode is supported.
+Currently, only the server supports UDP Relay.
Server:
```bash
@@ -337,6 +390,13 @@ There is built-in TLS certificate in gost, if you need to use other TLS certific
gost -L="http2://:443?cert=/path/to/my/cert/file&key=/path/to/my/key/file"
```
+
+For client, you can specify a CA certificate to allow for [Certificate Pinning](https://en.wikipedia.org/wiki/Transport_Layer_Security#Certificate_pinning):
+```bash
+gost -L=:8080 -F="http2://:443?ca=ca.pem"
+```
+Certificate Pinning is contributed by [@sheerun](https://github.com/sheerun).
+
SOCKS5 UDP Data Processing
------
#### No forward proxy
@@ -353,7 +413,38 @@ Gost acts as the standard SOCKS5 proxy for UDP relay.
-When forward proxies are set, gost uses UDP-over-TCP to forward UDP data, proxy1 to proxyN can be any HTTP/HTTPS/HTTP2/SOCKS5/Shadowsocks type.
+When forward proxies are set, gost uses UDP-over-TCP to forward UDP data, proxy1 to proxyN can be any HTTP/HTTPS/HTTP2/SOCKS4/SOCKS5/Shadowsocks type.
+
+Permission control
+------
+Contributed by [@sheerun](https://github.com/sheerun).
+
+One can pass available permissions with `whitelist` and `blacklist` values when starting a socks and ssh server. The format for each rule is as follows: `[actions]:[hosts]:[ports]`.
+
+`[actions]` are comma-separted list of allowed actions: `rtcp`, `rudp`, `tcp`, `udp`. can be `*` to encompass all actions.
+
+`[hosts]` are comma-separated list of allowed hosts that one can bind on (in case of `rtcp` and `rudp`), or forward to (incase of `tcp` and `udp`). hosts support globs, like `*.google.com`. can be `*` to encompass all hosts.
+
+`[ports]` are comma-separated list of ports that one can bind to (in case of `rtcp` and `rudp`), or forward to (incase of `tcp` and `udp`), can be `*` to encompass all ports.
+
+Multiple permissions can be passed if seperated with `+`:
+
+`rtcp,rudp:localhost,127.0.0.1:2222,8000-9000+udp:8.8.8.8,8.8.4.4:53` (allow for reverse tcp and udp binding on localhost and 127.0.0.1 on ports 2222 and 8000-9000 port range, plus allow for udp forwarding to 8.8.8.8 and 8.8.4.4 on port 53)
+
+SSH remote port forwarding can only bind on 127.0.0.1:8000
+```bash
+gost -L=forward+ssh://localhost:8389?whitelist=rtcp:127.0.0.1:8000
+```
+
+SOCKS5 TCP/UDP remote port forwarding can only bind on ports greater than 1000
+```bash
+gost -L=socks://localhost:8389?blacklist=rtcp,rudp:*:0-1000
+```
+
+SOCKS5 UDP forwading can only forward to 8.8.8.8:53
+```bash
+gost -L=socks://localhost:8389?whitelist=udp:8.8.8.8:53
+```
Limitation
------
diff --git a/chain.go b/chain.go
index 779f5c4..3cd0172 100644
--- a/chain.go
+++ b/chain.go
@@ -1,381 +1,110 @@
package gost
import (
- "crypto/rand"
- "crypto/tls"
- "encoding/base64"
"errors"
- "github.com/golang/glog"
- "golang.org/x/net/http2"
- "io"
"net"
- "net/http"
- "net/http/httputil"
- "net/url"
- "strconv"
- "strings"
- "sync"
- "time"
)
-// Proxy chain holds a list of proxy nodes
-type ProxyChain struct {
- nodes []ProxyNode
- lastNode *ProxyNode
- http2NodeIndex int
- http2Enabled bool
- http2Client *http.Client
- kcpEnabled bool
- kcpConfig *KCPConfig
- kcpSession *KCPSession
- kcpMutex sync.Mutex
+var (
+ // ErrEmptyChain is an error that implies the chain is empty.
+ ErrEmptyChain = errors.New("empty chain")
+)
+
+// Chain is a proxy chain that holds a list of proxy nodes.
+type Chain struct {
+ nodes []Node
}
-func NewProxyChain(nodes ...ProxyNode) *ProxyChain {
- chain := &ProxyChain{nodes: nodes, http2NodeIndex: -1}
- return chain
-}
-
-func (c *ProxyChain) AddProxyNode(node ...ProxyNode) {
- c.nodes = append(c.nodes, node...)
-}
-
-func (c *ProxyChain) AddProxyNodeString(snode ...string) error {
- for _, sn := range snode {
- node, err := ParseProxyNode(sn, false) // isServeNode == false
- if err != nil {
- return err
- }
- c.AddProxyNode(node)
+// NewChain creates a proxy chain with proxy nodes nodes.
+func NewChain(nodes ...Node) *Chain {
+ return &Chain{
+ nodes: nodes,
}
- return nil
}
-func (c *ProxyChain) Nodes() []ProxyNode {
+// Nodes returns the proxy nodes that the chain holds.
+func (c *Chain) Nodes() []Node {
return c.nodes
}
-func (c *ProxyChain) GetNode(index int) *ProxyNode {
- if index < len(c.nodes) {
- return &c.nodes[index]
+// LastNode returns the last node of the node list.
+// If the chain is empty, an empty node is returns.
+func (c *Chain) LastNode() Node {
+ if c.IsEmpty() {
+ return Node{}
}
- return nil
+ return c.nodes[len(c.nodes)-1]
}
-func (c *ProxyChain) SetNode(index int, node ProxyNode) {
- if index < len(c.nodes) {
- c.nodes[index] = node
- }
-}
-
-// Init initialize the proxy chain.
-// KCP will be enabled if the first proxy node is KCP proxy (transport == kcp).
-// HTTP2 will be enabled when at least one HTTP2 proxy node (scheme == http2) is present.
-//
-// NOTE: Should be called immediately when proxy nodes are ready.
-func (c *ProxyChain) Init() {
- length := len(c.nodes)
- if length == 0 {
- return
- }
-
- c.lastNode = &c.nodes[length-1]
-
- // HTTP2 restrict: HTTP2 will be enabled when at least one HTTP2 proxy node is present.
- for i, node := range c.nodes {
- if node.Transport == "http2" {
- glog.V(LINFO).Infoln("HTTP2 is enabled")
- cfg := &tls.Config{
- InsecureSkipVerify: node.insecureSkipVerify(),
- ServerName: node.serverName,
- }
- c.http2NodeIndex = i
- c.initHttp2Client(cfg, c.nodes[:i]...)
- break // shortest chain for HTTP2
- }
- }
-
- for i, node := range c.nodes {
- if node.Transport == "kcp" && i > 0 {
- glog.Fatal("KCP must be the first node in the proxy chain")
- }
- }
-
- if c.nodes[0].Transport == "kcp" {
- glog.V(LINFO).Infoln("KCP is enabled")
- c.kcpEnabled = true
- config, err := ParseKCPConfig(c.nodes[0].Get("c"))
- if err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- }
- if config == nil {
- config = DefaultKCPConfig
- }
- if c.nodes[0].Users != nil {
- config.Crypt = c.nodes[0].Users[0].Username()
- config.Key, _ = c.nodes[0].Users[0].Password()
- }
- c.kcpConfig = config
+// AddNode appends the node(s) to the chain.
+func (c *Chain) AddNode(nodes ...Node) {
+ if c == nil {
return
}
+ c.nodes = append(c.nodes, nodes...)
}
-func (c *ProxyChain) KCPEnabled() bool {
- return c.kcpEnabled
+// IsEmpty checks if the chain is empty.
+// An empty chain means that there is no proxy node in the chain.
+func (c *Chain) IsEmpty() bool {
+ return c == nil || len(c.nodes) == 0
}
-func (c *ProxyChain) Http2Enabled() bool {
- return c.http2Enabled
-}
-
-func (c *ProxyChain) initHttp2Client(config *tls.Config, nodes ...ProxyNode) {
- if c.http2NodeIndex < 0 || c.http2NodeIndex >= len(c.nodes) {
- return
- }
- http2Node := c.nodes[c.http2NodeIndex]
-
- tr := http2.Transport{
- TLSClientConfig: config,
- DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
- // replace the default dialer with our proxy chain.
- conn, err := c.dialWithNodes(false, http2Node.Addr, nodes...)
- if err != nil {
- return conn, err
- }
- conn = tls.Client(conn, cfg)
-
- // enable HTTP2 ping-pong
- pingIntvl, _ := strconv.Atoi(http2Node.Get("ping"))
- if pingIntvl > 0 {
- enablePing(conn, time.Duration(pingIntvl)*time.Second)
- }
-
- return conn, nil
- },
- }
- c.http2Client = &http.Client{Transport: &tr}
- c.http2Enabled = true
-
-}
-
-func enablePing(conn net.Conn, interval time.Duration) {
- if conn == nil || interval == 0 {
- return
+// Dial connects to the target address addr through the chain.
+// If the chain is empty, it will use the net.Dial directly.
+func (c *Chain) Dial(addr string) (net.Conn, error) {
+ if c.IsEmpty() {
+ return net.Dial("tcp", addr)
}
- glog.V(LINFO).Infoln("[http2] ping enabled, interval:", interval)
- go func() {
- t := time.NewTicker(interval)
- var framer *http2.Framer
- for {
- select {
- case <-t.C:
- if framer == nil {
- framer = http2.NewFramer(conn, conn)
- }
-
- var p [8]byte
- rand.Read(p[:])
- err := framer.WritePing(false, p)
- if err != nil {
- t.Stop()
- framer = nil
- glog.V(LWARNING).Infoln("[http2] ping:", err)
- return
- }
- }
- }
- }()
-}
-
-// Connect to addr through proxy chain
-func (c *ProxyChain) Dial(addr string) (net.Conn, error) {
- if !strings.Contains(addr, ":") {
- addr += ":80"
+ conn, err := c.Conn()
+ if err != nil {
+ return nil, err
}
- return c.dialWithNodes(true, addr, c.nodes...)
+
+ cc, err := c.LastNode().Client.Connect(conn, addr)
+ if err != nil {
+ conn.Close()
+ return nil, err
+ }
+ return cc, nil
}
-// GetConn initializes a proxy chain connection,
-// if no proxy nodes on this chain, it will return error
-func (c *ProxyChain) GetConn() (net.Conn, error) {
- nodes := c.nodes
- if len(nodes) == 0 {
+// Conn obtains a handshaked connection to the last node of the chain.
+// If the chain is empty, it returns an ErrEmptyChain error.
+func (c *Chain) Conn() (net.Conn, error) {
+ if c.IsEmpty() {
return nil, ErrEmptyChain
}
- if c.Http2Enabled() {
- nodes = nodes[c.http2NodeIndex+1:]
- if len(nodes) == 0 {
- header := make(http.Header)
- header.Set("Proxy-Switch", "gost") // Flag header to indicate server to switch to HTTP2 transport mode
- conn, err := c.getHttp2Conn(header)
- if err != nil {
- return nil, err
- }
- http2Node := c.nodes[c.http2NodeIndex]
- if http2Node.Transport == "http2" {
- http2Node.Transport = "h2"
- }
- if http2Node.Protocol == "http2" {
- http2Node.Protocol = "socks5" // assume it as socks5 protocol, so we can do much more things.
- }
- pc := NewProxyConn(conn, http2Node)
- if err := pc.Handshake(); err != nil {
- conn.Close()
- return nil, err
- }
- return pc, nil
- }
- }
- return c.travelNodes(true, nodes...)
-}
-
-func (c *ProxyChain) dialWithNodes(withHttp2 bool, addr string, nodes ...ProxyNode) (conn net.Conn, err error) {
- if len(nodes) == 0 {
- return net.DialTimeout("tcp", addr, DialTimeout)
- }
-
- if withHttp2 && c.Http2Enabled() {
- nodes = nodes[c.http2NodeIndex+1:]
- if len(nodes) == 0 {
- return c.http2Connect(addr)
- }
- }
- pc, err := c.travelNodes(withHttp2, nodes...)
+ nodes := c.nodes
+ conn, err := nodes[0].Client.Dial(nodes[0].Addr, nodes[0].DialOptions...)
if err != nil {
- return
+ return nil, err
}
- if err = pc.Connect(addr); err != nil {
- pc.Close()
- return
- }
- conn = pc
- return
-}
-func (c *ProxyChain) travelNodes(withHttp2 bool, nodes ...ProxyNode) (conn *ProxyConn, err error) {
- defer func() {
- if err != nil && conn != nil {
+ conn, err = nodes[0].Client.Handshake(conn, nodes[0].HandshakeOptions...)
+ if err != nil {
+ return nil, err
+ }
+
+ for i, node := range nodes {
+ if i == len(nodes)-1 {
+ break
+ }
+
+ next := nodes[i+1]
+ cc, err := node.Client.Connect(conn, next.Addr)
+ if err != nil {
conn.Close()
- conn = nil
+ return nil, err
}
- }()
-
- var cc net.Conn
- node := nodes[0]
-
- if withHttp2 && c.Http2Enabled() {
- cc, err = c.http2Connect(node.Addr)
- } else if node.Transport == "kcp" {
- cc, err = c.getKCPConn()
- } else {
- cc, err = net.DialTimeout("tcp", node.Addr, DialTimeout)
- }
- if err != nil {
- return
- }
- setKeepAlive(cc, KeepAliveTime)
-
- pc := NewProxyConn(cc, node)
- conn = pc
- if err = pc.Handshake(); err != nil {
- return
- }
-
- for _, node := range nodes[1:] {
- if err = conn.Connect(node.Addr); err != nil {
- return
- }
- pc := NewProxyConn(conn, node)
- conn = pc
- if err = pc.Handshake(); err != nil {
- return
+ cc, err = next.Client.Handshake(cc, next.HandshakeOptions...)
+ if err != nil {
+ conn.Close()
+ return nil, err
}
+ conn = cc
}
- return
-}
-
-func (c *ProxyChain) initKCPSession() (err error) {
- c.kcpMutex.Lock()
- defer c.kcpMutex.Unlock()
-
- if c.kcpSession == nil || c.kcpSession.IsClosed() {
- glog.V(LINFO).Infoln("[kcp] new kcp session")
- c.kcpSession, err = DialKCP(c.nodes[0].Addr, c.kcpConfig)
- }
- return
-}
-
-func (c *ProxyChain) getKCPConn() (conn net.Conn, err error) {
- if !c.KCPEnabled() {
- return nil, errors.New("KCP is not enabled")
- }
-
- if err = c.initKCPSession(); err != nil {
- return nil, err
- }
- return c.kcpSession.GetConn()
-}
-
-// Initialize an HTTP2 transport if HTTP2 is enabled.
-func (c *ProxyChain) getHttp2Conn(header http.Header) (net.Conn, error) {
- if !c.Http2Enabled() {
- return nil, errors.New("HTTP2 is not enabled")
- }
- http2Node := c.nodes[c.http2NodeIndex]
- pr, pw := io.Pipe()
-
- if header == nil {
- header = make(http.Header)
- }
-
- req := http.Request{
- Method: http.MethodConnect,
- URL: &url.URL{Scheme: "https", Host: http2Node.Addr},
- Header: header,
- Proto: "HTTP/2.0",
- ProtoMajor: 2,
- ProtoMinor: 0,
- Body: pr,
- Host: http2Node.Addr,
- ContentLength: -1,
- }
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpRequest(&req, false)
- glog.Infoln(string(dump))
- }
- resp, err := c.http2Client.Do(&req)
- if err != nil {
- return nil, err
- }
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpResponse(resp, false)
- glog.Infoln(string(dump))
- }
- if resp.StatusCode != http.StatusOK {
- resp.Body.Close()
- return nil, errors.New(resp.Status)
- }
- conn := &http2Conn{r: resp.Body, w: pw}
- conn.remoteAddr, _ = net.ResolveTCPAddr("tcp", http2Node.Addr)
return conn, nil
}
-
-// Use HTTP2 as transport to connect target addr.
-//
-// BUG: SOCKS5 is ignored, only HTTP supported
-func (c *ProxyChain) http2Connect(addr string) (net.Conn, error) {
- if !c.Http2Enabled() {
- return nil, errors.New("HTTP2 is not enabled")
- }
- http2Node := c.nodes[c.http2NodeIndex]
-
- header := make(http.Header)
- header.Set("Gost-Target", addr) // Flag header to indicate the address that server connected to
- if http2Node.Users != nil {
- header.Set("Proxy-Authorization",
- "Basic "+base64.StdEncoding.EncodeToString([]byte(http2Node.Users[0].String())))
- }
- return c.getHttp2Conn(header)
-}
diff --git a/client.go b/client.go
new file mode 100644
index 0000000..d26ffa6
--- /dev/null
+++ b/client.go
@@ -0,0 +1,174 @@
+package gost
+
+import (
+ "crypto/tls"
+ "net"
+ "net/url"
+ "time"
+)
+
+// Client is a proxy client.
+// A client is divided into two layers: connector and transporter.
+// Connector is responsible for connecting to the destination address through this proxy.
+// Transporter performs a handshake with this proxy.
+type Client struct {
+ Connector Connector
+ Transporter Transporter
+}
+
+// Dial connects to the target address.
+func (c *Client) Dial(addr string, options ...DialOption) (net.Conn, error) {
+ return c.Transporter.Dial(addr, options...)
+}
+
+// Handshake performs a handshake with the proxy over connection conn.
+func (c *Client) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
+ return c.Transporter.Handshake(conn, options...)
+}
+
+// Connect connects to the address addr via the proxy over connection conn.
+func (c *Client) Connect(conn net.Conn, addr string) (net.Conn, error) {
+ return c.Connector.Connect(conn, addr)
+}
+
+// DefaultClient is a standard HTTP proxy client.
+var DefaultClient = &Client{Connector: HTTPConnector(nil), Transporter: TCPTransporter()}
+
+// Dial connects to the address addr via the DefaultClient.
+func Dial(addr string, options ...DialOption) (net.Conn, error) {
+ return DefaultClient.Dial(addr, options...)
+}
+
+// Handshake performs a handshake via the DefaultClient.
+func Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
+ return DefaultClient.Handshake(conn, options...)
+}
+
+// Connect connects to the address addr via the DefaultClient.
+func Connect(conn net.Conn, addr string) (net.Conn, error) {
+ return DefaultClient.Connect(conn, addr)
+}
+
+// Connector is responsible for connecting to the destination address.
+type Connector interface {
+ Connect(conn net.Conn, addr string) (net.Conn, error)
+}
+
+// Transporter is responsible for handshaking with the proxy server.
+type Transporter interface {
+ Dial(addr string, options ...DialOption) (net.Conn, error)
+ Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error)
+ // Indicate that the Transporter supports multiplex
+ Multiplex() bool
+}
+
+type tcpTransporter struct {
+}
+
+// TCPTransporter creates a transporter for TCP proxy client.
+func TCPTransporter() Transporter {
+ return &tcpTransporter{}
+}
+
+func (tr *tcpTransporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
+ opts := &DialOptions{}
+ for _, option := range options {
+ option(opts)
+ }
+ if opts.Chain == nil {
+ return net.DialTimeout("tcp", addr, opts.Timeout)
+ }
+ return opts.Chain.Dial(addr)
+}
+
+func (tr *tcpTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
+ return conn, nil
+}
+
+func (tr *tcpTransporter) Multiplex() bool {
+ return false
+}
+
+// DialOptions describes the options for dialing.
+type DialOptions struct {
+ Timeout time.Duration
+ Chain *Chain
+}
+
+// DialOption allows a common way to set dial options.
+type DialOption func(opts *DialOptions)
+
+func TimeoutDialOption(timeout time.Duration) DialOption {
+ return func(opts *DialOptions) {
+ opts.Timeout = timeout
+ }
+}
+
+func ChainDialOption(chain *Chain) DialOption {
+ return func(opts *DialOptions) {
+ opts.Chain = chain
+ }
+}
+
+// HandshakeOptions describes the options for handshake.
+type HandshakeOptions struct {
+ Addr string
+ User *url.Userinfo
+ Timeout time.Duration
+ Interval time.Duration
+ TLSConfig *tls.Config
+ WSOptions *WSOptions
+ KCPConfig *KCPConfig
+ QUICConfig *QUICConfig
+}
+
+// HandshakeOption allows a common way to set handshake options.
+type HandshakeOption func(opts *HandshakeOptions)
+
+func AddrHandshakeOption(addr string) HandshakeOption {
+ return func(opts *HandshakeOptions) {
+ opts.Addr = addr
+ }
+}
+
+func UserHandshakeOption(user *url.Userinfo) HandshakeOption {
+ return func(opts *HandshakeOptions) {
+ opts.User = user
+ }
+}
+
+func TimeoutHandshakeOption(timeout time.Duration) HandshakeOption {
+ return func(opts *HandshakeOptions) {
+ opts.Timeout = timeout
+ }
+}
+
+func IntervalHandshakeOption(interval time.Duration) HandshakeOption {
+ return func(opts *HandshakeOptions) {
+ opts.Interval = interval
+ }
+}
+
+func TLSConfigHandshakeOption(config *tls.Config) HandshakeOption {
+ return func(opts *HandshakeOptions) {
+ opts.TLSConfig = config
+ }
+}
+
+func WSOptionsHandshakeOption(options *WSOptions) HandshakeOption {
+ return func(opts *HandshakeOptions) {
+ opts.WSOptions = options
+ }
+}
+
+func KCPConfigHandshakeOption(config *KCPConfig) HandshakeOption {
+ return func(opts *HandshakeOptions) {
+ opts.KCPConfig = config
+ }
+}
+
+func QUICConfigHandshakeOption(config *QUICConfig) HandshakeOption {
+ return func(opts *HandshakeOptions) {
+ opts.QUICConfig = config
+ }
+}
diff --git a/cmd/gost/kcp.json b/cmd/gost/kcp.json
index d23550d..00a576a 100644
--- a/cmd/gost/kcp.json
+++ b/cmd/gost/kcp.json
@@ -15,5 +15,7 @@
"resend": 0,
"nc": 0,
"sockbuf": 4194304,
- "keepalive": 10
+ "keepalive": 10,
+ "snmplog": "",
+ "snmpperiod": 60
}
\ No newline at end of file
diff --git a/cmd/gost/main.go b/cmd/gost/main.go
index 0fd8175..8efb8ee 100644
--- a/cmd/gost/main.go
+++ b/cmd/gost/main.go
@@ -1,22 +1,30 @@
package main
import (
+ "bufio"
"crypto/tls"
+ "crypto/x509"
"encoding/json"
+ "errors"
"flag"
"fmt"
- "github.com/ginuerzh/gost"
- "github.com/golang/glog"
- "golang.org/x/net/http2"
"io/ioutil"
+ "net"
+ "net/url"
"os"
"runtime"
- "sync"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/ginuerzh/gost"
+ "github.com/go-log/log"
)
var (
options struct {
- ChainNodes, ServeNodes flagStringList
+ chainNodes, serveNodes stringList
+ debugMode bool
}
)
@@ -26,64 +34,370 @@ func init() {
printVersion bool
)
+ flag.Var(&options.chainNodes, "F", "forward address, can make a forward chain")
+ flag.Var(&options.serveNodes, "L", "listen address, can listen on multiple ports")
flag.StringVar(&configureFile, "C", "", "configure file")
- flag.Var(&options.ChainNodes, "F", "forward address, can make a forward chain")
- flag.Var(&options.ServeNodes, "L", "listen address, can listen on multiple ports")
+ flag.BoolVar(&options.debugMode, "D", false, "enable debug log")
flag.BoolVar(&printVersion, "V", false, "print version")
flag.Parse()
if err := loadConfigureFile(configureFile); err != nil {
- glog.Fatal(err)
- }
-
- if glog.V(5) {
- http2.VerboseLogs = true
+ log.Log(err)
+ os.Exit(1)
}
if flag.NFlag() == 0 {
flag.PrintDefaults()
- return
+ os.Exit(0)
}
if printVersion {
fmt.Fprintf(os.Stderr, "gost %s (%s)\n", gost.Version, runtime.Version())
- return
+ os.Exit(0)
}
+
+ gost.Debug = options.debugMode
}
func main() {
- chain := gost.NewProxyChain()
- if err := chain.AddProxyNodeString(options.ChainNodes...); err != nil {
- glog.Fatal(err)
+ chain, err := initChain()
+ if err != nil {
+ log.Log(err)
+ os.Exit(1)
}
- chain.Init()
+ if err := serve(chain); err != nil {
+ log.Log(err)
+ os.Exit(1)
+ }
+ select {}
+}
- var wg sync.WaitGroup
- for _, ns := range options.ServeNodes {
- serverNode, err := gost.ParseProxyNode(ns, true) // isServeNode == true
+func initChain() (*gost.Chain, error) {
+ chain := gost.NewChain()
+ for _, ns := range options.chainNodes {
+ node, err := gost.ParseNode(ns)
if err != nil {
- glog.Fatal(err)
+ return nil, err
}
- wg.Add(1)
- go func(node gost.ProxyNode) {
- defer wg.Done()
- certFile, keyFile := node.Get("cert"), node.Get("key")
- if certFile == "" {
- certFile = gost.DefaultCertFile
+ serverName, _, _ := net.SplitHostPort(node.Addr)
+ if serverName == "" {
+ serverName = "localhost" // default server name
+ }
+
+ rootCAs, err := loadCA(node.Values.Get("ca"))
+ if err != nil {
+ return nil, err
+ }
+ tlsCfg := &tls.Config{
+ ServerName: serverName,
+ InsecureSkipVerify: !toBool(node.Values.Get("scure")),
+ RootCAs: rootCAs,
+ }
+ var tr gost.Transporter
+ switch node.Transport {
+ case "tls":
+ tr = gost.TLSTransporter()
+ case "ws":
+ wsOpts := &gost.WSOptions{}
+ wsOpts.EnableCompression = toBool(node.Values.Get("compression"))
+ wsOpts.ReadBufferSize, _ = strconv.Atoi(node.Values.Get("rbuf"))
+ wsOpts.WriteBufferSize, _ = strconv.Atoi(node.Values.Get("wbuf"))
+ node.HandshakeOptions = append(node.HandshakeOptions,
+ gost.WSOptionsHandshakeOption(wsOpts),
+ )
+ tr = gost.WSTransporter(nil)
+ case "wss":
+ tr = gost.WSSTransporter(nil)
+ case "kcp":
+ if !chain.IsEmpty() {
+ return nil, errors.New("KCP must be the first node in the proxy chain")
}
- if keyFile == "" {
- keyFile = gost.DefaultKeyFile
- }
- cert, err := gost.LoadCertificate(certFile, keyFile)
+ config, err := parseKCPConfig(node.Values.Get("c"))
if err != nil {
- glog.Fatal(err)
+ log.Log("[kcp]", err)
}
- server := gost.NewProxyServer(node, chain, &tls.Config{Certificates: []tls.Certificate{cert}})
- glog.Fatal(server.Serve())
- }(serverNode)
+ node.HandshakeOptions = append(node.HandshakeOptions,
+ gost.KCPConfigHandshakeOption(config),
+ )
+ tr = gost.KCPTransporter(nil)
+ case "ssh":
+ if node.Protocol == "direct" || node.Protocol == "remote" || node.Protocol == "forward" {
+ tr = gost.SSHForwardTransporter()
+ } else {
+ tr = gost.SSHTunnelTransporter()
+ }
+
+ node.DialOptions = append(node.DialOptions,
+ gost.ChainDialOption(chain),
+ )
+ chain = gost.NewChain() // cutoff the chain for multiplex
+ case "quic":
+ if !chain.IsEmpty() {
+ return nil, errors.New("QUIC must be the first node in the proxy chain")
+ }
+ config := &gost.QUICConfig{
+ TLSConfig: tlsCfg,
+ KeepAlive: toBool(node.Values.Get("keepalive")),
+ }
+ node.HandshakeOptions = append(node.HandshakeOptions,
+ gost.QUICConfigHandshakeOption(config),
+ )
+ tr = gost.QUICTransporter(nil)
+ case "http2":
+ tr = gost.HTTP2Transporter(nil)
+ node.DialOptions = append(node.DialOptions,
+ gost.ChainDialOption(chain),
+ )
+ chain = gost.NewChain() // cutoff the chain for multiplex
+ case "h2":
+ tr = gost.H2Transporter(nil)
+ node.DialOptions = append(node.DialOptions,
+ gost.ChainDialOption(chain),
+ )
+ chain = gost.NewChain() // cutoff the chain for multiplex
+ case "h2c":
+ tr = gost.H2CTransporter()
+ node.DialOptions = append(node.DialOptions,
+ gost.ChainDialOption(chain),
+ )
+ chain = gost.NewChain() // cutoff the chain for multiplex
+ case "obfs4":
+ if err := gost.Obfs4Init(node, false); err != nil {
+ return nil, err
+ }
+ tr = gost.Obfs4Transporter()
+ default:
+ tr = gost.TCPTransporter()
+ }
+
+ var connector gost.Connector
+ switch node.Protocol {
+ case "http2":
+ connector = gost.HTTP2Connector(node.User)
+ case "socks", "socks5":
+ connector = gost.SOCKS5Connector(node.User)
+ case "socks4":
+ connector = gost.SOCKS4Connector()
+ case "socks4a":
+ connector = gost.SOCKS4AConnector()
+ case "ss":
+ connector = gost.ShadowConnector(node.User)
+ case "direct", "forward":
+ connector = gost.SSHDirectForwardConnector()
+ case "remote":
+ connector = gost.SSHRemoteForwardConnector()
+ case "http":
+ fallthrough
+ default:
+ node.Protocol = "http" // default protocol is HTTP
+ connector = gost.HTTPConnector(node.User)
+ }
+
+ node.DialOptions = append(node.DialOptions,
+ gost.TimeoutDialOption(gost.DialTimeout),
+ )
+
+ interval, _ := strconv.Atoi(node.Values.Get("ping"))
+ node.HandshakeOptions = append(node.HandshakeOptions,
+ gost.AddrHandshakeOption(node.Addr),
+ gost.UserHandshakeOption(node.User),
+ gost.TLSConfigHandshakeOption(tlsCfg),
+ gost.IntervalHandshakeOption(time.Duration(interval)*time.Second),
+ )
+ node.Client = &gost.Client{
+ Connector: connector,
+ Transporter: tr,
+ }
+ chain.AddNode(node)
}
- wg.Wait()
+
+ return chain, nil
+}
+
+func serve(chain *gost.Chain) error {
+ for _, ns := range options.serveNodes {
+ node, err := gost.ParseNode(ns)
+ if err != nil {
+ return err
+ }
+ users, err := parseUsers(node.Values.Get("secrets"))
+ if err != nil {
+ return err
+ }
+ if node.User != nil {
+ users = append(users, node.User)
+ }
+ tlsCfg, _ := tlsConfig(node.Values.Get("cert"), node.Values.Get("key"))
+
+ var ln gost.Listener
+ switch node.Transport {
+ case "tls":
+ ln, err = gost.TLSListener(node.Addr, tlsCfg)
+ case "ws":
+ wsOpts := &gost.WSOptions{}
+ wsOpts.EnableCompression = toBool(node.Values.Get("compression"))
+ wsOpts.ReadBufferSize, _ = strconv.Atoi(node.Values.Get("rbuf"))
+ wsOpts.WriteBufferSize, _ = strconv.Atoi(node.Values.Get("wbuf"))
+ ln, err = gost.WSListener(node.Addr, wsOpts)
+ case "wss":
+ wsOpts := &gost.WSOptions{}
+ wsOpts.EnableCompression = toBool(node.Values.Get("compression"))
+ wsOpts.ReadBufferSize, _ = strconv.Atoi(node.Values.Get("rbuf"))
+ wsOpts.WriteBufferSize, _ = strconv.Atoi(node.Values.Get("wbuf"))
+ ln, err = gost.WSSListener(node.Addr, tlsCfg, wsOpts)
+ case "kcp":
+ config, err := parseKCPConfig(node.Values.Get("c"))
+ if err != nil {
+ log.Log("[kcp]", err)
+ }
+ ln, err = gost.KCPListener(node.Addr, config)
+ case "ssh":
+ config := &gost.SSHConfig{
+ Users: users,
+ TLSConfig: tlsCfg,
+ }
+ if node.Protocol == "forward" {
+ ln, err = gost.TCPListener(node.Addr)
+ } else {
+ ln, err = gost.SSHTunnelListener(node.Addr, config)
+ }
+ case "quic":
+ config := &gost.QUICConfig{
+ TLSConfig: tlsCfg,
+ KeepAlive: toBool(node.Values.Get("keepalive")),
+ }
+ timeout, _ := strconv.Atoi(node.Values.Get("timeout"))
+ config.Timeout = time.Duration(timeout) * time.Second
+ ln, err = gost.QUICListener(node.Addr, config)
+ case "http2":
+ ln, err = gost.HTTP2Listener(node.Addr, tlsCfg)
+ case "h2":
+ ln, err = gost.H2Listener(node.Addr, tlsCfg)
+ case "h2c":
+ ln, err = gost.H2CListener(node.Addr)
+ case "obfs4":
+ if err = gost.Obfs4Init(node, true); err != nil {
+ return err
+ }
+ ln, err = gost.Obfs4Listener(node.Addr)
+ case "tcp":
+ ln, err = gost.TCPListener(node.Addr)
+ case "rtcp":
+ if chain.LastNode().Protocol == "forward" && chain.LastNode().Transport == "ssh" {
+ chain.Nodes()[len(chain.Nodes())-1].Client.Connector = gost.SSHRemoteForwardConnector()
+ }
+ ln, err = gost.TCPRemoteForwardListener(node.Addr, chain)
+ case "udp":
+ ttl, _ := strconv.Atoi(node.Values.Get("ttl"))
+ ln, err = gost.UDPDirectForwardListener(node.Addr, time.Duration(ttl)*time.Second)
+ case "rudp":
+ ttl, _ := strconv.Atoi(node.Values.Get("ttl"))
+ ln, err = gost.UDPRemoteForwardListener(node.Addr, chain, time.Duration(ttl)*time.Second)
+ case "redirect":
+ ln, err = gost.TCPListener(node.Addr)
+ case "ssu":
+ ttl, _ := strconv.Atoi(node.Values.Get("ttl"))
+ ln, err = gost.ShadowUDPListener(node.Addr, node.User, time.Duration(ttl)*time.Second)
+ default:
+ ln, err = gost.TCPListener(node.Addr)
+ }
+ if err != nil {
+ return err
+ }
+
+ var whitelist, blacklist *gost.Permissions
+ if node.Values.Get("whitelist") != "" {
+ if whitelist, err = gost.ParsePermissions(node.Values.Get("whitelist")); err != nil {
+ return err
+ }
+ } else {
+ // By default allow for everyting
+ whitelist, _ = gost.ParsePermissions("*:*:*")
+ }
+
+ if node.Values.Get("blacklist") != "" {
+ if blacklist, err = gost.ParsePermissions(node.Values.Get("blacklist")); err != nil {
+ return err
+ }
+ } else {
+ // By default block nothing
+ blacklist, _ = gost.ParsePermissions("")
+ }
+
+ var handlerOptions []gost.HandlerOption
+
+ handlerOptions = append(handlerOptions,
+ gost.AddrHandlerOption(node.Addr),
+ gost.ChainHandlerOption(chain),
+ gost.UsersHandlerOption(users...),
+ gost.TLSConfigHandlerOption(tlsCfg),
+ gost.WhitelistHandlerOption(whitelist),
+ gost.BlacklistHandlerOption(blacklist),
+ )
+ var handler gost.Handler
+ switch node.Protocol {
+ case "http2":
+ handler = gost.HTTP2Handler(handlerOptions...)
+ case "socks", "socks5":
+ handler = gost.SOCKS5Handler(handlerOptions...)
+ case "socks4", "socks4a":
+ handler = gost.SOCKS4Handler(handlerOptions...)
+ case "ss":
+ handler = gost.ShadowHandler(handlerOptions...)
+ case "http":
+ handler = gost.HTTPHandler(handlerOptions...)
+ case "tcp":
+ handler = gost.TCPDirectForwardHandler(node.Remote, handlerOptions...)
+ case "rtcp":
+ handler = gost.TCPRemoteForwardHandler(node.Remote, handlerOptions...)
+ case "udp":
+ handler = gost.UDPDirectForwardHandler(node.Remote, handlerOptions...)
+ case "rudp":
+ handler = gost.UDPRemoteForwardHandler(node.Remote, handlerOptions...)
+ case "forward":
+ handler = gost.SSHForwardHandler(handlerOptions...)
+ case "redirect":
+ handler = gost.TCPRedirectHandler(handlerOptions...)
+ case "ssu":
+ handler = gost.ShadowUDPdHandler(handlerOptions...)
+ default:
+ handler = gost.AutoHandler(handlerOptions...)
+ }
+ go new(gost.Server).Serve(ln, handler)
+ }
+
+ return nil
+}
+
+// Load the certificate from cert and key files, will use the default certificate if the provided info are invalid.
+func tlsConfig(certFile, keyFile string) (*tls.Config, error) {
+ if certFile == "" {
+ certFile = "cert.pem"
+ }
+ if keyFile == "" {
+ keyFile = "key.pem"
+ }
+ cert, err := tls.LoadX509KeyPair(certFile, keyFile)
+ if err != nil {
+ return nil, err
+ }
+ return &tls.Config{Certificates: []tls.Certificate{cert}}, nil
+}
+
+func loadCA(caFile string) (cp *x509.CertPool, err error) {
+ if caFile == "" {
+ return
+ }
+ cp = x509.NewCertPool()
+ data, err := ioutil.ReadFile(caFile)
+ if err != nil {
+ return nil, err
+ }
+ if !cp.AppendCertsFromPEM(data) {
+ return nil, errors.New("AppendCertsFromPEM failed")
+ }
+ return
}
func loadConfigureFile(configureFile string) error {
@@ -100,12 +414,65 @@ func loadConfigureFile(configureFile string) error {
return nil
}
-type flagStringList []string
+type stringList []string
-func (this *flagStringList) String() string {
- return fmt.Sprintf("%s", *this)
+func (l *stringList) String() string {
+ return fmt.Sprintf("%s", *l)
}
-func (this *flagStringList) Set(value string) error {
- *this = append(*this, value)
+func (l *stringList) Set(value string) error {
+ *l = append(*l, value)
return nil
}
+
+func toBool(s string) bool {
+ if b, _ := strconv.ParseBool(s); b {
+ return b
+ }
+ n, _ := strconv.Atoi(s)
+ return n > 0
+}
+
+func parseKCPConfig(configFile string) (*gost.KCPConfig, error) {
+ if configFile == "" {
+ return nil, nil
+ }
+ file, err := os.Open(configFile)
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+
+ config := &gost.KCPConfig{}
+ if err = json.NewDecoder(file).Decode(config); err != nil {
+ return nil, err
+ }
+ return config, nil
+}
+
+func parseUsers(authFile string) (users []*url.Userinfo, err error) {
+ if authFile == "" {
+ return
+ }
+
+ file, err := os.Open(authFile)
+ if err != nil {
+ return
+ }
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ line := strings.TrimSpace(scanner.Text())
+ if line == "" || strings.HasPrefix(line, "#") {
+ continue
+ }
+
+ s := strings.SplitN(line, " ", 2)
+ if len(s) == 1 {
+ users = append(users, url.User(strings.TrimSpace(s[0])))
+ } else if len(s) == 2 {
+ users = append(users, url.UserPassword(strings.TrimSpace(s[0]), strings.TrimSpace(s[1])))
+ }
+ }
+
+ err = scanner.Err()
+ return
+}
diff --git a/cmd/gost/secrets.txt b/cmd/gost/secrets.txt
index 5a4b77b..a2a94f7 100644
--- a/cmd/gost/secrets.txt
+++ b/cmd/gost/secrets.txt
@@ -1,4 +1,6 @@
# username password
+test\admin 123456
+$test 123456
test001 123456
test002 12345678
\ No newline at end of file
diff --git a/cmd/gost/vendor/github.com/codahale/chacha20/README.md b/cmd/gost/vendor/github.com/codahale/chacha20/README.md
deleted file mode 100644
index e0cc2ec..0000000
--- a/cmd/gost/vendor/github.com/codahale/chacha20/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-chacha20
-========
-
-[](https://travis-ci.org/codahale/chacha20)
-
-A pure Go implementation of the ChaCha20 stream cipher.
-
-For documentation, check [godoc](http://godoc.org/github.com/codahale/chacha20).
diff --git a/cmd/gost/vendor/github.com/codahale/chacha20/chacha20.go b/cmd/gost/vendor/github.com/codahale/chacha20/chacha20.go
deleted file mode 100644
index ae671bc..0000000
--- a/cmd/gost/vendor/github.com/codahale/chacha20/chacha20.go
+++ /dev/null
@@ -1,235 +0,0 @@
-// Package chacha20 provides a pure Go implementation of ChaCha20, a fast,
-// secure stream cipher.
-//
-// From Bernstein, Daniel J. "ChaCha, a variant of Salsa20." Workshop Record of
-// SASC. 2008. (http://cr.yp.to/chacha/chacha-20080128.pdf):
-//
-// ChaCha8 is a 256-bit stream cipher based on the 8-round cipher Salsa20/8.
-// The changes from Salsa20/8 to ChaCha8 are designed to improve diffusion per
-// round, conjecturally increasing resistance to cryptanalysis, while
-// preserving -- and often improving -- time per round. ChaCha12 and ChaCha20
-// are analogous modifications of the 12-round and 20-round ciphers Salsa20/12
-// and Salsa20/20. This paper presents the ChaCha family and explains the
-// differences between Salsa20 and ChaCha.
-//
-// For more information, see http://cr.yp.to/chacha.html
-package chacha20
-
-import (
- "crypto/cipher"
- "encoding/binary"
- "errors"
- "unsafe"
-)
-
-const (
- // KeySize is the length of ChaCha20 keys, in bytes.
- KeySize = 32
- // NonceSize is the length of ChaCha20 nonces, in bytes.
- NonceSize = 8
- // XNonceSize is the length of XChaCha20 nonces, in bytes.
- XNonceSize = 24
-)
-
-var (
- // ErrInvalidKey is returned when the provided key is not 256 bits long.
- ErrInvalidKey = errors.New("invalid key length (must be 256 bits)")
- // ErrInvalidNonce is returned when the provided nonce is not 64 bits long.
- ErrInvalidNonce = errors.New("invalid nonce length (must be 64 bits)")
- // ErrInvalidXNonce is returned when the provided nonce is not 192 bits
- // long.
- ErrInvalidXNonce = errors.New("invalid nonce length (must be 192 bits)")
- // ErrInvalidRounds is returned when the provided rounds is not
- // 8, 12, or 20.
- ErrInvalidRounds = errors.New("invalid rounds number (must be 8, 12, or 20)")
-)
-
-// New creates and returns a new cipher.Stream. The key argument must be 256
-// bits long, and the nonce argument must be 64 bits long. The nonce must be
-// randomly generated or used only once. This Stream instance must not be used
-// to encrypt more than 2^70 bytes (~1 zettabyte).
-func New(key []byte, nonce []byte) (cipher.Stream, error) {
- return NewWithRounds(key, nonce, 20)
-}
-
-// NewWithRounds creates and returns a new cipher.Stream just like New but
-// the rounds number of 8, 12, or 20 can be specified.
-func NewWithRounds(key []byte, nonce []byte, rounds uint8) (cipher.Stream, error) {
- if len(key) != KeySize {
- return nil, ErrInvalidKey
- }
-
- if len(nonce) != NonceSize {
- return nil, ErrInvalidNonce
- }
-
- if (rounds != 8) && (rounds != 12) && (rounds != 20) {
- return nil, ErrInvalidRounds
- }
-
- s := new(stream)
- s.init(key, nonce, rounds)
- s.advance()
-
- return s, nil
-}
-
-// NewXChaCha creates and returns a new cipher.Stream. The key argument must be
-// 256 bits long, and the nonce argument must be 192 bits long. The nonce must
-// be randomly generated or only used once. This Stream instance must not be
-// used to encrypt more than 2^70 bytes (~1 zetta byte).
-func NewXChaCha(key []byte, nonce []byte) (cipher.Stream, error) {
- return NewXChaChaWithRounds(key, nonce, 20)
-}
-
-// NewXChaChaWithRounds creates and returns a new cipher.Stream just like
-// NewXChaCha but the rounds number of 8, 12, or 20 can be specified.
-func NewXChaChaWithRounds(key []byte, nonce []byte, rounds uint8) (cipher.Stream, error) {
- if len(key) != KeySize {
- return nil, ErrInvalidKey
- }
-
- if len(nonce) != XNonceSize {
- return nil, ErrInvalidXNonce
- }
-
- if (rounds != 8) && (rounds != 12) && (rounds != 20) {
- return nil, ErrInvalidRounds
- }
-
- s := new(stream)
- s.init(key, nonce, rounds)
-
- // Call HChaCha to derive the subkey using the key and the first 16 bytes
- // of the nonce, and re-initialize the state using the subkey and the
- // remaining nonce.
- blockArr := (*[stateSize]uint32)(unsafe.Pointer(&s.block))
- core(&s.state, blockArr, s.rounds, true)
- copy(s.state[4:8], blockArr[0:4])
- copy(s.state[8:12], blockArr[12:16])
- s.state[12] = 0
- s.state[13] = 0
- s.state[14] = binary.LittleEndian.Uint32(nonce[16:])
- s.state[15] = binary.LittleEndian.Uint32(nonce[20:])
-
- s.advance()
-
- return s, nil
-}
-
-type stream struct {
- state [stateSize]uint32 // the state as an array of 16 32-bit words
- block [blockSize]byte // the keystream as an array of 64 bytes
- offset int // the offset of used bytes in block
- rounds uint8
-}
-
-func (s *stream) XORKeyStream(dst, src []byte) {
- // Stride over the input in 64-byte blocks, minus the amount of keystream
- // previously used. This will produce best results when processing blocks
- // of a size evenly divisible by 64.
- i := 0
- max := len(src)
- for i < max {
- gap := blockSize - s.offset
-
- limit := i + gap
- if limit > max {
- limit = max
- }
-
- o := s.offset
- for j := i; j < limit; j++ {
- dst[j] = src[j] ^ s.block[o]
- o++
- }
-
- i += gap
- s.offset = o
-
- if o == blockSize {
- s.advance()
- }
- }
-}
-
-func (s *stream) init(key []byte, nonce []byte, rounds uint8) {
- // the magic constants for 256-bit keys
- s.state[0] = 0x61707865
- s.state[1] = 0x3320646e
- s.state[2] = 0x79622d32
- s.state[3] = 0x6b206574
-
- s.state[4] = binary.LittleEndian.Uint32(key[0:])
- s.state[5] = binary.LittleEndian.Uint32(key[4:])
- s.state[6] = binary.LittleEndian.Uint32(key[8:])
- s.state[7] = binary.LittleEndian.Uint32(key[12:])
- s.state[8] = binary.LittleEndian.Uint32(key[16:])
- s.state[9] = binary.LittleEndian.Uint32(key[20:])
- s.state[10] = binary.LittleEndian.Uint32(key[24:])
- s.state[11] = binary.LittleEndian.Uint32(key[28:])
-
- switch len(nonce) {
- case NonceSize:
- // ChaCha20 uses 8 byte nonces.
- s.state[12] = 0
- s.state[13] = 0
- s.state[14] = binary.LittleEndian.Uint32(nonce[0:])
- s.state[15] = binary.LittleEndian.Uint32(nonce[4:])
- case XNonceSize:
- // XChaCha20 derives the subkey via HChaCha initialized
- // with the first 16 bytes of the nonce.
- s.state[12] = binary.LittleEndian.Uint32(nonce[0:])
- s.state[13] = binary.LittleEndian.Uint32(nonce[4:])
- s.state[14] = binary.LittleEndian.Uint32(nonce[8:])
- s.state[15] = binary.LittleEndian.Uint32(nonce[12:])
- default:
- // Never happens, both ctors validate the nonce length.
- panic("invalid nonce size")
- }
-
- s.rounds = rounds
-}
-
-// BUG(codahale): Totally untested on big-endian CPUs. Would very much
-// appreciate someone with an ARM device giving this a swing.
-
-// advances the keystream
-func (s *stream) advance() {
- core(&s.state, (*[stateSize]uint32)(unsafe.Pointer(&s.block)), s.rounds, false)
-
- if bigEndian {
- j := blockSize - 1
- for i := 0; i < blockSize/2; i++ {
- s.block[j], s.block[i] = s.block[i], s.block[j]
- j--
- }
- }
-
- s.offset = 0
- i := s.state[12] + 1
- s.state[12] = i
- if i == 0 {
- s.state[13]++
- }
-}
-
-const (
- wordSize = 4 // the size of ChaCha20's words
- stateSize = 16 // the size of ChaCha20's state, in words
- blockSize = stateSize * wordSize // the size of ChaCha20's block, in bytes
-)
-
-var (
- bigEndian bool // whether or not we're running on a bigEndian CPU
-)
-
-// Do some up-front bookkeeping on what sort of CPU we're using. ChaCha20 treats
-// its state as a little-endian byte array when it comes to generating the
-// keystream, which allows for a zero-copy approach to the core transform. On
-// big-endian architectures, we have to take a hit to reverse the bytes.
-func init() {
- x := uint32(0x04030201)
- y := [4]byte{0x1, 0x2, 0x3, 0x4}
- bigEndian = *(*[4]byte)(unsafe.Pointer(&x)) != y
-}
diff --git a/cmd/gost/vendor/github.com/codahale/chacha20/core_ref.go b/cmd/gost/vendor/github.com/codahale/chacha20/core_ref.go
deleted file mode 100644
index 84f5e6c..0000000
--- a/cmd/gost/vendor/github.com/codahale/chacha20/core_ref.go
+++ /dev/null
@@ -1,166 +0,0 @@
-// The ChaCha20 core transform.
-// An unrolled and inlined implementation in pure Go.
-
-package chacha20
-
-func core(input, output *[stateSize]uint32, rounds uint8, hchacha bool) {
- var (
- x00 = input[0]
- x01 = input[1]
- x02 = input[2]
- x03 = input[3]
- x04 = input[4]
- x05 = input[5]
- x06 = input[6]
- x07 = input[7]
- x08 = input[8]
- x09 = input[9]
- x10 = input[10]
- x11 = input[11]
- x12 = input[12]
- x13 = input[13]
- x14 = input[14]
- x15 = input[15]
- )
-
- var x uint32
-
- // Unrolling all 20 rounds kills performance on modern Intel processors
- // (Tested on a i5 Haswell, likely applies to Sandy Bridge+), due to uop
- // cache thrashing. The straight forward 2 rounds per loop implementation
- // of this has double the performance of the fully unrolled version.
- for i := uint8(0); i < rounds; i += 2 {
- x00 += x04
- x = x12 ^ x00
- x12 = (x << 16) | (x >> 16)
- x08 += x12
- x = x04 ^ x08
- x04 = (x << 12) | (x >> 20)
- x00 += x04
- x = x12 ^ x00
- x12 = (x << 8) | (x >> 24)
- x08 += x12
- x = x04 ^ x08
- x04 = (x << 7) | (x >> 25)
- x01 += x05
- x = x13 ^ x01
- x13 = (x << 16) | (x >> 16)
- x09 += x13
- x = x05 ^ x09
- x05 = (x << 12) | (x >> 20)
- x01 += x05
- x = x13 ^ x01
- x13 = (x << 8) | (x >> 24)
- x09 += x13
- x = x05 ^ x09
- x05 = (x << 7) | (x >> 25)
- x02 += x06
- x = x14 ^ x02
- x14 = (x << 16) | (x >> 16)
- x10 += x14
- x = x06 ^ x10
- x06 = (x << 12) | (x >> 20)
- x02 += x06
- x = x14 ^ x02
- x14 = (x << 8) | (x >> 24)
- x10 += x14
- x = x06 ^ x10
- x06 = (x << 7) | (x >> 25)
- x03 += x07
- x = x15 ^ x03
- x15 = (x << 16) | (x >> 16)
- x11 += x15
- x = x07 ^ x11
- x07 = (x << 12) | (x >> 20)
- x03 += x07
- x = x15 ^ x03
- x15 = (x << 8) | (x >> 24)
- x11 += x15
- x = x07 ^ x11
- x07 = (x << 7) | (x >> 25)
- x00 += x05
- x = x15 ^ x00
- x15 = (x << 16) | (x >> 16)
- x10 += x15
- x = x05 ^ x10
- x05 = (x << 12) | (x >> 20)
- x00 += x05
- x = x15 ^ x00
- x15 = (x << 8) | (x >> 24)
- x10 += x15
- x = x05 ^ x10
- x05 = (x << 7) | (x >> 25)
- x01 += x06
- x = x12 ^ x01
- x12 = (x << 16) | (x >> 16)
- x11 += x12
- x = x06 ^ x11
- x06 = (x << 12) | (x >> 20)
- x01 += x06
- x = x12 ^ x01
- x12 = (x << 8) | (x >> 24)
- x11 += x12
- x = x06 ^ x11
- x06 = (x << 7) | (x >> 25)
- x02 += x07
- x = x13 ^ x02
- x13 = (x << 16) | (x >> 16)
- x08 += x13
- x = x07 ^ x08
- x07 = (x << 12) | (x >> 20)
- x02 += x07
- x = x13 ^ x02
- x13 = (x << 8) | (x >> 24)
- x08 += x13
- x = x07 ^ x08
- x07 = (x << 7) | (x >> 25)
- x03 += x04
- x = x14 ^ x03
- x14 = (x << 16) | (x >> 16)
- x09 += x14
- x = x04 ^ x09
- x04 = (x << 12) | (x >> 20)
- x03 += x04
- x = x14 ^ x03
- x14 = (x << 8) | (x >> 24)
- x09 += x14
- x = x04 ^ x09
- x04 = (x << 7) | (x >> 25)
- }
-
- if !hchacha {
- output[0] = x00 + input[0]
- output[1] = x01 + input[1]
- output[2] = x02 + input[2]
- output[3] = x03 + input[3]
- output[4] = x04 + input[4]
- output[5] = x05 + input[5]
- output[6] = x06 + input[6]
- output[7] = x07 + input[7]
- output[8] = x08 + input[8]
- output[9] = x09 + input[9]
- output[10] = x10 + input[10]
- output[11] = x11 + input[11]
- output[12] = x12 + input[12]
- output[13] = x13 + input[13]
- output[14] = x14 + input[14]
- output[15] = x15 + input[15]
- } else {
- output[0] = x00
- output[1] = x01
- output[2] = x02
- output[3] = x03
- output[4] = x04
- output[5] = x05
- output[6] = x06
- output[7] = x07
- output[8] = x08
- output[9] = x09
- output[10] = x10
- output[11] = x11
- output[12] = x12
- output[13] = x13
- output[14] = x14
- output[15] = x15
- }
-}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/README.md b/cmd/gost/vendor/github.com/ginuerzh/gost/README.md
deleted file mode 100644
index 031eb1b..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/README.md
+++ /dev/null
@@ -1,352 +0,0 @@
-gost - GO Simple Tunnel
-======
-
-### GO语言实现的安全隧道
-
-[English README](README_en.md)
-
-特性
-------
-* 可同时监听多端口
-* 可设置转发代理,支持多级转发(代理链)
-* 支持标准HTTP/HTTPS/SOCKS5代理协议
-* SOCKS5代理支持TLS协商加密
-* Tunnel UDP over TCP
-* 支持Shadowsocks协议 (OTA: 2.2+,UDP: 2.4+)
-* 支持本地/远程端口转发 (2.1+)
-* 支持HTTP 2.0 (2.2+)
-* 实验性支持QUIC (2.3+)
-* 支持KCP协议 (2.3+)
-* 透明代理 (2.3+)
-
-二进制文件下载:https://github.com/ginuerzh/gost/releases
-
-Google讨论组: https://groups.google.com/d/forum/go-gost
-
-在gost中,gost与其他代理服务都被看作是代理节点,gost可以自己处理请求,或者将请求转发给任意一个或多个代理节点。
-
-参数说明
-------
-#### 代理及代理链
-
-适用于-L和-F参数
-
-```bash
-[scheme://][user:pass@host]:port
-```
-scheme分为两部分: protocol+transport
-
-protocol: 代理协议类型(http, socks5, shadowsocks), transport: 数据传输方式(ws, wss, tls, http2, quic, kcp), 二者可以任意组合,或单独使用:
-
-> http - HTTP代理: http://:8080
-
-> http+tls - HTTPS代理(可能需要提供受信任的证书): http+tls://:443或https://:443
-
-> http2 - HTTP2代理并向下兼容HTTPS代理: http2://:443
-
-> socks - 标准SOCKS5代理(支持tls协商加密): socks://:1080
-
-> socks+wss - SOCKS5代理,使用websocket传输数据: socks+wss://:1080
-
-> tls - HTTPS/SOCKS5代理,使用tls传输数据: tls://:443
-
-> ss - Shadowsocks代理,ss://chacha20:123456@:8338
-
-> ssu - Shadowsocks UDP relay,ssu://chacha20:123456@:8338
-
-> quic - QUIC代理,quic://:6121
-
-> kcp - KCP代理,kcp://:8388或kcp://aes:123456@:8388
-
-> redirect - 透明代理,redirect://:12345
-
-#### 端口转发
-
-适用于-L参数
-
-```bash
-scheme://[bind_address]:port/[host]:hostport
-```
-> scheme - 端口转发模式, 本地端口转发: tcp, udp; 远程端口转发: rtcp, rudp
-
-> bind_address:port - 本地/远程绑定地址
-
-> host:hostport - 目标访问地址
-
-#### 配置文件
-
-> -C : 指定配置文件路径
-
-配置文件为标准json格式:
-```json
-{
- "ServeNodes": [
- ":8080",
- "ss://chacha20:12345678@:8338"
- ],
- "ChainNodes": [
- "http://192.168.1.1:8080",
- "https://10.0.2.1:443"
- ]
-}
-```
-
-ServeNodes等同于-L参数,ChainNodes等同于-F参数
-
-#### 开启日志
-
-> -logtostderr : 输出到控制台
-
-> -v=3 : 日志级别(1-5),级别越高,日志越详细(级别5将开启http2 debug)
-
-> -log_dir=/log/dir/path : 输出到目录/log/dir/path
-
-
-使用方法
-------
-#### 不设置转发代理
-
-
-
-* 作为标准HTTP/SOCKS5代理
-```bash
-gost -L=:8080
-```
-
-* 设置代理认证信息
-```bash
-gost -L=admin:123456@localhost:8080
-```
-
-* 多组认证信息
-```bash
-gost -L=localhost:8080?secrets=secrets.txt
-```
-
-通过secrets参数可以为HTTP/SOCKS5代理设置多组认证信息,格式为:
-```plain
-# username password
-
-test001 123456
-test002 12345678
-```
-
-* 多端口监听
-```bash
-gost -L=http2://:443 -L=socks://:1080 -L=ss://aes-128-cfb:123456@:8338
-```
-
-#### 设置转发代理
-
-
-```bash
-gost -L=:8080 -F=192.168.1.1:8081
-```
-
-* 转发代理认证
-```bash
-gost -L=:8080 -F=http://admin:123456@192.168.1.1:8081
-```
-
-#### 设置多级转发代理(代理链)
-
-
-```bash
-gost -L=:8080 -F=http+tls://192.168.1.1:443 -F=socks+ws://192.168.1.2:1080 -F=ss://aes-128-cfb:123456@192.168.1.3:8338 -F=a.b.c.d:NNNN
-```
-gost按照-F设置的顺序通过代理链将请求最终转发给a.b.c.d:NNNN处理,每一个转发代理可以是任意HTTP/HTTPS/HTTP2/SOCKS5/Shadowsocks类型代理。
-
-#### 本地端口转发(TCP)
-
-```bash
-gost -L=tcp://:2222/192.168.1.1:22 -F=...
-```
-将本地TCP端口2222上的数据(通过代理链)转发到192.168.1.1:22上。
-
-#### 本地端口转发(UDP)
-
-```bash
-gost -L=udp://:5353/192.168.1.1:53?ttl=60 -F=...
-```
-将本地UDP端口5353上的数据(通过代理链)转发到192.168.1.1:53上。
-每条转发通道都有超时时间,当超过此时间,且在此时间段内无任何数据交互,则此通道将关闭。可以通过`ttl`参数来设置超时时间,默认值为60秒。
-
-**注:** 转发UDP数据时,如果有代理链,则代理链的末端(最后一个-F参数)必须是gost SOCKS5类型代理。
-
-#### 远程端口转发(TCP)
-
-```bash
-gost -L=rtcp://:2222/192.168.1.1:22 -F=... -F=socks://172.24.10.1:1080
-```
-将172.24.10.1:2222上的数据(通过代理链)转发到192.168.1.1:22上。
-
-#### 远程端口转发(UDP)
-
-```bash
-gost -L=rudp://:5353/192.168.1.1:53 -F=... -F=socks://172.24.10.1:1080
-```
-将172.24.10.1:5353上的数据(通过代理链)转发到192.168.1.1:53上。
-
-**注:** 若要使用远程端口转发功能,代理链不能为空(至少要设置一个-F参数),且代理链的末端(最后一个-F参数)必须是gost SOCKS5类型代理。
-
-#### HTTP2
-gost的HTTP2支持两种模式并自适应:
-* 作为标准的HTTP2代理,并向下兼容HTTPS代理。
-* 作为transport(类似于wss),传输其他协议。
-
-服务端:
-```bash
-gost -L=http2://:443
-```
-客户端:
-```bash
-gost -L=:8080 -F=http2://server_ip:443?ping=30
-```
-
-客户端支持`ping`参数开启心跳检测(默认不开启),参数值代表心跳间隔秒数。
-
-**注:** gost的代理链仅支持一个HTTP2代理节点,采用就近原则,会将第一个遇到的HTTP2代理节点视为HTTP2代理,其他HTTP2代理节点则被视为HTTPS代理。
-
-#### QUIC
-gost对QUIC的支持是基于[quic-go](https://github.com/lucas-clemente/quic-go)库。
-
-服务端:
-```bash
-gost -L=quic://:6121
-```
-
-客户端(Chrome):
-```bash
-chrome --enable-quic --proxy-server=quic://server_ip:6121
-```
-
-**注:** 由于Chrome自身的限制,目前只能通过QUIC访问HTTP网站,无法访问HTTPS网站。
-
-#### KCP
-gost对KCP的支持是基于[kcp-go](https://github.com/xtaci/kcp-go)和[kcptun](https://github.com/xtaci/kcptun)库。
-
-服务端:
-```bash
-gost -L=kcp://:8388
-```
-
-客户端:
-```bash
-gost -L=:8080 -F=kcp://server_ip:8388
-```
-
-或者手动指定加密方法和密码(手动指定的加密方法和密码会覆盖配置文件中的相应值)
-
-服务端:
-```bash
-gost -L=kcp://aes:123456@:8388
-```
-
-客户端:
-```bash
-gost -L=:8080 -F=kcp://aes:123456@server_ip:8388
-```
-
-gost会自动加载当前工作目录中的kcp.json(如果存在)配置文件,或者可以手动通过参数指定配置文件路径:
-```bash
-gost -L=kcp://:8388?c=/path/to/conf/file
-```
-
-**注:** 客户端若要开启KCP转发,当且仅当代理链不为空且首个代理节点(第一个-F参数)为kcp类型。
-
-#### 透明代理
-基于iptables的透明代理。
-
-```bash
-gost -L=redirect://:12345 -F=http2://server_ip:443
-```
-
-加密机制
-------
-#### HTTP
-对于HTTP可以使用TLS加密整个通讯过程,即HTTPS代理:
-
-服务端:
-```bash
-gost -L=http+tls://:443
-```
-客户端:
-```bash
-gost -L=:8080 -F=http+tls://server_ip:443
-```
-
-#### HTTP2
-gost仅支持使用TLS加密的HTTP2协议,不支持明文HTTP2传输。
-
-
-#### SOCKS5
-gost支持标准SOCKS5协议的no-auth(0x00)和user/pass(0x02)方法,并在此基础上扩展了两个:tls(0x80)和tls-auth(0x82),用于数据加密。
-
-服务端:
-```bash
-gost -L=socks://:1080
-```
-客户端:
-```bash
-gost -L=:8080 -F=socks://server_ip:1080
-```
-
-如果两端都是gost(如上)则数据传输会被加密(协商使用tls或tls-auth方法),否则使用标准SOCKS5进行通讯(no-auth或user/pass方法)。
-
-**注:** 如果transport已经支持加密(wss, tls, http2, kcp),则SOCKS5不会再使用加密方法,防止不必要的双重加密。
-
-#### Shadowsocks
-gost对shadowsocks的支持是基于[shadowsocks-go](https://github.com/shadowsocks/shadowsocks-go)库。
-
-服务端(可以通过ota参数开启OTA强制模式,开启后客户端必须使用OTA模式):
-```bash
-gost -L=ss://aes-128-cfb:123456@:8338?ota=1
-```
-客户端(可以通过ota参数开启OTA模式):
-```bash
-gost -L=:8080 -F=ss://aes-128-cfb:123456@server_ip:8338?ota=1
-```
-
-##### Shadowsocks UDP relay
-
-目前仅服务端支持UDP,且仅支持OTA模式。
-
-服务端:
-```bash
-gost -L=ssu://aes-128-cfb:123456@:8338
-```
-
-#### TLS
-gost内置了TLS证书,如果需要使用其他TLS证书,有两种方法:
-* 在gost运行目录放置cert.pem(公钥)和key.pem(私钥)两个文件即可,gost会自动加载运行目录下的cert.pem和key.pem文件。
-* 使用参数指定证书文件路径:
-```bash
-gost -L="http2://:443?cert=/path/to/my/cert/file&key=/path/to/my/key/file"
-```
-
-SOCKS5 UDP数据处理
-------
-#### 不设置转发代理
-
-
-
-gost作为标准SOCKS5代理处理UDP数据
-
-#### 设置转发代理
-
-
-
-#### 设置多个转发代理(代理链)
-
-
-
-当设置转发代理时,gost会使用UDP-over-TCP方式转发UDP数据。proxy1 - proxyN可以为任意HTTP/HTTPS/HTTP2/SOCKS5/Shadowsocks类型代理。
-
-限制条件
-------
-代理链中的HTTP代理节点必须支持CONNECT方法。
-
-如果要转发SOCKS5的BIND和UDP请求,代理链的末端(最后一个-F参数)必须支持gost SOCKS5类型代理。
-
-
-
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/README_en.md b/cmd/gost/vendor/github.com/ginuerzh/gost/README_en.md
deleted file mode 100644
index b7c0e7f..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/README_en.md
+++ /dev/null
@@ -1,355 +0,0 @@
-gost - GO Simple Tunnel
-======
-
-### A simple security tunnel written in Golang
-
-Features
-------
-* Listening on multiple ports
-* Multi-level forward proxy - proxy chain
-* Standard HTTP/HTTPS/SOCKS5 proxy protocols support
-* TLS encryption via negotiation support for SOCKS5 proxy
-* Tunnel UDP over TCP
-* Shadowsocks protocol support (OTA: 2.2+, UDP: 2.4+)
-* Local/remote port forwarding (2.1+)
-* HTTP 2.0 support (2.2+)
-* Experimental QUIC support (2.3+)
-* KCP protocol support (2.3+)
-* Transparent proxy (2.3+)
-
-Binary file download:https://github.com/ginuerzh/gost/releases
-
-Google group: https://groups.google.com/d/forum/go-gost
-
-Gost and other proxy services are considered to be proxy nodes,
-gost can handle the request itself, or forward the request to any one or more proxy nodes.
-
-Parameter Description
-------
-#### Proxy and proxy chain
-
-Effective for the -L and -F parameters
-
-```bash
-[scheme://][user:pass@host]:port
-```
-scheme can be divided into two parts: protocol+transport
-
-protocol: proxy protocol types (http, socks5, shadowsocks),
-transport: data transmission mode (ws, wss, tls, http2, quic, kcp), may be used in any combination or individually:
-
-> http - standard HTTP proxy: http://:8080
-
-> http+tls - standard HTTPS proxy (may need to provide a trusted certificate): http+tls://:443 or https://:443
-
-> http2 - HTTP2 proxy and backwards-compatible with HTTPS proxy: http2://:443
-
-> socks - standard SOCKS5 proxy: socks://:1080
-
-> socks+wss - SOCKS5 over websocket: socks+wss://:1080
-
-> tls - HTTPS/SOCKS5 over tls: tls://:443
-
-> ss - standard shadowsocks proxy, ss://chacha20:123456@:8338
-
-> ssu - shadowsocks UDP relay,ssu://chacha20:123456@:8338
-
-> quic - standard QUIC proxy, quic://:6121
-
-> kcp - standard KCP tunnel,kcp://:8388 or kcp://aes:123456@:8388
-
-> redirect - transparent proxy,redirect://:12345
-
-#### Port forwarding
-
-Effective for the -L parameter
-
-```bash
-scheme://[bind_address]:port/[host]:hostport
-```
-> scheme - forward mode, local: tcp, udp; remote: rtcp, rudp
-
-> bind_address:port - local/remote binding address
-
-> host:hostport - target address
-
-#### Configuration file
-
-> -C : specifies the configuration file path
-
-The configuration file is in standard JSON format:
-```json
-{
- "ServeNodes": [
- ":8080",
- "ss://chacha20:12345678@:8338"
- ],
- "ChainNodes": [
- "http://192.168.1.1:8080",
- "https://10.0.2.1:443"
- ]
-}
-```
-
-ServeNodes is equivalent to the -L parameter, ChainNodes is equivalent to the -F parameter.
-
-#### Logging
-
-> -logtostderr : log to console
-
-> -v=3 : log level (1-5),The higher the level, the more detailed the log (level 5 will enable HTTP2 debug)
-
-> -log_dir=/log/dir/path : log to directory /log/dir/path
-
-Usage
-------
-#### No forward proxy
-
-
-
-* Standard HTTP/SOCKS5 proxy
-```bash
-gost -L=:8080
-```
-
-* Proxy authentication
-```bash
-gost -L=admin:123456@localhost:8080
-```
-
-* Multiple sets of authentication information
-```bash
-gost -L=localhost:8080?secrets=secrets.txt
-```
-
-The secrets parameter allows you to set multiple authentication information for HTTP/SOCKS5 proxies, the format is:
-```plain
-# username password
-
-test001 123456
-test002 12345678
-```
-
-* Listen on multiple ports
-```bash
-gost -L=http2://:443 -L=socks://:1080 -L=ss://aes-128-cfb:123456@:8338
-```
-
-#### Forward proxy
-
-
-```bash
-gost -L=:8080 -F=192.168.1.1:8081
-```
-
-* Forward proxy authentication
-```bash
-gost -L=:8080 -F=http://admin:123456@192.168.1.1:8081
-```
-
-#### Multi-level forward proxy
-
-
-```bash
-gost -L=:8080 -F=http+tls://192.168.1.1:443 -F=socks+ws://192.168.1.2:1080 -F=ss://aes-128-cfb:123456@192.168.1.3:8338 -F=a.b.c.d:NNNN
-```
-Gost forwards the request to a.b.c.d:NNNN through the proxy chain in the order set by -F,
-each forward proxy can be any HTTP/HTTPS/HTTP2/SOCKS5/Shadowsocks type.
-
-#### Local TCP port forwarding
-
-```bash
-gost -L=tcp://:2222/192.168.1.1:22 -F=...
-```
-The data on the local TCP port 2222 is forwarded to 192.168.1.1:22 (through the proxy chain).
-
-#### Local UDP port forwarding
-
-```bash
-gost -L=udp://:5353/192.168.1.1:53?ttl=60 -F=...
-```
-The data on the local UDP port 5353 is forwarded to 192.168.1.1:53 (through the proxy chain).
-Each forwarding channel has a timeout period. When this time is exceeded and there is no data interaction during this time period, the channel will be closed. The timeout value can be set by the `ttl` parameter. The default value is 60 seconds.
-
-**NOTE:** When forwarding UDP data, if there is a proxy chain, the end of the chain (the last -F parameter) must be gost SOCKS5 proxy.
-
-#### Remote TCP port forwarding
-
-```bash
-gost -L=rtcp://:2222/192.168.1.1:22 -F=... -F=socks://172.24.10.1:1080
-```
-The data on 172.24.10.1:2222 is forwarded to 192.168.1.1:22 (through the proxy chain).
-
-#### Remote UDP port forwarding
-
-```bash
-gost -L=rudp://:5353/192.168.1.1:53 -F=... -F=socks://172.24.10.1:1080
-```
-The data on 172.24.10.1:5353 is forwarded to 192.168.1.1:53 (through the proxy chain).
-
-**NOTE:** To use the remote port forwarding feature, the proxy chain can not be empty (at least one -F parameter is set)
-and the end of the chain (last -F parameter) must be gost SOCKS5 proxy.
-
-#### HTTP2
-Gost HTTP2 supports two modes and self-adapting:
-* As a standard HTTP2 proxy, and backwards-compatible with the HTTPS proxy.
-* As transport (similar to wss), tunnel other protocol.
-
-Server:
-```bash
-gost -L=http2://:443
-```
-Client:
-```bash
-gost -L=:8080 -F=http2://server_ip:443?ping=30
-```
-
-The client supports the `ping` parameter to enable heartbeat detection (which is disabled by default).
-Parameter value represents heartbeat interval seconds.
-
-**NOTE:** The proxy chain of gost supports only one HTTP2 proxy node and the nearest rule applies,
-the first HTTP2 proxy node is treated as an HTTP2 proxy, and the other HTTP2 proxy nodes are treated as HTTPS proxies.
-
-#### QUIC
-Support for QUIC is based on library [quic-go](https://github.com/lucas-clemente/quic-go).
-
-Server:
-```bash
-gost -L=quic://:6121
-```
-Client(Chrome):
-```bash
-chrome --enable-quic --proxy-server=quic://server_ip:6121
-```
-
-**NOTE:** Due to Chrome's limitations, it is currently only possible to access the HTTP (but not HTTPS) site through QUIC.
-
-#### KCP
-Support for KCP is based on libraries [kcp-go](https://github.com/xtaci/kcp-go) and [kcptun](https://github.com/xtaci/kcptun).
-
-Server:
-```bash
-gost -L=kcp://:8388
-```
-Client:
-```bash
-gost -L=:8080 -F=kcp://server_ip:8388
-```
-
-Or manually specify the encryption method and password (Manually specifying the encryption method and password overwrites the corresponding value in the configuration file)
-
-Server:
-```bash
-gost -L=kcp://aes:123456@:8388
-```
-
-Client:
-```bash
-gost -L=:8080 -F=kcp://aes:123456@server_ip:8388
-```
-
-Gost will automatically load kcp.json configuration file from current working directory if exists,
-or you can use the parameter to specify the path to the file.
-```bash
-gost -L=kcp://:8388?c=/path/to/conf/file
-```
-
-**NOTE:** KCP will be enabled if and only if the proxy chain is not empty and the first proxy node (the first -F parameter) is of type KCP.
-
-#### Transparent proxy
-Iptables-based transparent proxy
-
-```bash
-gost -L=redirect://:12345 -F=http2://server_ip:443
-```
-
-Encryption Mechanism
-------
-#### HTTP
-For HTTP, you can use TLS to encrypt the entire communication process, the HTTPS proxy:
-
-Server:
-```bash
-gost -L=http+tls://:443
-```
-Client:
-```bash
-gost -L=:8080 -F=http+tls://server_ip:443
-```
-
-#### HTTP2
-Gost supports only the HTTP2 protocol that uses TLS encryption (h2) and does not support plaintext HTTP2 (h2c) transport.
-
-
-#### SOCKS5
-Gost supports the standard SOCKS5 protocol methods: no-auth (0x00) and user/pass (0x02),
-and extends two methods for data encryption: tls(0x80) and tls-auth(0x82).
-
-Server:
-```bash
-gost -L=socks://:1080
-```
-Client:
-```bash
-gost -L=:8080 -F=socks://server_ip:1080
-```
-
-If both ends are gosts (as example above), the data transfer will be encrypted (using tls or tls-auth).
-Otherwise, use standard SOCKS5 for communication (no-auth or user/pass).
-
-**NOTE:** If transport already supports encryption (wss, tls, http2, kcp), SOCKS5 will no longer use the encryption method to prevent unnecessary double encryption.
-
-#### Shadowsocks
-Support for shadowsocks is based on library [shadowsocks-go](https://github.com/shadowsocks/shadowsocks-go).
-
-Server (The OTA mode can be enabled by the ota parameter. When enabled, the client must use OTA mode):
-```bash
-gost -L=ss://aes-128-cfb:123456@:8338?ota=1
-```
-Client (The OTA mode can be enabled by the ota parameter):
-```bash
-gost -L=:8080 -F=ss://aes-128-cfb:123456@server_ip:8338?ota=1
-```
-
-##### Shadowsocks UDP relay
-Currently, only the server supports UDP, and only OTA mode is supported.
-
-Server:
-```bash
-gost -L=ssu://aes-128-cfb:123456@:8338
-```
-
-#### TLS
-There is built-in TLS certificate in gost, if you need to use other TLS certificate, there are two ways:
-* Place two files cert.pem (public key) and key.pem (private key) in the current working directory, gost will automatically load them.
-* Use the parameter to specify the path to the certificate file:
-```bash
-gost -L="http2://:443?cert=/path/to/my/cert/file&key=/path/to/my/key/file"
-```
-
-SOCKS5 UDP Data Processing
-------
-#### No forward proxy
-
-
-
-Gost acts as the standard SOCKS5 proxy for UDP relay.
-
-#### Forward proxy
-
-
-
-#### Multi-level forward proxy
-
-
-
-When forward proxies are set, gost uses UDP-over-TCP to forward UDP data, proxy1 to proxyN can be any HTTP/HTTPS/HTTP2/SOCKS5/Shadowsocks type.
-
-Limitation
-------
-The HTTP proxy node in the proxy chain must support the CONNECT method.
-
-If the BIND and UDP requests for SOCKS5 are to be forwarded, the end of the chain (the last -F parameter) must be the gost SOCKS5 proxy.
-
-
-
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/chain.go b/cmd/gost/vendor/github.com/ginuerzh/gost/chain.go
deleted file mode 100644
index 9178067..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/chain.go
+++ /dev/null
@@ -1,381 +0,0 @@
-package gost
-
-import (
- "crypto/rand"
- "crypto/tls"
- "encoding/base64"
- "errors"
- "github.com/golang/glog"
- "golang.org/x/net/http2"
- "io"
- "net"
- "net/http"
- "net/http/httputil"
- "net/url"
- "strconv"
- "strings"
- "sync"
- "time"
-)
-
-// Proxy chain holds a list of proxy nodes
-type ProxyChain struct {
- nodes []ProxyNode
- lastNode *ProxyNode
- http2NodeIndex int
- http2Enabled bool
- http2Client *http.Client
- kcpEnabled bool
- kcpConfig *KCPConfig
- kcpSession *KCPSession
- kcpMutex sync.Mutex
-}
-
-func NewProxyChain(nodes ...ProxyNode) *ProxyChain {
- chain := &ProxyChain{nodes: nodes, http2NodeIndex: -1}
- return chain
-}
-
-func (c *ProxyChain) AddProxyNode(node ...ProxyNode) {
- c.nodes = append(c.nodes, node...)
-}
-
-func (c *ProxyChain) AddProxyNodeString(snode ...string) error {
- for _, sn := range snode {
- node, err := ParseProxyNode(sn)
- if err != nil {
- return err
- }
- c.AddProxyNode(node)
- }
- return nil
-}
-
-func (c *ProxyChain) Nodes() []ProxyNode {
- return c.nodes
-}
-
-func (c *ProxyChain) GetNode(index int) *ProxyNode {
- if index < len(c.nodes) {
- return &c.nodes[index]
- }
- return nil
-}
-
-func (c *ProxyChain) SetNode(index int, node ProxyNode) {
- if index < len(c.nodes) {
- c.nodes[index] = node
- }
-}
-
-// Init initialize the proxy chain.
-// KCP will be enabled if the first proxy node is KCP proxy (transport == kcp).
-// HTTP2 will be enabled when at least one HTTP2 proxy node (scheme == http2) is present.
-//
-// NOTE: Should be called immediately when proxy nodes are ready.
-func (c *ProxyChain) Init() {
- length := len(c.nodes)
- if length == 0 {
- return
- }
-
- c.lastNode = &c.nodes[length-1]
-
- // HTTP2 restrict: HTTP2 will be enabled when at least one HTTP2 proxy node is present.
- for i, node := range c.nodes {
- if node.Transport == "http2" {
- glog.V(LINFO).Infoln("HTTP2 is enabled")
- cfg := &tls.Config{
- InsecureSkipVerify: node.insecureSkipVerify(),
- ServerName: node.serverName,
- }
- c.http2NodeIndex = i
- c.initHttp2Client(cfg, c.nodes[:i]...)
- break // shortest chain for HTTP2
- }
- }
-
- for i, node := range c.nodes {
- if node.Transport == "kcp" && i > 0 {
- glog.Fatal("KCP must be the first node in the proxy chain")
- }
- }
-
- if c.nodes[0].Transport == "kcp" {
- glog.V(LINFO).Infoln("KCP is enabled")
- c.kcpEnabled = true
- config, err := ParseKCPConfig(c.nodes[0].Get("c"))
- if err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- }
- if config == nil {
- config = DefaultKCPConfig
- }
- if c.nodes[0].Users != nil {
- config.Crypt = c.nodes[0].Users[0].Username()
- config.Key, _ = c.nodes[0].Users[0].Password()
- }
- c.kcpConfig = config
- return
- }
-}
-
-func (c *ProxyChain) KCPEnabled() bool {
- return c.kcpEnabled
-}
-
-func (c *ProxyChain) Http2Enabled() bool {
- return c.http2Enabled
-}
-
-func (c *ProxyChain) initHttp2Client(config *tls.Config, nodes ...ProxyNode) {
- if c.http2NodeIndex < 0 || c.http2NodeIndex >= len(c.nodes) {
- return
- }
- http2Node := c.nodes[c.http2NodeIndex]
-
- tr := http2.Transport{
- TLSClientConfig: config,
- DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
- // replace the default dialer with our proxy chain.
- conn, err := c.dialWithNodes(false, http2Node.Addr, nodes...)
- if err != nil {
- return conn, err
- }
- conn = tls.Client(conn, cfg)
-
- // enable HTTP2 ping-pong
- pingIntvl, _ := strconv.Atoi(http2Node.Get("ping"))
- if pingIntvl > 0 {
- enablePing(conn, time.Duration(pingIntvl)*time.Second)
- }
-
- return conn, nil
- },
- }
- c.http2Client = &http.Client{Transport: &tr}
- c.http2Enabled = true
-
-}
-
-func enablePing(conn net.Conn, interval time.Duration) {
- if conn == nil || interval == 0 {
- return
- }
-
- glog.V(LINFO).Infoln("[http2] ping enabled, interval:", interval)
- go func() {
- t := time.NewTicker(interval)
- var framer *http2.Framer
- for {
- select {
- case <-t.C:
- if framer == nil {
- framer = http2.NewFramer(conn, conn)
- }
-
- var p [8]byte
- rand.Read(p[:])
- err := framer.WritePing(false, p)
- if err != nil {
- t.Stop()
- framer = nil
- glog.V(LWARNING).Infoln("[http2] ping:", err)
- return
- }
- }
- }
- }()
-}
-
-// Connect to addr through proxy chain
-func (c *ProxyChain) Dial(addr string) (net.Conn, error) {
- if !strings.Contains(addr, ":") {
- addr += ":80"
- }
- return c.dialWithNodes(true, addr, c.nodes...)
-}
-
-// GetConn initializes a proxy chain connection,
-// if no proxy nodes on this chain, it will return error
-func (c *ProxyChain) GetConn() (net.Conn, error) {
- nodes := c.nodes
- if len(nodes) == 0 {
- return nil, ErrEmptyChain
- }
-
- if c.Http2Enabled() {
- nodes = nodes[c.http2NodeIndex+1:]
- if len(nodes) == 0 {
- header := make(http.Header)
- header.Set("Proxy-Switch", "gost") // Flag header to indicate server to switch to HTTP2 transport mode
- conn, err := c.getHttp2Conn(header)
- if err != nil {
- return nil, err
- }
- http2Node := c.nodes[c.http2NodeIndex]
- if http2Node.Transport == "http2" {
- http2Node.Transport = "h2"
- }
- if http2Node.Protocol == "http2" {
- http2Node.Protocol = "socks5" // assume it as socks5 protocol, so we can do much more things.
- }
- pc := NewProxyConn(conn, http2Node)
- if err := pc.Handshake(); err != nil {
- conn.Close()
- return nil, err
- }
- return pc, nil
- }
- }
- return c.travelNodes(true, nodes...)
-}
-
-func (c *ProxyChain) dialWithNodes(withHttp2 bool, addr string, nodes ...ProxyNode) (conn net.Conn, err error) {
- if len(nodes) == 0 {
- return net.DialTimeout("tcp", addr, DialTimeout)
- }
-
- if withHttp2 && c.Http2Enabled() {
- nodes = nodes[c.http2NodeIndex+1:]
- if len(nodes) == 0 {
- return c.http2Connect(addr)
- }
- }
- pc, err := c.travelNodes(withHttp2, nodes...)
- if err != nil {
- return
- }
- if err = pc.Connect(addr); err != nil {
- pc.Close()
- return
- }
- conn = pc
- return
-}
-
-func (c *ProxyChain) travelNodes(withHttp2 bool, nodes ...ProxyNode) (conn *ProxyConn, err error) {
- defer func() {
- if err != nil && conn != nil {
- conn.Close()
- conn = nil
- }
- }()
-
- var cc net.Conn
- node := nodes[0]
-
- if withHttp2 && c.Http2Enabled() {
- cc, err = c.http2Connect(node.Addr)
- } else if node.Transport == "kcp" {
- cc, err = c.getKCPConn()
- } else {
- cc, err = net.DialTimeout("tcp", node.Addr, DialTimeout)
- }
- if err != nil {
- return
- }
- setKeepAlive(cc, KeepAliveTime)
-
- pc := NewProxyConn(cc, node)
- conn = pc
- if err = pc.Handshake(); err != nil {
- return
- }
-
- for _, node := range nodes[1:] {
- if err = conn.Connect(node.Addr); err != nil {
- return
- }
- pc := NewProxyConn(conn, node)
- conn = pc
- if err = pc.Handshake(); err != nil {
- return
- }
- }
- return
-}
-
-func (c *ProxyChain) initKCPSession() (err error) {
- c.kcpMutex.Lock()
- defer c.kcpMutex.Unlock()
-
- if c.kcpSession == nil || c.kcpSession.IsClosed() {
- glog.V(LINFO).Infoln("[kcp] new kcp session")
- c.kcpSession, err = DialKCP(c.nodes[0].Addr, c.kcpConfig)
- }
- return
-}
-
-func (c *ProxyChain) getKCPConn() (conn net.Conn, err error) {
- if !c.KCPEnabled() {
- return nil, errors.New("KCP is not enabled")
- }
-
- if err = c.initKCPSession(); err != nil {
- return nil, err
- }
- return c.kcpSession.GetConn()
-}
-
-// Initialize an HTTP2 transport if HTTP2 is enabled.
-func (c *ProxyChain) getHttp2Conn(header http.Header) (net.Conn, error) {
- if !c.Http2Enabled() {
- return nil, errors.New("HTTP2 is not enabled")
- }
- http2Node := c.nodes[c.http2NodeIndex]
- pr, pw := io.Pipe()
-
- if header == nil {
- header = make(http.Header)
- }
-
- req := http.Request{
- Method: http.MethodConnect,
- URL: &url.URL{Scheme: "https", Host: http2Node.Addr},
- Header: header,
- Proto: "HTTP/2.0",
- ProtoMajor: 2,
- ProtoMinor: 0,
- Body: pr,
- Host: http2Node.Addr,
- ContentLength: -1,
- }
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpRequest(&req, false)
- glog.Infoln(string(dump))
- }
- resp, err := c.http2Client.Do(&req)
- if err != nil {
- return nil, err
- }
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpResponse(resp, false)
- glog.Infoln(string(dump))
- }
- if resp.StatusCode != http.StatusOK {
- resp.Body.Close()
- return nil, errors.New(resp.Status)
- }
- conn := &http2Conn{r: resp.Body, w: pw}
- conn.remoteAddr, _ = net.ResolveTCPAddr("tcp", http2Node.Addr)
- return conn, nil
-}
-
-// Use HTTP2 as transport to connect target addr.
-//
-// BUG: SOCKS5 is ignored, only HTTP supported
-func (c *ProxyChain) http2Connect(addr string) (net.Conn, error) {
- if !c.Http2Enabled() {
- return nil, errors.New("HTTP2 is not enabled")
- }
- http2Node := c.nodes[c.http2NodeIndex]
-
- header := make(http.Header)
- header.Set("Gost-Target", addr) // Flag header to indicate the address that server connected to
- if http2Node.Users != nil {
- header.Set("Proxy-Authorization",
- "Basic "+base64.StdEncoding.EncodeToString([]byte(http2Node.Users[0].String())))
- }
- return c.getHttp2Conn(header)
-}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/conn.go b/cmd/gost/vendor/github.com/ginuerzh/gost/conn.go
deleted file mode 100644
index a46a285..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/conn.go
+++ /dev/null
@@ -1,257 +0,0 @@
-package gost
-
-import (
- "bufio"
- "crypto/tls"
- "encoding/base64"
- "errors"
- "github.com/ginuerzh/gosocks5"
- "github.com/golang/glog"
- ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
- "net"
- "net/http"
- "net/http/httputil"
- "net/url"
- "strconv"
- "strings"
- "sync"
- "time"
-)
-
-type ProxyConn struct {
- conn net.Conn
- Node ProxyNode
- handshaked bool
- handshakeMutex sync.Mutex
- handshakeErr error
-}
-
-func NewProxyConn(conn net.Conn, node ProxyNode) *ProxyConn {
- return &ProxyConn{
- conn: conn,
- Node: node,
- }
-}
-
-// Handshake handshake with this proxy node based on the proxy node info: transport, protocol, authentication, etc.
-//
-// NOTE: any HTTP2 scheme will be treated as http (for protocol) or tls (for transport).
-func (c *ProxyConn) Handshake() error {
- c.handshakeMutex.Lock()
- defer c.handshakeMutex.Unlock()
-
- if err := c.handshakeErr; err != nil {
- return err
- }
- if c.handshaked {
- return nil
- }
- c.handshakeErr = c.handshake()
- return c.handshakeErr
-}
-
-func (c *ProxyConn) handshake() error {
- var tlsUsed bool
-
- switch c.Node.Transport {
- case "ws": // websocket connection
- u := url.URL{Scheme: "ws", Host: c.Node.Addr, Path: "/ws"}
- conn, err := WebsocketClientConn(u.String(), c.conn, nil)
- if err != nil {
- return err
- }
- c.conn = conn
- case "wss": // websocket security
- tlsUsed = true
- u := url.URL{Scheme: "wss", Host: c.Node.Addr, Path: "/ws"}
- config := &tls.Config{
- InsecureSkipVerify: c.Node.insecureSkipVerify(),
- ServerName: c.Node.serverName,
- }
- conn, err := WebsocketClientConn(u.String(), c.conn, config)
- if err != nil {
- return err
- }
- c.conn = conn
- case "tls", "http2": // tls connection
- tlsUsed = true
- cfg := &tls.Config{
- InsecureSkipVerify: c.Node.insecureSkipVerify(),
- ServerName: c.Node.serverName,
- }
- c.conn = tls.Client(c.conn, cfg)
- case "h2": // same as http2, but just set a flag for later using.
- tlsUsed = true
- case "kcp": // kcp connection
- tlsUsed = true
- default:
- }
-
- switch c.Node.Protocol {
- case "socks", "socks5": // socks5 handshake with auth and tls supported
- selector := &clientSelector{
- methods: []uint8{
- gosocks5.MethodNoAuth,
- gosocks5.MethodUserPass,
- //MethodTLS,
- },
- }
-
- if len(c.Node.Users) > 0 {
- selector.user = c.Node.Users[0]
- }
-
- if !tlsUsed { // if transport is not security, enable security socks5
- selector.methods = append(selector.methods, MethodTLS)
- selector.tlsConfig = &tls.Config{
- InsecureSkipVerify: c.Node.insecureSkipVerify(),
- ServerName: c.Node.serverName,
- }
- }
-
- conn := gosocks5.ClientConn(c.conn, selector)
- if err := conn.Handleshake(); err != nil {
- return err
- }
- c.conn = conn
- case "ss": // shadowsocks
- // nothing to do
- case "http", "http2":
- fallthrough
- default:
- }
-
- c.handshaked = true
-
- return nil
-}
-
-// Connect connect to addr through this proxy node
-func (c *ProxyConn) Connect(addr string) error {
- switch c.Node.Protocol {
- case "ss": // shadowsocks
- rawaddr, err := ss.RawAddr(addr)
- if err != nil {
- return err
- }
-
- var method, password string
- if len(c.Node.Users) > 0 {
- method = c.Node.Users[0].Username()
- password, _ = c.Node.Users[0].Password()
- }
- if c.Node.getBool("ota") && !strings.HasSuffix(method, "-auth") {
- method += "-auth"
- }
-
- cipher, err := ss.NewCipher(method, password)
- if err != nil {
- return err
- }
-
- ssc, err := ss.DialWithRawAddrConn(rawaddr, c.conn, cipher)
- if err != nil {
- return err
- }
- c.conn = &shadowConn{conn: ssc}
- return nil
- case "socks", "socks5":
- host, port, err := net.SplitHostPort(addr)
- if err != nil {
- return err
- }
- p, _ := strconv.Atoi(port)
- req := gosocks5.NewRequest(gosocks5.CmdConnect, &gosocks5.Addr{
- Type: gosocks5.AddrDomain,
- Host: host,
- Port: uint16(p),
- })
- if err := req.Write(c); err != nil {
- return err
- }
- glog.V(LDEBUG).Infoln("[socks5]", req)
-
- reply, err := gosocks5.ReadReply(c)
- if err != nil {
- return err
- }
- glog.V(LDEBUG).Infoln("[socks5]", reply)
- if reply.Rep != gosocks5.Succeeded {
- return errors.New("Service unavailable")
- }
- case "http":
- fallthrough
- default:
- req := &http.Request{
- Method: http.MethodConnect,
- URL: &url.URL{Host: addr},
- Host: addr,
- ProtoMajor: 1,
- ProtoMinor: 1,
- Header: make(http.Header),
- }
- req.Header.Set("Proxy-Connection", "keep-alive")
- if len(c.Node.Users) > 0 {
- user := c.Node.Users[0]
- s := user.String()
- if _, set := user.Password(); !set {
- s += ":"
- }
- req.Header.Set("Proxy-Authorization",
- "Basic "+base64.StdEncoding.EncodeToString([]byte(s)))
- }
- if err := req.Write(c); err != nil {
- return err
- }
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpRequest(req, false)
- glog.Infoln(string(dump))
- }
-
- resp, err := http.ReadResponse(bufio.NewReader(c), req)
- if err != nil {
- return err
- }
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpResponse(resp, false)
- glog.Infoln(string(dump))
- }
- if resp.StatusCode != http.StatusOK {
- return errors.New(resp.Status)
- }
- }
-
- return nil
-}
-
-func (c *ProxyConn) Read(b []byte) (n int, err error) {
- return c.conn.Read(b)
-}
-
-func (c *ProxyConn) Write(b []byte) (n int, err error) {
- return c.conn.Write(b)
-}
-
-func (c *ProxyConn) Close() error {
- return c.conn.Close()
-}
-
-func (c *ProxyConn) LocalAddr() net.Addr {
- return c.conn.LocalAddr()
-}
-
-func (c *ProxyConn) RemoteAddr() net.Addr {
- return c.conn.RemoteAddr()
-}
-
-func (c *ProxyConn) SetDeadline(t time.Time) error {
- return c.conn.SetDeadline(t)
-}
-
-func (c *ProxyConn) SetReadDeadline(t time.Time) error {
- return c.conn.SetReadDeadline(t)
-}
-
-func (c *ProxyConn) SetWriteDeadline(t time.Time) error {
- return c.conn.SetWriteDeadline(t)
-}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/forward.go b/cmd/gost/vendor/github.com/ginuerzh/gost/forward.go
deleted file mode 100644
index ca76904..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/forward.go
+++ /dev/null
@@ -1,521 +0,0 @@
-package gost
-
-import (
- "errors"
- "fmt"
- "github.com/ginuerzh/gosocks5"
- "github.com/golang/glog"
- "net"
- "time"
-)
-
-type TcpForwardServer struct {
- Base *ProxyServer
- Handler func(conn net.Conn, raddr net.Addr)
-}
-
-func NewTcpForwardServer(base *ProxyServer) *TcpForwardServer {
- return &TcpForwardServer{Base: base}
-}
-
-func (s *TcpForwardServer) ListenAndServe() error {
- raddr, err := net.ResolveTCPAddr("tcp", s.Base.Node.Remote)
- if err != nil {
- return err
- }
-
- ln, err := net.Listen("tcp", s.Base.Node.Addr)
- if err != nil {
- return err
- }
- defer ln.Close()
-
- if s.Handler == nil {
- s.Handler = s.handleTcpForward
- }
-
- for {
- conn, err := ln.Accept()
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- continue
- }
- setKeepAlive(conn, KeepAliveTime)
-
- go s.Handler(conn, raddr)
- }
-}
-
-func (s *TcpForwardServer) handleTcpForward(conn net.Conn, raddr net.Addr) {
- defer conn.Close()
-
- glog.V(LINFO).Infof("[tcp] %s - %s", conn.RemoteAddr(), raddr)
- cc, err := s.Base.Chain.Dial(raddr.String())
- if err != nil {
- glog.V(LWARNING).Infof("[tcp] %s -> %s : %s", conn.RemoteAddr(), raddr, err)
- return
- }
- defer cc.Close()
-
- glog.V(LINFO).Infof("[tcp] %s <-> %s", conn.RemoteAddr(), raddr)
- s.Base.transport(conn, cc)
- glog.V(LINFO).Infof("[tcp] %s >-< %s", conn.RemoteAddr(), raddr)
-}
-
-type packet struct {
- srcAddr string // src address
- dstAddr string // dest address
- data []byte
-}
-
-type cnode struct {
- chain *ProxyChain
- conn net.Conn
- srcAddr, dstAddr string
- rChan, wChan chan *packet
- err error
- ttl time.Duration
-}
-
-func (node *cnode) getUDPTunnel() (net.Conn, error) {
- conn, err := node.chain.GetConn()
- if err != nil {
- return nil, err
- }
-
- conn.SetWriteDeadline(time.Now().Add(WriteTimeout))
- if err = gosocks5.NewRequest(CmdUdpTun, nil).Write(conn); err != nil {
- conn.Close()
- return nil, err
- }
- conn.SetWriteDeadline(time.Time{})
-
- conn.SetReadDeadline(time.Now().Add(ReadTimeout))
- reply, err := gosocks5.ReadReply(conn)
- if err != nil {
- conn.Close()
- return nil, err
- }
- conn.SetReadDeadline(time.Time{})
-
- if reply.Rep != gosocks5.Succeeded {
- conn.Close()
- return nil, errors.New("UDP tunnel failure")
- }
-
- return conn, nil
-}
-
-func (node *cnode) run() {
- if len(node.chain.Nodes()) == 0 {
- lconn, err := net.ListenUDP("udp", nil)
- if err != nil {
- glog.V(LWARNING).Infof("[udp] %s -> %s : %s", node.srcAddr, node.dstAddr, err)
- node.err = err
- return
- }
- node.conn = lconn
- } else {
- tc, err := node.getUDPTunnel()
- if err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s -> %s : %s", node.srcAddr, node.dstAddr, err)
- node.err = err
- return
- }
- node.conn = tc
- }
-
- defer node.conn.Close()
-
- timer := time.NewTimer(node.ttl)
- errChan := make(chan error, 2)
-
- go func() {
- for {
- switch c := node.conn.(type) {
- case *net.UDPConn:
- b := make([]byte, MediumBufferSize)
- n, addr, err := c.ReadFromUDP(b)
- if err != nil {
- glog.V(LWARNING).Infof("[udp] %s <- %s : %s", node.srcAddr, node.dstAddr, err)
- node.err = err
- errChan <- err
- return
- }
-
- timer.Reset(node.ttl)
- glog.V(LDEBUG).Infof("[udp] %s <<< %s : length %d", node.srcAddr, addr, n)
-
- select {
- // swap srcAddr with dstAddr
- case node.rChan <- &packet{srcAddr: addr.String(), dstAddr: node.srcAddr, data: b[:n]}:
- case <-time.After(time.Second * 3):
- glog.V(LWARNING).Infof("[udp] %s <- %s : %s", node.srcAddr, node.dstAddr, "recv queue is full, discard")
- }
-
- default:
- dgram, err := gosocks5.ReadUDPDatagram(c)
- if err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", node.srcAddr, node.dstAddr, err)
- node.err = err
- errChan <- err
- return
- }
-
- timer.Reset(node.ttl)
- glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s : length %d", node.srcAddr, dgram.Header.Addr.String(), len(dgram.Data))
-
- select {
- // swap srcAddr with dstAddr
- case node.rChan <- &packet{srcAddr: dgram.Header.Addr.String(), dstAddr: node.srcAddr, data: dgram.Data}:
- case <-time.After(time.Second * 3):
- glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", node.srcAddr, node.dstAddr, "recv queue is full, discard")
- }
- }
- }
- }()
-
- go func() {
- for pkt := range node.wChan {
- timer.Reset(node.ttl)
-
- dstAddr, err := net.ResolveUDPAddr("udp", pkt.dstAddr)
- if err != nil {
- glog.V(LWARNING).Infof("[udp] %s -> %s : %s", pkt.srcAddr, pkt.dstAddr, err)
- continue
- }
-
- switch c := node.conn.(type) {
- case *net.UDPConn:
- if _, err := c.WriteToUDP(pkt.data, dstAddr); err != nil {
- glog.V(LWARNING).Infof("[udp] %s -> %s : %s", pkt.srcAddr, pkt.dstAddr, err)
- node.err = err
- errChan <- err
- return
- }
- glog.V(LDEBUG).Infof("[udp] %s >>> %s : length %d", pkt.srcAddr, pkt.dstAddr, len(pkt.data))
-
- default:
- dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(len(pkt.data)), 0, ToSocksAddr(dstAddr)), pkt.data)
- if err := dgram.Write(c); err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s -> %s : %s", pkt.srcAddr, pkt.dstAddr, err)
- node.err = err
- errChan <- err
- return
- }
- glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s : length %d", pkt.srcAddr, pkt.dstAddr, len(pkt.data))
- }
- }
- }()
-
- select {
- case <-errChan:
- case <-timer.C:
- }
-}
-
-type UdpForwardServer struct {
- Base *ProxyServer
- TTL int
-}
-
-func NewUdpForwardServer(base *ProxyServer, ttl int) *UdpForwardServer {
- return &UdpForwardServer{Base: base, TTL: ttl}
-}
-
-func (s *UdpForwardServer) ListenAndServe() error {
- laddr, err := net.ResolveUDPAddr("udp", s.Base.Node.Addr)
- if err != nil {
- return err
- }
-
- raddr, err := net.ResolveUDPAddr("udp", s.Base.Node.Remote)
- if err != nil {
- return err
- }
-
- conn, err := net.ListenUDP("udp", laddr)
- if err != nil {
- glog.V(LWARNING).Infof("[udp] %s -> %s : %s", laddr, raddr, err)
- return err
- }
- defer conn.Close()
-
- rChan, wChan := make(chan *packet, 128), make(chan *packet, 128)
- // start send queue
- go func(ch chan<- *packet) {
- for {
- b := make([]byte, MediumBufferSize)
- n, addr, err := conn.ReadFromUDP(b)
- if err != nil {
- glog.V(LWARNING).Infof("[udp] %s -> %s : %s", laddr, raddr, err)
- continue
- }
-
- select {
- case ch <- &packet{srcAddr: addr.String(), dstAddr: raddr.String(), data: b[:n]}:
- case <-time.After(time.Second * 3):
- glog.V(LWARNING).Infof("[udp] %s -> %s : %s", addr, raddr, "send queue is full, discard")
- }
- }
- }(wChan)
- // start recv queue
- go func(ch <-chan *packet) {
- for pkt := range ch {
- dstAddr, err := net.ResolveUDPAddr("udp", pkt.dstAddr)
- if err != nil {
- glog.V(LWARNING).Infof("[udp] %s <- %s : %s", pkt.dstAddr, pkt.srcAddr, err)
- continue
- }
- if _, err := conn.WriteToUDP(pkt.data, dstAddr); err != nil {
- glog.V(LWARNING).Infof("[udp] %s <- %s : %s", pkt.dstAddr, pkt.srcAddr, err)
- return
- }
- }
- }(rChan)
-
- // mapping client to node
- m := make(map[string]*cnode)
-
- // start dispatcher
- for pkt := range wChan {
- // clear obsolete nodes
- for k, node := range m {
- if node != nil && node.err != nil {
- close(node.wChan)
- delete(m, k)
- glog.V(LINFO).Infof("[udp] clear node %s", k)
- }
- }
-
- node, ok := m[pkt.srcAddr]
- if !ok {
- node = &cnode{
- chain: s.Base.Chain,
- srcAddr: pkt.srcAddr,
- dstAddr: pkt.dstAddr,
- rChan: rChan,
- wChan: make(chan *packet, 32),
- ttl: time.Duration(s.TTL) * time.Second,
- }
- m[pkt.srcAddr] = node
- go node.run()
- glog.V(LINFO).Infof("[udp] %s -> %s : new client (%d)", pkt.srcAddr, pkt.dstAddr, len(m))
- }
-
- select {
- case node.wChan <- pkt:
- case <-time.After(time.Second * 3):
- glog.V(LWARNING).Infof("[udp] %s -> %s : %s", pkt.srcAddr, pkt.dstAddr, "node send queue is full, discard")
- }
- }
-
- return nil
-}
-
-type RTcpForwardServer struct {
- Base *ProxyServer
-}
-
-func NewRTcpForwardServer(base *ProxyServer) *RTcpForwardServer {
- return &RTcpForwardServer{Base: base}
-}
-
-func (s *RTcpForwardServer) Serve() error {
- if len(s.Base.Chain.nodes) == 0 {
- return errors.New("rtcp: at least one -F must be assigned")
- }
-
- laddr, err := net.ResolveTCPAddr("tcp", s.Base.Node.Addr)
- if err != nil {
- return err
- }
- raddr, err := net.ResolveTCPAddr("tcp", s.Base.Node.Remote)
- if err != nil {
- return err
- }
-
- retry := 0
- for {
- conn, err := s.Base.Chain.GetConn()
- if err != nil {
- glog.V(LWARNING).Infof("[rtcp] %s - %s : %s", laddr, raddr, err)
- time.Sleep((1 << uint(retry)) * time.Second)
- if retry < 5 {
- retry++
- }
- continue
- }
- retry = 0
-
- if err := s.connectRTcpForward(conn, laddr, raddr); err != nil {
- conn.Close()
- time.Sleep(6 * time.Second)
- }
- }
-}
-
-func (s *RTcpForwardServer) connectRTcpForward(conn net.Conn, laddr, raddr net.Addr) error {
- glog.V(LINFO).Infof("[rtcp] %s - %s", laddr, raddr)
-
- req := gosocks5.NewRequest(gosocks5.CmdBind, ToSocksAddr(laddr))
- if err := req.Write(conn); err != nil {
- glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", laddr, raddr, err)
- return err
- }
-
- // first reply, bind status
- conn.SetReadDeadline(time.Now().Add(ReadTimeout))
- rep, err := gosocks5.ReadReply(conn)
- if err != nil {
- glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", laddr, raddr, err)
- return err
- }
- conn.SetReadDeadline(time.Time{})
- if rep.Rep != gosocks5.Succeeded {
- glog.V(LWARNING).Infof("[rtcp] %s -> %s : bind on %s failure", laddr, raddr, laddr)
- return errors.New("Bind on " + laddr.String() + " failure")
- }
- glog.V(LINFO).Infof("[rtcp] %s - %s BIND ON %s OK", laddr, raddr, rep.Addr)
-
- // second reply, peer connection
- rep, err = gosocks5.ReadReply(conn)
- if err != nil {
- glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", laddr, raddr, err)
- return err
- }
- if rep.Rep != gosocks5.Succeeded {
- glog.V(LWARNING).Infof("[rtcp] %s -> %s : peer connect failure", laddr, raddr)
- return errors.New("peer connect failure")
- }
-
- glog.V(LINFO).Infof("[rtcp] %s -> %s PEER %s CONNECTED", laddr, raddr, rep.Addr)
-
- go func() {
- defer conn.Close()
-
- lconn, err := net.DialTimeout("tcp", raddr.String(), time.Second*180)
- if err != nil {
- glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", rep.Addr, raddr, err)
- return
- }
- defer lconn.Close()
-
- glog.V(LINFO).Infof("[rtcp] %s <-> %s", rep.Addr, lconn.RemoteAddr())
- s.Base.transport(lconn, conn)
- glog.V(LINFO).Infof("[rtcp] %s >-< %s", rep.Addr, lconn.RemoteAddr())
- }()
-
- return nil
-}
-
-type RUdpForwardServer struct {
- Base *ProxyServer
-}
-
-func NewRUdpForwardServer(base *ProxyServer) *RUdpForwardServer {
- return &RUdpForwardServer{Base: base}
-}
-
-func (s *RUdpForwardServer) Serve() error {
- if len(s.Base.Chain.nodes) == 0 {
- return errors.New("rudp: at least one -F must be assigned")
- }
-
- laddr, err := net.ResolveUDPAddr("udp", s.Base.Node.Addr)
- if err != nil {
- return err
- }
- raddr, err := net.ResolveUDPAddr("udp", s.Base.Node.Remote)
- if err != nil {
- return err
- }
-
- retry := 0
- for {
- conn, err := s.Base.Chain.GetConn()
- if err != nil {
- glog.V(LWARNING).Infof("[rudp] %s - %s : %s", laddr, raddr, err)
- time.Sleep((1 << uint(retry)) * time.Second)
- if retry < 5 {
- retry++
- }
- continue
- }
- retry = 0
-
- if err := s.connectRUdpForward(conn, laddr, raddr); err != nil {
- conn.Close()
- time.Sleep(6 * time.Second)
- }
- }
-}
-
-func (s *RUdpForwardServer) connectRUdpForward(conn net.Conn, laddr, raddr *net.UDPAddr) error {
- glog.V(LINFO).Infof("[rudp] %s - %s", laddr, raddr)
-
- req := gosocks5.NewRequest(CmdUdpTun, ToSocksAddr(laddr))
- conn.SetWriteDeadline(time.Now().Add(WriteTimeout))
- if err := req.Write(conn); err != nil {
- glog.V(LWARNING).Infof("[rudp] %s -> %s : %s", laddr, raddr, err)
- return err
- }
- conn.SetWriteDeadline(time.Time{})
-
- conn.SetReadDeadline(time.Now().Add(ReadTimeout))
- rep, err := gosocks5.ReadReply(conn)
- if err != nil {
- glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err)
- return err
- }
- conn.SetReadDeadline(time.Time{})
-
- if rep.Rep != gosocks5.Succeeded {
- glog.V(LWARNING).Infof("[rudp] %s <- %s : bind on %s failure", laddr, raddr, laddr)
- return errors.New(fmt.Sprintf("bind on %s failure", laddr))
- }
-
- glog.V(LINFO).Infof("[rudp] %s - %s BIND ON %s OK", laddr, raddr, rep.Addr)
-
- for {
- dgram, err := gosocks5.ReadUDPDatagram(conn)
- if err != nil {
- glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err)
- return err
- }
-
- go func() {
- b := make([]byte, MediumBufferSize)
-
- relay, err := net.DialUDP("udp", nil, raddr)
- if err != nil {
- glog.V(LWARNING).Infof("[rudp] %s -> %s : %s", laddr, raddr, err)
- return
- }
- defer relay.Close()
-
- if _, err := relay.Write(dgram.Data); err != nil {
- glog.V(LWARNING).Infof("[rudp] %s -> %s : %s", laddr, raddr, err)
- return
- }
- glog.V(LDEBUG).Infof("[rudp] %s >>> %s length: %d", laddr, raddr, len(dgram.Data))
-
- relay.SetReadDeadline(time.Now().Add(ReadTimeout))
- n, err := relay.Read(b)
- if err != nil {
- glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err)
- return
- }
- relay.SetReadDeadline(time.Time{})
-
- glog.V(LDEBUG).Infof("[rudp] %s <<< %s length: %d", laddr, raddr, n)
-
- conn.SetWriteDeadline(time.Now().Add(WriteTimeout))
- if err := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(n), 0, dgram.Header.Addr), b[:n]).Write(conn); err != nil {
- glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err)
- return
- }
- conn.SetWriteDeadline(time.Time{})
- }()
- }
-}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/gost.go b/cmd/gost/vendor/github.com/ginuerzh/gost/gost.go
deleted file mode 100644
index 6c043e7..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/gost.go
+++ /dev/null
@@ -1,146 +0,0 @@
-package gost
-
-import (
- "crypto/tls"
- "encoding/base64"
- "errors"
- "github.com/golang/glog"
- "net"
- "strings"
- "time"
-)
-
-const (
- Version = "2.4-dev"
-)
-
-// Log level for glog
-const (
- LFATAL = iota
- LERROR
- LWARNING
- LINFO
- LDEBUG
-)
-
-var (
- KeepAliveTime = 180 * time.Second
- DialTimeout = 30 * time.Second
- ReadTimeout = 90 * time.Second
- WriteTimeout = 90 * time.Second
-
- DefaultTTL = 60 // default udp node TTL in second for udp port forwarding
-)
-
-var (
- SmallBufferSize = 1 * 1024 // 1KB small buffer
- MediumBufferSize = 8 * 1024 // 8KB medium buffer
- LargeBufferSize = 32 * 1024 // 32KB large buffer
-)
-
-var (
- DefaultCertFile = "cert.pem"
- DefaultKeyFile = "key.pem"
-
- // This is the default cert and key data for convenience, providing your own cert is recommended.
- defaultRawCert = []byte(`-----BEGIN CERTIFICATE-----
-MIIC5jCCAdCgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
-bzAeFw0xNDAzMTcwNjIwNTFaFw0xNTAzMTcwNjIwNTFaMBIxEDAOBgNVBAoTB0Fj
-bWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDccNO1xmd4lWSf
-d/0/QS3E93cYIWHw831i/IKxigdRD/XMZonLdEHywW6lOiXazaP8e6CqPGSmnl0x
-5k/3dvGCMj2JCVxM6+z7NpL+AiwvXmvkj/TOciCgwqssCwYS2CiVwjfazRjx1ZUJ
-VDC5qiyRsfktQ2fVHrpnJGVSRagmiQgwGWBilVG9B8QvRtpQKN/GQGq17oIQm8aK
-kOdPt93g93ojMIg7YJpgDgOirvVz/hDn7YD4ryrtPos9CMafFkJprymKpRHyvz7P
-8a3+OkuPjFjPnwOHQ5u1U3+8vC44vfb1ExWzDLoT8Xp8Gndx39k0f7MVOol3GnYu
-MN/dvNUdAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIAoDATBgNVHSUEDDAKBggrBgEF
-BQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDALBgkqhkiG
-9w0BAQUDggEBAIG8CJqvTIgJnNOK+i5/IUc/3yF/mSCWuG8qP+Fmo2t6T0PVOtc0
-8wiWH5iWtCAhjn0MRY9l/hIjWm6gUZGHCGuEgsOPpJDYGoNLjH9Xwokm4y3LFNRK
-UBrrrDbKRNibApBHCapPf6gC5sXcjOwx7P2/kiHDgY7YH47jfcRhtAPNsM4gjsEO
-RmwENY+hRUFHIRfQTyalqND+x6PWhRo3K6hpHs4DQEYPq4P2kFPqUqSBymH+Ny5/
-BcQ3wdMNmC6Bm/oiL1QV0M+/InOsAgQk/EDd0kmoU1ZT2lYHQduGmP099bOlHNpS
-uqO3vXF3q8SPPr/A9TqSs7BKkBQbe0+cdsA=
------END CERTIFICATE-----`)
- defaultRawKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEA3HDTtcZneJVkn3f9P0EtxPd3GCFh8PN9YvyCsYoHUQ/1zGaJ
-y3RB8sFupTol2s2j/Hugqjxkpp5dMeZP93bxgjI9iQlcTOvs+zaS/gIsL15r5I/0
-znIgoMKrLAsGEtgolcI32s0Y8dWVCVQwuaoskbH5LUNn1R66ZyRlUkWoJokIMBlg
-YpVRvQfEL0baUCjfxkBqte6CEJvGipDnT7fd4Pd6IzCIO2CaYA4Doq71c/4Q5+2A
-+K8q7T6LPQjGnxZCaa8piqUR8r8+z/Gt/jpLj4xYz58Dh0ObtVN/vLwuOL329RMV
-swy6E/F6fBp3cd/ZNH+zFTqJdxp2LjDf3bzVHQIDAQABAoIBAHal26147nQ+pHwY
-jxwers3XDCjWvup7g79lfcqlKi79UiUEA6KYHm7UogMYewt7p4nb2KwH+XycvDiB
-aAUf5flXpTs+6IkWauUDiLZi4PlV7uiEexUq5FjirlL0U/6MjbudX4bK4WQ4uxDc
-WaV07Kw2iJFOOHLDKT0en9JaX5jtJNc4ZnE9efFoQ5jfypPWtRw65G1rULEg6nvc
-GDh+1ce+4foCkpLRC9c24xAwJONZG6x3UqrSS9qfAsb73nWRQrTfUcO3nhoN8VvL
-kL9skn1+S06NyUN0KoEtyRBp+RcpXSsBWAo6qZmo/WqhB/gjzWrxVwn20+yJSm35
-ZsMc6QECgYEA8GS+Mp9xfB2szWHz6YTOO1Uu4lHM1ccZMwS1G+dL0KO3uGAiPdvp
-woVot6v6w88t7onXsLo5pgz7SYug0CpkF3K/MRd1Ar4lH7PK7IBQ6rFr9ppVxDbx
-AEWRswUoPbKCr7W6HU8LbQHDavsDlEIwc6+DiwnL4BzlKjb7RpgQEz0CgYEA6sB5
-uHvx3Y5FDcGk1n73leQSAcq14l3ZLNpjrs8msoREDil/j5WmuSN58/7PGMiMgHEi
-1vLm3H796JmvGr9OBvspOjHyk07ui2/We/j9Hoxm1VWhyi8HkLNDj70HKalTTFMz
-RHO4O+0xCva+h9mKZrRMVktXr2jjdFn/0MYIZ2ECgYAIIsC1IeRLWQ3CHbCNlKsO
-IwHlMvOFwKk/qsceXKOaOhA7szU1dr3gkXdL0Aw6mEZrrkqYdpUA46uVf54/rU+Z
-445I8QxKvXiwK/uQKX+TkdGflPWWIG3jnnch4ejMvb/ihnn4B/bRB6A/fKNQXzUY
-lTYUfI5j1VaEKTwz1W2l2QKBgByFCcSp+jZqhGUpc3dDsZyaOr3Q/Mvlju7uEVI5
-hIAHpaT60a6GBd1UPAqymEJwivFHzW3D0NxU6VAK68UaHMaoWNfjHY9b9YsnKS2i
-kE3XzN56Ks+/avHfdYPO+UHMenw5V28nh+hv5pdoZrlmanQTz3pkaOC8o3WNQZEB
-nh/BAoGBAMY5z2f1pmMhrvtPDSlEVjgjELbaInxFaxPLR4Pdyzn83gtIIU14+R8X
-2LPs6PPwrNjWnIgrUSVXncIFL3pa45B+Mx1pYCpOAB1+nCZjIBQmpeo4Y0dwA/XH
-85EthKPvoszm+OPbyI16OcePV5ocX7lupRYuAo0pek7bomhmHWHz
------END RSA PRIVATE KEY-----`)
-)
-
-var (
- ErrEmptyChain = errors.New("empty chain")
-)
-
-func setKeepAlive(conn net.Conn, d time.Duration) error {
- c, ok := conn.(*net.TCPConn)
- if !ok {
- return errors.New("Not a TCP connection")
- }
- if err := c.SetKeepAlive(true); err != nil {
- return err
- }
- if err := c.SetKeepAlivePeriod(d); err != nil {
- return err
- }
- return nil
-}
-
-// Load the certificate from cert and key files, will use the default certificate if the provided info are invalid.
-func LoadCertificate(certFile, keyFile string) (tls.Certificate, error) {
- tlsCert, err := tls.LoadX509KeyPair(certFile, keyFile)
- if err == nil {
- return tlsCert, nil
- }
- glog.V(LWARNING).Infoln(err)
- return tls.X509KeyPair(defaultRawCert, defaultRawKey)
-}
-
-// Replace the default certificate by your own
-func SetDefaultCertificate(rawCert, rawKey []byte) {
- defaultRawCert = rawCert
- defaultRawKey = rawKey
-}
-
-func basicProxyAuth(proxyAuth string) (username, password string, ok bool) {
- if proxyAuth == "" {
- return
- }
-
- if !strings.HasPrefix(proxyAuth, "Basic ") {
- return
- }
- c, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(proxyAuth, "Basic "))
- if err != nil {
- return
- }
- cs := string(c)
- s := strings.IndexByte(cs, ':')
- if s < 0 {
- return
- }
-
- return cs[:s], cs[s+1:], true
-}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/http.go b/cmd/gost/vendor/github.com/ginuerzh/gost/http.go
deleted file mode 100644
index b9f7e4e..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/http.go
+++ /dev/null
@@ -1,385 +0,0 @@
-package gost
-
-import (
- "bufio"
- "crypto/tls"
- "encoding/base64"
- "github.com/golang/glog"
- "golang.org/x/net/http2"
- "io"
- "net"
- "net/http"
- "net/http/httputil"
- //"strings"
- "errors"
- "time"
-)
-
-type HttpServer struct {
- conn net.Conn
- Base *ProxyServer
-}
-
-func NewHttpServer(conn net.Conn, base *ProxyServer) *HttpServer {
- return &HttpServer{
- conn: conn,
- Base: base,
- }
-}
-
-// Default HTTP server handler
-func (s *HttpServer) HandleRequest(req *http.Request) {
- glog.V(LINFO).Infof("[http] %s %s - %s %s", req.Method, s.conn.RemoteAddr(), req.Host, req.Proto)
-
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpRequest(req, false)
- glog.Infoln(string(dump))
- }
-
- if req.Method == "PRI" && req.ProtoMajor == 2 {
- glog.V(LWARNING).Infof("[http] %s <- %s : Not an HTTP2 server", s.conn.RemoteAddr(), req.Host)
- resp := "HTTP/1.1 400 Bad Request\r\n" +
- "Proxy-Agent: gost/" + Version + "\r\n\r\n"
- s.conn.Write([]byte(resp))
- return
- }
-
- valid := false
- u, p, _ := basicProxyAuth(req.Header.Get("Proxy-Authorization"))
- glog.V(LINFO).Infoln(u, p)
- for _, user := range s.Base.Node.Users {
- username := user.Username()
- password, _ := user.Password()
- if (u == username && p == password) ||
- (u == username && password == "") ||
- (username == "" && p == password) {
- valid = true
- break
- }
- }
-
- if len(s.Base.Node.Users) > 0 && !valid {
- glog.V(LWARNING).Infof("[http] %s <- %s : proxy authentication required", s.conn.RemoteAddr(), req.Host)
- resp := "HTTP/1.1 407 Proxy Authentication Required\r\n" +
- "Proxy-Authenticate: Basic realm=\"gost\"\r\n" +
- "Proxy-Agent: gost/" + Version + "\r\n\r\n"
- s.conn.Write([]byte(resp))
- return
- }
-
- req.Header.Del("Proxy-Authorization")
-
- // forward http request
- lastNode := s.Base.Chain.lastNode
- if lastNode != nil && (lastNode.Protocol == "http" || lastNode.Protocol == "") {
- s.forwardRequest(req)
- return
- }
-
- c, err := s.Base.Chain.Dial(req.Host)
- if err != nil {
- glog.V(LWARNING).Infof("[http] %s -> %s : %s", s.conn.RemoteAddr(), req.Host, err)
-
- b := []byte("HTTP/1.1 503 Service unavailable\r\n" +
- "Proxy-Agent: gost/" + Version + "\r\n\r\n")
- glog.V(LDEBUG).Infof("[http] %s <- %s\n%s", s.conn.RemoteAddr(), req.Host, string(b))
- s.conn.Write(b)
- return
- }
- defer c.Close()
-
- if req.Method == http.MethodConnect {
- b := []byte("HTTP/1.1 200 Connection established\r\n" +
- "Proxy-Agent: gost/" + Version + "\r\n\r\n")
- glog.V(LDEBUG).Infof("[http] %s <- %s\n%s", s.conn.RemoteAddr(), req.Host, string(b))
- s.conn.Write(b)
- } else {
- req.Header.Del("Proxy-Connection")
- req.Header.Set("Connection", "Keep-Alive")
-
- if err = req.Write(c); err != nil {
- glog.V(LWARNING).Infof("[http] %s -> %s : %s", s.conn.RemoteAddr(), req.Host, err)
- return
- }
- }
-
- glog.V(LINFO).Infof("[http] %s <-> %s", s.conn.RemoteAddr(), req.Host)
- s.Base.transport(s.conn, c)
- glog.V(LINFO).Infof("[http] %s >-< %s", s.conn.RemoteAddr(), req.Host)
-}
-
-func (s *HttpServer) forwardRequest(req *http.Request) {
- last := s.Base.Chain.lastNode
- if last == nil {
- return
- }
- cc, err := s.Base.Chain.GetConn()
- if err != nil {
- glog.V(LWARNING).Infof("[http] %s -> %s : %s", s.conn.RemoteAddr(), last.Addr, err)
-
- b := []byte("HTTP/1.1 503 Service unavailable\r\n" +
- "Proxy-Agent: gost/" + Version + "\r\n\r\n")
- glog.V(LDEBUG).Infof("[http] %s <- %s\n%s", s.conn.RemoteAddr(), last.Addr, string(b))
- s.conn.Write(b)
- return
- }
- defer cc.Close()
-
- if len(last.Users) > 0 {
- user := last.Users[0]
- s := user.String()
- if _, set := user.Password(); !set {
- s += ":"
- }
- req.Header.Set("Proxy-Authorization",
- "Basic "+base64.StdEncoding.EncodeToString([]byte(s)))
- }
-
- cc.SetWriteDeadline(time.Now().Add(WriteTimeout))
- if err = req.WriteProxy(cc); err != nil {
- glog.V(LWARNING).Infof("[http] %s -> %s : %s", s.conn.RemoteAddr(), req.Host, err)
- return
- }
- cc.SetWriteDeadline(time.Time{})
-
- glog.V(LINFO).Infof("[http] %s <-> %s", s.conn.RemoteAddr(), req.Host)
- s.Base.transport(s.conn, cc)
- glog.V(LINFO).Infof("[http] %s >-< %s", s.conn.RemoteAddr(), req.Host)
- return
-}
-
-type Http2Server struct {
- Base *ProxyServer
- Handler http.Handler
- TLSConfig *tls.Config
-}
-
-func NewHttp2Server(base *ProxyServer) *Http2Server {
- return &Http2Server{Base: base}
-}
-
-func (s *Http2Server) ListenAndServeTLS(config *tls.Config) error {
- srv := http.Server{
- Addr: s.Base.Node.Addr,
- Handler: s.Handler,
- TLSConfig: config,
- }
- if srv.Handler == nil {
- srv.Handler = http.HandlerFunc(s.HandleRequest)
- }
- http2.ConfigureServer(&srv, nil)
- return srv.ListenAndServeTLS("", "")
-}
-
-// Default HTTP2 server handler
-func (s *Http2Server) HandleRequest(w http.ResponseWriter, req *http.Request) {
- target := req.Header.Get("Gost-Target")
- if target == "" {
- target = req.Host
- }
- glog.V(LINFO).Infof("[http2] %s %s - %s %s", req.Method, req.RemoteAddr, target, req.Proto)
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpRequest(req, false)
- glog.Infoln(string(dump))
- }
-
- w.Header().Set("Proxy-Agent", "gost/"+Version)
-
- // HTTP2 as transport
- if req.Header.Get("Proxy-Switch") == "gost" {
- conn, err := s.Upgrade(w, req)
- if err != nil {
- glog.V(LINFO).Infof("[http2] %s -> %s : %s", req.RemoteAddr, target, err)
- return
- }
- glog.V(LINFO).Infof("[http2] %s - %s : switch to HTTP2 transport mode OK", req.RemoteAddr, target)
- s.Base.handleConn(conn)
- return
- }
-
- valid := false
- u, p, _ := basicProxyAuth(req.Header.Get("Proxy-Authorization"))
- for _, user := range s.Base.Node.Users {
- username := user.Username()
- password, _ := user.Password()
- if (u == username && p == password) ||
- (u == username && password == "") ||
- (username == "" && p == password) {
- valid = true
- break
- }
- }
- if len(s.Base.Node.Users) > 0 && !valid {
- glog.V(LWARNING).Infof("[http2] %s <- %s : proxy authentication required", req.RemoteAddr, target)
- w.WriteHeader(http.StatusProxyAuthRequired)
- return
- }
-
- req.Header.Del("Proxy-Authorization")
-
- c, err := s.Base.Chain.Dial(target)
- if err != nil {
- glog.V(LWARNING).Infof("[http2] %s -> %s : %s", req.RemoteAddr, target, err)
- w.WriteHeader(http.StatusServiceUnavailable)
- return
- }
- defer c.Close()
-
- glog.V(LINFO).Infof("[http2] %s <-> %s", req.RemoteAddr, target)
-
- if req.Method == http.MethodConnect {
- w.WriteHeader(http.StatusOK)
- if fw, ok := w.(http.Flusher); ok {
- fw.Flush()
- }
-
- // compatible with HTTP1.x
- if hj, ok := w.(http.Hijacker); ok && req.ProtoMajor == 1 {
- // we take over the underly connection
- conn, _, err := hj.Hijack()
- if err != nil {
- glog.V(LWARNING).Infof("[http2] %s -> %s : %s", req.RemoteAddr, target, err)
- w.WriteHeader(http.StatusInternalServerError)
- return
- }
- defer conn.Close()
-
- s.Base.transport(conn, c)
- return
- }
-
- errc := make(chan error, 2)
-
- go func() {
- _, err := io.Copy(c, req.Body)
- errc <- err
- }()
- go func() {
- _, err := io.Copy(flushWriter{w}, c)
- errc <- err
- }()
-
- select {
- case <-errc:
- // glog.V(LWARNING).Infoln("exit", err)
- }
- glog.V(LINFO).Infof("[http2] %s >-< %s", req.RemoteAddr, target)
- return
- }
-
- req.Header.Set("Connection", "Keep-Alive")
- if err = req.Write(c); err != nil {
- glog.V(LWARNING).Infof("[http2] %s -> %s : %s", req.RemoteAddr, target, err)
- return
- }
-
- resp, err := http.ReadResponse(bufio.NewReader(c), req)
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- return
- }
- defer resp.Body.Close()
-
- for k, v := range resp.Header {
- for _, vv := range v {
- w.Header().Add(k, vv)
- }
- }
- w.WriteHeader(resp.StatusCode)
- if _, err := io.Copy(flushWriter{w}, resp.Body); err != nil {
- glog.V(LWARNING).Infof("[http2] %s <- %s : %s", req.RemoteAddr, target, err)
- }
-
- glog.V(LINFO).Infof("[http2] %s >-< %s", req.RemoteAddr, target)
-}
-
-// Upgrade upgrade an HTTP2 request to a bidirectional connection that preparing for tunneling other protocol, just like a websocket connection.
-func (s *Http2Server) Upgrade(w http.ResponseWriter, r *http.Request) (net.Conn, error) {
- if r.Method != http.MethodConnect {
- w.WriteHeader(http.StatusMethodNotAllowed)
- return nil, errors.New("Method not allowed")
- }
-
- w.WriteHeader(http.StatusOK)
-
- if fw, ok := w.(http.Flusher); ok {
- fw.Flush()
- }
-
- conn := &http2Conn{r: r.Body, w: flushWriter{w}}
- conn.remoteAddr, _ = net.ResolveTCPAddr("tcp", r.RemoteAddr)
- conn.localAddr, _ = net.ResolveTCPAddr("tcp", r.Host)
- return conn, nil
-}
-
-// HTTP2 client connection, wrapped up just like a net.Conn
-type http2Conn struct {
- r io.Reader
- w io.Writer
- remoteAddr net.Addr
- localAddr net.Addr
-}
-
-func (c *http2Conn) Read(b []byte) (n int, err error) {
- return c.r.Read(b)
-}
-
-func (c *http2Conn) Write(b []byte) (n int, err error) {
- return c.w.Write(b)
-}
-
-func (c *http2Conn) Close() (err error) {
- if rc, ok := c.r.(io.Closer); ok {
- err = rc.Close()
- }
- if w, ok := c.w.(io.Closer); ok {
- err = w.Close()
- }
- return
-}
-
-func (c *http2Conn) LocalAddr() net.Addr {
- return c.localAddr
-}
-
-func (c *http2Conn) RemoteAddr() net.Addr {
- return c.remoteAddr
-}
-
-func (c *http2Conn) SetDeadline(t time.Time) error {
- return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
-}
-
-func (c *http2Conn) SetReadDeadline(t time.Time) error {
- return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
-}
-
-func (c *http2Conn) SetWriteDeadline(t time.Time) error {
- return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
-}
-
-type flushWriter struct {
- w io.Writer
-}
-
-func (fw flushWriter) Write(p []byte) (n int, err error) {
- defer func() {
- if r := recover(); r != nil {
- if s, ok := r.(string); ok {
- err = errors.New(s)
- return
- }
- err = r.(error)
- }
- }()
-
- n, err = fw.w.Write(p)
- if err != nil {
- // glog.V(LWARNING).Infoln("flush writer:", err)
- return
- }
- if f, ok := fw.w.(http.Flusher); ok {
- f.Flush()
- }
- return
-}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/kcp.go b/cmd/gost/vendor/github.com/ginuerzh/gost/kcp.go
deleted file mode 100644
index 10752c3..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/kcp.go
+++ /dev/null
@@ -1,369 +0,0 @@
-// KCP feature is based on https://github.com/xtaci/kcptun
-
-package gost
-
-import (
- "crypto/sha1"
- "encoding/json"
- "github.com/golang/glog"
- "github.com/klauspost/compress/snappy"
- "golang.org/x/crypto/pbkdf2"
- "gopkg.in/xtaci/kcp-go.v2"
- "gopkg.in/xtaci/smux.v1"
- "net"
- "os"
- "time"
-)
-
-const (
- DefaultKCPConfigFile = "kcp.json"
-)
-
-var (
- SALT = "kcp-go"
-)
-
-type KCPConfig struct {
- Key string `json:"key"`
- Crypt string `json:"crypt"`
- Mode string `json:"mode"`
- MTU int `json:"mtu"`
- SndWnd int `json:"sndwnd"`
- RcvWnd int `json:"rcvwnd"`
- DataShard int `json:"datashard"`
- ParityShard int `json:"parityshard"`
- DSCP int `json:"dscp"`
- NoComp bool `json:"nocomp"`
- AckNodelay bool `json:"acknodelay"`
- NoDelay int `json:"nodelay"`
- Interval int `json:"interval"`
- Resend int `json:"resend"`
- NoCongestion int `json:"nc"`
- SockBuf int `json:"sockbuf"`
- KeepAlive int `json:"keepalive"`
-}
-
-func ParseKCPConfig(configFile string) (*KCPConfig, error) {
- if configFile == "" {
- configFile = DefaultKCPConfigFile
- }
- file, err := os.Open(configFile)
- if err != nil {
- return nil, err
- }
- defer file.Close()
-
- config := &KCPConfig{}
- if err = json.NewDecoder(file).Decode(config); err != nil {
- return nil, err
- }
- return config, nil
-}
-
-func (c *KCPConfig) Init() {
- switch c.Mode {
- case "normal":
- c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 30, 2, 1
- case "fast2":
- c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 20, 2, 1
- case "fast3":
- c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 10, 2, 1
- case "fast":
- fallthrough
- default:
- c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 20, 2, 1
- }
-}
-
-var (
- DefaultKCPConfig = &KCPConfig{
- Key: "it's a secrect",
- Crypt: "aes",
- Mode: "fast",
- MTU: 1350,
- SndWnd: 1024,
- RcvWnd: 1024,
- DataShard: 10,
- ParityShard: 3,
- DSCP: 0,
- NoComp: false,
- AckNodelay: false,
- NoDelay: 0,
- Interval: 40,
- Resend: 0,
- NoCongestion: 0,
- SockBuf: 4194304,
- KeepAlive: 10,
- }
-)
-
-type KCPServer struct {
- Base *ProxyServer
- Config *KCPConfig
-}
-
-func NewKCPServer(base *ProxyServer, config *KCPConfig) *KCPServer {
- return &KCPServer{Base: base, Config: config}
-}
-
-func (s *KCPServer) ListenAndServe() (err error) {
- if s.Config == nil {
- s.Config = DefaultKCPConfig
- }
- s.Config.Init()
-
- ln, err := kcp.ListenWithOptions(s.Base.Node.Addr,
- blockCrypt(s.Config.Key, s.Config.Crypt, SALT), s.Config.DataShard, s.Config.ParityShard)
- if err != nil {
- return err
- }
- if err = ln.SetDSCP(s.Config.DSCP); err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- }
- if err = ln.SetReadBuffer(s.Config.SockBuf); err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- }
- if err = ln.SetWriteBuffer(s.Config.SockBuf); err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- }
-
- for {
- conn, err := ln.AcceptKCP()
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- continue
- }
-
- conn.SetStreamMode(true)
- conn.SetNoDelay(s.Config.NoDelay, s.Config.Interval, s.Config.Resend, s.Config.NoCongestion)
- conn.SetMtu(s.Config.MTU)
- conn.SetWindowSize(s.Config.SndWnd, s.Config.RcvWnd)
- conn.SetACKNoDelay(s.Config.AckNodelay)
- conn.SetKeepAlive(s.Config.KeepAlive)
-
- go s.handleMux(conn)
- }
-}
-
-func (s *KCPServer) handleMux(conn net.Conn) {
- smuxConfig := smux.DefaultConfig()
- smuxConfig.MaxReceiveBuffer = s.Config.SockBuf
-
- glog.V(LINFO).Infof("[kcp] %s - %s", conn.RemoteAddr(), s.Base.Node.Addr)
-
- if !s.Config.NoComp {
- conn = newCompStreamConn(conn)
- }
-
- mux, err := smux.Server(conn, smuxConfig)
- if err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- return
- }
- defer mux.Close()
-
- glog.V(LINFO).Infof("[kcp] %s <-> %s", conn.RemoteAddr(), s.Base.Node.Addr)
- defer glog.V(LINFO).Infof("[kcp] %s >-< %s", conn.RemoteAddr(), s.Base.Node.Addr)
-
- for {
- stream, err := mux.AcceptStream()
- if err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- return
- }
- go s.Base.handleConn(NewKCPConn(conn, stream))
- }
-}
-
-func blockCrypt(key, crypt, salt string) (block kcp.BlockCrypt) {
- pass := pbkdf2.Key([]byte(key), []byte(salt), 4096, 32, sha1.New)
-
- switch crypt {
- case "tea":
- block, _ = kcp.NewTEABlockCrypt(pass[:16])
- case "xor":
- block, _ = kcp.NewSimpleXORBlockCrypt(pass)
- case "none":
- block, _ = kcp.NewNoneBlockCrypt(pass)
- case "aes-128":
- block, _ = kcp.NewAESBlockCrypt(pass[:16])
- case "aes-192":
- block, _ = kcp.NewAESBlockCrypt(pass[:24])
- case "blowfish":
- block, _ = kcp.NewBlowfishBlockCrypt(pass)
- case "twofish":
- block, _ = kcp.NewTwofishBlockCrypt(pass)
- case "cast5":
- block, _ = kcp.NewCast5BlockCrypt(pass[:16])
- case "3des":
- block, _ = kcp.NewTripleDESBlockCrypt(pass[:24])
- case "xtea":
- block, _ = kcp.NewXTEABlockCrypt(pass[:16])
- case "salsa20":
- block, _ = kcp.NewSalsa20BlockCrypt(pass)
- case "aes":
- fallthrough
- default: // aes
- block, _ = kcp.NewAESBlockCrypt(pass)
- }
- return
-}
-
-type KCPSession struct {
- conn net.Conn
- session *smux.Session
-}
-
-func DialKCP(addr string, config *KCPConfig) (*KCPSession, error) {
- if config == nil {
- config = DefaultKCPConfig
- }
- config.Init()
-
- kcpconn, err := kcp.DialWithOptions(addr,
- blockCrypt(config.Key, config.Crypt, SALT), config.DataShard, config.ParityShard)
- if err != nil {
- return nil, err
- }
-
- kcpconn.SetStreamMode(true)
- kcpconn.SetNoDelay(config.NoDelay, config.Interval, config.Resend, config.NoCongestion)
- kcpconn.SetWindowSize(config.SndWnd, config.RcvWnd)
- kcpconn.SetMtu(config.MTU)
- kcpconn.SetACKNoDelay(config.AckNodelay)
- kcpconn.SetKeepAlive(config.KeepAlive)
-
- if err := kcpconn.SetDSCP(config.DSCP); err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- }
- if err := kcpconn.SetReadBuffer(config.SockBuf); err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- }
- if err := kcpconn.SetWriteBuffer(config.SockBuf); err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- }
-
- // stream multiplex
- smuxConfig := smux.DefaultConfig()
- smuxConfig.MaxReceiveBuffer = config.SockBuf
- var conn net.Conn = kcpconn
- if !config.NoComp {
- conn = newCompStreamConn(kcpconn)
- }
- session, err := smux.Client(conn, smuxConfig)
- if err != nil {
- conn.Close()
- return nil, err
- }
- return &KCPSession{conn: conn, session: session}, nil
-}
-
-func (session *KCPSession) GetConn() (*KCPConn, error) {
- stream, err := session.session.OpenStream()
- if err != nil {
- session.Close()
- return nil, err
- }
- return NewKCPConn(session.conn, stream), nil
-}
-
-func (session *KCPSession) Close() error {
- return session.session.Close()
-}
-
-func (session *KCPSession) IsClosed() bool {
- return session.session.IsClosed()
-}
-
-func (session *KCPSession) NumStreams() int {
- return session.session.NumStreams()
-}
-
-type KCPConn struct {
- conn net.Conn
- stream *smux.Stream
-}
-
-func NewKCPConn(conn net.Conn, stream *smux.Stream) *KCPConn {
- return &KCPConn{conn: conn, stream: stream}
-}
-
-func (c *KCPConn) Read(b []byte) (n int, err error) {
- return c.stream.Read(b)
-}
-
-func (c *KCPConn) Write(b []byte) (n int, err error) {
- return c.stream.Write(b)
-}
-
-func (c *KCPConn) Close() error {
- return c.stream.Close()
-}
-
-func (c *KCPConn) LocalAddr() net.Addr {
- return c.conn.LocalAddr()
-}
-
-func (c *KCPConn) RemoteAddr() net.Addr {
- return c.conn.RemoteAddr()
-}
-
-func (c *KCPConn) SetDeadline(t time.Time) error {
- return c.conn.SetDeadline(t)
-}
-
-func (c *KCPConn) SetReadDeadline(t time.Time) error {
- return c.conn.SetReadDeadline(t)
-}
-
-func (c *KCPConn) SetWriteDeadline(t time.Time) error {
- return c.conn.SetWriteDeadline(t)
-}
-
-type compStreamConn struct {
- conn net.Conn
- w *snappy.Writer
- r *snappy.Reader
-}
-
-func newCompStreamConn(conn net.Conn) *compStreamConn {
- c := new(compStreamConn)
- c.conn = conn
- c.w = snappy.NewBufferedWriter(conn)
- c.r = snappy.NewReader(conn)
- return c
-}
-
-func (c *compStreamConn) Read(b []byte) (n int, err error) {
- return c.r.Read(b)
-}
-
-func (c *compStreamConn) Write(b []byte) (n int, err error) {
- n, err = c.w.Write(b)
- err = c.w.Flush()
- return n, err
-}
-
-func (c *compStreamConn) Close() error {
- return c.conn.Close()
-}
-
-func (c *compStreamConn) LocalAddr() net.Addr {
- return c.conn.LocalAddr()
-}
-
-func (c *compStreamConn) RemoteAddr() net.Addr {
- return c.conn.RemoteAddr()
-}
-
-func (c *compStreamConn) SetDeadline(t time.Time) error {
- return c.conn.SetDeadline(t)
-}
-
-func (c *compStreamConn) SetReadDeadline(t time.Time) error {
- return c.conn.SetReadDeadline(t)
-}
-
-func (c *compStreamConn) SetWriteDeadline(t time.Time) error {
- return c.conn.SetWriteDeadline(t)
-}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/node.go b/cmd/gost/vendor/github.com/ginuerzh/gost/node.go
deleted file mode 100644
index e72d0bb..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/node.go
+++ /dev/null
@@ -1,161 +0,0 @@
-package gost
-
-import (
- "bufio"
- "fmt"
- "github.com/golang/glog"
- "net"
- "net/url"
- "os"
- "strconv"
- "strings"
-)
-
-// Proxy node represent a proxy
-type ProxyNode struct {
- Addr string // [host]:port
- Protocol string // protocol: http/socks5/ss
- Transport string // transport: ws/wss/tls/http2/tcp/udp/rtcp/rudp
- Remote string // remote address, used by tcp/udp port forwarding
- Users []*url.Userinfo // authentication for proxy
- values url.Values
- serverName string
- conn net.Conn
-}
-
-// The proxy node string pattern is [scheme://][user:pass@host]:port.
-//
-// Scheme can be devided into two parts by character '+', such as: http+tls.
-func ParseProxyNode(s string) (node ProxyNode, err error) {
- if !strings.Contains(s, "://") {
- s = "gost://" + s
- }
- u, err := url.Parse(s)
- if err != nil {
- return
- }
-
- node = ProxyNode{
- Addr: u.Host,
- values: u.Query(),
- serverName: u.Host,
- }
-
- if u.User != nil {
- node.Users = append(node.Users, u.User)
- }
-
- users, er := parseUsers(node.Get("secrets"))
- if users != nil {
- node.Users = append(node.Users, users...)
- }
- if er != nil {
- glog.V(LWARNING).Infoln("secrets:", er)
- }
-
- if strings.Contains(u.Host, ":") {
- node.serverName, _, _ = net.SplitHostPort(u.Host)
- if node.serverName == "" {
- node.serverName = "localhost" // default server name
- }
- }
-
- schemes := strings.Split(u.Scheme, "+")
- if len(schemes) == 1 {
- node.Protocol = schemes[0]
- node.Transport = schemes[0]
- }
- if len(schemes) == 2 {
- node.Protocol = schemes[0]
- node.Transport = schemes[1]
- }
-
- switch node.Transport {
- case "ws", "wss", "tls", "http2", "quic", "kcp", "redirect", "ssu":
- case "https":
- node.Protocol = "http"
- node.Transport = "tls"
- case "tcp", "udp": // started from v2.1, tcp and udp are for local port forwarding
- node.Remote = strings.Trim(u.EscapedPath(), "/")
- case "rtcp", "rudp": // started from v2.1, rtcp and rudp are for remote port forwarding
- node.Remote = strings.Trim(u.EscapedPath(), "/")
- default:
- node.Transport = ""
- }
-
- switch node.Protocol {
- case "http", "http2", "socks", "socks5", "ss":
- default:
- node.Protocol = ""
- }
-
- return
-}
-
-func parseUsers(authFile string) (users []*url.Userinfo, err error) {
- if authFile == "" {
- return
- }
-
- file, err := os.Open(authFile)
- if err != nil {
- return
- }
- scanner := bufio.NewScanner(file)
- for scanner.Scan() {
- line := strings.TrimSpace(scanner.Text())
- if line == "" || strings.HasPrefix(line, "#") {
- continue
- }
-
- s := strings.SplitN(line, " ", 2)
- if len(s) == 1 {
- users = append(users, url.User(strings.TrimSpace(s[0])))
- } else if len(s) == 2 {
- users = append(users, url.UserPassword(strings.TrimSpace(s[0]), strings.TrimSpace(s[1])))
- }
- }
-
- err = scanner.Err()
- return
-}
-
-// Get get node parameter by key
-func (node *ProxyNode) Get(key string) string {
- return node.values.Get(key)
-}
-
-func (node *ProxyNode) getBool(key string) bool {
- s := node.Get(key)
- if b, _ := strconv.ParseBool(s); b {
- return b
- }
- n, _ := strconv.Atoi(s)
- return n > 0
-}
-
-func (node *ProxyNode) Set(key, value string) {
- node.values.Set(key, value)
-}
-
-func (node *ProxyNode) insecureSkipVerify() bool {
- return !node.getBool("secure")
-}
-
-func (node *ProxyNode) certFile() string {
- if cert := node.Get("cert"); cert != "" {
- return cert
- }
- return DefaultCertFile
-}
-
-func (node *ProxyNode) keyFile() string {
- if key := node.Get("key"); key != "" {
- return key
- }
- return DefaultKeyFile
-}
-
-func (node ProxyNode) String() string {
- return fmt.Sprintf("transport: %s, protocol: %s, addr: %s", node.Transport, node.Protocol, node.Addr)
-}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/quic.go b/cmd/gost/vendor/github.com/ginuerzh/gost/quic.go
deleted file mode 100644
index 0d97061..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/quic.go
+++ /dev/null
@@ -1,80 +0,0 @@
-package gost
-
-import (
- "bufio"
- "crypto/tls"
- "github.com/golang/glog"
- "github.com/lucas-clemente/quic-go/h2quic"
- "io"
- "net/http"
- "net/http/httputil"
-)
-
-type QuicServer struct {
- Base *ProxyServer
- Handler http.Handler
- TLSConfig *tls.Config
-}
-
-func NewQuicServer(base *ProxyServer) *QuicServer {
- return &QuicServer{Base: base}
-}
-
-func (s *QuicServer) ListenAndServeTLS(config *tls.Config) error {
- server := &h2quic.Server{
- Server: &http.Server{
- Addr: s.Base.Node.Addr,
- Handler: s.Handler,
- TLSConfig: config,
- },
- }
- if server.Handler == nil {
- server.Handler = http.HandlerFunc(s.HandleRequest)
- }
- return server.ListenAndServe()
-}
-
-func (s *QuicServer) HandleRequest(w http.ResponseWriter, req *http.Request) {
- target := req.Host
- glog.V(LINFO).Infof("[quic] %s %s - %s %s", req.Method, req.RemoteAddr, target, req.Proto)
-
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpRequest(req, false)
- glog.Infoln(string(dump))
- }
-
- c, err := s.Base.Chain.Dial(target)
- if err != nil {
- glog.V(LWARNING).Infof("[quic] %s -> %s : %s", req.RemoteAddr, target, err)
- w.WriteHeader(http.StatusServiceUnavailable)
- return
- }
- defer c.Close()
-
- glog.V(LINFO).Infof("[quic] %s <-> %s", req.RemoteAddr, target)
-
- req.Header.Set("Connection", "Keep-Alive")
- if err = req.Write(c); err != nil {
- glog.V(LWARNING).Infof("[quic] %s -> %s : %s", req.RemoteAddr, target, err)
- return
- }
-
- resp, err := http.ReadResponse(bufio.NewReader(c), req)
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- return
- }
- defer resp.Body.Close()
-
- for k, v := range resp.Header {
- for _, vv := range v {
- w.Header().Add(k, vv)
- }
- }
- w.WriteHeader(resp.StatusCode)
- if _, err := io.Copy(flushWriter{w}, resp.Body); err != nil {
- glog.V(LWARNING).Infof("[quic] %s <- %s : %s", req.RemoteAddr, target, err)
- }
-
- glog.V(LINFO).Infof("[quic] %s >-< %s", req.RemoteAddr, target)
-}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/redirect.go b/cmd/gost/vendor/github.com/ginuerzh/gost/redirect.go
deleted file mode 100644
index 7524418..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/redirect.go
+++ /dev/null
@@ -1,103 +0,0 @@
-// +build !windows
-
-package gost
-
-import (
- "errors"
- "fmt"
- "github.com/golang/glog"
- "net"
- "syscall"
-)
-
-const (
- SO_ORIGINAL_DST = 80
-)
-
-type RedsocksTCPServer struct {
- Base *ProxyServer
-}
-
-func NewRedsocksTCPServer(base *ProxyServer) *RedsocksTCPServer {
- return &RedsocksTCPServer{
- Base: base,
- }
-}
-
-func (s *RedsocksTCPServer) ListenAndServe() error {
- laddr, err := net.ResolveTCPAddr("tcp", s.Base.Node.Addr)
- if err != nil {
- return err
- }
- ln, err := net.ListenTCP("tcp", laddr)
- if err != nil {
- return err
- }
-
- defer ln.Close()
- for {
- conn, err := ln.AcceptTCP()
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- continue
- }
- go s.handleRedirectTCP(conn)
- }
-}
-
-func (s *RedsocksTCPServer) handleRedirectTCP(conn *net.TCPConn) {
- srcAddr := conn.RemoteAddr()
- dstAddr, conn, err := getOriginalDstAddr(conn)
- if err != nil {
- glog.V(LWARNING).Infof("[red-tcp] %s -> %s : %s", srcAddr, dstAddr, err)
- return
- }
- defer conn.Close()
-
- glog.V(LINFO).Infof("[red-tcp] %s -> %s", srcAddr, dstAddr)
-
- cc, err := s.Base.Chain.Dial(dstAddr.String())
- if err != nil {
- glog.V(LWARNING).Infof("[red-tcp] %s -> %s : %s", srcAddr, dstAddr, err)
- return
- }
- defer cc.Close()
-
- glog.V(LINFO).Infof("[red-tcp] %s <-> %s", srcAddr, dstAddr)
- s.Base.transport(conn, cc)
- glog.V(LINFO).Infof("[red-tcp] %s >-< %s", srcAddr, dstAddr)
-}
-
-func getOriginalDstAddr(conn *net.TCPConn) (addr net.Addr, c *net.TCPConn, err error) {
- defer conn.Close()
-
- fc, err := conn.File()
- if err != nil {
- return
- }
- defer fc.Close()
-
- mreq, err := syscall.GetsockoptIPv6Mreq(int(fc.Fd()), syscall.IPPROTO_IP, SO_ORIGINAL_DST)
- if err != nil {
- return
- }
-
- // only ipv4 support
- ip := net.IPv4(mreq.Multiaddr[4], mreq.Multiaddr[5], mreq.Multiaddr[6], mreq.Multiaddr[7])
- port := uint16(mreq.Multiaddr[2])<<8 + uint16(mreq.Multiaddr[3])
- addr, err = net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%d", ip.String(), port))
- if err != nil {
- return
- }
-
- cc, err := net.FileConn(fc)
- if err != nil {
- return
- }
-
- c, ok := cc.(*net.TCPConn)
- if !ok {
- err = errors.New("not a TCP connection")
- }
- return
-}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/redirect_win.go b/cmd/gost/vendor/github.com/ginuerzh/gost/redirect_win.go
deleted file mode 100644
index 116bdd8..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/redirect_win.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// +build windows
-
-package gost
-
-import (
- "errors"
-)
-
-type RedsocksTCPServer struct{}
-
-func NewRedsocksTCPServer(base *ProxyServer) *RedsocksTCPServer {
- return &RedsocksTCPServer{}
-}
-
-func (s *RedsocksTCPServer) ListenAndServe() error {
- return errors.New("Not supported")
-}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/server.go b/cmd/gost/vendor/github.com/ginuerzh/gost/server.go
deleted file mode 100644
index 63ff9a0..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/server.go
+++ /dev/null
@@ -1,260 +0,0 @@
-package gost
-
-import (
- "bufio"
- "crypto/tls"
- "github.com/ginuerzh/gosocks5"
- "github.com/golang/glog"
- ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
- "io"
- "net"
- "net/http"
- "strconv"
- "strings"
-)
-
-type ProxyServer struct {
- Node ProxyNode
- Chain *ProxyChain
- TLSConfig *tls.Config
- selector *serverSelector
- cipher *ss.Cipher
- ota bool
-}
-
-func NewProxyServer(node ProxyNode, chain *ProxyChain, config *tls.Config) *ProxyServer {
- if chain == nil {
- chain = NewProxyChain()
- }
- if config == nil {
- config = &tls.Config{}
- }
-
- var cipher *ss.Cipher
- var ota bool
- if node.Protocol == "ss" || node.Transport == "ssu" {
- var err error
- var method, password string
-
- if len(node.Users) > 0 {
- method = node.Users[0].Username()
- password, _ = node.Users[0].Password()
- }
- ota = node.getBool("ota")
- if strings.HasSuffix(method, "-auth") {
- ota = true
- method = strings.TrimSuffix(method, "-auth")
- }
- cipher, err = ss.NewCipher(method, password)
- if err != nil {
- glog.Fatal(err)
- }
- }
- return &ProxyServer{
- Node: node,
- Chain: chain,
- TLSConfig: config,
- selector: &serverSelector{ // socks5 server selector
- // methods that socks5 server supported
- methods: []uint8{
- gosocks5.MethodNoAuth,
- gosocks5.MethodUserPass,
- MethodTLS,
- MethodTLSAuth,
- },
- users: node.Users,
- tlsConfig: config,
- },
- cipher: cipher,
- ota: ota,
- }
-}
-
-func (s *ProxyServer) Serve() error {
- var ln net.Listener
- var err error
- node := s.Node
-
- switch node.Transport {
- case "ws": // websocket connection
- return NewWebsocketServer(s).ListenAndServe()
- case "wss": // websocket security connection
- return NewWebsocketServer(s).ListenAndServeTLS(s.TLSConfig)
- case "tls": // tls connection
- ln, err = tls.Listen("tcp", node.Addr, s.TLSConfig)
- case "http2": // Standard HTTP2 proxy server, compatible with HTTP1.x.
- server := NewHttp2Server(s)
- server.Handler = http.HandlerFunc(server.HandleRequest)
- return server.ListenAndServeTLS(s.TLSConfig)
- case "tcp": // Local TCP port forwarding
- return NewTcpForwardServer(s).ListenAndServe()
- case "udp": // Local UDP port forwarding
- ttl, _ := strconv.Atoi(s.Node.Get("ttl"))
- if ttl <= 0 {
- ttl = DefaultTTL
- }
- return NewUdpForwardServer(s, ttl).ListenAndServe()
- case "rtcp": // Remote TCP port forwarding
- return NewRTcpForwardServer(s).Serve()
- case "rudp": // Remote UDP port forwarding
- return NewRUdpForwardServer(s).Serve()
- case "quic":
- return NewQuicServer(s).ListenAndServeTLS(s.TLSConfig)
- case "kcp":
- config, err := ParseKCPConfig(s.Node.Get("c"))
- if err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- }
- if config == nil {
- config = DefaultKCPConfig
- }
- // override crypt and key if specified explicitly
- if s.Node.Users != nil {
- config.Crypt = s.Node.Users[0].Username()
- config.Key, _ = s.Node.Users[0].Password()
- }
- return NewKCPServer(s, config).ListenAndServe()
- case "redirect":
- return NewRedsocksTCPServer(s).ListenAndServe()
- case "ssu": // shadowsocks udp relay
- ttl, _ := strconv.Atoi(s.Node.Get("ttl"))
- if ttl <= 0 {
- ttl = DefaultTTL
- }
- return NewShadowUdpServer(s, ttl).ListenAndServe()
- default:
- ln, err = net.Listen("tcp", node.Addr)
- }
-
- if err != nil {
- return err
- }
-
- defer ln.Close()
-
- for {
- conn, err := ln.Accept()
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- continue
- }
-
- setKeepAlive(conn, KeepAliveTime)
-
- go s.handleConn(conn)
- }
-}
-
-func (s *ProxyServer) handleConn(conn net.Conn) {
- defer conn.Close()
-
- switch s.Node.Protocol {
- case "ss": // shadowsocks
- server := NewShadowServer(ss.NewConn(conn, s.cipher.Copy()), s)
- server.OTA = s.ota
- server.Serve()
- return
- case "http":
- req, err := http.ReadRequest(bufio.NewReader(conn))
- if err != nil {
- glog.V(LWARNING).Infoln("[http]", err)
- return
- }
- NewHttpServer(conn, s).HandleRequest(req)
- return
- case "socks", "socks5":
- conn = gosocks5.ServerConn(conn, s.selector)
- req, err := gosocks5.ReadRequest(conn)
- if err != nil {
- glog.V(LWARNING).Infoln("[socks5]", err)
- return
- }
- NewSocks5Server(conn, s).HandleRequest(req)
- return
- }
-
- // http or socks5
- b := make([]byte, MediumBufferSize)
-
- n, err := io.ReadAtLeast(conn, b, 2)
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- return
- }
-
- // TODO: use bufio.Reader
- if b[0] == gosocks5.Ver5 {
- mn := int(b[1]) // methods count
- length := 2 + mn
- if n < length {
- if _, err := io.ReadFull(conn, b[n:length]); err != nil {
- glog.V(LWARNING).Infoln("[socks5]", err)
- return
- }
- }
- // TODO: use gosocks5.ServerConn
- methods := b[2 : 2+mn]
- method := s.selector.Select(methods...)
- if _, err := conn.Write([]byte{gosocks5.Ver5, method}); err != nil {
- glog.V(LWARNING).Infoln("[socks5] select:", err)
- return
- }
- c, err := s.selector.OnSelected(method, conn)
- if err != nil {
- glog.V(LWARNING).Infoln("[socks5] onselected:", err)
- return
- }
- conn = c
-
- req, err := gosocks5.ReadRequest(conn)
- if err != nil {
- glog.V(LWARNING).Infoln("[socks5] request:", err)
- return
- }
- NewSocks5Server(conn, s).HandleRequest(req)
- return
- }
-
- req, err := http.ReadRequest(bufio.NewReader(&reqReader{b: b[:n], r: conn}))
- if err != nil {
- glog.V(LWARNING).Infoln("[http]", err)
- return
- }
- NewHttpServer(conn, s).HandleRequest(req)
-}
-
-func (_ *ProxyServer) transport(conn1, conn2 net.Conn) (err error) {
- errc := make(chan error, 2)
-
- go func() {
- _, err := io.Copy(conn1, conn2)
- errc <- err
- }()
-
- go func() {
- _, err := io.Copy(conn2, conn1)
- errc <- err
- }()
-
- select {
- case err = <-errc:
- //glog.V(LWARNING).Infoln("transport exit", err)
- }
-
- return
-}
-
-type reqReader struct {
- b []byte
- r io.Reader
-}
-
-func (r *reqReader) Read(p []byte) (n int, err error) {
- if len(r.b) == 0 {
- return r.r.Read(p)
- }
- n = copy(p, r.b)
- r.b = r.b[n:]
-
- return
-}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/socks.go b/cmd/gost/vendor/github.com/ginuerzh/gost/socks.go
deleted file mode 100644
index 59d801d..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/socks.go
+++ /dev/null
@@ -1,674 +0,0 @@
-package gost
-
-import (
- "bytes"
- "crypto/tls"
- //"errors"
- "github.com/ginuerzh/gosocks5"
- "github.com/golang/glog"
- //"os/exec"
- //"io"
- //"io/ioutil"
- "net"
- "net/url"
- "strconv"
- "time"
-)
-
-const (
- MethodTLS uint8 = 0x80 // extended method for tls
- MethodTLSAuth uint8 = 0x82 // extended method for tls+auth
-)
-
-const (
- CmdUdpTun uint8 = 0xF3 // extended method for udp over tcp
-)
-
-type clientSelector struct {
- methods []uint8
- user *url.Userinfo
- tlsConfig *tls.Config
-}
-
-func (selector *clientSelector) Methods() []uint8 {
- return selector.methods
-}
-
-func (selector *clientSelector) Select(methods ...uint8) (method uint8) {
- return
-}
-
-func (selector *clientSelector) OnSelected(method uint8, conn net.Conn) (net.Conn, error) {
- switch method {
- case MethodTLS:
- conn = tls.Client(conn, selector.tlsConfig)
-
- case gosocks5.MethodUserPass, MethodTLSAuth:
- if method == MethodTLSAuth {
- conn = tls.Client(conn, selector.tlsConfig)
- }
-
- var username, password string
- if selector.user != nil {
- username = selector.user.Username()
- password, _ = selector.user.Password()
- }
-
- req := gosocks5.NewUserPassRequest(gosocks5.UserPassVer, username, password)
- if err := req.Write(conn); err != nil {
- glog.V(LWARNING).Infoln("socks5 auth:", err)
- return nil, err
- }
- glog.V(LDEBUG).Infoln(req)
-
- resp, err := gosocks5.ReadUserPassResponse(conn)
- if err != nil {
- glog.V(LWARNING).Infoln("socks5 auth:", err)
- return nil, err
- }
- glog.V(LDEBUG).Infoln(resp)
-
- if resp.Status != gosocks5.Succeeded {
- return nil, gosocks5.ErrAuthFailure
- }
- case gosocks5.MethodNoAcceptable:
- return nil, gosocks5.ErrBadMethod
- }
-
- return conn, nil
-}
-
-type serverSelector struct {
- methods []uint8
- users []*url.Userinfo
- tlsConfig *tls.Config
-}
-
-func (selector *serverSelector) Methods() []uint8 {
- return selector.methods
-}
-
-func (selector *serverSelector) Select(methods ...uint8) (method uint8) {
- glog.V(LDEBUG).Infof("%d %d %v", gosocks5.Ver5, len(methods), methods)
-
- method = gosocks5.MethodNoAuth
- for _, m := range methods {
- if m == MethodTLS {
- method = m
- break
- }
- }
-
- // when user/pass is set, auth is mandatory
- if selector.users != nil {
- if method == gosocks5.MethodNoAuth {
- method = gosocks5.MethodUserPass
- }
- if method == MethodTLS {
- method = MethodTLSAuth
- }
- }
-
- return
-}
-
-func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Conn, error) {
- glog.V(LDEBUG).Infof("%d %d", gosocks5.Ver5, method)
-
- switch method {
- case MethodTLS:
- conn = tls.Server(conn, selector.tlsConfig)
-
- case gosocks5.MethodUserPass, MethodTLSAuth:
- if method == MethodTLSAuth {
- conn = tls.Server(conn, selector.tlsConfig)
- }
-
- req, err := gosocks5.ReadUserPassRequest(conn)
- if err != nil {
- glog.V(LWARNING).Infoln("[socks5-auth]", err)
- return nil, err
- }
- glog.V(LDEBUG).Infoln("[socks5]", req.String())
-
- valid := false
- for _, user := range selector.users {
- username := user.Username()
- password, _ := user.Password()
- if (req.Username == username && req.Password == password) ||
- (req.Username == username && password == "") ||
- (username == "" && req.Password == password) {
- valid = true
- break
- }
- }
- if len(selector.users) > 0 && !valid {
- resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Failure)
- if err := resp.Write(conn); err != nil {
- glog.V(LWARNING).Infoln("[socks5-auth]", err)
- return nil, err
- }
- glog.V(LDEBUG).Infoln("[socks5]", resp)
- glog.V(LWARNING).Infoln("[socks5-auth] proxy authentication required")
-
- return nil, gosocks5.ErrAuthFailure
- }
-
- resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Succeeded)
- if err := resp.Write(conn); err != nil {
- glog.V(LWARNING).Infoln("[socks5-auth]", err)
- return nil, err
- }
- glog.V(LDEBUG).Infoln(resp)
-
- case gosocks5.MethodNoAcceptable:
- return nil, gosocks5.ErrBadMethod
- }
-
- return conn, nil
-}
-
-type Socks5Server struct {
- conn net.Conn
- Base *ProxyServer
-}
-
-func NewSocks5Server(conn net.Conn, base *ProxyServer) *Socks5Server {
- return &Socks5Server{conn: conn, Base: base}
-}
-
-func (s *Socks5Server) HandleRequest(req *gosocks5.Request) {
- glog.V(LDEBUG).Infof("[socks5] %s -> %s\n%s", s.conn.RemoteAddr(), req.Addr, req)
-
- switch req.Cmd {
- case gosocks5.CmdConnect:
- glog.V(LINFO).Infof("[socks5-connect] %s -> %s", s.conn.RemoteAddr(), req.Addr)
- s.handleConnect(req)
-
- case gosocks5.CmdBind:
- glog.V(LINFO).Infof("[socks5-bind] %s - %s", s.conn.RemoteAddr(), req.Addr)
- s.handleBind(req)
-
- case gosocks5.CmdUdp:
- glog.V(LINFO).Infof("[socks5-udp] %s - %s", s.conn.RemoteAddr(), req.Addr)
- s.handleUDPRelay(req)
-
- case CmdUdpTun:
- glog.V(LINFO).Infof("[socks5-udp] %s - %s", s.conn.RemoteAddr(), req.Addr)
- s.handleUDPTunnel(req)
-
- default:
- glog.V(LWARNING).Infoln("[socks5] Unrecognized request:", req.Cmd)
- }
-}
-
-func (s *Socks5Server) handleConnect(req *gosocks5.Request) {
- cc, err := s.Base.Chain.Dial(req.Addr.String())
- if err != nil {
- glog.V(LWARNING).Infof("[socks5-connect] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err)
- rep := gosocks5.NewReply(gosocks5.HostUnreachable, nil)
- rep.Write(s.conn)
- glog.V(LDEBUG).Infof("[socks5-connect] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, rep)
- return
- }
- defer cc.Close()
-
- rep := gosocks5.NewReply(gosocks5.Succeeded, nil)
- if err := rep.Write(s.conn); err != nil {
- glog.V(LWARNING).Infof("[socks5-connect] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err)
- return
- }
- glog.V(LDEBUG).Infof("[socks5-connect] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, rep)
-
- glog.V(LINFO).Infof("[socks5-connect] %s <-> %s", s.conn.RemoteAddr(), req.Addr)
- //Transport(conn, cc)
- s.Base.transport(s.conn, cc)
- glog.V(LINFO).Infof("[socks5-connect] %s >-< %s", s.conn.RemoteAddr(), req.Addr)
-}
-
-func (s *Socks5Server) handleBind(req *gosocks5.Request) {
- cc, err := s.Base.Chain.GetConn()
-
- // connection error
- if err != nil && err != ErrEmptyChain {
- glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err)
- reply := gosocks5.NewReply(gosocks5.Failure, nil)
- reply.Write(s.conn)
- glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, reply)
- return
- }
- // serve socks5 bind
- if err == ErrEmptyChain {
- s.bindOn(req.Addr.String())
- return
- }
-
- defer cc.Close()
- // forward request
- req.Write(cc)
-
- glog.V(LINFO).Infof("[socks5-bind] %s <-> %s", s.conn.RemoteAddr(), cc.RemoteAddr())
- s.Base.transport(s.conn, cc)
- glog.V(LINFO).Infof("[socks5-bind] %s >-< %s", s.conn.RemoteAddr(), cc.RemoteAddr())
-}
-
-func (s *Socks5Server) handleUDPRelay(req *gosocks5.Request) {
- bindAddr, _ := net.ResolveUDPAddr("udp", req.Addr.String())
- relay, err := net.ListenUDP("udp", bindAddr) // udp associate, strict mode: if the port already in use, it will return error
- if err != nil {
- glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err)
- reply := gosocks5.NewReply(gosocks5.Failure, nil)
- reply.Write(s.conn)
- glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, reply)
- return
- }
- defer relay.Close()
-
- socksAddr := ToSocksAddr(relay.LocalAddr())
- socksAddr.Host, _, _ = net.SplitHostPort(s.conn.LocalAddr().String())
- reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr)
- if err := reply.Write(s.conn); err != nil {
- glog.V(LWARNING).Infof("[socks5-udp] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err)
- return
- }
- glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), reply.Addr, reply)
- glog.V(LINFO).Infof("[socks5-udp] %s - %s BIND ON %s OK", s.conn.RemoteAddr(), req.Addr, socksAddr)
-
- cc, err := s.Base.Chain.GetConn()
- // connection error
- if err != nil && err != ErrEmptyChain {
- glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), socksAddr, err)
- return
- }
-
- // serve as standard socks5 udp relay local <-> remote
- if err == ErrEmptyChain {
- peer, er := net.ListenUDP("udp", nil)
- if er != nil {
- glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), socksAddr, er)
- return
- }
- defer peer.Close()
-
- go s.transportUDP(relay, peer)
- }
-
- // forward udp local <-> tunnel
- if err == nil {
- defer cc.Close()
-
- cc.SetWriteDeadline(time.Now().Add(WriteTimeout))
- req := gosocks5.NewRequest(CmdUdpTun, nil)
- if err := req.Write(cc); err != nil {
- glog.V(LWARNING).Infoln("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), cc.RemoteAddr(), err)
- return
- }
- cc.SetWriteDeadline(time.Time{})
- glog.V(LDEBUG).Infof("[socks5-udp] %s -> %s\n%s", s.conn.RemoteAddr(), cc.RemoteAddr(), req)
-
- cc.SetReadDeadline(time.Now().Add(ReadTimeout))
- reply, err = gosocks5.ReadReply(cc)
- if err != nil {
- glog.V(LWARNING).Infoln("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), cc.RemoteAddr(), err)
- return
- }
- glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), cc.RemoteAddr(), reply)
-
- if reply.Rep != gosocks5.Succeeded {
- glog.V(LWARNING).Infoln("[socks5-udp] %s <- %s : udp associate failed", s.conn.RemoteAddr(), cc.RemoteAddr())
- return
- }
- cc.SetReadDeadline(time.Time{})
- glog.V(LINFO).Infof("[socks5-udp] %s <-> %s [tun: %s]", s.conn.RemoteAddr(), socksAddr, reply.Addr)
-
- go s.tunnelClientUDP(relay, cc)
- }
-
- glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr)
- b := make([]byte, SmallBufferSize)
- for {
- _, err := s.conn.Read(b) // discard any data from tcp connection
- if err != nil {
- glog.V(LWARNING).Infof("[socks5-udp] %s - %s : %s", s.conn.RemoteAddr(), socksAddr, err)
- break // client disconnected
- }
- }
- glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), socksAddr)
-}
-
-func (s *Socks5Server) handleUDPTunnel(req *gosocks5.Request) {
- cc, err := s.Base.Chain.GetConn()
-
- // connection error
- if err != nil && err != ErrEmptyChain {
- glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err)
- reply := gosocks5.NewReply(gosocks5.Failure, nil)
- reply.Write(s.conn)
- glog.V(LDEBUG).Infof("[socks5-udp] %s -> %s\n%s", s.conn.RemoteAddr(), req.Addr, reply)
- return
- }
-
- // serve tunnel udp, tunnel <-> remote, handle tunnel udp request
- if err == ErrEmptyChain {
- bindAddr, _ := net.ResolveUDPAddr("udp", req.Addr.String())
- uc, err := net.ListenUDP("udp", bindAddr)
- if err != nil {
- glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err)
- return
- }
- defer uc.Close()
-
- socksAddr := ToSocksAddr(uc.LocalAddr())
- socksAddr.Host, _, _ = net.SplitHostPort(s.conn.LocalAddr().String())
- reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr)
- if err := reply.Write(s.conn); err != nil {
- glog.V(LWARNING).Infof("[socks5-udp] %s <- %s : %s", s.conn.RemoteAddr(), socksAddr, err)
- return
- }
- glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), socksAddr, reply)
-
- glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr)
- s.tunnelServerUDP(s.conn, uc)
- glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), socksAddr)
- return
- }
-
- defer cc.Close()
-
- // tunnel <-> tunnel, direct forwarding
- req.Write(cc)
-
- glog.V(LINFO).Infof("[socks5-udp] %s <-> %s [tun]", s.conn.RemoteAddr(), cc.RemoteAddr())
- s.Base.transport(s.conn, cc)
- glog.V(LINFO).Infof("[socks5-udp] %s >-< %s [tun]", s.conn.RemoteAddr(), cc.RemoteAddr())
-}
-
-func (s *Socks5Server) bindOn(addr string) {
- bindAddr, _ := net.ResolveTCPAddr("tcp", addr)
- ln, err := net.ListenTCP("tcp", bindAddr) // strict mode: if the port already in use, it will return error
- if err != nil {
- glog.V(LWARNING).Infof("[socks5-bind] %s -> %s : %s", s.conn.RemoteAddr(), addr, err)
- gosocks5.NewReply(gosocks5.Failure, nil).Write(s.conn)
- return
- }
-
- socksAddr := ToSocksAddr(ln.Addr())
- // Issue: may not reachable when host has multi-interface
- socksAddr.Host, _, _ = net.SplitHostPort(s.conn.LocalAddr().String())
- reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr)
- if err := reply.Write(s.conn); err != nil {
- glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), addr, err)
- ln.Close()
- return
- }
- glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", s.conn.RemoteAddr(), addr, reply)
- glog.V(LINFO).Infof("[socks5-bind] %s - %s BIND ON %s OK", s.conn.RemoteAddr(), addr, socksAddr)
-
- var pconn net.Conn
- accept := func() <-chan error {
- errc := make(chan error, 1)
-
- go func() {
- defer close(errc)
- defer ln.Close()
-
- c, err := ln.AcceptTCP()
- if err != nil {
- errc <- err
- return
- }
- pconn = c
- }()
-
- return errc
- }
-
- pc1, pc2 := net.Pipe()
- pipe := func() <-chan error {
- errc := make(chan error, 1)
-
- go func() {
- defer close(errc)
- defer pc1.Close()
-
- errc <- s.Base.transport(s.conn, pc1)
- }()
-
- return errc
- }
-
- defer pc2.Close()
-
- for {
- select {
- case err := <-accept():
- if err != nil || pconn == nil {
- glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), addr, err)
- return
- }
- defer pconn.Close()
-
- reply := gosocks5.NewReply(gosocks5.Succeeded, ToSocksAddr(pconn.RemoteAddr()))
- if err := reply.Write(pc2); err != nil {
- glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), addr, err)
- }
- glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", s.conn.RemoteAddr(), addr, reply)
- glog.V(LINFO).Infof("[socks5-bind] %s <- %s PEER %s ACCEPTED", s.conn.RemoteAddr(), socksAddr, pconn.RemoteAddr())
-
- glog.V(LINFO).Infof("[socks5-bind] %s <-> %s", s.conn.RemoteAddr(), pconn.RemoteAddr())
- if err = s.Base.transport(pc2, pconn); err != nil {
- glog.V(LWARNING).Infoln(err)
- }
- glog.V(LINFO).Infof("[socks5-bind] %s >-< %s", s.conn.RemoteAddr(), pconn.RemoteAddr())
- return
- case err := <-pipe():
- glog.V(LWARNING).Infof("[socks5-bind] %s -> %s : %v", s.conn.RemoteAddr(), addr, err)
- ln.Close()
- return
- }
- }
-}
-
-func (s *Socks5Server) transportUDP(relay, peer *net.UDPConn) (err error) {
- errc := make(chan error, 2)
-
- var clientAddr *net.UDPAddr
-
- go func() {
- b := make([]byte, LargeBufferSize)
-
- for {
- n, laddr, err := relay.ReadFromUDP(b)
- if err != nil {
- errc <- err
- return
- }
- if clientAddr == nil {
- clientAddr = laddr
- }
- dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n]))
- if err != nil {
- errc <- err
- return
- }
-
- raddr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String())
- if err != nil {
- continue // drop silently
- }
- if _, err := peer.WriteToUDP(dgram.Data, raddr); err != nil {
- errc <- err
- return
- }
- glog.V(LDEBUG).Infof("[socks5-udp] %s >>> %s length: %d", relay.LocalAddr(), raddr, len(dgram.Data))
- }
- }()
-
- go func() {
- b := make([]byte, LargeBufferSize)
-
- for {
- n, raddr, err := peer.ReadFromUDP(b)
- if err != nil {
- errc <- err
- return
- }
- if clientAddr == nil {
- continue
- }
- buf := bytes.Buffer{}
- dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(0, 0, ToSocksAddr(raddr)), b[:n])
- dgram.Write(&buf)
- if _, err := relay.WriteToUDP(buf.Bytes(), clientAddr); err != nil {
- errc <- err
- return
- }
- glog.V(LDEBUG).Infof("[socks5-udp] %s <<< %s length: %d", relay.LocalAddr(), raddr, len(dgram.Data))
- }
- }()
-
- select {
- case err = <-errc:
- //log.Println("w exit", err)
- }
-
- return
-}
-
-func (s *Socks5Server) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error) {
- errc := make(chan error, 2)
-
- var clientAddr *net.UDPAddr
-
- go func() {
- b := make([]byte, LargeBufferSize)
-
- for {
- n, addr, err := uc.ReadFromUDP(b)
- if err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), addr, err)
- errc <- err
- return
- }
-
- // glog.V(LDEBUG).Infof("read udp %d, % #x", n, b[:n])
- // pipe from relay to tunnel
- dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n]))
- if err != nil {
- errc <- err
- return
- }
- if clientAddr == nil {
- clientAddr = addr
- }
- dgram.Header.Rsv = uint16(len(dgram.Data))
- if err := dgram.Write(cc); err != nil {
- errc <- err
- return
- }
- glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data))
- }
- }()
-
- go func() {
- for {
- dgram, err := gosocks5.ReadUDPDatagram(cc)
- if err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s -> 0 : %s", cc.RemoteAddr(), err)
- errc <- err
- return
- }
-
- // pipe from tunnel to relay
- if clientAddr == nil {
- continue
- }
- dgram.Header.Rsv = 0
-
- buf := bytes.Buffer{}
- dgram.Write(&buf)
- if _, err := uc.WriteToUDP(buf.Bytes(), clientAddr); err != nil {
- errc <- err
- return
- }
- glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data))
- }
- }()
-
- select {
- case err = <-errc:
- }
-
- return
-}
-
-func (s *Socks5Server) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error) {
- errc := make(chan error, 2)
-
- go func() {
- b := make([]byte, LargeBufferSize)
-
- for {
- n, addr, err := uc.ReadFromUDP(b)
- if err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), addr, err)
- errc <- err
- return
- }
-
- // pipe from peer to tunnel
- dgram := gosocks5.NewUDPDatagram(
- gosocks5.NewUDPHeader(uint16(n), 0, ToSocksAddr(addr)), b[:n])
- if err := dgram.Write(cc); err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), dgram.Header.Addr, err)
- errc <- err
- return
- }
- glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", cc.RemoteAddr(), dgram.Header.Addr, len(dgram.Data))
- }
- }()
-
- go func() {
- for {
- dgram, err := gosocks5.ReadUDPDatagram(cc)
- if err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s -> 0 : %s", cc.RemoteAddr(), err)
- errc <- err
- return
- }
-
- // pipe from tunnel to peer
- addr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String())
- if err != nil {
- continue // drop silently
- }
- if _, err := uc.WriteToUDP(dgram.Data, addr); err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s -> %s : %s", cc.RemoteAddr(), addr, err)
- errc <- err
- return
- }
- glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", cc.RemoteAddr(), addr, len(dgram.Data))
- }
- }()
-
- select {
- case err = <-errc:
- }
-
- return
-}
-
-func ToSocksAddr(addr net.Addr) *gosocks5.Addr {
- host := "0.0.0.0"
- port := 0
- if addr != nil {
- h, p, _ := net.SplitHostPort(addr.String())
- host = h
- port, _ = strconv.Atoi(p)
- }
- return &gosocks5.Addr{
- Type: gosocks5.AddrIPv4,
- Host: host,
- Port: uint16(port),
- }
-}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/ss.go b/cmd/gost/vendor/github.com/ginuerzh/gost/ss.go
deleted file mode 100644
index cf5eb47..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/ss.go
+++ /dev/null
@@ -1,353 +0,0 @@
-package gost
-
-import (
- "bytes"
- "encoding/binary"
- "errors"
- "fmt"
- "github.com/ginuerzh/gosocks5"
- "github.com/golang/glog"
- ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
- "io"
- "net"
- "strconv"
- "time"
-)
-
-const (
- idType = 0 // address type index
- idIP0 = 1 // ip addres start index
- idDmLen = 1 // domain address length index
- idDm0 = 2 // domain address start index
-
- typeIPv4 = 1 // type is ipv4 address
- typeDm = 3 // type is domain address
- typeIPv6 = 4 // type is ipv6 address
-
- lenIPv4 = net.IPv4len + 2 // ipv4 + 2port
- lenIPv6 = net.IPv6len + 2 // ipv6 + 2port
- lenDmBase = 2 // 1addrLen + 2port, plus addrLen
- lenHmacSha1 = 10
-)
-
-type ShadowServer struct {
- conn *ss.Conn
- Base *ProxyServer
- OTA bool // one time auth
-}
-
-func NewShadowServer(conn *ss.Conn, base *ProxyServer) *ShadowServer {
- return &ShadowServer{conn: conn, Base: base}
-}
-
-func (s *ShadowServer) Serve() {
- glog.V(LINFO).Infof("[ss] %s - %s", s.conn.RemoteAddr(), s.conn.LocalAddr())
-
- addr, ota, err := s.getRequest()
- if err != nil {
- glog.V(LWARNING).Infof("[ss] %s - %s : %s", s.conn.RemoteAddr(), s.conn.LocalAddr(), err)
- return
- }
- glog.V(LINFO).Infof("[ss] %s -> %s, ota: %v", s.conn.RemoteAddr(), addr, ota)
-
- cc, err := s.Base.Chain.Dial(addr)
- if err != nil {
- glog.V(LWARNING).Infof("[ss] %s -> %s : %s", s.conn.RemoteAddr(), addr, err)
- return
- }
- defer cc.Close()
-
- glog.V(LINFO).Infof("[ss] %s <-> %s", s.conn.RemoteAddr(), addr)
- if ota {
- s.transportOTA(s.conn, cc)
- } else {
- s.Base.transport(&shadowConn{conn: s.conn}, cc)
- }
- glog.V(LINFO).Infof("[ss] %s >-< %s", s.conn.RemoteAddr(), addr)
-}
-
-// This function is copied from shadowsocks library with some modification.
-func (s *ShadowServer) getRequest() (host string, ota bool, err error) {
- // buf size should at least have the same size with the largest possible
- // request size (when addrType is 3, domain name has at most 256 bytes)
- // 1(addrType) + 1(lenByte) + 256(max length address) + 2(port)
- buf := make([]byte, SmallBufferSize)
-
- // read till we get possible domain length field
- s.conn.SetReadDeadline(time.Now().Add(ReadTimeout))
- if _, err = io.ReadFull(s.conn, buf[:idType+1]); err != nil {
- return
- }
-
- var reqStart, reqEnd int
- addrType := buf[idType]
- switch addrType & ss.AddrMask {
- case typeIPv4:
- reqStart, reqEnd = idIP0, idIP0+lenIPv4
- case typeIPv6:
- reqStart, reqEnd = idIP0, idIP0+lenIPv6
- case typeDm:
- if _, err = io.ReadFull(s.conn, buf[idType+1:idDmLen+1]); err != nil {
- return
- }
- reqStart, reqEnd = idDm0, int(idDm0+buf[idDmLen]+lenDmBase)
- default:
- err = fmt.Errorf("addr type %d not supported", addrType&ss.AddrMask)
- return
- }
-
- if _, err = io.ReadFull(s.conn, buf[reqStart:reqEnd]); err != nil {
- return
- }
-
- // Return string for typeIP is not most efficient, but browsers (Chrome,
- // Safari, Firefox) all seems using typeDm exclusively. So this is not a
- // big problem.
- switch addrType & ss.AddrMask {
- case typeIPv4:
- host = net.IP(buf[idIP0 : idIP0+net.IPv4len]).String()
- case typeIPv6:
- host = net.IP(buf[idIP0 : idIP0+net.IPv6len]).String()
- case typeDm:
- host = string(buf[idDm0 : idDm0+buf[idDmLen]])
- }
- // parse port
- port := binary.BigEndian.Uint16(buf[reqEnd-2 : reqEnd])
- host = net.JoinHostPort(host, strconv.Itoa(int(port)))
- // if specified one time auth enabled, we should verify this
- if s.OTA || addrType&ss.OneTimeAuthMask > 0 {
- ota = true
- if _, err = io.ReadFull(s.conn, buf[reqEnd:reqEnd+lenHmacSha1]); err != nil {
- return
- }
- iv := s.conn.GetIv()
- key := s.conn.GetKey()
- actualHmacSha1Buf := ss.HmacSha1(append(iv, key...), buf[:reqEnd])
- if !bytes.Equal(buf[reqEnd:reqEnd+lenHmacSha1], actualHmacSha1Buf) {
- err = fmt.Errorf("verify one time auth failed, iv=%v key=%v data=%v", iv, key, buf[:reqEnd])
- return
- }
- }
- return
-}
-
-const (
- dataLenLen = 2
- hmacSha1Len = 10
- idxData0 = dataLenLen + hmacSha1Len
-)
-
-// copyOta copies data from src to dst with ota verification.
-//
-// This function is copied from shadowsocks library with some modification.
-func (s *ShadowServer) copyOta(dst net.Conn, src *ss.Conn) (int64, error) {
- // sometimes it have to fill large block
- buf := make([]byte, LargeBufferSize)
- for {
- src.SetReadDeadline(time.Now().Add(ReadTimeout))
- if n, err := io.ReadFull(src, buf[:dataLenLen+hmacSha1Len]); err != nil {
- return int64(n), err
- }
- src.SetReadDeadline(time.Time{})
-
- dataLen := binary.BigEndian.Uint16(buf[:dataLenLen])
- expectedHmacSha1 := buf[dataLenLen:idxData0]
-
- var dataBuf []byte
- if len(buf) < int(idxData0+dataLen) {
- dataBuf = make([]byte, dataLen)
- } else {
- dataBuf = buf[idxData0 : idxData0+dataLen]
- }
- if n, err := io.ReadFull(src, dataBuf); err != nil {
- return int64(n), err
- }
- chunkIdBytes := make([]byte, 4)
- chunkId := src.GetAndIncrChunkId()
- binary.BigEndian.PutUint32(chunkIdBytes, chunkId)
- actualHmacSha1 := ss.HmacSha1(append(src.GetIv(), chunkIdBytes...), dataBuf)
- if !bytes.Equal(expectedHmacSha1, actualHmacSha1) {
- return 0, errors.New("ota error: mismatch")
- }
-
- if n, err := dst.Write(dataBuf); err != nil {
- return int64(n), err
- }
- }
-}
-
-func (s *ShadowServer) transportOTA(sc *ss.Conn, cc net.Conn) (err error) {
- errc := make(chan error, 2)
-
- go func() {
- _, err := io.Copy(&shadowConn{conn: sc}, cc)
- errc <- err
- }()
-
- go func() {
- _, err := s.copyOta(cc, sc)
- errc <- err
- }()
-
- select {
- case err = <-errc:
- //glog.V(LWARNING).Infoln("transport exit", err)
- }
-
- return
-}
-
-// Due to in/out byte length is inconsistent of the shadowsocks.Conn.Write,
-// we wrap around it to make io.Copy happy
-type shadowConn struct {
- conn *ss.Conn
-}
-
-func (c *shadowConn) Read(b []byte) (n int, err error) {
- return c.conn.Read(b)
-}
-
-func (c *shadowConn) Write(b []byte) (n int, err error) {
- n = len(b) // force byte length consistent
- _, err = c.conn.Write(b)
- return
-}
-
-func (c *shadowConn) Close() error {
- return c.conn.Close()
-}
-
-func (c *shadowConn) LocalAddr() net.Addr {
- return c.conn.LocalAddr()
-}
-
-func (c *shadowConn) RemoteAddr() net.Addr {
- return c.conn.RemoteAddr()
-}
-
-func (c *shadowConn) SetDeadline(t time.Time) error {
- return c.conn.SetDeadline(t)
-}
-
-func (c *shadowConn) SetReadDeadline(t time.Time) error {
- return c.conn.SetReadDeadline(t)
-}
-
-func (c *shadowConn) SetWriteDeadline(t time.Time) error {
- return c.conn.SetWriteDeadline(t)
-}
-
-type ShadowUdpServer struct {
- Base *ProxyServer
- TTL int
-}
-
-func NewShadowUdpServer(base *ProxyServer, ttl int) *ShadowUdpServer {
- return &ShadowUdpServer{Base: base, TTL: ttl}
-}
-
-func (s *ShadowUdpServer) ListenAndServe() error {
- laddr, err := net.ResolveUDPAddr("udp", s.Base.Node.Addr)
- if err != nil {
- return err
- }
- lconn, err := net.ListenUDP("udp", laddr)
- if err != nil {
- return err
- }
- defer lconn.Close()
-
- conn := ss.NewSecurePacketConn(lconn, s.Base.cipher.Copy(), true) // force OTA on
-
- rChan, wChan := make(chan *packet, 128), make(chan *packet, 128)
- // start send queue
- go func(ch chan<- *packet) {
- for {
- b := make([]byte, MediumBufferSize)
- n, addr, err := conn.ReadFrom(b[3:]) // add rsv and frag fields to make it the standard SOCKS5 UDP datagram
- if err != nil {
- glog.V(LWARNING).Infof("[ssu] %s -> %s : %s", addr, laddr, err)
- continue
- }
-
- b[3] &= ss.AddrMask // remove OTA flag
- dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n+3]))
- if err != nil {
- glog.V(LWARNING).Infof("[ssu] %s -> %s : %s", addr, laddr, err)
- continue
- }
-
- select {
- case ch <- &packet{srcAddr: addr.String(), dstAddr: dgram.Header.Addr.String(), data: dgram.Data}:
- case <-time.After(time.Second * 3):
- glog.V(LWARNING).Infof("[ssu] %s -> %s : %s", addr, dgram.Header.Addr.String(), "send queue is full, discard")
- }
- }
- }(wChan)
- // start recv queue
- go func(ch <-chan *packet) {
- for pkt := range ch {
- srcAddr, err := net.ResolveUDPAddr("udp", pkt.srcAddr)
- if err != nil {
- glog.V(LWARNING).Infof("[ssu] %s <- %s : %s", pkt.dstAddr, pkt.srcAddr, err)
- continue
- }
- dstAddr, err := net.ResolveUDPAddr("udp", pkt.dstAddr)
- if err != nil {
- glog.V(LWARNING).Infof("[ssu] %s <- %s : %s", pkt.dstAddr, pkt.srcAddr, err)
- continue
- }
-
- dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(0, 0, ToSocksAddr(srcAddr)), pkt.data)
- b := bytes.Buffer{}
- dgram.Write(&b)
- if b.Len() < 10 {
- glog.V(LWARNING).Infof("[ssu] %s <- %s : invalid udp datagram", pkt.dstAddr, pkt.srcAddr)
- continue
- }
-
- if _, err := conn.WriteTo(b.Bytes()[3:], dstAddr); err != nil { // remove rsv and frag fields to make it standard shadowsocks UDP datagram
- glog.V(LWARNING).Infof("[ssu] %s <- %s : %s", pkt.dstAddr, pkt.srcAddr, err)
- return
- }
- }
- }(rChan)
-
- // mapping client to node
- m := make(map[string]*cnode)
-
- // start dispatcher
- for pkt := range wChan {
- // clear obsolete nodes
- for k, node := range m {
- if node != nil && node.err != nil {
- close(node.wChan)
- delete(m, k)
- glog.V(LINFO).Infof("[ssu] clear node %s", k)
- }
- }
-
- node, ok := m[pkt.srcAddr]
- if !ok {
- node = &cnode{
- chain: s.Base.Chain,
- srcAddr: pkt.srcAddr,
- dstAddr: pkt.dstAddr,
- rChan: rChan,
- wChan: make(chan *packet, 32),
- ttl: time.Duration(s.TTL) * time.Second,
- }
- m[pkt.srcAddr] = node
- go node.run()
- glog.V(LINFO).Infof("[ssu] %s -> %s : new client (%d)", pkt.srcAddr, pkt.dstAddr, len(m))
- }
-
- select {
- case node.wChan <- pkt:
- case <-time.After(time.Second * 3):
- glog.V(LWARNING).Infof("[ssu] %s -> %s : %s", pkt.srcAddr, pkt.dstAddr, "node send queue is full, discard")
- }
- }
-
- return nil
-}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/ws.go b/cmd/gost/vendor/github.com/ginuerzh/gost/ws.go
deleted file mode 100644
index da902e6..0000000
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/ws.go
+++ /dev/null
@@ -1,142 +0,0 @@
-package gost
-
-import (
- "crypto/tls"
- "github.com/golang/glog"
- "gopkg.in/gorilla/websocket.v1"
- "net"
- "net/http"
- "net/http/httputil"
- "time"
-)
-
-type WebsocketServer struct {
- Addr string
- Base *ProxyServer
- Handler http.Handler
- upgrader websocket.Upgrader
-}
-
-func NewWebsocketServer(base *ProxyServer) *WebsocketServer {
- return &WebsocketServer{
- Addr: base.Node.Addr,
- Base: base,
- upgrader: websocket.Upgrader{
- ReadBufferSize: 1024,
- WriteBufferSize: 1024,
- CheckOrigin: func(r *http.Request) bool { return true },
- EnableCompression: true,
- },
- }
-}
-
-// Default websocket server handler
-func (s *WebsocketServer) HandleRequest(w http.ResponseWriter, r *http.Request) {
- glog.V(LINFO).Infof("[ws] %s - %s", r.RemoteAddr, s.Addr)
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpRequest(r, false)
- glog.V(LDEBUG).Infof("[ws] %s - %s\n%s", r.RemoteAddr, s.Addr, string(dump))
- }
- conn, err := s.upgrader.Upgrade(w, r, nil)
- if err != nil {
- glog.V(LERROR).Infof("[ws] %s - %s : %s", r.RemoteAddr, s.Addr, err)
- return
- }
- s.Base.handleConn(WebsocketServerConn(conn))
-}
-
-func (s *WebsocketServer) ListenAndServe() error {
- mux := http.NewServeMux()
- if s.Handler == nil {
- s.Handler = http.HandlerFunc(s.HandleRequest)
- }
- mux.Handle("/ws", s.Handler)
- return http.ListenAndServe(s.Addr, mux)
-}
-
-func (s *WebsocketServer) ListenAndServeTLS(config *tls.Config) error {
- mux := http.NewServeMux()
- if s.Handler == nil {
- s.Handler = http.HandlerFunc(s.HandleRequest)
- }
- mux.Handle("/ws", s.Handler)
- server := &http.Server{
- Addr: s.Addr,
- Handler: mux,
- TLSConfig: config,
- }
- return server.ListenAndServeTLS("", "")
-}
-
-type WebsocketConn struct {
- conn *websocket.Conn
- rb []byte
-}
-
-func WebsocketClientConn(url string, conn net.Conn, config *tls.Config) (*WebsocketConn, error) {
- dialer := websocket.Dialer{
- ReadBufferSize: 1024,
- WriteBufferSize: 1024,
- TLSClientConfig: config,
- HandshakeTimeout: DialTimeout,
- EnableCompression: true,
- NetDial: func(net, addr string) (net.Conn, error) {
- return conn, nil
- },
- }
-
- c, resp, err := dialer.Dial(url, nil)
- if err != nil {
- return nil, err
- }
- resp.Body.Close()
- return &WebsocketConn{conn: c}, nil
-}
-
-func WebsocketServerConn(conn *websocket.Conn) *WebsocketConn {
- conn.EnableWriteCompression(true)
- return &WebsocketConn{
- conn: conn,
- }
-}
-
-func (c *WebsocketConn) Read(b []byte) (n int, err error) {
- if len(c.rb) == 0 {
- _, c.rb, err = c.conn.ReadMessage()
- }
- n = copy(b, c.rb)
- c.rb = c.rb[n:]
- return
-}
-
-func (c *WebsocketConn) Write(b []byte) (n int, err error) {
- err = c.conn.WriteMessage(websocket.BinaryMessage, b)
- n = len(b)
- return
-}
-
-func (c *WebsocketConn) Close() error {
- return c.conn.Close()
-}
-
-func (c *WebsocketConn) LocalAddr() net.Addr {
- return c.conn.LocalAddr()
-}
-
-func (c *WebsocketConn) RemoteAddr() net.Addr {
- return c.conn.RemoteAddr()
-}
-
-func (conn *WebsocketConn) SetDeadline(t time.Time) error {
- if err := conn.SetReadDeadline(t); err != nil {
- return err
- }
- return conn.SetWriteDeadline(t)
-}
-func (c *WebsocketConn) SetReadDeadline(t time.Time) error {
- return c.conn.SetReadDeadline(t)
-}
-
-func (c *WebsocketConn) SetWriteDeadline(t time.Time) error {
- return c.conn.SetWriteDeadline(t)
-}
diff --git a/cmd/gost/vendor/github.com/klauspost/crc32/README.md b/cmd/gost/vendor/github.com/klauspost/crc32/README.md
deleted file mode 100644
index 029625d..0000000
--- a/cmd/gost/vendor/github.com/klauspost/crc32/README.md
+++ /dev/null
@@ -1,87 +0,0 @@
-# crc32
-CRC32 hash with x64 optimizations
-
-This package is a drop-in replacement for the standard library `hash/crc32` package, that features SSE 4.2 optimizations on x64 platforms, for a 10x speedup.
-
-[](https://travis-ci.org/klauspost/crc32)
-
-# usage
-
-Install using `go get github.com/klauspost/crc32`. This library is based on Go 1.5 code and requires Go 1.3 or newer.
-
-Replace `import "hash/crc32"` with `import "github.com/klauspost/crc32"` and you are good to go.
-
-# changes
-* Oct 20, 2016: Changes have been merged to upstream Go. Package updated to match.
-* Dec 4, 2015: Uses the "slice-by-8" trick more extensively, which gives a 1.5 to 2.5x speedup if assembler is unavailable.
-
-
-# performance
-
-For *Go 1.7* performance is equivalent to the standard library. So if you use this package for Go 1.7 you can switch back.
-
-
-For IEEE tables (the most common), there is approximately a factor 10 speedup with "CLMUL" (Carryless multiplication) instruction:
-```
-benchmark old ns/op new ns/op delta
-BenchmarkCrc32KB 99955 10258 -89.74%
-
-benchmark old MB/s new MB/s speedup
-BenchmarkCrc32KB 327.83 3194.20 9.74x
-```
-
-For other tables and "CLMUL" capable machines the performance is the same as the standard library.
-
-Here are some detailed benchmarks, comparing to go 1.5 standard library with and without assembler enabled.
-
-```
-Std: Standard Go 1.5 library
-Crc: Indicates IEEE type CRC.
-40B: Size of each slice encoded.
-NoAsm: Assembler was disabled (ie. not an AMD64 or SSE 4.2+ capable machine).
-Castagnoli: Castagnoli CRC type.
-
-BenchmarkStdCrc40B-4 10000000 158 ns/op 252.88 MB/s
-BenchmarkCrc40BNoAsm-4 20000000 105 ns/op 377.38 MB/s (slice8)
-BenchmarkCrc40B-4 20000000 105 ns/op 378.77 MB/s (slice8)
-
-BenchmarkStdCrc1KB-4 500000 3604 ns/op 284.10 MB/s
-BenchmarkCrc1KBNoAsm-4 1000000 1463 ns/op 699.79 MB/s (slice8)
-BenchmarkCrc1KB-4 3000000 396 ns/op 2583.69 MB/s (asm)
-
-BenchmarkStdCrc8KB-4 200000 11417 ns/op 717.48 MB/s (slice8)
-BenchmarkCrc8KBNoAsm-4 200000 11317 ns/op 723.85 MB/s (slice8)
-BenchmarkCrc8KB-4 500000 2919 ns/op 2805.73 MB/s (asm)
-
-BenchmarkStdCrc32KB-4 30000 45749 ns/op 716.24 MB/s (slice8)
-BenchmarkCrc32KBNoAsm-4 30000 45109 ns/op 726.42 MB/s (slice8)
-BenchmarkCrc32KB-4 100000 11497 ns/op 2850.09 MB/s (asm)
-
-BenchmarkStdNoAsmCastagnol40B-4 10000000 161 ns/op 246.94 MB/s
-BenchmarkStdCastagnoli40B-4 50000000 28.4 ns/op 1410.69 MB/s (asm)
-BenchmarkCastagnoli40BNoAsm-4 20000000 100 ns/op 398.01 MB/s (slice8)
-BenchmarkCastagnoli40B-4 50000000 28.2 ns/op 1419.54 MB/s (asm)
-
-BenchmarkStdNoAsmCastagnoli1KB-4 500000 3622 ns/op 282.67 MB/s
-BenchmarkStdCastagnoli1KB-4 10000000 144 ns/op 7099.78 MB/s (asm)
-BenchmarkCastagnoli1KBNoAsm-4 1000000 1475 ns/op 694.14 MB/s (slice8)
-BenchmarkCastagnoli1KB-4 10000000 146 ns/op 6993.35 MB/s (asm)
-
-BenchmarkStdNoAsmCastagnoli8KB-4 50000 28781 ns/op 284.63 MB/s
-BenchmarkStdCastagnoli8KB-4 1000000 1029 ns/op 7957.89 MB/s (asm)
-BenchmarkCastagnoli8KBNoAsm-4 200000 11410 ns/op 717.94 MB/s (slice8)
-BenchmarkCastagnoli8KB-4 1000000 1000 ns/op 8188.71 MB/s (asm)
-
-BenchmarkStdNoAsmCastagnoli32KB-4 10000 115426 ns/op 283.89 MB/s
-BenchmarkStdCastagnoli32KB-4 300000 4065 ns/op 8059.13 MB/s (asm)
-BenchmarkCastagnoli32KBNoAsm-4 30000 45171 ns/op 725.41 MB/s (slice8)
-BenchmarkCastagnoli32KB-4 500000 4077 ns/op 8035.89 MB/s (asm)
-```
-
-The IEEE assembler optimizations has been submitted and will be part of the Go 1.6 standard library.
-
-However, the improved use of slice-by-8 has not, but will probably be submitted for Go 1.7.
-
-# license
-
-Standard Go license. Changes are Copyright (c) 2015 Klaus Post under same conditions.
diff --git a/cmd/gost/vendor/github.com/klauspost/crc32/crc32.go b/cmd/gost/vendor/github.com/klauspost/crc32/crc32.go
deleted file mode 100644
index 8aa91b1..0000000
--- a/cmd/gost/vendor/github.com/klauspost/crc32/crc32.go
+++ /dev/null
@@ -1,207 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package crc32 implements the 32-bit cyclic redundancy check, or CRC-32,
-// checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for
-// information.
-//
-// Polynomials are represented in LSB-first form also known as reversed representation.
-//
-// See http://en.wikipedia.org/wiki/Mathematics_of_cyclic_redundancy_checks#Reversed_representations_and_reciprocal_polynomials
-// for information.
-package crc32
-
-import (
- "hash"
- "sync"
-)
-
-// The size of a CRC-32 checksum in bytes.
-const Size = 4
-
-// Predefined polynomials.
-const (
- // IEEE is by far and away the most common CRC-32 polynomial.
- // Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, ...
- IEEE = 0xedb88320
-
- // Castagnoli's polynomial, used in iSCSI.
- // Has better error detection characteristics than IEEE.
- // http://dx.doi.org/10.1109/26.231911
- Castagnoli = 0x82f63b78
-
- // Koopman's polynomial.
- // Also has better error detection characteristics than IEEE.
- // http://dx.doi.org/10.1109/DSN.2002.1028931
- Koopman = 0xeb31d82e
-)
-
-// Table is a 256-word table representing the polynomial for efficient processing.
-type Table [256]uint32
-
-// This file makes use of functions implemented in architecture-specific files.
-// The interface that they implement is as follows:
-//
-// // archAvailableIEEE reports whether an architecture-specific CRC32-IEEE
-// // algorithm is available.
-// archAvailableIEEE() bool
-//
-// // archInitIEEE initializes the architecture-specific CRC3-IEEE algorithm.
-// // It can only be called if archAvailableIEEE() returns true.
-// archInitIEEE()
-//
-// // archUpdateIEEE updates the given CRC32-IEEE. It can only be called if
-// // archInitIEEE() was previously called.
-// archUpdateIEEE(crc uint32, p []byte) uint32
-//
-// // archAvailableCastagnoli reports whether an architecture-specific
-// // CRC32-C algorithm is available.
-// archAvailableCastagnoli() bool
-//
-// // archInitCastagnoli initializes the architecture-specific CRC32-C
-// // algorithm. It can only be called if archAvailableCastagnoli() returns
-// // true.
-// archInitCastagnoli()
-//
-// // archUpdateCastagnoli updates the given CRC32-C. It can only be called
-// // if archInitCastagnoli() was previously called.
-// archUpdateCastagnoli(crc uint32, p []byte) uint32
-
-// castagnoliTable points to a lazily initialized Table for the Castagnoli
-// polynomial. MakeTable will always return this value when asked to make a
-// Castagnoli table so we can compare against it to find when the caller is
-// using this polynomial.
-var castagnoliTable *Table
-var castagnoliTable8 *slicing8Table
-var castagnoliArchImpl bool
-var updateCastagnoli func(crc uint32, p []byte) uint32
-var castagnoliOnce sync.Once
-
-func castagnoliInit() {
- castagnoliTable = simpleMakeTable(Castagnoli)
- castagnoliArchImpl = archAvailableCastagnoli()
-
- if castagnoliArchImpl {
- archInitCastagnoli()
- updateCastagnoli = archUpdateCastagnoli
- } else {
- // Initialize the slicing-by-8 table.
- castagnoliTable8 = slicingMakeTable(Castagnoli)
- updateCastagnoli = func(crc uint32, p []byte) uint32 {
- return slicingUpdate(crc, castagnoliTable8, p)
- }
- }
-}
-
-// IEEETable is the table for the IEEE polynomial.
-var IEEETable = simpleMakeTable(IEEE)
-
-// ieeeTable8 is the slicing8Table for IEEE
-var ieeeTable8 *slicing8Table
-var ieeeArchImpl bool
-var updateIEEE func(crc uint32, p []byte) uint32
-var ieeeOnce sync.Once
-
-func ieeeInit() {
- ieeeArchImpl = archAvailableIEEE()
-
- if ieeeArchImpl {
- archInitIEEE()
- updateIEEE = archUpdateIEEE
- } else {
- // Initialize the slicing-by-8 table.
- ieeeTable8 = slicingMakeTable(IEEE)
- updateIEEE = func(crc uint32, p []byte) uint32 {
- return slicingUpdate(crc, ieeeTable8, p)
- }
- }
-}
-
-// MakeTable returns a Table constructed from the specified polynomial.
-// The contents of this Table must not be modified.
-func MakeTable(poly uint32) *Table {
- switch poly {
- case IEEE:
- ieeeOnce.Do(ieeeInit)
- return IEEETable
- case Castagnoli:
- castagnoliOnce.Do(castagnoliInit)
- return castagnoliTable
- }
- return simpleMakeTable(poly)
-}
-
-// digest represents the partial evaluation of a checksum.
-type digest struct {
- crc uint32
- tab *Table
-}
-
-// New creates a new hash.Hash32 computing the CRC-32 checksum
-// using the polynomial represented by the Table.
-// Its Sum method will lay the value out in big-endian byte order.
-func New(tab *Table) hash.Hash32 {
- if tab == IEEETable {
- ieeeOnce.Do(ieeeInit)
- }
- return &digest{0, tab}
-}
-
-// NewIEEE creates a new hash.Hash32 computing the CRC-32 checksum
-// using the IEEE polynomial.
-// Its Sum method will lay the value out in big-endian byte order.
-func NewIEEE() hash.Hash32 { return New(IEEETable) }
-
-func (d *digest) Size() int { return Size }
-
-func (d *digest) BlockSize() int { return 1 }
-
-func (d *digest) Reset() { d.crc = 0 }
-
-// Update returns the result of adding the bytes in p to the crc.
-func Update(crc uint32, tab *Table, p []byte) uint32 {
- switch tab {
- case castagnoliTable:
- return updateCastagnoli(crc, p)
- case IEEETable:
- // Unfortunately, because IEEETable is exported, IEEE may be used without a
- // call to MakeTable. We have to make sure it gets initialized in that case.
- ieeeOnce.Do(ieeeInit)
- return updateIEEE(crc, p)
- default:
- return simpleUpdate(crc, tab, p)
- }
-}
-
-func (d *digest) Write(p []byte) (n int, err error) {
- switch d.tab {
- case castagnoliTable:
- d.crc = updateCastagnoli(d.crc, p)
- case IEEETable:
- // We only create digest objects through New() which takes care of
- // initialization in this case.
- d.crc = updateIEEE(d.crc, p)
- default:
- d.crc = simpleUpdate(d.crc, d.tab, p)
- }
- return len(p), nil
-}
-
-func (d *digest) Sum32() uint32 { return d.crc }
-
-func (d *digest) Sum(in []byte) []byte {
- s := d.Sum32()
- return append(in, byte(s>>24), byte(s>>16), byte(s>>8), byte(s))
-}
-
-// Checksum returns the CRC-32 checksum of data
-// using the polynomial represented by the Table.
-func Checksum(data []byte, tab *Table) uint32 { return Update(0, tab, data) }
-
-// ChecksumIEEE returns the CRC-32 checksum of data
-// using the IEEE polynomial.
-func ChecksumIEEE(data []byte) uint32 {
- ieeeOnce.Do(ieeeInit)
- return updateIEEE(0, data)
-}
diff --git a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_amd64.go b/cmd/gost/vendor/github.com/klauspost/crc32/crc32_amd64.go
deleted file mode 100644
index af2a0b8..0000000
--- a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_amd64.go
+++ /dev/null
@@ -1,230 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !appengine,!gccgo
-
-// AMD64-specific hardware-assisted CRC32 algorithms. See crc32.go for a
-// description of the interface that each architecture-specific file
-// implements.
-
-package crc32
-
-import "unsafe"
-
-// This file contains the code to call the SSE 4.2 version of the Castagnoli
-// and IEEE CRC.
-
-// haveSSE41/haveSSE42/haveCLMUL are defined in crc_amd64.s and use
-// CPUID to test for SSE 4.1, 4.2 and CLMUL support.
-func haveSSE41() bool
-func haveSSE42() bool
-func haveCLMUL() bool
-
-// castagnoliSSE42 is defined in crc32_amd64.s and uses the SSE4.2 CRC32
-// instruction.
-//go:noescape
-func castagnoliSSE42(crc uint32, p []byte) uint32
-
-// castagnoliSSE42Triple is defined in crc32_amd64.s and uses the SSE4.2 CRC32
-// instruction.
-//go:noescape
-func castagnoliSSE42Triple(
- crcA, crcB, crcC uint32,
- a, b, c []byte,
- rounds uint32,
-) (retA uint32, retB uint32, retC uint32)
-
-// ieeeCLMUL is defined in crc_amd64.s and uses the PCLMULQDQ
-// instruction as well as SSE 4.1.
-//go:noescape
-func ieeeCLMUL(crc uint32, p []byte) uint32
-
-var sse42 = haveSSE42()
-var useFastIEEE = haveCLMUL() && haveSSE41()
-
-const castagnoliK1 = 168
-const castagnoliK2 = 1344
-
-type sse42Table [4]Table
-
-var castagnoliSSE42TableK1 *sse42Table
-var castagnoliSSE42TableK2 *sse42Table
-
-func archAvailableCastagnoli() bool {
- return sse42
-}
-
-func archInitCastagnoli() {
- if !sse42 {
- panic("arch-specific Castagnoli not available")
- }
- castagnoliSSE42TableK1 = new(sse42Table)
- castagnoliSSE42TableK2 = new(sse42Table)
- // See description in updateCastagnoli.
- // t[0][i] = CRC(i000, O)
- // t[1][i] = CRC(0i00, O)
- // t[2][i] = CRC(00i0, O)
- // t[3][i] = CRC(000i, O)
- // where O is a sequence of K zeros.
- var tmp [castagnoliK2]byte
- for b := 0; b < 4; b++ {
- for i := 0; i < 256; i++ {
- val := uint32(i) << uint32(b*8)
- castagnoliSSE42TableK1[b][i] = castagnoliSSE42(val, tmp[:castagnoliK1])
- castagnoliSSE42TableK2[b][i] = castagnoliSSE42(val, tmp[:])
- }
- }
-}
-
-// castagnoliShift computes the CRC32-C of K1 or K2 zeroes (depending on the
-// table given) with the given initial crc value. This corresponds to
-// CRC(crc, O) in the description in updateCastagnoli.
-func castagnoliShift(table *sse42Table, crc uint32) uint32 {
- return table[3][crc>>24] ^
- table[2][(crc>>16)&0xFF] ^
- table[1][(crc>>8)&0xFF] ^
- table[0][crc&0xFF]
-}
-
-func archUpdateCastagnoli(crc uint32, p []byte) uint32 {
- if !sse42 {
- panic("not available")
- }
-
- // This method is inspired from the algorithm in Intel's white paper:
- // "Fast CRC Computation for iSCSI Polynomial Using CRC32 Instruction"
- // The same strategy of splitting the buffer in three is used but the
- // combining calculation is different; the complete derivation is explained
- // below.
- //
- // -- The basic idea --
- //
- // The CRC32 instruction (available in SSE4.2) can process 8 bytes at a
- // time. In recent Intel architectures the instruction takes 3 cycles;
- // however the processor can pipeline up to three instructions if they
- // don't depend on each other.
- //
- // Roughly this means that we can process three buffers in about the same
- // time we can process one buffer.
- //
- // The idea is then to split the buffer in three, CRC the three pieces
- // separately and then combine the results.
- //
- // Combining the results requires precomputed tables, so we must choose a
- // fixed buffer length to optimize. The longer the length, the faster; but
- // only buffers longer than this length will use the optimization. We choose
- // two cutoffs and compute tables for both:
- // - one around 512: 168*3=504
- // - one around 4KB: 1344*3=4032
- //
- // -- The nitty gritty --
- //
- // Let CRC(I, X) be the non-inverted CRC32-C of the sequence X (with
- // initial non-inverted CRC I). This function has the following properties:
- // (a) CRC(I, AB) = CRC(CRC(I, A), B)
- // (b) CRC(I, A xor B) = CRC(I, A) xor CRC(0, B)
- //
- // Say we want to compute CRC(I, ABC) where A, B, C are three sequences of
- // K bytes each, where K is a fixed constant. Let O be the sequence of K zero
- // bytes.
- //
- // CRC(I, ABC) = CRC(I, ABO xor C)
- // = CRC(I, ABO) xor CRC(0, C)
- // = CRC(CRC(I, AB), O) xor CRC(0, C)
- // = CRC(CRC(I, AO xor B), O) xor CRC(0, C)
- // = CRC(CRC(I, AO) xor CRC(0, B), O) xor CRC(0, C)
- // = CRC(CRC(CRC(I, A), O) xor CRC(0, B), O) xor CRC(0, C)
- //
- // The castagnoliSSE42Triple function can compute CRC(I, A), CRC(0, B),
- // and CRC(0, C) efficiently. We just need to find a way to quickly compute
- // CRC(uvwx, O) given a 4-byte initial value uvwx. We can precompute these
- // values; since we can't have a 32-bit table, we break it up into four
- // 8-bit tables:
- //
- // CRC(uvwx, O) = CRC(u000, O) xor
- // CRC(0v00, O) xor
- // CRC(00w0, O) xor
- // CRC(000x, O)
- //
- // We can compute tables corresponding to the four terms for all 8-bit
- // values.
-
- crc = ^crc
-
- // If a buffer is long enough to use the optimization, process the first few
- // bytes to align the buffer to an 8 byte boundary (if necessary).
- if len(p) >= castagnoliK1*3 {
- delta := int(uintptr(unsafe.Pointer(&p[0])) & 7)
- if delta != 0 {
- delta = 8 - delta
- crc = castagnoliSSE42(crc, p[:delta])
- p = p[delta:]
- }
- }
-
- // Process 3*K2 at a time.
- for len(p) >= castagnoliK2*3 {
- // Compute CRC(I, A), CRC(0, B), and CRC(0, C).
- crcA, crcB, crcC := castagnoliSSE42Triple(
- crc, 0, 0,
- p, p[castagnoliK2:], p[castagnoliK2*2:],
- castagnoliK2/24)
-
- // CRC(I, AB) = CRC(CRC(I, A), O) xor CRC(0, B)
- crcAB := castagnoliShift(castagnoliSSE42TableK2, crcA) ^ crcB
- // CRC(I, ABC) = CRC(CRC(I, AB), O) xor CRC(0, C)
- crc = castagnoliShift(castagnoliSSE42TableK2, crcAB) ^ crcC
- p = p[castagnoliK2*3:]
- }
-
- // Process 3*K1 at a time.
- for len(p) >= castagnoliK1*3 {
- // Compute CRC(I, A), CRC(0, B), and CRC(0, C).
- crcA, crcB, crcC := castagnoliSSE42Triple(
- crc, 0, 0,
- p, p[castagnoliK1:], p[castagnoliK1*2:],
- castagnoliK1/24)
-
- // CRC(I, AB) = CRC(CRC(I, A), O) xor CRC(0, B)
- crcAB := castagnoliShift(castagnoliSSE42TableK1, crcA) ^ crcB
- // CRC(I, ABC) = CRC(CRC(I, AB), O) xor CRC(0, C)
- crc = castagnoliShift(castagnoliSSE42TableK1, crcAB) ^ crcC
- p = p[castagnoliK1*3:]
- }
-
- // Use the simple implementation for what's left.
- crc = castagnoliSSE42(crc, p)
- return ^crc
-}
-
-func archAvailableIEEE() bool {
- return useFastIEEE
-}
-
-var archIeeeTable8 *slicing8Table
-
-func archInitIEEE() {
- if !useFastIEEE {
- panic("not available")
- }
- // We still use slicing-by-8 for small buffers.
- archIeeeTable8 = slicingMakeTable(IEEE)
-}
-
-func archUpdateIEEE(crc uint32, p []byte) uint32 {
- if !useFastIEEE {
- panic("not available")
- }
-
- if len(p) >= 64 {
- left := len(p) & 15
- do := len(p) - left
- crc = ^ieeeCLMUL(^crc, p[:do])
- p = p[do:]
- }
- if len(p) == 0 {
- return crc
- }
- return slicingUpdate(crc, archIeeeTable8, p)
-}
diff --git a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_amd64.s b/cmd/gost/vendor/github.com/klauspost/crc32/crc32_amd64.s
deleted file mode 100644
index e8a7941..0000000
--- a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_amd64.s
+++ /dev/null
@@ -1,319 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build gc
-
-#define NOSPLIT 4
-#define RODATA 8
-
-// castagnoliSSE42 updates the (non-inverted) crc with the given buffer.
-//
-// func castagnoliSSE42(crc uint32, p []byte) uint32
-TEXT ·castagnoliSSE42(SB), NOSPLIT, $0
- MOVL crc+0(FP), AX // CRC value
- MOVQ p+8(FP), SI // data pointer
- MOVQ p_len+16(FP), CX // len(p)
-
- // If there are fewer than 8 bytes to process, skip alignment.
- CMPQ CX, $8
- JL less_than_8
-
- MOVQ SI, BX
- ANDQ $7, BX
- JZ aligned
-
- // Process the first few bytes to 8-byte align the input.
-
- // BX = 8 - BX. We need to process this many bytes to align.
- SUBQ $1, BX
- XORQ $7, BX
-
- BTQ $0, BX
- JNC align_2
-
- CRC32B (SI), AX
- DECQ CX
- INCQ SI
-
-align_2:
- BTQ $1, BX
- JNC align_4
-
- // CRC32W (SI), AX
- BYTE $0x66; BYTE $0xf2; BYTE $0x0f; BYTE $0x38; BYTE $0xf1; BYTE $0x06
-
- SUBQ $2, CX
- ADDQ $2, SI
-
-align_4:
- BTQ $2, BX
- JNC aligned
-
- // CRC32L (SI), AX
- BYTE $0xf2; BYTE $0x0f; BYTE $0x38; BYTE $0xf1; BYTE $0x06
-
- SUBQ $4, CX
- ADDQ $4, SI
-
-aligned:
- // The input is now 8-byte aligned and we can process 8-byte chunks.
- CMPQ CX, $8
- JL less_than_8
-
- CRC32Q (SI), AX
- ADDQ $8, SI
- SUBQ $8, CX
- JMP aligned
-
-less_than_8:
- // We may have some bytes left over; process 4 bytes, then 2, then 1.
- BTQ $2, CX
- JNC less_than_4
-
- // CRC32L (SI), AX
- BYTE $0xf2; BYTE $0x0f; BYTE $0x38; BYTE $0xf1; BYTE $0x06
- ADDQ $4, SI
-
-less_than_4:
- BTQ $1, CX
- JNC less_than_2
-
- // CRC32W (SI), AX
- BYTE $0x66; BYTE $0xf2; BYTE $0x0f; BYTE $0x38; BYTE $0xf1; BYTE $0x06
- ADDQ $2, SI
-
-less_than_2:
- BTQ $0, CX
- JNC done
-
- CRC32B (SI), AX
-
-done:
- MOVL AX, ret+32(FP)
- RET
-
-// castagnoliSSE42Triple updates three (non-inverted) crcs with (24*rounds)
-// bytes from each buffer.
-//
-// func castagnoliSSE42Triple(
-// crc1, crc2, crc3 uint32,
-// a, b, c []byte,
-// rounds uint32,
-// ) (retA uint32, retB uint32, retC uint32)
-TEXT ·castagnoliSSE42Triple(SB), NOSPLIT, $0
- MOVL crcA+0(FP), AX
- MOVL crcB+4(FP), CX
- MOVL crcC+8(FP), DX
-
- MOVQ a+16(FP), R8 // data pointer
- MOVQ b+40(FP), R9 // data pointer
- MOVQ c+64(FP), R10 // data pointer
-
- MOVL rounds+88(FP), R11
-
-loop:
- CRC32Q (R8), AX
- CRC32Q (R9), CX
- CRC32Q (R10), DX
-
- CRC32Q 8(R8), AX
- CRC32Q 8(R9), CX
- CRC32Q 8(R10), DX
-
- CRC32Q 16(R8), AX
- CRC32Q 16(R9), CX
- CRC32Q 16(R10), DX
-
- ADDQ $24, R8
- ADDQ $24, R9
- ADDQ $24, R10
-
- DECQ R11
- JNZ loop
-
- MOVL AX, retA+96(FP)
- MOVL CX, retB+100(FP)
- MOVL DX, retC+104(FP)
- RET
-
-// func haveSSE42() bool
-TEXT ·haveSSE42(SB), NOSPLIT, $0
- XORQ AX, AX
- INCL AX
- CPUID
- SHRQ $20, CX
- ANDQ $1, CX
- MOVB CX, ret+0(FP)
- RET
-
-// func haveCLMUL() bool
-TEXT ·haveCLMUL(SB), NOSPLIT, $0
- XORQ AX, AX
- INCL AX
- CPUID
- SHRQ $1, CX
- ANDQ $1, CX
- MOVB CX, ret+0(FP)
- RET
-
-// func haveSSE41() bool
-TEXT ·haveSSE41(SB), NOSPLIT, $0
- XORQ AX, AX
- INCL AX
- CPUID
- SHRQ $19, CX
- ANDQ $1, CX
- MOVB CX, ret+0(FP)
- RET
-
-// CRC32 polynomial data
-//
-// These constants are lifted from the
-// Linux kernel, since they avoid the costly
-// PSHUFB 16 byte reversal proposed in the
-// original Intel paper.
-DATA r2r1kp<>+0(SB)/8, $0x154442bd4
-DATA r2r1kp<>+8(SB)/8, $0x1c6e41596
-DATA r4r3kp<>+0(SB)/8, $0x1751997d0
-DATA r4r3kp<>+8(SB)/8, $0x0ccaa009e
-DATA rupolykp<>+0(SB)/8, $0x1db710641
-DATA rupolykp<>+8(SB)/8, $0x1f7011641
-DATA r5kp<>+0(SB)/8, $0x163cd6124
-
-GLOBL r2r1kp<>(SB), RODATA, $16
-GLOBL r4r3kp<>(SB), RODATA, $16
-GLOBL rupolykp<>(SB), RODATA, $16
-GLOBL r5kp<>(SB), RODATA, $8
-
-// Based on http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
-// len(p) must be at least 64, and must be a multiple of 16.
-
-// func ieeeCLMUL(crc uint32, p []byte) uint32
-TEXT ·ieeeCLMUL(SB), NOSPLIT, $0
- MOVL crc+0(FP), X0 // Initial CRC value
- MOVQ p+8(FP), SI // data pointer
- MOVQ p_len+16(FP), CX // len(p)
-
- MOVOU (SI), X1
- MOVOU 16(SI), X2
- MOVOU 32(SI), X3
- MOVOU 48(SI), X4
- PXOR X0, X1
- ADDQ $64, SI // buf+=64
- SUBQ $64, CX // len-=64
- CMPQ CX, $64 // Less than 64 bytes left
- JB remain64
-
- MOVOA r2r1kp<>+0(SB), X0
-
-loopback64:
- MOVOA X1, X5
- MOVOA X2, X6
- MOVOA X3, X7
- MOVOA X4, X8
-
- PCLMULQDQ $0, X0, X1
- PCLMULQDQ $0, X0, X2
- PCLMULQDQ $0, X0, X3
- PCLMULQDQ $0, X0, X4
-
- // Load next early
- MOVOU (SI), X11
- MOVOU 16(SI), X12
- MOVOU 32(SI), X13
- MOVOU 48(SI), X14
-
- PCLMULQDQ $0x11, X0, X5
- PCLMULQDQ $0x11, X0, X6
- PCLMULQDQ $0x11, X0, X7
- PCLMULQDQ $0x11, X0, X8
-
- PXOR X5, X1
- PXOR X6, X2
- PXOR X7, X3
- PXOR X8, X4
-
- PXOR X11, X1
- PXOR X12, X2
- PXOR X13, X3
- PXOR X14, X4
-
- ADDQ $0x40, DI
- ADDQ $64, SI // buf+=64
- SUBQ $64, CX // len-=64
- CMPQ CX, $64 // Less than 64 bytes left?
- JGE loopback64
-
- // Fold result into a single register (X1)
-remain64:
- MOVOA r4r3kp<>+0(SB), X0
-
- MOVOA X1, X5
- PCLMULQDQ $0, X0, X1
- PCLMULQDQ $0x11, X0, X5
- PXOR X5, X1
- PXOR X2, X1
-
- MOVOA X1, X5
- PCLMULQDQ $0, X0, X1
- PCLMULQDQ $0x11, X0, X5
- PXOR X5, X1
- PXOR X3, X1
-
- MOVOA X1, X5
- PCLMULQDQ $0, X0, X1
- PCLMULQDQ $0x11, X0, X5
- PXOR X5, X1
- PXOR X4, X1
-
- // If there is less than 16 bytes left we are done
- CMPQ CX, $16
- JB finish
-
- // Encode 16 bytes
-remain16:
- MOVOU (SI), X10
- MOVOA X1, X5
- PCLMULQDQ $0, X0, X1
- PCLMULQDQ $0x11, X0, X5
- PXOR X5, X1
- PXOR X10, X1
- SUBQ $16, CX
- ADDQ $16, SI
- CMPQ CX, $16
- JGE remain16
-
-finish:
- // Fold final result into 32 bits and return it
- PCMPEQB X3, X3
- PCLMULQDQ $1, X1, X0
- PSRLDQ $8, X1
- PXOR X0, X1
-
- MOVOA X1, X2
- MOVQ r5kp<>+0(SB), X0
-
- // Creates 32 bit mask. Note that we don't care about upper half.
- PSRLQ $32, X3
-
- PSRLDQ $4, X2
- PAND X3, X1
- PCLMULQDQ $0, X0, X1
- PXOR X2, X1
-
- MOVOA rupolykp<>+0(SB), X0
-
- MOVOA X1, X2
- PAND X3, X1
- PCLMULQDQ $0x10, X0, X1
- PAND X3, X1
- PCLMULQDQ $0, X0, X1
- PXOR X2, X1
-
- // PEXTRD $1, X1, AX (SSE 4.1)
- BYTE $0x66; BYTE $0x0f; BYTE $0x3a
- BYTE $0x16; BYTE $0xc8; BYTE $0x01
- MOVL AX, ret+32(FP)
-
- RET
diff --git a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_amd64p32.go b/cmd/gost/vendor/github.com/klauspost/crc32/crc32_amd64p32.go
deleted file mode 100644
index 3222b06..0000000
--- a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_amd64p32.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !appengine,!gccgo
-
-package crc32
-
-// This file contains the code to call the SSE 4.2 version of the Castagnoli
-// CRC.
-
-// haveSSE42 is defined in crc32_amd64p32.s and uses CPUID to test for SSE 4.2
-// support.
-func haveSSE42() bool
-
-// castagnoliSSE42 is defined in crc32_amd64p32.s and uses the SSE4.2 CRC32
-// instruction.
-//go:noescape
-func castagnoliSSE42(crc uint32, p []byte) uint32
-
-var sse42 = haveSSE42()
-
-func archAvailableCastagnoli() bool {
- return sse42
-}
-
-func archInitCastagnoli() {
- if !sse42 {
- panic("not available")
- }
- // No initialization necessary.
-}
-
-func archUpdateCastagnoli(crc uint32, p []byte) uint32 {
- if !sse42 {
- panic("not available")
- }
- return castagnoliSSE42(crc, p)
-}
-
-func archAvailableIEEE() bool { return false }
-func archInitIEEE() { panic("not available") }
-func archUpdateIEEE(crc uint32, p []byte) uint32 { panic("not available") }
diff --git a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_amd64p32.s b/cmd/gost/vendor/github.com/klauspost/crc32/crc32_amd64p32.s
deleted file mode 100644
index a578d68..0000000
--- a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_amd64p32.s
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build gc
-
-#define NOSPLIT 4
-#define RODATA 8
-
-// func castagnoliSSE42(crc uint32, p []byte) uint32
-TEXT ·castagnoliSSE42(SB), NOSPLIT, $0
- MOVL crc+0(FP), AX // CRC value
- MOVL p+4(FP), SI // data pointer
- MOVL p_len+8(FP), CX // len(p)
-
- NOTL AX
-
- // If there's less than 8 bytes to process, we do it byte-by-byte.
- CMPQ CX, $8
- JL cleanup
-
- // Process individual bytes until the input is 8-byte aligned.
-startup:
- MOVQ SI, BX
- ANDQ $7, BX
- JZ aligned
-
- CRC32B (SI), AX
- DECQ CX
- INCQ SI
- JMP startup
-
-aligned:
- // The input is now 8-byte aligned and we can process 8-byte chunks.
- CMPQ CX, $8
- JL cleanup
-
- CRC32Q (SI), AX
- ADDQ $8, SI
- SUBQ $8, CX
- JMP aligned
-
-cleanup:
- // We may have some bytes left over that we process one at a time.
- CMPQ CX, $0
- JE done
-
- CRC32B (SI), AX
- INCQ SI
- DECQ CX
- JMP cleanup
-
-done:
- NOTL AX
- MOVL AX, ret+16(FP)
- RET
-
-// func haveSSE42() bool
-TEXT ·haveSSE42(SB), NOSPLIT, $0
- XORQ AX, AX
- INCL AX
- CPUID
- SHRQ $20, CX
- ANDQ $1, CX
- MOVB CX, ret+0(FP)
- RET
-
diff --git a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_generic.go b/cmd/gost/vendor/github.com/klauspost/crc32/crc32_generic.go
deleted file mode 100644
index abacbb6..0000000
--- a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_generic.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This file contains CRC32 algorithms that are not specific to any architecture
-// and don't use hardware acceleration.
-//
-// The simple (and slow) CRC32 implementation only uses a 256*4 bytes table.
-//
-// The slicing-by-8 algorithm is a faster implementation that uses a bigger
-// table (8*256*4 bytes).
-
-package crc32
-
-// simpleMakeTable allocates and constructs a Table for the specified
-// polynomial. The table is suitable for use with the simple algorithm
-// (simpleUpdate).
-func simpleMakeTable(poly uint32) *Table {
- t := new(Table)
- simplePopulateTable(poly, t)
- return t
-}
-
-// simplePopulateTable constructs a Table for the specified polynomial, suitable
-// for use with simpleUpdate.
-func simplePopulateTable(poly uint32, t *Table) {
- for i := 0; i < 256; i++ {
- crc := uint32(i)
- for j := 0; j < 8; j++ {
- if crc&1 == 1 {
- crc = (crc >> 1) ^ poly
- } else {
- crc >>= 1
- }
- }
- t[i] = crc
- }
-}
-
-// simpleUpdate uses the simple algorithm to update the CRC, given a table that
-// was previously computed using simpleMakeTable.
-func simpleUpdate(crc uint32, tab *Table, p []byte) uint32 {
- crc = ^crc
- for _, v := range p {
- crc = tab[byte(crc)^v] ^ (crc >> 8)
- }
- return ^crc
-}
-
-// Use slicing-by-8 when payload >= this value.
-const slicing8Cutoff = 16
-
-// slicing8Table is array of 8 Tables, used by the slicing-by-8 algorithm.
-type slicing8Table [8]Table
-
-// slicingMakeTable constructs a slicing8Table for the specified polynomial. The
-// table is suitable for use with the slicing-by-8 algorithm (slicingUpdate).
-func slicingMakeTable(poly uint32) *slicing8Table {
- t := new(slicing8Table)
- simplePopulateTable(poly, &t[0])
- for i := 0; i < 256; i++ {
- crc := t[0][i]
- for j := 1; j < 8; j++ {
- crc = t[0][crc&0xFF] ^ (crc >> 8)
- t[j][i] = crc
- }
- }
- return t
-}
-
-// slicingUpdate uses the slicing-by-8 algorithm to update the CRC, given a
-// table that was previously computed using slicingMakeTable.
-func slicingUpdate(crc uint32, tab *slicing8Table, p []byte) uint32 {
- if len(p) >= slicing8Cutoff {
- crc = ^crc
- for len(p) > 8 {
- crc ^= uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
- crc = tab[0][p[7]] ^ tab[1][p[6]] ^ tab[2][p[5]] ^ tab[3][p[4]] ^
- tab[4][crc>>24] ^ tab[5][(crc>>16)&0xFF] ^
- tab[6][(crc>>8)&0xFF] ^ tab[7][crc&0xFF]
- p = p[8:]
- }
- crc = ^crc
- }
- if len(p) == 0 {
- return crc
- }
- return simpleUpdate(crc, &tab[0], p)
-}
diff --git a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_otherarch.go b/cmd/gost/vendor/github.com/klauspost/crc32/crc32_otherarch.go
deleted file mode 100644
index cc96076..0000000
--- a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_otherarch.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !amd64,!amd64p32,!s390x
-
-package crc32
-
-func archAvailableIEEE() bool { return false }
-func archInitIEEE() { panic("not available") }
-func archUpdateIEEE(crc uint32, p []byte) uint32 { panic("not available") }
-
-func archAvailableCastagnoli() bool { return false }
-func archInitCastagnoli() { panic("not available") }
-func archUpdateCastagnoli(crc uint32, p []byte) uint32 { panic("not available") }
diff --git a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_s390x.go b/cmd/gost/vendor/github.com/klauspost/crc32/crc32_s390x.go
deleted file mode 100644
index ce96f03..0000000
--- a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_s390x.go
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build s390x
-
-package crc32
-
-const (
- vxMinLen = 64
- vxAlignMask = 15 // align to 16 bytes
-)
-
-// hasVectorFacility reports whether the machine has the z/Architecture
-// vector facility installed and enabled.
-func hasVectorFacility() bool
-
-var hasVX = hasVectorFacility()
-
-// vectorizedCastagnoli implements CRC32 using vector instructions.
-// It is defined in crc32_s390x.s.
-//go:noescape
-func vectorizedCastagnoli(crc uint32, p []byte) uint32
-
-// vectorizedIEEE implements CRC32 using vector instructions.
-// It is defined in crc32_s390x.s.
-//go:noescape
-func vectorizedIEEE(crc uint32, p []byte) uint32
-
-func archAvailableCastagnoli() bool {
- return hasVX
-}
-
-var archCastagnoliTable8 *slicing8Table
-
-func archInitCastagnoli() {
- if !hasVX {
- panic("not available")
- }
- // We still use slicing-by-8 for small buffers.
- archCastagnoliTable8 = slicingMakeTable(Castagnoli)
-}
-
-// archUpdateCastagnoli calculates the checksum of p using
-// vectorizedCastagnoli.
-func archUpdateCastagnoli(crc uint32, p []byte) uint32 {
- if !hasVX {
- panic("not available")
- }
- // Use vectorized function if data length is above threshold.
- if len(p) >= vxMinLen {
- aligned := len(p) & ^vxAlignMask
- crc = vectorizedCastagnoli(crc, p[:aligned])
- p = p[aligned:]
- }
- if len(p) == 0 {
- return crc
- }
- return slicingUpdate(crc, archCastagnoliTable8, p)
-}
-
-func archAvailableIEEE() bool {
- return hasVX
-}
-
-var archIeeeTable8 *slicing8Table
-
-func archInitIEEE() {
- if !hasVX {
- panic("not available")
- }
- // We still use slicing-by-8 for small buffers.
- archIeeeTable8 = slicingMakeTable(IEEE)
-}
-
-// archUpdateIEEE calculates the checksum of p using vectorizedIEEE.
-func archUpdateIEEE(crc uint32, p []byte) uint32 {
- if !hasVX {
- panic("not available")
- }
- // Use vectorized function if data length is above threshold.
- if len(p) >= vxMinLen {
- aligned := len(p) & ^vxAlignMask
- crc = vectorizedIEEE(crc, p[:aligned])
- p = p[aligned:]
- }
- if len(p) == 0 {
- return crc
- }
- return slicingUpdate(crc, archIeeeTable8, p)
-}
diff --git a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_s390x.s b/cmd/gost/vendor/github.com/klauspost/crc32/crc32_s390x.s
deleted file mode 100644
index e980ca2..0000000
--- a/cmd/gost/vendor/github.com/klauspost/crc32/crc32_s390x.s
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build s390x
-
-#include "textflag.h"
-
-// Vector register range containing CRC-32 constants
-
-#define CONST_PERM_LE2BE V9
-#define CONST_R2R1 V10
-#define CONST_R4R3 V11
-#define CONST_R5 V12
-#define CONST_RU_POLY V13
-#define CONST_CRC_POLY V14
-
-// The CRC-32 constant block contains reduction constants to fold and
-// process particular chunks of the input data stream in parallel.
-//
-// Note that the constant definitions below are extended in order to compute
-// intermediate results with a single VECTOR GALOIS FIELD MULTIPLY instruction.
-// The rightmost doubleword can be 0 to prevent contribution to the result or
-// can be multiplied by 1 to perform an XOR without the need for a separate
-// VECTOR EXCLUSIVE OR instruction.
-//
-// The polynomials used are bit-reflected:
-//
-// IEEE: P'(x) = 0x0edb88320
-// Castagnoli: P'(x) = 0x082f63b78
-
-// IEEE polynomial constants
-DATA ·crcleconskp+0(SB)/8, $0x0F0E0D0C0B0A0908 // LE-to-BE mask
-DATA ·crcleconskp+8(SB)/8, $0x0706050403020100
-DATA ·crcleconskp+16(SB)/8, $0x00000001c6e41596 // R2
-DATA ·crcleconskp+24(SB)/8, $0x0000000154442bd4 // R1
-DATA ·crcleconskp+32(SB)/8, $0x00000000ccaa009e // R4
-DATA ·crcleconskp+40(SB)/8, $0x00000001751997d0 // R3
-DATA ·crcleconskp+48(SB)/8, $0x0000000000000000
-DATA ·crcleconskp+56(SB)/8, $0x0000000163cd6124 // R5
-DATA ·crcleconskp+64(SB)/8, $0x0000000000000000
-DATA ·crcleconskp+72(SB)/8, $0x00000001F7011641 // u'
-DATA ·crcleconskp+80(SB)/8, $0x0000000000000000
-DATA ·crcleconskp+88(SB)/8, $0x00000001DB710641 // P'(x) << 1
-
-GLOBL ·crcleconskp(SB), RODATA, $144
-
-// Castagonli Polynomial constants
-DATA ·crccleconskp+0(SB)/8, $0x0F0E0D0C0B0A0908 // LE-to-BE mask
-DATA ·crccleconskp+8(SB)/8, $0x0706050403020100
-DATA ·crccleconskp+16(SB)/8, $0x000000009e4addf8 // R2
-DATA ·crccleconskp+24(SB)/8, $0x00000000740eef02 // R1
-DATA ·crccleconskp+32(SB)/8, $0x000000014cd00bd6 // R4
-DATA ·crccleconskp+40(SB)/8, $0x00000000f20c0dfe // R3
-DATA ·crccleconskp+48(SB)/8, $0x0000000000000000
-DATA ·crccleconskp+56(SB)/8, $0x00000000dd45aab8 // R5
-DATA ·crccleconskp+64(SB)/8, $0x0000000000000000
-DATA ·crccleconskp+72(SB)/8, $0x00000000dea713f1 // u'
-DATA ·crccleconskp+80(SB)/8, $0x0000000000000000
-DATA ·crccleconskp+88(SB)/8, $0x0000000105ec76f0 // P'(x) << 1
-
-GLOBL ·crccleconskp(SB), RODATA, $144
-
-// func hasVectorFacility() bool
-TEXT ·hasVectorFacility(SB), NOSPLIT, $24-1
- MOVD $x-24(SP), R1
- XC $24, 0(R1), 0(R1) // clear the storage
- MOVD $2, R0 // R0 is the number of double words stored -1
- WORD $0xB2B01000 // STFLE 0(R1)
- XOR R0, R0 // reset the value of R0
- MOVBZ z-8(SP), R1
- AND $0x40, R1
- BEQ novector
-
-vectorinstalled:
- // check if the vector instruction has been enabled
- VLEIB $0, $0xF, V16
- VLGVB $0, V16, R1
- CMPBNE R1, $0xF, novector
- MOVB $1, ret+0(FP) // have vx
- RET
-
-novector:
- MOVB $0, ret+0(FP) // no vx
- RET
-
-// The CRC-32 function(s) use these calling conventions:
-//
-// Parameters:
-//
-// R2: Initial CRC value, typically ~0; and final CRC (return) value.
-// R3: Input buffer pointer, performance might be improved if the
-// buffer is on a doubleword boundary.
-// R4: Length of the buffer, must be 64 bytes or greater.
-//
-// Register usage:
-//
-// R5: CRC-32 constant pool base pointer.
-// V0: Initial CRC value and intermediate constants and results.
-// V1..V4: Data for CRC computation.
-// V5..V8: Next data chunks that are fetched from the input buffer.
-//
-// V9..V14: CRC-32 constants.
-
-// func vectorizedIEEE(crc uint32, p []byte) uint32
-TEXT ·vectorizedIEEE(SB), NOSPLIT, $0
- MOVWZ crc+0(FP), R2 // R2 stores the CRC value
- MOVD p+8(FP), R3 // data pointer
- MOVD p_len+16(FP), R4 // len(p)
-
- MOVD $·crcleconskp(SB), R5
- BR vectorizedBody<>(SB)
-
-// func vectorizedCastagnoli(crc uint32, p []byte) uint32
-TEXT ·vectorizedCastagnoli(SB), NOSPLIT, $0
- MOVWZ crc+0(FP), R2 // R2 stores the CRC value
- MOVD p+8(FP), R3 // data pointer
- MOVD p_len+16(FP), R4 // len(p)
-
- // R5: crc-32 constant pool base pointer, constant is used to reduce crc
- MOVD $·crccleconskp(SB), R5
- BR vectorizedBody<>(SB)
-
-TEXT vectorizedBody<>(SB), NOSPLIT, $0
- XOR $0xffffffff, R2 // NOTW R2
- VLM 0(R5), CONST_PERM_LE2BE, CONST_CRC_POLY
-
- // Load the initial CRC value into the rightmost word of V0
- VZERO V0
- VLVGF $3, R2, V0
-
- // Crash if the input size is less than 64-bytes.
- CMP R4, $64
- BLT crash
-
- // Load a 64-byte data chunk and XOR with CRC
- VLM 0(R3), V1, V4 // 64-bytes into V1..V4
-
- // Reflect the data if the CRC operation is in the bit-reflected domain
- VPERM V1, V1, CONST_PERM_LE2BE, V1
- VPERM V2, V2, CONST_PERM_LE2BE, V2
- VPERM V3, V3, CONST_PERM_LE2BE, V3
- VPERM V4, V4, CONST_PERM_LE2BE, V4
-
- VX V0, V1, V1 // V1 ^= CRC
- ADD $64, R3 // BUF = BUF + 64
- ADD $(-64), R4
-
- // Check remaining buffer size and jump to proper folding method
- CMP R4, $64
- BLT less_than_64bytes
-
-fold_64bytes_loop:
- // Load the next 64-byte data chunk into V5 to V8
- VLM 0(R3), V5, V8
- VPERM V5, V5, CONST_PERM_LE2BE, V5
- VPERM V6, V6, CONST_PERM_LE2BE, V6
- VPERM V7, V7, CONST_PERM_LE2BE, V7
- VPERM V8, V8, CONST_PERM_LE2BE, V8
-
- // Perform a GF(2) multiplication of the doublewords in V1 with
- // the reduction constants in V0. The intermediate result is
- // then folded (accumulated) with the next data chunk in V5 and
- // stored in V1. Repeat this step for the register contents
- // in V2, V3, and V4 respectively.
-
- VGFMAG CONST_R2R1, V1, V5, V1
- VGFMAG CONST_R2R1, V2, V6, V2
- VGFMAG CONST_R2R1, V3, V7, V3
- VGFMAG CONST_R2R1, V4, V8, V4
-
- // Adjust buffer pointer and length for next loop
- ADD $64, R3 // BUF = BUF + 64
- ADD $(-64), R4 // LEN = LEN - 64
-
- CMP R4, $64
- BGE fold_64bytes_loop
-
-less_than_64bytes:
- // Fold V1 to V4 into a single 128-bit value in V1
- VGFMAG CONST_R4R3, V1, V2, V1
- VGFMAG CONST_R4R3, V1, V3, V1
- VGFMAG CONST_R4R3, V1, V4, V1
-
- // Check whether to continue with 64-bit folding
- CMP R4, $16
- BLT final_fold
-
-fold_16bytes_loop:
- VL 0(R3), V2 // Load next data chunk
- VPERM V2, V2, CONST_PERM_LE2BE, V2
-
- VGFMAG CONST_R4R3, V1, V2, V1 // Fold next data chunk
-
- // Adjust buffer pointer and size for folding next data chunk
- ADD $16, R3
- ADD $-16, R4
-
- // Process remaining data chunks
- CMP R4, $16
- BGE fold_16bytes_loop
-
-final_fold:
- VLEIB $7, $0x40, V9
- VSRLB V9, CONST_R4R3, V0
- VLEIG $0, $1, V0
-
- VGFMG V0, V1, V1
-
- VLEIB $7, $0x20, V9 // Shift by words
- VSRLB V9, V1, V2 // Store remaining bits in V2
- VUPLLF V1, V1 // Split rightmost doubleword
- VGFMAG CONST_R5, V1, V2, V1 // V1 = (V1 * R5) XOR V2
-
- // The input values to the Barret reduction are the degree-63 polynomial
- // in V1 (R(x)), degree-32 generator polynomial, and the reduction
- // constant u. The Barret reduction result is the CRC value of R(x) mod
- // P(x).
- //
- // The Barret reduction algorithm is defined as:
- //
- // 1. T1(x) = floor( R(x) / x^32 ) GF2MUL u
- // 2. T2(x) = floor( T1(x) / x^32 ) GF2MUL P(x)
- // 3. C(x) = R(x) XOR T2(x) mod x^32
- //
- // Note: To compensate the division by x^32, use the vector unpack
- // instruction to move the leftmost word into the leftmost doubleword
- // of the vector register. The rightmost doubleword is multiplied
- // with zero to not contribute to the intermedate results.
-
- // T1(x) = floor( R(x) / x^32 ) GF2MUL u
- VUPLLF V1, V2
- VGFMG CONST_RU_POLY, V2, V2
-
- // Compute the GF(2) product of the CRC polynomial in VO with T1(x) in
- // V2 and XOR the intermediate result, T2(x), with the value in V1.
- // The final result is in the rightmost word of V2.
-
- VUPLLF V2, V2
- VGFMAG CONST_CRC_POLY, V2, V1, V2
-
-done:
- VLGVF $2, V2, R2
- XOR $0xffffffff, R2 // NOTW R2
- MOVWZ R2, ret + 32(FP)
- RET
-
-crash:
- MOVD $0, (R0) // input size is less than 64-bytes
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/packet.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/packet.go
deleted file mode 100644
index 6fe567c..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/packet.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package ackhandler
-
-import (
- "time"
-
- "github.com/lucas-clemente/quic-go/frames"
- "github.com/lucas-clemente/quic-go/protocol"
-)
-
-// A Packet is a packet
-// +gen linkedlist
-type Packet struct {
- PacketNumber protocol.PacketNumber
- Frames []frames.Frame
- Length protocol.ByteCount
-
- MissingReports uint8
-
- SendTime time.Time
-}
-
-// GetStreamFramesForRetransmission gets all the streamframes for retransmission
-func (p *Packet) GetStreamFramesForRetransmission() []*frames.StreamFrame {
- var streamFrames []*frames.StreamFrame
- for _, frame := range p.Frames {
- if streamFrame, isStreamFrame := frame.(*frames.StreamFrame); isStreamFrame {
- streamFrames = append(streamFrames, streamFrame)
- }
- }
- return streamFrames
-}
-
-// GetControlFramesForRetransmission gets all the control frames for retransmission
-func (p *Packet) GetControlFramesForRetransmission() []frames.Frame {
- var controlFrames []frames.Frame
- for _, frame := range p.Frames {
- // omit ACKs
- if _, isStreamFrame := frame.(*frames.StreamFrame); isStreamFrame {
- continue
- }
-
- _, isAck := frame.(*frames.AckFrame)
- _, isStopWaiting := frame.(*frames.StopWaitingFrame)
- if !isAck && !isStopWaiting {
- controlFrames = append(controlFrames, frame)
- }
- }
- return controlFrames
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_handler.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_handler.go
deleted file mode 100644
index dcc1b30..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_handler.go
+++ /dev/null
@@ -1,143 +0,0 @@
-package ackhandler
-
-import (
- "errors"
- "time"
-
- "github.com/lucas-clemente/quic-go/frames"
- "github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/qerr"
-)
-
-var (
- // ErrDuplicatePacket occurres when a duplicate packet is received
- ErrDuplicatePacket = errors.New("ReceivedPacketHandler: Duplicate Packet")
- // ErrMapAccess occurs when a NACK contains invalid NACK ranges
- ErrMapAccess = qerr.Error(qerr.InvalidAckData, "Packet does not exist in PacketHistory")
- // ErrPacketSmallerThanLastStopWaiting occurs when a packet arrives with a packet number smaller than the largest LeastUnacked of a StopWaitingFrame. If this error occurs, the packet should be ignored
- ErrPacketSmallerThanLastStopWaiting = errors.New("ReceivedPacketHandler: Packet number smaller than highest StopWaiting")
-)
-
-var (
- errInvalidPacketNumber = errors.New("ReceivedPacketHandler: Invalid packet number")
- errTooManyOutstandingReceivedPackets = qerr.Error(qerr.TooManyOutstandingReceivedPackets, "")
-)
-
-type receivedPacketHandler struct {
- largestInOrderObserved protocol.PacketNumber
- largestObserved protocol.PacketNumber
- ignorePacketsBelow protocol.PacketNumber
- currentAckFrame *frames.AckFrame
- stateChanged bool // has an ACK for this state already been sent? Will be set to false every time a new packet arrives, and to false every time an ACK is sent
-
- packetHistory *receivedPacketHistory
-
- receivedTimes map[protocol.PacketNumber]time.Time
- lowestInReceivedTimes protocol.PacketNumber
-}
-
-// NewReceivedPacketHandler creates a new receivedPacketHandler
-func NewReceivedPacketHandler() ReceivedPacketHandler {
- return &receivedPacketHandler{
- receivedTimes: make(map[protocol.PacketNumber]time.Time),
- packetHistory: newReceivedPacketHistory(),
- }
-}
-
-func (h *receivedPacketHandler) ReceivedPacket(packetNumber protocol.PacketNumber) error {
- if packetNumber == 0 {
- return errInvalidPacketNumber
- }
-
- // if the packet number is smaller than the largest LeastUnacked value of a StopWaiting we received, we cannot detect if this packet has a duplicate number
- // the packet has to be ignored anyway
- if packetNumber <= h.ignorePacketsBelow {
- return ErrPacketSmallerThanLastStopWaiting
- }
-
- _, ok := h.receivedTimes[packetNumber]
- if packetNumber <= h.largestInOrderObserved || ok {
- return ErrDuplicatePacket
- }
-
- h.packetHistory.ReceivedPacket(packetNumber)
-
- h.stateChanged = true
- h.currentAckFrame = nil
-
- if packetNumber > h.largestObserved {
- h.largestObserved = packetNumber
- }
-
- if packetNumber == h.largestInOrderObserved+1 {
- h.largestInOrderObserved = packetNumber
- }
-
- h.receivedTimes[packetNumber] = time.Now()
-
- if protocol.PacketNumber(len(h.receivedTimes)) > protocol.MaxTrackedReceivedPackets {
- return errTooManyOutstandingReceivedPackets
- }
-
- return nil
-}
-
-func (h *receivedPacketHandler) ReceivedStopWaiting(f *frames.StopWaitingFrame) error {
- // ignore if StopWaiting is unneeded, because we already received a StopWaiting with a higher LeastUnacked
- if h.ignorePacketsBelow >= f.LeastUnacked {
- return nil
- }
-
- h.ignorePacketsBelow = f.LeastUnacked - 1
- h.garbageCollectReceivedTimes()
-
- // the LeastUnacked is the smallest packet number of any packet for which the sender is still awaiting an ack. So the largestInOrderObserved is one less than that
- if f.LeastUnacked > h.largestInOrderObserved {
- h.largestInOrderObserved = f.LeastUnacked - 1
- }
-
- h.packetHistory.DeleteBelow(f.LeastUnacked)
-
- return nil
-}
-
-func (h *receivedPacketHandler) GetAckFrame(dequeue bool) (*frames.AckFrame, error) {
- if !h.stateChanged {
- return nil, nil
- }
-
- if dequeue {
- h.stateChanged = false
- }
-
- if h.currentAckFrame != nil {
- return h.currentAckFrame, nil
- }
-
- packetReceivedTime, ok := h.receivedTimes[h.largestObserved]
- if !ok {
- return nil, ErrMapAccess
- }
-
- ackRanges := h.packetHistory.GetAckRanges()
- h.currentAckFrame = &frames.AckFrame{
- LargestAcked: h.largestObserved,
- LowestAcked: ackRanges[len(ackRanges)-1].FirstPacketNumber,
- PacketReceivedTime: packetReceivedTime,
- }
-
- if len(ackRanges) > 1 {
- h.currentAckFrame.AckRanges = ackRanges
- }
-
- return h.currentAckFrame, nil
-}
-
-func (h *receivedPacketHandler) garbageCollectReceivedTimes() {
- for i := h.lowestInReceivedTimes; i <= h.ignorePacketsBelow; i++ {
- delete(h.receivedTimes, i)
- }
- if h.ignorePacketsBelow > h.lowestInReceivedTimes {
- h.lowestInReceivedTimes = h.ignorePacketsBelow + 1
- }
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/sent_packet_handler.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/sent_packet_handler.go
deleted file mode 100644
index 531a99a..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/sent_packet_handler.go
+++ /dev/null
@@ -1,350 +0,0 @@
-package ackhandler
-
-import (
- "errors"
- "fmt"
- "time"
-
- "github.com/lucas-clemente/quic-go/congestion"
- "github.com/lucas-clemente/quic-go/frames"
- "github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
-)
-
-var (
- // ErrDuplicateOrOutOfOrderAck occurs when a duplicate or an out-of-order ACK is received
- ErrDuplicateOrOutOfOrderAck = errors.New("SentPacketHandler: Duplicate or out-of-order ACK")
- // ErrTooManyTrackedSentPackets occurs when the sentPacketHandler has to keep track of too many packets
- ErrTooManyTrackedSentPackets = errors.New("Too many outstanding non-acked and non-retransmitted packets")
- // ErrAckForSkippedPacket occurs when the client sent an ACK for a packet number that we intentionally skipped
- ErrAckForSkippedPacket = qerr.Error(qerr.InvalidAckData, "Received an ACK for a skipped packet number")
- errAckForUnsentPacket = qerr.Error(qerr.InvalidAckData, "Received ACK for an unsent package")
-)
-
-var errPacketNumberNotIncreasing = errors.New("Already sent a packet with a higher packet number.")
-
-type sentPacketHandler struct {
- lastSentPacketNumber protocol.PacketNumber
- lastSentPacketTime time.Time
- skippedPackets []protocol.PacketNumber
-
- LargestAcked protocol.PacketNumber
-
- largestReceivedPacketWithAck protocol.PacketNumber
-
- packetHistory *PacketList
- stopWaitingManager stopWaitingManager
-
- retransmissionQueue []*Packet
-
- bytesInFlight protocol.ByteCount
-
- rttStats *congestion.RTTStats
- congestion congestion.SendAlgorithm
-
- consecutiveRTOCount uint32
-}
-
-// NewSentPacketHandler creates a new sentPacketHandler
-func NewSentPacketHandler() SentPacketHandler {
- rttStats := &congestion.RTTStats{}
-
- congestion := congestion.NewCubicSender(
- congestion.DefaultClock{},
- rttStats,
- false, /* don't use reno since chromium doesn't (why?) */
- protocol.InitialCongestionWindow,
- protocol.DefaultMaxCongestionWindow,
- )
-
- return &sentPacketHandler{
- packetHistory: NewPacketList(),
- stopWaitingManager: stopWaitingManager{},
- rttStats: rttStats,
- congestion: congestion,
- }
-}
-
-func (h *sentPacketHandler) ackPacket(packetElement *PacketElement) {
- packet := &packetElement.Value
- h.bytesInFlight -= packet.Length
- h.packetHistory.Remove(packetElement)
-}
-
-// nackPacket NACKs a packet
-// it returns true if a FastRetransmissions was triggered
-func (h *sentPacketHandler) nackPacket(packetElement *PacketElement) bool {
- packet := &packetElement.Value
-
- packet.MissingReports++
-
- if packet.MissingReports > protocol.RetransmissionThreshold {
- utils.Debugf("\tQueueing packet 0x%x for retransmission (fast)", packet.PacketNumber)
- h.queuePacketForRetransmission(packetElement)
- return true
- }
- return false
-}
-
-// does NOT set packet.Retransmitted. This variable is not needed anymore
-func (h *sentPacketHandler) queuePacketForRetransmission(packetElement *PacketElement) {
- packet := &packetElement.Value
- h.bytesInFlight -= packet.Length
- h.retransmissionQueue = append(h.retransmissionQueue, packet)
-
- h.packetHistory.Remove(packetElement)
-
- // strictly speaking, this is only necessary for RTO retransmissions
- // this is because FastRetransmissions are triggered by missing ranges in ACKs, and then the LargestAcked will already be higher than the packet number of the retransmitted packet
- h.stopWaitingManager.QueuedRetransmissionForPacketNumber(packet.PacketNumber)
-}
-
-func (h *sentPacketHandler) largestInOrderAcked() protocol.PacketNumber {
- if f := h.packetHistory.Front(); f != nil {
- return f.Value.PacketNumber - 1
- }
- return h.LargestAcked
-}
-
-func (h *sentPacketHandler) SentPacket(packet *Packet) error {
- if packet.PacketNumber <= h.lastSentPacketNumber {
- return errPacketNumberNotIncreasing
- }
-
- for p := h.lastSentPacketNumber + 1; p < packet.PacketNumber; p++ {
- h.skippedPackets = append(h.skippedPackets, p)
-
- if len(h.skippedPackets) > protocol.MaxTrackedSkippedPackets {
- h.skippedPackets = h.skippedPackets[1:]
- }
- }
-
- now := time.Now()
- h.lastSentPacketTime = now
- packet.SendTime = now
- if packet.Length == 0 {
- return errors.New("SentPacketHandler: packet cannot be empty")
- }
- h.bytesInFlight += packet.Length
-
- h.lastSentPacketNumber = packet.PacketNumber
- h.packetHistory.PushBack(*packet)
-
- h.congestion.OnPacketSent(
- now,
- h.BytesInFlight(),
- packet.PacketNumber,
- packet.Length,
- true, /* TODO: is retransmittable */
- )
-
- return nil
-}
-
-func (h *sentPacketHandler) ReceivedAck(ackFrame *frames.AckFrame, withPacketNumber protocol.PacketNumber, rcvTime time.Time) error {
- if ackFrame.LargestAcked > h.lastSentPacketNumber {
- return errAckForUnsentPacket
- }
-
- // duplicate or out-of-order ACK
- if withPacketNumber <= h.largestReceivedPacketWithAck {
- return ErrDuplicateOrOutOfOrderAck
- }
-
- h.largestReceivedPacketWithAck = withPacketNumber
-
- // ignore repeated ACK (ACKs that don't have a higher LargestAcked than the last ACK)
- if ackFrame.LargestAcked <= h.largestInOrderAcked() {
- return nil
- }
-
- // check if it acks any packets that were skipped
- for _, p := range h.skippedPackets {
- if ackFrame.AcksPacket(p) {
- return ErrAckForSkippedPacket
- }
- }
-
- h.LargestAcked = ackFrame.LargestAcked
-
- var ackedPackets congestion.PacketVector
- var lostPackets congestion.PacketVector
- ackRangeIndex := 0
- rttUpdated := false
-
- var el, elNext *PacketElement
- for el = h.packetHistory.Front(); el != nil; el = elNext {
- // determine the next list element right at the beginning, because el.Next() is not avaible anymore, when the list element is deleted (i.e. when the packet is ACKed)
- elNext = el.Next()
- packet := el.Value
- packetNumber := packet.PacketNumber
-
- // NACK packets below the LowestAcked
- if packetNumber < ackFrame.LowestAcked {
- retransmitted := h.nackPacket(el)
- if retransmitted {
- lostPackets = append(lostPackets, congestion.PacketInfo{Number: packetNumber, Length: packet.Length})
- }
- continue
- }
-
- // Update the RTT
- if packetNumber == h.LargestAcked {
- rttUpdated = true
- timeDelta := rcvTime.Sub(packet.SendTime)
- h.rttStats.UpdateRTT(timeDelta, ackFrame.DelayTime, rcvTime)
- if utils.Debug() {
- utils.Debugf("\tEstimated RTT: %dms", h.rttStats.SmoothedRTT()/time.Millisecond)
- }
- }
-
- if packetNumber > ackFrame.LargestAcked {
- break
- }
-
- if ackFrame.HasMissingRanges() {
- ackRange := ackFrame.AckRanges[len(ackFrame.AckRanges)-1-ackRangeIndex]
-
- for packetNumber > ackRange.LastPacketNumber && ackRangeIndex < len(ackFrame.AckRanges)-1 {
- ackRangeIndex++
- ackRange = ackFrame.AckRanges[len(ackFrame.AckRanges)-1-ackRangeIndex]
- }
-
- if packetNumber >= ackRange.FirstPacketNumber { // packet i contained in ACK range
- if packetNumber > ackRange.LastPacketNumber {
- return fmt.Errorf("BUG: ackhandler would have acked wrong packet 0x%x, while evaluating range 0x%x -> 0x%x", packetNumber, ackRange.FirstPacketNumber, ackRange.LastPacketNumber)
- }
- h.ackPacket(el)
- ackedPackets = append(ackedPackets, congestion.PacketInfo{Number: packetNumber, Length: packet.Length})
- } else {
- retransmitted := h.nackPacket(el)
- if retransmitted {
- lostPackets = append(lostPackets, congestion.PacketInfo{Number: packetNumber, Length: packet.Length})
- }
- }
- } else {
- h.ackPacket(el)
- ackedPackets = append(ackedPackets, congestion.PacketInfo{Number: packetNumber, Length: packet.Length})
- }
- }
-
- if rttUpdated {
- // Reset counter if a new packet was acked
- h.consecutiveRTOCount = 0
- }
-
- h.garbageCollectSkippedPackets()
-
- h.stopWaitingManager.ReceivedAck(ackFrame)
-
- h.congestion.OnCongestionEvent(
- rttUpdated,
- h.BytesInFlight(),
- ackedPackets,
- lostPackets,
- )
-
- return nil
-}
-
-func (h *sentPacketHandler) DequeuePacketForRetransmission() *Packet {
- if len(h.retransmissionQueue) == 0 {
- return nil
- }
-
- if len(h.retransmissionQueue) > 0 {
- queueLen := len(h.retransmissionQueue)
- // packets are usually NACKed in descending order. So use the slice as a stack
- packet := h.retransmissionQueue[queueLen-1]
- h.retransmissionQueue = h.retransmissionQueue[:queueLen-1]
- return packet
- }
-
- return nil
-}
-
-func (h *sentPacketHandler) BytesInFlight() protocol.ByteCount {
- return h.bytesInFlight
-}
-
-func (h *sentPacketHandler) GetLeastUnacked() protocol.PacketNumber {
- return h.largestInOrderAcked() + 1
-}
-
-func (h *sentPacketHandler) GetStopWaitingFrame(force bool) *frames.StopWaitingFrame {
- return h.stopWaitingManager.GetStopWaitingFrame(force)
-}
-
-func (h *sentPacketHandler) SendingAllowed() bool {
- congestionLimited := h.BytesInFlight() > h.congestion.GetCongestionWindow()
- maxTrackedLimited := protocol.PacketNumber(len(h.retransmissionQueue)+h.packetHistory.Len()) >= protocol.MaxTrackedSentPackets
- return !(congestionLimited || maxTrackedLimited)
-}
-
-func (h *sentPacketHandler) CheckForError() error {
- length := len(h.retransmissionQueue) + h.packetHistory.Len()
- if protocol.PacketNumber(length) > protocol.MaxTrackedSentPackets {
- return ErrTooManyTrackedSentPackets
- }
- return nil
-}
-
-func (h *sentPacketHandler) MaybeQueueRTOs() {
- if time.Now().Before(h.TimeOfFirstRTO()) {
- return
- }
-
- // Always queue the two oldest packets
- if h.packetHistory.Front() != nil {
- h.queueRTO(h.packetHistory.Front())
- }
- if h.packetHistory.Front() != nil {
- h.queueRTO(h.packetHistory.Front())
- }
-
- // Reset the RTO timer here, since it's not clear that this packet contained any retransmittable frames
- h.lastSentPacketTime = time.Now()
- h.consecutiveRTOCount++
-}
-
-func (h *sentPacketHandler) queueRTO(el *PacketElement) {
- packet := &el.Value
- packetsLost := congestion.PacketVector{congestion.PacketInfo{
- Number: packet.PacketNumber,
- Length: packet.Length,
- }}
- h.congestion.OnCongestionEvent(false, h.BytesInFlight(), nil, packetsLost)
- h.congestion.OnRetransmissionTimeout(true)
- utils.Debugf("\tQueueing packet 0x%x for retransmission (RTO)", packet.PacketNumber)
- h.queuePacketForRetransmission(el)
-}
-
-func (h *sentPacketHandler) getRTO() time.Duration {
- rto := h.congestion.RetransmissionDelay()
- if rto == 0 {
- rto = protocol.DefaultRetransmissionTime
- }
- rto = utils.MaxDuration(rto, protocol.MinRetransmissionTime)
- // Exponential backoff
- rto *= 1 << h.consecutiveRTOCount
- return utils.MinDuration(rto, protocol.MaxRetransmissionTime)
-}
-
-func (h *sentPacketHandler) TimeOfFirstRTO() time.Time {
- if h.lastSentPacketTime.IsZero() {
- return time.Time{}
- }
- return h.lastSentPacketTime.Add(h.getRTO())
-}
-
-func (h *sentPacketHandler) garbageCollectSkippedPackets() {
- lioa := h.largestInOrderAcked()
- deleteIndex := 0
- for i, p := range h.skippedPackets {
- if p <= lioa {
- deleteIndex = i + 1
- }
- }
- h.skippedPackets = h.skippedPackets[deleteIndex:]
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/congestion_vector.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/congestion_vector.go
deleted file mode 100644
index 9c6ebb4..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/congestion_vector.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package congestion
-
-import "github.com/lucas-clemente/quic-go/protocol"
-
-// PacketInfo combines packet number and length of a packet for congestion calculation
-type PacketInfo struct {
- Number protocol.PacketNumber
- Length protocol.ByteCount
-}
-
-// PacketVector is passed to the congestion algorithm
-type PacketVector []PacketInfo
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/proof_source.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/proof_source.go
deleted file mode 100644
index 6af8072..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/proof_source.go
+++ /dev/null
@@ -1,92 +0,0 @@
-package crypto
-
-import (
- "crypto"
- "crypto/rand"
- "crypto/rsa"
- "crypto/sha256"
- "crypto/tls"
- "errors"
- "strings"
-)
-
-// proofSource stores a key and a certificate for the server proof
-type proofSource struct {
- config *tls.Config
-}
-
-// NewProofSource loads the key and cert from files
-func NewProofSource(tlsConfig *tls.Config) (Signer, error) {
- return &proofSource{config: tlsConfig}, nil
-}
-
-// SignServerProof signs CHLO and server config for use in the server proof
-func (ps *proofSource) SignServerProof(sni string, chlo []byte, serverConfigData []byte) ([]byte, error) {
- cert, err := ps.getCertForSNI(sni)
- if err != nil {
- return nil, err
- }
-
- hash := sha256.New()
- hash.Write([]byte("QUIC CHLO and server config signature\x00"))
- chloHash := sha256.Sum256(chlo)
- hash.Write([]byte{32, 0, 0, 0})
- hash.Write(chloHash[:])
- hash.Write(serverConfigData)
-
- key, ok := cert.PrivateKey.(crypto.Signer)
- if !ok {
- return nil, errors.New("expected PrivateKey to implement crypto.Signer")
- }
-
- opts := crypto.SignerOpts(crypto.SHA256)
-
- if _, ok = key.(*rsa.PrivateKey); ok {
- opts = &rsa.PSSOptions{SaltLength: 32, Hash: crypto.SHA256}
- }
-
- return key.Sign(rand.Reader, hash.Sum(nil), opts)
-}
-
-// GetCertsCompressed gets the certificate in the format described by the QUIC crypto doc
-func (ps *proofSource) GetCertsCompressed(sni string, pCommonSetHashes, pCachedHashes []byte) ([]byte, error) {
- cert, err := ps.getCertForSNI(sni)
- if err != nil {
- return nil, err
- }
- return getCompressedCert(cert.Certificate, pCommonSetHashes, pCachedHashes)
-}
-
-// GetLeafCert gets the leaf certificate
-func (ps *proofSource) GetLeafCert(sni string) ([]byte, error) {
- cert, err := ps.getCertForSNI(sni)
- if err != nil {
- return nil, err
- }
- return cert.Certificate[0], nil
-}
-
-func (ps *proofSource) getCertForSNI(sni string) (*tls.Certificate, error) {
- if ps.config.GetCertificate != nil {
- cert, err := ps.config.GetCertificate(&tls.ClientHelloInfo{ServerName: sni})
- if err != nil {
- return nil, err
- }
- if cert != nil {
- return cert, nil
- }
- }
- if len(ps.config.NameToCertificate) != 0 {
- if cert, ok := ps.config.NameToCertificate[sni]; ok {
- return cert, nil
- }
- wildcardSNI := "*" + strings.TrimLeftFunc(sni, func(r rune) bool { return r != '.' })
- if cert, ok := ps.config.NameToCertificate[wildcardSNI]; ok {
- return cert, nil
- }
- }
- if len(ps.config.Certificates) != 0 {
- return &ps.config.Certificates[0], nil
- }
- return nil, errors.New("no matching certificate found")
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/signer.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/signer.go
deleted file mode 100644
index 0d9ba4e..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/signer.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package crypto
-
-// A Signer holds a certificate and a private key
-type Signer interface {
- SignServerProof(sni string, chlo []byte, serverConfigData []byte) ([]byte, error)
- GetCertsCompressed(sni string, commonSetHashes, cachedHashes []byte) ([]byte, error)
- GetLeafCert(sni string) ([]byte, error)
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/source_address_token.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/source_address_token.go
deleted file mode 100644
index 6afdacd..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/source_address_token.go
+++ /dev/null
@@ -1,128 +0,0 @@
-package crypto
-
-import (
- "crypto/aes"
- "crypto/cipher"
- "crypto/rand"
- "crypto/sha256"
- "crypto/subtle"
- "encoding/binary"
- "errors"
- "fmt"
- "io"
- "net"
- "time"
-
- "github.com/lucas-clemente/quic-go/protocol"
-
- "golang.org/x/crypto/hkdf"
-)
-
-// StkSource is used to create and verify source address tokens
-type StkSource interface {
- // NewToken creates a new token for a given IP address
- NewToken(ip net.IP) ([]byte, error)
- // VerifyToken verifies if a token matches a given IP address and is not outdated
- VerifyToken(ip net.IP, data []byte) error
-}
-
-type sourceAddressToken struct {
- ip net.IP
- // unix timestamp in seconds
- timestamp uint64
-}
-
-func (t *sourceAddressToken) serialize() []byte {
- res := make([]byte, 8+len(t.ip))
- binary.LittleEndian.PutUint64(res, t.timestamp)
- copy(res[8:], t.ip)
- return res
-}
-
-func parseToken(data []byte) (*sourceAddressToken, error) {
- if len(data) != 8+4 && len(data) != 8+16 {
- return nil, fmt.Errorf("invalid STK length: %d", len(data))
- }
- return &sourceAddressToken{
- ip: data[8:],
- timestamp: binary.LittleEndian.Uint64(data),
- }, nil
-}
-
-type stkSource struct {
- aead cipher.AEAD
-}
-
-const stkKeySize = 16
-
-// Chrome currently sets this to 12, but discusses changing it to 16. We start
-// at 16 :)
-const stkNonceSize = 16
-
-// NewStkSource creates a source for source address tokens
-func NewStkSource(secret []byte) (StkSource, error) {
- key, err := deriveKey(secret)
- if err != nil {
- return nil, err
- }
- c, err := aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- aead, err := cipher.NewGCMWithNonceSize(c, stkNonceSize)
- if err != nil {
- return nil, err
- }
- return &stkSource{aead: aead}, nil
-}
-
-func (s *stkSource) NewToken(ip net.IP) ([]byte, error) {
- return encryptToken(s.aead, &sourceAddressToken{
- ip: ip,
- timestamp: uint64(time.Now().Unix()),
- })
-}
-
-func (s *stkSource) VerifyToken(ip net.IP, data []byte) error {
- if len(data) < stkNonceSize {
- return errors.New("STK too short")
- }
- nonce := data[:stkNonceSize]
-
- res, err := s.aead.Open(nil, nonce, data[stkNonceSize:], nil)
- if err != nil {
- return err
- }
-
- token, err := parseToken(res)
- if err != nil {
- return err
- }
-
- if subtle.ConstantTimeCompare(token.ip, ip) != 1 {
- return errors.New("invalid ip in STK")
- }
-
- if time.Now().Unix() > int64(token.timestamp)+protocol.STKExpiryTimeSec {
- return errors.New("STK expired")
- }
-
- return nil
-}
-
-func deriveKey(secret []byte) ([]byte, error) {
- r := hkdf.New(sha256.New, secret, nil, []byte("QUIC source address token key"))
- key := make([]byte, stkKeySize)
- if _, err := io.ReadFull(r, key); err != nil {
- return nil, err
- }
- return key, nil
-}
-
-func encryptToken(aead cipher.AEAD, token *sourceAddressToken) ([]byte, error) {
- nonce := make([]byte, stkNonceSize)
- if _, err := rand.Read(nonce); err != nil {
- return nil, err
- }
- return aead.Seal(nonce, nonce, token.serialize(), nil), nil
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_control_manager.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_control_manager.go
deleted file mode 100644
index 0ab6363..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_control_manager.go
+++ /dev/null
@@ -1,188 +0,0 @@
-package flowcontrol
-
-import (
- "errors"
- "sync"
-
- "github.com/lucas-clemente/quic-go/handshake"
- "github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
-)
-
-type flowControlManager struct {
- connectionParametersManager *handshake.ConnectionParametersManager
- streamFlowController map[protocol.StreamID]*flowController
- contributesToConnectionFlowControl map[protocol.StreamID]bool
- mutex sync.RWMutex
-}
-
-var (
- // ErrStreamFlowControlViolation is a stream flow control violation
- ErrStreamFlowControlViolation = errors.New("Stream level flow control violation")
- // ErrConnectionFlowControlViolation is a connection level flow control violation
- ErrConnectionFlowControlViolation = errors.New("Connection level flow control violation")
-)
-
-var errMapAccess = errors.New("Error accessing the flowController map.")
-
-// NewFlowControlManager creates a new flow control manager
-func NewFlowControlManager(connectionParametersManager *handshake.ConnectionParametersManager) FlowControlManager {
- fcm := flowControlManager{
- connectionParametersManager: connectionParametersManager,
- streamFlowController: make(map[protocol.StreamID]*flowController),
- contributesToConnectionFlowControl: make(map[protocol.StreamID]bool),
- }
- // initialize connection level flow controller
- fcm.streamFlowController[0] = newFlowController(0, connectionParametersManager)
- fcm.contributesToConnectionFlowControl[0] = false
- return &fcm
-}
-
-// NewStream creates new flow controllers for a stream
-func (f *flowControlManager) NewStream(streamID protocol.StreamID, contributesToConnectionFlow bool) {
- f.mutex.Lock()
- defer f.mutex.Unlock()
-
- if _, ok := f.streamFlowController[streamID]; ok {
- return
- }
-
- f.streamFlowController[streamID] = newFlowController(streamID, f.connectionParametersManager)
- f.contributesToConnectionFlowControl[streamID] = contributesToConnectionFlow
-}
-
-// RemoveStream removes a closed stream from flow control
-func (f *flowControlManager) RemoveStream(streamID protocol.StreamID) {
- f.mutex.Lock()
- delete(f.streamFlowController, streamID)
- delete(f.contributesToConnectionFlowControl, streamID)
- f.mutex.Unlock()
-}
-
-// UpdateHighestReceived updates the highest received byte offset for a stream
-// it adds the number of additional bytes to connection level flow control
-// streamID must not be 0 here
-func (f *flowControlManager) UpdateHighestReceived(streamID protocol.StreamID, byteOffset protocol.ByteCount) error {
- f.mutex.Lock()
- defer f.mutex.Unlock()
-
- streamFlowController, err := f.getFlowController(streamID)
- if err != nil {
- return err
- }
- increment := streamFlowController.UpdateHighestReceived(byteOffset)
-
- if streamFlowController.CheckFlowControlViolation() {
- return ErrStreamFlowControlViolation
- }
-
- if f.contributesToConnectionFlowControl[streamID] {
- connectionFlowController := f.streamFlowController[0]
- connectionFlowController.IncrementHighestReceived(increment)
- if connectionFlowController.CheckFlowControlViolation() {
- return ErrConnectionFlowControlViolation
- }
- }
-
- return nil
-}
-
-// streamID must not be 0 here
-func (f *flowControlManager) AddBytesRead(streamID protocol.StreamID, n protocol.ByteCount) error {
- f.mutex.Lock()
- defer f.mutex.Unlock()
-
- streamFlowController, err := f.getFlowController(streamID)
- if err != nil {
- return err
- }
-
- streamFlowController.AddBytesRead(n)
-
- if f.contributesToConnectionFlowControl[streamID] {
- f.streamFlowController[0].AddBytesRead(n)
- }
-
- return nil
-}
-
-func (f *flowControlManager) GetWindowUpdates() (res []WindowUpdate) {
- f.mutex.Lock()
- defer f.mutex.Unlock()
- for id, fc := range f.streamFlowController {
- if necessary, offset := fc.MaybeTriggerWindowUpdate(); necessary {
- res = append(res, WindowUpdate{StreamID: id, Offset: offset})
- }
- }
- return res
-}
-
-// streamID must not be 0 here
-func (f *flowControlManager) AddBytesSent(streamID protocol.StreamID, n protocol.ByteCount) error {
- // Only lock the part reading from the map, since send-windows are only accessed from the session goroutine.
- f.mutex.Lock()
- streamFlowController, err := f.getFlowController(streamID)
- f.mutex.Unlock()
- if err != nil {
- return err
- }
-
- streamFlowController.AddBytesSent(n)
-
- if f.contributesToConnectionFlowControl[streamID] {
- f.streamFlowController[0].AddBytesSent(n)
- }
-
- return nil
-}
-
-// must not be called with StreamID 0
-func (f *flowControlManager) SendWindowSize(streamID protocol.StreamID) (protocol.ByteCount, error) {
- // Only lock the part reading from the map, since send-windows are only accessed from the session goroutine.
- f.mutex.RLock()
- streamFlowController, err := f.getFlowController(streamID)
- f.mutex.RUnlock()
- if err != nil {
- return 0, err
- }
- res := streamFlowController.SendWindowSize()
-
- contributes, ok := f.contributesToConnectionFlowControl[streamID]
- if !ok {
- return 0, errMapAccess
- }
- if contributes {
- res = utils.MinByteCount(res, f.streamFlowController[0].SendWindowSize())
- }
-
- return res, nil
-}
-
-func (f *flowControlManager) RemainingConnectionWindowSize() protocol.ByteCount {
- // Only lock the part reading from the map, since send-windows are only accessed from the session goroutine.
- f.mutex.RLock()
- res := f.streamFlowController[0].SendWindowSize()
- f.mutex.RUnlock()
- return res
-}
-
-// streamID may be 0 here
-func (f *flowControlManager) UpdateWindow(streamID protocol.StreamID, offset protocol.ByteCount) (bool, error) {
- // Only lock the part reading from the map, since send-windows are only accessed from the session goroutine.
- f.mutex.Lock()
- streamFlowController, err := f.getFlowController(streamID)
- f.mutex.Unlock()
- if err != nil {
- return false, err
- }
-
- return streamFlowController.UpdateSendWindow(offset), nil
-}
-
-func (f *flowControlManager) getFlowController(streamID protocol.StreamID) (*flowController, error) {
- streamFlowController, ok := f.streamFlowController[streamID]
- if !ok {
- return nil, errMapAccess
- }
- return streamFlowController, nil
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_controller.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_controller.go
deleted file mode 100644
index 21020ad..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_controller.go
+++ /dev/null
@@ -1,115 +0,0 @@
-package flowcontrol
-
-import (
- "github.com/lucas-clemente/quic-go/handshake"
- "github.com/lucas-clemente/quic-go/protocol"
-)
-
-type flowController struct {
- streamID protocol.StreamID
-
- connectionParametersManager *handshake.ConnectionParametersManager
-
- bytesSent protocol.ByteCount
- sendFlowControlWindow protocol.ByteCount
-
- bytesRead protocol.ByteCount
- highestReceived protocol.ByteCount
- receiveFlowControlWindow protocol.ByteCount
- receiveFlowControlWindowIncrement protocol.ByteCount
-}
-
-// newFlowController gets a new flow controller
-func newFlowController(streamID protocol.StreamID, connectionParametersManager *handshake.ConnectionParametersManager) *flowController {
- fc := flowController{
- streamID: streamID,
- connectionParametersManager: connectionParametersManager,
- }
-
- if streamID == 0 {
- fc.receiveFlowControlWindow = connectionParametersManager.GetReceiveConnectionFlowControlWindow()
- fc.receiveFlowControlWindowIncrement = fc.receiveFlowControlWindow
- } else {
- fc.receiveFlowControlWindow = connectionParametersManager.GetReceiveStreamFlowControlWindow()
- fc.receiveFlowControlWindowIncrement = fc.receiveFlowControlWindow
- }
-
- return &fc
-}
-
-func (c *flowController) getSendFlowControlWindow() protocol.ByteCount {
- if c.sendFlowControlWindow == 0 {
- if c.streamID == 0 {
- return c.connectionParametersManager.GetSendConnectionFlowControlWindow()
- }
- return c.connectionParametersManager.GetSendStreamFlowControlWindow()
- }
- return c.sendFlowControlWindow
-}
-
-func (c *flowController) AddBytesSent(n protocol.ByteCount) {
- c.bytesSent += n
-}
-
-// UpdateSendWindow should be called after receiving a WindowUpdateFrame
-// it returns true if the window was actually updated
-func (c *flowController) UpdateSendWindow(newOffset protocol.ByteCount) bool {
- if newOffset > c.sendFlowControlWindow {
- c.sendFlowControlWindow = newOffset
- return true
- }
- return false
-}
-
-func (c *flowController) SendWindowSize() protocol.ByteCount {
- sendFlowControlWindow := c.getSendFlowControlWindow()
-
- if c.bytesSent > sendFlowControlWindow { // should never happen, but make sure we don't do an underflow here
- return 0
- }
- return sendFlowControlWindow - c.bytesSent
-}
-
-func (c *flowController) SendWindowOffset() protocol.ByteCount {
- return c.getSendFlowControlWindow()
-}
-
-// UpdateHighestReceived updates the highestReceived value, if the byteOffset is higher
-// Should **only** be used for the stream-level FlowController
-func (c *flowController) UpdateHighestReceived(byteOffset protocol.ByteCount) protocol.ByteCount {
- if byteOffset > c.highestReceived {
- increment := byteOffset - c.highestReceived
- c.highestReceived = byteOffset
- return increment
- }
- return 0
-}
-
-// IncrementHighestReceived adds an increment to the highestReceived value
-// Should **only** be used for the connection-level FlowController
-func (c *flowController) IncrementHighestReceived(increment protocol.ByteCount) {
- c.highestReceived += increment
-}
-
-func (c *flowController) AddBytesRead(n protocol.ByteCount) {
- c.bytesRead += n
-}
-
-// MaybeTriggerWindowUpdate determines if it is necessary to send a WindowUpdate
-// if so, it returns true and the offset of the window
-func (c *flowController) MaybeTriggerWindowUpdate() (bool, protocol.ByteCount) {
- diff := c.receiveFlowControlWindow - c.bytesRead
- // Chromium implements the same threshold
- if diff < (c.receiveFlowControlWindowIncrement / 2) {
- c.receiveFlowControlWindow = c.bytesRead + c.receiveFlowControlWindowIncrement
- return true, c.receiveFlowControlWindow
- }
- return false, 0
-}
-
-func (c *flowController) CheckFlowControlViolation() bool {
- if c.highestReceived > c.receiveFlowControlWindow {
- return true
- }
- return false
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/log.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/log.go
deleted file mode 100644
index ac548c6..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/log.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package frames
-
-import "github.com/lucas-clemente/quic-go/utils"
-
-// LogFrame logs a frame, either sent or received
-func LogFrame(frame Frame, sent bool) {
- if !utils.Debug() {
- return
- }
- dir := "<-"
- if sent {
- dir = "->"
- }
- if sf, ok := frame.(*StreamFrame); ok {
- utils.Debugf("\t%s &frames.StreamFrame{StreamID: %d, FinBit: %t, Offset: 0x%x, Data length: 0x%x, Offset + Data length: 0x%x}", dir, sf.StreamID, sf.FinBit, sf.Offset, sf.DataLen(), sf.Offset+sf.DataLen())
- return
- }
- utils.Debugf("\t%s %#v", dir, frame)
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/h2quic/request.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/h2quic/request.go
deleted file mode 100644
index f2e0fa5..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/h2quic/request.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package h2quic
-
-import (
- "errors"
- "net/http"
- "net/url"
-
- "golang.org/x/net/http2/hpack"
-)
-
-func requestFromHeaders(headers []hpack.HeaderField) (*http.Request, error) {
- var path, authority, method string
- httpHeaders := http.Header{}
-
- for _, h := range headers {
- switch h.Name {
- case ":path":
- path = h.Value
- case ":method":
- method = h.Value
- case ":authority":
- authority = h.Value
- default:
- if !h.IsPseudo() {
- httpHeaders.Add(h.Name, h.Value)
- }
- }
- }
-
- if len(path) == 0 || len(authority) == 0 || len(method) == 0 {
- return nil, errors.New(":path, :authority and :method must not be empty")
- }
-
- u, err := url.Parse(path)
- if err != nil {
- return nil, err
- }
-
- return &http.Request{
- Method: method,
- URL: u,
- Proto: "HTTP/2.0",
- ProtoMajor: 2,
- ProtoMinor: 0,
- Header: httpHeaders,
- Body: nil,
- // ContentLength: -1,
- Host: authority,
- RequestURI: path,
- }, nil
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/connection_parameters_manager.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/connection_parameters_manager.go
deleted file mode 100644
index df26119..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/connection_parameters_manager.go
+++ /dev/null
@@ -1,202 +0,0 @@
-package handshake
-
-import (
- "bytes"
- "encoding/binary"
- "errors"
- "sync"
- "time"
-
- "github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
-)
-
-// ConnectionParametersManager stores the connection parameters
-// Warning: Writes may only be done from the crypto stream, see the comment
-// in GetSHLOMap().
-type ConnectionParametersManager struct {
- params map[Tag][]byte
- mutex sync.RWMutex
-
- flowControlNegotiated bool // have the flow control parameters for sending already been negotiated
-
- maxStreamsPerConnection uint32
- idleConnectionStateLifetime time.Duration
- sendStreamFlowControlWindow protocol.ByteCount
- sendConnectionFlowControlWindow protocol.ByteCount
- receiveStreamFlowControlWindow protocol.ByteCount
- receiveConnectionFlowControlWindow protocol.ByteCount
-}
-
-var errTagNotInConnectionParameterMap = errors.New("ConnectionParametersManager: Tag not found in ConnectionsParameter map")
-
-// ErrMalformedTag is returned when the tag value cannot be read
-var (
- ErrMalformedTag = qerr.Error(qerr.InvalidCryptoMessageParameter, "malformed Tag value")
- ErrFlowControlRenegotiationNotSupported = qerr.Error(qerr.InvalidCryptoMessageParameter, "renegotiation of flow control parameters not supported")
-)
-
-// NewConnectionParamatersManager creates a new connection parameters manager
-func NewConnectionParamatersManager() *ConnectionParametersManager {
- return &ConnectionParametersManager{
- params: make(map[Tag][]byte),
- idleConnectionStateLifetime: protocol.DefaultIdleTimeout,
- sendStreamFlowControlWindow: protocol.InitialStreamFlowControlWindow, // can only be changed by the client
- sendConnectionFlowControlWindow: protocol.InitialConnectionFlowControlWindow, // can only be changed by the client
- receiveStreamFlowControlWindow: protocol.ReceiveStreamFlowControlWindow,
- receiveConnectionFlowControlWindow: protocol.ReceiveConnectionFlowControlWindow,
- maxStreamsPerConnection: protocol.MaxStreamsPerConnection,
- }
-}
-
-// SetFromMap reads all params
-func (h *ConnectionParametersManager) SetFromMap(params map[Tag][]byte) error {
- h.mutex.Lock()
- defer h.mutex.Unlock()
-
- for key, value := range params {
- switch key {
- case TagTCID:
- h.params[key] = value
- case TagMSPC:
- clientValue, err := utils.ReadUint32(bytes.NewBuffer(value))
- if err != nil {
- return ErrMalformedTag
- }
- h.maxStreamsPerConnection = h.negotiateMaxStreamsPerConnection(clientValue)
- case TagICSL:
- clientValue, err := utils.ReadUint32(bytes.NewBuffer(value))
- if err != nil {
- return ErrMalformedTag
- }
- h.idleConnectionStateLifetime = h.negotiateIdleConnectionStateLifetime(time.Duration(clientValue) * time.Second)
- case TagSFCW:
- if h.flowControlNegotiated {
- return ErrFlowControlRenegotiationNotSupported
- }
- sendStreamFlowControlWindow, err := utils.ReadUint32(bytes.NewBuffer(value))
- if err != nil {
- return ErrMalformedTag
- }
- h.sendStreamFlowControlWindow = protocol.ByteCount(sendStreamFlowControlWindow)
- case TagCFCW:
- if h.flowControlNegotiated {
- return ErrFlowControlRenegotiationNotSupported
- }
- sendConnectionFlowControlWindow, err := utils.ReadUint32(bytes.NewBuffer(value))
- if err != nil {
- return ErrMalformedTag
- }
- h.sendConnectionFlowControlWindow = protocol.ByteCount(sendConnectionFlowControlWindow)
- }
- }
-
- _, containsSFCW := params[TagSFCW]
- _, containsCFCW := params[TagCFCW]
- if containsCFCW || containsSFCW {
- h.flowControlNegotiated = true
- }
-
- return nil
-}
-
-func (h *ConnectionParametersManager) negotiateMaxStreamsPerConnection(clientValue uint32) uint32 {
- return utils.MinUint32(clientValue, protocol.MaxStreamsPerConnection)
-}
-
-func (h *ConnectionParametersManager) negotiateIdleConnectionStateLifetime(clientValue time.Duration) time.Duration {
- return utils.MinDuration(clientValue, protocol.MaxIdleTimeout)
-}
-
-// getRawValue gets the byte-slice for a tag
-func (h *ConnectionParametersManager) getRawValue(tag Tag) ([]byte, error) {
- h.mutex.RLock()
- rawValue, ok := h.params[tag]
- h.mutex.RUnlock()
-
- if !ok {
- return nil, errTagNotInConnectionParameterMap
- }
- return rawValue, nil
-}
-
-// GetSHLOMap gets all values (except crypto values) needed for the SHLO
-func (h *ConnectionParametersManager) GetSHLOMap() map[Tag][]byte {
- sfcw := bytes.NewBuffer([]byte{})
- utils.WriteUint32(sfcw, uint32(h.GetReceiveStreamFlowControlWindow()))
- cfcw := bytes.NewBuffer([]byte{})
- utils.WriteUint32(cfcw, uint32(h.GetReceiveConnectionFlowControlWindow()))
- mspc := bytes.NewBuffer([]byte{})
- utils.WriteUint32(mspc, h.GetMaxStreamsPerConnection())
- mids := bytes.NewBuffer([]byte{})
- utils.WriteUint32(mids, protocol.MaxIncomingDynamicStreams)
- icsl := bytes.NewBuffer([]byte{})
- utils.WriteUint32(icsl, uint32(h.GetIdleConnectionStateLifetime()/time.Second))
-
- return map[Tag][]byte{
- TagICSL: icsl.Bytes(),
- TagMSPC: mspc.Bytes(),
- TagMIDS: mids.Bytes(),
- TagCFCW: cfcw.Bytes(),
- TagSFCW: sfcw.Bytes(),
- }
-}
-
-// GetSendStreamFlowControlWindow gets the size of the stream-level flow control window for sending data
-func (h *ConnectionParametersManager) GetSendStreamFlowControlWindow() protocol.ByteCount {
- h.mutex.RLock()
- defer h.mutex.RUnlock()
- return h.sendStreamFlowControlWindow
-}
-
-// GetSendConnectionFlowControlWindow gets the size of the stream-level flow control window for sending data
-func (h *ConnectionParametersManager) GetSendConnectionFlowControlWindow() protocol.ByteCount {
- h.mutex.RLock()
- defer h.mutex.RUnlock()
- return h.sendConnectionFlowControlWindow
-}
-
-// GetReceiveStreamFlowControlWindow gets the size of the stream-level flow control window for receiving data
-func (h *ConnectionParametersManager) GetReceiveStreamFlowControlWindow() protocol.ByteCount {
- h.mutex.RLock()
- defer h.mutex.RUnlock()
- return h.receiveStreamFlowControlWindow
-}
-
-// GetReceiveConnectionFlowControlWindow gets the size of the stream-level flow control window for receiving data
-func (h *ConnectionParametersManager) GetReceiveConnectionFlowControlWindow() protocol.ByteCount {
- h.mutex.RLock()
- defer h.mutex.RUnlock()
- return h.receiveConnectionFlowControlWindow
-}
-
-// GetMaxStreamsPerConnection gets the maximum number of streams per connection
-func (h *ConnectionParametersManager) GetMaxStreamsPerConnection() uint32 {
- h.mutex.RLock()
- defer h.mutex.RUnlock()
- return h.maxStreamsPerConnection
-}
-
-// GetIdleConnectionStateLifetime gets the idle timeout
-func (h *ConnectionParametersManager) GetIdleConnectionStateLifetime() time.Duration {
- h.mutex.RLock()
- defer h.mutex.RUnlock()
- return h.idleConnectionStateLifetime
-}
-
-// TruncateConnectionID determines if the client requests truncated ConnectionIDs
-func (h *ConnectionParametersManager) TruncateConnectionID() bool {
- rawValue, err := h.getRawValue(TagTCID)
- if err != nil {
- return false
- }
- if len(rawValue) != 4 {
- return false
- }
- value := binary.LittleEndian.Uint32(rawValue)
- if value == 0 {
- return true
- }
- return false
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/crypto_setup.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/crypto_setup.go
deleted file mode 100644
index 56e9764..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/crypto_setup.go
+++ /dev/null
@@ -1,327 +0,0 @@
-package handshake
-
-import (
- "bytes"
- "crypto/rand"
- "io"
- "net"
- "sync"
-
- "github.com/lucas-clemente/quic-go/crypto"
- "github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
-)
-
-// KeyDerivationFunction is used for key derivation
-type KeyDerivationFunction func(forwardSecure bool, sharedSecret, nonces []byte, connID protocol.ConnectionID, chlo []byte, scfg []byte, cert []byte, divNonce []byte) (crypto.AEAD, error)
-
-// KeyExchangeFunction is used to make a new KEX
-type KeyExchangeFunction func() crypto.KeyExchange
-
-// The CryptoSetup handles all things crypto for the Session
-type CryptoSetup struct {
- connID protocol.ConnectionID
- ip net.IP
- version protocol.VersionNumber
- scfg *ServerConfig
- diversificationNonce []byte
-
- secureAEAD crypto.AEAD
- forwardSecureAEAD crypto.AEAD
- receivedForwardSecurePacket bool
- receivedSecurePacket bool
- aeadChanged chan struct{}
-
- keyDerivation KeyDerivationFunction
- keyExchange KeyExchangeFunction
-
- cryptoStream utils.Stream
-
- connectionParametersManager *ConnectionParametersManager
-
- mutex sync.RWMutex
-}
-
-var _ crypto.AEAD = &CryptoSetup{}
-
-// NewCryptoSetup creates a new CryptoSetup instance
-func NewCryptoSetup(
- connID protocol.ConnectionID,
- ip net.IP,
- version protocol.VersionNumber,
- scfg *ServerConfig,
- cryptoStream utils.Stream,
- connectionParametersManager *ConnectionParametersManager,
- aeadChanged chan struct{},
-) (*CryptoSetup, error) {
- return &CryptoSetup{
- connID: connID,
- ip: ip,
- version: version,
- scfg: scfg,
- keyDerivation: crypto.DeriveKeysAESGCM,
- keyExchange: getEphermalKEX,
- cryptoStream: cryptoStream,
- connectionParametersManager: connectionParametersManager,
- aeadChanged: aeadChanged,
- }, nil
-}
-
-// HandleCryptoStream reads and writes messages on the crypto stream
-func (h *CryptoSetup) HandleCryptoStream() error {
- for {
- var chloData bytes.Buffer
- messageTag, cryptoData, err := ParseHandshakeMessage(io.TeeReader(h.cryptoStream, &chloData))
- if err != nil {
- return qerr.HandshakeFailed
- }
- if messageTag != TagCHLO {
- return qerr.InvalidCryptoMessageType
- }
-
- utils.Debugf("Got CHLO:\n%s", printHandshakeMessage(cryptoData))
-
- done, err := h.handleMessage(chloData.Bytes(), cryptoData)
- if err != nil {
- return err
- }
- if done {
- return nil
- }
- }
-}
-
-func (h *CryptoSetup) handleMessage(chloData []byte, cryptoData map[Tag][]byte) (bool, error) {
- sniSlice, ok := cryptoData[TagSNI]
- if !ok {
- return false, qerr.Error(qerr.CryptoMessageParameterNotFound, "SNI required")
- }
- sni := string(sniSlice)
- if sni == "" {
- return false, qerr.Error(qerr.CryptoMessageParameterNotFound, "SNI required")
- }
-
- var reply []byte
- var err error
- if !h.isInchoateCHLO(cryptoData) {
- // We have a CHLO with a proper server config ID, do a 0-RTT handshake
- reply, err = h.handleCHLO(sni, chloData, cryptoData)
- if err != nil {
- return false, err
- }
- _, err = h.cryptoStream.Write(reply)
- if err != nil {
- return false, err
- }
- return true, nil
- }
-
- // We have an inchoate or non-matching CHLO, we now send a rejection
- reply, err = h.handleInchoateCHLO(sni, chloData, cryptoData)
- if err != nil {
- return false, err
- }
- _, err = h.cryptoStream.Write(reply)
- if err != nil {
- return false, err
- }
- return false, nil
-}
-
-// Open a message
-func (h *CryptoSetup) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) {
- h.mutex.RLock()
- defer h.mutex.RUnlock()
-
- if h.forwardSecureAEAD != nil {
- res, err := h.forwardSecureAEAD.Open(dst, src, packetNumber, associatedData)
- if err == nil {
- h.receivedForwardSecurePacket = true
- return res, nil
- }
- if h.receivedForwardSecurePacket {
- return nil, err
- }
- }
- if h.secureAEAD != nil {
- res, err := h.secureAEAD.Open(dst, src, packetNumber, associatedData)
- if err == nil {
- h.receivedSecurePacket = true
- return res, nil
- }
- if h.receivedSecurePacket {
- return nil, err
- }
- }
- return (&crypto.NullAEAD{}).Open(dst, src, packetNumber, associatedData)
-}
-
-// Seal a message, call LockForSealing() before!
-func (h *CryptoSetup) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
- if h.receivedForwardSecurePacket {
- return h.forwardSecureAEAD.Seal(dst, src, packetNumber, associatedData)
- } else if h.secureAEAD != nil {
- return h.secureAEAD.Seal(dst, src, packetNumber, associatedData)
- } else {
- return (&crypto.NullAEAD{}).Seal(dst, src, packetNumber, associatedData)
- }
-}
-
-func (h *CryptoSetup) isInchoateCHLO(cryptoData map[Tag][]byte) bool {
- scid, ok := cryptoData[TagSCID]
- if !ok || !bytes.Equal(h.scfg.ID, scid) {
- return true
- }
- if _, ok := cryptoData[TagPUBS]; !ok {
- return true
- }
- if err := h.scfg.stkSource.VerifyToken(h.ip, cryptoData[TagSTK]); err != nil {
- utils.Infof("STK invalid: %s", err.Error())
- return true
- }
- return false
-}
-
-func (h *CryptoSetup) handleInchoateCHLO(sni string, chlo []byte, cryptoData map[Tag][]byte) ([]byte, error) {
- if len(chlo) < protocol.ClientHelloMinimumSize {
- return nil, qerr.Error(qerr.CryptoInvalidValueLength, "CHLO too small")
- }
-
- token, err := h.scfg.stkSource.NewToken(h.ip)
- if err != nil {
- return nil, err
- }
-
- replyMap := map[Tag][]byte{
- TagSCFG: h.scfg.Get(),
- TagSTK: token,
- TagSVID: []byte("quic-go"),
- }
-
- if h.scfg.stkSource.VerifyToken(h.ip, cryptoData[TagSTK]) == nil {
- proof, err := h.scfg.Sign(sni, chlo)
- if err != nil {
- return nil, err
- }
-
- commonSetHashes := cryptoData[TagCCS]
- cachedCertsHashes := cryptoData[TagCCRT]
-
- certCompressed, err := h.scfg.GetCertsCompressed(sni, commonSetHashes, cachedCertsHashes)
- if err != nil {
- return nil, err
- }
- // Token was valid, send more details
- replyMap[TagPROF] = proof
- replyMap[TagCERT] = certCompressed
- }
-
- var serverReply bytes.Buffer
- WriteHandshakeMessage(&serverReply, TagREJ, replyMap)
- return serverReply.Bytes(), nil
-}
-
-func (h *CryptoSetup) handleCHLO(sni string, data []byte, cryptoData map[Tag][]byte) ([]byte, error) {
- // We have a CHLO matching our server config, we can continue with the 0-RTT handshake
- sharedSecret, err := h.scfg.kex.CalculateSharedKey(cryptoData[TagPUBS])
- if err != nil {
- return nil, err
- }
-
- h.mutex.Lock()
- defer h.mutex.Unlock()
-
- certUncompressed, err := h.scfg.signer.GetLeafCert(sni)
- if err != nil {
- return nil, err
- }
-
- nonce := make([]byte, 32)
- if _, err = rand.Read(nonce); err != nil {
- return nil, err
- }
-
- h.diversificationNonce = make([]byte, 32)
- if _, err = rand.Read(h.diversificationNonce); err != nil {
- return nil, err
- }
-
- h.secureAEAD, err = h.keyDerivation(
- false,
- sharedSecret,
- cryptoData[TagNONC],
- h.connID,
- data,
- h.scfg.Get(),
- certUncompressed,
- h.diversificationNonce,
- )
- if err != nil {
- return nil, err
- }
-
- // Generate a new curve instance to derive the forward secure key
- var fsNonce bytes.Buffer
- fsNonce.Write(cryptoData[TagNONC])
- fsNonce.Write(nonce)
- ephermalKex := h.keyExchange()
- ephermalSharedSecret, err := ephermalKex.CalculateSharedKey(cryptoData[TagPUBS])
- if err != nil {
- return nil, err
- }
- h.forwardSecureAEAD, err = h.keyDerivation(
- true,
- ephermalSharedSecret,
- fsNonce.Bytes(),
- h.connID,
- data,
- h.scfg.Get(),
- certUncompressed,
- nil,
- )
- if err != nil {
- return nil, err
- }
-
- err = h.connectionParametersManager.SetFromMap(cryptoData)
- if err != nil {
- return nil, err
- }
-
- replyMap := h.connectionParametersManager.GetSHLOMap()
- // add crypto parameters
- replyMap[TagPUBS] = ephermalKex.PublicKey()
- replyMap[TagSNO] = nonce
- replyMap[TagVER] = protocol.SupportedVersionsAsTags
-
- var reply bytes.Buffer
- WriteHandshakeMessage(&reply, TagSHLO, replyMap)
-
- h.aeadChanged <- struct{}{}
-
- return reply.Bytes(), nil
-}
-
-// DiversificationNonce returns a diversification nonce if required in the next packet to be Seal'ed. See LockForSealing()!
-func (h *CryptoSetup) DiversificationNonce() []byte {
- if h.receivedForwardSecurePacket || h.secureAEAD == nil {
- return nil
- }
- return h.diversificationNonce
-}
-
-// LockForSealing should be called before Seal(). It is needed so that diversification nonces can be obtained before packets are sealed, and the AEADs are not changed in the meantime.
-func (h *CryptoSetup) LockForSealing() {
- h.mutex.RLock()
-}
-
-// UnlockForSealing should be called after Seal() is complete, see LockForSealing().
-func (h *CryptoSetup) UnlockForSealing() {
- h.mutex.RUnlock()
-}
-
-// HandshakeComplete returns true after the first forward secure packet was received form the client.
-func (h *CryptoSetup) HandshakeComplete() bool {
- return h.receivedForwardSecurePacket
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/packet_packer.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/packet_packer.go
deleted file mode 100644
index 359fa73..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/packet_packer.go
+++ /dev/null
@@ -1,203 +0,0 @@
-package quic
-
-import (
- "bytes"
- "errors"
- "fmt"
-
- "github.com/lucas-clemente/quic-go/frames"
- "github.com/lucas-clemente/quic-go/handshake"
- "github.com/lucas-clemente/quic-go/protocol"
-)
-
-type packedPacket struct {
- number protocol.PacketNumber
- raw []byte
- frames []frames.Frame
-}
-
-type packetPacker struct {
- connectionID protocol.ConnectionID
- version protocol.VersionNumber
- cryptoSetup *handshake.CryptoSetup
-
- packetNumberGenerator *packetNumberGenerator
-
- connectionParametersManager *handshake.ConnectionParametersManager
-
- streamFramer *streamFramer
- controlFrames []frames.Frame
-}
-
-func newPacketPacker(connectionID protocol.ConnectionID, cryptoSetup *handshake.CryptoSetup, connectionParametersHandler *handshake.ConnectionParametersManager, streamFramer *streamFramer, version protocol.VersionNumber) *packetPacker {
- return &packetPacker{
- cryptoSetup: cryptoSetup,
- connectionID: connectionID,
- connectionParametersManager: connectionParametersHandler,
- version: version,
- streamFramer: streamFramer,
- packetNumberGenerator: newPacketNumberGenerator(protocol.SkipPacketAveragePeriodLength),
- }
-}
-
-func (p *packetPacker) PackConnectionClose(frame *frames.ConnectionCloseFrame, leastUnacked protocol.PacketNumber) (*packedPacket, error) {
- return p.packPacket(nil, []frames.Frame{frame}, leastUnacked, true, false)
-}
-
-func (p *packetPacker) PackPacket(stopWaitingFrame *frames.StopWaitingFrame, controlFrames []frames.Frame, leastUnacked protocol.PacketNumber, maySendOnlyAck bool) (*packedPacket, error) {
- return p.packPacket(stopWaitingFrame, controlFrames, leastUnacked, false, maySendOnlyAck)
-}
-
-func (p *packetPacker) packPacket(stopWaitingFrame *frames.StopWaitingFrame, controlFrames []frames.Frame, leastUnacked protocol.PacketNumber, onlySendOneControlFrame, maySendOnlyAck bool) (*packedPacket, error) {
- if len(controlFrames) > 0 {
- p.controlFrames = append(p.controlFrames, controlFrames...)
- }
-
- currentPacketNumber := p.packetNumberGenerator.Peek()
-
- // cryptoSetup needs to be locked here, so that the AEADs are not changed between
- // calling DiversificationNonce() and Seal().
- p.cryptoSetup.LockForSealing()
- defer p.cryptoSetup.UnlockForSealing()
-
- packetNumberLen := protocol.GetPacketNumberLengthForPublicHeader(currentPacketNumber, leastUnacked)
- responsePublicHeader := &PublicHeader{
- ConnectionID: p.connectionID,
- PacketNumber: currentPacketNumber,
- PacketNumberLen: packetNumberLen,
- TruncateConnectionID: p.connectionParametersManager.TruncateConnectionID(),
- DiversificationNonce: p.cryptoSetup.DiversificationNonce(),
- }
-
- publicHeaderLength, err := responsePublicHeader.GetLength()
- if err != nil {
- return nil, err
- }
-
- if stopWaitingFrame != nil {
- stopWaitingFrame.PacketNumber = currentPacketNumber
- stopWaitingFrame.PacketNumberLen = packetNumberLen
- }
-
- var payloadFrames []frames.Frame
- if onlySendOneControlFrame {
- payloadFrames = []frames.Frame{controlFrames[0]}
- } else {
- payloadFrames, err = p.composeNextPacket(stopWaitingFrame, publicHeaderLength)
- if err != nil {
- return nil, err
- }
- }
-
- // Check if we have enough frames to send
- if len(payloadFrames) == 0 {
- return nil, nil
- }
- // Don't send out packets that only contain a StopWaitingFrame
- if !onlySendOneControlFrame && len(payloadFrames) == 1 && stopWaitingFrame != nil {
- return nil, nil
- }
- // Don't send out packets that only contain an ACK (plus optional STOP_WAITING), if requested
- if !maySendOnlyAck {
- if len(payloadFrames) == 1 {
- if _, ok := payloadFrames[0].(*frames.AckFrame); ok {
- return nil, nil
- }
- } else if len(payloadFrames) == 2 && stopWaitingFrame != nil {
- if _, ok := payloadFrames[1].(*frames.AckFrame); ok {
- return nil, nil
- }
- }
- }
-
- raw := getPacketBuffer()
- buffer := bytes.NewBuffer(raw)
-
- if err = responsePublicHeader.WritePublicHeader(buffer, p.version); err != nil {
- return nil, err
- }
-
- payloadStartIndex := buffer.Len()
-
- for _, frame := range payloadFrames {
- err := frame.Write(buffer, p.version)
- if err != nil {
- return nil, err
- }
- }
-
- if protocol.ByteCount(buffer.Len()+12) > protocol.MaxPacketSize {
- return nil, errors.New("PacketPacker BUG: packet too large")
- }
-
- raw = raw[0:buffer.Len()]
- p.cryptoSetup.Seal(raw[payloadStartIndex:payloadStartIndex], raw[payloadStartIndex:], currentPacketNumber, raw[:payloadStartIndex])
- raw = raw[0 : buffer.Len()+12]
-
- num := p.packetNumberGenerator.Pop()
- if num != currentPacketNumber {
- return nil, errors.New("PacketPacker BUG: Peeked and Popped packet numbers do not match.")
- }
-
- return &packedPacket{
- number: currentPacketNumber,
- raw: raw,
- frames: payloadFrames,
- }, nil
-}
-
-func (p *packetPacker) composeNextPacket(stopWaitingFrame *frames.StopWaitingFrame, publicHeaderLength protocol.ByteCount) ([]frames.Frame, error) {
- var payloadLength protocol.ByteCount
- var payloadFrames []frames.Frame
-
- maxFrameSize := protocol.MaxFrameAndPublicHeaderSize - publicHeaderLength
-
- if stopWaitingFrame != nil {
- payloadFrames = append(payloadFrames, stopWaitingFrame)
- minLength, err := stopWaitingFrame.MinLength(p.version)
- if err != nil {
- return nil, err
- }
- payloadLength += minLength
- }
-
- for len(p.controlFrames) > 0 {
- frame := p.controlFrames[len(p.controlFrames)-1]
- minLength, _ := frame.MinLength(p.version) // controlFrames does not contain any StopWaitingFrames. So it will *never* return an error
- if payloadLength+minLength > maxFrameSize {
- break
- }
- payloadFrames = append(payloadFrames, frame)
- payloadLength += minLength
- p.controlFrames = p.controlFrames[:len(p.controlFrames)-1]
- }
-
- if payloadLength > maxFrameSize {
- return nil, fmt.Errorf("Packet Packer BUG: packet payload (%d) too large (%d)", payloadLength, maxFrameSize)
- }
-
- // temporarily increase the maxFrameSize by 2 bytes
- // this leads to a properly sized packet in all cases, since we do all the packet length calculations with StreamFrames that have the DataLen set
- // however, for the last StreamFrame in the packet, we can omit the DataLen, thus saving 2 bytes and yielding a packet of exactly the correct size
- maxFrameSize += 2
-
- fs := p.streamFramer.PopStreamFrames(maxFrameSize - payloadLength)
- if len(fs) != 0 {
- fs[len(fs)-1].DataLenPresent = false
- }
-
- // TODO: Simplify
- for _, f := range fs {
- payloadFrames = append(payloadFrames, f)
- }
-
- for b := p.streamFramer.PopBlockedFrame(); b != nil; b = p.streamFramer.PopBlockedFrame() {
- p.controlFrames = append(p.controlFrames, b)
- }
-
- return payloadFrames, nil
-}
-
-func (p *packetPacker) QueueControlFrameForNextPacket(f frames.Frame) {
- p.controlFrames = append(p.controlFrames, f)
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/protocol/server_parameters.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/protocol/server_parameters.go
deleted file mode 100644
index 99894a0..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/protocol/server_parameters.go
+++ /dev/null
@@ -1,90 +0,0 @@
-package protocol
-
-import "time"
-
-// DefaultMaxCongestionWindow is the default for the max congestion window
-const DefaultMaxCongestionWindow PacketNumber = 1000
-
-// InitialCongestionWindow is the initial congestion window in QUIC packets
-const InitialCongestionWindow PacketNumber = 32
-
-// MaxUndecryptablePackets limits the number of undecryptable packets that a
-// session queues for later until it sends a public reset.
-const MaxUndecryptablePackets = 10
-
-// AckSendDelay is the maximal time delay applied to packets containing only ACKs
-const AckSendDelay = 5 * time.Millisecond
-
-// ReceiveStreamFlowControlWindow is the stream-level flow control window for receiving data
-// This is the value that Google servers are using
-const ReceiveStreamFlowControlWindow ByteCount = (1 << 20) // 1 MB
-
-// ReceiveConnectionFlowControlWindow is the stream-level flow control window for receiving data
-// This is the value that Google servers are using
-const ReceiveConnectionFlowControlWindow ByteCount = (1 << 20) * 1.5 // 1.5 MB
-
-// MaxStreamsPerConnection is the maximum value accepted for the number of streams per connection
-const MaxStreamsPerConnection = 100
-
-// MaxIncomingDynamicStreams is the maximum value accepted for the incoming number of dynamic streams per connection
-const MaxIncomingDynamicStreams = 100
-
-// MaxStreamsMultiplier is the slack the client is allowed for the maximum number of streams per connection, needed e.g. when packets are out of order or dropped. The minimum of this procentual increase and the absolute increment specified by MaxStreamsMinimumIncrement is used.
-const MaxStreamsMultiplier = 1.1
-
-// MaxStreamsMinimumIncrement is the slack the client is allowed for the maximum number of streams per connection, needed e.g. when packets are out of order or dropped. The minimum of this absolute increment and the procentual increase specified by MaxStreamsMultiplier is used.
-const MaxStreamsMinimumIncrement = 10
-
-// MaxNewStreamIDDelta is the maximum difference between and a newly opened Stream and the highest StreamID that a client has ever opened
-// note that the number of streams is half this value, since the client can only open streams with open StreamID
-const MaxNewStreamIDDelta = 4 * MaxStreamsPerConnection
-
-// MaxSessionUnprocessedPackets is the max number of packets stored in each session that are not yet processed.
-const MaxSessionUnprocessedPackets = DefaultMaxCongestionWindow
-
-// RetransmissionThreshold + 1 is the number of times a packet has to be NACKed so that it gets retransmitted
-const RetransmissionThreshold = 3
-
-// SkipPacketAveragePeriodLength is the average period length in which one packet number is skipped to prevent an Optimistic ACK attack
-const SkipPacketAveragePeriodLength PacketNumber = 500
-
-// MaxTrackedSkippedPackets is the maximum number of skipped packet numbers the SentPacketHandler keep track of for Optimistic ACK attack mitigation
-const MaxTrackedSkippedPackets = 10
-
-// STKExpiryTimeSec is the valid time of a source address token in seconds
-const STKExpiryTimeSec = 24 * 60 * 60
-
-// MaxTrackedSentPackets is maximum number of sent packets saved for either later retransmission or entropy calculation
-const MaxTrackedSentPackets = 2 * DefaultMaxCongestionWindow
-
-// MaxTrackedReceivedPackets is the maximum number of received packets saved for doing the entropy calculations
-const MaxTrackedReceivedPackets = 2 * DefaultMaxCongestionWindow
-
-// MaxStreamFrameSorterGaps is the maximum number of gaps between received StreamFrames
-// prevents DOS attacks against the streamFrameSorter
-const MaxStreamFrameSorterGaps = 1000
-
-// CryptoMaxParams is the upper limit for the number of parameters in a crypto message.
-// Value taken from Chrome.
-const CryptoMaxParams = 128
-
-// CryptoParameterMaxLength is the upper limit for the length of a parameter in a crypto message.
-const CryptoParameterMaxLength = 2000
-
-// EphermalKeyLifetime is the lifetime of the ephermal key during the handshake, see handshake.getEphermalKEX.
-const EphermalKeyLifetime = time.Minute
-
-// InitialIdleTimeout is the timeout before the handshake succeeds.
-const InitialIdleTimeout = 5 * time.Second
-
-// DefaultIdleTimeout is the default idle timeout.
-const DefaultIdleTimeout = 30 * time.Second
-
-// MaxIdleTimeout is the maximum idle timeout that can be negotiated.
-const MaxIdleTimeout = 1 * time.Minute
-
-// MaxTimeForCryptoHandshake is the default timeout for a connection until the crypto handshake succeeds.
-const MaxTimeForCryptoHandshake = 10 * time.Second
-
-// NumCachedCertificates is the number of cached compressed certificate chains, each taking ~1K space
-const NumCachedCertificates = 128
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/protocol/version.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/protocol/version.go
deleted file mode 100644
index cd0cd47..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/protocol/version.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package protocol
-
-import (
- "bytes"
- "encoding/binary"
- "strconv"
-)
-
-// VersionNumber is a version number as int
-type VersionNumber int
-
-// The version numbers, making grepping easier
-const (
- Version34 VersionNumber = 34 + iota
- Version35
- Version36
- VersionWhatever = 0 // for when the version doesn't matter
-)
-
-// SupportedVersions lists the versions that the server supports
-var SupportedVersions = []VersionNumber{
- Version34, Version35, Version36,
-}
-
-// SupportedVersionsAsTags is needed for the SHLO crypto message
-var SupportedVersionsAsTags []byte
-
-// SupportedVersionsAsString is needed for the Alt-Scv HTTP header
-var SupportedVersionsAsString string
-
-// VersionNumberToTag maps version numbers ('32') to tags ('Q032')
-func VersionNumberToTag(vn VersionNumber) uint32 {
- v := uint32(vn)
- return 'Q' + ((v/100%10)+'0')<<8 + ((v/10%10)+'0')<<16 + ((v%10)+'0')<<24
-}
-
-// VersionTagToNumber is built from VersionNumberToTag in init()
-func VersionTagToNumber(v uint32) VersionNumber {
- return VersionNumber(((v>>8)&0xff-'0')*100 + ((v>>16)&0xff-'0')*10 + ((v>>24)&0xff - '0'))
-}
-
-// IsSupportedVersion returns true if the server supports this version
-func IsSupportedVersion(v VersionNumber) bool {
- for _, t := range SupportedVersions {
- if t == v {
- return true
- }
- }
- return false
-}
-
-func init() {
- var b bytes.Buffer
- for _, v := range SupportedVersions {
- s := make([]byte, 4)
- binary.LittleEndian.PutUint32(s, VersionNumberToTag(v))
- b.Write(s)
- }
- SupportedVersionsAsTags = b.Bytes()
-
- for i := len(SupportedVersions) - 1; i >= 0; i-- {
- SupportedVersionsAsString += strconv.Itoa(int(SupportedVersions[i]))
- if i != 0 {
- SupportedVersionsAsString += ","
- }
- }
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/public_header.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/public_header.go
deleted file mode 100644
index 475c1b6..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/public_header.go
+++ /dev/null
@@ -1,178 +0,0 @@
-package quic
-
-import (
- "bytes"
- "errors"
- "io"
-
- "github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
-)
-
-var (
- errPacketNumberLenNotSet = errors.New("PublicHeader: PacketNumberLen not set")
- errResetAndVersionFlagSet = errors.New("PublicHeader: Reset Flag and Version Flag should not be set at the same time")
- errReceivedTruncatedConnectionID = qerr.Error(qerr.InvalidPacketHeader, "receiving packets with truncated ConnectionID is not supported")
- errInvalidConnectionID = qerr.Error(qerr.InvalidPacketHeader, "connection ID cannot be 0")
- errGetLengthOnlyForRegularPackets = errors.New("PublicHeader: GetLength can only be called for regular packets")
-)
-
-// The PublicHeader of a QUIC packet
-type PublicHeader struct {
- Raw []byte
- ConnectionID protocol.ConnectionID
- VersionFlag bool
- ResetFlag bool
- TruncateConnectionID bool
- PacketNumberLen protocol.PacketNumberLen
- PacketNumber protocol.PacketNumber
- VersionNumber protocol.VersionNumber
- DiversificationNonce []byte
-}
-
-// WritePublicHeader writes a public header
-func (h *PublicHeader) WritePublicHeader(b *bytes.Buffer, version protocol.VersionNumber) error {
- publicFlagByte := uint8(0x00)
- if h.VersionFlag && h.ResetFlag {
- return errResetAndVersionFlagSet
- }
- if h.VersionFlag {
- publicFlagByte |= 0x01
- }
- if h.ResetFlag {
- publicFlagByte |= 0x02
- }
- if !h.TruncateConnectionID {
- publicFlagByte |= 0x08
- }
-
- if len(h.DiversificationNonce) > 0 {
- if len(h.DiversificationNonce) != 32 {
- return errors.New("invalid diversification nonce length")
- }
- publicFlagByte |= 0x04
- }
-
- if !h.ResetFlag && !h.VersionFlag {
- switch h.PacketNumberLen {
- case protocol.PacketNumberLen1:
- publicFlagByte |= 0x00
- case protocol.PacketNumberLen2:
- publicFlagByte |= 0x10
- case protocol.PacketNumberLen4:
- publicFlagByte |= 0x20
- case protocol.PacketNumberLen6:
- publicFlagByte |= 0x30
- }
- }
-
- b.WriteByte(publicFlagByte)
-
- if !h.TruncateConnectionID {
- utils.WriteUint64(b, uint64(h.ConnectionID))
- }
-
- if len(h.DiversificationNonce) > 0 {
- b.Write(h.DiversificationNonce)
- }
-
- if !h.ResetFlag && !h.VersionFlag {
- switch h.PacketNumberLen {
- case protocol.PacketNumberLen1:
- b.WriteByte(uint8(h.PacketNumber))
- case protocol.PacketNumberLen2:
- utils.WriteUint16(b, uint16(h.PacketNumber))
- case protocol.PacketNumberLen4:
- utils.WriteUint32(b, uint32(h.PacketNumber))
- case protocol.PacketNumberLen6:
- utils.WriteUint48(b, uint64(h.PacketNumber))
- default:
- return errPacketNumberLenNotSet
- }
- }
-
- return nil
-}
-
-// ParsePublicHeader parses a QUIC packet's public header
-func ParsePublicHeader(b io.ByteReader) (*PublicHeader, error) {
- header := &PublicHeader{}
-
- // First byte
- publicFlagByte, err := b.ReadByte()
- if err != nil {
- return nil, err
- }
- header.VersionFlag = publicFlagByte&0x01 > 0
- header.ResetFlag = publicFlagByte&0x02 > 0
-
- // TODO: activate this check once Chrome sends the correct value
- // see https://github.com/lucas-clemente/quic-go/issues/232
- // if publicFlagByte&0x04 > 0 {
- // return nil, errors.New("diversification nonces should only be sent by servers")
- // }
-
- if publicFlagByte&0x08 == 0 {
- return nil, errReceivedTruncatedConnectionID
- }
-
- switch publicFlagByte & 0x30 {
- case 0x30:
- header.PacketNumberLen = protocol.PacketNumberLen6
- case 0x20:
- header.PacketNumberLen = protocol.PacketNumberLen4
- case 0x10:
- header.PacketNumberLen = protocol.PacketNumberLen2
- case 0x00:
- header.PacketNumberLen = protocol.PacketNumberLen1
- }
-
- // Connection ID
- connID, err := utils.ReadUint64(b)
- if err != nil {
- return nil, err
- }
- header.ConnectionID = protocol.ConnectionID(connID)
- if header.ConnectionID == 0 {
- return nil, errInvalidConnectionID
- }
-
- // Version (optional)
- if header.VersionFlag {
- var versionTag uint32
- versionTag, err = utils.ReadUint32(b)
- if err != nil {
- return nil, err
- }
- header.VersionNumber = protocol.VersionTagToNumber(versionTag)
- }
-
- // Packet number
- packetNumber, err := utils.ReadUintN(b, uint8(header.PacketNumberLen))
- if err != nil {
- return nil, err
- }
- header.PacketNumber = protocol.PacketNumber(packetNumber)
-
- return header, nil
-}
-
-// GetLength gets the length of the publicHeader in bytes
-// can only be called for regular packets
-func (h *PublicHeader) GetLength() (protocol.ByteCount, error) {
- if h.VersionFlag || h.ResetFlag {
- return 0, errGetLengthOnlyForRegularPackets
- }
-
- length := protocol.ByteCount(1) // 1 byte for public flags
- if h.PacketNumberLen != protocol.PacketNumberLen1 && h.PacketNumberLen != protocol.PacketNumberLen2 && h.PacketNumberLen != protocol.PacketNumberLen4 && h.PacketNumberLen != protocol.PacketNumberLen6 {
- return 0, errPacketNumberLenNotSet
- }
- if !h.TruncateConnectionID {
- length += 8 // 8 bytes for the connection ID
- }
- length += protocol.ByteCount(len(h.DiversificationNonce))
- length += protocol.ByteCount(h.PacketNumberLen)
- return length, nil
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/public_reset.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/public_reset.go
deleted file mode 100644
index 7cceb2e..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/public_reset.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package quic
-
-import (
- "bytes"
-
- "github.com/lucas-clemente/quic-go/handshake"
- "github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
-)
-
-func writePublicReset(connectionID protocol.ConnectionID, rejectedPacketNumber protocol.PacketNumber, nonceProof uint64) []byte {
- b := &bytes.Buffer{}
- b.WriteByte(0x0a)
- utils.WriteUint64(b, uint64(connectionID))
- utils.WriteUint32(b, uint32(handshake.TagPRST))
- utils.WriteUint32(b, 2)
- utils.WriteUint32(b, uint32(handshake.TagRNON))
- utils.WriteUint32(b, 8)
- utils.WriteUint32(b, uint32(handshake.TagRSEQ))
- utils.WriteUint32(b, 16)
- utils.WriteUint64(b, nonceProof)
- utils.WriteUint64(b, uint64(rejectedPacketNumber))
- return b.Bytes()
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/server.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/server.go
deleted file mode 100644
index 54ccc6d..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/server.go
+++ /dev/null
@@ -1,205 +0,0 @@
-package quic
-
-import (
- "bytes"
- "crypto/tls"
- "net"
- "strings"
- "sync"
- "time"
-
- "github.com/lucas-clemente/quic-go/crypto"
- "github.com/lucas-clemente/quic-go/handshake"
- "github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
-)
-
-// packetHandler handles packets
-type packetHandler interface {
- handlePacket(*receivedPacket)
- run()
- Close(error) error
-}
-
-// A Server of QUIC
-type Server struct {
- addr *net.UDPAddr
-
- conn *net.UDPConn
- connMutex sync.Mutex
-
- signer crypto.Signer
- scfg *handshake.ServerConfig
-
- sessions map[protocol.ConnectionID]packetHandler
- sessionsMutex sync.RWMutex
-
- streamCallback StreamCallback
-
- newSession func(conn connection, v protocol.VersionNumber, connectionID protocol.ConnectionID, sCfg *handshake.ServerConfig, streamCallback StreamCallback, closeCallback closeCallback) (packetHandler, error)
-}
-
-// NewServer makes a new server
-func NewServer(addr string, tlsConfig *tls.Config, cb StreamCallback) (*Server, error) {
- signer, err := crypto.NewProofSource(tlsConfig)
- if err != nil {
- return nil, err
- }
-
- kex, err := crypto.NewCurve25519KEX()
- if err != nil {
- return nil, err
- }
- scfg, err := handshake.NewServerConfig(kex, signer)
- if err != nil {
- return nil, err
- }
-
- udpAddr, err := net.ResolveUDPAddr("udp", addr)
- if err != nil {
- return nil, err
- }
-
- return &Server{
- addr: udpAddr,
- signer: signer,
- scfg: scfg,
- streamCallback: cb,
- sessions: map[protocol.ConnectionID]packetHandler{},
- newSession: newSession,
- }, nil
-}
-
-// ListenAndServe listens and serves a connection
-func (s *Server) ListenAndServe() error {
- conn, err := net.ListenUDP("udp", s.addr)
- if err != nil {
- return err
- }
- return s.Serve(conn)
-}
-
-// Serve on an existing UDP connection.
-func (s *Server) Serve(conn *net.UDPConn) error {
- s.connMutex.Lock()
- s.conn = conn
- s.connMutex.Unlock()
-
- for {
- data := getPacketBuffer()
- data = data[:protocol.MaxPacketSize]
- n, remoteAddr, err := conn.ReadFromUDP(data)
- if err != nil {
- if strings.HasSuffix(err.Error(), "use of closed network connection") {
- return nil
- }
- return err
- }
- data = data[:n]
- if err := s.handlePacket(conn, remoteAddr, data); err != nil {
- utils.Errorf("error handling packet: %s", err.Error())
- }
- }
-}
-
-// Close the server
-func (s *Server) Close() error {
- s.sessionsMutex.Lock()
- for _, session := range s.sessions {
- if session != nil {
- s.sessionsMutex.Unlock()
- _ = session.Close(nil)
- s.sessionsMutex.Lock()
- }
- }
- s.sessionsMutex.Unlock()
-
- s.connMutex.Lock()
- conn := s.conn
- s.conn = nil
- s.connMutex.Unlock()
-
- if conn == nil {
- return nil
- }
- return conn.Close()
-}
-
-func (s *Server) handlePacket(conn *net.UDPConn, remoteAddr *net.UDPAddr, packet []byte) error {
- if protocol.ByteCount(len(packet)) > protocol.MaxPacketSize {
- return qerr.PacketTooLarge
- }
-
- rcvTime := time.Now()
-
- r := bytes.NewReader(packet)
-
- hdr, err := ParsePublicHeader(r)
- if err != nil {
- return qerr.Error(qerr.InvalidPacketHeader, err.Error())
- }
- hdr.Raw = packet[:len(packet)-r.Len()]
-
- // Send Version Negotiation Packet if the client is speaking a different protocol version
- if hdr.VersionFlag && !protocol.IsSupportedVersion(hdr.VersionNumber) {
- utils.Infof("Client offered version %d, sending VersionNegotiationPacket", hdr.VersionNumber)
- _, err = conn.WriteToUDP(composeVersionNegotiation(hdr.ConnectionID), remoteAddr)
- return err
- }
-
- s.sessionsMutex.RLock()
- session, ok := s.sessions[hdr.ConnectionID]
- s.sessionsMutex.RUnlock()
-
- if !ok {
- utils.Infof("Serving new connection: %x, version %d from %v", hdr.ConnectionID, hdr.VersionNumber, remoteAddr)
- session, err = s.newSession(
- &udpConn{conn: conn, currentAddr: remoteAddr},
- hdr.VersionNumber,
- hdr.ConnectionID,
- s.scfg,
- s.streamCallback,
- s.closeCallback,
- )
- if err != nil {
- return err
- }
- go session.run()
- s.sessionsMutex.Lock()
- s.sessions[hdr.ConnectionID] = session
- s.sessionsMutex.Unlock()
- }
- if session == nil {
- // Late packet for closed session
- return nil
- }
- session.handlePacket(&receivedPacket{
- remoteAddr: remoteAddr,
- publicHeader: hdr,
- data: packet[len(packet)-r.Len():],
- rcvTime: rcvTime,
- })
- return nil
-}
-
-func (s *Server) closeCallback(id protocol.ConnectionID) {
- s.sessionsMutex.Lock()
- s.sessions[id] = nil
- s.sessionsMutex.Unlock()
-}
-
-func composeVersionNegotiation(connectionID protocol.ConnectionID) []byte {
- fullReply := &bytes.Buffer{}
- responsePublicHeader := PublicHeader{
- ConnectionID: connectionID,
- PacketNumber: 1,
- VersionFlag: true,
- }
- err := responsePublicHeader.WritePublicHeader(fullReply, protocol.Version35)
- if err != nil {
- utils.Errorf("error composing version negotiation packet: %s", err.Error())
- }
- fullReply.Write(protocol.SupportedVersionsAsTags)
- return fullReply.Bytes()
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/session.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/session.go
deleted file mode 100644
index 2f75299..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/session.go
+++ /dev/null
@@ -1,673 +0,0 @@
-package quic
-
-import (
- "errors"
- "fmt"
- "net"
- "runtime"
- "sync/atomic"
- "time"
-
- "github.com/lucas-clemente/quic-go/ackhandler"
- "github.com/lucas-clemente/quic-go/flowcontrol"
- "github.com/lucas-clemente/quic-go/frames"
- "github.com/lucas-clemente/quic-go/handshake"
- "github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
-)
-
-type unpacker interface {
- Unpack(publicHeaderBinary []byte, hdr *PublicHeader, data []byte) (*unpackedPacket, error)
-}
-
-type receivedPacket struct {
- remoteAddr interface{}
- publicHeader *PublicHeader
- data []byte
- rcvTime time.Time
-}
-
-var (
- errRstStreamOnInvalidStream = errors.New("RST_STREAM received for unknown stream")
- errWindowUpdateOnClosedStream = errors.New("WINDOW_UPDATE received for an already closed stream")
-)
-
-// StreamCallback gets a stream frame and returns a reply frame
-type StreamCallback func(*Session, utils.Stream)
-
-// closeCallback is called when a session is closed
-type closeCallback func(id protocol.ConnectionID)
-
-// A Session is a QUIC session
-type Session struct {
- connectionID protocol.ConnectionID
- version protocol.VersionNumber
-
- streamCallback StreamCallback
- closeCallback closeCallback
-
- conn connection
-
- streamsMap *streamsMap
-
- sentPacketHandler ackhandler.SentPacketHandler
- receivedPacketHandler ackhandler.ReceivedPacketHandler
- streamFramer *streamFramer
-
- flowControlManager flowcontrol.FlowControlManager
-
- unpacker unpacker
- packer *packetPacker
-
- cryptoSetup *handshake.CryptoSetup
-
- receivedPackets chan *receivedPacket
- sendingScheduled chan struct{}
- // closeChan is used to notify the run loop that it should terminate.
- // If the value is not nil, the error is sent as a CONNECTION_CLOSE.
- closeChan chan *qerr.QuicError
- closed uint32 // atomic bool
-
- undecryptablePackets []*receivedPacket
- aeadChanged chan struct{}
-
- delayedAckOriginTime time.Time
-
- connectionParametersManager *handshake.ConnectionParametersManager
-
- lastRcvdPacketNumber protocol.PacketNumber
- // Used to calculate the next packet number from the truncated wire
- // representation, and sent back in public reset packets
- largestRcvdPacketNumber protocol.PacketNumber
-
- sessionCreationTime time.Time
- lastNetworkActivityTime time.Time
-
- timer *time.Timer
- currentDeadline time.Time
- timerRead bool
-}
-
-// newSession makes a new session
-func newSession(conn connection, v protocol.VersionNumber, connectionID protocol.ConnectionID, sCfg *handshake.ServerConfig, streamCallback StreamCallback, closeCallback closeCallback) (packetHandler, error) {
- connectionParametersManager := handshake.NewConnectionParamatersManager()
- flowControlManager := flowcontrol.NewFlowControlManager(connectionParametersManager)
-
- var sentPacketHandler ackhandler.SentPacketHandler
- var receivedPacketHandler ackhandler.ReceivedPacketHandler
-
- sentPacketHandler = ackhandler.NewSentPacketHandler()
- receivedPacketHandler = ackhandler.NewReceivedPacketHandler()
-
- now := time.Now()
- session := &Session{
- conn: conn,
- connectionID: connectionID,
- version: v,
-
- streamCallback: streamCallback,
- closeCallback: closeCallback,
-
- connectionParametersManager: connectionParametersManager,
- sentPacketHandler: sentPacketHandler,
- receivedPacketHandler: receivedPacketHandler,
- flowControlManager: flowControlManager,
-
- receivedPackets: make(chan *receivedPacket, protocol.MaxSessionUnprocessedPackets),
- closeChan: make(chan *qerr.QuicError, 1),
- sendingScheduled: make(chan struct{}, 1),
- undecryptablePackets: make([]*receivedPacket, 0, protocol.MaxUndecryptablePackets),
- aeadChanged: make(chan struct{}, 1),
-
- timer: time.NewTimer(0),
- lastNetworkActivityTime: now,
- sessionCreationTime: now,
- }
-
- session.streamsMap = newStreamsMap(session.newStream)
-
- cryptoStream, _ := session.GetOrOpenStream(1)
- var err error
- session.cryptoSetup, err = handshake.NewCryptoSetup(connectionID, conn.RemoteAddr().IP, v, sCfg, cryptoStream, session.connectionParametersManager, session.aeadChanged)
- if err != nil {
- return nil, err
- }
-
- session.streamFramer = newStreamFramer(session.streamsMap, flowControlManager)
- session.packer = newPacketPacker(connectionID, session.cryptoSetup, session.connectionParametersManager, session.streamFramer, v)
- session.unpacker = &packetUnpacker{aead: session.cryptoSetup, version: v}
-
- return session, err
-}
-
-// run the session main loop
-func (s *Session) run() {
- // Start the crypto stream handler
- go func() {
- if err := s.cryptoSetup.HandleCryptoStream(); err != nil {
- s.Close(err)
- }
- }()
-
- for {
- // Close immediately if requested
- select {
- case errForConnClose := <-s.closeChan:
- if errForConnClose != nil {
- s.sendConnectionClose(errForConnClose)
- }
- return
- default:
- }
-
- s.maybeResetTimer()
-
- var err error
- select {
- case errForConnClose := <-s.closeChan:
- if errForConnClose != nil {
- s.sendConnectionClose(errForConnClose)
- }
- return
- case <-s.timer.C:
- s.timerRead = true
- // We do all the interesting stuff after the switch statement, so
- // nothing to see here.
- case <-s.sendingScheduled:
- // We do all the interesting stuff after the switch statement, so
- // nothing to see here.
- case p := <-s.receivedPackets:
- err = s.handlePacketImpl(p)
- if qErr, ok := err.(*qerr.QuicError); ok && qErr.ErrorCode == qerr.DecryptionFailure {
- s.tryQueueingUndecryptablePacket(p)
- continue
- }
- // This is a bit unclean, but works properly, since the packet always
- // begins with the public header and we never copy it.
- putPacketBuffer(p.publicHeader.Raw)
- if s.delayedAckOriginTime.IsZero() {
- s.delayedAckOriginTime = p.rcvTime
- }
- case <-s.aeadChanged:
- s.tryDecryptingQueuedPackets()
- }
-
- if err != nil {
- s.Close(err)
- }
-
- if err := s.sendPacket(); err != nil {
- s.Close(err)
- }
- if time.Now().Sub(s.lastNetworkActivityTime) >= s.idleTimeout() {
- s.Close(qerr.Error(qerr.NetworkIdleTimeout, "No recent network activity."))
- }
- if !s.cryptoSetup.HandshakeComplete() && time.Now().Sub(s.sessionCreationTime) >= protocol.MaxTimeForCryptoHandshake {
- s.Close(qerr.Error(qerr.NetworkIdleTimeout, "Crypto handshake did not complete in time."))
- }
- s.garbageCollectStreams()
- }
-}
-
-func (s *Session) maybeResetTimer() {
- nextDeadline := s.lastNetworkActivityTime.Add(s.idleTimeout())
-
- if !s.delayedAckOriginTime.IsZero() {
- nextDeadline = utils.MinTime(nextDeadline, s.delayedAckOriginTime.Add(protocol.AckSendDelay))
- }
- if rtoTime := s.sentPacketHandler.TimeOfFirstRTO(); !rtoTime.IsZero() {
- nextDeadline = utils.MinTime(nextDeadline, rtoTime)
- }
- if !s.cryptoSetup.HandshakeComplete() {
- handshakeDeadline := s.sessionCreationTime.Add(protocol.MaxTimeForCryptoHandshake)
- nextDeadline = utils.MinTime(nextDeadline, handshakeDeadline)
- }
-
- if nextDeadline.Equal(s.currentDeadline) {
- // No need to reset the timer
- return
- }
-
- // We need to drain the timer if the value from its channel was not read yet.
- // See https://groups.google.com/forum/#!topic/golang-dev/c9UUfASVPoU
- if !s.timer.Stop() && !s.timerRead {
- <-s.timer.C
- }
- s.timer.Reset(nextDeadline.Sub(time.Now()))
-
- s.timerRead = false
- s.currentDeadline = nextDeadline
-}
-
-func (s *Session) idleTimeout() time.Duration {
- if s.cryptoSetup.HandshakeComplete() {
- return s.connectionParametersManager.GetIdleConnectionStateLifetime()
- }
- return protocol.InitialIdleTimeout
-}
-
-func (s *Session) handlePacketImpl(p *receivedPacket) error {
- if p.rcvTime.IsZero() {
- // To simplify testing
- p.rcvTime = time.Now()
- }
-
- s.lastNetworkActivityTime = p.rcvTime
- hdr := p.publicHeader
- data := p.data
-
- // Calculate packet number
- hdr.PacketNumber = protocol.InferPacketNumber(
- hdr.PacketNumberLen,
- s.largestRcvdPacketNumber,
- hdr.PacketNumber,
- )
- if utils.Debug() {
- utils.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID)
- }
-
- // TODO: Only do this after authenticating
- s.conn.setCurrentRemoteAddr(p.remoteAddr)
-
- packet, err := s.unpacker.Unpack(hdr.Raw, hdr, data)
- if err != nil {
- return err
- }
-
- s.lastRcvdPacketNumber = hdr.PacketNumber
- // Only do this after decrypting, so we are sure the packet is not attacker-controlled
- s.largestRcvdPacketNumber = utils.MaxPacketNumber(s.largestRcvdPacketNumber, hdr.PacketNumber)
-
- err = s.receivedPacketHandler.ReceivedPacket(hdr.PacketNumber)
- // ignore duplicate packets
- if err == ackhandler.ErrDuplicatePacket {
- utils.Infof("Ignoring packet 0x%x due to ErrDuplicatePacket", hdr.PacketNumber)
- return nil
- }
- // ignore packets with packet numbers smaller than the LeastUnacked of a StopWaiting
- if err == ackhandler.ErrPacketSmallerThanLastStopWaiting {
- utils.Infof("Ignoring packet 0x%x due to ErrPacketSmallerThanLastStopWaiting", hdr.PacketNumber)
- return nil
- }
-
- if err != nil {
- return err
- }
-
- return s.handleFrames(packet.frames)
-}
-
-func (s *Session) handleFrames(fs []frames.Frame) error {
- for _, ff := range fs {
- var err error
- frames.LogFrame(ff, false)
- switch frame := ff.(type) {
- case *frames.StreamFrame:
- err = s.handleStreamFrame(frame)
- // TODO: send RstStreamFrame
- case *frames.AckFrame:
- err = s.handleAckFrame(frame)
- case *frames.ConnectionCloseFrame:
- s.closeImpl(qerr.Error(frame.ErrorCode, frame.ReasonPhrase), true)
- case *frames.GoawayFrame:
- err = errors.New("unimplemented: handling GOAWAY frames")
- case *frames.StopWaitingFrame:
- err = s.receivedPacketHandler.ReceivedStopWaiting(frame)
- case *frames.RstStreamFrame:
- err = s.handleRstStreamFrame(frame)
- case *frames.WindowUpdateFrame:
- err = s.handleWindowUpdateFrame(frame)
- case *frames.BlockedFrame:
- case *frames.PingFrame:
- default:
- return errors.New("Session BUG: unexpected frame type")
- }
-
- if err != nil {
- switch err {
- case ackhandler.ErrDuplicateOrOutOfOrderAck:
- // Can happen e.g. when packets thought missing arrive late
- case errRstStreamOnInvalidStream:
- // Can happen when RST_STREAMs arrive early or late (?)
- utils.Errorf("Ignoring error in session: %s", err.Error())
- case errWindowUpdateOnClosedStream:
- // Can happen when we already sent the last StreamFrame with the FinBit, but the client already sent a WindowUpdate for this Stream
- default:
- return err
- }
- }
- }
- return nil
-}
-
-// handlePacket is called by the server with a new packet
-func (s *Session) handlePacket(p *receivedPacket) {
- // Discard packets once the amount of queued packets is larger than
- // the channel size, protocol.MaxSessionUnprocessedPackets
- select {
- case s.receivedPackets <- p:
- default:
- }
-}
-
-func (s *Session) handleStreamFrame(frame *frames.StreamFrame) error {
- str, err := s.streamsMap.GetOrOpenStream(frame.StreamID)
- if err != nil {
- return err
- }
- if str == nil {
- // Stream is closed, ignore
- return nil
- }
- err = str.AddStreamFrame(frame)
- if err != nil {
- return err
- }
- return nil
-}
-
-func (s *Session) handleWindowUpdateFrame(frame *frames.WindowUpdateFrame) error {
- if frame.StreamID != 0 {
- str, err := s.streamsMap.GetOrOpenStream(frame.StreamID)
- if err != nil {
- return err
- }
- if str == nil {
- return errWindowUpdateOnClosedStream
- }
- }
- _, err := s.flowControlManager.UpdateWindow(frame.StreamID, frame.ByteOffset)
- return err
-}
-
-// TODO: Handle frame.byteOffset
-func (s *Session) handleRstStreamFrame(frame *frames.RstStreamFrame) error {
- str, err := s.streamsMap.GetOrOpenStream(frame.StreamID)
- if err != nil {
- return err
- }
- if str == nil {
- return errRstStreamOnInvalidStream
- }
- s.closeStreamWithError(str, fmt.Errorf("RST_STREAM received with code %d", frame.ErrorCode))
- return nil
-}
-
-func (s *Session) handleAckFrame(frame *frames.AckFrame) error {
- if err := s.sentPacketHandler.ReceivedAck(frame, s.lastRcvdPacketNumber, s.lastNetworkActivityTime); err != nil {
- return err
- }
- return nil
-}
-
-// Close the connection. If err is nil it will be set to qerr.PeerGoingAway.
-func (s *Session) Close(e error) error {
- return s.closeImpl(e, false)
-}
-
-func (s *Session) closeImpl(e error, remoteClose bool) error {
- // Only close once
- if !atomic.CompareAndSwapUint32(&s.closed, 0, 1) {
- return nil
- }
-
- if e == nil {
- e = qerr.PeerGoingAway
- }
-
- quicErr := qerr.ToQuicError(e)
-
- // Don't log 'normal' reasons
- if quicErr.ErrorCode == qerr.PeerGoingAway || quicErr.ErrorCode == qerr.NetworkIdleTimeout {
- utils.Infof("Closing connection %x", s.connectionID)
- } else {
- utils.Errorf("Closing session with error: %s", e.Error())
- }
-
- s.closeStreamsWithError(quicErr)
- s.closeCallback(s.connectionID)
-
- if remoteClose {
- // If this is a remote close we don't need to send a CONNECTION_CLOSE
- s.closeChan <- nil
- return nil
- }
-
- if quicErr.ErrorCode == qerr.DecryptionFailure {
- // If we send a public reset, don't send a CONNECTION_CLOSE
- s.closeChan <- nil
- return s.sendPublicReset(s.lastRcvdPacketNumber)
- }
- s.closeChan <- quicErr
- return nil
-}
-
-func (s *Session) closeStreamsWithError(err error) {
- s.streamsMap.Iterate(func(str *stream) (bool, error) {
- s.closeStreamWithError(str, err)
- return true, nil
- })
-}
-
-func (s *Session) closeStreamWithError(str *stream, err error) {
- str.RegisterError(err)
-}
-
-func (s *Session) sendPacket() error {
- // Repeatedly try sending until we don't have any more data, or run out of the congestion window
- for {
- err := s.sentPacketHandler.CheckForError()
- if err != nil {
- return err
- }
-
- // Do this before checking the congestion, since we might de-congestionize here :)
- s.sentPacketHandler.MaybeQueueRTOs()
-
- if !s.sentPacketHandler.SendingAllowed() {
- return nil
- }
-
- var controlFrames []frames.Frame
-
- // check for retransmissions first
- for {
- retransmitPacket := s.sentPacketHandler.DequeuePacketForRetransmission()
- if retransmitPacket == nil {
- break
- }
- utils.Debugf("\tDequeueing retransmission for packet 0x%x", retransmitPacket.PacketNumber)
-
- // resend the frames that were in the packet
- controlFrames = append(controlFrames, retransmitPacket.GetControlFramesForRetransmission()...)
- for _, streamFrame := range retransmitPacket.GetStreamFramesForRetransmission() {
- s.streamFramer.AddFrameForRetransmission(streamFrame)
- }
- }
-
- windowUpdateFrames, err := s.getWindowUpdateFrames()
- if err != nil {
- return err
- }
-
- for _, wuf := range windowUpdateFrames {
- controlFrames = append(controlFrames, wuf)
- }
-
- ack, err := s.receivedPacketHandler.GetAckFrame(false)
- if err != nil {
- return err
- }
- if ack != nil {
- controlFrames = append(controlFrames, ack)
- }
-
- // Check whether we are allowed to send a packet containing only an ACK
- maySendOnlyAck := time.Now().Sub(s.delayedAckOriginTime) > protocol.AckSendDelay
- if runtime.GOOS == "windows" {
- maySendOnlyAck = true
- }
-
- hasRetransmission := s.streamFramer.HasFramesForRetransmission()
-
- var stopWaitingFrame *frames.StopWaitingFrame
- if ack != nil || hasRetransmission {
- stopWaitingFrame = s.sentPacketHandler.GetStopWaitingFrame(hasRetransmission)
- }
- packet, err := s.packer.PackPacket(stopWaitingFrame, controlFrames, s.sentPacketHandler.GetLeastUnacked(), maySendOnlyAck)
- if err != nil {
- return err
- }
- if packet == nil {
- return nil
- }
-
- // Pop the ACK frame now that we are sure we're gonna send it
- _, err = s.receivedPacketHandler.GetAckFrame(true)
- if err != nil {
- return err
- }
-
- for _, f := range windowUpdateFrames {
- s.packer.QueueControlFrameForNextPacket(f)
- }
-
- err = s.sentPacketHandler.SentPacket(&ackhandler.Packet{
- PacketNumber: packet.number,
- Frames: packet.frames,
- Length: protocol.ByteCount(len(packet.raw)),
- })
- if err != nil {
- return err
- }
-
- s.logPacket(packet)
- s.delayedAckOriginTime = time.Time{}
-
- err = s.conn.write(packet.raw)
- putPacketBuffer(packet.raw)
- if err != nil {
- return err
- }
- }
-}
-
-func (s *Session) sendConnectionClose(quicErr *qerr.QuicError) error {
- packet, err := s.packer.PackConnectionClose(&frames.ConnectionCloseFrame{ErrorCode: quicErr.ErrorCode, ReasonPhrase: quicErr.ErrorMessage}, s.sentPacketHandler.GetLeastUnacked())
- if err != nil {
- return err
- }
- if packet == nil {
- return errors.New("Session BUG: expected packet not to be nil")
- }
- s.logPacket(packet)
- return s.conn.write(packet.raw)
-}
-
-func (s *Session) logPacket(packet *packedPacket) {
- if !utils.Debug() {
- // We don't need to allocate the slices for calling the format functions
- return
- }
- if utils.Debug() {
- utils.Debugf("-> Sending packet 0x%x (%d bytes)", packet.number, len(packet.raw))
- for _, frame := range packet.frames {
- frames.LogFrame(frame, true)
- }
- }
-}
-
-// GetOrOpenStream either returns an existing stream, a newly opened stream, or nil if a stream with the provided ID is already closed.
-// Newly opened streams should only originate from the client. To open a stream from the server, OpenStream should be used.
-func (s *Session) GetOrOpenStream(id protocol.StreamID) (utils.Stream, error) {
- return s.streamsMap.GetOrOpenStream(id)
-}
-
-// OpenStream opens a stream from the server's side
-func (s *Session) OpenStream(id protocol.StreamID) (utils.Stream, error) {
- return s.streamsMap.OpenStream(id)
-}
-
-func (s *Session) newStreamImpl(id protocol.StreamID) (*stream, error) {
- return s.streamsMap.GetOrOpenStream(id)
-}
-
-func (s *Session) newStream(id protocol.StreamID) (*stream, error) {
- stream, err := newStream(id, s.scheduleSending, s.flowControlManager)
- if err != nil {
- return nil, err
- }
-
- // TODO: find a better solution for determining which streams contribute to connection level flow control
- if id == 1 || id == 3 {
- s.flowControlManager.NewStream(id, false)
- } else {
- s.flowControlManager.NewStream(id, true)
- }
-
- s.streamCallback(s, stream)
-
- return stream, nil
-}
-
-// garbageCollectStreams goes through all streams and removes EOF'ed streams
-// from the streams map.
-func (s *Session) garbageCollectStreams() {
- s.streamsMap.Iterate(func(str *stream) (bool, error) {
- id := str.StreamID()
- if str.finished() {
- err := s.streamsMap.RemoveStream(id)
- if err != nil {
- return false, err
- }
- s.flowControlManager.RemoveStream(id)
- }
- return true, nil
- })
-}
-
-func (s *Session) sendPublicReset(rejectedPacketNumber protocol.PacketNumber) error {
- utils.Infof("Sending public reset for connection %x, packet number %d", s.connectionID, rejectedPacketNumber)
- return s.conn.write(writePublicReset(s.connectionID, rejectedPacketNumber, 0))
-}
-
-// scheduleSending signals that we have data for sending
-func (s *Session) scheduleSending() {
- select {
- case s.sendingScheduled <- struct{}{}:
- default:
- }
-}
-
-func (s *Session) tryQueueingUndecryptablePacket(p *receivedPacket) {
- if s.cryptoSetup.HandshakeComplete() {
- return
- }
- utils.Infof("Queueing packet 0x%x for later decryption", p.publicHeader.PacketNumber)
- if len(s.undecryptablePackets)+1 >= protocol.MaxUndecryptablePackets {
- s.Close(qerr.Error(qerr.DecryptionFailure, "too many undecryptable packets received"))
- }
- s.undecryptablePackets = append(s.undecryptablePackets, p)
-}
-
-func (s *Session) tryDecryptingQueuedPackets() {
- for _, p := range s.undecryptablePackets {
- s.handlePacket(p)
- }
- s.undecryptablePackets = s.undecryptablePackets[:0]
-}
-
-func (s *Session) getWindowUpdateFrames() ([]*frames.WindowUpdateFrame, error) {
- updates := s.flowControlManager.GetWindowUpdates()
- res := make([]*frames.WindowUpdateFrame, len(updates))
- for i, u := range updates {
- res[i] = &frames.WindowUpdateFrame{StreamID: u.StreamID, ByteOffset: u.Offset}
- }
- return res, nil
-}
-
-// RemoteAddr returns the net.UDPAddr of the client
-func (s *Session) RemoteAddr() *net.UDPAddr {
- return s.conn.RemoteAddr()
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/stream.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/stream.go
deleted file mode 100644
index fc73b1e..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/stream.go
+++ /dev/null
@@ -1,267 +0,0 @@
-package quic
-
-import (
- "fmt"
- "io"
- "sync"
- "sync/atomic"
-
- "github.com/lucas-clemente/quic-go/flowcontrol"
- "github.com/lucas-clemente/quic-go/frames"
- "github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
-)
-
-// A Stream assembles the data from StreamFrames and provides a super-convenient Read-Interface
-//
-// Read() and Write() may be called concurrently, but multiple calls to Read() or Write() individually must be synchronized manually.
-type stream struct {
- streamID protocol.StreamID
- onData func()
-
- readPosInFrame int
- writeOffset protocol.ByteCount
- readOffset protocol.ByteCount
-
- // Once set, err must not be changed!
- err error
- mutex sync.Mutex
-
- // eof is set if we are finished reading
- eof int32 // really a bool
- // closed is set when we are finished writing
- closed int32 // really a bool
-
- frameQueue *streamFrameSorter
- newFrameOrErrCond sync.Cond
-
- dataForWriting []byte
- finSent bool
- doneWritingOrErrCond sync.Cond
-
- flowControlManager flowcontrol.FlowControlManager
-}
-
-// newStream creates a new Stream
-func newStream(StreamID protocol.StreamID, onData func(), flowControlManager flowcontrol.FlowControlManager) (*stream, error) {
- s := &stream{
- onData: onData,
- streamID: StreamID,
- flowControlManager: flowControlManager,
- frameQueue: newStreamFrameSorter(),
- }
-
- s.newFrameOrErrCond.L = &s.mutex
- s.doneWritingOrErrCond.L = &s.mutex
-
- return s, nil
-}
-
-// Read implements io.Reader. It is not thread safe!
-func (s *stream) Read(p []byte) (int, error) {
- if atomic.LoadInt32(&s.eof) != 0 {
- return 0, io.EOF
- }
-
- bytesRead := 0
- for bytesRead < len(p) {
- s.mutex.Lock()
- frame := s.frameQueue.Head()
-
- if frame == nil && bytesRead > 0 {
- s.mutex.Unlock()
- return bytesRead, s.err
- }
-
- var err error
- for {
- // Stop waiting on errors
- if s.err != nil {
- err = s.err
- break
- }
- if frame != nil {
- s.readPosInFrame = int(s.readOffset - frame.Offset)
- break
- }
- s.newFrameOrErrCond.Wait()
- frame = s.frameQueue.Head()
- }
- s.mutex.Unlock()
- // Here, either frame != nil xor err != nil
-
- if frame == nil {
- atomic.StoreInt32(&s.eof, 1)
- // We have an err and no data, return the error
- return bytesRead, err
- }
-
- m := utils.Min(len(p)-bytesRead, int(frame.DataLen())-s.readPosInFrame)
-
- if bytesRead > len(p) {
- return bytesRead, fmt.Errorf("BUG: bytesRead (%d) > len(p) (%d) in stream.Read", bytesRead, len(p))
- }
- if s.readPosInFrame > int(frame.DataLen()) {
- return bytesRead, fmt.Errorf("BUG: readPosInFrame (%d) > frame.DataLen (%d) in stream.Read", s.readPosInFrame, frame.DataLen())
- }
- copy(p[bytesRead:], frame.Data[s.readPosInFrame:])
-
- s.readPosInFrame += m
- bytesRead += m
- s.readOffset += protocol.ByteCount(m)
-
- s.flowControlManager.AddBytesRead(s.streamID, protocol.ByteCount(m))
- s.onData() // so that a possible WINDOW_UPDATE is sent
-
- if s.readPosInFrame >= int(frame.DataLen()) {
- fin := frame.FinBit
- s.mutex.Lock()
- s.frameQueue.Pop()
- s.mutex.Unlock()
- if fin {
- atomic.StoreInt32(&s.eof, 1)
- return bytesRead, io.EOF
- }
- }
- }
-
- return bytesRead, nil
-}
-
-func (s *stream) Write(p []byte) (int, error) {
- s.mutex.Lock()
- defer s.mutex.Unlock()
-
- if s.err != nil {
- return 0, s.err
- }
-
- if len(p) == 0 {
- return 0, nil
- }
-
- s.dataForWriting = make([]byte, len(p))
- copy(s.dataForWriting, p)
-
- s.onData()
-
- for s.dataForWriting != nil && s.err == nil {
- s.doneWritingOrErrCond.Wait()
- }
-
- if s.err != nil {
- return 0, s.err
- }
-
- return len(p), nil
-}
-
-func (s *stream) lenOfDataForWriting() protocol.ByteCount {
- s.mutex.Lock()
- l := protocol.ByteCount(len(s.dataForWriting))
- s.mutex.Unlock()
- return l
-}
-
-func (s *stream) getDataForWriting(maxBytes protocol.ByteCount) []byte {
- s.mutex.Lock()
- if s.dataForWriting == nil {
- s.mutex.Unlock()
- return nil
- }
- var ret []byte
- if protocol.ByteCount(len(s.dataForWriting)) > maxBytes {
- ret = s.dataForWriting[:maxBytes]
- s.dataForWriting = s.dataForWriting[maxBytes:]
- } else {
- ret = s.dataForWriting
- s.dataForWriting = nil
- s.doneWritingOrErrCond.Signal()
- }
- s.writeOffset += protocol.ByteCount(len(ret))
- s.mutex.Unlock()
- return ret
-}
-
-// Close implements io.Closer
-func (s *stream) Close() error {
- atomic.StoreInt32(&s.closed, 1)
- s.onData()
- return nil
-}
-
-func (s *stream) shouldSendFin() bool {
- s.mutex.Lock()
- res := atomic.LoadInt32(&s.closed) != 0 && !s.finSent && s.err == nil && s.dataForWriting == nil
- s.mutex.Unlock()
- return res
-}
-
-func (s *stream) sentFin() {
- s.mutex.Lock()
- s.finSent = true
- s.mutex.Unlock()
-}
-
-// AddStreamFrame adds a new stream frame
-func (s *stream) AddStreamFrame(frame *frames.StreamFrame) error {
- maxOffset := frame.Offset + frame.DataLen()
- err := s.flowControlManager.UpdateHighestReceived(s.streamID, maxOffset)
-
- if err == flowcontrol.ErrStreamFlowControlViolation {
- return qerr.FlowControlReceivedTooMuchData
- }
- if err == flowcontrol.ErrConnectionFlowControlViolation {
- return qerr.FlowControlReceivedTooMuchData
- }
- if err != nil {
- return err
- }
-
- s.mutex.Lock()
- defer s.mutex.Unlock()
- err = s.frameQueue.Push(frame)
- if err != nil && err != errDuplicateStreamData {
- return err
- }
- s.newFrameOrErrCond.Signal()
- return nil
-}
-
-// CloseRemote makes the stream receive a "virtual" FIN stream frame at a given offset
-func (s *stream) CloseRemote(offset protocol.ByteCount) {
- s.AddStreamFrame(&frames.StreamFrame{FinBit: true, Offset: offset})
-}
-
-// RegisterError is called by session to indicate that an error occurred and the
-// stream should be closed.
-func (s *stream) RegisterError(err error) {
- atomic.StoreInt32(&s.closed, 1)
- s.mutex.Lock()
- defer s.mutex.Unlock()
- if s.err != nil { // s.err must not be changed!
- return
- }
- s.err = err
- s.doneWritingOrErrCond.Signal()
- s.newFrameOrErrCond.Signal()
-}
-
-func (s *stream) finishedReading() bool {
- return atomic.LoadInt32(&s.eof) != 0
-}
-
-func (s *stream) finishedWriting() bool {
- s.mutex.Lock()
- defer s.mutex.Unlock()
- return s.err != nil || (atomic.LoadInt32(&s.closed) != 0 && s.finSent)
-}
-
-func (s *stream) finished() bool {
- return s.finishedReading() && s.finishedWriting()
-}
-
-func (s *stream) StreamID() protocol.StreamID {
- return s.streamID
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/stream_frame_sorter.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/stream_frame_sorter.go
deleted file mode 100644
index 7a95f1f..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/stream_frame_sorter.go
+++ /dev/null
@@ -1,119 +0,0 @@
-package quic
-
-import (
- "errors"
-
- "github.com/lucas-clemente/quic-go/frames"
- "github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
-)
-
-type streamFrameSorter struct {
- queuedFrames map[protocol.ByteCount]*frames.StreamFrame
- readPosition protocol.ByteCount
- gaps *utils.ByteIntervalList
-}
-
-var (
- errTooManyGapsInReceivedStreamData = errors.New("Too many gaps in received StreamFrame data")
- errDuplicateStreamData = errors.New("Overlapping Stream Data")
- errEmptyStreamData = errors.New("Stream Data empty")
-)
-
-func newStreamFrameSorter() *streamFrameSorter {
- s := streamFrameSorter{
- gaps: utils.NewByteIntervalList(),
- queuedFrames: make(map[protocol.ByteCount]*frames.StreamFrame),
- }
- s.gaps.PushFront(utils.ByteInterval{Start: 0, End: protocol.MaxByteCount})
- return &s
-}
-
-func (s *streamFrameSorter) Push(frame *frames.StreamFrame) error {
- _, ok := s.queuedFrames[frame.Offset]
- if ok {
- return errDuplicateStreamData
- }
-
- start := frame.Offset
- end := frame.Offset + frame.DataLen()
-
- if start == end {
- if frame.FinBit {
- s.queuedFrames[frame.Offset] = frame
- return nil
- }
- return errEmptyStreamData
- }
-
- var foundInGap bool
-
- for gap := s.gaps.Front(); gap != nil; gap = gap.Next() {
- // the complete frame lies before or after the gap
- if end <= gap.Value.Start || start > gap.Value.End {
- continue
- }
-
- if start < gap.Value.Start {
- return qerr.Error(qerr.OverlappingStreamData, "start of gap in stream chunk")
- }
-
- if start < gap.Value.End && end > gap.Value.End {
- return qerr.Error(qerr.OverlappingStreamData, "end of gap in stream chunk")
- }
-
- foundInGap = true
-
- if start == gap.Value.Start {
- if end == gap.Value.End {
- s.gaps.Remove(gap)
- break
- }
- if end < gap.Value.End {
- gap.Value.Start = end
- break
- }
- }
-
- if end == gap.Value.End {
- gap.Value.End = start
- break
- }
-
- if end < gap.Value.End {
- intv := utils.ByteInterval{Start: end, End: gap.Value.End}
- s.gaps.InsertAfter(intv, gap)
- gap.Value.End = start
- break
- }
- }
-
- if !foundInGap {
- return errDuplicateStreamData
- }
-
- if s.gaps.Len() > protocol.MaxStreamFrameSorterGaps {
- return errTooManyGapsInReceivedStreamData
- }
-
- s.queuedFrames[frame.Offset] = frame
- return nil
-}
-
-func (s *streamFrameSorter) Pop() *frames.StreamFrame {
- frame := s.Head()
- if frame != nil {
- s.readPosition += frame.DataLen()
- delete(s.queuedFrames, frame.Offset)
- }
- return frame
-}
-
-func (s *streamFrameSorter) Head() *frames.StreamFrame {
- frame, ok := s.queuedFrames[s.readPosition]
- if ok {
- return frame
- }
- return nil
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/streams_map.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/streams_map.go
deleted file mode 100644
index 8b41b86..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/streams_map.go
+++ /dev/null
@@ -1,219 +0,0 @@
-package quic
-
-import (
- "errors"
- "fmt"
- "sync"
-
- "github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
-)
-
-type streamsMap struct {
- mutex sync.RWMutex
-
- streams map[protocol.StreamID]*stream
- openStreams []protocol.StreamID
-
- highestStreamOpenedByClient protocol.StreamID
- streamsOpenedAfterLastGarbageCollect int
-
- newStream newStreamLambda
- maxNumStreams int
-
- roundRobinIndex int
-}
-
-type streamLambda func(*stream) (bool, error)
-type newStreamLambda func(protocol.StreamID) (*stream, error)
-
-var (
- errMapAccess = errors.New("streamsMap: Error accessing the streams map")
-)
-
-func newStreamsMap(newStream newStreamLambda) *streamsMap {
- maxNumStreams := utils.Max(int(float32(protocol.MaxIncomingDynamicStreams)*protocol.MaxStreamsMultiplier), int(protocol.MaxIncomingDynamicStreams))
-
- return &streamsMap{
- streams: map[protocol.StreamID]*stream{},
- openStreams: make([]protocol.StreamID, 0, maxNumStreams),
- newStream: newStream,
- maxNumStreams: maxNumStreams,
- }
-}
-
-// GetOrOpenStream either returns an existing stream, a newly opened stream, or nil if a stream with the provided ID is already closed.
-// Newly opened streams should only originate from the client. To open a stream from the server, OpenStream should be used.
-func (m *streamsMap) GetOrOpenStream(id protocol.StreamID) (*stream, error) {
- m.mutex.RLock()
- s, ok := m.streams[id]
- m.mutex.RUnlock()
- if ok {
- return s, nil // s may be nil
- }
-
- // ... we don't have an existing stream, try opening a new one
- m.mutex.Lock()
- defer m.mutex.Unlock()
- // We need to check whether another invocation has already created a stream (between RUnlock() and Lock()).
- s, ok = m.streams[id]
- if ok {
- return s, nil
- }
- if len(m.openStreams) == m.maxNumStreams {
- return nil, qerr.TooManyOpenStreams
- }
- if id%2 == 0 {
- return nil, qerr.Error(qerr.InvalidStreamID, fmt.Sprintf("attempted to open stream %d from client-side", id))
- }
- if id+protocol.MaxNewStreamIDDelta < m.highestStreamOpenedByClient {
- return nil, qerr.Error(qerr.InvalidStreamID, fmt.Sprintf("attempted to open stream %d, which is a lot smaller than the highest opened stream, %d", id, m.highestStreamOpenedByClient))
- }
-
- s, err := m.newStream(id)
- if err != nil {
- return nil, err
- }
-
- if id > m.highestStreamOpenedByClient {
- m.highestStreamOpenedByClient = id
- }
-
- m.streamsOpenedAfterLastGarbageCollect++
- if m.streamsOpenedAfterLastGarbageCollect%protocol.MaxNewStreamIDDelta == 0 {
- m.garbageCollectClosedStreams()
- }
-
- m.putStream(s)
- return s, nil
-}
-
-// OpenStream opens a stream from the server's side
-func (m *streamsMap) OpenStream(id protocol.StreamID) (*stream, error) {
- panic("OpenStream: not implemented")
-}
-
-func (m *streamsMap) Iterate(fn streamLambda) error {
- m.mutex.Lock()
- defer m.mutex.Unlock()
-
- for _, streamID := range m.openStreams {
- cont, err := m.iterateFunc(streamID, fn)
- if err != nil {
- return err
- }
- if !cont {
- break
- }
- }
- return nil
-}
-
-// RoundRobinIterate executes the streamLambda for every open stream, until the streamLambda returns false
-// It uses a round-robin-like scheduling to ensure that every stream is considered fairly
-// It prioritizes the crypto- and the header-stream (StreamIDs 1 and 3)
-func (m *streamsMap) RoundRobinIterate(fn streamLambda) error {
- m.mutex.Lock()
- defer m.mutex.Unlock()
-
- numStreams := len(m.openStreams)
- startIndex := m.roundRobinIndex
-
- for _, i := range []protocol.StreamID{1, 3} {
- cont, err := m.iterateFunc(i, fn)
- if err != nil && err != errMapAccess {
- return err
- }
- if !cont {
- return nil
- }
- }
-
- for i := 0; i < numStreams; i++ {
- streamID := m.openStreams[(i+startIndex)%numStreams]
-
- if streamID == 1 || streamID == 3 {
- continue
- }
-
- cont, err := m.iterateFunc(streamID, fn)
- if err != nil {
- return err
- }
- m.roundRobinIndex = (m.roundRobinIndex + 1) % numStreams
- if !cont {
- break
- }
- }
- return nil
-}
-
-func (m *streamsMap) iterateFunc(streamID protocol.StreamID, fn streamLambda) (bool, error) {
- str, ok := m.streams[streamID]
- if !ok {
- return true, errMapAccess
- }
- if str == nil {
- return false, fmt.Errorf("BUG: Stream %d is closed, but still in openStreams map", streamID)
- }
- return fn(str)
-}
-
-func (m *streamsMap) putStream(s *stream) error {
- id := s.StreamID()
- if _, ok := m.streams[id]; ok {
- return fmt.Errorf("a stream with ID %d already exists", id)
- }
-
- m.streams[id] = s
- m.openStreams = append(m.openStreams, id)
-
- return nil
-}
-
-// Attention: this function must only be called if a mutex has been acquired previously
-func (m *streamsMap) RemoveStream(id protocol.StreamID) error {
- s, ok := m.streams[id]
- if !ok || s == nil {
- return fmt.Errorf("attempted to remove non-existing stream: %d", id)
- }
-
- m.streams[id] = nil
-
- for i, s := range m.openStreams {
- if s == id {
- // delete the streamID from the openStreams slice
- m.openStreams = m.openStreams[:i+copy(m.openStreams[i:], m.openStreams[i+1:])]
- // adjust round-robin index, if necessary
- if i < m.roundRobinIndex {
- m.roundRobinIndex--
- }
- break
- }
- }
-
- return nil
-}
-
-// NumberOfStreams gets the number of open streams
-func (m *streamsMap) NumberOfStreams() int {
- m.mutex.RLock()
- n := len(m.openStreams)
- m.mutex.RUnlock()
- return n
-}
-
-// garbageCollectClosedStreams deletes nil values in the streams if they are smaller than protocol.MaxNewStreamIDDelta than the highest stream opened by the client
-// note that this garbage collection is relatively expensive, since it iterates over the whole streams map. It should not be called every time a stream is openend or closed
-func (m *streamsMap) garbageCollectClosedStreams() {
- for id, str := range m.streams {
- if str != nil {
- continue
- }
- if id+protocol.MaxNewStreamIDDelta <= m.highestStreamOpenedByClient {
- delete(m.streams, id)
- }
- }
- m.streamsOpenedAfterLastGarbageCollect = 0
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/udp_conn.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/udp_conn.go
deleted file mode 100644
index 2c1bafe..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/udp_conn.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package quic
-
-import "net"
-
-type connection interface {
- write([]byte) error
- setCurrentRemoteAddr(interface{})
- RemoteAddr() *net.UDPAddr
-}
-
-type udpConn struct {
- conn *net.UDPConn
- currentAddr *net.UDPAddr
-}
-
-var _ connection = &udpConn{}
-
-func (c *udpConn) write(p []byte) error {
- _, err := c.conn.WriteToUDP(p, c.currentAddr)
- return err
-}
-
-func (c *udpConn) setCurrentRemoteAddr(addr interface{}) {
- c.currentAddr = addr.(*net.UDPAddr)
-}
-
-func (c *udpConn) RemoteAddr() *net.UDPAddr {
- return c.currentAddr
-}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/log.go b/cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/log.go
deleted file mode 100644
index bb0f255..0000000
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/log.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package utils
-
-import (
- "fmt"
- "io"
- "os"
- "sync"
-)
-
-var out io.Writer = os.Stdout
-
-// LogLevel of quic-go
-type LogLevel uint8
-
-const (
- // LogLevelDebug enables debug logs (e.g. packet contents)
- LogLevelDebug LogLevel = iota
- // LogLevelInfo enables info logs (e.g. packets)
- LogLevelInfo
- // LogLevelError enables err logs
- LogLevelError
- // LogLevelNothing disables
- LogLevelNothing
-)
-
-var logLevel = LogLevelNothing
-
-var mutex sync.Mutex
-
-// SetLogWriter sets the log writer.
-func SetLogWriter(w io.Writer) {
- out = w
-}
-
-// SetLogLevel sets the log level
-func SetLogLevel(level LogLevel) {
- logLevel = level
-}
-
-// Debugf logs something
-func Debugf(format string, args ...interface{}) {
- if logLevel == LogLevelDebug {
- mutex.Lock()
- fmt.Fprintf(out, format+"\n", args...)
- mutex.Unlock()
- }
-}
-
-// Infof logs something
-func Infof(format string, args ...interface{}) {
- if logLevel <= LogLevelInfo {
- mutex.Lock()
- fmt.Fprintf(out, format+"\n", args...)
- mutex.Unlock()
- }
-}
-
-// Errorf logs something
-func Errorf(format string, args ...interface{}) {
- if logLevel <= LogLevelError {
- mutex.Lock()
- fmt.Fprintf(out, format+"\n", args...)
- mutex.Unlock()
- }
-}
-
-// Debug returns true if the log level is LogLevelDebug
-func Debug() bool {
- return logLevel == LogLevelDebug
-}
diff --git a/cmd/gost/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s b/cmd/gost/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
deleted file mode 100644
index 45484d1..0000000
--- a/cmd/gost/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
-
-// +build amd64,!gccgo,!appengine
-
-// func cswap(inout *[5]uint64, v uint64)
-TEXT ·cswap(SB),7,$0
- MOVQ inout+0(FP),DI
- MOVQ v+8(FP),SI
-
- CMPQ SI,$1
- MOVQ 0(DI),SI
- MOVQ 80(DI),DX
- MOVQ 8(DI),CX
- MOVQ 88(DI),R8
- MOVQ SI,R9
- CMOVQEQ DX,SI
- CMOVQEQ R9,DX
- MOVQ CX,R9
- CMOVQEQ R8,CX
- CMOVQEQ R9,R8
- MOVQ SI,0(DI)
- MOVQ DX,80(DI)
- MOVQ CX,8(DI)
- MOVQ R8,88(DI)
- MOVQ 16(DI),SI
- MOVQ 96(DI),DX
- MOVQ 24(DI),CX
- MOVQ 104(DI),R8
- MOVQ SI,R9
- CMOVQEQ DX,SI
- CMOVQEQ R9,DX
- MOVQ CX,R9
- CMOVQEQ R8,CX
- CMOVQEQ R9,R8
- MOVQ SI,16(DI)
- MOVQ DX,96(DI)
- MOVQ CX,24(DI)
- MOVQ R8,104(DI)
- MOVQ 32(DI),SI
- MOVQ 112(DI),DX
- MOVQ 40(DI),CX
- MOVQ 120(DI),R8
- MOVQ SI,R9
- CMOVQEQ DX,SI
- CMOVQEQ R9,DX
- MOVQ CX,R9
- CMOVQEQ R8,CX
- CMOVQEQ R9,R8
- MOVQ SI,32(DI)
- MOVQ DX,112(DI)
- MOVQ CX,40(DI)
- MOVQ R8,120(DI)
- MOVQ 48(DI),SI
- MOVQ 128(DI),DX
- MOVQ 56(DI),CX
- MOVQ 136(DI),R8
- MOVQ SI,R9
- CMOVQEQ DX,SI
- CMOVQEQ R9,DX
- MOVQ CX,R9
- CMOVQEQ R8,CX
- CMOVQEQ R9,R8
- MOVQ SI,48(DI)
- MOVQ DX,128(DI)
- MOVQ CX,56(DI)
- MOVQ R8,136(DI)
- MOVQ 64(DI),SI
- MOVQ 144(DI),DX
- MOVQ 72(DI),CX
- MOVQ 152(DI),R8
- MOVQ SI,R9
- CMOVQEQ DX,SI
- CMOVQEQ R9,DX
- MOVQ CX,R9
- CMOVQEQ R8,CX
- CMOVQEQ R9,R8
- MOVQ SI,64(DI)
- MOVQ DX,144(DI)
- MOVQ CX,72(DI)
- MOVQ R8,152(DI)
- MOVQ DI,AX
- MOVQ SI,DX
- RET
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/fixed_buffer.go b/cmd/gost/vendor/golang.org/x/net/http2/fixed_buffer.go
deleted file mode 100644
index 47da0f0..0000000
--- a/cmd/gost/vendor/golang.org/x/net/http2/fixed_buffer.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package http2
-
-import (
- "errors"
-)
-
-// fixedBuffer is an io.ReadWriter backed by a fixed size buffer.
-// It never allocates, but moves old data as new data is written.
-type fixedBuffer struct {
- buf []byte
- r, w int
-}
-
-var (
- errReadEmpty = errors.New("read from empty fixedBuffer")
- errWriteFull = errors.New("write on full fixedBuffer")
-)
-
-// Read copies bytes from the buffer into p.
-// It is an error to read when no data is available.
-func (b *fixedBuffer) Read(p []byte) (n int, err error) {
- if b.r == b.w {
- return 0, errReadEmpty
- }
- n = copy(p, b.buf[b.r:b.w])
- b.r += n
- if b.r == b.w {
- b.r = 0
- b.w = 0
- }
- return n, nil
-}
-
-// Len returns the number of bytes of the unread portion of the buffer.
-func (b *fixedBuffer) Len() int {
- return b.w - b.r
-}
-
-// Write copies bytes from p into the buffer.
-// It is an error to write more data than the buffer can hold.
-func (b *fixedBuffer) Write(p []byte) (n int, err error) {
- // Slide existing data to beginning.
- if b.r > 0 && len(p) > len(b.buf)-b.w {
- copy(b.buf, b.buf[b.r:b.w])
- b.w -= b.r
- b.r = 0
- }
-
- // Write new data.
- n = copy(b.buf[b.w:], p)
- b.w += n
- if n < len(p) {
- err = errWriteFull
- }
- return n, err
-}
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/go16.go b/cmd/gost/vendor/golang.org/x/net/http2/go16.go
deleted file mode 100644
index 2b72855..0000000
--- a/cmd/gost/vendor/golang.org/x/net/http2/go16.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build go1.6
-
-package http2
-
-import (
- "crypto/tls"
- "net/http"
- "time"
-)
-
-func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
- return t1.ExpectContinueTimeout
-}
-
-// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
-func isBadCipher(cipher uint16) bool {
- switch cipher {
- case tls.TLS_RSA_WITH_RC4_128_SHA,
- tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
- tls.TLS_RSA_WITH_AES_128_CBC_SHA,
- tls.TLS_RSA_WITH_AES_256_CBC_SHA,
- tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
- tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
- tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
- tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
- tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
- tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
- tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
- tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
- tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
- // Reject cipher suites from Appendix A.
- // "This list includes those cipher suites that do not
- // offer an ephemeral key exchange and those that are
- // based on the TLS null, stream or block cipher type"
- return true
- default:
- return false
- }
-}
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/not_go16.go b/cmd/gost/vendor/golang.org/x/net/http2/not_go16.go
deleted file mode 100644
index efd2e12..0000000
--- a/cmd/gost/vendor/golang.org/x/net/http2/not_go16.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !go1.6
-
-package http2
-
-import (
- "crypto/tls"
- "net/http"
- "time"
-)
-
-func configureTransport(t1 *http.Transport) (*Transport, error) {
- return nil, errTransportVersion
-}
-
-func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
- return 0
-
-}
-
-// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
-func isBadCipher(cipher uint16) bool {
- switch cipher {
- case tls.TLS_RSA_WITH_RC4_128_SHA,
- tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
- tls.TLS_RSA_WITH_AES_128_CBC_SHA,
- tls.TLS_RSA_WITH_AES_256_CBC_SHA,
- tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
- tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
- tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
- tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
- tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
- tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
- tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
- // Reject cipher suites from Appendix A.
- // "This list includes those cipher suites that do not
- // offer an ephemeral key exchange and those that are
- // based on the TLS null, stream or block cipher type"
- return true
- default:
- return false
- }
-}
diff --git a/cmd/gost/vendor/golang.org/x/net/idna/idna.go b/cmd/gost/vendor/golang.org/x/net/idna/idna.go
deleted file mode 100644
index 3daa897..0000000
--- a/cmd/gost/vendor/golang.org/x/net/idna/idna.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package idna implements IDNA2008 (Internationalized Domain Names for
-// Applications), defined in RFC 5890, RFC 5891, RFC 5892, RFC 5893 and
-// RFC 5894.
-package idna // import "golang.org/x/net/idna"
-
-import (
- "strings"
- "unicode/utf8"
-)
-
-// TODO(nigeltao): specify when errors occur. For example, is ToASCII(".") or
-// ToASCII("foo\x00") an error? See also http://www.unicode.org/faq/idn.html#11
-
-// acePrefix is the ASCII Compatible Encoding prefix.
-const acePrefix = "xn--"
-
-// ToASCII converts a domain or domain label to its ASCII form. For example,
-// ToASCII("bücher.example.com") is "xn--bcher-kva.example.com", and
-// ToASCII("golang") is "golang".
-func ToASCII(s string) (string, error) {
- if ascii(s) {
- return s, nil
- }
- labels := strings.Split(s, ".")
- for i, label := range labels {
- if !ascii(label) {
- a, err := encode(acePrefix, label)
- if err != nil {
- return "", err
- }
- labels[i] = a
- }
- }
- return strings.Join(labels, "."), nil
-}
-
-// ToUnicode converts a domain or domain label to its Unicode form. For example,
-// ToUnicode("xn--bcher-kva.example.com") is "bücher.example.com", and
-// ToUnicode("golang") is "golang".
-func ToUnicode(s string) (string, error) {
- if !strings.Contains(s, acePrefix) {
- return s, nil
- }
- labels := strings.Split(s, ".")
- for i, label := range labels {
- if strings.HasPrefix(label, acePrefix) {
- u, err := decode(label[len(acePrefix):])
- if err != nil {
- return "", err
- }
- labels[i] = u
- }
- }
- return strings.Join(labels, "."), nil
-}
-
-func ascii(s string) bool {
- for i := 0; i < len(s); i++ {
- if s[i] >= utf8.RuneSelf {
- return false
- }
- }
- return true
-}
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/frame.png b/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/frame.png
deleted file mode 100644
index 7952e4a..0000000
Binary files a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/frame.png and /dev/null differ
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/snmp.go b/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/snmp.go
deleted file mode 100644
index 997b163..0000000
--- a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/snmp.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package kcp
-
-import "sync/atomic"
-
-// Snmp defines network statistics indicator
-type Snmp struct {
- BytesSent uint64 // payload bytes sent
- BytesReceived uint64
- MaxConn uint64
- ActiveOpens uint64
- PassiveOpens uint64
- CurrEstab uint64
- InErrs uint64
- InCsumErrors uint64 // checksum errors
- InSegs uint64
- OutSegs uint64
- OutBytes uint64 // udp bytes sent
- RetransSegs uint64
- FastRetransSegs uint64
- EarlyRetransSegs uint64
- LostSegs uint64
- RepeatSegs uint64
- FECRecovered uint64
- FECErrs uint64
- FECSegs uint64 // fec segments received
-}
-
-func newSnmp() *Snmp {
- return new(Snmp)
-}
-
-// Copy make a copy of current snmp snapshot
-func (s *Snmp) Copy() *Snmp {
- d := newSnmp()
- d.BytesSent = atomic.LoadUint64(&s.BytesSent)
- d.BytesReceived = atomic.LoadUint64(&s.BytesReceived)
- d.MaxConn = atomic.LoadUint64(&s.MaxConn)
- d.ActiveOpens = atomic.LoadUint64(&s.ActiveOpens)
- d.PassiveOpens = atomic.LoadUint64(&s.PassiveOpens)
- d.CurrEstab = atomic.LoadUint64(&s.CurrEstab)
- d.InErrs = atomic.LoadUint64(&s.InErrs)
- d.InCsumErrors = atomic.LoadUint64(&s.InCsumErrors)
- d.InSegs = atomic.LoadUint64(&s.InSegs)
- d.OutSegs = atomic.LoadUint64(&s.OutSegs)
- d.OutBytes = atomic.LoadUint64(&s.OutBytes)
- d.RetransSegs = atomic.LoadUint64(&s.RetransSegs)
- d.FastRetransSegs = atomic.LoadUint64(&s.FastRetransSegs)
- d.EarlyRetransSegs = atomic.LoadUint64(&s.EarlyRetransSegs)
- d.LostSegs = atomic.LoadUint64(&s.LostSegs)
- d.RepeatSegs = atomic.LoadUint64(&s.RepeatSegs)
- d.FECSegs = atomic.LoadUint64(&s.FECSegs)
- d.FECErrs = atomic.LoadUint64(&s.FECErrs)
- d.FECRecovered = atomic.LoadUint64(&s.FECRecovered)
- return d
-}
-
-// DefaultSnmp is the global KCP connection statistics collector
-var DefaultSnmp *Snmp
-
-func init() {
- DefaultSnmp = newSnmp()
-}
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/smux.v1/stream.go b/cmd/gost/vendor/gopkg.in/xtaci/smux.v1/stream.go
deleted file mode 100644
index 8c44dd8..0000000
--- a/cmd/gost/vendor/gopkg.in/xtaci/smux.v1/stream.go
+++ /dev/null
@@ -1,166 +0,0 @@
-package smux
-
-import (
- "bytes"
- "encoding/binary"
- "sync"
- "sync/atomic"
-
- "github.com/pkg/errors"
-)
-
-// Stream implements io.ReadWriteCloser
-type Stream struct {
- id uint32
- rstflag int32
- sess *Session
- buffer bytes.Buffer
- bufferLock sync.Mutex
- frameSize int
- chReadEvent chan struct{} // notify a read event
- die chan struct{} // flag the stream has closed
- dieLock sync.Mutex
-}
-
-// newStream initiates a Stream struct
-func newStream(id uint32, frameSize int, sess *Session) *Stream {
- s := new(Stream)
- s.id = id
- s.chReadEvent = make(chan struct{}, 1)
- s.frameSize = frameSize
- s.sess = sess
- s.die = make(chan struct{})
- return s
-}
-
-// Read implements io.ReadWriteCloser
-func (s *Stream) Read(b []byte) (n int, err error) {
-READ:
- select {
- case <-s.die:
- return 0, errors.New(errBrokenPipe)
- default:
- }
-
- s.bufferLock.Lock()
- n, err = s.buffer.Read(b)
- s.bufferLock.Unlock()
-
- if n > 0 {
- s.sess.returnTokens(n)
- return n, nil
- } else if atomic.LoadInt32(&s.rstflag) == 1 {
- _ = s.Close()
- return 0, errors.New(errConnReset)
- }
-
- select {
- case <-s.chReadEvent:
- goto READ
- case <-s.die:
- return 0, errors.New(errBrokenPipe)
- }
-}
-
-// Write implements io.ReadWriteCloser
-func (s *Stream) Write(b []byte) (n int, err error) {
- select {
- case <-s.die:
- return 0, errors.New(errBrokenPipe)
- default:
- }
-
- frames := s.split(b, cmdPSH, s.id)
- // preallocate buffer
- buffer := make([]byte, len(frames)*headerSize+len(b))
- bts := buffer
-
- // combine frames into a large blob
- for k := range frames {
- bts[0] = version
- bts[1] = frames[k].cmd
- binary.LittleEndian.PutUint16(bts[2:], uint16(len(frames[k].data)))
- binary.LittleEndian.PutUint32(bts[4:], frames[k].sid)
- copy(bts[headerSize:], frames[k].data)
- bts = bts[len(frames[k].data)+headerSize:]
- }
-
- if _, err = s.sess.writeBinary(buffer); err != nil {
- return 0, err
- }
- return len(b), nil
-}
-
-// Close implements io.ReadWriteCloser
-func (s *Stream) Close() error {
- s.dieLock.Lock()
- defer s.dieLock.Unlock()
-
- select {
- case <-s.die:
- return errors.New(errBrokenPipe)
- default:
- close(s.die)
- s.sess.streamClosed(s.id)
- _, err := s.sess.writeFrame(newFrame(cmdRST, s.id))
- return err
- }
-}
-
-// session closes the stream
-func (s *Stream) sessionClose() {
- s.dieLock.Lock()
- defer s.dieLock.Unlock()
-
- select {
- case <-s.die:
- default:
- close(s.die)
- }
-}
-
-// pushBytes a slice into buffer
-func (s *Stream) pushBytes(p []byte) {
- s.bufferLock.Lock()
- s.buffer.Write(p)
- s.bufferLock.Unlock()
-}
-
-// recycleTokens transform remaining bytes to tokens(will truncate buffer)
-func (s *Stream) recycleTokens() (n int) {
- s.bufferLock.Lock()
- n = s.buffer.Len()
- s.buffer.Reset()
- s.bufferLock.Unlock()
- return
-}
-
-// split large byte buffer into smaller frames, reference only
-func (s *Stream) split(bts []byte, cmd byte, sid uint32) []Frame {
- var frames []Frame
- for len(bts) > s.frameSize {
- frame := newFrame(cmd, sid)
- frame.data = bts[:s.frameSize]
- bts = bts[s.frameSize:]
- frames = append(frames, frame)
- }
- if len(bts) > 0 {
- frame := newFrame(cmd, sid)
- frame.data = bts
- frames = append(frames, frame)
- }
- return frames
-}
-
-// notify read event
-func (s *Stream) notifyReadEvent() {
- select {
- case s.chReadEvent <- struct{}{}:
- default:
- }
-}
-
-// mark this stream has been reset
-func (s *Stream) markRST() {
- atomic.StoreInt32(&s.rstflag, 1)
-}
diff --git a/cmd/gost/vendor/vendor.json b/cmd/gost/vendor/vendor.json
deleted file mode 100644
index 9cb9f4d..0000000
--- a/cmd/gost/vendor/vendor.json
+++ /dev/null
@@ -1,295 +0,0 @@
-{
- "comment": "",
- "ignore": "test",
- "package": [
- {
- "checksumSHA1": "IFJyJgPCjumDG37lEb0lyRBBGZE=",
- "path": "github.com/Yawning/chacha20",
- "revision": "c91e78db502ff629614837aacb7aa4efa61c651a",
- "revisionTime": "2016-04-30T09:49:23Z"
- },
- {
- "checksumSHA1": "QPs3L3mjPoi+a9GJCjW8HhyJczM=",
- "path": "github.com/codahale/chacha20",
- "revision": "ec07b4f69a3f70b1dd2a8ad77230deb1ba5d6953",
- "revisionTime": "2015-11-07T02:50:05Z"
- },
- {
- "checksumSHA1": "5TwW96Afcvo+zm0tAn+DSNIQreQ=",
- "path": "github.com/ginuerzh/gosocks5",
- "revision": "0f737bddba2abd1496dc03c8b39b817cc5f33fa7",
- "revisionTime": "2017-01-19T05:34:58Z"
- },
- {
- "checksumSHA1": "VXFPGZtx+GKexkXeL3YljqJLHFk=",
- "path": "github.com/ginuerzh/gost",
- "revision": "dc75931858cf96d95525faa22b7ffa0cea3e7d68",
- "revisionTime": "2017-01-25T04:21:04Z"
- },
- {
- "checksumSHA1": "URsJa4y/sUUw/STmbeYx9EKqaYE=",
- "path": "github.com/golang/glog",
- "revision": "44145f04b68cf362d9c4df2182967c2275eaefed",
- "revisionTime": "2014-09-23T20:47:00Z"
- },
- {
- "checksumSHA1": "d9PxF1XQGLMJZRct2R8qVM/eYlE=",
- "path": "github.com/hashicorp/golang-lru",
- "revision": "0a025b7e63adc15a622f29b0b2c4c3848243bbf6",
- "revisionTime": "2016-08-13T22:13:03Z"
- },
- {
- "checksumSHA1": "9hffs0bAIU6CquiRhKQdzjHnKt0=",
- "path": "github.com/hashicorp/golang-lru/simplelru",
- "revision": "0a025b7e63adc15a622f29b0b2c4c3848243bbf6",
- "revisionTime": "2016-08-13T22:13:03Z"
- },
- {
- "checksumSHA1": "/EgCTbjJkJh2yi9lqEgzmau8O4I=",
- "path": "github.com/klauspost/compress/snappy",
- "revision": "1e658061989f47658e69492cf63a839630a25eba",
- "revisionTime": "2016-10-20T15:14:30Z"
- },
- {
- "checksumSHA1": "iKPMvbAueGfdyHcWCgzwKzm8WVo=",
- "path": "github.com/klauspost/cpuid",
- "revision": "09cded8978dc9e80714c4d85b0322337b0a1e5e0",
- "revisionTime": "2016-03-02T07:53:16Z"
- },
- {
- "checksumSHA1": "BM6ZlNJmtKy3GBoWwg2X55gnZ4A=",
- "path": "github.com/klauspost/crc32",
- "revision": "cb6bfca970f6908083f26f39a79009d608efd5cd",
- "revisionTime": "2016-10-16T15:41:25Z"
- },
- {
- "checksumSHA1": "dwSGkUfh3A2h0VkXndzBX/27hVc=",
- "path": "github.com/klauspost/reedsolomon",
- "revision": "c54154da9e35cab25232314cf69ab9d78447f9a5",
- "revisionTime": "2016-09-12T19:31:07Z"
- },
- {
- "checksumSHA1": "fbae4URna3lp8RtTOutiXIO1JS0=",
- "path": "github.com/lucas-clemente/aes12",
- "revision": "8ee5b5610baca43b60ecfad586b3c40d92a96e0c",
- "revisionTime": "2016-08-23T09:51:02Z"
- },
- {
- "checksumSHA1": "ne1X+frkx5fJcpz9FaZPuUZ7amM=",
- "path": "github.com/lucas-clemente/fnv128a",
- "revision": "393af48d391698c6ae4219566bfbdfef67269997",
- "revisionTime": "2016-05-04T15:23:51Z"
- },
- {
- "checksumSHA1": "xbX/mARowOKpW3S1G8hmaDlWdp8=",
- "path": "github.com/lucas-clemente/quic-go",
- "revision": "ef977ee0591f72543f8323cd12a585f5406ff971",
- "revisionTime": "2016-10-14T09:35:10Z"
- },
- {
- "checksumSHA1": "OA9E+y7g05x/mWJJHmA7oPxWKQo=",
- "path": "github.com/lucas-clemente/quic-go-certificates",
- "revision": "d2f86524cced5186554df90d92529757d22c1cb6",
- "revisionTime": "2016-08-23T09:51:56Z"
- },
- {
- "checksumSHA1": "1+iOTf/w8VXGqQao0FMNEE2RFFg=",
- "path": "github.com/lucas-clemente/quic-go/ackhandler",
- "revision": "ef977ee0591f72543f8323cd12a585f5406ff971",
- "revisionTime": "2016-10-14T09:35:10Z"
- },
- {
- "checksumSHA1": "8zoU6uLKP2Czs96VgmNMubNcWKk=",
- "path": "github.com/lucas-clemente/quic-go/congestion",
- "revision": "ef977ee0591f72543f8323cd12a585f5406ff971",
- "revisionTime": "2016-10-14T09:35:10Z"
- },
- {
- "checksumSHA1": "vzBxE7JViWonmrSndgmRuye8ntA=",
- "path": "github.com/lucas-clemente/quic-go/crypto",
- "revision": "ef977ee0591f72543f8323cd12a585f5406ff971",
- "revisionTime": "2016-10-14T09:35:10Z"
- },
- {
- "checksumSHA1": "CaOt7EZEuyWQ073FITB8qQfFswA=",
- "path": "github.com/lucas-clemente/quic-go/flowcontrol",
- "revision": "ef977ee0591f72543f8323cd12a585f5406ff971",
- "revisionTime": "2016-10-14T09:35:10Z"
- },
- {
- "checksumSHA1": "VvhIOTKtMkPZ7pdrCPHlDQI2wIw=",
- "path": "github.com/lucas-clemente/quic-go/frames",
- "revision": "ef977ee0591f72543f8323cd12a585f5406ff971",
- "revisionTime": "2016-10-14T09:35:10Z"
- },
- {
- "checksumSHA1": "IJDUjsrJP5dtHvxVNT32x4SQQVk=",
- "path": "github.com/lucas-clemente/quic-go/h2quic",
- "revision": "ef977ee0591f72543f8323cd12a585f5406ff971",
- "revisionTime": "2016-10-14T09:35:10Z"
- },
- {
- "checksumSHA1": "1DQTvvwcUUrmMKkN4ASjX5+iGqs=",
- "path": "github.com/lucas-clemente/quic-go/handshake",
- "revision": "ef977ee0591f72543f8323cd12a585f5406ff971",
- "revisionTime": "2016-10-14T09:35:10Z"
- },
- {
- "checksumSHA1": "qp5LXpuvIAgW3BffRzHVZQk1WfE=",
- "path": "github.com/lucas-clemente/quic-go/protocol",
- "revision": "ef977ee0591f72543f8323cd12a585f5406ff971",
- "revisionTime": "2016-10-14T09:35:10Z"
- },
- {
- "checksumSHA1": "ss57bkTclCnmt9fVosYie/ehkoo=",
- "path": "github.com/lucas-clemente/quic-go/qerr",
- "revision": "ef977ee0591f72543f8323cd12a585f5406ff971",
- "revisionTime": "2016-10-14T09:35:10Z"
- },
- {
- "checksumSHA1": "j/A6Rfz4BWpt5rsR2j5kR0H2ZTI=",
- "path": "github.com/lucas-clemente/quic-go/utils",
- "revision": "ef977ee0591f72543f8323cd12a585f5406ff971",
- "revisionTime": "2016-10-14T09:35:10Z"
- },
- {
- "checksumSHA1": "ynJSWoF6v+3zMnh9R0QmmG6iGV8=",
- "path": "github.com/pkg/errors",
- "revision": "839d9e913e063e28dfd0e6c7b7512793e0a48be9",
- "revisionTime": "2016-10-02T05:25:12Z"
- },
- {
- "checksumSHA1": "MRsfMrdZwnnCTfIzT3czcj0lb0s=",
- "path": "github.com/shadowsocks/shadowsocks-go/shadowsocks",
- "revision": "97a5c71f80ba5f5b3e549f14a619fe557ff4f3c9",
- "revisionTime": "2017-01-21T20:35:16Z"
- },
- {
- "checksumSHA1": "JsJdKXhz87gWenMwBeejTOeNE7k=",
- "path": "golang.org/x/crypto/blowfish",
- "revision": "1150b8bd09e53aea1d415621adae9bad665061a1",
- "revisionTime": "2016-10-21T22:59:10Z"
- },
- {
- "checksumSHA1": "TT1rac6kpQp2vz24m5yDGUNQ/QQ=",
- "path": "golang.org/x/crypto/cast5",
- "revision": "1150b8bd09e53aea1d415621adae9bad665061a1",
- "revisionTime": "2016-10-21T22:59:10Z"
- },
- {
- "checksumSHA1": "dwOedwBJ1EIK9+S3t108Bx054Y8=",
- "path": "golang.org/x/crypto/curve25519",
- "revision": "1150b8bd09e53aea1d415621adae9bad665061a1",
- "revisionTime": "2016-10-21T22:59:10Z"
- },
- {
- "checksumSHA1": "4D8hxMIaSDEW5pCQk22Xj4DcDh4=",
- "path": "golang.org/x/crypto/hkdf",
- "revision": "1150b8bd09e53aea1d415621adae9bad665061a1",
- "revisionTime": "2016-10-21T22:59:10Z"
- },
- {
- "checksumSHA1": "1MGpGDQqnUoRpv7VEcQrXOBydXE=",
- "path": "golang.org/x/crypto/pbkdf2",
- "revision": "1150b8bd09e53aea1d415621adae9bad665061a1",
- "revisionTime": "2016-10-21T22:59:10Z"
- },
- {
- "checksumSHA1": "o5QDZYQhyiEt2jg1Fot34mR1rBg=",
- "path": "golang.org/x/crypto/salsa20",
- "revision": "1150b8bd09e53aea1d415621adae9bad665061a1",
- "revisionTime": "2016-10-21T22:59:10Z"
- },
- {
- "checksumSHA1": "w8PESKJweP+BCAxCYPU1QC08qUU=",
- "path": "golang.org/x/crypto/salsa20/salsa",
- "revision": "1150b8bd09e53aea1d415621adae9bad665061a1",
- "revisionTime": "2016-10-21T22:59:10Z"
- },
- {
- "checksumSHA1": "Iwv89z1aXYKaB936lnsmE2NcfqA=",
- "path": "golang.org/x/crypto/tea",
- "revision": "1150b8bd09e53aea1d415621adae9bad665061a1",
- "revisionTime": "2016-10-21T22:59:10Z"
- },
- {
- "checksumSHA1": "/qXTeb4Dp6W5qlttwaN+Yur36+A=",
- "path": "golang.org/x/crypto/twofish",
- "revision": "1150b8bd09e53aea1d415621adae9bad665061a1",
- "revisionTime": "2016-10-21T22:59:10Z"
- },
- {
- "checksumSHA1": "d37eTFvbbuPQcKt5vkgsx+6C4c0=",
- "path": "golang.org/x/crypto/xtea",
- "revision": "1150b8bd09e53aea1d415621adae9bad665061a1",
- "revisionTime": "2016-10-21T22:59:10Z"
- },
- {
- "checksumSHA1": "tK8eFmQ0JeKpR3P0TjiGobzlIh0=",
- "path": "golang.org/x/net/bpf",
- "revision": "65dfc08770ce66f74becfdff5f8ab01caef4e946",
- "revisionTime": "2016-10-24T22:38:16Z"
- },
- {
- "checksumSHA1": "N1akwAdrHVfPPrsFOhG2ouP21VA=",
- "path": "golang.org/x/net/http2",
- "revision": "60c41d1de8da134c05b7b40154a9a82bf5b7edb9",
- "revisionTime": "2017-01-10T03:16:11Z"
- },
- {
- "checksumSHA1": "HzuGD7AwgC0p1az1WAQnEFnEk98=",
- "path": "golang.org/x/net/http2/hpack",
- "revision": "65dfc08770ce66f74becfdff5f8ab01caef4e946",
- "revisionTime": "2016-10-24T22:38:16Z"
- },
- {
- "checksumSHA1": "GIGmSrYACByf5JDIP9ByBZksY80=",
- "path": "golang.org/x/net/idna",
- "revision": "65dfc08770ce66f74becfdff5f8ab01caef4e946",
- "revisionTime": "2016-10-24T22:38:16Z"
- },
- {
- "checksumSHA1": "yRuyntx9a59ugMi5NlN4ST0XRcI=",
- "path": "golang.org/x/net/internal/iana",
- "revision": "65dfc08770ce66f74becfdff5f8ab01caef4e946",
- "revisionTime": "2016-10-24T22:38:16Z"
- },
- {
- "checksumSHA1": "LVY0kRV5iwxDS3XQaBWxdzPemyc=",
- "path": "golang.org/x/net/internal/netreflect",
- "revision": "65dfc08770ce66f74becfdff5f8ab01caef4e946",
- "revisionTime": "2016-10-24T22:38:16Z"
- },
- {
- "checksumSHA1": "yzxKtJnG6O34n0gsbnoceGhASdQ=",
- "path": "golang.org/x/net/ipv4",
- "revision": "65dfc08770ce66f74becfdff5f8ab01caef4e946",
- "revisionTime": "2016-10-24T22:38:16Z"
- },
- {
- "checksumSHA1": "3xyuaSNmClqG4YWC7g0isQIbUTc=",
- "path": "golang.org/x/net/lex/httplex",
- "revision": "65dfc08770ce66f74becfdff5f8ab01caef4e946",
- "revisionTime": "2016-10-24T22:38:16Z"
- },
- {
- "checksumSHA1": "G/v7O8ukxRnqPUrKYmf+niQ+JNU=",
- "path": "gopkg.in/gorilla/websocket.v1",
- "revision": "3ab3a8b8831546bd18fd182c20687ca853b2bb13",
- "revisionTime": "2016-12-15T22:53:35Z"
- },
- {
- "checksumSHA1": "nkIlj9QTxHQ78Vb+VgjhXZ4rZ3E=",
- "path": "gopkg.in/xtaci/kcp-go.v2",
- "revision": "6610d527ea5c4890cf593796ff8ff1f10486bb68",
- "revisionTime": "2016-09-08T14:44:41Z"
- },
- {
- "checksumSHA1": "aIqXwA82JxLOXcgmuVSgcRqdJvU=",
- "path": "gopkg.in/xtaci/smux.v1",
- "revision": "9f2b528a60917e6446273926f4c676cac759d2b0",
- "revisionTime": "2016-09-22T10:26:45Z"
- }
- ],
- "rootPath": "github.com/ginuerzh/gost/cmd/gost"
-}
diff --git a/conn.go b/conn.go
deleted file mode 100644
index b5d41cb..0000000
--- a/conn.go
+++ /dev/null
@@ -1,263 +0,0 @@
-package gost
-
-import (
- "bufio"
- "crypto/tls"
- "encoding/base64"
- "errors"
- "github.com/ginuerzh/gosocks5"
- "github.com/golang/glog"
- ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
- "net"
- "net/http"
- "net/http/httputil"
- "net/url"
- "strconv"
- "strings"
- "sync"
- "time"
-)
-
-type ProxyConn struct {
- conn net.Conn
- Node ProxyNode
- handshaked bool
- handshakeMutex sync.Mutex
- handshakeErr error
-}
-
-func NewProxyConn(conn net.Conn, node ProxyNode) *ProxyConn {
- return &ProxyConn{
- conn: conn,
- Node: node,
- }
-}
-
-// Handshake handshake with this proxy node based on the proxy node info: transport, protocol, authentication, etc.
-//
-// NOTE: any HTTP2 scheme will be treated as http (for protocol) or tls (for transport).
-func (c *ProxyConn) Handshake() error {
- c.handshakeMutex.Lock()
- defer c.handshakeMutex.Unlock()
-
- if err := c.handshakeErr; err != nil {
- return err
- }
- if c.handshaked {
- return nil
- }
- c.handshakeErr = c.handshake()
- return c.handshakeErr
-}
-
-func (c *ProxyConn) handshake() error {
- var tlsUsed bool
-
- switch c.Node.Transport {
- case "ws": // websocket connection
- u := url.URL{Scheme: "ws", Host: c.Node.Addr, Path: "/ws"}
- conn, err := WebsocketClientConn(u.String(), c.conn, nil)
- if err != nil {
- return err
- }
- c.conn = conn
- case "wss": // websocket security
- tlsUsed = true
- u := url.URL{Scheme: "wss", Host: c.Node.Addr, Path: "/ws"}
- config := &tls.Config{
- InsecureSkipVerify: c.Node.insecureSkipVerify(),
- ServerName: c.Node.serverName,
- }
- conn, err := WebsocketClientConn(u.String(), c.conn, config)
- if err != nil {
- return err
- }
- c.conn = conn
- case "tls", "http2": // tls connection
- tlsUsed = true
- cfg := &tls.Config{
- InsecureSkipVerify: c.Node.insecureSkipVerify(),
- ServerName: c.Node.serverName,
- }
- c.conn = tls.Client(c.conn, cfg)
- case "h2": // same as http2, but just set a flag for later using.
- tlsUsed = true
- case "kcp": // kcp connection
- tlsUsed = true
- case "obfs4":
- conn, err := c.Node.Obfs4ClientConn(c.conn)
- if err != nil {
- return err
- }
- c.conn = conn
- default:
- }
-
- switch c.Node.Protocol {
- case "socks", "socks5": // socks5 handshake with auth and tls supported
- selector := &clientSelector{
- methods: []uint8{
- gosocks5.MethodNoAuth,
- gosocks5.MethodUserPass,
- //MethodTLS,
- },
- }
-
- if len(c.Node.Users) > 0 {
- selector.user = c.Node.Users[0]
- }
-
- if !tlsUsed { // if transport is not security, enable security socks5
- selector.methods = append(selector.methods, MethodTLS)
- selector.tlsConfig = &tls.Config{
- InsecureSkipVerify: c.Node.insecureSkipVerify(),
- ServerName: c.Node.serverName,
- }
- }
-
- conn := gosocks5.ClientConn(c.conn, selector)
- if err := conn.Handleshake(); err != nil {
- return err
- }
- c.conn = conn
- case "ss": // shadowsocks
- // nothing to do
- case "http", "http2":
- fallthrough
- default:
- }
-
- c.handshaked = true
-
- return nil
-}
-
-// Connect connect to addr through this proxy node
-func (c *ProxyConn) Connect(addr string) error {
- switch c.Node.Protocol {
- case "ss": // shadowsocks
- rawaddr, err := ss.RawAddr(addr)
- if err != nil {
- return err
- }
-
- var method, password string
- if len(c.Node.Users) > 0 {
- method = c.Node.Users[0].Username()
- password, _ = c.Node.Users[0].Password()
- }
- if c.Node.getBool("ota") && !strings.HasSuffix(method, "-auth") {
- method += "-auth"
- }
-
- cipher, err := ss.NewCipher(method, password)
- if err != nil {
- return err
- }
-
- ssc, err := ss.DialWithRawAddrConn(rawaddr, c.conn, cipher)
- if err != nil {
- return err
- }
- c.conn = &shadowConn{conn: ssc}
- return nil
- case "socks", "socks5":
- host, port, err := net.SplitHostPort(addr)
- if err != nil {
- return err
- }
- p, _ := strconv.Atoi(port)
- req := gosocks5.NewRequest(gosocks5.CmdConnect, &gosocks5.Addr{
- Type: gosocks5.AddrDomain,
- Host: host,
- Port: uint16(p),
- })
- if err := req.Write(c); err != nil {
- return err
- }
- glog.V(LDEBUG).Infoln("[socks5]", req)
-
- reply, err := gosocks5.ReadReply(c)
- if err != nil {
- return err
- }
- glog.V(LDEBUG).Infoln("[socks5]", reply)
- if reply.Rep != gosocks5.Succeeded {
- return errors.New("Service unavailable")
- }
- case "http":
- fallthrough
- default:
- req := &http.Request{
- Method: http.MethodConnect,
- URL: &url.URL{Host: addr},
- Host: addr,
- ProtoMajor: 1,
- ProtoMinor: 1,
- Header: make(http.Header),
- }
- req.Header.Set("Proxy-Connection", "keep-alive")
- if len(c.Node.Users) > 0 {
- user := c.Node.Users[0]
- s := user.String()
- if _, set := user.Password(); !set {
- s += ":"
- }
- req.Header.Set("Proxy-Authorization",
- "Basic "+base64.StdEncoding.EncodeToString([]byte(s)))
- }
- if err := req.Write(c); err != nil {
- return err
- }
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpRequest(req, false)
- glog.Infoln(string(dump))
- }
-
- resp, err := http.ReadResponse(bufio.NewReader(c), req)
- if err != nil {
- return err
- }
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpResponse(resp, false)
- glog.Infoln(string(dump))
- }
- if resp.StatusCode != http.StatusOK {
- return errors.New(resp.Status)
- }
- }
-
- return nil
-}
-
-func (c *ProxyConn) Read(b []byte) (n int, err error) {
- return c.conn.Read(b)
-}
-
-func (c *ProxyConn) Write(b []byte) (n int, err error) {
- return c.conn.Write(b)
-}
-
-func (c *ProxyConn) Close() error {
- return c.conn.Close()
-}
-
-func (c *ProxyConn) LocalAddr() net.Addr {
- return c.conn.LocalAddr()
-}
-
-func (c *ProxyConn) RemoteAddr() net.Addr {
- return c.conn.RemoteAddr()
-}
-
-func (c *ProxyConn) SetDeadline(t time.Time) error {
- return c.conn.SetDeadline(t)
-}
-
-func (c *ProxyConn) SetReadDeadline(t time.Time) error {
- return c.conn.SetReadDeadline(t)
-}
-
-func (c *ProxyConn) SetWriteDeadline(t time.Time) error {
- return c.conn.SetWriteDeadline(t)
-}
diff --git a/examples/bench/cli.go b/examples/bench/cli.go
new file mode 100644
index 0000000..57c189c
--- /dev/null
+++ b/examples/bench/cli.go
@@ -0,0 +1,220 @@
+package main
+
+import (
+ "bufio"
+ "flag"
+ "log"
+ "net/http"
+ "net/http/httputil"
+ "net/url"
+ "sync"
+ "time"
+
+ "github.com/ginuerzh/gost"
+ "golang.org/x/net/http2"
+)
+
+var (
+ requests, concurrency int
+ quiet bool
+ swg, ewg sync.WaitGroup
+)
+
+func init() {
+ log.SetFlags(log.LstdFlags | log.Lshortfile)
+
+ flag.IntVar(&requests, "n", 1, "Number of requests to perform")
+ flag.IntVar(&concurrency, "c", 1, "Number of multiple requests to make at a time")
+ flag.BoolVar(&quiet, "q", false, "quiet mode")
+ flag.BoolVar(&http2.VerboseLogs, "v", false, "HTTP2 verbose logs")
+ flag.BoolVar(&gost.Debug, "d", false, "debug mode")
+ flag.Parse()
+
+ if quiet {
+ gost.SetLogger(&gost.NopLogger{})
+ }
+}
+
+func main() {
+ chain := gost.NewChain(
+
+ /*
+ // http+tcp
+ gost.Node{
+ Addr: "127.0.0.1:18080",
+ Client: gost.NewClient(
+ gost.HTTPConnector(url.UserPassword("admin", "123456")),
+ gost.TCPTransporter(),
+ ),
+ },
+ */
+
+ /*
+ // socks5+tcp
+ gost.Node{
+ Addr: "127.0.0.1:11080",
+ Client: gost.NewClient(
+ gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
+ gost.TCPTransporter(),
+ ),
+ },
+ */
+
+ /*
+ // ss+tcp
+ gost.Node{
+ Addr: "127.0.0.1:18338",
+ Client: gost.NewClient(
+ gost.ShadowConnector(url.UserPassword("chacha20", "123456")),
+ gost.TCPTransporter(),
+ ),
+ },
+ */
+
+ /*
+ // http+ws
+ gost.Node{
+ Addr: "127.0.0.1:18000",
+ Client: gost.NewClient(
+ gost.HTTPConnector(url.UserPassword("admin", "123456")),
+ gost.WSTransporter(nil),
+ ),
+ },
+ */
+
+ /*
+ // http+wss
+ gost.Node{
+ Addr: "127.0.0.1:18443",
+ Client: gost.NewClient(
+ gost.HTTPConnector(url.UserPassword("admin", "123456")),
+ gost.WSSTransporter(nil),
+ ),
+ },
+ */
+
+ /*
+ // http+tls
+ gost.Node{
+ Addr: "127.0.0.1:11443",
+ Client: gost.NewClient(
+ gost.HTTPConnector(url.UserPassword("admin", "123456")),
+ gost.TLSTransporter(),
+ ),
+ },
+ */
+
+ /*
+ // http2
+ gost.Node{
+ Addr: "127.0.0.1:1443",
+ Client: &gost.Client{
+ Connector: gost.HTTP2Connector(url.UserPassword("admin", "123456")),
+ Transporter: gost.HTTP2Transporter(nil),
+ },
+ },
+ */
+
+ /*
+ // http+kcp
+ gost.Node{
+ Addr: "127.0.0.1:18388",
+ Client: gost.NewClient(
+ gost.HTTPConnector(nil),
+ gost.KCPTransporter(nil),
+ ),
+ },
+ */
+
+ /*
+ // http+ssh
+ gost.Node{
+ Addr: "127.0.0.1:12222",
+ Client: gost.NewClient(
+ gost.HTTPConnector(url.UserPassword("admin", "123456")),
+ gost.SSHTunnelTransporter(),
+ ),
+ },
+ */
+
+ /*
+ // http+quic
+ gost.Node{
+ Addr: "localhost:6121",
+ Client: &gost.Client{
+ Connector: gost.HTTPConnector(url.UserPassword("admin", "123456")),
+ Transporter: gost.QUICTransporter(nil),
+ },
+ },
+ */
+ // socks5+h2
+ gost.Node{
+ Addr: "localhost:8443",
+ Client: &gost.Client{
+ // Connector: gost.HTTPConnector(url.UserPassword("admin", "123456")),
+ Connector: gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
+ // Transporter: gost.H2CTransporter(), // HTTP2 h2c mode
+ Transporter: gost.H2Transporter(nil), // HTTP2 h2
+ },
+ },
+ )
+
+ total := 0
+ for total < requests {
+ if total+concurrency > requests {
+ concurrency = requests - total
+ }
+ startChan := make(chan struct{})
+ for i := 0; i < concurrency; i++ {
+ swg.Add(1)
+ ewg.Add(1)
+ go request(chain, startChan)
+ }
+
+ start := time.Now()
+ swg.Wait() // wait for workers ready
+ close(startChan) // start signal
+ ewg.Wait() // wait for workers done
+
+ duration := time.Since(start)
+ total += concurrency
+ log.Printf("%d/%d/%d requests done (%v/%v)", total, requests, concurrency, duration, duration/time.Duration(concurrency))
+ }
+}
+
+func request(chain *gost.Chain, start <-chan struct{}) {
+ defer ewg.Done()
+
+ swg.Done()
+ <-start
+
+ conn, err := chain.Dial("localhost:18888")
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ defer conn.Close()
+ //conn = tls.Client(conn, &tls.Config{InsecureSkipVerify: true})
+ req, err := http.NewRequest(http.MethodGet, "http://localhost:18888", nil)
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ if err := req.Write(conn); err != nil {
+ log.Println(err)
+ return
+ }
+ resp, err := http.ReadResponse(bufio.NewReader(conn), req)
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ defer resp.Body.Close()
+
+ if gost.Debug {
+ rb, _ := httputil.DumpRequest(req, true)
+ log.Println(string(rb))
+ rb, _ = httputil.DumpResponse(resp, true)
+ log.Println(string(rb))
+ }
+}
diff --git a/examples/bench/srv.go b/examples/bench/srv.go
new file mode 100644
index 0000000..e2bb953
--- /dev/null
+++ b/examples/bench/srv.go
@@ -0,0 +1,359 @@
+package main
+
+import (
+ "crypto/tls"
+ "flag"
+ "fmt"
+ "log"
+ "net/http"
+ "net/url"
+ "time"
+
+ "github.com/ginuerzh/gost"
+ "golang.org/x/net/http2"
+)
+
+var (
+ quiet bool
+)
+
+func init() {
+ log.SetFlags(log.LstdFlags | log.Lshortfile)
+
+ flag.BoolVar(&quiet, "q", false, "quiet mode")
+ flag.BoolVar(&gost.Debug, "d", false, "debug mode")
+ flag.BoolVar(&http2.VerboseLogs, "v", false, "HTTP2 verbose logs")
+ flag.Parse()
+
+ if quiet {
+ gost.SetLogger(&gost.NopLogger{})
+ }
+}
+
+func main() {
+ go httpServer()
+ go socks5Server()
+ go tlsServer()
+ go shadowServer()
+ go wsServer()
+ go wssServer()
+ go kcpServer()
+ go tcpForwardServer()
+ go tcpRemoteForwardServer()
+ // go rudpForwardServer()
+ // go tcpRedirectServer()
+ go sshTunnelServer()
+ go http2Server()
+ go http2TunnelServer()
+ go quicServer()
+ go shadowUDPServer()
+ go testServer()
+ select {}
+}
+
+func httpServer() {
+ s := &gost.Server{}
+ ln, err := gost.TCPListener(":18080")
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.HTTPHandler(
+ gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+func socks5Server() {
+ s := &gost.Server{}
+ ln, err := gost.TCPListener(":11080")
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.SOCKS5Handler(
+ gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
+ gost.TLSConfigHandlerOption(tlsConfig()),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+func shadowServer() {
+ s := &gost.Server{}
+ ln, err := gost.TCPListener(":18338")
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.ShadowHandler(
+ gost.UsersHandlerOption(url.UserPassword("chacha20", "123456")),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+func tlsServer() {
+ s := &gost.Server{}
+ ln, err := gost.TLSListener(":11443", tlsConfig())
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.HTTPHandler(
+ gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+func wsServer() {
+ s := &gost.Server{}
+ ln, err := gost.WSListener(":18000", nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.HTTPHandler(
+ gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+func wssServer() {
+ s := &gost.Server{}
+ ln, err := gost.WSSListener(":18443", tlsConfig(), nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.HTTPHandler(
+ gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+func kcpServer() {
+ s := &gost.Server{}
+ ln, err := gost.KCPListener(":18388", nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.HTTPHandler()
+ log.Fatal(s.Serve(ln, h))
+}
+
+func tcpForwardServer() {
+ s := &gost.Server{}
+ ln, err := gost.TCPListener(":2222")
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.TCPDirectForwardHandler("localhost:22")
+ log.Fatal(s.Serve(ln, h))
+}
+
+func tcpRemoteForwardServer() {
+ s := &gost.Server{}
+ ln, err := gost.TCPRemoteForwardListener(
+ ":1222",
+ /*
+ gost.NewChain(
+ gost.Node{
+ Protocol: "socks5",
+ Transport: "tcp",
+ Addr: "localhost:12345",
+ User: url.UserPassword("admin", "123456"),
+ Client: &gost.Client{
+ Connector: gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
+ Transporter: gost.TCPTransporter(),
+ },
+ },
+ ),
+ */
+ nil,
+ )
+ if err != nil {
+ log.Fatal()
+ }
+ h := gost.TCPRemoteForwardHandler(
+ ":22",
+ //gost.AddrHandlerOption("127.0.0.1:22"),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+func rudpForwardServer() {
+ s := &gost.Server{}
+ ln, err := gost.UDPRemoteForwardListener(
+ ":10053",
+ gost.NewChain(
+ gost.Node{
+ Protocol: "socks5",
+ Transport: "tcp",
+ Addr: "localhost:12345",
+ User: url.UserPassword("admin", "123456"),
+ Client: &gost.Client{
+ Connector: gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
+ Transporter: gost.TCPTransporter(),
+ },
+ },
+ ),
+ 30*time.Second,
+ )
+ if err != nil {
+ log.Fatal()
+ }
+ h := gost.UDPRemoteForwardHandler("localhost:53")
+ log.Fatal(s.Serve(ln, h))
+}
+
+func tcpRedirectServer() {
+ s := &gost.Server{}
+ ln, err := gost.TCPListener(":8008")
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.TCPRedirectHandler()
+ log.Fatal(s.Serve(ln, h))
+}
+
+func sshTunnelServer() {
+ s := &gost.Server{}
+ ln, err := gost.SSHTunnelListener(":12222", &gost.SSHConfig{TLSConfig: tlsConfig()})
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.HTTPHandler(
+ gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+func http2Server() {
+ // http2.VerboseLogs = true
+
+ s := &gost.Server{}
+ ln, err := gost.HTTP2Listener(":1443", tlsConfig())
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.HTTP2Handler(
+ gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+func http2TunnelServer() {
+ s := &gost.Server{}
+ ln, err := gost.H2Listener(":8443", tlsConfig()) // HTTP2 h2 mode
+ // ln, err := gost.H2CListener(":8443") // HTTP2 h2c mode
+ if err != nil {
+ log.Fatal(err)
+ }
+ // h := gost.HTTPHandler(
+ // gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
+ // )
+ h := gost.SOCKS5Handler(
+ gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
+ gost.TLSConfigHandlerOption(tlsConfig()),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+func quicServer() {
+ s := &gost.Server{}
+ ln, err := gost.QUICListener("localhost:6121", &gost.QUICConfig{TLSConfig: tlsConfig()})
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.HTTPHandler(
+ gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+func shadowUDPServer() {
+ s := &gost.Server{}
+ ln, err := gost.ShadowUDPListener(":18338", url.UserPassword("chacha20", "123456"), 30*time.Second)
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.ShadowUDPdHandler(
+ /*
+ gost.ChainHandlerOption(gost.NewChain(
+ gost.Node{
+ Protocol: "socks5",
+ Transport: "tcp",
+ Addr: "localhost:11080",
+ User: url.UserPassword("admin", "123456"),
+ Client: &gost.Client{
+ Connector: gost.SOCKS5Connector(url.UserPassword("admin", "123456")),
+ Transporter: gost.TCPTransporter(),
+ },
+ },
+ )),
+ */
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+var (
+ rawCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIC+jCCAeKgAwIBAgIRAMlREhz8Miu1FQozsxbeqyMwDQYJKoZIhvcNAQELBQAw
+EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNzA1MTkwNTM5MDJaFw0xODA1MTkwNTM5
+MDJaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCyfqvv0kDriciEAVIW6JaWYFCL9a19jj1wmAGmVGxV3kNsr01kpa6N
+0EBqnrcy7WknhCt1d43CqhKtTcXgJ/J9phZVxlizb8sUB85hm+MvP0N3HCg3f0Jw
+hLuMrPijS6xjyw0fKCK/p6OUYMIfo5cdqeZid2WV4Ozts5uRd6Dmy2kyBe8Zg1F4
+8YJGuTWZmL2L7uZUiPY4T3q9+1iucq3vUpxymVRi1BTXnTpx+C0GS8NNgeEmevHv
+482vHM5DNflAQ+mvGZvBVduq/AfirCDnt2DIZm1DcZXLrY9F3EPrlRZexmAhCDGR
+LIKnMmoGicBM11Aw1fDIfJAHynk43tjPAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIF
+oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuC
+CWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAAx8Lna8DcQv0bRB3L9i2+KRN
+l/UhPCoFagxk1cZore4p0w+1m7OgigOoTpg5jh78DzVDhScZlgJ0bBVYp5rojeJS
+cBDC9lCDcaXQfFmT5LykCAwIgw/gs+rw5Aq0y3D0m8CcqKosyZa9wnZ2cVy/+45w
+emcSdboc65ueZScv38/W7aTUoVRcjyRUv0jv0zW0EPnnDlluVkeZo9spBhiTTwoj
+b3zGODs6alTNIJwZIHNxxyOmfJPpVVp8BzGbMk7YBixSlZ/vbrrYV34TcSiy7J57
+lNNoVWM+OwiVk1+AEZfQDwaQfef5tsIkAZBUyITkkDKRhygtwM2110dejbEsgg==
+-----END CERTIFICATE-----`)
+ rawKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAsn6r79JA64nIhAFSFuiWlmBQi/WtfY49cJgBplRsVd5DbK9N
+ZKWujdBAap63Mu1pJ4QrdXeNwqoSrU3F4CfyfaYWVcZYs2/LFAfOYZvjLz9Ddxwo
+N39CcIS7jKz4o0usY8sNHygiv6ejlGDCH6OXHanmYndlleDs7bObkXeg5stpMgXv
+GYNRePGCRrk1mZi9i+7mVIj2OE96vftYrnKt71KccplUYtQU1506cfgtBkvDTYHh
+Jnrx7+PNrxzOQzX5QEPprxmbwVXbqvwH4qwg57dgyGZtQ3GVy62PRdxD65UWXsZg
+IQgxkSyCpzJqBonATNdQMNXwyHyQB8p5ON7YzwIDAQABAoIBAQCG4doj3Apa8z+n
+IShbT1+cOyQi34A+xOIA151Hh7xmFxN0afRd/iWt3JUQ/OcLgQRZbDM7DSD+3W5H
+r+G7xfQkpwFxx/T3g58+f7ehYx+GcJQWyhxJ88zNIkBnyb4KCAE5WBOOW9IGajPe
+yE9pgUGMlPsXpYoKfHIOHg+NGY1pWUGBfBNR2kGrbkpZMmyy5bGa8dyrwAFBFRru
+kcmmKvate8UlbRspFtd4nR/GQLTBrcDJ1k1i1Su/4BpDuDeK6LPI8ZRePGqbdcxk
+TS30lsdYozuGfjZ5Zu8lSIJ//+7RjfDg8r684dpWjpalq8Quen60ZrIs01CSbfyU
+k8gOzTHhAoGBAOKhp41wXveegq+WylSXFyngm4bzF4dVdTRsSbJVk7NaOx1vCU6o
+/xIHoGEQyLI6wF+EaHmY89/Qu6tSV97XyBbiKeskopv5iXS/BsWTHJ1VbCA1ZLmK
+HgGllEkS0xfc9AdB7b6/K7LxAAQVKP3DtN6+6pSDZh9Sv2M1j0DbhkNbAoGBAMmg
+HcMfExaaeskjHqyLudtKX+znwaIoumleOGuavohR4R+Fpk8Yv8Xhb5U7Yr4gk0vY
+CFmhp1WAi6QMZ/8jePlKKXl3Ney827luoKiMczp2DoYE0t0u2Kw3LfkNKfjADZ7d
+JI6xPJV9/X1erwjq+4UdKqrpOf05SY4nkBMcvr6dAoGAXzisvbDJNiFTp5Mj0Abr
+pJzKvBjHegVeCXi2PkfWlzUCQYu1zWcURO8PY7k5mik1SuzHONAbJ578Oy+N3AOt
+/m9oTXRHHmHqbzMUFU+KZlDN7XqBp7NwiCCZ/Vn7d7tOjP4Wdl68baL07sI1RupD
+xJNS3LOY5PBPmc+XMRkLgKECgYEAgBNDlJSCrZMHeAjlDTncn53I/VXiPD2e3BvL
+vx6W9UT9ueZN1GSmPO6M0MDeYmOS7VSXSUhUYQ28pkJzNTC1QbWITu4YxP7anBnX
+1/kPoQ0pAJzDzVharlqGy3M/PBHTFRzogfO3xkY35ZFlokaR6uayGcr42Q+w16nt
+7RYPXEkCgYEA3GQYirHnGZuQ952jMvduqnpgkJiSnr0fa+94Rwa1pAhxHLFMo5s4
+fqZOtqKPj2s5X1JR0VCey1ilCcaAhWeb3tXCpbYLZSbMtjtqwA6LUeGY+Xdupsjw
+cfWIcOfHsIm2kP+RCxEnZf1XwiN9wyJeiUKlE0dqmx9j7F0Bm+7YDhI=
+-----END RSA PRIVATE KEY-----`)
+)
+
+func tlsConfig() *tls.Config {
+ cert, err := tls.X509KeyPair(rawCert, rawKey)
+ if err != nil {
+ panic(err)
+ }
+ return &tls.Config{
+ Certificates: []tls.Certificate{cert},
+ PreferServerCipherSuites: true,
+ }
+}
+
+func testServer() {
+ s := &http.Server{
+ Addr: ":18888",
+ Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintln(w, "abcdefghijklmnopqrstuvwxyz")
+ }),
+ }
+ log.Fatal(s.ListenAndServe())
+}
diff --git a/examples/forward/direct/client.go b/examples/forward/direct/client.go
new file mode 100644
index 0000000..11cdf96
--- /dev/null
+++ b/examples/forward/direct/client.go
@@ -0,0 +1,34 @@
+package main
+
+import (
+ "log"
+
+ "github.com/ginuerzh/gost"
+)
+
+func main() {
+ tcpForward()
+}
+
+func tcpForward() {
+ chain := gost.NewChain(
+ gost.Node{
+ Addr: "localhost:11222",
+ Client: &gost.Client{
+ Connector: gost.SSHDirectForwardConnector(),
+ Transporter: gost.SSHForwardTransporter(),
+ },
+ },
+ )
+
+ s := &gost.Server{}
+ ln, err := gost.TCPListener(":11800")
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.TCPDirectForwardHandler(
+ "localhost:22",
+ gost.ChainHandlerOption(chain),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
diff --git a/examples/forward/direct/server.go b/examples/forward/direct/server.go
new file mode 100644
index 0000000..1427bc2
--- /dev/null
+++ b/examples/forward/direct/server.go
@@ -0,0 +1,82 @@
+package main
+
+import (
+ "crypto/tls"
+ "log"
+
+ "github.com/ginuerzh/gost"
+)
+
+func main() {
+ sshForwardServer()
+}
+
+func sshForwardServer() {
+ s := &gost.Server{}
+ ln, err := gost.TCPListener(":11222")
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.SSHForwardHandler(
+ gost.AddrHandlerOption(":11222"),
+ // gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
+ gost.TLSConfigHandlerOption(tlsConfig()),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+var (
+ rawCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIC+jCCAeKgAwIBAgIRAMlREhz8Miu1FQozsxbeqyMwDQYJKoZIhvcNAQELBQAw
+EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNzA1MTkwNTM5MDJaFw0xODA1MTkwNTM5
+MDJaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCyfqvv0kDriciEAVIW6JaWYFCL9a19jj1wmAGmVGxV3kNsr01kpa6N
+0EBqnrcy7WknhCt1d43CqhKtTcXgJ/J9phZVxlizb8sUB85hm+MvP0N3HCg3f0Jw
+hLuMrPijS6xjyw0fKCK/p6OUYMIfo5cdqeZid2WV4Ozts5uRd6Dmy2kyBe8Zg1F4
+8YJGuTWZmL2L7uZUiPY4T3q9+1iucq3vUpxymVRi1BTXnTpx+C0GS8NNgeEmevHv
+482vHM5DNflAQ+mvGZvBVduq/AfirCDnt2DIZm1DcZXLrY9F3EPrlRZexmAhCDGR
+LIKnMmoGicBM11Aw1fDIfJAHynk43tjPAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIF
+oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuC
+CWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAAx8Lna8DcQv0bRB3L9i2+KRN
+l/UhPCoFagxk1cZore4p0w+1m7OgigOoTpg5jh78DzVDhScZlgJ0bBVYp5rojeJS
+cBDC9lCDcaXQfFmT5LykCAwIgw/gs+rw5Aq0y3D0m8CcqKosyZa9wnZ2cVy/+45w
+emcSdboc65ueZScv38/W7aTUoVRcjyRUv0jv0zW0EPnnDlluVkeZo9spBhiTTwoj
+b3zGODs6alTNIJwZIHNxxyOmfJPpVVp8BzGbMk7YBixSlZ/vbrrYV34TcSiy7J57
+lNNoVWM+OwiVk1+AEZfQDwaQfef5tsIkAZBUyITkkDKRhygtwM2110dejbEsgg==
+-----END CERTIFICATE-----`)
+ rawKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAsn6r79JA64nIhAFSFuiWlmBQi/WtfY49cJgBplRsVd5DbK9N
+ZKWujdBAap63Mu1pJ4QrdXeNwqoSrU3F4CfyfaYWVcZYs2/LFAfOYZvjLz9Ddxwo
+N39CcIS7jKz4o0usY8sNHygiv6ejlGDCH6OXHanmYndlleDs7bObkXeg5stpMgXv
+GYNRePGCRrk1mZi9i+7mVIj2OE96vftYrnKt71KccplUYtQU1506cfgtBkvDTYHh
+Jnrx7+PNrxzOQzX5QEPprxmbwVXbqvwH4qwg57dgyGZtQ3GVy62PRdxD65UWXsZg
+IQgxkSyCpzJqBonATNdQMNXwyHyQB8p5ON7YzwIDAQABAoIBAQCG4doj3Apa8z+n
+IShbT1+cOyQi34A+xOIA151Hh7xmFxN0afRd/iWt3JUQ/OcLgQRZbDM7DSD+3W5H
+r+G7xfQkpwFxx/T3g58+f7ehYx+GcJQWyhxJ88zNIkBnyb4KCAE5WBOOW9IGajPe
+yE9pgUGMlPsXpYoKfHIOHg+NGY1pWUGBfBNR2kGrbkpZMmyy5bGa8dyrwAFBFRru
+kcmmKvate8UlbRspFtd4nR/GQLTBrcDJ1k1i1Su/4BpDuDeK6LPI8ZRePGqbdcxk
+TS30lsdYozuGfjZ5Zu8lSIJ//+7RjfDg8r684dpWjpalq8Quen60ZrIs01CSbfyU
+k8gOzTHhAoGBAOKhp41wXveegq+WylSXFyngm4bzF4dVdTRsSbJVk7NaOx1vCU6o
+/xIHoGEQyLI6wF+EaHmY89/Qu6tSV97XyBbiKeskopv5iXS/BsWTHJ1VbCA1ZLmK
+HgGllEkS0xfc9AdB7b6/K7LxAAQVKP3DtN6+6pSDZh9Sv2M1j0DbhkNbAoGBAMmg
+HcMfExaaeskjHqyLudtKX+znwaIoumleOGuavohR4R+Fpk8Yv8Xhb5U7Yr4gk0vY
+CFmhp1WAi6QMZ/8jePlKKXl3Ney827luoKiMczp2DoYE0t0u2Kw3LfkNKfjADZ7d
+JI6xPJV9/X1erwjq+4UdKqrpOf05SY4nkBMcvr6dAoGAXzisvbDJNiFTp5Mj0Abr
+pJzKvBjHegVeCXi2PkfWlzUCQYu1zWcURO8PY7k5mik1SuzHONAbJ578Oy+N3AOt
+/m9oTXRHHmHqbzMUFU+KZlDN7XqBp7NwiCCZ/Vn7d7tOjP4Wdl68baL07sI1RupD
+xJNS3LOY5PBPmc+XMRkLgKECgYEAgBNDlJSCrZMHeAjlDTncn53I/VXiPD2e3BvL
+vx6W9UT9ueZN1GSmPO6M0MDeYmOS7VSXSUhUYQ28pkJzNTC1QbWITu4YxP7anBnX
+1/kPoQ0pAJzDzVharlqGy3M/PBHTFRzogfO3xkY35ZFlokaR6uayGcr42Q+w16nt
+7RYPXEkCgYEA3GQYirHnGZuQ952jMvduqnpgkJiSnr0fa+94Rwa1pAhxHLFMo5s4
+fqZOtqKPj2s5X1JR0VCey1ilCcaAhWeb3tXCpbYLZSbMtjtqwA6LUeGY+Xdupsjw
+cfWIcOfHsIm2kP+RCxEnZf1XwiN9wyJeiUKlE0dqmx9j7F0Bm+7YDhI=
+-----END RSA PRIVATE KEY-----`)
+)
+
+func tlsConfig() *tls.Config {
+ cert, err := tls.X509KeyPair(rawCert, rawKey)
+ if err != nil {
+ panic(err)
+ }
+ return &tls.Config{Certificates: []tls.Certificate{cert}}
+}
diff --git a/examples/forward/remote/client.go b/examples/forward/remote/client.go
new file mode 100644
index 0000000..623a17b
--- /dev/null
+++ b/examples/forward/remote/client.go
@@ -0,0 +1,35 @@
+package main
+
+import (
+ "log"
+
+ "github.com/ginuerzh/gost"
+)
+
+func main() {
+ sshRemoteForward()
+}
+
+func sshRemoteForward() {
+ chain := gost.NewChain(
+ gost.Node{
+ Protocol: "forward",
+ Transport: "ssh",
+ Addr: "localhost:11222",
+ Client: &gost.Client{
+ Connector: gost.SSHRemoteForwardConnector(),
+ Transporter: gost.SSHForwardTransporter(),
+ },
+ },
+ )
+
+ s := &gost.Server{}
+ ln, err := gost.TCPRemoteForwardListener(":11800", chain)
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.TCPRemoteForwardHandler(
+ "localhost:10000",
+ )
+ log.Fatal(s.Serve(ln, h))
+}
diff --git a/examples/forward/remote/server.go b/examples/forward/remote/server.go
new file mode 100644
index 0000000..2268f49
--- /dev/null
+++ b/examples/forward/remote/server.go
@@ -0,0 +1,82 @@
+package main
+
+import (
+ "crypto/tls"
+ "log"
+
+ "github.com/ginuerzh/gost"
+)
+
+func main() {
+ sshRemoteForwardServer()
+}
+
+func sshRemoteForwardServer() {
+ s := &gost.Server{}
+ ln, err := gost.TCPListener(":11222")
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.SSHForwardHandler(
+ gost.AddrHandlerOption(":11222"),
+ // gost.UsersHandlerOption(url.UserPassword("admin", "123456")),
+ gost.TLSConfigHandlerOption(tlsConfig()),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+var (
+ rawCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIC+jCCAeKgAwIBAgIRAMlREhz8Miu1FQozsxbeqyMwDQYJKoZIhvcNAQELBQAw
+EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNzA1MTkwNTM5MDJaFw0xODA1MTkwNTM5
+MDJaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCyfqvv0kDriciEAVIW6JaWYFCL9a19jj1wmAGmVGxV3kNsr01kpa6N
+0EBqnrcy7WknhCt1d43CqhKtTcXgJ/J9phZVxlizb8sUB85hm+MvP0N3HCg3f0Jw
+hLuMrPijS6xjyw0fKCK/p6OUYMIfo5cdqeZid2WV4Ozts5uRd6Dmy2kyBe8Zg1F4
+8YJGuTWZmL2L7uZUiPY4T3q9+1iucq3vUpxymVRi1BTXnTpx+C0GS8NNgeEmevHv
+482vHM5DNflAQ+mvGZvBVduq/AfirCDnt2DIZm1DcZXLrY9F3EPrlRZexmAhCDGR
+LIKnMmoGicBM11Aw1fDIfJAHynk43tjPAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIF
+oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuC
+CWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAAx8Lna8DcQv0bRB3L9i2+KRN
+l/UhPCoFagxk1cZore4p0w+1m7OgigOoTpg5jh78DzVDhScZlgJ0bBVYp5rojeJS
+cBDC9lCDcaXQfFmT5LykCAwIgw/gs+rw5Aq0y3D0m8CcqKosyZa9wnZ2cVy/+45w
+emcSdboc65ueZScv38/W7aTUoVRcjyRUv0jv0zW0EPnnDlluVkeZo9spBhiTTwoj
+b3zGODs6alTNIJwZIHNxxyOmfJPpVVp8BzGbMk7YBixSlZ/vbrrYV34TcSiy7J57
+lNNoVWM+OwiVk1+AEZfQDwaQfef5tsIkAZBUyITkkDKRhygtwM2110dejbEsgg==
+-----END CERTIFICATE-----`)
+ rawKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAsn6r79JA64nIhAFSFuiWlmBQi/WtfY49cJgBplRsVd5DbK9N
+ZKWujdBAap63Mu1pJ4QrdXeNwqoSrU3F4CfyfaYWVcZYs2/LFAfOYZvjLz9Ddxwo
+N39CcIS7jKz4o0usY8sNHygiv6ejlGDCH6OXHanmYndlleDs7bObkXeg5stpMgXv
+GYNRePGCRrk1mZi9i+7mVIj2OE96vftYrnKt71KccplUYtQU1506cfgtBkvDTYHh
+Jnrx7+PNrxzOQzX5QEPprxmbwVXbqvwH4qwg57dgyGZtQ3GVy62PRdxD65UWXsZg
+IQgxkSyCpzJqBonATNdQMNXwyHyQB8p5ON7YzwIDAQABAoIBAQCG4doj3Apa8z+n
+IShbT1+cOyQi34A+xOIA151Hh7xmFxN0afRd/iWt3JUQ/OcLgQRZbDM7DSD+3W5H
+r+G7xfQkpwFxx/T3g58+f7ehYx+GcJQWyhxJ88zNIkBnyb4KCAE5WBOOW9IGajPe
+yE9pgUGMlPsXpYoKfHIOHg+NGY1pWUGBfBNR2kGrbkpZMmyy5bGa8dyrwAFBFRru
+kcmmKvate8UlbRspFtd4nR/GQLTBrcDJ1k1i1Su/4BpDuDeK6LPI8ZRePGqbdcxk
+TS30lsdYozuGfjZ5Zu8lSIJ//+7RjfDg8r684dpWjpalq8Quen60ZrIs01CSbfyU
+k8gOzTHhAoGBAOKhp41wXveegq+WylSXFyngm4bzF4dVdTRsSbJVk7NaOx1vCU6o
+/xIHoGEQyLI6wF+EaHmY89/Qu6tSV97XyBbiKeskopv5iXS/BsWTHJ1VbCA1ZLmK
+HgGllEkS0xfc9AdB7b6/K7LxAAQVKP3DtN6+6pSDZh9Sv2M1j0DbhkNbAoGBAMmg
+HcMfExaaeskjHqyLudtKX+znwaIoumleOGuavohR4R+Fpk8Yv8Xhb5U7Yr4gk0vY
+CFmhp1WAi6QMZ/8jePlKKXl3Ney827luoKiMczp2DoYE0t0u2Kw3LfkNKfjADZ7d
+JI6xPJV9/X1erwjq+4UdKqrpOf05SY4nkBMcvr6dAoGAXzisvbDJNiFTp5Mj0Abr
+pJzKvBjHegVeCXi2PkfWlzUCQYu1zWcURO8PY7k5mik1SuzHONAbJ578Oy+N3AOt
+/m9oTXRHHmHqbzMUFU+KZlDN7XqBp7NwiCCZ/Vn7d7tOjP4Wdl68baL07sI1RupD
+xJNS3LOY5PBPmc+XMRkLgKECgYEAgBNDlJSCrZMHeAjlDTncn53I/VXiPD2e3BvL
+vx6W9UT9ueZN1GSmPO6M0MDeYmOS7VSXSUhUYQ28pkJzNTC1QbWITu4YxP7anBnX
+1/kPoQ0pAJzDzVharlqGy3M/PBHTFRzogfO3xkY35ZFlokaR6uayGcr42Q+w16nt
+7RYPXEkCgYEA3GQYirHnGZuQ952jMvduqnpgkJiSnr0fa+94Rwa1pAhxHLFMo5s4
+fqZOtqKPj2s5X1JR0VCey1ilCcaAhWeb3tXCpbYLZSbMtjtqwA6LUeGY+Xdupsjw
+cfWIcOfHsIm2kP+RCxEnZf1XwiN9wyJeiUKlE0dqmx9j7F0Bm+7YDhI=
+-----END RSA PRIVATE KEY-----`)
+)
+
+func tlsConfig() *tls.Config {
+ cert, err := tls.X509KeyPair(rawCert, rawKey)
+ if err != nil {
+ panic(err)
+ }
+ return &tls.Config{Certificates: []tls.Certificate{cert}}
+}
diff --git a/examples/forward/udp/cli.go b/examples/forward/udp/cli.go
new file mode 100644
index 0000000..42dd16b
--- /dev/null
+++ b/examples/forward/udp/cli.go
@@ -0,0 +1,53 @@
+package main
+
+import (
+ "flag"
+ "log"
+ "net"
+ "time"
+)
+
+var (
+ concurrency int
+ saddr string
+)
+
+func init() {
+ log.SetFlags(log.LstdFlags | log.Lshortfile)
+
+ flag.StringVar(&saddr, "S", ":18080", "server address")
+ flag.IntVar(&concurrency, "c", 1, "Number of multiple echo to make at a time")
+ flag.Parse()
+}
+
+func main() {
+ for i := 0; i < concurrency; i++ {
+ go udpEchoLoop()
+ }
+ select{}
+}
+
+func udpEchoLoop() {
+ addr, err := net.ResolveUDPAddr("udp", saddr)
+ if err != nil {
+ log.Fatal(err)
+ }
+ conn, err := net.DialUDP("udp", nil, addr)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ msg := []byte(`abcdefghijklmnopqrstuvwxyz`)
+ for {
+ if _, err := conn.Write(msg); err != nil {
+ log.Fatal(err)
+ }
+ b := make([]byte, 1024)
+ _, err := conn.Read(b)
+ if err != nil {
+ log.Fatal(err)
+ }
+ // log.Println(string(b[:n]))
+ time.Sleep(100 * time.Millisecond)
+ }
+}
diff --git a/examples/forward/udp/direct.go b/examples/forward/udp/direct.go
new file mode 100644
index 0000000..c9da045
--- /dev/null
+++ b/examples/forward/udp/direct.go
@@ -0,0 +1,57 @@
+package main
+
+import (
+ "flag"
+ "log"
+ "time"
+
+ "github.com/ginuerzh/gost"
+)
+
+var (
+ laddr, faddr string
+ quiet bool
+)
+
+func init() {
+ log.SetFlags(log.LstdFlags | log.Lshortfile)
+
+ flag.StringVar(&laddr, "L", ":18080", "listen address")
+ flag.StringVar(&faddr, "F", ":8080", "forward address")
+ flag.BoolVar(&quiet, "q", false, "quiet mode")
+ flag.BoolVar(&gost.Debug, "d", false, "debug mode")
+ flag.Parse()
+
+ if quiet {
+ gost.SetLogger(&gost.NopLogger{})
+ }
+}
+func main() {
+ udpDirectForwardServer()
+}
+
+func udpDirectForwardServer() {
+ s := &gost.Server{}
+ ln, err := gost.UDPDirectForwardListener(laddr, time.Second*30)
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.UDPDirectForwardHandler(
+ faddr,
+ /*
+ gost.ChainHandlerOption(gost.NewChain(gost.Node{
+ Protocol: "socks5",
+ Transport: "tcp",
+ Addr: ":11080",
+ User: url.UserPassword("admin", "123456"),
+ Client: &gost.Client{
+ Connector: gost.SOCKS5Connector(
+ url.UserPassword("admin", "123456"),
+ ),
+ Transporter: gost.TCPTransporter(),
+ },
+ })),
+ */
+ )
+ log.Fatal(s.Serve(ln, h))
+}
diff --git a/examples/forward/udp/remote.go b/examples/forward/udp/remote.go
new file mode 100644
index 0000000..6ef3e36
--- /dev/null
+++ b/examples/forward/udp/remote.go
@@ -0,0 +1,60 @@
+package main
+
+import (
+ "flag"
+ "log"
+ "time"
+
+ "github.com/ginuerzh/gost"
+)
+
+var (
+ laddr, faddr string
+ quiet bool
+)
+
+func init() {
+ log.SetFlags(log.LstdFlags | log.Lshortfile)
+
+ flag.StringVar(&laddr, "L", ":18080", "listen address")
+ flag.StringVar(&faddr, "F", ":8080", "forward address")
+ flag.BoolVar(&quiet, "q", false, "quiet mode")
+ flag.BoolVar(&gost.Debug, "d", false, "debug mode")
+ flag.Parse()
+
+ if quiet {
+ gost.SetLogger(&gost.NopLogger{})
+ }
+}
+func main() {
+ udpRemoteForwardServer()
+}
+
+func udpRemoteForwardServer() {
+ s := &gost.Server{}
+ ln, err := gost.UDPRemoteForwardListener(
+ laddr,
+ /*
+ gost.NewChain(gost.Node{
+ Protocol: "socks5",
+ Transport: "tcp",
+ Addr: ":11080",
+ User: url.UserPassword("admin", "123456"),
+ Client: &gost.Client{
+ Connector: gost.SOCKS5Connector(
+ url.UserPassword("admin", "123456"),
+ ),
+ Transporter: gost.TCPTransporter(),
+ },
+ }),
+ */
+ nil,
+ time.Second*30)
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.UDPRemoteForwardHandler(
+ faddr,
+ )
+ log.Fatal(s.Serve(ln, h))
+}
diff --git a/examples/forward/udp/srv.go b/examples/forward/udp/srv.go
new file mode 100644
index 0000000..3aadf2d
--- /dev/null
+++ b/examples/forward/udp/srv.go
@@ -0,0 +1,44 @@
+package main
+
+import (
+ "flag"
+ "log"
+ "net"
+)
+
+var (
+ laddr string
+)
+
+func init() {
+ log.SetFlags(log.LstdFlags | log.Lshortfile)
+
+ flag.StringVar(&laddr, "L", ":8080", "listen address")
+ flag.Parse()
+}
+func main() {
+ udpEchoServer()
+}
+
+func udpEchoServer() {
+ addr, err := net.ResolveUDPAddr("udp", laddr)
+ if err != nil {
+ log.Fatal(err)
+ }
+ conn, err := net.ListenUDP("udp", addr)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ for {
+ b := make([]byte, 1024)
+ n, raddr, err := conn.ReadFromUDP(b)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if _, err = conn.WriteToUDP(b[:n], raddr); err != nil {
+ log.Fatal(err)
+ }
+
+ }
+}
diff --git a/examples/http2/http2.go b/examples/http2/http2.go
new file mode 100644
index 0000000..1d3f6c5
--- /dev/null
+++ b/examples/http2/http2.go
@@ -0,0 +1,125 @@
+package main
+
+import (
+ "crypto/tls"
+ "flag"
+ "log"
+ "net/url"
+
+ "golang.org/x/net/http2"
+
+ "github.com/ginuerzh/gost"
+)
+
+var (
+ quiet bool
+ keyFile, certFile string
+ laddr string
+ user, passwd string
+)
+
+func init() {
+ log.SetFlags(log.LstdFlags | log.Lshortfile)
+
+ flag.StringVar(&laddr, "L", ":1443", "listen address")
+ flag.StringVar(&user, "u", "", "username")
+ flag.StringVar(&passwd, "p", "", "password")
+ flag.BoolVar(&quiet, "q", false, "quiet mode")
+ flag.BoolVar(&gost.Debug, "d", false, "debug mode")
+ flag.BoolVar(&http2.VerboseLogs, "v", false, "HTTP2 verbose log")
+ flag.StringVar(&keyFile, "key", "key.pem", "TLS key file")
+ flag.StringVar(&certFile, "cert", "cert.pem", "TLS cert file")
+ flag.Parse()
+
+ if quiet {
+ gost.SetLogger(&gost.NopLogger{})
+ }
+}
+
+func main() {
+ http2Server()
+}
+
+func http2Server() {
+ cert, er := tls.LoadX509KeyPair(certFile, keyFile)
+ if er != nil {
+ log.Println(er)
+ cert, er = tls.X509KeyPair(rawCert, rawKey)
+ if er != nil {
+ panic(er)
+ }
+ }
+
+ s := &gost.Server{}
+ ln, err := gost.HTTP2Listener(laddr, &tls.Config{Certificates: []tls.Certificate{cert}})
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ var users []*url.Userinfo
+ if user != "" || passwd != "" {
+ users = append(users, url.UserPassword(user, passwd))
+ }
+
+ h := gost.HTTP2Handler(
+ gost.UsersHandlerOption(users...),
+ gost.AddrHandlerOption(laddr),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+var (
+ rawCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIC+jCCAeKgAwIBAgIRAMlREhz8Miu1FQozsxbeqyMwDQYJKoZIhvcNAQELBQAw
+EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNzA1MTkwNTM5MDJaFw0xODA1MTkwNTM5
+MDJaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCyfqvv0kDriciEAVIW6JaWYFCL9a19jj1wmAGmVGxV3kNsr01kpa6N
+0EBqnrcy7WknhCt1d43CqhKtTcXgJ/J9phZVxlizb8sUB85hm+MvP0N3HCg3f0Jw
+hLuMrPijS6xjyw0fKCK/p6OUYMIfo5cdqeZid2WV4Ozts5uRd6Dmy2kyBe8Zg1F4
+8YJGuTWZmL2L7uZUiPY4T3q9+1iucq3vUpxymVRi1BTXnTpx+C0GS8NNgeEmevHv
+482vHM5DNflAQ+mvGZvBVduq/AfirCDnt2DIZm1DcZXLrY9F3EPrlRZexmAhCDGR
+LIKnMmoGicBM11Aw1fDIfJAHynk43tjPAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIF
+oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuC
+CWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAAx8Lna8DcQv0bRB3L9i2+KRN
+l/UhPCoFagxk1cZore4p0w+1m7OgigOoTpg5jh78DzVDhScZlgJ0bBVYp5rojeJS
+cBDC9lCDcaXQfFmT5LykCAwIgw/gs+rw5Aq0y3D0m8CcqKosyZa9wnZ2cVy/+45w
+emcSdboc65ueZScv38/W7aTUoVRcjyRUv0jv0zW0EPnnDlluVkeZo9spBhiTTwoj
+b3zGODs6alTNIJwZIHNxxyOmfJPpVVp8BzGbMk7YBixSlZ/vbrrYV34TcSiy7J57
+lNNoVWM+OwiVk1+AEZfQDwaQfef5tsIkAZBUyITkkDKRhygtwM2110dejbEsgg==
+-----END CERTIFICATE-----`)
+ rawKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAsn6r79JA64nIhAFSFuiWlmBQi/WtfY49cJgBplRsVd5DbK9N
+ZKWujdBAap63Mu1pJ4QrdXeNwqoSrU3F4CfyfaYWVcZYs2/LFAfOYZvjLz9Ddxwo
+N39CcIS7jKz4o0usY8sNHygiv6ejlGDCH6OXHanmYndlleDs7bObkXeg5stpMgXv
+GYNRePGCRrk1mZi9i+7mVIj2OE96vftYrnKt71KccplUYtQU1506cfgtBkvDTYHh
+Jnrx7+PNrxzOQzX5QEPprxmbwVXbqvwH4qwg57dgyGZtQ3GVy62PRdxD65UWXsZg
+IQgxkSyCpzJqBonATNdQMNXwyHyQB8p5ON7YzwIDAQABAoIBAQCG4doj3Apa8z+n
+IShbT1+cOyQi34A+xOIA151Hh7xmFxN0afRd/iWt3JUQ/OcLgQRZbDM7DSD+3W5H
+r+G7xfQkpwFxx/T3g58+f7ehYx+GcJQWyhxJ88zNIkBnyb4KCAE5WBOOW9IGajPe
+yE9pgUGMlPsXpYoKfHIOHg+NGY1pWUGBfBNR2kGrbkpZMmyy5bGa8dyrwAFBFRru
+kcmmKvate8UlbRspFtd4nR/GQLTBrcDJ1k1i1Su/4BpDuDeK6LPI8ZRePGqbdcxk
+TS30lsdYozuGfjZ5Zu8lSIJ//+7RjfDg8r684dpWjpalq8Quen60ZrIs01CSbfyU
+k8gOzTHhAoGBAOKhp41wXveegq+WylSXFyngm4bzF4dVdTRsSbJVk7NaOx1vCU6o
+/xIHoGEQyLI6wF+EaHmY89/Qu6tSV97XyBbiKeskopv5iXS/BsWTHJ1VbCA1ZLmK
+HgGllEkS0xfc9AdB7b6/K7LxAAQVKP3DtN6+6pSDZh9Sv2M1j0DbhkNbAoGBAMmg
+HcMfExaaeskjHqyLudtKX+znwaIoumleOGuavohR4R+Fpk8Yv8Xhb5U7Yr4gk0vY
+CFmhp1WAi6QMZ/8jePlKKXl3Ney827luoKiMczp2DoYE0t0u2Kw3LfkNKfjADZ7d
+JI6xPJV9/X1erwjq+4UdKqrpOf05SY4nkBMcvr6dAoGAXzisvbDJNiFTp5Mj0Abr
+pJzKvBjHegVeCXi2PkfWlzUCQYu1zWcURO8PY7k5mik1SuzHONAbJ578Oy+N3AOt
+/m9oTXRHHmHqbzMUFU+KZlDN7XqBp7NwiCCZ/Vn7d7tOjP4Wdl68baL07sI1RupD
+xJNS3LOY5PBPmc+XMRkLgKECgYEAgBNDlJSCrZMHeAjlDTncn53I/VXiPD2e3BvL
+vx6W9UT9ueZN1GSmPO6M0MDeYmOS7VSXSUhUYQ28pkJzNTC1QbWITu4YxP7anBnX
+1/kPoQ0pAJzDzVharlqGy3M/PBHTFRzogfO3xkY35ZFlokaR6uayGcr42Q+w16nt
+7RYPXEkCgYEA3GQYirHnGZuQ952jMvduqnpgkJiSnr0fa+94Rwa1pAhxHLFMo5s4
+fqZOtqKPj2s5X1JR0VCey1ilCcaAhWeb3tXCpbYLZSbMtjtqwA6LUeGY+Xdupsjw
+cfWIcOfHsIm2kP+RCxEnZf1XwiN9wyJeiUKlE0dqmx9j7F0Bm+7YDhI=
+-----END RSA PRIVATE KEY-----`)
+)
+
+func tlsConfig() *tls.Config {
+ cert, err := tls.X509KeyPair(rawCert, rawKey)
+ if err != nil {
+ panic(err)
+ }
+ return &tls.Config{Certificates: []tls.Certificate{cert}}
+}
diff --git a/examples/quic/quicc.go b/examples/quic/quicc.go
new file mode 100644
index 0000000..5b25106
--- /dev/null
+++ b/examples/quic/quicc.go
@@ -0,0 +1,110 @@
+package main
+
+import (
+ "crypto/tls"
+ "flag"
+ "log"
+ "time"
+
+ "github.com/ginuerzh/gost"
+)
+
+var (
+ laddr, faddr string
+ quiet bool
+)
+
+func init() {
+ log.SetFlags(log.LstdFlags | log.Lshortfile)
+
+ flag.StringVar(&laddr, "L", ":18080", "listen address")
+ flag.StringVar(&faddr, "F", "localhost:6121", "forward address")
+ flag.BoolVar(&quiet, "q", false, "quiet mode")
+ flag.BoolVar(&gost.Debug, "d", false, "debug mode")
+ flag.Parse()
+
+ if quiet {
+ gost.SetLogger(&gost.NopLogger{})
+ }
+}
+
+func main() {
+ chain := gost.NewChain(
+ gost.Node{
+ Protocol: "socks5",
+ Transport: "quic",
+ Addr: faddr,
+ Client: &gost.Client{
+ Connector: gost.SOCKS5Connector(nil),
+ Transporter: gost.QUICTransporter(&gost.QUICConfig{Timeout: 30 * time.Second, KeepAlive: true}),
+ },
+ },
+ )
+
+ s := &gost.Server{}
+ ln, err := gost.TCPListener(laddr)
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.SOCKS5Handler(
+ gost.ChainHandlerOption(chain),
+ gost.TLSConfigHandlerOption(tlsConfig()),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+var (
+ rawCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIC+jCCAeKgAwIBAgIRAMlREhz8Miu1FQozsxbeqyMwDQYJKoZIhvcNAQELBQAw
+EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNzA1MTkwNTM5MDJaFw0xODA1MTkwNTM5
+MDJaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCyfqvv0kDriciEAVIW6JaWYFCL9a19jj1wmAGmVGxV3kNsr01kpa6N
+0EBqnrcy7WknhCt1d43CqhKtTcXgJ/J9phZVxlizb8sUB85hm+MvP0N3HCg3f0Jw
+hLuMrPijS6xjyw0fKCK/p6OUYMIfo5cdqeZid2WV4Ozts5uRd6Dmy2kyBe8Zg1F4
+8YJGuTWZmL2L7uZUiPY4T3q9+1iucq3vUpxymVRi1BTXnTpx+C0GS8NNgeEmevHv
+482vHM5DNflAQ+mvGZvBVduq/AfirCDnt2DIZm1DcZXLrY9F3EPrlRZexmAhCDGR
+LIKnMmoGicBM11Aw1fDIfJAHynk43tjPAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIF
+oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuC
+CWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAAx8Lna8DcQv0bRB3L9i2+KRN
+l/UhPCoFagxk1cZore4p0w+1m7OgigOoTpg5jh78DzVDhScZlgJ0bBVYp5rojeJS
+cBDC9lCDcaXQfFmT5LykCAwIgw/gs+rw5Aq0y3D0m8CcqKosyZa9wnZ2cVy/+45w
+emcSdboc65ueZScv38/W7aTUoVRcjyRUv0jv0zW0EPnnDlluVkeZo9spBhiTTwoj
+b3zGODs6alTNIJwZIHNxxyOmfJPpVVp8BzGbMk7YBixSlZ/vbrrYV34TcSiy7J57
+lNNoVWM+OwiVk1+AEZfQDwaQfef5tsIkAZBUyITkkDKRhygtwM2110dejbEsgg==
+-----END CERTIFICATE-----`)
+ rawKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAsn6r79JA64nIhAFSFuiWlmBQi/WtfY49cJgBplRsVd5DbK9N
+ZKWujdBAap63Mu1pJ4QrdXeNwqoSrU3F4CfyfaYWVcZYs2/LFAfOYZvjLz9Ddxwo
+N39CcIS7jKz4o0usY8sNHygiv6ejlGDCH6OXHanmYndlleDs7bObkXeg5stpMgXv
+GYNRePGCRrk1mZi9i+7mVIj2OE96vftYrnKt71KccplUYtQU1506cfgtBkvDTYHh
+Jnrx7+PNrxzOQzX5QEPprxmbwVXbqvwH4qwg57dgyGZtQ3GVy62PRdxD65UWXsZg
+IQgxkSyCpzJqBonATNdQMNXwyHyQB8p5ON7YzwIDAQABAoIBAQCG4doj3Apa8z+n
+IShbT1+cOyQi34A+xOIA151Hh7xmFxN0afRd/iWt3JUQ/OcLgQRZbDM7DSD+3W5H
+r+G7xfQkpwFxx/T3g58+f7ehYx+GcJQWyhxJ88zNIkBnyb4KCAE5WBOOW9IGajPe
+yE9pgUGMlPsXpYoKfHIOHg+NGY1pWUGBfBNR2kGrbkpZMmyy5bGa8dyrwAFBFRru
+kcmmKvate8UlbRspFtd4nR/GQLTBrcDJ1k1i1Su/4BpDuDeK6LPI8ZRePGqbdcxk
+TS30lsdYozuGfjZ5Zu8lSIJ//+7RjfDg8r684dpWjpalq8Quen60ZrIs01CSbfyU
+k8gOzTHhAoGBAOKhp41wXveegq+WylSXFyngm4bzF4dVdTRsSbJVk7NaOx1vCU6o
+/xIHoGEQyLI6wF+EaHmY89/Qu6tSV97XyBbiKeskopv5iXS/BsWTHJ1VbCA1ZLmK
+HgGllEkS0xfc9AdB7b6/K7LxAAQVKP3DtN6+6pSDZh9Sv2M1j0DbhkNbAoGBAMmg
+HcMfExaaeskjHqyLudtKX+znwaIoumleOGuavohR4R+Fpk8Yv8Xhb5U7Yr4gk0vY
+CFmhp1WAi6QMZ/8jePlKKXl3Ney827luoKiMczp2DoYE0t0u2Kw3LfkNKfjADZ7d
+JI6xPJV9/X1erwjq+4UdKqrpOf05SY4nkBMcvr6dAoGAXzisvbDJNiFTp5Mj0Abr
+pJzKvBjHegVeCXi2PkfWlzUCQYu1zWcURO8PY7k5mik1SuzHONAbJ578Oy+N3AOt
+/m9oTXRHHmHqbzMUFU+KZlDN7XqBp7NwiCCZ/Vn7d7tOjP4Wdl68baL07sI1RupD
+xJNS3LOY5PBPmc+XMRkLgKECgYEAgBNDlJSCrZMHeAjlDTncn53I/VXiPD2e3BvL
+vx6W9UT9ueZN1GSmPO6M0MDeYmOS7VSXSUhUYQ28pkJzNTC1QbWITu4YxP7anBnX
+1/kPoQ0pAJzDzVharlqGy3M/PBHTFRzogfO3xkY35ZFlokaR6uayGcr42Q+w16nt
+7RYPXEkCgYEA3GQYirHnGZuQ952jMvduqnpgkJiSnr0fa+94Rwa1pAhxHLFMo5s4
+fqZOtqKPj2s5X1JR0VCey1ilCcaAhWeb3tXCpbYLZSbMtjtqwA6LUeGY+Xdupsjw
+cfWIcOfHsIm2kP+RCxEnZf1XwiN9wyJeiUKlE0dqmx9j7F0Bm+7YDhI=
+-----END RSA PRIVATE KEY-----`)
+)
+
+func tlsConfig() *tls.Config {
+ cert, err := tls.X509KeyPair(rawCert, rawKey)
+ if err != nil {
+ panic(err)
+ }
+ return &tls.Config{Certificates: []tls.Certificate{cert}}
+}
diff --git a/examples/quic/quics.go b/examples/quic/quics.go
new file mode 100644
index 0000000..b40d455
--- /dev/null
+++ b/examples/quic/quics.go
@@ -0,0 +1,99 @@
+package main
+
+import (
+ "crypto/tls"
+ "flag"
+ "log"
+
+ "github.com/ginuerzh/gost"
+)
+
+var (
+ laddr string
+ quiet bool
+)
+
+func init() {
+ log.SetFlags(log.LstdFlags | log.Lshortfile)
+
+ flag.StringVar(&laddr, "L", ":6121", "listen address")
+ flag.BoolVar(&quiet, "q", false, "quiet mode")
+ flag.BoolVar(&gost.Debug, "d", false, "debug mode")
+
+ flag.Parse()
+
+ if quiet {
+ gost.SetLogger(&gost.NopLogger{})
+ }
+}
+
+func main() {
+ quicServer()
+}
+
+func quicServer() {
+ s := &gost.Server{}
+ ln, err := gost.QUICListener(laddr, &gost.QUICConfig{TLSConfig: tlsConfig()})
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.SOCKS5Handler(gost.TLSConfigHandlerOption(tlsConfig()))
+ log.Println("server listen on", laddr)
+ log.Fatal(s.Serve(ln, h))
+}
+
+var (
+ rawCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIC+jCCAeKgAwIBAgIRAMlREhz8Miu1FQozsxbeqyMwDQYJKoZIhvcNAQELBQAw
+EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNzA1MTkwNTM5MDJaFw0xODA1MTkwNTM5
+MDJaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCyfqvv0kDriciEAVIW6JaWYFCL9a19jj1wmAGmVGxV3kNsr01kpa6N
+0EBqnrcy7WknhCt1d43CqhKtTcXgJ/J9phZVxlizb8sUB85hm+MvP0N3HCg3f0Jw
+hLuMrPijS6xjyw0fKCK/p6OUYMIfo5cdqeZid2WV4Ozts5uRd6Dmy2kyBe8Zg1F4
+8YJGuTWZmL2L7uZUiPY4T3q9+1iucq3vUpxymVRi1BTXnTpx+C0GS8NNgeEmevHv
+482vHM5DNflAQ+mvGZvBVduq/AfirCDnt2DIZm1DcZXLrY9F3EPrlRZexmAhCDGR
+LIKnMmoGicBM11Aw1fDIfJAHynk43tjPAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIF
+oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuC
+CWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAAx8Lna8DcQv0bRB3L9i2+KRN
+l/UhPCoFagxk1cZore4p0w+1m7OgigOoTpg5jh78DzVDhScZlgJ0bBVYp5rojeJS
+cBDC9lCDcaXQfFmT5LykCAwIgw/gs+rw5Aq0y3D0m8CcqKosyZa9wnZ2cVy/+45w
+emcSdboc65ueZScv38/W7aTUoVRcjyRUv0jv0zW0EPnnDlluVkeZo9spBhiTTwoj
+b3zGODs6alTNIJwZIHNxxyOmfJPpVVp8BzGbMk7YBixSlZ/vbrrYV34TcSiy7J57
+lNNoVWM+OwiVk1+AEZfQDwaQfef5tsIkAZBUyITkkDKRhygtwM2110dejbEsgg==
+-----END CERTIFICATE-----`)
+ rawKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAsn6r79JA64nIhAFSFuiWlmBQi/WtfY49cJgBplRsVd5DbK9N
+ZKWujdBAap63Mu1pJ4QrdXeNwqoSrU3F4CfyfaYWVcZYs2/LFAfOYZvjLz9Ddxwo
+N39CcIS7jKz4o0usY8sNHygiv6ejlGDCH6OXHanmYndlleDs7bObkXeg5stpMgXv
+GYNRePGCRrk1mZi9i+7mVIj2OE96vftYrnKt71KccplUYtQU1506cfgtBkvDTYHh
+Jnrx7+PNrxzOQzX5QEPprxmbwVXbqvwH4qwg57dgyGZtQ3GVy62PRdxD65UWXsZg
+IQgxkSyCpzJqBonATNdQMNXwyHyQB8p5ON7YzwIDAQABAoIBAQCG4doj3Apa8z+n
+IShbT1+cOyQi34A+xOIA151Hh7xmFxN0afRd/iWt3JUQ/OcLgQRZbDM7DSD+3W5H
+r+G7xfQkpwFxx/T3g58+f7ehYx+GcJQWyhxJ88zNIkBnyb4KCAE5WBOOW9IGajPe
+yE9pgUGMlPsXpYoKfHIOHg+NGY1pWUGBfBNR2kGrbkpZMmyy5bGa8dyrwAFBFRru
+kcmmKvate8UlbRspFtd4nR/GQLTBrcDJ1k1i1Su/4BpDuDeK6LPI8ZRePGqbdcxk
+TS30lsdYozuGfjZ5Zu8lSIJ//+7RjfDg8r684dpWjpalq8Quen60ZrIs01CSbfyU
+k8gOzTHhAoGBAOKhp41wXveegq+WylSXFyngm4bzF4dVdTRsSbJVk7NaOx1vCU6o
+/xIHoGEQyLI6wF+EaHmY89/Qu6tSV97XyBbiKeskopv5iXS/BsWTHJ1VbCA1ZLmK
+HgGllEkS0xfc9AdB7b6/K7LxAAQVKP3DtN6+6pSDZh9Sv2M1j0DbhkNbAoGBAMmg
+HcMfExaaeskjHqyLudtKX+znwaIoumleOGuavohR4R+Fpk8Yv8Xhb5U7Yr4gk0vY
+CFmhp1WAi6QMZ/8jePlKKXl3Ney827luoKiMczp2DoYE0t0u2Kw3LfkNKfjADZ7d
+JI6xPJV9/X1erwjq+4UdKqrpOf05SY4nkBMcvr6dAoGAXzisvbDJNiFTp5Mj0Abr
+pJzKvBjHegVeCXi2PkfWlzUCQYu1zWcURO8PY7k5mik1SuzHONAbJ578Oy+N3AOt
+/m9oTXRHHmHqbzMUFU+KZlDN7XqBp7NwiCCZ/Vn7d7tOjP4Wdl68baL07sI1RupD
+xJNS3LOY5PBPmc+XMRkLgKECgYEAgBNDlJSCrZMHeAjlDTncn53I/VXiPD2e3BvL
+vx6W9UT9ueZN1GSmPO6M0MDeYmOS7VSXSUhUYQ28pkJzNTC1QbWITu4YxP7anBnX
+1/kPoQ0pAJzDzVharlqGy3M/PBHTFRzogfO3xkY35ZFlokaR6uayGcr42Q+w16nt
+7RYPXEkCgYEA3GQYirHnGZuQ952jMvduqnpgkJiSnr0fa+94Rwa1pAhxHLFMo5s4
+fqZOtqKPj2s5X1JR0VCey1ilCcaAhWeb3tXCpbYLZSbMtjtqwA6LUeGY+Xdupsjw
+cfWIcOfHsIm2kP+RCxEnZf1XwiN9wyJeiUKlE0dqmx9j7F0Bm+7YDhI=
+-----END RSA PRIVATE KEY-----`)
+)
+
+func tlsConfig() *tls.Config {
+ cert, err := tls.X509KeyPair(rawCert, rawKey)
+ if err != nil {
+ panic(err)
+ }
+ return &tls.Config{Certificates: []tls.Certificate{cert}}
+}
diff --git a/examples/ssh/sshc.go b/examples/ssh/sshc.go
new file mode 100644
index 0000000..137febf
--- /dev/null
+++ b/examples/ssh/sshc.go
@@ -0,0 +1,113 @@
+package main
+
+import (
+ "crypto/tls"
+ "flag"
+ "log"
+ "time"
+
+ "github.com/ginuerzh/gost"
+)
+
+var (
+ laddr, faddr string
+ quiet bool
+)
+
+func init() {
+ log.SetFlags(log.LstdFlags | log.Lshortfile)
+
+ flag.StringVar(&laddr, "L", ":18080", "listen address")
+ flag.StringVar(&faddr, "F", ":12222", "forward address")
+ flag.BoolVar(&quiet, "q", false, "quiet mode")
+ flag.BoolVar(&gost.Debug, "d", false, "debug mode")
+ flag.Parse()
+
+ if quiet {
+ gost.SetLogger(&gost.NopLogger{})
+ }
+}
+
+func main() {
+ chain := gost.NewChain(
+ gost.Node{
+ Protocol: "socks5",
+ Transport: "ssh",
+ Addr: faddr,
+ HandshakeOptions: []gost.HandshakeOption{
+ gost.IntervalHandshakeOption(30 * time.Second),
+ },
+ Client: &gost.Client{
+ Connector: gost.SOCKS5Connector(nil),
+ Transporter: gost.SSHTunnelTransporter(),
+ },
+ },
+ )
+
+ s := &gost.Server{}
+ ln, err := gost.TCPListener(laddr)
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.SOCKS5Handler(
+ gost.ChainHandlerOption(chain),
+ gost.TLSConfigHandlerOption(tlsConfig()),
+ )
+ log.Fatal(s.Serve(ln, h))
+}
+
+var (
+ rawCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIC+jCCAeKgAwIBAgIRAMlREhz8Miu1FQozsxbeqyMwDQYJKoZIhvcNAQELBQAw
+EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNzA1MTkwNTM5MDJaFw0xODA1MTkwNTM5
+MDJaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCyfqvv0kDriciEAVIW6JaWYFCL9a19jj1wmAGmVGxV3kNsr01kpa6N
+0EBqnrcy7WknhCt1d43CqhKtTcXgJ/J9phZVxlizb8sUB85hm+MvP0N3HCg3f0Jw
+hLuMrPijS6xjyw0fKCK/p6OUYMIfo5cdqeZid2WV4Ozts5uRd6Dmy2kyBe8Zg1F4
+8YJGuTWZmL2L7uZUiPY4T3q9+1iucq3vUpxymVRi1BTXnTpx+C0GS8NNgeEmevHv
+482vHM5DNflAQ+mvGZvBVduq/AfirCDnt2DIZm1DcZXLrY9F3EPrlRZexmAhCDGR
+LIKnMmoGicBM11Aw1fDIfJAHynk43tjPAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIF
+oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuC
+CWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAAx8Lna8DcQv0bRB3L9i2+KRN
+l/UhPCoFagxk1cZore4p0w+1m7OgigOoTpg5jh78DzVDhScZlgJ0bBVYp5rojeJS
+cBDC9lCDcaXQfFmT5LykCAwIgw/gs+rw5Aq0y3D0m8CcqKosyZa9wnZ2cVy/+45w
+emcSdboc65ueZScv38/W7aTUoVRcjyRUv0jv0zW0EPnnDlluVkeZo9spBhiTTwoj
+b3zGODs6alTNIJwZIHNxxyOmfJPpVVp8BzGbMk7YBixSlZ/vbrrYV34TcSiy7J57
+lNNoVWM+OwiVk1+AEZfQDwaQfef5tsIkAZBUyITkkDKRhygtwM2110dejbEsgg==
+-----END CERTIFICATE-----`)
+ rawKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAsn6r79JA64nIhAFSFuiWlmBQi/WtfY49cJgBplRsVd5DbK9N
+ZKWujdBAap63Mu1pJ4QrdXeNwqoSrU3F4CfyfaYWVcZYs2/LFAfOYZvjLz9Ddxwo
+N39CcIS7jKz4o0usY8sNHygiv6ejlGDCH6OXHanmYndlleDs7bObkXeg5stpMgXv
+GYNRePGCRrk1mZi9i+7mVIj2OE96vftYrnKt71KccplUYtQU1506cfgtBkvDTYHh
+Jnrx7+PNrxzOQzX5QEPprxmbwVXbqvwH4qwg57dgyGZtQ3GVy62PRdxD65UWXsZg
+IQgxkSyCpzJqBonATNdQMNXwyHyQB8p5ON7YzwIDAQABAoIBAQCG4doj3Apa8z+n
+IShbT1+cOyQi34A+xOIA151Hh7xmFxN0afRd/iWt3JUQ/OcLgQRZbDM7DSD+3W5H
+r+G7xfQkpwFxx/T3g58+f7ehYx+GcJQWyhxJ88zNIkBnyb4KCAE5WBOOW9IGajPe
+yE9pgUGMlPsXpYoKfHIOHg+NGY1pWUGBfBNR2kGrbkpZMmyy5bGa8dyrwAFBFRru
+kcmmKvate8UlbRspFtd4nR/GQLTBrcDJ1k1i1Su/4BpDuDeK6LPI8ZRePGqbdcxk
+TS30lsdYozuGfjZ5Zu8lSIJ//+7RjfDg8r684dpWjpalq8Quen60ZrIs01CSbfyU
+k8gOzTHhAoGBAOKhp41wXveegq+WylSXFyngm4bzF4dVdTRsSbJVk7NaOx1vCU6o
+/xIHoGEQyLI6wF+EaHmY89/Qu6tSV97XyBbiKeskopv5iXS/BsWTHJ1VbCA1ZLmK
+HgGllEkS0xfc9AdB7b6/K7LxAAQVKP3DtN6+6pSDZh9Sv2M1j0DbhkNbAoGBAMmg
+HcMfExaaeskjHqyLudtKX+znwaIoumleOGuavohR4R+Fpk8Yv8Xhb5U7Yr4gk0vY
+CFmhp1WAi6QMZ/8jePlKKXl3Ney827luoKiMczp2DoYE0t0u2Kw3LfkNKfjADZ7d
+JI6xPJV9/X1erwjq+4UdKqrpOf05SY4nkBMcvr6dAoGAXzisvbDJNiFTp5Mj0Abr
+pJzKvBjHegVeCXi2PkfWlzUCQYu1zWcURO8PY7k5mik1SuzHONAbJ578Oy+N3AOt
+/m9oTXRHHmHqbzMUFU+KZlDN7XqBp7NwiCCZ/Vn7d7tOjP4Wdl68baL07sI1RupD
+xJNS3LOY5PBPmc+XMRkLgKECgYEAgBNDlJSCrZMHeAjlDTncn53I/VXiPD2e3BvL
+vx6W9UT9ueZN1GSmPO6M0MDeYmOS7VSXSUhUYQ28pkJzNTC1QbWITu4YxP7anBnX
+1/kPoQ0pAJzDzVharlqGy3M/PBHTFRzogfO3xkY35ZFlokaR6uayGcr42Q+w16nt
+7RYPXEkCgYEA3GQYirHnGZuQ952jMvduqnpgkJiSnr0fa+94Rwa1pAhxHLFMo5s4
+fqZOtqKPj2s5X1JR0VCey1ilCcaAhWeb3tXCpbYLZSbMtjtqwA6LUeGY+Xdupsjw
+cfWIcOfHsIm2kP+RCxEnZf1XwiN9wyJeiUKlE0dqmx9j7F0Bm+7YDhI=
+-----END RSA PRIVATE KEY-----`)
+)
+
+func tlsConfig() *tls.Config {
+ cert, err := tls.X509KeyPair(rawCert, rawKey)
+ if err != nil {
+ panic(err)
+ }
+ return &tls.Config{Certificates: []tls.Certificate{cert}}
+}
diff --git a/examples/ssh/sshd.go b/examples/ssh/sshd.go
new file mode 100644
index 0000000..68f1f81
--- /dev/null
+++ b/examples/ssh/sshd.go
@@ -0,0 +1,99 @@
+package main
+
+import (
+ "crypto/tls"
+ "flag"
+ "log"
+
+ "github.com/ginuerzh/gost"
+)
+
+var (
+ laddr string
+ quiet bool
+)
+
+func init() {
+ log.SetFlags(log.LstdFlags | log.Lshortfile)
+
+ flag.StringVar(&laddr, "L", ":12222", "listen address")
+ flag.BoolVar(&quiet, "q", false, "quiet mode")
+ flag.BoolVar(&gost.Debug, "d", false, "debug mode")
+
+ flag.Parse()
+
+ if quiet {
+ gost.SetLogger(&gost.NopLogger{})
+ }
+}
+
+func main() {
+ sshTunnelServer()
+}
+
+func sshTunnelServer() {
+ s := &gost.Server{}
+ ln, err := gost.SSHTunnelListener(laddr, &gost.SSHConfig{TLSConfig: tlsConfig()})
+ if err != nil {
+ log.Fatal(err)
+ }
+ h := gost.SOCKS5Handler(gost.TLSConfigHandlerOption(tlsConfig()))
+ log.Println("server listen on", laddr)
+ log.Fatal(s.Serve(ln, h))
+}
+
+var (
+ rawCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIC+jCCAeKgAwIBAgIRAMlREhz8Miu1FQozsxbeqyMwDQYJKoZIhvcNAQELBQAw
+EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNzA1MTkwNTM5MDJaFw0xODA1MTkwNTM5
+MDJaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCyfqvv0kDriciEAVIW6JaWYFCL9a19jj1wmAGmVGxV3kNsr01kpa6N
+0EBqnrcy7WknhCt1d43CqhKtTcXgJ/J9phZVxlizb8sUB85hm+MvP0N3HCg3f0Jw
+hLuMrPijS6xjyw0fKCK/p6OUYMIfo5cdqeZid2WV4Ozts5uRd6Dmy2kyBe8Zg1F4
+8YJGuTWZmL2L7uZUiPY4T3q9+1iucq3vUpxymVRi1BTXnTpx+C0GS8NNgeEmevHv
+482vHM5DNflAQ+mvGZvBVduq/AfirCDnt2DIZm1DcZXLrY9F3EPrlRZexmAhCDGR
+LIKnMmoGicBM11Aw1fDIfJAHynk43tjPAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIF
+oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuC
+CWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAAx8Lna8DcQv0bRB3L9i2+KRN
+l/UhPCoFagxk1cZore4p0w+1m7OgigOoTpg5jh78DzVDhScZlgJ0bBVYp5rojeJS
+cBDC9lCDcaXQfFmT5LykCAwIgw/gs+rw5Aq0y3D0m8CcqKosyZa9wnZ2cVy/+45w
+emcSdboc65ueZScv38/W7aTUoVRcjyRUv0jv0zW0EPnnDlluVkeZo9spBhiTTwoj
+b3zGODs6alTNIJwZIHNxxyOmfJPpVVp8BzGbMk7YBixSlZ/vbrrYV34TcSiy7J57
+lNNoVWM+OwiVk1+AEZfQDwaQfef5tsIkAZBUyITkkDKRhygtwM2110dejbEsgg==
+-----END CERTIFICATE-----`)
+ rawKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAsn6r79JA64nIhAFSFuiWlmBQi/WtfY49cJgBplRsVd5DbK9N
+ZKWujdBAap63Mu1pJ4QrdXeNwqoSrU3F4CfyfaYWVcZYs2/LFAfOYZvjLz9Ddxwo
+N39CcIS7jKz4o0usY8sNHygiv6ejlGDCH6OXHanmYndlleDs7bObkXeg5stpMgXv
+GYNRePGCRrk1mZi9i+7mVIj2OE96vftYrnKt71KccplUYtQU1506cfgtBkvDTYHh
+Jnrx7+PNrxzOQzX5QEPprxmbwVXbqvwH4qwg57dgyGZtQ3GVy62PRdxD65UWXsZg
+IQgxkSyCpzJqBonATNdQMNXwyHyQB8p5ON7YzwIDAQABAoIBAQCG4doj3Apa8z+n
+IShbT1+cOyQi34A+xOIA151Hh7xmFxN0afRd/iWt3JUQ/OcLgQRZbDM7DSD+3W5H
+r+G7xfQkpwFxx/T3g58+f7ehYx+GcJQWyhxJ88zNIkBnyb4KCAE5WBOOW9IGajPe
+yE9pgUGMlPsXpYoKfHIOHg+NGY1pWUGBfBNR2kGrbkpZMmyy5bGa8dyrwAFBFRru
+kcmmKvate8UlbRspFtd4nR/GQLTBrcDJ1k1i1Su/4BpDuDeK6LPI8ZRePGqbdcxk
+TS30lsdYozuGfjZ5Zu8lSIJ//+7RjfDg8r684dpWjpalq8Quen60ZrIs01CSbfyU
+k8gOzTHhAoGBAOKhp41wXveegq+WylSXFyngm4bzF4dVdTRsSbJVk7NaOx1vCU6o
+/xIHoGEQyLI6wF+EaHmY89/Qu6tSV97XyBbiKeskopv5iXS/BsWTHJ1VbCA1ZLmK
+HgGllEkS0xfc9AdB7b6/K7LxAAQVKP3DtN6+6pSDZh9Sv2M1j0DbhkNbAoGBAMmg
+HcMfExaaeskjHqyLudtKX+znwaIoumleOGuavohR4R+Fpk8Yv8Xhb5U7Yr4gk0vY
+CFmhp1WAi6QMZ/8jePlKKXl3Ney827luoKiMczp2DoYE0t0u2Kw3LfkNKfjADZ7d
+JI6xPJV9/X1erwjq+4UdKqrpOf05SY4nkBMcvr6dAoGAXzisvbDJNiFTp5Mj0Abr
+pJzKvBjHegVeCXi2PkfWlzUCQYu1zWcURO8PY7k5mik1SuzHONAbJ578Oy+N3AOt
+/m9oTXRHHmHqbzMUFU+KZlDN7XqBp7NwiCCZ/Vn7d7tOjP4Wdl68baL07sI1RupD
+xJNS3LOY5PBPmc+XMRkLgKECgYEAgBNDlJSCrZMHeAjlDTncn53I/VXiPD2e3BvL
+vx6W9UT9ueZN1GSmPO6M0MDeYmOS7VSXSUhUYQ28pkJzNTC1QbWITu4YxP7anBnX
+1/kPoQ0pAJzDzVharlqGy3M/PBHTFRzogfO3xkY35ZFlokaR6uayGcr42Q+w16nt
+7RYPXEkCgYEA3GQYirHnGZuQ952jMvduqnpgkJiSnr0fa+94Rwa1pAhxHLFMo5s4
+fqZOtqKPj2s5X1JR0VCey1ilCcaAhWeb3tXCpbYLZSbMtjtqwA6LUeGY+Xdupsjw
+cfWIcOfHsIm2kP+RCxEnZf1XwiN9wyJeiUKlE0dqmx9j7F0Bm+7YDhI=
+-----END RSA PRIVATE KEY-----`)
+)
+
+func tlsConfig() *tls.Config {
+ cert, err := tls.X509KeyPair(rawCert, rawKey)
+ if err != nil {
+ panic(err)
+ }
+ return &tls.Config{Certificates: []tls.Certificate{cert}}
+}
diff --git a/examples/ssu/ssu.go b/examples/ssu/ssu.go
new file mode 100644
index 0000000..cae97d0
--- /dev/null
+++ b/examples/ssu/ssu.go
@@ -0,0 +1,65 @@
+package main
+
+import (
+ "bytes"
+ "log"
+ "net"
+ "strconv"
+
+ "github.com/ginuerzh/gosocks5"
+ ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
+)
+
+func main() {
+ ssuClient()
+}
+
+func ssuClient() {
+ addr, err := net.ResolveUDPAddr("udp", ":18338")
+ if err != nil {
+ log.Fatal(err)
+ }
+ laddr, _ := net.ResolveUDPAddr("udp", ":10800")
+ conn, err := net.ListenUDP("udp", laddr)
+ if err != nil {
+ log.Fatal(err)
+ }
+ cp, err := ss.NewCipher("chacha20", "123456")
+ if err != nil {
+ log.Fatal(err)
+ }
+ cc := ss.NewSecurePacketConn(conn, cp, false)
+
+ raddr, _ := net.ResolveUDPAddr("udp", ":8080")
+ msg := []byte(`abcdefghijklmnopqrstuvwxyz`)
+ dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(0, 0, toSocksAddr(raddr)), msg)
+ buf := bytes.Buffer{}
+ dgram.Write(&buf)
+ for {
+ log.Printf("%# x", buf.Bytes()[3:])
+ if _, err := cc.WriteTo(buf.Bytes()[3:], addr); err != nil {
+ log.Fatal(err)
+ }
+ b := make([]byte, 1024)
+ n, adr, err := cc.ReadFrom(b)
+ if err != nil {
+ log.Fatal(err)
+ }
+ log.Printf("%s: %# x", adr, b[:n])
+ }
+}
+
+func toSocksAddr(addr net.Addr) *gosocks5.Addr {
+ host := "0.0.0.0"
+ port := 0
+ if addr != nil {
+ h, p, _ := net.SplitHostPort(addr.String())
+ host = h
+ port, _ = strconv.Atoi(p)
+ }
+ return &gosocks5.Addr{
+ Type: gosocks5.AddrIPv4,
+ Host: host,
+ Port: uint16(port),
+ }
+}
diff --git a/forward.go b/forward.go
index ca76904..5c5e9a6 100644
--- a/forward.go
+++ b/forward.go
@@ -2,520 +2,662 @@ package gost
import (
"errors"
- "fmt"
- "github.com/ginuerzh/gosocks5"
- "github.com/golang/glog"
"net"
+ "sync"
"time"
+
+ "fmt"
+
+ "github.com/ginuerzh/gosocks5"
+ "github.com/go-log/log"
)
-type TcpForwardServer struct {
- Base *ProxyServer
- Handler func(conn net.Conn, raddr net.Addr)
+type tcpDirectForwardHandler struct {
+ raddr string
+ options *HandlerOptions
}
-func NewTcpForwardServer(base *ProxyServer) *TcpForwardServer {
- return &TcpForwardServer{Base: base}
+// TCPDirectForwardHandler creates a server Handler for TCP port forwarding server.
+// The raddr is the remote address that the server will forward to.
+func TCPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler {
+ h := &tcpDirectForwardHandler{
+ raddr: raddr,
+ options: &HandlerOptions{},
+ }
+ for _, opt := range opts {
+ opt(h.options)
+ }
+ return h
}
-func (s *TcpForwardServer) ListenAndServe() error {
- raddr, err := net.ResolveTCPAddr("tcp", s.Base.Node.Remote)
- if err != nil {
- return err
- }
-
- ln, err := net.Listen("tcp", s.Base.Node.Addr)
- if err != nil {
- return err
- }
- defer ln.Close()
-
- if s.Handler == nil {
- s.Handler = s.handleTcpForward
- }
-
- for {
- conn, err := ln.Accept()
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- continue
- }
- setKeepAlive(conn, KeepAliveTime)
-
- go s.Handler(conn, raddr)
- }
-}
-
-func (s *TcpForwardServer) handleTcpForward(conn net.Conn, raddr net.Addr) {
+func (h *tcpDirectForwardHandler) Handle(conn net.Conn) {
defer conn.Close()
- glog.V(LINFO).Infof("[tcp] %s - %s", conn.RemoteAddr(), raddr)
- cc, err := s.Base.Chain.Dial(raddr.String())
+ log.Logf("[tcp] %s - %s", conn.RemoteAddr(), h.raddr)
+ cc, err := h.options.Chain.Dial(h.raddr)
if err != nil {
- glog.V(LWARNING).Infof("[tcp] %s -> %s : %s", conn.RemoteAddr(), raddr, err)
+ log.Logf("[tcp] %s -> %s : %s", conn.RemoteAddr(), h.raddr, err)
return
}
defer cc.Close()
- glog.V(LINFO).Infof("[tcp] %s <-> %s", conn.RemoteAddr(), raddr)
- s.Base.transport(conn, cc)
- glog.V(LINFO).Infof("[tcp] %s >-< %s", conn.RemoteAddr(), raddr)
+ log.Logf("[tcp] %s <-> %s", conn.RemoteAddr(), h.raddr)
+ transport(conn, cc)
+ log.Logf("[tcp] %s >-< %s", conn.RemoteAddr(), h.raddr)
}
-type packet struct {
- srcAddr string // src address
- dstAddr string // dest address
- data []byte
+type udpDirectForwardHandler struct {
+ raddr string
+ options *HandlerOptions
}
-type cnode struct {
- chain *ProxyChain
- conn net.Conn
- srcAddr, dstAddr string
- rChan, wChan chan *packet
- err error
- ttl time.Duration
+// UDPDirectForwardHandler creates a server Handler for UDP port forwarding server.
+// The raddr is the remote address that the server will forward to.
+func UDPDirectForwardHandler(raddr string, opts ...HandlerOption) Handler {
+ h := &udpDirectForwardHandler{
+ raddr: raddr,
+ options: &HandlerOptions{},
+ }
+ for _, opt := range opts {
+ opt(h.options)
+ }
+ return h
}
-func (node *cnode) getUDPTunnel() (net.Conn, error) {
- conn, err := node.chain.GetConn()
- if err != nil {
- return nil, err
- }
-
- conn.SetWriteDeadline(time.Now().Add(WriteTimeout))
- if err = gosocks5.NewRequest(CmdUdpTun, nil).Write(conn); err != nil {
- conn.Close()
- return nil, err
- }
- conn.SetWriteDeadline(time.Time{})
-
- conn.SetReadDeadline(time.Now().Add(ReadTimeout))
- reply, err := gosocks5.ReadReply(conn)
- if err != nil {
- conn.Close()
- return nil, err
- }
- conn.SetReadDeadline(time.Time{})
-
- if reply.Rep != gosocks5.Succeeded {
- conn.Close()
- return nil, errors.New("UDP tunnel failure")
- }
-
- return conn, nil
-}
-
-func (node *cnode) run() {
- if len(node.chain.Nodes()) == 0 {
- lconn, err := net.ListenUDP("udp", nil)
- if err != nil {
- glog.V(LWARNING).Infof("[udp] %s -> %s : %s", node.srcAddr, node.dstAddr, err)
- node.err = err
- return
- }
- node.conn = lconn
- } else {
- tc, err := node.getUDPTunnel()
- if err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s -> %s : %s", node.srcAddr, node.dstAddr, err)
- node.err = err
- return
- }
- node.conn = tc
- }
-
- defer node.conn.Close()
-
- timer := time.NewTimer(node.ttl)
- errChan := make(chan error, 2)
-
- go func() {
- for {
- switch c := node.conn.(type) {
- case *net.UDPConn:
- b := make([]byte, MediumBufferSize)
- n, addr, err := c.ReadFromUDP(b)
- if err != nil {
- glog.V(LWARNING).Infof("[udp] %s <- %s : %s", node.srcAddr, node.dstAddr, err)
- node.err = err
- errChan <- err
- return
- }
-
- timer.Reset(node.ttl)
- glog.V(LDEBUG).Infof("[udp] %s <<< %s : length %d", node.srcAddr, addr, n)
-
- select {
- // swap srcAddr with dstAddr
- case node.rChan <- &packet{srcAddr: addr.String(), dstAddr: node.srcAddr, data: b[:n]}:
- case <-time.After(time.Second * 3):
- glog.V(LWARNING).Infof("[udp] %s <- %s : %s", node.srcAddr, node.dstAddr, "recv queue is full, discard")
- }
-
- default:
- dgram, err := gosocks5.ReadUDPDatagram(c)
- if err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", node.srcAddr, node.dstAddr, err)
- node.err = err
- errChan <- err
- return
- }
-
- timer.Reset(node.ttl)
- glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s : length %d", node.srcAddr, dgram.Header.Addr.String(), len(dgram.Data))
-
- select {
- // swap srcAddr with dstAddr
- case node.rChan <- &packet{srcAddr: dgram.Header.Addr.String(), dstAddr: node.srcAddr, data: dgram.Data}:
- case <-time.After(time.Second * 3):
- glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", node.srcAddr, node.dstAddr, "recv queue is full, discard")
- }
- }
- }
- }()
-
- go func() {
- for pkt := range node.wChan {
- timer.Reset(node.ttl)
-
- dstAddr, err := net.ResolveUDPAddr("udp", pkt.dstAddr)
- if err != nil {
- glog.V(LWARNING).Infof("[udp] %s -> %s : %s", pkt.srcAddr, pkt.dstAddr, err)
- continue
- }
-
- switch c := node.conn.(type) {
- case *net.UDPConn:
- if _, err := c.WriteToUDP(pkt.data, dstAddr); err != nil {
- glog.V(LWARNING).Infof("[udp] %s -> %s : %s", pkt.srcAddr, pkt.dstAddr, err)
- node.err = err
- errChan <- err
- return
- }
- glog.V(LDEBUG).Infof("[udp] %s >>> %s : length %d", pkt.srcAddr, pkt.dstAddr, len(pkt.data))
-
- default:
- dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(len(pkt.data)), 0, ToSocksAddr(dstAddr)), pkt.data)
- if err := dgram.Write(c); err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s -> %s : %s", pkt.srcAddr, pkt.dstAddr, err)
- node.err = err
- errChan <- err
- return
- }
- glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s : length %d", pkt.srcAddr, pkt.dstAddr, len(pkt.data))
- }
- }
- }()
-
- select {
- case <-errChan:
- case <-timer.C:
- }
-}
-
-type UdpForwardServer struct {
- Base *ProxyServer
- TTL int
-}
-
-func NewUdpForwardServer(base *ProxyServer, ttl int) *UdpForwardServer {
- return &UdpForwardServer{Base: base, TTL: ttl}
-}
-
-func (s *UdpForwardServer) ListenAndServe() error {
- laddr, err := net.ResolveUDPAddr("udp", s.Base.Node.Addr)
- if err != nil {
- return err
- }
-
- raddr, err := net.ResolveUDPAddr("udp", s.Base.Node.Remote)
- if err != nil {
- return err
- }
-
- conn, err := net.ListenUDP("udp", laddr)
- if err != nil {
- glog.V(LWARNING).Infof("[udp] %s -> %s : %s", laddr, raddr, err)
- return err
- }
+func (h *udpDirectForwardHandler) Handle(conn net.Conn) {
defer conn.Close()
- rChan, wChan := make(chan *packet, 128), make(chan *packet, 128)
- // start send queue
- go func(ch chan<- *packet) {
- for {
- b := make([]byte, MediumBufferSize)
- n, addr, err := conn.ReadFromUDP(b)
- if err != nil {
- glog.V(LWARNING).Infof("[udp] %s -> %s : %s", laddr, raddr, err)
- continue
- }
+ var cc net.Conn
+ if h.options.Chain.IsEmpty() {
+ raddr, err := net.ResolveUDPAddr("udp", h.raddr)
+ if err != nil {
+ log.Logf("[udp] %s - %s : %s", conn.LocalAddr(), h.raddr, err)
+ return
+ }
+ cc, err = net.DialUDP("udp", nil, raddr)
+ if err != nil {
+ log.Logf("[udp] %s - %s : %s", conn.LocalAddr(), h.raddr, err)
+ return
+ }
+ } else {
+ var err error
+ cc, err = getSOCKS5UDPTunnel(h.options.Chain, nil)
+ if err != nil {
+ log.Logf("[udp] %s - %s : %s", conn.LocalAddr(), h.raddr, err)
+ return
+ }
+ cc = &udpTunnelConn{Conn: cc, raddr: h.raddr}
+ }
+
+ defer cc.Close()
+
+ log.Logf("[udp] %s <-> %s", conn.RemoteAddr(), h.raddr)
+ transport(conn, cc)
+ log.Logf("[udp] %s >-< %s", conn.RemoteAddr(), h.raddr)
+}
+
+type tcpRemoteForwardHandler struct {
+ raddr string
+ options *HandlerOptions
+}
+
+// TCPRemoteForwardHandler creates a server Handler for TCP remote port forwarding server.
+// The raddr is the remote address that the server will forward to.
+func TCPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler {
+ h := &tcpRemoteForwardHandler{
+ raddr: raddr,
+ options: &HandlerOptions{},
+ }
+ for _, opt := range opts {
+ opt(h.options)
+ }
+ return h
+}
+
+func (h *tcpRemoteForwardHandler) Handle(conn net.Conn) {
+ defer conn.Close()
+
+ cc, err := net.DialTimeout("tcp", h.raddr, DialTimeout)
+ if err != nil {
+ log.Logf("[rtcp] %s -> %s : %s", conn.LocalAddr(), h.raddr, err)
+ return
+ }
+ defer cc.Close()
+
+ log.Logf("[rtcp] %s <-> %s", conn.LocalAddr(), h.raddr)
+ transport(cc, conn)
+ log.Logf("[rtcp] %s >-< %s", conn.LocalAddr(), h.raddr)
+}
+
+type udpRemoteForwardHandler struct {
+ raddr string
+ options *HandlerOptions
+}
+
+// UDPRemoteForwardHandler creates a server Handler for UDP remote port forwarding server.
+// The raddr is the remote address that the server will forward to.
+func UDPRemoteForwardHandler(raddr string, opts ...HandlerOption) Handler {
+ h := &udpRemoteForwardHandler{
+ raddr: raddr,
+ options: &HandlerOptions{},
+ }
+ for _, opt := range opts {
+ opt(h.options)
+ }
+ return h
+}
+
+func (h *udpRemoteForwardHandler) Handle(conn net.Conn) {
+ defer conn.Close()
+
+ raddr, err := net.ResolveUDPAddr("udp", h.raddr)
+ if err != nil {
+ log.Logf("[rudp] %s - %s : %s", conn.RemoteAddr(), h.raddr, err)
+ return
+ }
+ cc, err := net.DialUDP("udp", nil, raddr)
+ if err != nil {
+ log.Logf("[rudp] %s - %s : %s", conn.RemoteAddr(), h.raddr, err)
+ return
+ }
+
+ log.Logf("[rudp] %s <-> %s", conn.RemoteAddr(), h.raddr)
+ transport(conn, cc)
+ log.Logf("[rudp] %s >-< %s", conn.RemoteAddr(), h.raddr)
+}
+
+type udpDirectForwardListener struct {
+ ln net.PacketConn
+ conns map[string]*udpServerConn
+ connChan chan net.Conn
+ errChan chan error
+ ttl time.Duration
+}
+
+// UDPDirectForwardListener creates a Listener for UDP port forwarding server.
+func UDPDirectForwardListener(addr string, ttl time.Duration) (Listener, error) {
+ laddr, err := net.ResolveUDPAddr("udp", addr)
+ if err != nil {
+ return nil, err
+ }
+ ln, err := net.ListenUDP("udp", laddr)
+ if err != nil {
+ return nil, err
+ }
+ l := &udpDirectForwardListener{
+ ln: ln,
+ conns: make(map[string]*udpServerConn),
+ connChan: make(chan net.Conn, 1024),
+ errChan: make(chan error, 1),
+ ttl: ttl,
+ }
+ go l.listenLoop()
+ return l, nil
+}
+
+func (l *udpDirectForwardListener) listenLoop() {
+ for {
+ b := make([]byte, mediumBufferSize)
+ n, raddr, err := l.ln.ReadFrom(b)
+ if err != nil {
+ log.Logf("[udp] peer -> %s : %s", l.Addr(), err)
+ l.ln.Close()
+ l.errChan <- err
+ close(l.errChan)
+ return
+ }
+ if Debug {
+ log.Logf("[udp] %s >>> %s : length %d", raddr, l.Addr(), n)
+ }
+ conn, ok := l.conns[raddr.String()]
+ if !ok || conn.Closed() {
+ conn = newUDPServerConn(l.ln, raddr, l.ttl)
+ l.conns[raddr.String()] = conn
select {
- case ch <- &packet{srcAddr: addr.String(), dstAddr: raddr.String(), data: b[:n]}:
- case <-time.After(time.Second * 3):
- glog.V(LWARNING).Infof("[udp] %s -> %s : %s", addr, raddr, "send queue is full, discard")
+ case l.connChan <- conn:
+ default:
+ conn.Close()
+ log.Logf("[udp] %s - %s: connection queue is full", raddr, l.Addr())
}
}
- }(wChan)
- // start recv queue
- go func(ch <-chan *packet) {
- for pkt := range ch {
- dstAddr, err := net.ResolveUDPAddr("udp", pkt.dstAddr)
- if err != nil {
- glog.V(LWARNING).Infof("[udp] %s <- %s : %s", pkt.dstAddr, pkt.srcAddr, err)
- continue
- }
- if _, err := conn.WriteToUDP(pkt.data, dstAddr); err != nil {
- glog.V(LWARNING).Infof("[udp] %s <- %s : %s", pkt.dstAddr, pkt.srcAddr, err)
- return
- }
- }
- }(rChan)
-
- // mapping client to node
- m := make(map[string]*cnode)
-
- // start dispatcher
- for pkt := range wChan {
- // clear obsolete nodes
- for k, node := range m {
- if node != nil && node.err != nil {
- close(node.wChan)
- delete(m, k)
- glog.V(LINFO).Infof("[udp] clear node %s", k)
- }
- }
-
- node, ok := m[pkt.srcAddr]
- if !ok {
- node = &cnode{
- chain: s.Base.Chain,
- srcAddr: pkt.srcAddr,
- dstAddr: pkt.dstAddr,
- rChan: rChan,
- wChan: make(chan *packet, 32),
- ttl: time.Duration(s.TTL) * time.Second,
- }
- m[pkt.srcAddr] = node
- go node.run()
- glog.V(LINFO).Infof("[udp] %s -> %s : new client (%d)", pkt.srcAddr, pkt.dstAddr, len(m))
- }
select {
- case node.wChan <- pkt:
- case <-time.After(time.Second * 3):
- glog.V(LWARNING).Infof("[udp] %s -> %s : %s", pkt.srcAddr, pkt.dstAddr, "node send queue is full, discard")
+ case conn.rChan <- b[:n]:
+ default:
+ log.Logf("[udp] %s -> %s : read queue is full", raddr, l.Addr())
}
}
+}
+func (l *udpDirectForwardListener) Accept() (conn net.Conn, err error) {
+ var ok bool
+ select {
+ case conn = <-l.connChan:
+ case err, ok = <-l.errChan:
+ if !ok {
+ err = errors.New("accpet on closed listener")
+ }
+ }
+ return
+}
+
+func (l *udpDirectForwardListener) Addr() net.Addr {
+ return l.ln.LocalAddr()
+}
+
+func (l *udpDirectForwardListener) Close() error {
+ return l.ln.Close()
+}
+
+type udpServerConn struct {
+ conn net.PacketConn
+ raddr net.Addr
+ rChan, wChan chan []byte
+ closed chan struct{}
+ brokenChan chan struct{}
+ closeMutex sync.Mutex
+ ttl time.Duration
+ nopChan chan int
+}
+
+func newUDPServerConn(conn net.PacketConn, raddr net.Addr, ttl time.Duration) *udpServerConn {
+ c := &udpServerConn{
+ conn: conn,
+ raddr: raddr,
+ rChan: make(chan []byte, 128),
+ wChan: make(chan []byte, 128),
+ closed: make(chan struct{}),
+ brokenChan: make(chan struct{}),
+ nopChan: make(chan int),
+ ttl: ttl,
+ }
+ go c.writeLoop()
+ go c.ttlWait()
+ return c
+}
+
+func (c *udpServerConn) Read(b []byte) (n int, err error) {
+ select {
+ case bb := <-c.rChan:
+ n = copy(b, bb)
+ if n != len(bb) {
+ err = errors.New("read partial data")
+ return
+ }
+ case <-c.brokenChan:
+ err = errors.New("Broken pipe")
+ case <-c.closed:
+ err = errors.New("read from closed connection")
+ return
+ }
+
+ select {
+ case c.nopChan <- n:
+ default:
+ }
+ return
+}
+
+func (c *udpServerConn) Write(b []byte) (n int, err error) {
+ if len(b) == 0 {
+ return 0, nil
+ }
+ select {
+ case c.wChan <- b:
+ n = len(b)
+ case <-c.brokenChan:
+ err = errors.New("Broken pipe")
+ case <-c.closed:
+ err = errors.New("write to closed connection")
+ return
+ }
+
+ select {
+ case c.nopChan <- n:
+ default:
+ }
+
+ return
+}
+
+func (c *udpServerConn) Close() error {
+ c.closeMutex.Lock()
+ defer c.closeMutex.Unlock()
+
+ select {
+ case <-c.closed:
+ return errors.New("connection is closed")
+ default:
+ close(c.closed)
+ }
return nil
}
-type RTcpForwardServer struct {
- Base *ProxyServer
+func (c *udpServerConn) Closed() bool {
+ select {
+ case <-c.closed:
+ return true
+ default:
+ return false
+ }
}
-func NewRTcpForwardServer(base *ProxyServer) *RTcpForwardServer {
- return &RTcpForwardServer{Base: base}
-}
-
-func (s *RTcpForwardServer) Serve() error {
- if len(s.Base.Chain.nodes) == 0 {
- return errors.New("rtcp: at least one -F must be assigned")
- }
-
- laddr, err := net.ResolveTCPAddr("tcp", s.Base.Node.Addr)
- if err != nil {
- return err
- }
- raddr, err := net.ResolveTCPAddr("tcp", s.Base.Node.Remote)
- if err != nil {
- return err
- }
-
- retry := 0
+func (c *udpServerConn) writeLoop() {
for {
- conn, err := s.Base.Chain.GetConn()
- if err != nil {
- glog.V(LWARNING).Infof("[rtcp] %s - %s : %s", laddr, raddr, err)
- time.Sleep((1 << uint(retry)) * time.Second)
- if retry < 5 {
- retry++
+ select {
+ case b, ok := <-c.wChan:
+ if !ok {
+ return
}
+ n, err := c.conn.WriteTo(b, c.raddr)
+ if err != nil {
+ log.Logf("[udp] %s - %s : %s", c.RemoteAddr(), c.LocalAddr(), err)
+ return
+ }
+ if Debug {
+ log.Logf("[udp] %s <<< %s : length %d", c.RemoteAddr(), c.LocalAddr(), n)
+ }
+ case <-c.brokenChan:
+ return
+ case <-c.closed:
+ return
+ }
+ }
+}
+
+func (c *udpServerConn) ttlWait() {
+ ttl := c.ttl
+ if ttl == 0 {
+ ttl = defaultTTL
+ }
+ timer := time.NewTimer(ttl)
+
+ for {
+ select {
+ case <-c.nopChan:
+ timer.Reset(ttl)
+ case <-timer.C:
+ close(c.brokenChan)
+ return
+ case <-c.closed:
+ return
+ }
+ }
+}
+
+func (c *udpServerConn) LocalAddr() net.Addr {
+ return c.conn.LocalAddr()
+}
+
+func (c *udpServerConn) RemoteAddr() net.Addr {
+ return c.raddr
+}
+
+func (c *udpServerConn) SetDeadline(t time.Time) error {
+ return nil
+}
+
+func (c *udpServerConn) SetReadDeadline(t time.Time) error {
+ return nil
+}
+
+func (c *udpServerConn) SetWriteDeadline(t time.Time) error {
+ return nil
+}
+
+type tcpRemoteForwardListener struct {
+ addr net.Addr
+ chain *Chain
+ ln net.Listener
+ closed chan struct{}
+}
+
+// TCPRemoteForwardListener creates a Listener for TCP remote port forwarding server.
+func TCPRemoteForwardListener(addr string, chain *Chain) (Listener, error) {
+ laddr, err := net.ResolveTCPAddr("tcp", addr)
+ if err != nil {
+ return nil, err
+ }
+
+ return &tcpRemoteForwardListener{
+ addr: laddr,
+ chain: chain,
+ closed: make(chan struct{}),
+ }, nil
+}
+
+func (l *tcpRemoteForwardListener) Accept() (net.Conn, error) {
+ select {
+ case <-l.closed:
+ return nil, errors.New("closed")
+ default:
+ }
+
+ var tempDelay time.Duration
+ for {
+ conn, err := l.accept()
+ if err != nil {
+ if tempDelay == 0 {
+ tempDelay = 1000 * time.Millisecond
+ } else {
+ tempDelay *= 2
+ }
+ if max := 6 * time.Second; tempDelay > max {
+ tempDelay = max
+ }
+ log.Logf("[rtcp] Accept error: %v; retrying in %v", err, tempDelay)
+ time.Sleep(tempDelay)
continue
}
- retry = 0
-
- if err := s.connectRTcpForward(conn, laddr, raddr); err != nil {
- conn.Close()
- time.Sleep(6 * time.Second)
- }
+ return conn, nil
}
}
-func (s *RTcpForwardServer) connectRTcpForward(conn net.Conn, laddr, raddr net.Addr) error {
- glog.V(LINFO).Infof("[rtcp] %s - %s", laddr, raddr)
+func (l *tcpRemoteForwardListener) accept() (conn net.Conn, err error) {
+ lastNode := l.chain.LastNode()
+ if lastNode.Protocol == "forward" && lastNode.Transport == "ssh" {
+ conn, err = l.chain.Dial(l.addr.String())
+ } else if lastNode.Protocol == "socks5" {
+ cc, er := l.chain.Conn()
+ if er != nil {
+ return nil, er
+ }
+ conn, err = l.waitConnectSOCKS5(cc)
+ if err != nil {
+ cc.Close()
+ }
+ } else {
+ if l.ln == nil {
+ l.ln, err = net.Listen("tcp", l.addr.String())
+ if err != nil {
+ return
+ }
+ }
+ conn, err = l.ln.Accept()
+ }
+ return
+}
- req := gosocks5.NewRequest(gosocks5.CmdBind, ToSocksAddr(laddr))
+func (l *tcpRemoteForwardListener) waitConnectSOCKS5(conn net.Conn) (net.Conn, error) {
+ conn, err := socks5Handshake(conn, l.chain.LastNode().User)
+ if err != nil {
+ return nil, err
+ }
+ req := gosocks5.NewRequest(gosocks5.CmdBind, toSocksAddr(l.addr))
if err := req.Write(conn); err != nil {
- glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", laddr, raddr, err)
- return err
+ log.Log("[rtcp] SOCKS5 BIND request: ", err)
+ return nil, err
}
// first reply, bind status
conn.SetReadDeadline(time.Now().Add(ReadTimeout))
rep, err := gosocks5.ReadReply(conn)
if err != nil {
- glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", laddr, raddr, err)
- return err
+ log.Log("[rtcp] SOCKS5 BIND reply: ", err)
+ return nil, err
}
conn.SetReadDeadline(time.Time{})
if rep.Rep != gosocks5.Succeeded {
- glog.V(LWARNING).Infof("[rtcp] %s -> %s : bind on %s failure", laddr, raddr, laddr)
- return errors.New("Bind on " + laddr.String() + " failure")
+ log.Logf("[rtcp] bind on %s failure", l.addr)
+ return nil, fmt.Errorf("Bind on %s failure", l.addr.String())
}
- glog.V(LINFO).Infof("[rtcp] %s - %s BIND ON %s OK", laddr, raddr, rep.Addr)
+ log.Logf("[rtcp] BIND ON %s OK", rep.Addr)
- // second reply, peer connection
+ // second reply, peer connected
rep, err = gosocks5.ReadReply(conn)
if err != nil {
- glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", laddr, raddr, err)
- return err
+ log.Log("[rtcp]", err)
+ return nil, err
}
if rep.Rep != gosocks5.Succeeded {
- glog.V(LWARNING).Infof("[rtcp] %s -> %s : peer connect failure", laddr, raddr)
- return errors.New("peer connect failure")
+ log.Logf("[rtcp] peer connect failure: %d", rep.Rep)
+ return nil, errors.New("peer connect failure")
}
- glog.V(LINFO).Infof("[rtcp] %s -> %s PEER %s CONNECTED", laddr, raddr, rep.Addr)
+ log.Logf("[rtcp] PEER %s CONNECTED", rep.Addr)
+ return conn, nil
+}
- go func() {
- defer conn.Close()
-
- lconn, err := net.DialTimeout("tcp", raddr.String(), time.Second*180)
- if err != nil {
- glog.V(LWARNING).Infof("[rtcp] %s -> %s : %s", rep.Addr, raddr, err)
- return
- }
- defer lconn.Close()
-
- glog.V(LINFO).Infof("[rtcp] %s <-> %s", rep.Addr, lconn.RemoteAddr())
- s.Base.transport(lconn, conn)
- glog.V(LINFO).Infof("[rtcp] %s >-< %s", rep.Addr, lconn.RemoteAddr())
- }()
+func (l *tcpRemoteForwardListener) Addr() net.Addr {
+ return l.addr
+}
+func (l *tcpRemoteForwardListener) Close() error {
+ close(l.closed)
return nil
}
-type RUdpForwardServer struct {
- Base *ProxyServer
+type udpRemoteForwardListener struct {
+ addr *net.UDPAddr
+ chain *Chain
+ conns map[string]*udpServerConn
+ connChan chan net.Conn
+ errChan chan error
+ ttl time.Duration
+ closed chan struct{}
}
-func NewRUdpForwardServer(base *ProxyServer) *RUdpForwardServer {
- return &RUdpForwardServer{Base: base}
+// UDPRemoteForwardListener creates a Listener for UDP remote port forwarding server.
+func UDPRemoteForwardListener(addr string, chain *Chain, ttl time.Duration) (Listener, error) {
+ laddr, err := net.ResolveUDPAddr("udp", addr)
+ if err != nil {
+ return nil, err
+ }
+
+ ln := &udpRemoteForwardListener{
+ addr: laddr,
+ chain: chain,
+ conns: make(map[string]*udpServerConn),
+ connChan: make(chan net.Conn, 1024),
+ errChan: make(chan error, 1),
+ ttl: ttl,
+ closed: make(chan struct{}),
+ }
+ go ln.listenLoop()
+ return ln, nil
}
-func (s *RUdpForwardServer) Serve() error {
- if len(s.Base.Chain.nodes) == 0 {
- return errors.New("rudp: at least one -F must be assigned")
- }
-
- laddr, err := net.ResolveUDPAddr("udp", s.Base.Node.Addr)
- if err != nil {
- return err
- }
- raddr, err := net.ResolveUDPAddr("udp", s.Base.Node.Remote)
- if err != nil {
- return err
- }
-
- retry := 0
+func (l *udpRemoteForwardListener) listenLoop() {
for {
- conn, err := s.Base.Chain.GetConn()
+ conn, err := l.connect()
if err != nil {
- glog.V(LWARNING).Infof("[rudp] %s - %s : %s", laddr, raddr, err)
- time.Sleep((1 << uint(retry)) * time.Second)
- if retry < 5 {
- retry++
+ log.Logf("[rudp] %s : %s", l.Addr(), err)
+ return
+ }
+
+ defer conn.Close()
+
+ for {
+ b := make([]byte, mediumBufferSize)
+ n, raddr, err := conn.ReadFrom(b)
+ if err != nil {
+ log.Logf("[rudp] %s : %s", l.Addr(), err)
+ break
}
+ if Debug {
+ log.Logf("[udp] %s >>> %s : length %d", raddr, l.Addr(), n)
+ }
+ uc, ok := l.conns[raddr.String()]
+ if !ok || uc.Closed() {
+ uc = newUDPServerConn(conn, raddr, l.ttl)
+ l.conns[raddr.String()] = uc
+
+ select {
+ case l.connChan <- uc:
+ default:
+ uc.Close()
+ log.Logf("[rudp] %s - %s: connection queue is full", raddr, l.Addr())
+ }
+ }
+
+ select {
+ case uc.rChan <- b[:n]:
+ default:
+ log.Logf("[rudp] %s -> %s : write queue is full", raddr, l.Addr())
+ }
+ }
+ }
+
+}
+
+func (l *udpRemoteForwardListener) connect() (conn net.PacketConn, err error) {
+ var tempDelay time.Duration
+
+ for {
+ select {
+ case <-l.closed:
+ return nil, errors.New("closed")
+ default:
+ }
+
+ lastNode := l.chain.LastNode()
+ if lastNode.Protocol == "socks5" {
+ var cc net.Conn
+ cc, err = getSOCKS5UDPTunnel(l.chain, l.addr)
+ if err != nil {
+ log.Logf("[rudp] %s : %s", l.Addr(), err)
+ } else {
+ conn = &udpTunnelConn{Conn: cc}
+ }
+ } else {
+ conn, err = net.ListenUDP("udp", l.addr)
+ }
+
+ if err != nil {
+ if tempDelay == 0 {
+ tempDelay = 1000 * time.Millisecond
+ } else {
+ tempDelay *= 2
+ }
+ if max := 6 * time.Second; tempDelay > max {
+ tempDelay = max
+ }
+ log.Logf("[rudp] Accept error: %v; retrying in %v", err, tempDelay)
+ time.Sleep(tempDelay)
continue
}
- retry = 0
-
- if err := s.connectRUdpForward(conn, laddr, raddr); err != nil {
- conn.Close()
- time.Sleep(6 * time.Second)
- }
+ return
}
}
-func (s *RUdpForwardServer) connectRUdpForward(conn net.Conn, laddr, raddr *net.UDPAddr) error {
- glog.V(LINFO).Infof("[rudp] %s - %s", laddr, raddr)
-
- req := gosocks5.NewRequest(CmdUdpTun, ToSocksAddr(laddr))
- conn.SetWriteDeadline(time.Now().Add(WriteTimeout))
- if err := req.Write(conn); err != nil {
- glog.V(LWARNING).Infof("[rudp] %s -> %s : %s", laddr, raddr, err)
- return err
- }
- conn.SetWriteDeadline(time.Time{})
-
- conn.SetReadDeadline(time.Now().Add(ReadTimeout))
- rep, err := gosocks5.ReadReply(conn)
- if err != nil {
- glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err)
- return err
- }
- conn.SetReadDeadline(time.Time{})
-
- if rep.Rep != gosocks5.Succeeded {
- glog.V(LWARNING).Infof("[rudp] %s <- %s : bind on %s failure", laddr, raddr, laddr)
- return errors.New(fmt.Sprintf("bind on %s failure", laddr))
- }
-
- glog.V(LINFO).Infof("[rudp] %s - %s BIND ON %s OK", laddr, raddr, rep.Addr)
-
- for {
- dgram, err := gosocks5.ReadUDPDatagram(conn)
- if err != nil {
- glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err)
- return err
+func (l *udpRemoteForwardListener) Accept() (conn net.Conn, err error) {
+ var ok bool
+ select {
+ case conn = <-l.connChan:
+ case err, ok = <-l.errChan:
+ if !ok {
+ err = errors.New("accpet on closed listener")
}
-
- go func() {
- b := make([]byte, MediumBufferSize)
-
- relay, err := net.DialUDP("udp", nil, raddr)
- if err != nil {
- glog.V(LWARNING).Infof("[rudp] %s -> %s : %s", laddr, raddr, err)
- return
- }
- defer relay.Close()
-
- if _, err := relay.Write(dgram.Data); err != nil {
- glog.V(LWARNING).Infof("[rudp] %s -> %s : %s", laddr, raddr, err)
- return
- }
- glog.V(LDEBUG).Infof("[rudp] %s >>> %s length: %d", laddr, raddr, len(dgram.Data))
-
- relay.SetReadDeadline(time.Now().Add(ReadTimeout))
- n, err := relay.Read(b)
- if err != nil {
- glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err)
- return
- }
- relay.SetReadDeadline(time.Time{})
-
- glog.V(LDEBUG).Infof("[rudp] %s <<< %s length: %d", laddr, raddr, n)
-
- conn.SetWriteDeadline(time.Now().Add(WriteTimeout))
- if err := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(n), 0, dgram.Header.Addr), b[:n]).Write(conn); err != nil {
- glog.V(LWARNING).Infof("[rudp] %s <- %s : %s", laddr, raddr, err)
- return
- }
- conn.SetWriteDeadline(time.Time{})
- }()
}
+ return
+}
+
+func (l *udpRemoteForwardListener) Addr() net.Addr {
+ return l.addr
+}
+
+func (l *udpRemoteForwardListener) Close() error {
+ close(l.closed)
+ return nil
}
diff --git a/gost.go b/gost.go
index 6c043e7..83e665d 100644
--- a/gost.go
+++ b/gost.go
@@ -1,146 +1,104 @@
package gost
import (
+ "crypto/rand"
+ "crypto/rsa"
"crypto/tls"
- "encoding/base64"
- "errors"
- "github.com/golang/glog"
- "net"
- "strings"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/pem"
+ "math/big"
"time"
+
+ "github.com/go-log/log"
)
-const (
- Version = "2.4-dev"
-)
+// Version is the gost version.
+const Version = "2.4-rc1"
-// Log level for glog
-const (
- LFATAL = iota
- LERROR
- LWARNING
- LINFO
- LDEBUG
+// Debug is a flag that enables the debug log.
+var Debug bool
+
+var (
+ tinyBufferSize = 128
+ smallBufferSize = 1 * 1024 // 1KB small buffer
+ mediumBufferSize = 8 * 1024 // 8KB medium buffer
+ largeBufferSize = 32 * 1024 // 32KB large buffer
)
var (
+ // KeepAliveTime is the keep alive time period for TCP connection.
KeepAliveTime = 180 * time.Second
- DialTimeout = 30 * time.Second
- ReadTimeout = 90 * time.Second
- WriteTimeout = 90 * time.Second
-
- DefaultTTL = 60 // default udp node TTL in second for udp port forwarding
+ // DialTimeout is the timeout of dial.
+ DialTimeout = 30 * time.Second
+ // ReadTimeout is the timeout for reading.
+ ReadTimeout = 30 * time.Second
+ // WriteTimeout is the timeout for writing.
+ WriteTimeout = 60 * time.Second
+ // PingTimeout is the timeout for pinging.
+ PingTimeout = 30 * time.Second
+ // PingRetries is the reties of ping.
+ PingRetries = 3
+ // default udp node TTL in second for udp port forwarding.
+ defaultTTL = 60 * time.Second
)
var (
- SmallBufferSize = 1 * 1024 // 1KB small buffer
- MediumBufferSize = 8 * 1024 // 8KB medium buffer
- LargeBufferSize = 32 * 1024 // 32KB large buffer
+ DefaultTLSConfig *tls.Config
)
-var (
- DefaultCertFile = "cert.pem"
- DefaultKeyFile = "key.pem"
-
- // This is the default cert and key data for convenience, providing your own cert is recommended.
- defaultRawCert = []byte(`-----BEGIN CERTIFICATE-----
-MIIC5jCCAdCgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
-bzAeFw0xNDAzMTcwNjIwNTFaFw0xNTAzMTcwNjIwNTFaMBIxEDAOBgNVBAoTB0Fj
-bWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDccNO1xmd4lWSf
-d/0/QS3E93cYIWHw831i/IKxigdRD/XMZonLdEHywW6lOiXazaP8e6CqPGSmnl0x
-5k/3dvGCMj2JCVxM6+z7NpL+AiwvXmvkj/TOciCgwqssCwYS2CiVwjfazRjx1ZUJ
-VDC5qiyRsfktQ2fVHrpnJGVSRagmiQgwGWBilVG9B8QvRtpQKN/GQGq17oIQm8aK
-kOdPt93g93ojMIg7YJpgDgOirvVz/hDn7YD4ryrtPos9CMafFkJprymKpRHyvz7P
-8a3+OkuPjFjPnwOHQ5u1U3+8vC44vfb1ExWzDLoT8Xp8Gndx39k0f7MVOol3GnYu
-MN/dvNUdAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIAoDATBgNVHSUEDDAKBggrBgEF
-BQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDALBgkqhkiG
-9w0BAQUDggEBAIG8CJqvTIgJnNOK+i5/IUc/3yF/mSCWuG8qP+Fmo2t6T0PVOtc0
-8wiWH5iWtCAhjn0MRY9l/hIjWm6gUZGHCGuEgsOPpJDYGoNLjH9Xwokm4y3LFNRK
-UBrrrDbKRNibApBHCapPf6gC5sXcjOwx7P2/kiHDgY7YH47jfcRhtAPNsM4gjsEO
-RmwENY+hRUFHIRfQTyalqND+x6PWhRo3K6hpHs4DQEYPq4P2kFPqUqSBymH+Ny5/
-BcQ3wdMNmC6Bm/oiL1QV0M+/InOsAgQk/EDd0kmoU1ZT2lYHQduGmP099bOlHNpS
-uqO3vXF3q8SPPr/A9TqSs7BKkBQbe0+cdsA=
------END CERTIFICATE-----`)
- defaultRawKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEA3HDTtcZneJVkn3f9P0EtxPd3GCFh8PN9YvyCsYoHUQ/1zGaJ
-y3RB8sFupTol2s2j/Hugqjxkpp5dMeZP93bxgjI9iQlcTOvs+zaS/gIsL15r5I/0
-znIgoMKrLAsGEtgolcI32s0Y8dWVCVQwuaoskbH5LUNn1R66ZyRlUkWoJokIMBlg
-YpVRvQfEL0baUCjfxkBqte6CEJvGipDnT7fd4Pd6IzCIO2CaYA4Doq71c/4Q5+2A
-+K8q7T6LPQjGnxZCaa8piqUR8r8+z/Gt/jpLj4xYz58Dh0ObtVN/vLwuOL329RMV
-swy6E/F6fBp3cd/ZNH+zFTqJdxp2LjDf3bzVHQIDAQABAoIBAHal26147nQ+pHwY
-jxwers3XDCjWvup7g79lfcqlKi79UiUEA6KYHm7UogMYewt7p4nb2KwH+XycvDiB
-aAUf5flXpTs+6IkWauUDiLZi4PlV7uiEexUq5FjirlL0U/6MjbudX4bK4WQ4uxDc
-WaV07Kw2iJFOOHLDKT0en9JaX5jtJNc4ZnE9efFoQ5jfypPWtRw65G1rULEg6nvc
-GDh+1ce+4foCkpLRC9c24xAwJONZG6x3UqrSS9qfAsb73nWRQrTfUcO3nhoN8VvL
-kL9skn1+S06NyUN0KoEtyRBp+RcpXSsBWAo6qZmo/WqhB/gjzWrxVwn20+yJSm35
-ZsMc6QECgYEA8GS+Mp9xfB2szWHz6YTOO1Uu4lHM1ccZMwS1G+dL0KO3uGAiPdvp
-woVot6v6w88t7onXsLo5pgz7SYug0CpkF3K/MRd1Ar4lH7PK7IBQ6rFr9ppVxDbx
-AEWRswUoPbKCr7W6HU8LbQHDavsDlEIwc6+DiwnL4BzlKjb7RpgQEz0CgYEA6sB5
-uHvx3Y5FDcGk1n73leQSAcq14l3ZLNpjrs8msoREDil/j5WmuSN58/7PGMiMgHEi
-1vLm3H796JmvGr9OBvspOjHyk07ui2/We/j9Hoxm1VWhyi8HkLNDj70HKalTTFMz
-RHO4O+0xCva+h9mKZrRMVktXr2jjdFn/0MYIZ2ECgYAIIsC1IeRLWQ3CHbCNlKsO
-IwHlMvOFwKk/qsceXKOaOhA7szU1dr3gkXdL0Aw6mEZrrkqYdpUA46uVf54/rU+Z
-445I8QxKvXiwK/uQKX+TkdGflPWWIG3jnnch4ejMvb/ihnn4B/bRB6A/fKNQXzUY
-lTYUfI5j1VaEKTwz1W2l2QKBgByFCcSp+jZqhGUpc3dDsZyaOr3Q/Mvlju7uEVI5
-hIAHpaT60a6GBd1UPAqymEJwivFHzW3D0NxU6VAK68UaHMaoWNfjHY9b9YsnKS2i
-kE3XzN56Ks+/avHfdYPO+UHMenw5V28nh+hv5pdoZrlmanQTz3pkaOC8o3WNQZEB
-nh/BAoGBAMY5z2f1pmMhrvtPDSlEVjgjELbaInxFaxPLR4Pdyzn83gtIIU14+R8X
-2LPs6PPwrNjWnIgrUSVXncIFL3pa45B+Mx1pYCpOAB1+nCZjIBQmpeo4Y0dwA/XH
-85EthKPvoszm+OPbyI16OcePV5ocX7lupRYuAo0pek7bomhmHWHz
------END RSA PRIVATE KEY-----`)
-)
-
-var (
- ErrEmptyChain = errors.New("empty chain")
-)
-
-func setKeepAlive(conn net.Conn, d time.Duration) error {
- c, ok := conn.(*net.TCPConn)
- if !ok {
- return errors.New("Not a TCP connection")
+func init() {
+ rawCert, rawKey, err := generateKeyPair()
+ if err != nil {
+ panic(err)
}
- if err := c.SetKeepAlive(true); err != nil {
- return err
+ cert, err := tls.X509KeyPair(rawCert, rawKey)
+ if err != nil {
+ panic(err)
}
- if err := c.SetKeepAlivePeriod(d); err != nil {
- return err
+ DefaultTLSConfig = &tls.Config{
+ Certificates: []tls.Certificate{cert},
}
- return nil
+
+ log.DefaultLogger = &LogLogger{}
}
-// Load the certificate from cert and key files, will use the default certificate if the provided info are invalid.
-func LoadCertificate(certFile, keyFile string) (tls.Certificate, error) {
- tlsCert, err := tls.LoadX509KeyPair(certFile, keyFile)
- if err == nil {
- return tlsCert, nil
- }
- glog.V(LWARNING).Infoln(err)
- return tls.X509KeyPair(defaultRawCert, defaultRawKey)
+func SetLogger(logger log.Logger) {
+ log.DefaultLogger = logger
}
-// Replace the default certificate by your own
-func SetDefaultCertificate(rawCert, rawKey []byte) {
- defaultRawCert = rawCert
- defaultRawKey = rawKey
-}
+func generateKeyPair() (rawCert, rawKey []byte, err error) {
+ // Create private key and self-signed certificate
+ // Adapted from https://golang.org/src/crypto/tls/generate_cert.go
-func basicProxyAuth(proxyAuth string) (username, password string, ok bool) {
- if proxyAuth == "" {
- return
- }
-
- if !strings.HasPrefix(proxyAuth, "Basic ") {
- return
- }
- c, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(proxyAuth, "Basic "))
+ priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return
}
- cs := string(c)
- s := strings.IndexByte(cs, ':')
- if s < 0 {
+ validFor := time.Hour * 24 * 365 * 10 // ten years
+ notBefore := time.Now()
+ notAfter := notBefore.Add(validFor)
+ serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
+ serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
+ template := x509.Certificate{
+ SerialNumber: serialNumber,
+ Subject: pkix.Name{
+ Organization: []string{"gost"},
+ },
+ NotBefore: notBefore,
+ NotAfter: notAfter,
+
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+ BasicConstraintsValid: true,
+ }
+ derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
+ if err != nil {
return
}
- return cs[:s], cs[s+1:], true
+ rawCert = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
+ rawKey = pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
+
+ return
}
diff --git a/handler.go b/handler.go
new file mode 100644
index 0000000..4a454a0
--- /dev/null
+++ b/handler.go
@@ -0,0 +1,114 @@
+package gost
+
+import (
+ "bufio"
+ "crypto/tls"
+ "net"
+ "net/url"
+
+ "github.com/ginuerzh/gosocks4"
+ "github.com/ginuerzh/gosocks5"
+ "github.com/go-log/log"
+)
+
+// Handler is a proxy server handler
+type Handler interface {
+ Handle(net.Conn)
+}
+
+// HandlerOptions describes the options for Handler.
+type HandlerOptions struct {
+ Addr string
+ Chain *Chain
+ Users []*url.Userinfo
+ TLSConfig *tls.Config
+ Whitelist *Permissions
+ Blacklist *Permissions
+}
+
+// HandlerOption allows a common way to set handler options.
+type HandlerOption func(opts *HandlerOptions)
+
+// AddrHandlerOption sets the Addr option of HandlerOptions.
+func AddrHandlerOption(addr string) HandlerOption {
+ return func(opts *HandlerOptions) {
+ opts.Addr = addr
+ }
+}
+
+// ChainHandlerOption sets the Chain option of HandlerOptions.
+func ChainHandlerOption(chain *Chain) HandlerOption {
+ return func(opts *HandlerOptions) {
+ opts.Chain = chain
+ }
+}
+
+// UsersHandlerOption sets the Users option of HandlerOptions.
+func UsersHandlerOption(users ...*url.Userinfo) HandlerOption {
+ return func(opts *HandlerOptions) {
+ opts.Users = users
+ }
+}
+
+// TLSConfigHandlerOption sets the TLSConfig option of HandlerOptions.
+func TLSConfigHandlerOption(config *tls.Config) HandlerOption {
+ return func(opts *HandlerOptions) {
+ opts.TLSConfig = config
+ }
+}
+
+// WhitelistHandlerOption sets the Whitelist option of HandlerOptions.
+func WhitelistHandlerOption(whitelist *Permissions) HandlerOption {
+ return func(opts *HandlerOptions) {
+ opts.Whitelist = whitelist
+ }
+}
+
+// BlacklistHandlerOption sets the Blacklist option of HandlerOptions.
+func BlacklistHandlerOption(blacklist *Permissions) HandlerOption {
+ return func(opts *HandlerOptions) {
+ opts.Blacklist = blacklist
+ }
+}
+
+type autoHandler struct {
+ options []HandlerOption
+}
+
+// AutoHandler creates a server Handler for auto proxy server.
+func AutoHandler(opts ...HandlerOption) Handler {
+ h := &autoHandler{
+ options: opts,
+ }
+ return h
+}
+
+func (h *autoHandler) Handle(conn net.Conn) {
+ defer conn.Close()
+
+ br := bufio.NewReader(conn)
+ b, err := br.Peek(1)
+ if err != nil {
+ log.Log(err)
+ return
+ }
+
+ cc := &bufferdConn{Conn: conn, br: br}
+ switch b[0] {
+ case gosocks4.Ver4:
+ SOCKS4Handler(h.options...).Handle(cc)
+ case gosocks5.Ver5:
+ SOCKS5Handler(h.options...).Handle(cc)
+ default: // http
+ HTTPHandler(h.options...).Handle(cc)
+ }
+}
+
+type bufferdConn struct {
+ net.Conn
+ br *bufio.Reader
+}
+
+func (c *bufferdConn) Read(b []byte) (int, error) {
+ return c.br.Read(b)
+}
diff --git a/http.go b/http.go
index 5ad16fb..a17f696 100644
--- a/http.go
+++ b/http.go
@@ -2,133 +2,208 @@ package gost
import (
"bufio"
- "crypto/tls"
"encoding/base64"
- "github.com/golang/glog"
- "golang.org/x/net/http2"
- "io"
+ "fmt"
"net"
"net/http"
"net/http/httputil"
- //"strings"
- "errors"
+ "net/url"
+ "strings"
"time"
+
+ "github.com/go-log/log"
)
-type HttpServer struct {
- conn net.Conn
- Base *ProxyServer
+type httpConnector struct {
+ User *url.Userinfo
}
-func NewHttpServer(conn net.Conn, base *ProxyServer) *HttpServer {
- return &HttpServer{
- conn: conn,
- Base: base,
+// HTTPConnector creates a Connector for HTTP proxy client.
+// It accepts an optional auth info for HTTP Basic Authentication.
+func HTTPConnector(user *url.Userinfo) Connector {
+ return &httpConnector{User: user}
+}
+
+func (c *httpConnector) Connect(conn net.Conn, addr string) (net.Conn, error) {
+ req := &http.Request{
+ Method: http.MethodConnect,
+ URL: &url.URL{Host: addr},
+ Host: addr,
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ Header: make(http.Header),
}
-}
+ req.Header.Set("Proxy-Connection", "keep-alive")
-// Default HTTP server handler
-func (s *HttpServer) HandleRequest(req *http.Request) {
- glog.V(LINFO).Infof("[http] %s %s - %s %s", req.Method, s.conn.RemoteAddr(), req.Host, req.Proto)
+ if c.User != nil {
+ s := c.User.String()
+ if _, set := c.User.Password(); !set {
+ s += ":"
+ }
+ req.Header.Set("Proxy-Authorization",
+ "Basic "+base64.StdEncoding.EncodeToString([]byte(s)))
+ }
- if glog.V(LDEBUG) {
+ if err := req.Write(conn); err != nil {
+ return nil, err
+ }
+
+ if Debug {
dump, _ := httputil.DumpRequest(req, false)
- glog.Infoln(string(dump))
+ log.Log(string(dump))
}
- if req.Method == "PRI" && req.ProtoMajor == 2 {
- glog.V(LWARNING).Infof("[http] %s <- %s : Not an HTTP2 server", s.conn.RemoteAddr(), req.Host)
- resp := "HTTP/1.1 400 Bad Request\r\n" +
- "Proxy-Agent: gost/" + Version + "\r\n\r\n"
- s.conn.Write([]byte(resp))
+ resp, err := http.ReadResponse(bufio.NewReader(conn), req)
+ if err != nil {
+ return nil, err
+ }
+
+ if Debug {
+ dump, _ := httputil.DumpResponse(resp, false)
+ log.Log(string(dump))
+ }
+
+ if resp.StatusCode != http.StatusOK {
+ return nil, fmt.Errorf("%s", resp.Status)
+ }
+
+ return conn, nil
+}
+
+type httpHandler struct {
+ options *HandlerOptions
+}
+
+// HTTPHandler creates a server Handler for HTTP proxy server.
+func HTTPHandler(opts ...HandlerOption) Handler {
+ h := &httpHandler{
+ options: &HandlerOptions{},
+ }
+ for _, opt := range opts {
+ opt(h.options)
+ }
+ return h
+}
+
+func (h *httpHandler) Handle(conn net.Conn) {
+ defer conn.Close()
+
+ req, err := http.ReadRequest(bufio.NewReader(conn))
+ if err != nil {
+ log.Logf("[http] %s - %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
return
}
- valid := false
- u, p, _ := basicProxyAuth(req.Header.Get("Proxy-Authorization"))
- glog.V(LINFO).Infoln(u, p)
- for _, user := range s.Base.Node.Users {
- username := user.Username()
- password, _ := user.Password()
- if (u == username && p == password) ||
- (u == username && password == "") ||
- (username == "" && p == password) {
- valid = true
- break
- }
+ if Debug {
+ log.Logf("[http] %s %s - %s %s", req.Method, conn.RemoteAddr(), req.Host, req.Proto)
+ dump, _ := httputil.DumpRequest(req, false)
+ log.Logf(string(dump))
}
- if len(s.Base.Node.Users) > 0 && !valid {
- glog.V(LWARNING).Infof("[http] %s <- %s : proxy authentication required", s.conn.RemoteAddr(), req.Host)
+ if req.Method == "PRI" && req.ProtoMajor == 2 {
+ log.Logf("[http] %s <- %s : Not an HTTP2 server", conn.RemoteAddr(), req.Host)
+ resp := "HTTP/1.1 400 Bad Request\r\n" +
+ "Proxy-Agent: gost/" + Version + "\r\n\r\n"
+ conn.Write([]byte(resp))
+ return
+ }
+
+ u, p, _ := basicProxyAuth(req.Header.Get("Proxy-Authorization"))
+ if Debug && (u != "" || p != "") {
+ log.Logf("[http] %s - %s : Authorization: '%s' '%s'", conn.RemoteAddr(), req.Host, u, p)
+ }
+ if !authenticate(u, p, h.options.Users...) {
+ log.Logf("[http] %s <- %s : proxy authentication required", conn.RemoteAddr(), req.Host)
resp := "HTTP/1.1 407 Proxy Authentication Required\r\n" +
"Proxy-Authenticate: Basic realm=\"gost\"\r\n" +
"Proxy-Agent: gost/" + Version + "\r\n\r\n"
- s.conn.Write([]byte(resp))
+ conn.Write([]byte(resp))
return
}
req.Header.Del("Proxy-Authorization")
+ req.Header.Del("Proxy-Connection")
+
+ if !Can("tcp", req.Host, h.options.Whitelist, h.options.Blacklist) {
+ log.Logf("[http] Unauthorized to tcp connect to %s", req.Host)
+ b := []byte("HTTP/1.1 403 Forbidden\r\n" +
+ "Proxy-Agent: gost/" + Version + "\r\n\r\n")
+ conn.Write(b)
+ if Debug {
+ log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), req.Host, string(b))
+ }
+ return
+ }
// forward http request
- lastNode := s.Base.Chain.lastNode
- if lastNode != nil && (lastNode.Protocol == "http" || lastNode.Protocol == "") {
- s.forwardRequest(req)
+ lastNode := h.options.Chain.LastNode()
+ if req.Method != http.MethodConnect && lastNode.Protocol == "http" {
+ h.forwardRequest(conn, req)
return
}
- c, err := s.Base.Chain.Dial(req.Host)
+ host := req.Host
+ if !strings.Contains(req.Host, ":") {
+ host += ":80"
+ }
+ cc, err := h.options.Chain.Dial(host)
if err != nil {
- glog.V(LWARNING).Infof("[http] %s -> %s : %s", s.conn.RemoteAddr(), req.Host, err)
+ log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), req.Host, err)
b := []byte("HTTP/1.1 503 Service unavailable\r\n" +
"Proxy-Agent: gost/" + Version + "\r\n\r\n")
- glog.V(LDEBUG).Infof("[http] %s <- %s\n%s", s.conn.RemoteAddr(), req.Host, string(b))
- s.conn.Write(b)
- return
- }
- defer c.Close()
-
- if req.Method == http.MethodConnect {
- b := []byte("HTTP/1.1 200 Connection established\r\n" +
- "Proxy-Agent: gost/" + Version + "\r\n\r\n")
- glog.V(LDEBUG).Infof("[http] %s <- %s\n%s", s.conn.RemoteAddr(), req.Host, string(b))
- s.conn.Write(b)
- } else {
- req.Header.Del("Proxy-Connection")
- req.Header.Set("Connection", "Keep-Alive")
-
- if err = req.Write(c); err != nil {
- glog.V(LWARNING).Infof("[http] %s -> %s : %s", s.conn.RemoteAddr(), req.Host, err)
- return
+ if Debug {
+ log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), req.Host, string(b))
}
- }
-
- glog.V(LINFO).Infof("[http] %s <-> %s", s.conn.RemoteAddr(), req.Host)
- s.Base.transport(s.conn, c)
- glog.V(LINFO).Infof("[http] %s >-< %s", s.conn.RemoteAddr(), req.Host)
-}
-
-func (s *HttpServer) forwardRequest(req *http.Request) {
- last := s.Base.Chain.lastNode
- if last == nil {
- return
- }
- cc, err := s.Base.Chain.GetConn()
- if err != nil {
- glog.V(LWARNING).Infof("[http] %s -> %s : %s", s.conn.RemoteAddr(), last.Addr, err)
-
- b := []byte("HTTP/1.1 503 Service unavailable\r\n" +
- "Proxy-Agent: gost/" + Version + "\r\n\r\n")
- glog.V(LDEBUG).Infof("[http] %s <- %s\n%s", s.conn.RemoteAddr(), last.Addr, string(b))
- s.conn.Write(b)
+ conn.Write(b)
return
}
defer cc.Close()
- if len(last.Users) > 0 {
- user := last.Users[0]
- s := user.String()
- if _, set := user.Password(); !set {
+ if req.Method == http.MethodConnect {
+ b := []byte("HTTP/1.1 200 Connection established\r\n" +
+ "Proxy-Agent: gost/" + Version + "\r\n\r\n")
+ if Debug {
+ log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), req.Host, string(b))
+ }
+ conn.Write(b)
+ } else {
+ req.Header.Del("Proxy-Connection")
+
+ if err = req.Write(cc); err != nil {
+ log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), req.Host, err)
+ return
+ }
+ }
+
+ log.Logf("[http] %s <-> %s", cc.LocalAddr(), req.Host)
+ transport(conn, cc)
+ log.Logf("[http] %s >-< %s", cc.LocalAddr(), req.Host)
+}
+
+func (h *httpHandler) forwardRequest(conn net.Conn, req *http.Request) {
+ if h.options.Chain.IsEmpty() {
+ return
+ }
+ lastNode := h.options.Chain.LastNode()
+
+ cc, err := h.options.Chain.Conn()
+ if err != nil {
+ log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), lastNode.Addr, err)
+
+ b := []byte("HTTP/1.1 503 Service unavailable\r\n" +
+ "Proxy-Agent: gost/" + Version + "\r\n\r\n")
+ if Debug {
+ log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), lastNode.Addr, string(b))
+ }
+ conn.Write(b)
+ return
+ }
+ defer cc.Close()
+
+ if lastNode.User != nil {
+ s := lastNode.User.String()
+ if _, set := lastNode.User.Password(); !set {
s += ":"
}
req.Header.Set("Proxy-Authorization",
@@ -137,250 +212,51 @@ func (s *HttpServer) forwardRequest(req *http.Request) {
cc.SetWriteDeadline(time.Now().Add(WriteTimeout))
if err = req.WriteProxy(cc); err != nil {
- glog.V(LWARNING).Infof("[http] %s -> %s : %s", s.conn.RemoteAddr(), req.Host, err)
+ log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), req.Host, err)
return
}
cc.SetWriteDeadline(time.Time{})
- glog.V(LINFO).Infof("[http] %s <-> %s", s.conn.RemoteAddr(), req.Host)
- s.Base.transport(s.conn, cc)
- glog.V(LINFO).Infof("[http] %s >-< %s", s.conn.RemoteAddr(), req.Host)
+ log.Logf("[http] %s <-> %s", conn.RemoteAddr(), req.Host)
+ transport(conn, cc)
+ log.Logf("[http] %s >-< %s", conn.RemoteAddr(), req.Host)
return
}
-type Http2Server struct {
- Base *ProxyServer
- Handler http.Handler
- TLSConfig *tls.Config
-}
-
-func NewHttp2Server(base *ProxyServer) *Http2Server {
- return &Http2Server{Base: base}
-}
-
-func (s *Http2Server) ListenAndServeTLS(config *tls.Config) error {
- srv := http.Server{
- Addr: s.Base.Node.Addr,
- Handler: s.Handler,
- TLSConfig: config,
- }
- if srv.Handler == nil {
- srv.Handler = http.HandlerFunc(s.HandleRequest)
- }
- http2.ConfigureServer(&srv, nil)
- return srv.ListenAndServeTLS("", "")
-}
-
-// Default HTTP2 server handler
-func (s *Http2Server) HandleRequest(w http.ResponseWriter, req *http.Request) {
- target := req.Header.Get("Gost-Target")
- if target == "" {
- target = req.Host
- }
- glog.V(LINFO).Infof("[http2] %s %s - %s %s", req.Method, req.RemoteAddr, target, req.Proto)
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpRequest(req, false)
- glog.Infoln(string(dump))
- }
-
- w.Header().Set("Proxy-Agent", "gost/"+Version)
-
- // HTTP2 as transport
- if req.Header.Get("Proxy-Switch") == "gost" {
- conn, err := s.Upgrade(w, req)
- if err != nil {
- glog.V(LINFO).Infof("[http2] %s -> %s : %s", req.RemoteAddr, target, err)
- return
- }
- glog.V(LINFO).Infof("[http2] %s - %s : switch to HTTP2 transport mode OK", req.RemoteAddr, target)
- s.Base.handleConn(conn)
+func basicProxyAuth(proxyAuth string) (username, password string, ok bool) {
+ if proxyAuth == "" {
return
}
- valid := false
- u, p, _ := basicProxyAuth(req.Header.Get("Proxy-Authorization"))
- for _, user := range s.Base.Node.Users {
- username := user.Username()
- password, _ := user.Password()
+ if !strings.HasPrefix(proxyAuth, "Basic ") {
+ return
+ }
+ c, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(proxyAuth, "Basic "))
+ if err != nil {
+ return
+ }
+ cs := string(c)
+ s := strings.IndexByte(cs, ':')
+ if s < 0 {
+ return
+ }
+
+ return cs[:s], cs[s+1:], true
+}
+
+func authenticate(username, password string, users ...*url.Userinfo) bool {
+ if len(users) == 0 {
+ return true
+ }
+
+ for _, user := range users {
+ u := user.Username()
+ p, _ := user.Password()
if (u == username && p == password) ||
- (u == username && password == "") ||
- (username == "" && p == password) {
- valid = true
- break
+ (u == username && p == "") ||
+ (u == "" && p == password) {
+ return true
}
}
- if len(s.Base.Node.Users) > 0 && !valid {
- glog.V(LWARNING).Infof("[http2] %s <- %s : proxy authentication required", req.RemoteAddr, target)
- w.Header().Set("Proxy-Authenticate", "Basic realm=\"gost\"")
- w.WriteHeader(http.StatusProxyAuthRequired)
- return
- }
-
- req.Header.Del("Proxy-Authorization")
-
- c, err := s.Base.Chain.Dial(target)
- if err != nil {
- glog.V(LWARNING).Infof("[http2] %s -> %s : %s", req.RemoteAddr, target, err)
- w.WriteHeader(http.StatusServiceUnavailable)
- return
- }
- defer c.Close()
-
- glog.V(LINFO).Infof("[http2] %s <-> %s", req.RemoteAddr, target)
-
- if req.Method == http.MethodConnect {
- w.WriteHeader(http.StatusOK)
- if fw, ok := w.(http.Flusher); ok {
- fw.Flush()
- }
-
- // compatible with HTTP1.x
- if hj, ok := w.(http.Hijacker); ok && req.ProtoMajor == 1 {
- // we take over the underly connection
- conn, _, err := hj.Hijack()
- if err != nil {
- glog.V(LWARNING).Infof("[http2] %s -> %s : %s", req.RemoteAddr, target, err)
- w.WriteHeader(http.StatusInternalServerError)
- return
- }
- defer conn.Close()
-
- s.Base.transport(conn, c)
- return
- }
-
- errc := make(chan error, 2)
-
- go func() {
- _, err := io.Copy(c, req.Body)
- errc <- err
- }()
- go func() {
- _, err := io.Copy(flushWriter{w}, c)
- errc <- err
- }()
-
- select {
- case <-errc:
- // glog.V(LWARNING).Infoln("exit", err)
- }
- glog.V(LINFO).Infof("[http2] %s >-< %s", req.RemoteAddr, target)
- return
- }
-
- req.Header.Set("Connection", "Keep-Alive")
- if err = req.Write(c); err != nil {
- glog.V(LWARNING).Infof("[http2] %s -> %s : %s", req.RemoteAddr, target, err)
- return
- }
-
- resp, err := http.ReadResponse(bufio.NewReader(c), req)
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- return
- }
- defer resp.Body.Close()
-
- for k, v := range resp.Header {
- for _, vv := range v {
- w.Header().Add(k, vv)
- }
- }
- w.WriteHeader(resp.StatusCode)
- if _, err := io.Copy(flushWriter{w}, resp.Body); err != nil {
- glog.V(LWARNING).Infof("[http2] %s <- %s : %s", req.RemoteAddr, target, err)
- }
-
- glog.V(LINFO).Infof("[http2] %s >-< %s", req.RemoteAddr, target)
-}
-
-// Upgrade upgrade an HTTP2 request to a bidirectional connection that preparing for tunneling other protocol, just like a websocket connection.
-func (s *Http2Server) Upgrade(w http.ResponseWriter, r *http.Request) (net.Conn, error) {
- if r.Method != http.MethodConnect {
- w.WriteHeader(http.StatusMethodNotAllowed)
- return nil, errors.New("Method not allowed")
- }
-
- w.WriteHeader(http.StatusOK)
-
- if fw, ok := w.(http.Flusher); ok {
- fw.Flush()
- }
-
- conn := &http2Conn{r: r.Body, w: flushWriter{w}}
- conn.remoteAddr, _ = net.ResolveTCPAddr("tcp", r.RemoteAddr)
- conn.localAddr, _ = net.ResolveTCPAddr("tcp", r.Host)
- return conn, nil
-}
-
-// HTTP2 client connection, wrapped up just like a net.Conn
-type http2Conn struct {
- r io.Reader
- w io.Writer
- remoteAddr net.Addr
- localAddr net.Addr
-}
-
-func (c *http2Conn) Read(b []byte) (n int, err error) {
- return c.r.Read(b)
-}
-
-func (c *http2Conn) Write(b []byte) (n int, err error) {
- return c.w.Write(b)
-}
-
-func (c *http2Conn) Close() (err error) {
- if rc, ok := c.r.(io.Closer); ok {
- err = rc.Close()
- }
- if w, ok := c.w.(io.Closer); ok {
- err = w.Close()
- }
- return
-}
-
-func (c *http2Conn) LocalAddr() net.Addr {
- return c.localAddr
-}
-
-func (c *http2Conn) RemoteAddr() net.Addr {
- return c.remoteAddr
-}
-
-func (c *http2Conn) SetDeadline(t time.Time) error {
- return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
-}
-
-func (c *http2Conn) SetReadDeadline(t time.Time) error {
- return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
-}
-
-func (c *http2Conn) SetWriteDeadline(t time.Time) error {
- return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
-}
-
-type flushWriter struct {
- w io.Writer
-}
-
-func (fw flushWriter) Write(p []byte) (n int, err error) {
- defer func() {
- if r := recover(); r != nil {
- if s, ok := r.(string); ok {
- err = errors.New(s)
- return
- }
- err = r.(error)
- }
- }()
-
- n, err = fw.w.Write(p)
- if err != nil {
- // glog.V(LWARNING).Infoln("flush writer:", err)
- return
- }
- if f, ok := fw.w.(http.Flusher); ok {
- f.Flush()
- }
- return
+ return false
}
diff --git a/http2.go b/http2.go
new file mode 100644
index 0000000..aef66e0
--- /dev/null
+++ b/http2.go
@@ -0,0 +1,772 @@
+package gost
+
+import (
+ "bufio"
+ "crypto/tls"
+ "encoding/base64"
+ "errors"
+ "io"
+ "net"
+ "net/http"
+ "net/http/httputil"
+ "net/url"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/go-log/log"
+ "golang.org/x/net/http2"
+)
+
+type http2Connector struct {
+ User *url.Userinfo
+}
+
+// HTTP2Connector creates a Connector for HTTP2 proxy client.
+// It accepts an optional auth info for HTTP Basic Authentication.
+func HTTP2Connector(user *url.Userinfo) Connector {
+ return &http2Connector{User: user}
+}
+
+func (c *http2Connector) Connect(conn net.Conn, addr string) (net.Conn, error) {
+ cc, ok := conn.(*http2ClientConn)
+ if !ok {
+ return nil, errors.New("wrong connection type")
+ }
+
+ pr, pw := io.Pipe()
+ req := &http.Request{
+ Method: http.MethodConnect,
+ URL: &url.URL{Scheme: "https", Host: addr},
+ Header: make(http.Header),
+ Proto: "HTTP/2.0",
+ ProtoMajor: 2,
+ ProtoMinor: 0,
+ Body: pr,
+ Host: addr,
+ ContentLength: -1,
+ }
+ if c.User != nil {
+ req.Header.Set("Proxy-Authorization",
+ "Basic "+base64.StdEncoding.EncodeToString([]byte(c.User.String())))
+ }
+ if Debug {
+ dump, _ := httputil.DumpRequest(req, false)
+ log.Log("[http2]", string(dump))
+ }
+ resp, err := cc.client.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ if Debug {
+ dump, _ := httputil.DumpResponse(resp, false)
+ log.Log("[http2]", string(dump))
+ }
+
+ if resp.StatusCode != http.StatusOK {
+ resp.Body.Close()
+ return nil, errors.New(resp.Status)
+ }
+ hc := &http2Conn{
+ r: resp.Body,
+ w: pw,
+ closed: make(chan struct{}),
+ }
+ hc.remoteAddr, _ = net.ResolveTCPAddr("tcp", addr)
+ hc.localAddr, _ = net.ResolveTCPAddr("tcp", cc.addr)
+
+ return hc, nil
+}
+
+type http2Transporter struct {
+ clients map[string]*http.Client
+ clientMutex sync.Mutex
+ tlsConfig *tls.Config
+}
+
+// HTTP2Transporter creates a Transporter that is used by HTTP2 h2 proxy client.
+func HTTP2Transporter(config *tls.Config) Transporter {
+ if config == nil {
+ config = &tls.Config{InsecureSkipVerify: true}
+ }
+ return &http2Transporter{
+ clients: make(map[string]*http.Client),
+ tlsConfig: config,
+ }
+}
+
+func (tr *http2Transporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
+ opts := &DialOptions{}
+ for _, option := range options {
+ option(opts)
+ }
+
+ tr.clientMutex.Lock()
+ client, ok := tr.clients[addr]
+ if !ok {
+ transport := http2.Transport{
+ TLSClientConfig: tr.tlsConfig,
+ DialTLS: func(network, adr string, cfg *tls.Config) (net.Conn, error) {
+ conn, err := opts.Chain.Dial(addr)
+ if err != nil {
+ return nil, err
+ }
+ return wrapTLSClient(conn, cfg)
+ },
+ }
+ client = &http.Client{
+ Transport: &transport,
+ Timeout: opts.Timeout,
+ }
+ tr.clients[addr] = client
+ }
+ tr.clientMutex.Unlock()
+
+ return &http2ClientConn{
+ addr: addr,
+ client: client,
+ }, nil
+}
+
+func (tr *http2Transporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
+ return conn, nil
+}
+
+func (tr *http2Transporter) Multiplex() bool {
+ return true
+}
+
+type h2Transporter struct {
+ clients map[string]*http.Client
+ clientMutex sync.Mutex
+ tlsConfig *tls.Config
+}
+
+// H2Transporter creates a Transporter that is used by HTTP2 h2 tunnel client.
+func H2Transporter(config *tls.Config) Transporter {
+ if config == nil {
+ config = &tls.Config{InsecureSkipVerify: true}
+ }
+ return &h2Transporter{
+ clients: make(map[string]*http.Client),
+ tlsConfig: config,
+ }
+}
+
+// H2CTransporter creates a Transporter that is used by HTTP2 h2c tunnel client.
+func H2CTransporter() Transporter {
+ return &h2Transporter{
+ clients: make(map[string]*http.Client),
+ }
+}
+
+func (tr *h2Transporter) Dial(addr string, options ...DialOption) (net.Conn, error) {
+ opts := &DialOptions{}
+ for _, option := range options {
+ option(opts)
+ }
+
+ tr.clientMutex.Lock()
+ client, ok := tr.clients[addr]
+ if !ok {
+ transport := http2.Transport{
+ TLSClientConfig: tr.tlsConfig,
+ DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
+ conn, err := opts.Chain.Dial(addr)
+ if err != nil {
+ return nil, err
+ }
+ if tr.tlsConfig == nil {
+ return conn, nil
+ }
+ return wrapTLSClient(conn, cfg)
+ },
+ }
+ client = &http.Client{
+ Transport: &transport,
+ Timeout: opts.Timeout,
+ }
+ tr.clients[addr] = client
+ }
+ tr.clientMutex.Unlock()
+
+ pr, pw := io.Pipe()
+ req := &http.Request{
+ Method: http.MethodConnect,
+ URL: &url.URL{Scheme: "https", Host: addr},
+ Header: make(http.Header),
+ Proto: "HTTP/2.0",
+ ProtoMajor: 2,
+ ProtoMinor: 0,
+ Body: pr,
+ Host: addr,
+ ContentLength: -1,
+ }
+ if Debug {
+ dump, _ := httputil.DumpRequest(req, false)
+ log.Log("[http2]", string(dump))
+ }
+ resp, err := client.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ if Debug {
+ dump, _ := httputil.DumpResponse(resp, false)
+ log.Log("[http2]", string(dump))
+ }
+
+ if resp.StatusCode != http.StatusOK {
+ resp.Body.Close()
+ return nil, errors.New(resp.Status)
+ }
+ conn := &http2Conn{
+ r: resp.Body,
+ w: pw,
+ closed: make(chan struct{}),
+ }
+ conn.remoteAddr, _ = net.ResolveTCPAddr("tcp", addr)
+ conn.localAddr = &net.TCPAddr{IP: net.IPv4zero, Port: 0}
+ return conn, nil
+}
+
+func (tr *h2Transporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
+ opts := &HandshakeOptions{}
+ for _, option := range options {
+ option(opts)
+ }
+ return conn, nil
+}
+
+func (tr *h2Transporter) Multiplex() bool {
+ return true
+}
+
+type http2Handler struct {
+ options *HandlerOptions
+}
+
+// HTTP2Handler creates a server Handler for HTTP2 proxy server.
+func HTTP2Handler(opts ...HandlerOption) Handler {
+ h := &http2Handler{
+ options: new(HandlerOptions),
+ }
+ for _, opt := range opts {
+ opt(h.options)
+ }
+
+ return h
+}
+
+func (h *http2Handler) Handle(conn net.Conn) {
+ defer conn.Close()
+
+ h2c, ok := conn.(*http2ServerConn)
+ if !ok {
+ log.Log("[http2] wrong connection type")
+ return
+ }
+
+ h.roundTrip(h2c.w, h2c.r)
+}
+
+func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) {
+ target := r.Host
+ if !strings.Contains(target, ":") {
+ target += ":80"
+ }
+
+ if Debug {
+ log.Logf("[http2] %s %s - %s %s", r.Method, r.RemoteAddr, target, r.Proto)
+ dump, _ := httputil.DumpRequest(r, false)
+ log.Log("[http2]", string(dump))
+ }
+
+ w.Header().Set("Proxy-Agent", "gost/"+Version)
+
+ if !Can("tcp", target, h.options.Whitelist, h.options.Blacklist) {
+ log.Logf("[http2] Unauthorized to tcp connect to %s", target)
+ w.WriteHeader(http.StatusForbidden)
+ return
+ }
+
+ u, p, _ := basicProxyAuth(r.Header.Get("Proxy-Authorization"))
+ if Debug && (u != "" || p != "") {
+ log.Logf("[http] %s - %s : Authorization: '%s' '%s'", r.RemoteAddr, target, u, p)
+ }
+ if !authenticate(u, p, h.options.Users...) {
+ log.Logf("[http2] %s <- %s : proxy authentication required", r.RemoteAddr, target)
+ w.Header().Set("Proxy-Authenticate", "Basic realm=\"gost\"")
+ w.WriteHeader(http.StatusProxyAuthRequired)
+ return
+ }
+
+ r.Header.Del("Proxy-Authorization")
+ r.Header.Del("Proxy-Connection")
+
+ cc, err := h.options.Chain.Dial(target)
+ if err != nil {
+ log.Logf("[http2] %s -> %s : %s", r.RemoteAddr, target, err)
+ w.WriteHeader(http.StatusServiceUnavailable)
+ return
+ }
+ defer cc.Close()
+
+ if r.Method == http.MethodConnect {
+ w.WriteHeader(http.StatusOK)
+ if fw, ok := w.(http.Flusher); ok {
+ fw.Flush()
+ }
+
+ // compatible with HTTP1.x
+ if hj, ok := w.(http.Hijacker); ok && r.ProtoMajor == 1 {
+ // we take over the underly connection
+ conn, _, err := hj.Hijack()
+ if err != nil {
+ log.Logf("[http2] %s -> %s : %s", r.RemoteAddr, target, err)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+ defer conn.Close()
+
+ log.Logf("[http2] %s <-> %s : downgrade to HTTP/1.1", r.RemoteAddr, target)
+ transport(conn, cc)
+ log.Logf("[http2] %s >-< %s", r.RemoteAddr, target)
+ return
+ }
+
+ log.Logf("[http2] %s <-> %s", r.RemoteAddr, target)
+ errc := make(chan error, 2)
+ go func() {
+ _, err := io.Copy(cc, r.Body)
+ errc <- err
+ }()
+ go func() {
+ _, err := io.Copy(flushWriter{w}, cc)
+ errc <- err
+ }()
+
+ select {
+ case <-errc:
+ // glog.V(LWARNING).Infoln("exit", err)
+ }
+ log.Logf("[http2] %s >-< %s", r.RemoteAddr, target)
+ return
+ }
+
+ log.Logf("[http2] %s <-> %s", r.RemoteAddr, target)
+ if err = r.Write(cc); err != nil {
+ log.Logf("[http2] %s -> %s : %s", r.RemoteAddr, target, err)
+ return
+ }
+
+ resp, err := http.ReadResponse(bufio.NewReader(cc), r)
+ if err != nil {
+ log.Logf("[http2] %s -> %s : %s", r.RemoteAddr, target, err)
+ return
+ }
+ defer resp.Body.Close()
+
+ for k, v := range resp.Header {
+ for _, vv := range v {
+ w.Header().Add(k, vv)
+ }
+ }
+ w.WriteHeader(resp.StatusCode)
+ if _, err := io.Copy(flushWriter{w}, resp.Body); err != nil {
+ log.Logf("[http2] %s <- %s : %s", r.RemoteAddr, target, err)
+ }
+ log.Logf("[http2] %s >-< %s", r.RemoteAddr, target)
+}
+
+type http2Listener struct {
+ server *http.Server
+ connChan chan *http2ServerConn
+ errChan chan error
+}
+
+// HTTP2Listener creates a Listener for HTTP2 proxy server.
+func HTTP2Listener(addr string, config *tls.Config) (Listener, error) {
+ l := &http2Listener{
+ connChan: make(chan *http2ServerConn, 1024),
+ errChan: make(chan error, 1),
+ }
+ if config == nil {
+ config = DefaultTLSConfig
+ }
+ server := &http.Server{
+ Addr: addr,
+ Handler: http.HandlerFunc(l.handleFunc),
+ TLSConfig: config,
+ }
+ if err := http2.ConfigureServer(server, nil); err != nil {
+ return nil, err
+ }
+ l.server = server
+
+ ln, err := tls.Listen("tcp", addr, config)
+ if err != nil {
+ return nil, err
+ }
+ go func() {
+ err := server.Serve(ln)
+ if err != nil {
+ log.Log("[http2]", err)
+ }
+ }()
+
+ return l, nil
+}
+
+func (l *http2Listener) handleFunc(w http.ResponseWriter, r *http.Request) {
+ conn := &http2ServerConn{
+ r: r,
+ w: w,
+ closed: make(chan struct{}),
+ }
+ select {
+ case l.connChan <- conn:
+ default:
+ log.Logf("[http2] %s - %s: connection queue is full", r.RemoteAddr, l.server.Addr)
+ return
+ }
+
+ <-conn.closed
+}
+
+func (l *http2Listener) Accept() (conn net.Conn, err error) {
+ select {
+ case conn = <-l.connChan:
+ case err = <-l.errChan:
+ if err == nil {
+ err = errors.New("accpet on closed listener")
+ }
+ }
+ return
+}
+
+func (l *http2Listener) Addr() net.Addr {
+ addr, _ := net.ResolveTCPAddr("tcp", l.server.Addr)
+ return addr
+}
+
+func (l *http2Listener) Close() (err error) {
+ select {
+ case <-l.errChan:
+ default:
+ err = l.server.Close()
+ l.errChan <- err
+ close(l.errChan)
+ }
+ return nil
+}
+
+type h2Listener struct {
+ net.Listener
+ server *http2.Server
+ tlsConfig *tls.Config
+ connChan chan net.Conn
+ errChan chan error
+}
+
+// H2Listener creates a Listener for HTTP2 h2 tunnel server.
+func H2Listener(addr string, config *tls.Config) (Listener, error) {
+ ln, err := net.Listen("tcp", addr)
+ if err != nil {
+ return nil, err
+ }
+ if config == nil {
+ config = DefaultTLSConfig
+ }
+
+ l := &h2Listener{
+ Listener: tcpKeepAliveListener{ln.(*net.TCPListener)},
+ server: &http2.Server{
+ // MaxConcurrentStreams: 1000,
+ PermitProhibitedCipherSuites: true,
+ IdleTimeout: 5 * time.Minute,
+ },
+ tlsConfig: config,
+ connChan: make(chan net.Conn, 1024),
+ errChan: make(chan error, 1),
+ }
+ go l.listenLoop()
+
+ return l, nil
+}
+
+// H2CListener creates a Listener for HTTP2 h2c tunnel server.
+func H2CListener(addr string) (Listener, error) {
+ ln, err := net.Listen("tcp", addr)
+ if err != nil {
+ return nil, err
+ }
+ l := &h2Listener{
+ Listener: tcpKeepAliveListener{ln.(*net.TCPListener)},
+ server: &http2.Server{
+ // MaxConcurrentStreams: 1000,
+ },
+ connChan: make(chan net.Conn, 1024),
+ errChan: make(chan error, 1),
+ }
+ go l.listenLoop()
+
+ return l, nil
+}
+
+func (l *h2Listener) listenLoop() {
+ for {
+ conn, err := l.Listener.Accept()
+ if err != nil {
+ log.Log("[http2] accept:", err)
+ l.errChan <- err
+ close(l.errChan)
+ return
+ }
+ go l.handleLoop(conn)
+ }
+}
+
+func (l *h2Listener) handleLoop(conn net.Conn) {
+ if l.tlsConfig != nil {
+ conn = tls.Server(conn, l.tlsConfig)
+ }
+
+ if tc, ok := conn.(*tls.Conn); ok {
+ // NOTE: HTTP2 server will check the TLS version,
+ // so we must ensure that the TLS connection is handshake completed.
+ if err := tc.Handshake(); err != nil {
+ log.Logf("[http2] %s - %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
+ return
+ }
+ }
+
+ opt := http2.ServeConnOpts{
+ Handler: http.HandlerFunc(l.handleFunc),
+ }
+ l.server.ServeConn(conn, &opt)
+}
+
+func (l *h2Listener) handleFunc(w http.ResponseWriter, r *http.Request) {
+ log.Logf("[http2] %s %s - %s %s", r.Method, r.RemoteAddr, r.Host, r.Proto)
+ if Debug {
+ dump, _ := httputil.DumpRequest(r, false)
+ log.Log("[http2]", string(dump))
+ }
+ w.Header().Set("Proxy-Agent", "gost/"+Version)
+ conn, err := l.upgrade(w, r)
+ if err != nil {
+ log.Logf("[http2] %s %s - %s %s", r.Method, r.RemoteAddr, r.Host, r.Proto)
+ return
+ }
+ select {
+ case l.connChan <- conn:
+ default:
+ conn.Close()
+ log.Logf("[http2] %s - %s: connection queue is full", conn.RemoteAddr(), conn.LocalAddr())
+ }
+
+ <-conn.closed // NOTE: we need to wait for streaming end, or the connection will be closed
+}
+
+func (l *h2Listener) upgrade(w http.ResponseWriter, r *http.Request) (*http2Conn, error) {
+ if r.Method != http.MethodConnect {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return nil, errors.New("Method not allowed")
+ }
+ w.WriteHeader(http.StatusOK)
+ if fw, ok := w.(http.Flusher); ok {
+ fw.Flush() // write header to client
+ }
+
+ remoteAddr, _ := net.ResolveTCPAddr("tcp", r.RemoteAddr)
+ if remoteAddr == nil {
+ remoteAddr = &net.TCPAddr{
+ IP: net.IPv4zero,
+ Port: 0,
+ }
+ }
+ conn := &http2Conn{
+ r: r.Body,
+ w: flushWriter{w},
+ localAddr: l.Listener.Addr(),
+ remoteAddr: remoteAddr,
+ closed: make(chan struct{}),
+ }
+ return conn, nil
+}
+
+func (l *h2Listener) Accept() (conn net.Conn, err error) {
+ var ok bool
+ select {
+ case conn = <-l.connChan:
+ case err, ok = <-l.errChan:
+ if !ok {
+ err = errors.New("accpet on closed listener")
+ }
+ }
+ return
+}
+
+// HTTP2 connection, wrapped up just like a net.Conn
+type http2Conn struct {
+ r io.Reader
+ w io.Writer
+ remoteAddr net.Addr
+ localAddr net.Addr
+ closed chan struct{}
+}
+
+func (c *http2Conn) Read(b []byte) (n int, err error) {
+ return c.r.Read(b)
+}
+
+func (c *http2Conn) Write(b []byte) (n int, err error) {
+ return c.w.Write(b)
+}
+
+func (c *http2Conn) Close() (err error) {
+ select {
+ case <-c.closed:
+ return
+ default:
+ close(c.closed)
+ }
+ if rc, ok := c.r.(io.Closer); ok {
+ err = rc.Close()
+ }
+ if w, ok := c.w.(io.Closer); ok {
+ err = w.Close()
+ }
+ return
+}
+
+func (c *http2Conn) LocalAddr() net.Addr {
+ return c.localAddr
+}
+
+func (c *http2Conn) RemoteAddr() net.Addr {
+ return c.remoteAddr
+}
+
+func (c *http2Conn) SetDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
+
+func (c *http2Conn) SetReadDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
+
+func (c *http2Conn) SetWriteDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
+
+// a dummy HTTP2 server conn used by HTTP2 handler
+type http2ServerConn struct {
+ r *http.Request
+ w http.ResponseWriter
+ closed chan struct{}
+}
+
+func (c *http2ServerConn) Read(b []byte) (n int, err error) {
+ return 0, &net.OpError{Op: "read", Net: "http2", Source: nil, Addr: nil, Err: errors.New("read not supported")}
+}
+
+func (c *http2ServerConn) Write(b []byte) (n int, err error) {
+ return 0, &net.OpError{Op: "write", Net: "http2", Source: nil, Addr: nil, Err: errors.New("write not supported")}
+}
+
+func (c *http2ServerConn) Close() error {
+ select {
+ case <-c.closed:
+ default:
+ close(c.closed)
+ }
+ return nil
+}
+
+func (c *http2ServerConn) LocalAddr() net.Addr {
+ addr, _ := net.ResolveTCPAddr("tcp", c.r.Host)
+ return addr
+}
+
+func (c *http2ServerConn) RemoteAddr() net.Addr {
+ addr, _ := net.ResolveTCPAddr("tcp", c.r.RemoteAddr)
+ return addr
+}
+
+func (c *http2ServerConn) SetDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
+
+func (c *http2ServerConn) SetReadDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
+
+func (c *http2ServerConn) SetWriteDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
+
+// a dummy HTTP2 client conn used by HTTP2 client connector
+type http2ClientConn struct {
+ addr string
+ client *http.Client
+}
+
+func (c *http2ClientConn) Read(b []byte) (n int, err error) {
+ return 0, &net.OpError{Op: "read", Net: "http2", Source: nil, Addr: nil, Err: errors.New("read not supported")}
+}
+
+func (c *http2ClientConn) Write(b []byte) (n int, err error) {
+ return 0, &net.OpError{Op: "write", Net: "http2", Source: nil, Addr: nil, Err: errors.New("write not supported")}
+}
+
+func (c *http2ClientConn) Close() error {
+ return nil
+}
+
+func (c *http2ClientConn) LocalAddr() net.Addr {
+ return nil
+}
+
+func (c *http2ClientConn) RemoteAddr() net.Addr {
+ return nil
+}
+
+func (c *http2ClientConn) SetDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
+
+func (c *http2ClientConn) SetReadDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
+
+func (c *http2ClientConn) SetWriteDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
+
+type flushWriter struct {
+ w io.Writer
+}
+
+func (fw flushWriter) Write(p []byte) (n int, err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ if s, ok := r.(string); ok {
+ err = errors.New(s)
+ log.Log("[http2]", err)
+ return
+ }
+ err = r.(error)
+ }
+ }()
+
+ n, err = fw.w.Write(p)
+ if err != nil {
+ // log.Log("flush writer:", err)
+ return
+ }
+ if f, ok := fw.w.(http.Flusher); ok {
+ f.Flush()
+ }
+ return
+}
diff --git a/kcp.go b/kcp.go
index 10752c3..857c697 100644
--- a/kcp.go
+++ b/kcp.go
@@ -1,28 +1,30 @@
-// KCP feature is based on https://github.com/xtaci/kcptun
-
package gost
import (
"crypto/sha1"
- "encoding/json"
- "github.com/golang/glog"
- "github.com/klauspost/compress/snappy"
- "golang.org/x/crypto/pbkdf2"
- "gopkg.in/xtaci/kcp-go.v2"
- "gopkg.in/xtaci/smux.v1"
+ "encoding/csv"
+ "errors"
+ "fmt"
"net"
"os"
"time"
-)
-const (
- DefaultKCPConfigFile = "kcp.json"
+ "golang.org/x/crypto/pbkdf2"
+
+ "sync"
+
+ "github.com/go-log/log"
+ "github.com/klauspost/compress/snappy"
+ "gopkg.in/xtaci/kcp-go.v2"
+ "gopkg.in/xtaci/smux.v1"
)
var (
- SALT = "kcp-go"
+ // KCPSalt is the default salt for KCP cipher.
+ KCPSalt = "kcp-go"
)
+// KCPConfig describes the config for KCP.
type KCPConfig struct {
Key string `json:"key"`
Crypt string `json:"crypt"`
@@ -41,41 +43,29 @@ type KCPConfig struct {
NoCongestion int `json:"nc"`
SockBuf int `json:"sockbuf"`
KeepAlive int `json:"keepalive"`
+ SnmpLog string `json:"snmplog"`
+ SnmpPeriod int `json:"snmpperiod"`
+ Signal bool `json:"signal"` // Signal enables the signal SIGUSR1 feature.
}
-func ParseKCPConfig(configFile string) (*KCPConfig, error) {
- if configFile == "" {
- configFile = DefaultKCPConfigFile
- }
- file, err := os.Open(configFile)
- if err != nil {
- return nil, err
- }
- defer file.Close()
-
- config := &KCPConfig{}
- if err = json.NewDecoder(file).Decode(config); err != nil {
- return nil, err
- }
- return config, nil
-}
-
+// Init initializes the KCP config.
func (c *KCPConfig) Init() {
switch c.Mode {
case "normal":
- c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 30, 2, 1
+ c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 50, 2, 1
case "fast2":
- c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 20, 2, 1
+ c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 30, 2, 1
case "fast3":
- c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 10, 2, 1
+ c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 20, 2, 1
case "fast":
fallthrough
default:
- c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 20, 2, 1
+ c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 0, 40, 2, 1
}
}
var (
+ // DefaultKCPConfig is the default KCP config.
DefaultKCPConfig = &KCPConfig{
Key: "it's a secrect",
Crypt: "aes",
@@ -89,92 +79,330 @@ var (
NoComp: false,
AckNodelay: false,
NoDelay: 0,
- Interval: 40,
+ Interval: 50,
Resend: 0,
NoCongestion: 0,
SockBuf: 4194304,
KeepAlive: 10,
+ SnmpLog: "",
+ SnmpPeriod: 60,
+ Signal: false,
}
)
-type KCPServer struct {
- Base *ProxyServer
- Config *KCPConfig
+type kcpConn struct {
+ conn net.Conn
+ stream *smux.Stream
}
-func NewKCPServer(base *ProxyServer, config *KCPConfig) *KCPServer {
- return &KCPServer{Base: base, Config: config}
+func (c *kcpConn) Read(b []byte) (n int, err error) {
+ return c.stream.Read(b)
}
-func (s *KCPServer) ListenAndServe() (err error) {
- if s.Config == nil {
- s.Config = DefaultKCPConfig
- }
- s.Config.Init()
+func (c *kcpConn) Write(b []byte) (n int, err error) {
+ return c.stream.Write(b)
+}
- ln, err := kcp.ListenWithOptions(s.Base.Node.Addr,
- blockCrypt(s.Config.Key, s.Config.Crypt, SALT), s.Config.DataShard, s.Config.ParityShard)
+func (c *kcpConn) Close() error {
+ return c.stream.Close()
+}
+
+func (c *kcpConn) LocalAddr() net.Addr {
+ return c.conn.LocalAddr()
+}
+
+func (c *kcpConn) RemoteAddr() net.Addr {
+ return c.conn.RemoteAddr()
+}
+
+func (c *kcpConn) SetDeadline(t time.Time) error {
+ return c.conn.SetDeadline(t)
+}
+
+func (c *kcpConn) SetReadDeadline(t time.Time) error {
+ return c.conn.SetReadDeadline(t)
+}
+
+func (c *kcpConn) SetWriteDeadline(t time.Time) error {
+ return c.conn.SetWriteDeadline(t)
+}
+
+type kcpSession struct {
+ conn net.Conn
+ session *smux.Session
+}
+
+func (session *kcpSession) GetConn() (*kcpConn, error) {
+ stream, err := session.session.OpenStream()
if err != nil {
- return err
+ return nil, err
}
- if err = ln.SetDSCP(s.Config.DSCP); err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
+ return &kcpConn{conn: session.conn, stream: stream}, nil
+}
+
+func (session *kcpSession) Close() error {
+ return session.session.Close()
+}
+
+func (session *kcpSession) IsClosed() bool {
+ return session.session.IsClosed()
+}
+
+func (session *kcpSession) NumStreams() int {
+ return session.session.NumStreams()
+}
+
+type kcpTransporter struct {
+ sessions map[string]*kcpSession
+ sessionMutex sync.Mutex
+ config *KCPConfig
+}
+
+// KCPTransporter creates a Transporter that is used by KCP proxy client.
+func KCPTransporter(config *KCPConfig) Transporter {
+ if config == nil {
+ config = DefaultKCPConfig
}
- if err = ln.SetReadBuffer(s.Config.SockBuf); err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- }
- if err = ln.SetWriteBuffer(s.Config.SockBuf); err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
+ config.Init()
+
+ go snmpLogger(config.SnmpLog, config.SnmpPeriod)
+ if config.Signal {
+ go kcpSigHandler()
}
- for {
- conn, err := ln.AcceptKCP()
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- continue
- }
-
- conn.SetStreamMode(true)
- conn.SetNoDelay(s.Config.NoDelay, s.Config.Interval, s.Config.Resend, s.Config.NoCongestion)
- conn.SetMtu(s.Config.MTU)
- conn.SetWindowSize(s.Config.SndWnd, s.Config.RcvWnd)
- conn.SetACKNoDelay(s.Config.AckNodelay)
- conn.SetKeepAlive(s.Config.KeepAlive)
-
- go s.handleMux(conn)
+ return &kcpTransporter{
+ config: config,
+ sessions: make(map[string]*kcpSession),
}
}
-func (s *KCPServer) handleMux(conn net.Conn) {
+func (tr *kcpTransporter) Dial(addr string, options ...DialOption) (conn net.Conn, err error) {
+ uaddr, err := net.ResolveUDPAddr("udp", addr)
+ if err != nil {
+ return
+ }
+
+ tr.sessionMutex.Lock()
+ defer tr.sessionMutex.Unlock()
+
+ session, ok := tr.sessions[addr]
+ if !ok {
+ conn, err = net.DialUDP("udp", nil, uaddr)
+ if err != nil {
+ return
+ }
+ session = &kcpSession{conn: conn}
+ tr.sessions[addr] = session
+ }
+ return session.conn, nil
+}
+
+func (tr *kcpTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
+ opts := &HandshakeOptions{}
+ for _, option := range options {
+ option(opts)
+ }
+ config := tr.config
+ if opts.KCPConfig != nil {
+ config = opts.KCPConfig
+ }
+ tr.sessionMutex.Lock()
+ defer tr.sessionMutex.Unlock()
+
+ session, ok := tr.sessions[opts.Addr]
+ if session != nil && session.conn != conn {
+ conn.Close()
+ return nil, errors.New("kcp: unrecognized connection")
+ }
+ if !ok || session.session == nil {
+ s, err := tr.initSession(opts.Addr, conn, config)
+ if err != nil {
+ conn.Close()
+ delete(tr.sessions, opts.Addr)
+ return nil, err
+ }
+ session = s
+ tr.sessions[opts.Addr] = session
+ }
+ cc, err := session.GetConn()
+ if err != nil {
+ session.Close()
+ delete(tr.sessions, opts.Addr)
+ return nil, err
+ }
+
+ return cc, nil
+}
+
+func (tr *kcpTransporter) initSession(addr string, conn net.Conn, config *KCPConfig) (*kcpSession, error) {
+ udpConn, ok := conn.(*net.UDPConn)
+ if !ok {
+ return nil, errors.New("kcp: wrong connection type")
+ }
+
+ kcpconn, err := kcp.NewConn(addr,
+ blockCrypt(config.Key, config.Crypt, KCPSalt),
+ config.DataShard, config.ParityShard,
+ &kcp.ConnectedUDPConn{UDPConn: udpConn, Conn: udpConn})
+ if err != nil {
+ return nil, err
+ }
+
+ kcpconn.SetStreamMode(true)
+ kcpconn.SetNoDelay(config.NoDelay, config.Interval, config.Resend, config.NoCongestion)
+ kcpconn.SetWindowSize(config.SndWnd, config.RcvWnd)
+ kcpconn.SetMtu(config.MTU)
+ kcpconn.SetACKNoDelay(config.AckNodelay)
+ kcpconn.SetKeepAlive(config.KeepAlive)
+
+ if err := kcpconn.SetDSCP(config.DSCP); err != nil {
+ log.Log("[kcp]", err)
+ }
+ if err := kcpconn.SetReadBuffer(config.SockBuf); err != nil {
+ log.Log("[kcp]", err)
+ }
+ if err := kcpconn.SetWriteBuffer(config.SockBuf); err != nil {
+ log.Log("[kcp]", err)
+ }
+
+ // stream multiplex
smuxConfig := smux.DefaultConfig()
- smuxConfig.MaxReceiveBuffer = s.Config.SockBuf
+ smuxConfig.MaxReceiveBuffer = config.SockBuf
+ var cc net.Conn = kcpconn
+ if !config.NoComp {
+ cc = newCompStreamConn(kcpconn)
+ }
+ session, err := smux.Client(cc, smuxConfig)
+ if err != nil {
+ return nil, err
+ }
+ return &kcpSession{conn: conn, session: session}, nil
+}
- glog.V(LINFO).Infof("[kcp] %s - %s", conn.RemoteAddr(), s.Base.Node.Addr)
+func (tr *kcpTransporter) Multiplex() bool {
+ return true
+}
- if !s.Config.NoComp {
+type kcpListener struct {
+ config *KCPConfig
+ ln *kcp.Listener
+ connChan chan net.Conn
+ errChan chan error
+}
+
+// KCPListener creates a Listener for KCP proxy server.
+func KCPListener(addr string, config *KCPConfig) (Listener, error) {
+ if config == nil {
+ config = DefaultKCPConfig
+ }
+ config.Init()
+
+ ln, err := kcp.ListenWithOptions(addr,
+ blockCrypt(config.Key, config.Crypt, KCPSalt), config.DataShard, config.ParityShard)
+ if err != nil {
+ return nil, err
+ }
+ if err = ln.SetDSCP(config.DSCP); err != nil {
+ log.Log("[kcp]", err)
+ }
+ if err = ln.SetReadBuffer(config.SockBuf); err != nil {
+ log.Log("[kcp]", err)
+ }
+ if err = ln.SetWriteBuffer(config.SockBuf); err != nil {
+ log.Log("[kcp]", err)
+ }
+
+ go snmpLogger(config.SnmpLog, config.SnmpPeriod)
+ if config.Signal {
+ go kcpSigHandler()
+ }
+
+ l := &kcpListener{
+ config: config,
+ ln: ln,
+ connChan: make(chan net.Conn, 1024),
+ errChan: make(chan error, 1),
+ }
+ go l.listenLoop()
+
+ return l, nil
+}
+
+func (l *kcpListener) listenLoop() {
+ for {
+ conn, err := l.ln.AcceptKCP()
+ if err != nil {
+ log.Log("[kcp] accept:", err)
+ l.errChan <- err
+ close(l.errChan)
+ return
+ }
+ conn.SetStreamMode(true)
+ conn.SetNoDelay(l.config.NoDelay, l.config.Interval, l.config.Resend, l.config.NoCongestion)
+ conn.SetMtu(l.config.MTU)
+ conn.SetWindowSize(l.config.SndWnd, l.config.RcvWnd)
+ conn.SetACKNoDelay(l.config.AckNodelay)
+ conn.SetKeepAlive(l.config.KeepAlive)
+ go l.mux(conn)
+ }
+}
+
+func (l *kcpListener) mux(conn net.Conn) {
+ smuxConfig := smux.DefaultConfig()
+ smuxConfig.MaxReceiveBuffer = l.config.SockBuf
+
+ log.Logf("[kcp] %s - %s", conn.RemoteAddr(), l.Addr())
+
+ if !l.config.NoComp {
conn = newCompStreamConn(conn)
}
mux, err := smux.Server(conn, smuxConfig)
if err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
+ log.Log("[kcp]", err)
return
}
defer mux.Close()
- glog.V(LINFO).Infof("[kcp] %s <-> %s", conn.RemoteAddr(), s.Base.Node.Addr)
- defer glog.V(LINFO).Infof("[kcp] %s >-< %s", conn.RemoteAddr(), s.Base.Node.Addr)
+ log.Logf("[kcp] %s <-> %s", conn.RemoteAddr(), l.Addr())
+ defer log.Logf("[kcp] %s >-< %s", conn.RemoteAddr(), l.Addr())
for {
stream, err := mux.AcceptStream()
if err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
+ log.Log("[kcp] accept stream:", err)
return
}
- go s.Base.handleConn(NewKCPConn(conn, stream))
+
+ cc := &kcpConn{conn: conn, stream: stream}
+ select {
+ case l.connChan <- cc:
+ default:
+ cc.Close()
+ log.Logf("[kcp] %s - %s: connection queue is full", conn.RemoteAddr(), conn.LocalAddr())
+ }
}
}
+func (l *kcpListener) Accept() (conn net.Conn, err error) {
+ var ok bool
+ select {
+ case conn = <-l.connChan:
+ case err, ok = <-l.errChan:
+ if !ok {
+ err = errors.New("accpet on closed listener")
+ }
+ }
+ return
+}
+func (l *kcpListener) Addr() net.Addr {
+ return l.ln.Addr()
+}
+
+func (l *kcpListener) Close() error {
+ return l.ln.Close()
+}
+
func blockCrypt(key, crypt, salt string) (block kcp.BlockCrypt) {
pass := pbkdf2.Key([]byte(key), []byte(salt), 4096, 32, sha1.New)
@@ -209,115 +437,35 @@ func blockCrypt(key, crypt, salt string) (block kcp.BlockCrypt) {
return
}
-type KCPSession struct {
- conn net.Conn
- session *smux.Session
-}
-
-func DialKCP(addr string, config *KCPConfig) (*KCPSession, error) {
- if config == nil {
- config = DefaultKCPConfig
+func snmpLogger(format string, interval int) {
+ if format == "" || interval == 0 {
+ return
}
- config.Init()
-
- kcpconn, err := kcp.DialWithOptions(addr,
- blockCrypt(config.Key, config.Crypt, SALT), config.DataShard, config.ParityShard)
- if err != nil {
- return nil, err
+ ticker := time.NewTicker(time.Duration(interval) * time.Second)
+ defer ticker.Stop()
+ for {
+ select {
+ case <-ticker.C:
+ f, err := os.OpenFile(time.Now().Format(format), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
+ if err != nil {
+ log.Log("[kcp]", err)
+ return
+ }
+ w := csv.NewWriter(f)
+ // write header in empty file
+ if stat, err := f.Stat(); err == nil && stat.Size() == 0 {
+ if err := w.Write(append([]string{"Unix"}, kcp.DefaultSnmp.Header()...)); err != nil {
+ log.Log("[kcp]", err)
+ }
+ }
+ if err := w.Write(append([]string{fmt.Sprint(time.Now().Unix())}, kcp.DefaultSnmp.ToSlice()...)); err != nil {
+ log.Log("[kcp]", err)
+ }
+ kcp.DefaultSnmp.Reset()
+ w.Flush()
+ f.Close()
+ }
}
-
- kcpconn.SetStreamMode(true)
- kcpconn.SetNoDelay(config.NoDelay, config.Interval, config.Resend, config.NoCongestion)
- kcpconn.SetWindowSize(config.SndWnd, config.RcvWnd)
- kcpconn.SetMtu(config.MTU)
- kcpconn.SetACKNoDelay(config.AckNodelay)
- kcpconn.SetKeepAlive(config.KeepAlive)
-
- if err := kcpconn.SetDSCP(config.DSCP); err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- }
- if err := kcpconn.SetReadBuffer(config.SockBuf); err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- }
- if err := kcpconn.SetWriteBuffer(config.SockBuf); err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- }
-
- // stream multiplex
- smuxConfig := smux.DefaultConfig()
- smuxConfig.MaxReceiveBuffer = config.SockBuf
- var conn net.Conn = kcpconn
- if !config.NoComp {
- conn = newCompStreamConn(kcpconn)
- }
- session, err := smux.Client(conn, smuxConfig)
- if err != nil {
- conn.Close()
- return nil, err
- }
- return &KCPSession{conn: conn, session: session}, nil
-}
-
-func (session *KCPSession) GetConn() (*KCPConn, error) {
- stream, err := session.session.OpenStream()
- if err != nil {
- session.Close()
- return nil, err
- }
- return NewKCPConn(session.conn, stream), nil
-}
-
-func (session *KCPSession) Close() error {
- return session.session.Close()
-}
-
-func (session *KCPSession) IsClosed() bool {
- return session.session.IsClosed()
-}
-
-func (session *KCPSession) NumStreams() int {
- return session.session.NumStreams()
-}
-
-type KCPConn struct {
- conn net.Conn
- stream *smux.Stream
-}
-
-func NewKCPConn(conn net.Conn, stream *smux.Stream) *KCPConn {
- return &KCPConn{conn: conn, stream: stream}
-}
-
-func (c *KCPConn) Read(b []byte) (n int, err error) {
- return c.stream.Read(b)
-}
-
-func (c *KCPConn) Write(b []byte) (n int, err error) {
- return c.stream.Write(b)
-}
-
-func (c *KCPConn) Close() error {
- return c.stream.Close()
-}
-
-func (c *KCPConn) LocalAddr() net.Addr {
- return c.conn.LocalAddr()
-}
-
-func (c *KCPConn) RemoteAddr() net.Addr {
- return c.conn.RemoteAddr()
-}
-
-func (c *KCPConn) SetDeadline(t time.Time) error {
- return c.conn.SetDeadline(t)
-}
-
-func (c *KCPConn) SetReadDeadline(t time.Time) error {
- return c.conn.SetReadDeadline(t)
-}
-
-func (c *KCPConn) SetWriteDeadline(t time.Time) error {
- return c.conn.SetWriteDeadline(t)
}
type compStreamConn struct {
diff --git a/log.go b/log.go
new file mode 100644
index 0000000..0c22259
--- /dev/null
+++ b/log.go
@@ -0,0 +1,32 @@
+package gost
+
+import (
+ "fmt"
+ "log"
+)
+
+func init() {
+ log.SetFlags(log.LstdFlags | log.Lshortfile)
+}
+
+// LogLogger uses the standard log package as the logger
+type LogLogger struct {
+}
+
+func (l *LogLogger) Log(v ...interface{}) {
+ log.Output(3, fmt.Sprintln(v...))
+}
+
+func (l *LogLogger) Logf(format string, v ...interface{}) {
+ log.Output(3, fmt.Sprintf(format, v...))
+}
+
+// NopLogger is a dummy logger that discards the log outputs
+type NopLogger struct {
+}
+
+func (l *NopLogger) Log(v ...interface{}) {
+}
+
+func (l *NopLogger) Logf(format string, v ...interface{}) {
+}
diff --git a/node.go b/node.go
index def140d..125d4b7 100644
--- a/node.go
+++ b/node.go
@@ -1,63 +1,41 @@
package gost
import (
- "bufio"
- "fmt"
- "github.com/golang/glog"
"net"
"net/url"
- "os"
"strconv"
"strings"
)
-// Proxy node represent a proxy
-type ProxyNode struct {
- Addr string // [host]:port
- Protocol string // protocol: http/socks5/ss
- Transport string // transport: ws/wss/tls/http2/tcp/udp/rtcp/rudp
- Remote string // remote address, used by tcp/udp port forwarding
- Users []*url.Userinfo // authentication for proxy
- values url.Values
- serverName string
- conn net.Conn
+// Node is a proxy node, mainly used to construct a proxy chain.
+type Node struct {
+ Addr string
+ Protocol string
+ Transport string
+ Remote string // remote address, used by tcp/udp port forwarding
+ User *url.Userinfo
+ Values url.Values
+ Client *Client
+ DialOptions []DialOption
+ HandshakeOptions []HandshakeOption
}
+// ParseNode parses the node info.
// The proxy node string pattern is [scheme://][user:pass@host]:port.
-//
// Scheme can be devided into two parts by character '+', such as: http+tls.
-func ParseProxyNode(s string, isServeNode bool) (node ProxyNode, err error) {
+func ParseNode(s string) (node Node, err error) {
if !strings.Contains(s, "://") {
- s = "gost://" + s
+ s = "auto://" + s
}
u, err := url.Parse(s)
if err != nil {
return
}
- node = ProxyNode{
- Addr: u.Host,
- values: u.Query(),
- serverName: u.Host,
- }
-
- if u.User != nil {
- node.Users = append(node.Users, u.User)
- }
-
- users, er := parseUsers(node.Get("secrets"))
- if users != nil {
- node.Users = append(node.Users, users...)
- }
- if er != nil {
- glog.V(LWARNING).Infoln("secrets:", er)
- }
-
- if strings.Contains(u.Host, ":") {
- node.serverName, _, _ = net.SplitHostPort(u.Host)
- if node.serverName == "" {
- node.serverName = "localhost" // default server name
- }
+ node = Node{
+ Addr: u.Host,
+ Values: u.Query(),
+ User: u.User,
}
schemes := strings.Split(u.Scheme, "+")
@@ -71,26 +49,24 @@ func ParseProxyNode(s string, isServeNode bool) (node ProxyNode, err error) {
}
switch node.Transport {
- case "ws", "wss", "tls", "http2", "quic", "kcp", "redirect", "ssu":
+ case "tls", "ws", "wss", "kcp", "ssh", "quic", "ssu", "http2", "h2", "h2c", "redirect", "obfs4":
case "https":
node.Protocol = "http"
node.Transport = "tls"
case "tcp", "udp": // started from v2.1, tcp and udp are for local port forwarding
node.Remote = strings.Trim(u.EscapedPath(), "/")
- case "rtcp", "rudp": // started from v2.1, rtcp and rudp are for remote port forwarding
+ case "rtcp", "rudp": // rtcp and rudp are for remote port forwarding
node.Remote = strings.Trim(u.EscapedPath(), "/")
- case "obfs4":
- err := node.Obfs4Init(isServeNode)
- if err != nil {
- glog.V(LDEBUG).Infoln("obfs4 init failed", err)
- return node, err
- }
default:
node.Transport = ""
}
switch node.Protocol {
- case "http", "http2", "socks", "socks5", "ss":
+ case "http", "http2", "socks4", "socks4a", "ss", "ssu":
+ case "socks", "socks5":
+ node.Protocol = "socks5"
+ case "tcp", "udp", "rtcp", "rudp": // port forwarding
+ case "direct", "remote", "forward": // SSH port forwarding
default:
node.Protocol = ""
}
@@ -98,70 +74,21 @@ func ParseProxyNode(s string, isServeNode bool) (node ProxyNode, err error) {
return
}
-func parseUsers(authFile string) (users []*url.Userinfo, err error) {
- if authFile == "" {
- return
+func Can(action string, addr string, whitelist, blacklist *Permissions) bool {
+ if !strings.Contains(addr, ":") {
+ addr = addr + ":80"
}
+ host, strport, err := net.SplitHostPort(addr)
- file, err := os.Open(authFile)
if err != nil {
- return
- }
- scanner := bufio.NewScanner(file)
- for scanner.Scan() {
- line := strings.TrimSpace(scanner.Text())
- if line == "" || strings.HasPrefix(line, "#") {
- continue
- }
-
- s := strings.SplitN(line, " ", 2)
- if len(s) == 1 {
- users = append(users, url.User(strings.TrimSpace(s[0])))
- } else if len(s) == 2 {
- users = append(users, url.UserPassword(strings.TrimSpace(s[0]), strings.TrimSpace(s[1])))
- }
+ return false
}
- err = scanner.Err()
- return
-}
+ port, err := strconv.Atoi(strport)
-// Get get node parameter by key
-func (node *ProxyNode) Get(key string) string {
- return node.values.Get(key)
-}
-
-func (node *ProxyNode) getBool(key string) bool {
- s := node.Get(key)
- if b, _ := strconv.ParseBool(s); b {
- return b
+ if err != nil {
+ return false
}
- n, _ := strconv.Atoi(s)
- return n > 0
-}
-func (node *ProxyNode) Set(key, value string) {
- node.values.Set(key, value)
-}
-
-func (node *ProxyNode) insecureSkipVerify() bool {
- return !node.getBool("secure")
-}
-
-func (node *ProxyNode) certFile() string {
- if cert := node.Get("cert"); cert != "" {
- return cert
- }
- return DefaultCertFile
-}
-
-func (node *ProxyNode) keyFile() string {
- if key := node.Get("key"); key != "" {
- return key
- }
- return DefaultKeyFile
-}
-
-func (node ProxyNode) String() string {
- return fmt.Sprintf("transport: %s, protocol: %s, addr: %s", node.Transport, node.Protocol, node.Addr)
+ return whitelist.Can(action, host, port) && !blacklist.Can(action, host, port)
}
diff --git a/obfs4.go b/obfs4.go
index c8aa5b6..68087c5 100644
--- a/obfs4.go
+++ b/obfs4.go
@@ -1,4 +1,4 @@
-// obfs4 connection wrappers
+// obfs4 connection wrappers
package gost
@@ -6,47 +6,36 @@ import (
"fmt"
"net"
"net/url"
- "git.torproject.org/pluggable-transports/goptlib.git" // package pt
+
+ "github.com/go-log/log"
+
+ pt "git.torproject.org/pluggable-transports/goptlib.git"
"git.torproject.org/pluggable-transports/obfs4.git/transports/base"
- "git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4"
+ "git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4"
)
-// Factories are stored per node since some arguments reside in them.
-// For simplicity, c & s variables are packed together.
-
type obfs4Context struct {
- cf base.ClientFactory
- cargs interface{} // type obfs4ClientArgs
- sf base.ServerFactory
- sargs *pt.Args
+ cf base.ClientFactory
+ cargs interface{} // type obfs4ClientArgs
+ sf base.ServerFactory
+ sargs *pt.Args
}
-
+
var obfs4Map = make(map[string]obfs4Context)
-func (node *ProxyNode) obfs4GetContext() (obfs4Context, error) {
- if node.Transport != "obfs4" {
- return obfs4Context{}, fmt.Errorf("non-obfs4 node has no obfs4 context")
- }
- ctx, ok := obfs4Map[node.Addr]
- if !ok {
- return obfs4Context{}, fmt.Errorf("obfs4 context not inited")
- }
- return ctx, nil
-}
-
-func (node *ProxyNode) Obfs4Init(isServeNode bool) error {
+func Obfs4Init(node Node, isServeNode bool) error {
if _, ok := obfs4Map[node.Addr]; ok {
return fmt.Errorf("obfs4 context already inited")
}
t := new(obfs4.Transport)
- stateDir := node.values.Get("state-dir")
+ stateDir := node.Values.Get("state-dir")
if stateDir == "" {
stateDir = "."
}
- ptArgs := pt.Args(node.values)
+ ptArgs := pt.Args(node.Values)
if !isServeNode {
cf, err := t.ClientFactory(stateDir)
@@ -70,40 +59,28 @@ func (node *ProxyNode) Obfs4Init(isServeNode bool) error {
obfs4Map[node.Addr] = obfs4Context{sf: sf, sargs: sargs}
- fmt.Println("[obfs4 server inited]", node.Obfs4ServerURL())
+ log.Log("[obfs4] server inited:", obfs4ServerURL(node))
}
return nil
}
-func (node *ProxyNode) Obfs4ClientConn(conn net.Conn) (net.Conn, error) {
- ctx, err := node.obfs4GetContext()
- if err != nil {
- return nil, err
+func obfs4GetContext(addr string) (obfs4Context, error) {
+ ctx, ok := obfs4Map[addr]
+ if !ok {
+ return obfs4Context{}, fmt.Errorf("obfs4 context not inited")
}
-
- pseudoDial := func (a, b string) (net.Conn, error) {return conn, nil}
- return ctx.cf.Dial("tcp", "", pseudoDial, ctx.cargs)
+ return ctx, nil
}
-func (node *ProxyNode) Obfs4ServerConn(conn net.Conn) (net.Conn, error) {
- ctx, err := node.obfs4GetContext()
- if err != nil {
- return nil, err
- }
-
- return ctx.sf.WrapConn(conn)
-}
-
-func (node *ProxyNode) Obfs4ServerURL() string {
- ctx, err := node.obfs4GetContext()
+func obfs4ServerURL(node Node) string {
+ ctx, err := obfs4GetContext(node.Addr)
if err != nil {
return ""
}
values := (*url.Values)(ctx.sargs)
query := values.Encode()
-
return fmt.Sprintf(
"%s+%s://%s/?%s", //obfs4-cert=%s&iat-mode=%s",
node.Protocol,
@@ -112,3 +89,70 @@ func (node *ProxyNode) Obfs4ServerURL() string {
query,
)
}
+
+func obfs4ClientConn(addr string, conn net.Conn) (net.Conn, error) {
+ ctx, err := obfs4GetContext(addr)
+ if err != nil {
+ return nil, err
+ }
+
+ pseudoDial := func(a, b string) (net.Conn, error) { return conn, nil }
+ return ctx.cf.Dial("tcp", "", pseudoDial, ctx.cargs)
+}
+
+func obfs4ServerConn(addr string, conn net.Conn) (net.Conn, error) {
+ ctx, err := obfs4GetContext(addr)
+ if err != nil {
+ return nil, err
+ }
+
+ return ctx.sf.WrapConn(conn)
+}
+
+type obfs4Transporter struct {
+ tcpTransporter
+}
+
+// Obfs4Transporter creates a Transporter that is used by obfs4 client.
+func Obfs4Transporter() Transporter {
+ return &obfs4Transporter{}
+}
+
+func (tr *obfs4Transporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
+ opts := &HandshakeOptions{}
+ for _, option := range options {
+ option(opts)
+ }
+ return obfs4ClientConn(opts.Addr, conn)
+}
+
+type obfs4Listener struct {
+ addr string
+ net.Listener
+}
+
+// Obfs4Listener creates a Listener for obfs4 server.
+func Obfs4Listener(addr string) (Listener, error) {
+ ln, err := net.Listen("tcp", addr)
+ if err != nil {
+ return nil, err
+ }
+ l := &obfs4Listener{
+ addr: addr,
+ Listener: ln,
+ }
+ return l, nil
+}
+
+func (l *obfs4Listener) Accept() (net.Conn, error) {
+ conn, err := l.Listener.Accept()
+ if err != nil {
+ return nil, err
+ }
+ cc, err := obfs4ServerConn(l.addr, conn)
+ if err != nil {
+ conn.Close()
+ return nil, err
+ }
+ return cc, nil
+}
diff --git a/permissions.go b/permissions.go
new file mode 100644
index 0000000..8566c80
--- /dev/null
+++ b/permissions.go
@@ -0,0 +1,185 @@
+package gost
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+
+ glob "github.com/ryanuber/go-glob"
+)
+
+type Permission struct {
+ Actions StringSet
+ Hosts StringSet
+ Ports PortSet
+}
+
+type Permissions []Permission
+
+func minint(x, y int) int {
+ if x < y {
+ return x
+ }
+ return y
+}
+
+func maxint(x, y int) int {
+ if x > y {
+ return x
+ }
+ return y
+}
+
+type PortRange struct {
+ Min, Max int
+}
+
+func (ir *PortRange) Contains(value int) bool {
+ return value >= ir.Min && value <= ir.Max
+}
+
+func ParsePortRange(s string) (*PortRange, error) {
+ if s == "*" {
+ return &PortRange{Min: 0, Max: 65535}, nil
+ }
+
+ minmax := strings.Split(s, "-")
+ switch len(minmax) {
+ case 1:
+ port, err := strconv.Atoi(s)
+ if err != nil {
+ return nil, err
+ }
+ if port < 0 || port > 65535 {
+ return nil, fmt.Errorf("invalid port: %s", s)
+ }
+ return &PortRange{Min: port, Max: port}, nil
+ case 2:
+ min, err := strconv.Atoi(minmax[0])
+ if err != nil {
+ return nil, err
+ }
+ max, err := strconv.Atoi(minmax[1])
+ if err != nil {
+ return nil, err
+ }
+
+ realmin := maxint(0, minint(min, max))
+ realmax := minint(65535, maxint(min, max))
+
+ return &PortRange{Min: realmin, Max: realmax}, nil
+ default:
+ return nil, fmt.Errorf("invalid range: %s", s)
+ }
+}
+
+func (ps *PortSet) Contains(value int) bool {
+ for _, portRange := range *ps {
+ if portRange.Contains(value) {
+ return true
+ }
+ }
+
+ return false
+}
+
+type PortSet []PortRange
+
+func ParsePortSet(s string) (*PortSet, error) {
+ ps := &PortSet{}
+
+ if s == "" {
+ return nil, errors.New("must specify at least one port")
+ }
+
+ ranges := strings.Split(s, ",")
+
+ for _, r := range ranges {
+ portRange, err := ParsePortRange(r)
+
+ if err != nil {
+ return nil, err
+ }
+
+ *ps = append(*ps, *portRange)
+ }
+
+ return ps, nil
+}
+
+func (ss *StringSet) Contains(subj string) bool {
+ for _, s := range *ss {
+ if glob.Glob(s, subj) {
+ return true
+ }
+ }
+
+ return false
+}
+
+type StringSet []string
+
+func ParseStringSet(s string) (*StringSet, error) {
+ ss := &StringSet{}
+ if s == "" {
+ return nil, errors.New("cannot be empty")
+ }
+
+ *ss = strings.Split(s, ",")
+
+ return ss, nil
+}
+
+func (ps *Permissions) Can(action string, host string, port int) bool {
+ for _, p := range *ps {
+ if p.Actions.Contains(action) && p.Hosts.Contains(host) && p.Ports.Contains(port) {
+ return true
+ }
+ }
+
+ return false
+}
+
+func ParsePermissions(s string) (*Permissions, error) {
+ ps := &Permissions{}
+
+ if s == "" {
+ return &Permissions{}, nil
+ }
+
+ perms := strings.Split(s, " ")
+
+ for _, perm := range perms {
+ parts := strings.Split(perm, ":")
+
+ switch len(parts) {
+ case 3:
+ actions, err := ParseStringSet(parts[0])
+
+ if err != nil {
+ return nil, fmt.Errorf("action list must look like connect,bind given: %s", parts[0])
+ }
+
+ hosts, err := ParseStringSet(parts[1])
+
+ if err != nil {
+ return nil, fmt.Errorf("hosts list must look like google.pl,*.google.com given: %s", parts[1])
+ }
+
+ ports, err := ParsePortSet(parts[2])
+
+ if err != nil {
+ return nil, fmt.Errorf("ports list must look like 80,8000-9000, given: %s", parts[2])
+ }
+
+ permission := Permission{Actions: *actions, Hosts: *hosts, Ports: *ports}
+
+ *ps = append(*ps, permission)
+ default:
+ return nil, fmt.Errorf("permission must have format [actions]:[hosts]:[ports] given: %s", perm)
+ }
+ }
+
+ return ps, nil
+}
diff --git a/permissions_test.go b/permissions_test.go
new file mode 100644
index 0000000..bc99824
--- /dev/null
+++ b/permissions_test.go
@@ -0,0 +1,152 @@
+package gost
+
+import (
+ "fmt"
+ "testing"
+)
+
+var portRangeTests = []struct {
+ in string
+ out *PortRange
+}{
+ {"1", &PortRange{Min: 1, Max: 1}},
+ {"1-3", &PortRange{Min: 1, Max: 3}},
+ {"3-1", &PortRange{Min: 1, Max: 3}},
+ {"0-100000", &PortRange{Min: 0, Max: 65535}},
+ {"*", &PortRange{Min: 0, Max: 65535}},
+}
+
+var stringSetTests = []struct {
+ in string
+ out *StringSet
+}{
+ {"*", &StringSet{"*"}},
+ {"google.pl,google.com", &StringSet{"google.pl", "google.com"}},
+}
+
+var portSetTests = []struct {
+ in string
+ out *PortSet
+}{
+ {"1,3", &PortSet{PortRange{Min: 1, Max: 1}, PortRange{Min: 3, Max: 3}}},
+ {"1-3,7-5", &PortSet{PortRange{Min: 1, Max: 3}, PortRange{Min: 5, Max: 7}}},
+ {"0-100000", &PortSet{PortRange{Min: 0, Max: 65535}}},
+ {"*", &PortSet{PortRange{Min: 0, Max: 65535}}},
+}
+
+var permissionsTests = []struct {
+ in string
+ out *Permissions
+}{
+ {"", &Permissions{}},
+ {"*:*:*", &Permissions{
+ Permission{
+ Actions: StringSet{"*"},
+ Hosts: StringSet{"*"},
+ Ports: PortSet{PortRange{Min: 0, Max: 65535}},
+ },
+ }},
+ {"bind:127.0.0.1,localhost:80,443,8000-8100 connect:*.google.pl:80,443", &Permissions{
+ Permission{
+ Actions: StringSet{"bind"},
+ Hosts: StringSet{"127.0.0.1", "localhost"},
+ Ports: PortSet{
+ PortRange{Min: 80, Max: 80},
+ PortRange{Min: 443, Max: 443},
+ PortRange{Min: 8000, Max: 8100},
+ },
+ },
+ Permission{
+ Actions: StringSet{"connect"},
+ Hosts: StringSet{"*.google.pl"},
+ Ports: PortSet{
+ PortRange{Min: 80, Max: 80},
+ PortRange{Min: 443, Max: 443},
+ },
+ },
+ }},
+}
+
+func TestPortRangeParse(t *testing.T) {
+ for _, test := range portRangeTests {
+ actual, err := ParsePortRange(test.in)
+ if err != nil {
+ t.Errorf("ParsePortRange(%q) returned error: %v", test.in, err)
+ } else if *actual != *test.out {
+ t.Errorf("ParsePortRange(%q): got %v, want %v", test.in, actual, test.out)
+ }
+ }
+}
+
+func TestPortRangeContains(t *testing.T) {
+ actual, _ := ParsePortRange("5-10")
+
+ if !actual.Contains(5) || !actual.Contains(7) || !actual.Contains(10) {
+ t.Errorf("5-10 should contain 5, 7 and 10")
+ }
+
+ if actual.Contains(4) || actual.Contains(11) {
+ t.Errorf("5-10 should not contain 4, 11")
+ }
+}
+
+func TestStringSetParse(t *testing.T) {
+ for _, test := range stringSetTests {
+ actual, err := ParseStringSet(test.in)
+ if err != nil {
+ t.Errorf("ParseStringSet(%q) returned error: %v", test.in, err)
+ } else if fmt.Sprintln(actual) != fmt.Sprintln(test.out) {
+ t.Errorf("ParseStringSet(%q): got %v, want %v", test.in, actual, test.out)
+ }
+ }
+}
+
+func TestStringSetContains(t *testing.T) {
+ ss, _ := ParseStringSet("google.pl,*.google.com")
+
+ if !ss.Contains("google.pl") || !ss.Contains("www.google.com") {
+ t.Errorf("google.pl,*.google.com should contain google.pl and www.google.com")
+ }
+
+ if ss.Contains("www.google.pl") || ss.Contains("foobar.com") {
+ t.Errorf("google.pl,*.google.com shound not contain www.google.pl and foobar.com")
+ }
+}
+
+func TestPortSetParse(t *testing.T) {
+ for _, test := range portSetTests {
+ actual, err := ParsePortSet(test.in)
+ if err != nil {
+ t.Errorf("ParsePortRange(%q) returned error: %v", test.in, err)
+ } else if fmt.Sprintln(actual) != fmt.Sprintln(test.out) {
+ t.Errorf("ParsePortRange(%q): got %v, want %v", test.in, actual, test.out)
+ }
+ }
+}
+
+func TestPortSetContains(t *testing.T) {
+ actual, _ := ParsePortSet("5-10,20-30")
+
+ if !actual.Contains(5) || !actual.Contains(7) || !actual.Contains(10) {
+ t.Errorf("5-10,20-30 should contain 5, 7 and 10")
+ }
+
+ if !actual.Contains(20) || !actual.Contains(27) || !actual.Contains(30) {
+ t.Errorf("5-10,20-30 should contain 20, 27 and 30")
+ }
+
+ if actual.Contains(4) || actual.Contains(11) || actual.Contains(31) {
+ t.Errorf("5-10,20-30 should not contain 4, 11, 31")
+ }
+}
+
+func TestPermissionsParse(t *testing.T) {
+ for _, test := range permissionsTests {
+ actual, err := ParsePermissions(test.in)
+ if err != nil {
+ t.Errorf("ParsePermissions(%q) returned error: %v", test.in, err)
+ } else if fmt.Sprintln(actual) != fmt.Sprintln(test.out) {
+ t.Errorf("ParsePermissions(%q): got %v, want %v", test.in, actual, test.out)
+ }
+ }
+}
diff --git a/quic.go b/quic.go
index 0d97061..712fdfb 100644
--- a/quic.go
+++ b/quic.go
@@ -1,80 +1,241 @@
package gost
import (
- "bufio"
"crypto/tls"
- "github.com/golang/glog"
- "github.com/lucas-clemente/quic-go/h2quic"
- "io"
- "net/http"
- "net/http/httputil"
+ "errors"
+ "net"
+ "sync"
+ "time"
+
+ "github.com/go-log/log"
+ quic "github.com/lucas-clemente/quic-go"
)
-type QuicServer struct {
- Base *ProxyServer
- Handler http.Handler
+type quicSession struct {
+ conn net.Conn
+ session quic.Session
+}
+
+func (session *quicSession) GetConn() (*quicConn, error) {
+ stream, err := session.session.OpenStream()
+ if err != nil {
+ return nil, err
+ }
+ return &quicConn{
+ Stream: stream,
+ laddr: session.session.LocalAddr(),
+ raddr: session.session.RemoteAddr(),
+ }, nil
+}
+
+func (session *quicSession) Close() error {
+ return session.session.Close(nil)
+}
+
+type quicTransporter struct {
+ config *QUICConfig
+ sessionMutex sync.Mutex
+ sessions map[string]*quicSession
+}
+
+// QUICTransporter creates a Transporter that is used by QUIC proxy client.
+func QUICTransporter(config *QUICConfig) Transporter {
+ if config == nil {
+ config = &QUICConfig{}
+ }
+ return &quicTransporter{
+ config: config,
+ sessions: make(map[string]*quicSession),
+ }
+}
+
+func (tr *quicTransporter) Dial(addr string, options ...DialOption) (conn net.Conn, err error) {
+ tr.sessionMutex.Lock()
+ defer tr.sessionMutex.Unlock()
+
+ session, ok := tr.sessions[addr]
+ if !ok {
+ conn, err = net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
+ if err != nil {
+ return
+ }
+ session = &quicSession{conn: conn}
+ tr.sessions[addr] = session
+ }
+ return session.conn, nil
+}
+
+func (tr *quicTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
+ opts := &HandshakeOptions{}
+ for _, option := range options {
+ option(opts)
+ }
+ config := tr.config
+ if opts.QUICConfig != nil {
+ config = opts.QUICConfig
+ }
+ if config.TLSConfig == nil {
+ config.TLSConfig = &tls.Config{InsecureSkipVerify: true}
+ }
+
+ tr.sessionMutex.Lock()
+ defer tr.sessionMutex.Unlock()
+
+ session, ok := tr.sessions[opts.Addr]
+ if session != nil && session.conn != conn {
+ conn.Close()
+ return nil, errors.New("quic: unrecognized connection")
+ }
+ if !ok || session.session == nil {
+ s, err := tr.initSession(opts.Addr, conn, config)
+ if err != nil {
+ conn.Close()
+ delete(tr.sessions, opts.Addr)
+ return nil, err
+ }
+ session = s
+ tr.sessions[opts.Addr] = session
+ }
+ cc, err := session.GetConn()
+ if err != nil {
+ session.Close()
+ delete(tr.sessions, opts.Addr)
+ return nil, err
+ }
+
+ return cc, nil
+}
+
+func (tr *quicTransporter) initSession(addr string, conn net.Conn, config *QUICConfig) (*quicSession, error) {
+ udpConn, ok := conn.(*net.UDPConn)
+ if !ok {
+ return nil, errors.New("quic: wrong connection type")
+ }
+ udpAddr, err := net.ResolveUDPAddr("udp", addr)
+ if err != nil {
+ return nil, err
+ }
+ quicConfig := &quic.Config{
+ HandshakeTimeout: config.Timeout,
+ KeepAlive: config.KeepAlive,
+ }
+ session, err := quic.Dial(udpConn, udpAddr, addr, config.TLSConfig, quicConfig)
+ if err != nil {
+ log.Log("quic dial", err)
+ return nil, err
+ }
+ return &quicSession{conn: conn, session: session}, nil
+}
+
+func (tr *quicTransporter) Multiplex() bool {
+ return true
+}
+
+type QUICConfig struct {
TLSConfig *tls.Config
+ Timeout time.Duration
+ KeepAlive bool
}
-func NewQuicServer(base *ProxyServer) *QuicServer {
- return &QuicServer{Base: base}
+type quicListener struct {
+ ln quic.Listener
+ connChan chan net.Conn
+ errChan chan error
}
-func (s *QuicServer) ListenAndServeTLS(config *tls.Config) error {
- server := &h2quic.Server{
- Server: &http.Server{
- Addr: s.Base.Node.Addr,
- Handler: s.Handler,
- TLSConfig: config,
- },
+// QUICListener creates a Listener for QUIC proxy server.
+func QUICListener(addr string, config *QUICConfig) (Listener, error) {
+ if config == nil {
+ config = &QUICConfig{}
}
- if server.Handler == nil {
- server.Handler = http.HandlerFunc(s.HandleRequest)
- }
- return server.ListenAndServe()
-}
-
-func (s *QuicServer) HandleRequest(w http.ResponseWriter, req *http.Request) {
- target := req.Host
- glog.V(LINFO).Infof("[quic] %s %s - %s %s", req.Method, req.RemoteAddr, target, req.Proto)
-
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpRequest(req, false)
- glog.Infoln(string(dump))
+ quicConfig := &quic.Config{
+ HandshakeTimeout: config.Timeout,
+ KeepAlive: config.KeepAlive,
}
- c, err := s.Base.Chain.Dial(target)
+ tlsConfig := config.TLSConfig
+ if tlsConfig == nil {
+ tlsConfig = DefaultTLSConfig
+ }
+ ln, err := quic.ListenAddr(addr, tlsConfig, quicConfig)
if err != nil {
- glog.V(LWARNING).Infof("[quic] %s -> %s : %s", req.RemoteAddr, target, err)
- w.WriteHeader(http.StatusServiceUnavailable)
- return
- }
- defer c.Close()
-
- glog.V(LINFO).Infof("[quic] %s <-> %s", req.RemoteAddr, target)
-
- req.Header.Set("Connection", "Keep-Alive")
- if err = req.Write(c); err != nil {
- glog.V(LWARNING).Infof("[quic] %s -> %s : %s", req.RemoteAddr, target, err)
- return
+ return nil, err
}
- resp, err := http.ReadResponse(bufio.NewReader(c), req)
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- return
+ l := &quicListener{
+ ln: ln,
+ connChan: make(chan net.Conn, 1024),
+ errChan: make(chan error, 1),
}
- defer resp.Body.Close()
+ go l.listenLoop()
- for k, v := range resp.Header {
- for _, vv := range v {
- w.Header().Add(k, vv)
+ return l, nil
+}
+
+func (l *quicListener) listenLoop() {
+ for {
+ session, err := l.ln.Accept()
+ if err != nil {
+ log.Log("[quic] accept:", err)
+ l.errChan <- err
+ close(l.errChan)
+ return
+ }
+ go l.sessionLoop(session)
+ }
+}
+
+func (l *quicListener) sessionLoop(session quic.Session) {
+ log.Logf("[quic] %s <-> %s", session.RemoteAddr(), session.LocalAddr())
+ defer log.Logf("[quic] %s >-< %s", session.RemoteAddr(), session.LocalAddr())
+
+ for {
+ stream, err := session.AcceptStream()
+ if err != nil {
+ log.Log("[quic] accept stream:", err)
+ return
+ }
+
+ cc := &quicConn{Stream: stream, laddr: session.LocalAddr(), raddr: session.RemoteAddr()}
+ select {
+ case l.connChan <- cc:
+ default:
+ cc.Close()
+ log.Logf("[quic] %s - %s: connection queue is full", session.RemoteAddr(), session.LocalAddr())
}
}
- w.WriteHeader(resp.StatusCode)
- if _, err := io.Copy(flushWriter{w}, resp.Body); err != nil {
- glog.V(LWARNING).Infof("[quic] %s <- %s : %s", req.RemoteAddr, target, err)
- }
-
- glog.V(LINFO).Infof("[quic] %s >-< %s", req.RemoteAddr, target)
+}
+
+func (l *quicListener) Accept() (conn net.Conn, err error) {
+ var ok bool
+ select {
+ case conn = <-l.connChan:
+ case err, ok = <-l.errChan:
+ if !ok {
+ err = errors.New("accpet on closed listener")
+ }
+ }
+ return
+}
+
+func (l *quicListener) Addr() net.Addr {
+ return l.ln.Addr()
+}
+
+func (l *quicListener) Close() error {
+ return l.ln.Close()
+}
+
+type quicConn struct {
+ quic.Stream
+ laddr net.Addr
+ raddr net.Addr
+}
+
+func (c *quicConn) LocalAddr() net.Addr {
+ return c.laddr
+}
+
+func (c *quicConn) RemoteAddr() net.Addr {
+ return c.raddr
}
diff --git a/redirect.go b/redirect.go
index 7524418..f7033c6 100644
--- a/redirect.go
+++ b/redirect.go
@@ -5,70 +5,58 @@ package gost
import (
"errors"
"fmt"
- "github.com/golang/glog"
"net"
"syscall"
+
+ "github.com/go-log/log"
)
-const (
- SO_ORIGINAL_DST = 80
-)
-
-type RedsocksTCPServer struct {
- Base *ProxyServer
+type tcpRedirectHandler struct {
+ options *HandlerOptions
}
-func NewRedsocksTCPServer(base *ProxyServer) *RedsocksTCPServer {
- return &RedsocksTCPServer{
- Base: base,
+// TCPRedirectHandler creates a server Handler for TCP redirect server.
+func TCPRedirectHandler(opts ...HandlerOption) Handler {
+ h := &tcpRedirectHandler{
+ options: &HandlerOptions{
+ Chain: new(Chain),
+ },
}
+ for _, opt := range opts {
+ opt(h.options)
+ }
+ return h
}
-func (s *RedsocksTCPServer) ListenAndServe() error {
- laddr, err := net.ResolveTCPAddr("tcp", s.Base.Node.Addr)
- if err != nil {
- return err
- }
- ln, err := net.ListenTCP("tcp", laddr)
- if err != nil {
- return err
+func (h *tcpRedirectHandler) Handle(c net.Conn) {
+ conn, ok := c.(*net.TCPConn)
+ if !ok {
+ log.Log("[red-tcp] not a TCP connection")
}
- defer ln.Close()
- for {
- conn, err := ln.AcceptTCP()
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- continue
- }
- go s.handleRedirectTCP(conn)
- }
-}
-
-func (s *RedsocksTCPServer) handleRedirectTCP(conn *net.TCPConn) {
srcAddr := conn.RemoteAddr()
- dstAddr, conn, err := getOriginalDstAddr(conn)
+ dstAddr, conn, err := h.getOriginalDstAddr(conn)
if err != nil {
- glog.V(LWARNING).Infof("[red-tcp] %s -> %s : %s", srcAddr, dstAddr, err)
+ log.Logf("[red-tcp] %s -> %s : %s", srcAddr, dstAddr, err)
return
}
defer conn.Close()
- glog.V(LINFO).Infof("[red-tcp] %s -> %s", srcAddr, dstAddr)
+ log.Logf("[red-tcp] %s -> %s", srcAddr, dstAddr)
- cc, err := s.Base.Chain.Dial(dstAddr.String())
+ cc, err := h.options.Chain.Dial(dstAddr.String())
if err != nil {
- glog.V(LWARNING).Infof("[red-tcp] %s -> %s : %s", srcAddr, dstAddr, err)
+ log.Logf("[red-tcp] %s -> %s : %s", srcAddr, dstAddr, err)
return
}
defer cc.Close()
- glog.V(LINFO).Infof("[red-tcp] %s <-> %s", srcAddr, dstAddr)
- s.Base.transport(conn, cc)
- glog.V(LINFO).Infof("[red-tcp] %s >-< %s", srcAddr, dstAddr)
+ log.Logf("[red-tcp] %s <-> %s", srcAddr, dstAddr)
+ transport(conn, cc)
+ log.Logf("[red-tcp] %s >-< %s", srcAddr, dstAddr)
}
-func getOriginalDstAddr(conn *net.TCPConn) (addr net.Addr, c *net.TCPConn, err error) {
+func (h *tcpRedirectHandler) getOriginalDstAddr(conn *net.TCPConn) (addr net.Addr, c *net.TCPConn, err error) {
defer conn.Close()
fc, err := conn.File()
@@ -77,7 +65,7 @@ func getOriginalDstAddr(conn *net.TCPConn) (addr net.Addr, c *net.TCPConn, err e
}
defer fc.Close()
- mreq, err := syscall.GetsockoptIPv6Mreq(int(fc.Fd()), syscall.IPPROTO_IP, SO_ORIGINAL_DST)
+ mreq, err := syscall.GetsockoptIPv6Mreq(int(fc.Fd()), syscall.IPPROTO_IP, 80)
if err != nil {
return
}
diff --git a/redirect_win.go b/redirect_win.go
index 116bdd8..848b70b 100644
--- a/redirect_win.go
+++ b/redirect_win.go
@@ -3,15 +3,29 @@
package gost
import (
- "errors"
+ "net"
+
+ "github.com/go-log/log"
)
-type RedsocksTCPServer struct{}
-
-func NewRedsocksTCPServer(base *ProxyServer) *RedsocksTCPServer {
- return &RedsocksTCPServer{}
+type tcpRedirectHandler struct {
+ options *HandlerOptions
}
-func (s *RedsocksTCPServer) ListenAndServe() error {
- return errors.New("Not supported")
+// TCPRedirectHandler creates a server Handler for TCP redirect server.
+func TCPRedirectHandler(opts ...HandlerOption) Handler {
+ h := &tcpRedirectHandler{
+ options: &HandlerOptions{
+ Chain: new(Chain),
+ },
+ }
+ for _, opt := range opts {
+ opt(h.options)
+ }
+ return h
+}
+
+func (h *tcpRedirectHandler) Handle(c net.Conn) {
+ log.Log("[red-tcp] TCP redirect is not available on the Windows platform")
+ c.Close()
}
diff --git a/server.go b/server.go
index 10efd5e..fb34958 100644
--- a/server.go
+++ b/server.go
@@ -1,270 +1,104 @@
package gost
import (
- "bufio"
- "crypto/tls"
- "github.com/ginuerzh/gosocks5"
- "github.com/golang/glog"
- ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
"io"
"net"
- "net/http"
- "strconv"
- "strings"
+ "time"
+
+ "github.com/go-log/log"
)
-type ProxyServer struct {
- Node ProxyNode
- Chain *ProxyChain
- TLSConfig *tls.Config
- selector *serverSelector
- cipher *ss.Cipher
- ota bool
+// Server is a proxy server.
+type Server struct {
}
-func NewProxyServer(node ProxyNode, chain *ProxyChain, config *tls.Config) *ProxyServer {
- if chain == nil {
- chain = NewProxyChain()
- }
- if config == nil {
- config = &tls.Config{}
- }
+// Serve serves as a proxy server.
+func (s *Server) Serve(l net.Listener, h Handler) error {
+ defer l.Close()
- var cipher *ss.Cipher
- var ota bool
- if node.Protocol == "ss" || node.Transport == "ssu" {
- var err error
- var method, password string
-
- if len(node.Users) > 0 {
- method = node.Users[0].Username()
- password, _ = node.Users[0].Password()
- }
- ota = node.getBool("ota")
- if strings.HasSuffix(method, "-auth") {
- ota = true
- method = strings.TrimSuffix(method, "-auth")
- }
- cipher, err = ss.NewCipher(method, password)
+ if l == nil {
+ ln, err := TCPListener(":8080")
if err != nil {
- glog.Fatal(err)
+ return err
}
+ l = ln
}
- return &ProxyServer{
- Node: node,
- Chain: chain,
- TLSConfig: config,
- selector: &serverSelector{ // socks5 server selector
- // methods that socks5 server supported
- methods: []uint8{
- gosocks5.MethodNoAuth,
- gosocks5.MethodUserPass,
- MethodTLS,
- MethodTLSAuth,
- },
- users: node.Users,
- tlsConfig: config,
- },
- cipher: cipher,
- ota: ota,
- }
-}
-
-func (s *ProxyServer) Serve() error {
- var ln net.Listener
- var err error
- node := s.Node
-
- switch node.Transport {
- case "ws": // websocket connection
- return NewWebsocketServer(s).ListenAndServe()
- case "wss": // websocket security connection
- return NewWebsocketServer(s).ListenAndServeTLS(s.TLSConfig)
- case "tls": // tls connection
- ln, err = tls.Listen("tcp", node.Addr, s.TLSConfig)
- case "http2": // Standard HTTP2 proxy server, compatible with HTTP1.x.
- server := NewHttp2Server(s)
- server.Handler = http.HandlerFunc(server.HandleRequest)
- return server.ListenAndServeTLS(s.TLSConfig)
- case "tcp": // Local TCP port forwarding
- return NewTcpForwardServer(s).ListenAndServe()
- case "udp": // Local UDP port forwarding
- ttl, _ := strconv.Atoi(s.Node.Get("ttl"))
- if ttl <= 0 {
- ttl = DefaultTTL
- }
- return NewUdpForwardServer(s, ttl).ListenAndServe()
- case "rtcp": // Remote TCP port forwarding
- return NewRTcpForwardServer(s).Serve()
- case "rudp": // Remote UDP port forwarding
- return NewRUdpForwardServer(s).Serve()
- case "quic":
- return NewQuicServer(s).ListenAndServeTLS(s.TLSConfig)
- case "kcp":
- config, err := ParseKCPConfig(s.Node.Get("c"))
- if err != nil {
- glog.V(LWARNING).Infoln("[kcp]", err)
- }
- if config == nil {
- config = DefaultKCPConfig
- }
- // override crypt and key if specified explicitly
- if s.Node.Users != nil {
- config.Crypt = s.Node.Users[0].Username()
- config.Key, _ = s.Node.Users[0].Password()
- }
- return NewKCPServer(s, config).ListenAndServe()
- case "redirect":
- return NewRedsocksTCPServer(s).ListenAndServe()
- case "ssu": // shadowsocks udp relay
- ttl, _ := strconv.Atoi(s.Node.Get("ttl"))
- if ttl <= 0 {
- ttl = DefaultTTL
- }
- return NewShadowUdpServer(s, ttl).ListenAndServe()
- default:
- ln, err = net.Listen("tcp", node.Addr)
+ if h == nil {
+ h = HTTPHandler()
}
- if err != nil {
- return err
- }
-
- defer ln.Close()
-
+ var tempDelay time.Duration
for {
- conn, err := ln.Accept()
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- continue
- }
-
- setKeepAlive(conn, KeepAliveTime)
-
- if node.Transport == "obfs4" {
- obfs4Conn, err := node.Obfs4ServerConn(conn)
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- conn.Close()
+ conn, e := l.Accept()
+ if e != nil {
+ if ne, ok := e.(net.Error); ok && ne.Temporary() {
+ if tempDelay == 0 {
+ tempDelay = 5 * time.Millisecond
+ } else {
+ tempDelay *= 2
+ }
+ if max := 1 * time.Second; tempDelay > max {
+ tempDelay = max
+ }
+ log.Logf("server: Accept error: %v; retrying in %v", e, tempDelay)
+ time.Sleep(tempDelay)
continue
}
- conn = obfs4Conn
+ return e
}
-
- go s.handleConn(conn)
+ tempDelay = 0
+ go h.Handle(conn)
}
+
}
-func (s *ProxyServer) handleConn(conn net.Conn) {
- defer conn.Close()
-
- switch s.Node.Protocol {
- case "ss": // shadowsocks
- server := NewShadowServer(ss.NewConn(conn, s.cipher.Copy()), s)
- server.OTA = s.ota
- server.Serve()
- return
- case "http":
- req, err := http.ReadRequest(bufio.NewReader(conn))
- if err != nil {
- glog.V(LWARNING).Infoln("[http]", err)
- return
- }
- NewHttpServer(conn, s).HandleRequest(req)
- return
- case "socks", "socks5":
- conn = gosocks5.ServerConn(conn, s.selector)
- req, err := gosocks5.ReadRequest(conn)
- if err != nil {
- glog.V(LWARNING).Infoln("[socks5]", err)
- return
- }
- NewSocks5Server(conn, s).HandleRequest(req)
- return
- }
-
- // http or socks5
- b := make([]byte, MediumBufferSize)
-
- n, err := io.ReadAtLeast(conn, b, 2)
- if err != nil {
- glog.V(LWARNING).Infoln(err)
- return
- }
-
- // TODO: use bufio.Reader
- if b[0] == gosocks5.Ver5 {
- mn := int(b[1]) // methods count
- length := 2 + mn
- if n < length {
- if _, err := io.ReadFull(conn, b[n:length]); err != nil {
- glog.V(LWARNING).Infoln("[socks5]", err)
- return
- }
- }
- // TODO: use gosocks5.ServerConn
- methods := b[2 : 2+mn]
- method := s.selector.Select(methods...)
- if _, err := conn.Write([]byte{gosocks5.Ver5, method}); err != nil {
- glog.V(LWARNING).Infoln("[socks5] select:", err)
- return
- }
- c, err := s.selector.OnSelected(method, conn)
- if err != nil {
- glog.V(LWARNING).Infoln("[socks5] onselected:", err)
- return
- }
- conn = c
-
- req, err := gosocks5.ReadRequest(conn)
- if err != nil {
- glog.V(LWARNING).Infoln("[socks5] request:", err)
- return
- }
- NewSocks5Server(conn, s).HandleRequest(req)
- return
- }
-
- req, err := http.ReadRequest(bufio.NewReader(&reqReader{b: b[:n], r: conn}))
- if err != nil {
- glog.V(LWARNING).Infoln("[http]", err)
- return
- }
- NewHttpServer(conn, s).HandleRequest(req)
+// Listener is a proxy server listener, just like a net.Listener.
+type Listener interface {
+ net.Listener
}
-func (_ *ProxyServer) transport(conn1, conn2 net.Conn) (err error) {
- errc := make(chan error, 2)
+type tcpListener struct {
+ net.Listener
+}
+// TCPListener creates a Listener for TCP proxy server.
+func TCPListener(addr string) (Listener, error) {
+ ln, err := net.Listen("tcp", addr)
+ if err != nil {
+ return nil, err
+ }
+ return &tcpListener{Listener: tcpKeepAliveListener{ln.(*net.TCPListener)}}, nil
+}
+
+type tcpKeepAliveListener struct {
+ *net.TCPListener
+}
+
+func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
+ tc, err := ln.AcceptTCP()
+ if err != nil {
+ return
+ }
+ tc.SetKeepAlive(true)
+ tc.SetKeepAlivePeriod(KeepAliveTime)
+ return tc, nil
+}
+
+func transport(rw1, rw2 io.ReadWriter) error {
+ errc := make(chan error, 1)
go func() {
- _, err := io.Copy(conn1, conn2)
+ _, err := io.Copy(rw1, rw2)
errc <- err
}()
go func() {
- _, err := io.Copy(conn2, conn1)
+ _, err := io.Copy(rw2, rw1)
errc <- err
}()
- select {
- case err = <-errc:
- //glog.V(LWARNING).Infoln("transport exit", err)
+ err := <-errc
+ if err != nil && err == io.EOF {
+ err = nil
}
-
- return
-}
-
-type reqReader struct {
- b []byte
- r io.Reader
-}
-
-func (r *reqReader) Read(p []byte) (n int, err error) {
- if len(r.b) == 0 {
- return r.r.Read(p)
- }
- n = copy(p, r.b)
- r.b = r.b[n:]
-
- return
+ return err
}
diff --git a/signal.go b/signal.go
new file mode 100644
index 0000000..f12e902
--- /dev/null
+++ b/signal.go
@@ -0,0 +1,5 @@
+// +build windows
+
+package gost
+
+func kcpSigHandler() {}
diff --git a/signal_unix.go b/signal_unix.go
new file mode 100644
index 0000000..a761318
--- /dev/null
+++ b/signal_unix.go
@@ -0,0 +1,24 @@
+// +build !windows
+
+package gost
+
+import (
+ "os"
+ "os/signal"
+ "syscall"
+
+ "github.com/go-log/log"
+ "gopkg.in/xtaci/kcp-go.v2"
+)
+
+func kcpSigHandler() {
+ ch := make(chan os.Signal, 1)
+ signal.Notify(ch, syscall.SIGUSR1)
+
+ for {
+ switch <-ch {
+ case syscall.SIGUSR1:
+ log.Logf("[kcp] SNMP: %+v", kcp.DefaultSnmp.Copy())
+ }
+ }
+}
diff --git a/socks.go b/socks.go
index 59d801d..858e725 100644
--- a/socks.go
+++ b/socks.go
@@ -3,37 +3,46 @@ package gost
import (
"bytes"
"crypto/tls"
- //"errors"
- "github.com/ginuerzh/gosocks5"
- "github.com/golang/glog"
- //"os/exec"
- //"io"
- //"io/ioutil"
+ "errors"
+ "fmt"
"net"
"net/url"
"strconv"
"time"
+
+ "io"
+
+ "github.com/ginuerzh/gosocks4"
+ "github.com/ginuerzh/gosocks5"
+ "github.com/go-log/log"
)
const (
- MethodTLS uint8 = 0x80 // extended method for tls
- MethodTLSAuth uint8 = 0x82 // extended method for tls+auth
+ // MethodTLS is an extended SOCKS5 method for TLS.
+ MethodTLS uint8 = 0x80
+ // MethodTLSAuth is an extended SOCKS5 method for TLS+AUTH.
+ MethodTLSAuth uint8 = 0x82
)
const (
- CmdUdpTun uint8 = 0xF3 // extended method for udp over tcp
+ // CmdUDPTun is an extended SOCKS5 method for UDP over TCP.
+ CmdUDPTun uint8 = 0xF3
)
type clientSelector struct {
methods []uint8
- user *url.Userinfo
- tlsConfig *tls.Config
+ User *url.Userinfo
+ TLSConfig *tls.Config
}
func (selector *clientSelector) Methods() []uint8 {
return selector.methods
}
+func (selector *clientSelector) AddMethod(methods ...uint8) {
+ selector.methods = append(selector.methods, methods...)
+}
+
func (selector *clientSelector) Select(methods ...uint8) (method uint8) {
return
}
@@ -41,33 +50,35 @@ func (selector *clientSelector) Select(methods ...uint8) (method uint8) {
func (selector *clientSelector) OnSelected(method uint8, conn net.Conn) (net.Conn, error) {
switch method {
case MethodTLS:
- conn = tls.Client(conn, selector.tlsConfig)
+ conn = tls.Client(conn, selector.TLSConfig)
case gosocks5.MethodUserPass, MethodTLSAuth:
if method == MethodTLSAuth {
- conn = tls.Client(conn, selector.tlsConfig)
+ conn = tls.Client(conn, selector.TLSConfig)
}
var username, password string
- if selector.user != nil {
- username = selector.user.Username()
- password, _ = selector.user.Password()
+ if selector.User != nil {
+ username = selector.User.Username()
+ password, _ = selector.User.Password()
}
req := gosocks5.NewUserPassRequest(gosocks5.UserPassVer, username, password)
if err := req.Write(conn); err != nil {
- glog.V(LWARNING).Infoln("socks5 auth:", err)
+ log.Log("[socks5]", err)
return nil, err
}
- glog.V(LDEBUG).Infoln(req)
-
+ if Debug {
+ log.Log("[socks5]", req)
+ }
resp, err := gosocks5.ReadUserPassResponse(conn)
if err != nil {
- glog.V(LWARNING).Infoln("socks5 auth:", err)
+ log.Log("[socks5]", err)
return nil, err
}
- glog.V(LDEBUG).Infoln(resp)
-
+ if Debug {
+ log.Log("[socks5]", resp)
+ }
if resp.Status != gosocks5.Succeeded {
return nil, gosocks5.ErrAuthFailure
}
@@ -80,17 +91,22 @@ func (selector *clientSelector) OnSelected(method uint8, conn net.Conn) (net.Con
type serverSelector struct {
methods []uint8
- users []*url.Userinfo
- tlsConfig *tls.Config
+ Users []*url.Userinfo
+ TLSConfig *tls.Config
}
func (selector *serverSelector) Methods() []uint8 {
return selector.methods
}
-func (selector *serverSelector) Select(methods ...uint8) (method uint8) {
- glog.V(LDEBUG).Infof("%d %d %v", gosocks5.Ver5, len(methods), methods)
+func (selector *serverSelector) AddMethod(methods ...uint8) {
+ selector.methods = append(selector.methods, methods...)
+}
+func (selector *serverSelector) Select(methods ...uint8) (method uint8) {
+ if Debug {
+ log.Logf("[socks5] %d %d %v", gosocks5.Ver5, len(methods), methods)
+ }
method = gosocks5.MethodNoAuth
for _, m := range methods {
if m == MethodTLS {
@@ -100,7 +116,7 @@ func (selector *serverSelector) Select(methods ...uint8) (method uint8) {
}
// when user/pass is set, auth is mandatory
- if selector.users != nil {
+ if len(selector.Users) > 0 {
if method == gosocks5.MethodNoAuth {
method = gosocks5.MethodUserPass
}
@@ -113,26 +129,28 @@ func (selector *serverSelector) Select(methods ...uint8) (method uint8) {
}
func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Conn, error) {
- glog.V(LDEBUG).Infof("%d %d", gosocks5.Ver5, method)
-
+ if Debug {
+ log.Logf("[socks5] %d %d", gosocks5.Ver5, method)
+ }
switch method {
case MethodTLS:
- conn = tls.Server(conn, selector.tlsConfig)
+ conn = tls.Server(conn, selector.TLSConfig)
case gosocks5.MethodUserPass, MethodTLSAuth:
if method == MethodTLSAuth {
- conn = tls.Server(conn, selector.tlsConfig)
+ conn = tls.Server(conn, selector.TLSConfig)
}
req, err := gosocks5.ReadUserPassRequest(conn)
if err != nil {
- glog.V(LWARNING).Infoln("[socks5-auth]", err)
+ log.Log("[socks5]", err)
return nil, err
}
- glog.V(LDEBUG).Infoln("[socks5]", req.String())
-
+ if Debug {
+ log.Log("[socks5]", req.String())
+ }
valid := false
- for _, user := range selector.users {
+ for _, user := range selector.Users {
username := user.Username()
password, _ := user.Password()
if (req.Username == username && req.Password == password) ||
@@ -142,25 +160,27 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con
break
}
}
- if len(selector.users) > 0 && !valid {
+ if len(selector.Users) > 0 && !valid {
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Failure)
if err := resp.Write(conn); err != nil {
- glog.V(LWARNING).Infoln("[socks5-auth]", err)
+ log.Log("[socks5]", err)
return nil, err
}
- glog.V(LDEBUG).Infoln("[socks5]", resp)
- glog.V(LWARNING).Infoln("[socks5-auth] proxy authentication required")
-
+ if Debug {
+ log.Log("[socks5]", resp)
+ }
+ log.Log("[socks5] proxy authentication required")
return nil, gosocks5.ErrAuthFailure
}
resp := gosocks5.NewUserPassResponse(gosocks5.UserPassVer, gosocks5.Succeeded)
if err := resp.Write(conn); err != nil {
- glog.V(LWARNING).Infoln("[socks5-auth]", err)
+ log.Log("[socks5]", err)
return nil, err
}
- glog.V(LDEBUG).Infoln(resp)
-
+ if Debug {
+ log.Log("[socks5]", resp)
+ }
case gosocks5.MethodNoAcceptable:
return nil, gosocks5.ErrBadMethod
}
@@ -168,241 +188,306 @@ func (selector *serverSelector) OnSelected(method uint8, conn net.Conn) (net.Con
return conn, nil
}
-type Socks5Server struct {
- conn net.Conn
- Base *ProxyServer
+type socks5Connector struct {
+ User *url.Userinfo
}
-func NewSocks5Server(conn net.Conn, base *ProxyServer) *Socks5Server {
- return &Socks5Server{conn: conn, Base: base}
+// SOCKS5Connector creates a connector for SOCKS5 proxy client.
+// It accepts an optional auth info for SOCKS5 Username/Password Authentication.
+func SOCKS5Connector(user *url.Userinfo) Connector {
+ return &socks5Connector{User: user}
}
-func (s *Socks5Server) HandleRequest(req *gosocks5.Request) {
- glog.V(LDEBUG).Infof("[socks5] %s -> %s\n%s", s.conn.RemoteAddr(), req.Addr, req)
+func (c *socks5Connector) Connect(conn net.Conn, addr string) (net.Conn, error) {
+ selector := &clientSelector{
+ TLSConfig: &tls.Config{InsecureSkipVerify: true},
+ User: c.User,
+ }
+ selector.AddMethod(
+ gosocks5.MethodNoAuth,
+ gosocks5.MethodUserPass,
+ MethodTLS,
+ )
- switch req.Cmd {
- case gosocks5.CmdConnect:
- glog.V(LINFO).Infof("[socks5-connect] %s -> %s", s.conn.RemoteAddr(), req.Addr)
- s.handleConnect(req)
+ cc := gosocks5.ClientConn(conn, selector)
+ if err := cc.Handleshake(); err != nil {
+ return nil, err
+ }
+ conn = cc
- case gosocks5.CmdBind:
- glog.V(LINFO).Infof("[socks5-bind] %s - %s", s.conn.RemoteAddr(), req.Addr)
- s.handleBind(req)
+ host, port, err := net.SplitHostPort(addr)
+ if err != nil {
+ return nil, err
+ }
+ p, _ := strconv.Atoi(port)
+ req := gosocks5.NewRequest(gosocks5.CmdConnect, &gosocks5.Addr{
+ Type: gosocks5.AddrDomain,
+ Host: host,
+ Port: uint16(p),
+ })
+ if err := req.Write(conn); err != nil {
+ return nil, err
+ }
- case gosocks5.CmdUdp:
- glog.V(LINFO).Infof("[socks5-udp] %s - %s", s.conn.RemoteAddr(), req.Addr)
- s.handleUDPRelay(req)
+ if Debug {
+ log.Log("[socks5]", req)
+ }
- case CmdUdpTun:
- glog.V(LINFO).Infof("[socks5-udp] %s - %s", s.conn.RemoteAddr(), req.Addr)
- s.handleUDPTunnel(req)
+ reply, err := gosocks5.ReadReply(conn)
+ if err != nil {
+ return nil, err
+ }
- default:
- glog.V(LWARNING).Infoln("[socks5] Unrecognized request:", req.Cmd)
+ if Debug {
+ log.Log("[socks5]", reply)
+ }
+
+ if reply.Rep != gosocks5.Succeeded {
+ return nil, errors.New("Service unavailable")
+ }
+
+ return conn, nil
+}
+
+type socks4Connector struct{}
+
+// SOCKS4Connector creates a Connector for SOCKS4 proxy client.
+func SOCKS4Connector() Connector {
+ return &socks4Connector{}
+}
+
+func (c *socks4Connector) Connect(conn net.Conn, addr string) (net.Conn, error) {
+ taddr, err := net.ResolveTCPAddr("tcp4", addr)
+ if err != nil {
+ return nil, err
+ }
+
+ req := gosocks4.NewRequest(gosocks4.CmdConnect,
+ &gosocks4.Addr{
+ Type: gosocks4.AddrIPv4,
+ Host: taddr.IP.String(),
+ Port: uint16(taddr.Port),
+ }, nil,
+ )
+ if err := req.Write(conn); err != nil {
+ return nil, err
+ }
+
+ if Debug {
+ log.Logf("[socks4] %s", req)
+ }
+
+ reply, err := gosocks4.ReadReply(conn)
+ if err != nil {
+ return nil, err
+ }
+
+ if Debug {
+ log.Logf("[socks4] %s", reply)
+ }
+
+ if reply.Code != gosocks4.Granted {
+ return nil, fmt.Errorf("[socks4] %d", reply.Code)
+ }
+
+ return conn, nil
+}
+
+type socks4aConnector struct{}
+
+// SOCKS4AConnector creates a Connector for SOCKS4A proxy client.
+func SOCKS4AConnector() Connector {
+ return &socks4aConnector{}
+}
+
+func (c *socks4aConnector) Connect(conn net.Conn, addr string) (net.Conn, error) {
+ host, port, err := net.SplitHostPort(addr)
+ if err != nil {
+ return nil, err
+ }
+ p, _ := strconv.Atoi(port)
+
+ req := gosocks4.NewRequest(gosocks4.CmdConnect,
+ &gosocks4.Addr{Type: gosocks4.AddrDomain, Host: host, Port: uint16(p)}, nil)
+ if err := req.Write(conn); err != nil {
+ return nil, err
+ }
+
+ if Debug {
+ log.Logf("[socks4] %s", req)
+ }
+
+ reply, err := gosocks4.ReadReply(conn)
+ if err != nil {
+ return nil, err
+ }
+
+ if Debug {
+ log.Logf("[socks4] %s", reply)
+ }
+
+ if reply.Code != gosocks4.Granted {
+ return nil, fmt.Errorf("[socks4] %d", reply.Code)
+ }
+
+ return conn, nil
+}
+
+type socks5Handler struct {
+ selector *serverSelector
+ options *HandlerOptions
+}
+
+// SOCKS5Handler creates a server Handler for SOCKS5 proxy server.
+func SOCKS5Handler(opts ...HandlerOption) Handler {
+ options := &HandlerOptions{}
+ for _, opt := range opts {
+ opt(options)
+ }
+
+ tlsConfig := options.TLSConfig
+ if tlsConfig == nil {
+ tlsConfig = DefaultTLSConfig
+ }
+ selector := &serverSelector{ // socks5 server selector
+ Users: options.Users,
+ TLSConfig: tlsConfig,
+ }
+ // methods that socks5 server supported
+ selector.AddMethod(
+ gosocks5.MethodNoAuth,
+ gosocks5.MethodUserPass,
+ MethodTLS,
+ MethodTLSAuth,
+ )
+ return &socks5Handler{
+ options: options,
+ selector: selector,
}
}
-func (s *Socks5Server) handleConnect(req *gosocks5.Request) {
- cc, err := s.Base.Chain.Dial(req.Addr.String())
+func (h *socks5Handler) Handle(conn net.Conn) {
+ defer conn.Close()
+
+ conn = gosocks5.ServerConn(conn, h.selector)
+ req, err := gosocks5.ReadRequest(conn)
if err != nil {
- glog.V(LWARNING).Infof("[socks5-connect] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err)
+ log.Log("[socks5]", err)
+ return
+ }
+
+ if Debug {
+ log.Logf("[socks5] %s - %s\n%s", conn.RemoteAddr(), req.Addr, req)
+ }
+ switch req.Cmd {
+ case gosocks5.CmdConnect:
+ h.handleConnect(conn, req)
+
+ case gosocks5.CmdBind:
+ h.handleBind(conn, req)
+
+ case gosocks5.CmdUdp:
+ h.handleUDPRelay(conn, req)
+
+ case CmdUDPTun:
+ h.handleUDPTunnel(conn, req)
+
+ default:
+ log.Log("[socks5] Unrecognized request:", req.Cmd)
+ }
+}
+
+func (h *socks5Handler) handleConnect(conn net.Conn, req *gosocks5.Request) {
+ addr := req.Addr.String()
+ if !Can("tcp", addr, h.options.Whitelist, h.options.Blacklist) {
+ log.Logf("[socks5-connect] Unauthorized to tcp connect to %s", addr)
+ rep := gosocks5.NewReply(gosocks5.NotAllowed, nil)
+ rep.Write(conn)
+ if Debug {
+ log.Logf("[socks5-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
+ }
+ return
+ }
+
+ cc, err := h.options.Chain.Dial(addr)
+ if err != nil {
+ log.Logf("[socks5-connect] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
rep := gosocks5.NewReply(gosocks5.HostUnreachable, nil)
- rep.Write(s.conn)
- glog.V(LDEBUG).Infof("[socks5-connect] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, rep)
+ rep.Write(conn)
+ if Debug {
+ log.Logf("[socks5-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
+ }
return
}
defer cc.Close()
rep := gosocks5.NewReply(gosocks5.Succeeded, nil)
- if err := rep.Write(s.conn); err != nil {
- glog.V(LWARNING).Infof("[socks5-connect] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err)
+ if err := rep.Write(conn); err != nil {
+ log.Logf("[socks5-connect] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
return
}
- glog.V(LDEBUG).Infof("[socks5-connect] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, rep)
-
- glog.V(LINFO).Infof("[socks5-connect] %s <-> %s", s.conn.RemoteAddr(), req.Addr)
- //Transport(conn, cc)
- s.Base.transport(s.conn, cc)
- glog.V(LINFO).Infof("[socks5-connect] %s >-< %s", s.conn.RemoteAddr(), req.Addr)
+ if Debug {
+ log.Logf("[socks5-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
+ }
+ log.Logf("[socks5-connect] %s <-> %s", conn.RemoteAddr(), req.Addr)
+ transport(conn, cc)
+ log.Logf("[socks5-connect] %s >-< %s", conn.RemoteAddr(), req.Addr)
}
-func (s *Socks5Server) handleBind(req *gosocks5.Request) {
- cc, err := s.Base.Chain.GetConn()
-
- // connection error
- if err != nil && err != ErrEmptyChain {
- glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err)
- reply := gosocks5.NewReply(gosocks5.Failure, nil)
- reply.Write(s.conn)
- glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, reply)
- return
- }
- // serve socks5 bind
- if err == ErrEmptyChain {
- s.bindOn(req.Addr.String())
+func (h *socks5Handler) handleBind(conn net.Conn, req *gosocks5.Request) {
+ if h.options.Chain.IsEmpty() {
+ addr := req.Addr.String()
+ if !Can("rtcp", addr, h.options.Whitelist, h.options.Blacklist) {
+ log.Logf("Unauthorized to tcp bind to %s", addr)
+ return
+ }
+ h.bindOn(conn, addr)
return
}
- defer cc.Close()
- // forward request
- req.Write(cc)
-
- glog.V(LINFO).Infof("[socks5-bind] %s <-> %s", s.conn.RemoteAddr(), cc.RemoteAddr())
- s.Base.transport(s.conn, cc)
- glog.V(LINFO).Infof("[socks5-bind] %s >-< %s", s.conn.RemoteAddr(), cc.RemoteAddr())
-}
-
-func (s *Socks5Server) handleUDPRelay(req *gosocks5.Request) {
- bindAddr, _ := net.ResolveUDPAddr("udp", req.Addr.String())
- relay, err := net.ListenUDP("udp", bindAddr) // udp associate, strict mode: if the port already in use, it will return error
+ cc, err := h.options.Chain.Conn()
if err != nil {
- glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err)
+ log.Logf("[socks5-bind] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
reply := gosocks5.NewReply(gosocks5.Failure, nil)
- reply.Write(s.conn)
- glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), req.Addr, reply)
- return
- }
- defer relay.Close()
-
- socksAddr := ToSocksAddr(relay.LocalAddr())
- socksAddr.Host, _, _ = net.SplitHostPort(s.conn.LocalAddr().String())
- reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr)
- if err := reply.Write(s.conn); err != nil {
- glog.V(LWARNING).Infof("[socks5-udp] %s <- %s : %s", s.conn.RemoteAddr(), req.Addr, err)
- return
- }
- glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), reply.Addr, reply)
- glog.V(LINFO).Infof("[socks5-udp] %s - %s BIND ON %s OK", s.conn.RemoteAddr(), req.Addr, socksAddr)
-
- cc, err := s.Base.Chain.GetConn()
- // connection error
- if err != nil && err != ErrEmptyChain {
- glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), socksAddr, err)
- return
- }
-
- // serve as standard socks5 udp relay local <-> remote
- if err == ErrEmptyChain {
- peer, er := net.ListenUDP("udp", nil)
- if er != nil {
- glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), socksAddr, er)
- return
- }
- defer peer.Close()
-
- go s.transportUDP(relay, peer)
- }
-
- // forward udp local <-> tunnel
- if err == nil {
- defer cc.Close()
-
- cc.SetWriteDeadline(time.Now().Add(WriteTimeout))
- req := gosocks5.NewRequest(CmdUdpTun, nil)
- if err := req.Write(cc); err != nil {
- glog.V(LWARNING).Infoln("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), cc.RemoteAddr(), err)
- return
- }
- cc.SetWriteDeadline(time.Time{})
- glog.V(LDEBUG).Infof("[socks5-udp] %s -> %s\n%s", s.conn.RemoteAddr(), cc.RemoteAddr(), req)
-
- cc.SetReadDeadline(time.Now().Add(ReadTimeout))
- reply, err = gosocks5.ReadReply(cc)
- if err != nil {
- glog.V(LWARNING).Infoln("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), cc.RemoteAddr(), err)
- return
- }
- glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), cc.RemoteAddr(), reply)
-
- if reply.Rep != gosocks5.Succeeded {
- glog.V(LWARNING).Infoln("[socks5-udp] %s <- %s : udp associate failed", s.conn.RemoteAddr(), cc.RemoteAddr())
- return
- }
- cc.SetReadDeadline(time.Time{})
- glog.V(LINFO).Infof("[socks5-udp] %s <-> %s [tun: %s]", s.conn.RemoteAddr(), socksAddr, reply.Addr)
-
- go s.tunnelClientUDP(relay, cc)
- }
-
- glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr)
- b := make([]byte, SmallBufferSize)
- for {
- _, err := s.conn.Read(b) // discard any data from tcp connection
- if err != nil {
- glog.V(LWARNING).Infof("[socks5-udp] %s - %s : %s", s.conn.RemoteAddr(), socksAddr, err)
- break // client disconnected
- }
- }
- glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), socksAddr)
-}
-
-func (s *Socks5Server) handleUDPTunnel(req *gosocks5.Request) {
- cc, err := s.Base.Chain.GetConn()
-
- // connection error
- if err != nil && err != ErrEmptyChain {
- glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err)
- reply := gosocks5.NewReply(gosocks5.Failure, nil)
- reply.Write(s.conn)
- glog.V(LDEBUG).Infof("[socks5-udp] %s -> %s\n%s", s.conn.RemoteAddr(), req.Addr, reply)
- return
- }
-
- // serve tunnel udp, tunnel <-> remote, handle tunnel udp request
- if err == ErrEmptyChain {
- bindAddr, _ := net.ResolveUDPAddr("udp", req.Addr.String())
- uc, err := net.ListenUDP("udp", bindAddr)
- if err != nil {
- glog.V(LWARNING).Infof("[socks5-udp] %s -> %s : %s", s.conn.RemoteAddr(), req.Addr, err)
- return
- }
- defer uc.Close()
-
- socksAddr := ToSocksAddr(uc.LocalAddr())
- socksAddr.Host, _, _ = net.SplitHostPort(s.conn.LocalAddr().String())
- reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr)
- if err := reply.Write(s.conn); err != nil {
- glog.V(LWARNING).Infof("[socks5-udp] %s <- %s : %s", s.conn.RemoteAddr(), socksAddr, err)
- return
- }
- glog.V(LDEBUG).Infof("[socks5-udp] %s <- %s\n%s", s.conn.RemoteAddr(), socksAddr, reply)
-
- glog.V(LINFO).Infof("[socks5-udp] %s <-> %s", s.conn.RemoteAddr(), socksAddr)
- s.tunnelServerUDP(s.conn, uc)
- glog.V(LINFO).Infof("[socks5-udp] %s >-< %s", s.conn.RemoteAddr(), socksAddr)
+ reply.Write(conn)
+ if Debug {
+ log.Logf("[socks5-bind] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, reply)
+ }
return
}
+ // forward request
+ // note: this type of request forwarding is defined when starting server,
+ // so we don't need to authenticate it, as it's as explicit as whitelisting
defer cc.Close()
-
- // tunnel <-> tunnel, direct forwarding
req.Write(cc)
-
- glog.V(LINFO).Infof("[socks5-udp] %s <-> %s [tun]", s.conn.RemoteAddr(), cc.RemoteAddr())
- s.Base.transport(s.conn, cc)
- glog.V(LINFO).Infof("[socks5-udp] %s >-< %s [tun]", s.conn.RemoteAddr(), cc.RemoteAddr())
+ log.Logf("[socks5-bind] %s <-> %s", conn.RemoteAddr(), cc.RemoteAddr())
+ transport(conn, cc)
+ log.Logf("[socks5-bind] %s >-< %s", conn.RemoteAddr(), cc.RemoteAddr())
}
-func (s *Socks5Server) bindOn(addr string) {
+func (h *socks5Handler) bindOn(conn net.Conn, addr string) {
bindAddr, _ := net.ResolveTCPAddr("tcp", addr)
ln, err := net.ListenTCP("tcp", bindAddr) // strict mode: if the port already in use, it will return error
if err != nil {
- glog.V(LWARNING).Infof("[socks5-bind] %s -> %s : %s", s.conn.RemoteAddr(), addr, err)
- gosocks5.NewReply(gosocks5.Failure, nil).Write(s.conn)
+ log.Logf("[socks5-bind] %s -> %s : %s", conn.RemoteAddr(), addr, err)
+ gosocks5.NewReply(gosocks5.Failure, nil).Write(conn)
return
}
- socksAddr := ToSocksAddr(ln.Addr())
+ socksAddr := toSocksAddr(ln.Addr())
// Issue: may not reachable when host has multi-interface
- socksAddr.Host, _, _ = net.SplitHostPort(s.conn.LocalAddr().String())
+ socksAddr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr)
- if err := reply.Write(s.conn); err != nil {
- glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), addr, err)
+ if err := reply.Write(conn); err != nil {
+ log.Logf("[socks5-bind] %s <- %s : %s", conn.RemoteAddr(), addr, err)
ln.Close()
return
}
- glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", s.conn.RemoteAddr(), addr, reply)
- glog.V(LINFO).Infof("[socks5-bind] %s - %s BIND ON %s OK", s.conn.RemoteAddr(), addr, socksAddr)
+ if Debug {
+ log.Logf("[socks5-bind] %s <- %s\n%s", conn.RemoteAddr(), addr, reply)
+ }
+ log.Logf("[socks5-bind] %s - %s BIND ON %s OK", conn.RemoteAddr(), addr, socksAddr)
var pconn net.Conn
accept := func() <-chan error {
@@ -431,7 +516,7 @@ func (s *Socks5Server) bindOn(addr string) {
defer close(errc)
defer pc1.Close()
- errc <- s.Base.transport(s.conn, pc1)
+ errc <- transport(conn, pc1)
}()
return errc
@@ -443,39 +528,163 @@ func (s *Socks5Server) bindOn(addr string) {
select {
case err := <-accept():
if err != nil || pconn == nil {
- glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), addr, err)
+ log.Logf("[socks5-bind] %s <- %s : %v", conn.RemoteAddr(), addr, err)
return
}
defer pconn.Close()
- reply := gosocks5.NewReply(gosocks5.Succeeded, ToSocksAddr(pconn.RemoteAddr()))
+ reply := gosocks5.NewReply(gosocks5.Succeeded, toSocksAddr(pconn.RemoteAddr()))
if err := reply.Write(pc2); err != nil {
- glog.V(LWARNING).Infof("[socks5-bind] %s <- %s : %s", s.conn.RemoteAddr(), addr, err)
+ log.Logf("[socks5-bind] %s <- %s : %v", conn.RemoteAddr(), addr, err)
}
- glog.V(LDEBUG).Infof("[socks5-bind] %s <- %s\n%s", s.conn.RemoteAddr(), addr, reply)
- glog.V(LINFO).Infof("[socks5-bind] %s <- %s PEER %s ACCEPTED", s.conn.RemoteAddr(), socksAddr, pconn.RemoteAddr())
+ if Debug {
+ log.Logf("[socks5-bind] %s <- %s\n%s", conn.RemoteAddr(), addr, reply)
+ }
+ log.Logf("[socks5-bind] %s <- %s PEER %s ACCEPTED", conn.RemoteAddr(), socksAddr, pconn.RemoteAddr())
- glog.V(LINFO).Infof("[socks5-bind] %s <-> %s", s.conn.RemoteAddr(), pconn.RemoteAddr())
- if err = s.Base.transport(pc2, pconn); err != nil {
- glog.V(LWARNING).Infoln(err)
+ log.Logf("[socks5-bind] %s <-> %s", conn.RemoteAddr(), pconn.RemoteAddr())
+ if err = transport(pc2, pconn); err != nil {
+ log.Logf("[socks5-bind] %s - %s : %v", conn.RemoteAddr(), pconn.RemoteAddr(), err)
}
- glog.V(LINFO).Infof("[socks5-bind] %s >-< %s", s.conn.RemoteAddr(), pconn.RemoteAddr())
+ log.Logf("[socks5-bind] %s >-< %s", conn.RemoteAddr(), pconn.RemoteAddr())
return
case err := <-pipe():
- glog.V(LWARNING).Infof("[socks5-bind] %s -> %s : %v", s.conn.RemoteAddr(), addr, err)
+ if err != nil {
+ log.Logf("[socks5-bind] %s -> %s : %v", conn.RemoteAddr(), addr, err)
+ }
ln.Close()
return
}
}
}
-func (s *Socks5Server) transportUDP(relay, peer *net.UDPConn) (err error) {
+func (h *socks5Handler) handleUDPRelay(conn net.Conn, req *gosocks5.Request) {
+ addr := req.Addr.String()
+ if !Can("udp", addr, h.options.Whitelist, h.options.Blacklist) {
+ log.Logf("[socks5-udp] Unauthorized to udp connect to %s", addr)
+ rep := gosocks5.NewReply(gosocks5.NotAllowed, nil)
+ rep.Write(conn)
+ if Debug {
+ log.Logf("[socks5-udp] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
+ }
+ return
+ }
+
+ relay, err := net.ListenUDP("udp", nil)
+ if err != nil {
+ log.Logf("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), relay.LocalAddr(), err)
+ reply := gosocks5.NewReply(gosocks5.Failure, nil)
+ reply.Write(conn)
+ if Debug {
+ log.Logf("[socks5-udp] %s <- %s\n%s", conn.RemoteAddr(), relay.LocalAddr(), reply)
+ }
+ return
+ }
+ defer relay.Close()
+
+ socksAddr := toSocksAddr(relay.LocalAddr())
+ socksAddr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String()) // replace the IP to the out-going interface's
+ reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr)
+ if err := reply.Write(conn); err != nil {
+ log.Logf("[socks5-udp] %s <- %s : %s", conn.RemoteAddr(), relay.LocalAddr(), err)
+ return
+ }
+ if Debug {
+ log.Logf("[socks5-udp] %s <- %s\n%s", conn.RemoteAddr(), reply.Addr, reply)
+ }
+ log.Logf("[socks5-udp] %s - %s BIND ON %s OK", conn.RemoteAddr(), relay.LocalAddr(), socksAddr)
+
+ // serve as standard socks5 udp relay local <-> remote
+ if h.options.Chain.IsEmpty() {
+ peer, er := net.ListenUDP("udp", nil)
+ if er != nil {
+ log.Logf("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), socksAddr, er)
+ return
+ }
+ defer peer.Close()
+
+ go h.transportUDP(relay, peer)
+ log.Logf("[socks5-udp] %s <-> %s", conn.RemoteAddr(), socksAddr)
+ if err := h.discardClientData(conn); err != nil {
+ log.Logf("[socks5-udp] %s - %s : %s", conn.RemoteAddr(), socksAddr, err)
+ }
+ log.Logf("[socks5-udp] %s >-< %s", conn.RemoteAddr(), socksAddr)
+ return
+ }
+
+ cc, err := h.options.Chain.Conn()
+ // connection error
+ if err != nil {
+ log.Logf("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), socksAddr, err)
+ return
+ }
+ // forward udp local <-> tunnel
+ defer cc.Close()
+
+ cc, err = socks5Handshake(cc, h.options.Chain.LastNode().User)
+ if err != nil {
+ log.Logf("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), socksAddr, err)
+ return
+ }
+
+ cc.SetWriteDeadline(time.Now().Add(WriteTimeout))
+ r := gosocks5.NewRequest(CmdUDPTun, nil)
+ if err := r.Write(cc); err != nil {
+ log.Logf("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), cc.RemoteAddr(), err)
+ return
+ }
+ cc.SetWriteDeadline(time.Time{})
+ if Debug {
+ log.Logf("[socks5-udp] %s -> %s\n%s", conn.RemoteAddr(), cc.RemoteAddr(), r)
+ }
+ cc.SetReadDeadline(time.Now().Add(ReadTimeout))
+ reply, err = gosocks5.ReadReply(cc)
+ if err != nil {
+ log.Logf("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), cc.RemoteAddr(), err)
+ return
+ }
+ if Debug {
+ log.Logf("[socks5-udp] %s <- %s\n%s", conn.RemoteAddr(), cc.RemoteAddr(), reply)
+ }
+
+ if reply.Rep != gosocks5.Succeeded {
+ log.Logf("[socks5-udp] %s <- %s : udp associate failed", conn.RemoteAddr(), cc.RemoteAddr())
+ return
+ }
+ cc.SetReadDeadline(time.Time{})
+ log.Logf("[socks5-udp] %s <-> %s [tun: %s]", conn.RemoteAddr(), socksAddr, reply.Addr)
+
+ go h.tunnelClientUDP(relay, cc)
+ log.Logf("[socks5-udp] %s <-> %s", conn.RemoteAddr(), socksAddr)
+ if err := h.discardClientData(conn); err != nil {
+ log.Logf("[socks5-udp] %s - %s : %s", conn.RemoteAddr(), socksAddr, err)
+ }
+ log.Logf("[socks5-udp] %s >-< %s", conn.RemoteAddr(), socksAddr)
+}
+
+func (h *socks5Handler) discardClientData(conn net.Conn) (err error) {
+ b := make([]byte, tinyBufferSize)
+ n := 0
+ for {
+ n, err = conn.Read(b) // discard any data from tcp connection
+ if err != nil {
+ if err == io.EOF { // disconnect normally
+ err = nil
+ }
+ break // client disconnected
+ }
+ log.Logf("[socks5-udp] read %d UNEXPECTED TCP data from client", n)
+ }
+ return
+}
+
+func (h *socks5Handler) transportUDP(relay, peer *net.UDPConn) (err error) {
errc := make(chan error, 2)
var clientAddr *net.UDPAddr
go func() {
- b := make([]byte, LargeBufferSize)
+ b := make([]byte, largeBufferSize)
for {
n, laddr, err := relay.ReadFromUDP(b)
@@ -500,12 +709,14 @@ func (s *Socks5Server) transportUDP(relay, peer *net.UDPConn) (err error) {
errc <- err
return
}
- glog.V(LDEBUG).Infof("[socks5-udp] %s >>> %s length: %d", relay.LocalAddr(), raddr, len(dgram.Data))
+ if Debug {
+ log.Logf("[socks5-udp] %s >>> %s length: %d", relay.LocalAddr(), raddr, len(dgram.Data))
+ }
}
}()
go func() {
- b := make([]byte, LargeBufferSize)
+ b := make([]byte, largeBufferSize)
for {
n, raddr, err := peer.ReadFromUDP(b)
@@ -517,13 +728,15 @@ func (s *Socks5Server) transportUDP(relay, peer *net.UDPConn) (err error) {
continue
}
buf := bytes.Buffer{}
- dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(0, 0, ToSocksAddr(raddr)), b[:n])
+ dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(0, 0, toSocksAddr(raddr)), b[:n])
dgram.Write(&buf)
if _, err := relay.WriteToUDP(buf.Bytes(), clientAddr); err != nil {
errc <- err
return
}
- glog.V(LDEBUG).Infof("[socks5-udp] %s <<< %s length: %d", relay.LocalAddr(), raddr, len(dgram.Data))
+ if Debug {
+ log.Logf("[socks5-udp] %s <<< %s length: %d", relay.LocalAddr(), raddr, len(dgram.Data))
+ }
}
}()
@@ -535,18 +748,18 @@ func (s *Socks5Server) transportUDP(relay, peer *net.UDPConn) (err error) {
return
}
-func (s *Socks5Server) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error) {
+func (h *socks5Handler) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error) {
errc := make(chan error, 2)
var clientAddr *net.UDPAddr
go func() {
- b := make([]byte, LargeBufferSize)
+ b := make([]byte, mediumBufferSize)
for {
n, addr, err := uc.ReadFromUDP(b)
if err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), addr, err)
+ log.Logf("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), addr, err)
errc <- err
return
}
@@ -566,7 +779,9 @@ func (s *Socks5Server) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error)
errc <- err
return
}
- glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data))
+ if Debug {
+ log.Logf("[udp-tun] %s >>> %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data))
+ }
}
}()
@@ -574,7 +789,7 @@ func (s *Socks5Server) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error)
for {
dgram, err := gosocks5.ReadUDPDatagram(cc)
if err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s -> 0 : %s", cc.RemoteAddr(), err)
+ log.Logf("[udp-tun] %s -> 0 : %s", cc.RemoteAddr(), err)
errc <- err
return
}
@@ -591,7 +806,9 @@ func (s *Socks5Server) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error)
errc <- err
return
}
- glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data))
+ if Debug {
+ log.Logf("[udp-tun] %s <<< %s length: %d", uc.LocalAddr(), dgram.Header.Addr, len(dgram.Data))
+ }
}
}()
@@ -602,29 +819,91 @@ func (s *Socks5Server) tunnelClientUDP(uc *net.UDPConn, cc net.Conn) (err error)
return
}
-func (s *Socks5Server) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error) {
+func (h *socks5Handler) handleUDPTunnel(conn net.Conn, req *gosocks5.Request) {
+ // serve tunnel udp, tunnel <-> remote, handle tunnel udp request
+ if h.options.Chain.IsEmpty() {
+ addr := req.Addr.String()
+
+ if !Can("rudp", addr, h.options.Whitelist, h.options.Blacklist) {
+ log.Logf("[socks5-udp] Unauthorized to udp bind to %s", addr)
+ return
+ }
+
+ bindAddr, _ := net.ResolveUDPAddr("udp", addr)
+ uc, err := net.ListenUDP("udp", bindAddr)
+ if err != nil {
+ log.Logf("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
+ return
+ }
+ defer uc.Close()
+
+ socksAddr := toSocksAddr(uc.LocalAddr())
+ socksAddr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
+ reply := gosocks5.NewReply(gosocks5.Succeeded, socksAddr)
+ if err := reply.Write(conn); err != nil {
+ log.Logf("[socks5-udp] %s <- %s : %s", conn.RemoteAddr(), socksAddr, err)
+ return
+ }
+ if Debug {
+ log.Logf("[socks5-udp] %s <- %s\n%s", conn.RemoteAddr(), socksAddr, reply)
+ }
+ log.Logf("[socks5-udp] %s <-> %s", conn.RemoteAddr(), socksAddr)
+ h.tunnelServerUDP(conn, uc)
+ log.Logf("[socks5-udp] %s >-< %s", conn.RemoteAddr(), socksAddr)
+ return
+ }
+
+ cc, err := h.options.Chain.Conn()
+ // connection error
+ if err != nil {
+ log.Logf("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
+ reply := gosocks5.NewReply(gosocks5.Failure, nil)
+ reply.Write(conn)
+ log.Logf("[socks5-udp] %s -> %s\n%s", conn.RemoteAddr(), req.Addr, reply)
+ return
+ }
+ defer cc.Close()
+
+ cc, err = socks5Handshake(cc, h.options.Chain.LastNode().User)
+ if err != nil {
+ log.Logf("[socks5-udp] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
+ return
+ }
+ // tunnel <-> tunnel, direct forwarding
+ // note: this type of request forwarding is defined when starting server
+ // so we don't need to authenticate it, as it's as explicit as whitelisting
+ req.Write(cc)
+
+ log.Logf("[socks5-udp] %s <-> %s [tun]", conn.RemoteAddr(), cc.RemoteAddr())
+ transport(conn, cc)
+ log.Logf("[socks5-udp] %s >-< %s [tun]", conn.RemoteAddr(), cc.RemoteAddr())
+}
+
+func (h *socks5Handler) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error) {
errc := make(chan error, 2)
go func() {
- b := make([]byte, LargeBufferSize)
+ b := make([]byte, mediumBufferSize)
for {
n, addr, err := uc.ReadFromUDP(b)
if err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), addr, err)
+ log.Logf("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), addr, err)
errc <- err
return
}
// pipe from peer to tunnel
dgram := gosocks5.NewUDPDatagram(
- gosocks5.NewUDPHeader(uint16(n), 0, ToSocksAddr(addr)), b[:n])
+ gosocks5.NewUDPHeader(uint16(n), 0, toSocksAddr(addr)), b[:n])
if err := dgram.Write(cc); err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), dgram.Header.Addr, err)
+ log.Logf("[udp-tun] %s <- %s : %s", cc.RemoteAddr(), dgram.Header.Addr, err)
errc <- err
return
}
- glog.V(LDEBUG).Infof("[udp-tun] %s <<< %s length: %d", cc.RemoteAddr(), dgram.Header.Addr, len(dgram.Data))
+ if Debug {
+ log.Logf("[udp-tun] %s <<< %s length: %d", cc.RemoteAddr(), dgram.Header.Addr, len(dgram.Data))
+ }
}
}()
@@ -632,7 +911,7 @@ func (s *Socks5Server) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error)
for {
dgram, err := gosocks5.ReadUDPDatagram(cc)
if err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s -> 0 : %s", cc.RemoteAddr(), err)
+ log.Logf("[udp-tun] %s -> 0 : %s", cc.RemoteAddr(), err)
errc <- err
return
}
@@ -643,11 +922,13 @@ func (s *Socks5Server) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error)
continue // drop silently
}
if _, err := uc.WriteToUDP(dgram.Data, addr); err != nil {
- glog.V(LWARNING).Infof("[udp-tun] %s -> %s : %s", cc.RemoteAddr(), addr, err)
+ log.Logf("[udp-tun] %s -> %s : %s", cc.RemoteAddr(), addr, err)
errc <- err
return
}
- glog.V(LDEBUG).Infof("[udp-tun] %s >>> %s length: %d", cc.RemoteAddr(), addr, len(dgram.Data))
+ if Debug {
+ log.Logf("[udp-tun] %s >>> %s length: %d", cc.RemoteAddr(), addr, len(dgram.Data))
+ }
}
}()
@@ -658,7 +939,7 @@ func (s *Socks5Server) tunnelServerUDP(cc net.Conn, uc *net.UDPConn) (err error)
return
}
-func ToSocksAddr(addr net.Addr) *gosocks5.Addr {
+func toSocksAddr(addr net.Addr) *gosocks5.Addr {
host := "0.0.0.0"
port := 0
if addr != nil {
@@ -672,3 +953,218 @@ func ToSocksAddr(addr net.Addr) *gosocks5.Addr {
Port: uint16(port),
}
}
+
+type socks4Handler struct {
+ options *HandlerOptions
+}
+
+// SOCKS4Handler creates a server Handler for SOCKS4(A) proxy server.
+func SOCKS4Handler(opts ...HandlerOption) Handler {
+ options := &HandlerOptions{}
+ for _, opt := range opts {
+ opt(options)
+ }
+ return &socks4Handler{
+ options: options,
+ }
+}
+
+func (h *socks4Handler) Handle(conn net.Conn) {
+ defer conn.Close()
+
+ req, err := gosocks4.ReadRequest(conn)
+ if err != nil {
+ log.Log("[socks4]", err)
+ return
+ }
+
+ if Debug {
+ log.Logf("[socks4] %s -> %s\n%s", conn.RemoteAddr(), req.Addr, req)
+ }
+
+ switch req.Cmd {
+ case gosocks4.CmdConnect:
+ log.Logf("[socks4-connect] %s -> %s", conn.RemoteAddr(), req.Addr)
+ h.handleConnect(conn, req)
+
+ case gosocks4.CmdBind:
+ log.Logf("[socks4-bind] %s - %s", conn.RemoteAddr(), req.Addr)
+ h.handleBind(conn, req)
+
+ default:
+ log.Logf("[socks4] Unrecognized request: %d", req.Cmd)
+ }
+}
+
+func (h *socks4Handler) handleConnect(conn net.Conn, req *gosocks4.Request) {
+ addr := req.Addr.String()
+
+ if !Can("tcp", addr, h.options.Whitelist, h.options.Blacklist) {
+ log.Logf("[socks4-connect] Unauthorized to tcp connect to %s", addr)
+ rep := gosocks5.NewReply(gosocks4.Rejected, nil)
+ rep.Write(conn)
+ if Debug {
+ log.Logf("[socks4-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
+ }
+ return
+ }
+
+ cc, err := h.options.Chain.Dial(addr)
+ if err != nil {
+ log.Logf("[socks4-connect] %s -> %s : %s", conn.RemoteAddr(), req.Addr, err)
+ rep := gosocks4.NewReply(gosocks4.Failed, nil)
+ rep.Write(conn)
+ if Debug {
+ log.Logf("[socks4-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
+ }
+ return
+ }
+ defer cc.Close()
+
+ rep := gosocks4.NewReply(gosocks4.Granted, nil)
+ if err := rep.Write(conn); err != nil {
+ log.Logf("[socks4-connect] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
+ return
+ }
+ if Debug {
+ log.Logf("[socks4-connect] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, rep)
+ }
+
+ log.Logf("[socks4-connect] %s <-> %s", conn.RemoteAddr(), req.Addr)
+ transport(conn, cc)
+ log.Logf("[socks4-connect] %s >-< %s", conn.RemoteAddr(), req.Addr)
+}
+
+func (h *socks4Handler) handleBind(conn net.Conn, req *gosocks4.Request) {
+ // TODO: serve socks4 bind
+ if h.options.Chain.IsEmpty() {
+ reply := gosocks4.NewReply(gosocks4.Rejected, nil)
+ reply.Write(conn)
+ if Debug {
+ log.Logf("[socks4-bind] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, reply)
+ }
+ return
+ }
+
+ cc, err := h.options.Chain.Conn()
+ // connection error
+ if err != nil && err != ErrEmptyChain {
+ log.Logf("[socks4-bind] %s <- %s : %s", conn.RemoteAddr(), req.Addr, err)
+ reply := gosocks4.NewReply(gosocks4.Failed, nil)
+ reply.Write(conn)
+ if Debug {
+ log.Logf("[socks4-bind] %s <- %s\n%s", conn.RemoteAddr(), req.Addr, reply)
+ }
+ return
+ }
+
+ defer cc.Close()
+ // forward request
+ req.Write(cc)
+
+ log.Logf("[socks4-bind] %s <-> %s", conn.RemoteAddr(), cc.RemoteAddr())
+ transport(conn, cc)
+ log.Logf("[socks4-bind] %s >-< %s", conn.RemoteAddr(), cc.RemoteAddr())
+}
+
+func getSOCKS5UDPTunnel(chain *Chain, addr net.Addr) (net.Conn, error) {
+ conn, err := chain.Conn()
+ if err != nil {
+ return nil, err
+ }
+ cc, err := socks5Handshake(conn, chain.LastNode().User)
+ if err != nil {
+ conn.Close()
+ return nil, err
+ }
+ conn = cc
+
+ conn.SetWriteDeadline(time.Now().Add(WriteTimeout))
+ req := gosocks5.NewRequest(CmdUDPTun, toSocksAddr(addr))
+ if err := req.Write(conn); err != nil {
+ conn.Close()
+ return nil, err
+ }
+ if Debug {
+ log.Log("[socks5]", req)
+ }
+ conn.SetWriteDeadline(time.Time{})
+
+ conn.SetReadDeadline(time.Now().Add(ReadTimeout))
+ reply, err := gosocks5.ReadReply(conn)
+ if err != nil {
+ conn.Close()
+ return nil, err
+ }
+ conn.SetReadDeadline(time.Time{})
+ if Debug {
+ log.Log("[socks5]", reply)
+ }
+
+ if reply.Rep != gosocks5.Succeeded {
+ conn.Close()
+ return nil, errors.New("UDP tunnel failure")
+ }
+ return conn, nil
+}
+
+func socks5Handshake(conn net.Conn, user *url.Userinfo) (net.Conn, error) {
+ selector := &clientSelector{
+ TLSConfig: &tls.Config{InsecureSkipVerify: true},
+ User: user,
+ }
+ selector.AddMethod(
+ gosocks5.MethodNoAuth,
+ gosocks5.MethodUserPass,
+ MethodTLS,
+ )
+ cc := gosocks5.ClientConn(conn, selector)
+ if err := cc.Handleshake(); err != nil {
+ return nil, err
+ }
+ return cc, nil
+}
+
+type udpTunnelConn struct {
+ raddr string
+ net.Conn
+}
+
+func (c *udpTunnelConn) Read(b []byte) (n int, err error) {
+ dgram, err := gosocks5.ReadUDPDatagram(c.Conn)
+ if err != nil {
+ return
+ }
+ n = copy(b, dgram.Data)
+ return
+}
+
+func (c *udpTunnelConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
+ dgram, err := gosocks5.ReadUDPDatagram(c.Conn)
+ if err != nil {
+ return
+ }
+ n = copy(b, dgram.Data)
+ addr, err = net.ResolveUDPAddr("udp", dgram.Header.Addr.String())
+ return
+}
+
+func (c *udpTunnelConn) Write(b []byte) (n int, err error) {
+ addr, err := net.ResolveUDPAddr("udp", c.raddr)
+ if err != nil {
+ return
+ }
+ dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(len(b)), 0, toSocksAddr(addr)), b)
+ if err = dgram.Write(c.Conn); err != nil {
+ return
+ }
+ return len(b), nil
+}
+
+func (c *udpTunnelConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
+ dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(uint16(len(b)), 0, toSocksAddr(addr)), b)
+ if err = dgram.Write(c.Conn); err != nil {
+ return
+ }
+ return len(b), nil
+}
diff --git a/ss.go b/ss.go
index cf5eb47..079015d 100644
--- a/ss.go
+++ b/ss.go
@@ -5,202 +5,21 @@ import (
"encoding/binary"
"errors"
"fmt"
- "github.com/ginuerzh/gosocks5"
- "github.com/golang/glog"
- ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
"io"
"net"
+ "net/url"
"strconv"
"time"
+
+ "github.com/ginuerzh/gosocks5"
+ "github.com/go-log/log"
+ ss "github.com/shadowsocks/shadowsocks-go/shadowsocks"
)
-const (
- idType = 0 // address type index
- idIP0 = 1 // ip addres start index
- idDmLen = 1 // domain address length index
- idDm0 = 2 // domain address start index
-
- typeIPv4 = 1 // type is ipv4 address
- typeDm = 3 // type is domain address
- typeIPv6 = 4 // type is ipv6 address
-
- lenIPv4 = net.IPv4len + 2 // ipv4 + 2port
- lenIPv6 = net.IPv6len + 2 // ipv6 + 2port
- lenDmBase = 2 // 1addrLen + 2port, plus addrLen
- lenHmacSha1 = 10
-)
-
-type ShadowServer struct {
- conn *ss.Conn
- Base *ProxyServer
- OTA bool // one time auth
-}
-
-func NewShadowServer(conn *ss.Conn, base *ProxyServer) *ShadowServer {
- return &ShadowServer{conn: conn, Base: base}
-}
-
-func (s *ShadowServer) Serve() {
- glog.V(LINFO).Infof("[ss] %s - %s", s.conn.RemoteAddr(), s.conn.LocalAddr())
-
- addr, ota, err := s.getRequest()
- if err != nil {
- glog.V(LWARNING).Infof("[ss] %s - %s : %s", s.conn.RemoteAddr(), s.conn.LocalAddr(), err)
- return
- }
- glog.V(LINFO).Infof("[ss] %s -> %s, ota: %v", s.conn.RemoteAddr(), addr, ota)
-
- cc, err := s.Base.Chain.Dial(addr)
- if err != nil {
- glog.V(LWARNING).Infof("[ss] %s -> %s : %s", s.conn.RemoteAddr(), addr, err)
- return
- }
- defer cc.Close()
-
- glog.V(LINFO).Infof("[ss] %s <-> %s", s.conn.RemoteAddr(), addr)
- if ota {
- s.transportOTA(s.conn, cc)
- } else {
- s.Base.transport(&shadowConn{conn: s.conn}, cc)
- }
- glog.V(LINFO).Infof("[ss] %s >-< %s", s.conn.RemoteAddr(), addr)
-}
-
-// This function is copied from shadowsocks library with some modification.
-func (s *ShadowServer) getRequest() (host string, ota bool, err error) {
- // buf size should at least have the same size with the largest possible
- // request size (when addrType is 3, domain name has at most 256 bytes)
- // 1(addrType) + 1(lenByte) + 256(max length address) + 2(port)
- buf := make([]byte, SmallBufferSize)
-
- // read till we get possible domain length field
- s.conn.SetReadDeadline(time.Now().Add(ReadTimeout))
- if _, err = io.ReadFull(s.conn, buf[:idType+1]); err != nil {
- return
- }
-
- var reqStart, reqEnd int
- addrType := buf[idType]
- switch addrType & ss.AddrMask {
- case typeIPv4:
- reqStart, reqEnd = idIP0, idIP0+lenIPv4
- case typeIPv6:
- reqStart, reqEnd = idIP0, idIP0+lenIPv6
- case typeDm:
- if _, err = io.ReadFull(s.conn, buf[idType+1:idDmLen+1]); err != nil {
- return
- }
- reqStart, reqEnd = idDm0, int(idDm0+buf[idDmLen]+lenDmBase)
- default:
- err = fmt.Errorf("addr type %d not supported", addrType&ss.AddrMask)
- return
- }
-
- if _, err = io.ReadFull(s.conn, buf[reqStart:reqEnd]); err != nil {
- return
- }
-
- // Return string for typeIP is not most efficient, but browsers (Chrome,
- // Safari, Firefox) all seems using typeDm exclusively. So this is not a
- // big problem.
- switch addrType & ss.AddrMask {
- case typeIPv4:
- host = net.IP(buf[idIP0 : idIP0+net.IPv4len]).String()
- case typeIPv6:
- host = net.IP(buf[idIP0 : idIP0+net.IPv6len]).String()
- case typeDm:
- host = string(buf[idDm0 : idDm0+buf[idDmLen]])
- }
- // parse port
- port := binary.BigEndian.Uint16(buf[reqEnd-2 : reqEnd])
- host = net.JoinHostPort(host, strconv.Itoa(int(port)))
- // if specified one time auth enabled, we should verify this
- if s.OTA || addrType&ss.OneTimeAuthMask > 0 {
- ota = true
- if _, err = io.ReadFull(s.conn, buf[reqEnd:reqEnd+lenHmacSha1]); err != nil {
- return
- }
- iv := s.conn.GetIv()
- key := s.conn.GetKey()
- actualHmacSha1Buf := ss.HmacSha1(append(iv, key...), buf[:reqEnd])
- if !bytes.Equal(buf[reqEnd:reqEnd+lenHmacSha1], actualHmacSha1Buf) {
- err = fmt.Errorf("verify one time auth failed, iv=%v key=%v data=%v", iv, key, buf[:reqEnd])
- return
- }
- }
- return
-}
-
-const (
- dataLenLen = 2
- hmacSha1Len = 10
- idxData0 = dataLenLen + hmacSha1Len
-)
-
-// copyOta copies data from src to dst with ota verification.
-//
-// This function is copied from shadowsocks library with some modification.
-func (s *ShadowServer) copyOta(dst net.Conn, src *ss.Conn) (int64, error) {
- // sometimes it have to fill large block
- buf := make([]byte, LargeBufferSize)
- for {
- src.SetReadDeadline(time.Now().Add(ReadTimeout))
- if n, err := io.ReadFull(src, buf[:dataLenLen+hmacSha1Len]); err != nil {
- return int64(n), err
- }
- src.SetReadDeadline(time.Time{})
-
- dataLen := binary.BigEndian.Uint16(buf[:dataLenLen])
- expectedHmacSha1 := buf[dataLenLen:idxData0]
-
- var dataBuf []byte
- if len(buf) < int(idxData0+dataLen) {
- dataBuf = make([]byte, dataLen)
- } else {
- dataBuf = buf[idxData0 : idxData0+dataLen]
- }
- if n, err := io.ReadFull(src, dataBuf); err != nil {
- return int64(n), err
- }
- chunkIdBytes := make([]byte, 4)
- chunkId := src.GetAndIncrChunkId()
- binary.BigEndian.PutUint32(chunkIdBytes, chunkId)
- actualHmacSha1 := ss.HmacSha1(append(src.GetIv(), chunkIdBytes...), dataBuf)
- if !bytes.Equal(expectedHmacSha1, actualHmacSha1) {
- return 0, errors.New("ota error: mismatch")
- }
-
- if n, err := dst.Write(dataBuf); err != nil {
- return int64(n), err
- }
- }
-}
-
-func (s *ShadowServer) transportOTA(sc *ss.Conn, cc net.Conn) (err error) {
- errc := make(chan error, 2)
-
- go func() {
- _, err := io.Copy(&shadowConn{conn: sc}, cc)
- errc <- err
- }()
-
- go func() {
- _, err := s.copyOta(cc, sc)
- errc <- err
- }()
-
- select {
- case err = <-errc:
- //glog.V(LWARNING).Infoln("transport exit", err)
- }
-
- return
-}
-
// Due to in/out byte length is inconsistent of the shadowsocks.Conn.Write,
-// we wrap around it to make io.Copy happy
+// we wrap around it to make io.Copy happy.
type shadowConn struct {
- conn *ss.Conn
+ conn net.Conn
}
func (c *shadowConn) Read(b []byte) (n int, err error) {
@@ -237,117 +56,364 @@ func (c *shadowConn) SetWriteDeadline(t time.Time) error {
return c.conn.SetWriteDeadline(t)
}
-type ShadowUdpServer struct {
- Base *ProxyServer
- TTL int
+type shadowConnector struct {
+ Cipher *url.Userinfo
}
-func NewShadowUdpServer(base *ProxyServer, ttl int) *ShadowUdpServer {
- return &ShadowUdpServer{Base: base, TTL: ttl}
+// ShadowConnector creates a Connector for shadowsocks proxy client.
+// It accepts a cipher info for shadowsocks data encryption/decryption.
+// The cipher must not be nil.
+func ShadowConnector(cipher *url.Userinfo) Connector {
+ return &shadowConnector{Cipher: cipher}
}
-func (s *ShadowUdpServer) ListenAndServe() error {
- laddr, err := net.ResolveUDPAddr("udp", s.Base.Node.Addr)
+func (c *shadowConnector) Connect(conn net.Conn, addr string) (net.Conn, error) {
+ rawaddr, err := ss.RawAddr(addr)
if err != nil {
- return err
+ return nil, err
}
- lconn, err := net.ListenUDP("udp", laddr)
+
+ var method, password string
+ if c.Cipher != nil {
+ method = c.Cipher.Username()
+ password, _ = c.Cipher.Password()
+ }
+
+ cipher, err := ss.NewCipher(method, password)
if err != nil {
- return err
+ return nil, err
}
- defer lconn.Close()
- conn := ss.NewSecurePacketConn(lconn, s.Base.cipher.Copy(), true) // force OTA on
+ sc, err := ss.DialWithRawAddrConn(rawaddr, conn, cipher)
+ if err != nil {
+ return nil, err
+ }
+ return &shadowConn{conn: sc}, nil
+}
- rChan, wChan := make(chan *packet, 128), make(chan *packet, 128)
- // start send queue
- go func(ch chan<- *packet) {
- for {
- b := make([]byte, MediumBufferSize)
- n, addr, err := conn.ReadFrom(b[3:]) // add rsv and frag fields to make it the standard SOCKS5 UDP datagram
- if err != nil {
- glog.V(LWARNING).Infof("[ssu] %s -> %s : %s", addr, laddr, err)
- continue
- }
+type shadowHandler struct {
+ options *HandlerOptions
+}
- b[3] &= ss.AddrMask // remove OTA flag
- dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n+3]))
- if err != nil {
- glog.V(LWARNING).Infof("[ssu] %s -> %s : %s", addr, laddr, err)
- continue
- }
+// ShadowHandler creates a server Handler for shadowsocks proxy server.
+func ShadowHandler(opts ...HandlerOption) Handler {
+ h := &shadowHandler{
+ options: &HandlerOptions{},
+ }
+ for _, opt := range opts {
+ opt(h.options)
+ }
+ return h
+}
+
+func (h *shadowHandler) Handle(conn net.Conn) {
+ defer conn.Close()
+
+ var method, password string
+ users := h.options.Users
+ if len(users) > 0 {
+ method = users[0].Username()
+ password, _ = users[0].Password()
+ }
+ cipher, err := ss.NewCipher(method, password)
+ if err != nil {
+ log.Log("[ss]", err)
+ return
+ }
+ conn = &shadowConn{conn: ss.NewConn(conn, cipher)}
+
+ log.Logf("[ss] %s - %s", conn.RemoteAddr(), conn.LocalAddr())
+
+ addr, err := h.getRequest(conn)
+ if err != nil {
+ log.Logf("[ss] %s - %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
+ return
+ }
+ log.Logf("[ss] %s -> %s", conn.RemoteAddr(), addr)
+
+ if !Can("tcp", addr, h.options.Whitelist, h.options.Blacklist) {
+ log.Logf("[ss] Unauthorized to tcp connect to %s", addr)
+ return
+ }
+
+ cc, err := h.options.Chain.Dial(addr)
+ if err != nil {
+ log.Logf("[ss] %s -> %s : %s", conn.RemoteAddr(), addr, err)
+ return
+ }
+ defer cc.Close()
+
+ log.Logf("[ss] %s <-> %s", conn.RemoteAddr(), addr)
+ transport(conn, cc)
+ log.Logf("[ss] %s >-< %s", conn.RemoteAddr(), addr)
+}
+
+const (
+ idType = 0 // address type index
+ idIP0 = 1 // ip addres start index
+ idDmLen = 1 // domain address length index
+ idDm0 = 2 // domain address start index
+
+ typeIPv4 = 1 // type is ipv4 address
+ typeDm = 3 // type is domain address
+ typeIPv6 = 4 // type is ipv6 address
+
+ lenIPv4 = net.IPv4len + 2 // ipv4 + 2port
+ lenIPv6 = net.IPv6len + 2 // ipv6 + 2port
+ lenDmBase = 2 // 1addrLen + 2port, plus addrLen
+ lenHmacSha1 = 10
+)
+
+// This function is copied from shadowsocks library with some modification.
+func (h *shadowHandler) getRequest(conn net.Conn) (host string, err error) {
+ // buf size should at least have the same size with the largest possible
+ // request size (when addrType is 3, domain name has at most 256 bytes)
+ // 1(addrType) + 1(lenByte) + 256(max length address) + 2(port)
+ buf := make([]byte, smallBufferSize)
+
+ // read till we get possible domain length field
+ conn.SetReadDeadline(time.Now().Add(30 * time.Second))
+ if _, err = io.ReadFull(conn, buf[:idType+1]); err != nil {
+ return
+ }
+
+ var reqStart, reqEnd int
+ addrType := buf[idType]
+ switch addrType & ss.AddrMask {
+ case typeIPv4:
+ reqStart, reqEnd = idIP0, idIP0+lenIPv4
+ case typeIPv6:
+ reqStart, reqEnd = idIP0, idIP0+lenIPv6
+ case typeDm:
+ if _, err = io.ReadFull(conn, buf[idType+1:idDmLen+1]); err != nil {
+ return
+ }
+ reqStart, reqEnd = idDm0, int(idDm0+buf[idDmLen]+lenDmBase)
+ default:
+ err = fmt.Errorf("addr type %d not supported", addrType&ss.AddrMask)
+ return
+ }
+
+ if _, err = io.ReadFull(conn, buf[reqStart:reqEnd]); err != nil {
+ return
+ }
+
+ // Return string for typeIP is not most efficient, but browsers (Chrome,
+ // Safari, Firefox) all seems using typeDm exclusively. So this is not a
+ // big problem.
+ switch addrType & ss.AddrMask {
+ case typeIPv4:
+ host = net.IP(buf[idIP0 : idIP0+net.IPv4len]).String()
+ case typeIPv6:
+ host = net.IP(buf[idIP0 : idIP0+net.IPv6len]).String()
+ case typeDm:
+ host = string(buf[idDm0 : idDm0+buf[idDmLen]])
+ }
+ // parse port
+ port := binary.BigEndian.Uint16(buf[reqEnd-2 : reqEnd])
+ host = net.JoinHostPort(host, strconv.Itoa(int(port)))
+ return
+}
+
+type shadowUDPListener struct {
+ ln net.PacketConn
+ conns map[string]*udpServerConn
+ connChan chan net.Conn
+ errChan chan error
+ ttl time.Duration
+}
+
+// ShadowUDPListener creates a Listener for shadowsocks UDP relay server.
+func ShadowUDPListener(addr string, cipher *url.Userinfo, ttl time.Duration) (Listener, error) {
+ laddr, err := net.ResolveUDPAddr("udp", addr)
+ if err != nil {
+ return nil, err
+ }
+ ln, err := net.ListenUDP("udp", laddr)
+ if err != nil {
+ return nil, err
+ }
+
+ var method, password string
+ if cipher != nil {
+ method = cipher.Username()
+ password, _ = cipher.Password()
+ }
+ cp, err := ss.NewCipher(method, password)
+ if err != nil {
+ ln.Close()
+ return nil, err
+ }
+ l := &shadowUDPListener{
+ ln: ss.NewSecurePacketConn(ln, cp, false),
+ conns: make(map[string]*udpServerConn),
+ connChan: make(chan net.Conn, 1024),
+ errChan: make(chan error, 1),
+ ttl: ttl,
+ }
+ go l.listenLoop()
+ return l, nil
+}
+
+func (l *shadowUDPListener) listenLoop() {
+ for {
+ b := make([]byte, mediumBufferSize)
+ n, raddr, err := l.ln.ReadFrom(b)
+ if err != nil {
+ log.Logf("[ssu] peer -> %s : %s", l.Addr(), err)
+ l.ln.Close()
+ l.errChan <- err
+ close(l.errChan)
+ return
+ }
+ if Debug {
+ log.Logf("[ssu] %s >>> %s : length %d", raddr, l.Addr(), n)
+ }
+
+ conn, ok := l.conns[raddr.String()]
+ if !ok || conn.Closed() {
+ conn = newUDPServerConn(l.ln, raddr, l.ttl)
+ l.conns[raddr.String()] = conn
select {
- case ch <- &packet{srcAddr: addr.String(), dstAddr: dgram.Header.Addr.String(), data: dgram.Data}:
- case <-time.After(time.Second * 3):
- glog.V(LWARNING).Infof("[ssu] %s -> %s : %s", addr, dgram.Header.Addr.String(), "send queue is full, discard")
+ case l.connChan <- conn:
+ default:
+ conn.Close()
+ log.Logf("[ssu] %s - %s: connection queue is full", raddr, l.Addr())
}
}
- }(wChan)
- // start recv queue
- go func(ch <-chan *packet) {
- for pkt := range ch {
- srcAddr, err := net.ResolveUDPAddr("udp", pkt.srcAddr)
- if err != nil {
- glog.V(LWARNING).Infof("[ssu] %s <- %s : %s", pkt.dstAddr, pkt.srcAddr, err)
- continue
- }
- dstAddr, err := net.ResolveUDPAddr("udp", pkt.dstAddr)
- if err != nil {
- glog.V(LWARNING).Infof("[ssu] %s <- %s : %s", pkt.dstAddr, pkt.srcAddr, err)
- continue
- }
-
- dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(0, 0, ToSocksAddr(srcAddr)), pkt.data)
- b := bytes.Buffer{}
- dgram.Write(&b)
- if b.Len() < 10 {
- glog.V(LWARNING).Infof("[ssu] %s <- %s : invalid udp datagram", pkt.dstAddr, pkt.srcAddr)
- continue
- }
-
- if _, err := conn.WriteTo(b.Bytes()[3:], dstAddr); err != nil { // remove rsv and frag fields to make it standard shadowsocks UDP datagram
- glog.V(LWARNING).Infof("[ssu] %s <- %s : %s", pkt.dstAddr, pkt.srcAddr, err)
- return
- }
- }
- }(rChan)
-
- // mapping client to node
- m := make(map[string]*cnode)
-
- // start dispatcher
- for pkt := range wChan {
- // clear obsolete nodes
- for k, node := range m {
- if node != nil && node.err != nil {
- close(node.wChan)
- delete(m, k)
- glog.V(LINFO).Infof("[ssu] clear node %s", k)
- }
- }
-
- node, ok := m[pkt.srcAddr]
- if !ok {
- node = &cnode{
- chain: s.Base.Chain,
- srcAddr: pkt.srcAddr,
- dstAddr: pkt.dstAddr,
- rChan: rChan,
- wChan: make(chan *packet, 32),
- ttl: time.Duration(s.TTL) * time.Second,
- }
- m[pkt.srcAddr] = node
- go node.run()
- glog.V(LINFO).Infof("[ssu] %s -> %s : new client (%d)", pkt.srcAddr, pkt.dstAddr, len(m))
- }
select {
- case node.wChan <- pkt:
- case <-time.After(time.Second * 3):
- glog.V(LWARNING).Infof("[ssu] %s -> %s : %s", pkt.srcAddr, pkt.dstAddr, "node send queue is full, discard")
+ case conn.rChan <- b[:n]: // we keep the addr info so that the handler can identify the destination.
+ default:
+ log.Logf("[ssu] %s -> %s : read queue is full", raddr, l.Addr())
}
}
-
- return nil
+}
+
+func (l *shadowUDPListener) Accept() (conn net.Conn, err error) {
+ var ok bool
+ select {
+ case conn = <-l.connChan:
+ case err, ok = <-l.errChan:
+ if !ok {
+ err = errors.New("accpet on closed listener")
+ }
+ }
+ return
+}
+
+func (l *shadowUDPListener) Addr() net.Addr {
+ return l.ln.LocalAddr()
+}
+
+func (l *shadowUDPListener) Close() error {
+ return l.ln.Close()
+}
+
+type shadowUDPdHandler struct {
+ ttl time.Duration
+ options *HandlerOptions
+}
+
+// ShadowUDPdHandler creates a server Handler for shadowsocks UDP relay server.
+func ShadowUDPdHandler(opts ...HandlerOption) Handler {
+ h := &shadowUDPdHandler{
+ options: &HandlerOptions{},
+ }
+ for _, opt := range opts {
+ opt(h.options)
+ }
+ return h
+}
+
+func (h *shadowUDPdHandler) Handle(conn net.Conn) {
+ defer conn.Close()
+
+ var err error
+ var cc net.PacketConn
+ if h.options.Chain.IsEmpty() {
+ cc, err = net.ListenUDP("udp", nil)
+ if err != nil {
+ log.Logf("[ssu] %s - : %s", conn.LocalAddr(), err)
+ return
+ }
+ } else {
+ var c net.Conn
+ c, err = getSOCKS5UDPTunnel(h.options.Chain, nil)
+ if err != nil {
+ log.Logf("[ssu] %s - : %s", conn.LocalAddr(), err)
+ return
+ }
+ cc = &udpTunnelConn{Conn: c}
+ }
+ defer cc.Close()
+
+ log.Logf("[ssu] %s <-> %s", conn.RemoteAddr(), conn.LocalAddr())
+ transportUDP(conn, cc)
+ log.Logf("[ssu] %s >-< %s", conn.RemoteAddr(), conn.LocalAddr())
+}
+
+func transportUDP(sc net.Conn, cc net.PacketConn) error {
+ errc := make(chan error, 1)
+ go func() {
+ for {
+ b := make([]byte, mediumBufferSize)
+ n, err := sc.Read(b[3:]) // add rsv and frag fields to make it the standard SOCKS5 UDP datagram
+ if err != nil {
+ // log.Logf("[ssu] %s - %s : %s", sc.RemoteAddr(), sc.LocalAddr(), err)
+ errc <- err
+ return
+ }
+ dgram, err := gosocks5.ReadUDPDatagram(bytes.NewReader(b[:n+3]))
+ if err != nil {
+ log.Logf("[ssu] %s - %s : %s", sc.RemoteAddr(), sc.LocalAddr(), err)
+ errc <- err
+ return
+ }
+ //if Debug {
+ // log.Logf("[ssu] %s >>> %s length: %d", sc.RemoteAddr(), dgram.Header.Addr.String(), len(dgram.Data))
+ //}
+ addr, err := net.ResolveUDPAddr("udp", dgram.Header.Addr.String())
+ if err != nil {
+ errc <- err
+ return
+ }
+ if _, err := cc.WriteTo(dgram.Data, addr); err != nil {
+ errc <- err
+ return
+ }
+ }
+ }()
+
+ go func() {
+ for {
+ b := make([]byte, mediumBufferSize)
+ n, addr, err := cc.ReadFrom(b)
+ if err != nil {
+ errc <- err
+ return
+ }
+ //if Debug {
+ // log.Logf("[ssu] %s <<< %s length: %d", sc.RemoteAddr(), addr, n)
+ //}
+ dgram := gosocks5.NewUDPDatagram(gosocks5.NewUDPHeader(0, 0, toSocksAddr(addr)), b[:n])
+ buf := bytes.Buffer{}
+ dgram.Write(&buf)
+ if buf.Len() < 10 {
+ log.Logf("[ssu] %s <- %s : invalid udp datagram", sc.RemoteAddr(), addr)
+ continue
+ }
+ if _, err := sc.Write(buf.Bytes()[3:]); err != nil {
+ errc <- err
+ return
+ }
+ }
+ }()
+
+ err := <-errc
+ if err != nil && err == io.EOF {
+ err = nil
+ }
+ return err
}
diff --git a/ssh.go b/ssh.go
new file mode 100644
index 0000000..a2e1fe9
--- /dev/null
+++ b/ssh.go
@@ -0,0 +1,835 @@
+package gost
+
+import (
+ "context"
+ "crypto/tls"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "net"
+ "net/url"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/go-log/log"
+ "golang.org/x/crypto/ssh"
+)
+
+// Applicaple SSH Request types for Port Forwarding - RFC 4254 7.X
+const (
+ DirectForwardRequest = "direct-tcpip" // RFC 4254 7.2
+ RemoteForwardRequest = "tcpip-forward" // RFC 4254 7.1
+ ForwardedTCPReturnRequest = "forwarded-tcpip" // RFC 4254 7.2
+ CancelRemoteForwardRequest = "cancel-tcpip-forward" // RFC 4254 7.1
+
+ GostSSHTunnelRequest = "gost-tunnel" // extended request type for ssh tunnel
+)
+
+var (
+ errSessionDead = errors.New("session is dead")
+)
+
+type sshDirectForwardConnector struct {
+}
+
+func SSHDirectForwardConnector() Connector {
+ return &sshDirectForwardConnector{}
+}
+
+func (c *sshDirectForwardConnector) Connect(conn net.Conn, raddr string) (net.Conn, error) {
+ cc, ok := conn.(*sshNopConn) // TODO: this is an ugly type assertion, need to find a better solution.
+ if !ok {
+ return nil, errors.New("ssh: wrong connection type")
+ }
+ conn, err := cc.session.client.Dial("tcp", raddr)
+ if err != nil {
+ log.Logf("[ssh-tcp] %s -> %s : %s", cc.session.addr, raddr, err)
+ return nil, err
+ }
+ return conn, nil
+}
+
+type sshRemoteForwardConnector struct {
+}
+
+func SSHRemoteForwardConnector() Connector {
+ return &sshRemoteForwardConnector{}
+}
+
+func (c *sshRemoteForwardConnector) Connect(conn net.Conn, addr string) (net.Conn, error) {
+ cc, ok := conn.(*sshNopConn) // TODO: this is an ugly type assertion, need to find a better solution.
+ if !ok {
+ return nil, errors.New("ssh: wrong connection type")
+ }
+
+ cc.session.once.Do(func() {
+ go func() {
+ defer log.Log("ssh-rtcp: session is closed")
+ defer close(cc.session.connChan)
+
+ if cc.session == nil || cc.session.client == nil {
+ return
+ }
+ if strings.HasPrefix(addr, ":") {
+ addr = "0.0.0.0" + addr
+ }
+ ln, err := cc.session.client.Listen("tcp", addr)
+ if err != nil {
+ return
+ }
+ for {
+ rc, err := ln.Accept()
+ if err != nil {
+ log.Logf("[ssh-rtcp] %s <-> %s accpet : %s", ln.Addr(), addr, err)
+ return
+ }
+
+ select {
+ case cc.session.connChan <- rc:
+ default:
+ rc.Close()
+ log.Logf("[ssh-rtcp] %s - %s: connection queue is full", ln.Addr(), addr)
+ }
+ }
+ }()
+ })
+
+ sc, ok := <-cc.session.connChan
+ if !ok {
+ return nil, errors.New("ssh-rtcp: connection is closed")
+ }
+ return sc, nil
+}
+
+type sshForwardTransporter struct {
+ sessions map[string]*sshSession
+ sessionMutex sync.Mutex
+}
+
+func SSHForwardTransporter() Transporter {
+ return &sshForwardTransporter{
+ sessions: make(map[string]*sshSession),
+ }
+}
+
+func (tr *sshForwardTransporter) Dial(addr string, options ...DialOption) (conn net.Conn, err error) {
+ opts := &DialOptions{}
+ for _, option := range options {
+ option(opts)
+ }
+
+ tr.sessionMutex.Lock()
+ defer tr.sessionMutex.Unlock()
+
+ session, ok := tr.sessions[addr]
+ if !ok || session.Closed() {
+ if opts.Chain == nil {
+ conn, err = net.DialTimeout("tcp", addr, opts.Timeout)
+ } else {
+ conn, err = opts.Chain.Dial(addr)
+ }
+ if err != nil {
+ return
+ }
+ session = &sshSession{
+ addr: addr,
+ conn: conn,
+ }
+ tr.sessions[addr] = session
+ }
+
+ return session.conn, nil
+}
+
+func (tr *sshForwardTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
+ opts := &HandshakeOptions{}
+ for _, option := range options {
+ option(opts)
+ }
+
+ config := ssh.ClientConfig{
+ Timeout: opts.Timeout,
+ HostKeyCallback: ssh.InsecureIgnoreHostKey(),
+ }
+ if opts.User != nil {
+ config.User = opts.User.Username()
+ password, _ := opts.User.Password()
+ config.Auth = []ssh.AuthMethod{
+ ssh.Password(password),
+ }
+ }
+
+ tr.sessionMutex.Lock()
+ defer tr.sessionMutex.Unlock()
+
+ session, ok := tr.sessions[opts.Addr]
+ if session != nil && session.conn != conn {
+ conn.Close()
+ return nil, errors.New("ssh: unrecognized connection")
+ }
+ if !ok || session.client == nil {
+ sshConn, chans, reqs, err := ssh.NewClientConn(conn, opts.Addr, &config)
+ if err != nil {
+ conn.Close()
+ delete(tr.sessions, opts.Addr)
+ return nil, err
+ }
+
+ session = &sshSession{
+ addr: opts.Addr,
+ conn: conn,
+ client: ssh.NewClient(sshConn, chans, reqs),
+ closed: make(chan struct{}),
+ deaded: make(chan struct{}),
+ connChan: make(chan net.Conn, 1024),
+ }
+ tr.sessions[opts.Addr] = session
+ go session.Ping(opts.Interval, opts.Timeout, 1)
+ go session.waitServer()
+ go session.waitClose()
+ }
+ if session.Closed() {
+ delete(tr.sessions, opts.Addr)
+ return nil, errSessionDead
+ }
+
+ return &sshNopConn{session: session}, nil
+}
+
+func (tr *sshForwardTransporter) Multiplex() bool {
+ return true
+}
+
+type sshTunnelTransporter struct {
+ sessions map[string]*sshSession
+ sessionMutex sync.Mutex
+}
+
+// SSHTunnelTransporter creates a Transporter that is used by SSH tunnel client.
+func SSHTunnelTransporter() Transporter {
+ return &sshTunnelTransporter{
+ sessions: make(map[string]*sshSession),
+ }
+}
+
+func (tr *sshTunnelTransporter) Dial(addr string, options ...DialOption) (conn net.Conn, err error) {
+ opts := &DialOptions{}
+ for _, option := range options {
+ option(opts)
+ }
+
+ tr.sessionMutex.Lock()
+ defer tr.sessionMutex.Unlock()
+
+ session, ok := tr.sessions[addr]
+ if !ok || session.Closed() {
+ if opts.Chain == nil {
+ conn, err = net.DialTimeout("tcp", addr, opts.Timeout)
+ } else {
+ conn, err = opts.Chain.Dial(addr)
+ }
+ if err != nil {
+ return
+ }
+ session = &sshSession{
+ addr: addr,
+ conn: conn,
+ }
+ tr.sessions[addr] = session
+ }
+
+ return session.conn, nil
+}
+
+func (tr *sshTunnelTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
+ opts := &HandshakeOptions{}
+ for _, option := range options {
+ option(opts)
+ }
+
+ config := ssh.ClientConfig{
+ Timeout: opts.Timeout,
+ HostKeyCallback: ssh.InsecureIgnoreHostKey(),
+ }
+ if opts.User != nil {
+ config.User = opts.User.Username()
+ password, _ := opts.User.Password()
+ config.Auth = []ssh.AuthMethod{
+ ssh.Password(password),
+ }
+ }
+
+ tr.sessionMutex.Lock()
+ defer tr.sessionMutex.Unlock()
+
+ session, ok := tr.sessions[opts.Addr]
+ if session != nil && session.conn != conn {
+ conn.Close()
+ return nil, errors.New("ssh: unrecognized connection")
+ }
+ if !ok || session.client == nil {
+ sshConn, chans, reqs, err := ssh.NewClientConn(conn, opts.Addr, &config)
+ if err != nil {
+ conn.Close()
+ delete(tr.sessions, opts.Addr)
+ return nil, err
+ }
+
+ session = &sshSession{
+ addr: opts.Addr,
+ conn: conn,
+ client: ssh.NewClient(sshConn, chans, reqs),
+ closed: make(chan struct{}),
+ deaded: make(chan struct{}),
+ }
+ tr.sessions[opts.Addr] = session
+ go session.Ping(opts.Interval, opts.Timeout, 1)
+ go session.waitServer()
+ go session.waitClose()
+ }
+
+ if session.Closed() {
+ delete(tr.sessions, opts.Addr)
+ return nil, errSessionDead
+ }
+
+ channel, reqs, err := session.client.OpenChannel(GostSSHTunnelRequest, nil)
+ if err != nil {
+ return nil, err
+ }
+ go ssh.DiscardRequests(reqs)
+ return &sshConn{channel: channel, conn: conn}, nil
+}
+
+func (tr *sshTunnelTransporter) Multiplex() bool {
+ return true
+}
+
+type sshSession struct {
+ addr string
+ conn net.Conn
+ client *ssh.Client
+ closed chan struct{}
+ deaded chan struct{}
+ once sync.Once
+ connChan chan net.Conn
+}
+
+func (s *sshSession) Ping(interval, timeout time.Duration, retries int) {
+ if interval <= 0 {
+ return
+ }
+ if timeout <= 0 {
+ timeout = 30 * time.Second
+ }
+ defer close(s.deaded)
+
+ log.Log("[ssh] ping is enabled, interval:", interval)
+ baseCtx := context.Background()
+ t := time.NewTicker(interval)
+ defer t.Stop()
+
+ for {
+ select {
+ case <-t.C:
+ start := time.Now()
+ //if Debug {
+ log.Log("[ssh] sending ping")
+ //}
+ ctx, cancel := context.WithTimeout(baseCtx, timeout)
+ var err error
+ select {
+ case err = <-s.sendPing():
+ case <-ctx.Done():
+ err = errors.New("Timeout")
+ }
+ cancel()
+ if err != nil {
+ log.Log("[ssh] ping:", err)
+ return
+ }
+ //if Debug {
+ log.Log("[ssh] ping OK, RTT:", time.Since(start))
+ //}
+
+ case <-s.closed:
+ return
+ }
+ }
+}
+
+func (s *sshSession) sendPing() <-chan error {
+ ch := make(chan error, 1)
+ go func() {
+ if _, _, err := s.client.SendRequest("ping", true, nil); err != nil {
+ ch <- err
+ }
+ close(ch)
+ }()
+ return ch
+}
+
+func (s *sshSession) waitServer() error {
+ defer close(s.closed)
+ return s.client.Wait()
+}
+
+func (s *sshSession) waitClose() {
+ defer s.client.Close()
+
+ select {
+ case <-s.deaded:
+ case <-s.closed:
+ }
+}
+
+func (s *sshSession) Closed() bool {
+ select {
+ case <-s.deaded:
+ return true
+ case <-s.closed:
+ return true
+ default:
+ }
+ return false
+}
+
+type sshForwardHandler struct {
+ options *HandlerOptions
+ config *ssh.ServerConfig
+}
+
+func SSHForwardHandler(opts ...HandlerOption) Handler {
+ h := &sshForwardHandler{
+ options: new(HandlerOptions),
+ config: new(ssh.ServerConfig),
+ }
+ for _, opt := range opts {
+ opt(h.options)
+ }
+ h.config.PasswordCallback = defaultSSHPasswordCallback(h.options.Users...)
+ if len(h.options.Users) == 0 {
+ h.config.NoClientAuth = true
+ }
+ tlsConfig := h.options.TLSConfig
+ if tlsConfig == nil {
+ tlsConfig = DefaultTLSConfig
+ }
+ if tlsConfig != nil && len(tlsConfig.Certificates) > 0 {
+ signer, err := ssh.NewSignerFromKey(tlsConfig.Certificates[0].PrivateKey)
+ if err != nil {
+ log.Log("[ssh-forward]", err)
+ }
+ h.config.AddHostKey(signer)
+ }
+
+ return h
+}
+
+func (h *sshForwardHandler) Handle(conn net.Conn) {
+ sshConn, chans, reqs, err := ssh.NewServerConn(conn, h.config)
+ if err != nil {
+ log.Logf("[ssh-forward] %s -> %s : %s", conn.RemoteAddr(), h.options.Addr, err)
+ conn.Close()
+ return
+ }
+ defer sshConn.Close()
+
+ log.Logf("[ssh-forward] %s <-> %s", conn.RemoteAddr(), h.options.Addr)
+ h.handleForward(sshConn, chans, reqs)
+ log.Logf("[ssh-forward] %s >-< %s", conn.RemoteAddr(), h.options.Addr)
+}
+
+func (h *sshForwardHandler) handleForward(conn ssh.Conn, chans <-chan ssh.NewChannel, reqs <-chan *ssh.Request) {
+ quit := make(chan struct{})
+ defer close(quit) // quit signal
+
+ go func() {
+ for req := range reqs {
+ switch req.Type {
+ case RemoteForwardRequest:
+ go h.tcpipForwardRequest(conn, req, quit)
+ default:
+ // log.Log("[ssh] unknown channel type:", req.Type)
+ if req.WantReply {
+ req.Reply(false, nil)
+ }
+ }
+ }
+ }()
+
+ go func() {
+ for newChannel := range chans {
+ // Check the type of channel
+ t := newChannel.ChannelType()
+ switch t {
+ case DirectForwardRequest:
+ channel, requests, err := newChannel.Accept()
+ if err != nil {
+ log.Log("[ssh] Could not accept channel:", err)
+ continue
+ }
+ p := directForward{}
+ ssh.Unmarshal(newChannel.ExtraData(), &p)
+
+ if p.Host1 == "" {
+ p.Host1 = ""
+ }
+
+ go ssh.DiscardRequests(requests)
+ go h.directPortForwardChannel(channel, fmt.Sprintf("%s:%d", p.Host1, p.Port1))
+ default:
+ log.Log("[ssh] Unknown channel type:", t)
+ newChannel.Reject(ssh.UnknownChannelType, fmt.Sprintf("unknown channel type: %s", t))
+ }
+ }
+ }()
+
+ conn.Wait()
+}
+
+func (h *sshForwardHandler) directPortForwardChannel(channel ssh.Channel, raddr string) {
+ defer channel.Close()
+
+ log.Logf("[ssh-tcp] %s - %s", h.options.Addr, raddr)
+
+ if !Can("tcp", raddr, h.options.Whitelist, h.options.Blacklist) {
+ log.Logf("[ssh-tcp] Unauthorized to tcp connect to %s", raddr)
+ return
+ }
+
+ conn, err := h.options.Chain.Dial(raddr)
+ if err != nil {
+ log.Logf("[ssh-tcp] %s - %s : %s", h.options.Addr, raddr, err)
+ return
+ }
+ defer conn.Close()
+
+ log.Logf("[ssh-tcp] %s <-> %s", h.options.Addr, raddr)
+ transport(conn, channel)
+ log.Logf("[ssh-tcp] %s >-< %s", h.options.Addr, raddr)
+}
+
+// tcpipForward is structure for RFC 4254 7.1 "tcpip-forward" request
+type tcpipForward struct {
+ Host string
+ Port uint32
+}
+
+func (h *sshForwardHandler) tcpipForwardRequest(sshConn ssh.Conn, req *ssh.Request, quit <-chan struct{}) {
+ t := tcpipForward{}
+ ssh.Unmarshal(req.Payload, &t)
+
+ addr := fmt.Sprintf("%s:%d", t.Host, t.Port)
+
+ if !Can("rtcp", addr, h.options.Whitelist, h.options.Blacklist) {
+ log.Logf("[ssh-rtcp] Unauthorized to tcp bind to %s", addr)
+ req.Reply(false, nil)
+ return
+ }
+
+ log.Log("[ssh-rtcp] listening on tcp", addr)
+ ln, err := net.Listen("tcp", addr) //tie to the client connection
+ if err != nil {
+ log.Log("[ssh-rtcp]", err)
+ req.Reply(false, nil)
+ return
+ }
+ defer ln.Close()
+
+ replyFunc := func() error {
+ if t.Port == 0 && req.WantReply { // Client sent port 0. let them know which port is actually being used
+ _, port, err := getHostPortFromAddr(ln.Addr())
+ if err != nil {
+ return err
+ }
+ var b [4]byte
+ binary.BigEndian.PutUint32(b[:], uint32(port))
+ t.Port = uint32(port)
+ return req.Reply(true, b[:])
+ }
+ return req.Reply(true, nil)
+ }
+ if err := replyFunc(); err != nil {
+ log.Log("[ssh-rtcp]", err)
+ return
+ }
+
+ go func() {
+ for {
+ conn, err := ln.Accept()
+ if err != nil { // Unable to accept new connection - listener is likely closed
+ return
+ }
+
+ go func(conn net.Conn) {
+ defer conn.Close()
+
+ p := directForward{}
+ var err error
+
+ var portnum int
+ p.Host1 = t.Host
+ p.Port1 = t.Port
+ p.Host2, portnum, err = getHostPortFromAddr(conn.RemoteAddr())
+ if err != nil {
+ return
+ }
+
+ p.Port2 = uint32(portnum)
+ ch, reqs, err := sshConn.OpenChannel(ForwardedTCPReturnRequest, ssh.Marshal(p))
+ if err != nil {
+ log.Log("[ssh-rtcp] open forwarded channel:", err)
+ return
+ }
+ defer ch.Close()
+ go ssh.DiscardRequests(reqs)
+
+ log.Logf("[ssh-rtcp] %s <-> %s", conn.RemoteAddr(), conn.LocalAddr())
+ transport(ch, conn)
+ log.Logf("[ssh-rtcp] %s >-< %s", conn.RemoteAddr(), conn.LocalAddr())
+ }(conn)
+ }
+ }()
+
+ <-quit
+}
+
+// SSHConfig holds the SSH tunnel server config
+type SSHConfig struct {
+ Users []*url.Userinfo
+ TLSConfig *tls.Config
+}
+
+type sshTunnelListener struct {
+ net.Listener
+ config *ssh.ServerConfig
+ connChan chan net.Conn
+ errChan chan error
+}
+
+// SSHTunnelListener creates a Listener for SSH tunnel server.
+func SSHTunnelListener(addr string, config *SSHConfig) (Listener, error) {
+ ln, err := net.Listen("tcp", addr)
+ if err != nil {
+ return nil, err
+ }
+
+ if config == nil {
+ config = &SSHConfig{}
+ }
+
+ sshConfig := &ssh.ServerConfig{}
+ sshConfig.PasswordCallback = defaultSSHPasswordCallback(config.Users...)
+ if len(config.Users) == 0 {
+ sshConfig.NoClientAuth = true
+ }
+ tlsConfig := config.TLSConfig
+ if tlsConfig == nil {
+ tlsConfig = DefaultTLSConfig
+ }
+
+ signer, err := ssh.NewSignerFromKey(tlsConfig.Certificates[0].PrivateKey)
+ if err != nil {
+ ln.Close()
+ return nil, err
+
+ }
+ sshConfig.AddHostKey(signer)
+
+ l := &sshTunnelListener{
+ Listener: tcpKeepAliveListener{ln.(*net.TCPListener)},
+ config: sshConfig,
+ connChan: make(chan net.Conn, 1024),
+ errChan: make(chan error, 1),
+ }
+
+ go l.listenLoop()
+
+ return l, nil
+}
+
+func (l *sshTunnelListener) listenLoop() {
+ for {
+ conn, err := l.Listener.Accept()
+ if err != nil {
+ log.Log("[ssh] accept:", err)
+ l.errChan <- err
+ close(l.errChan)
+ return
+ }
+ go l.serveConn(conn)
+ }
+}
+
+func (l *sshTunnelListener) serveConn(conn net.Conn) {
+ sc, chans, reqs, err := ssh.NewServerConn(conn, l.config)
+ if err != nil {
+ log.Logf("[ssh] %s -> %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err)
+ conn.Close()
+ return
+ }
+ defer sc.Close()
+
+ go ssh.DiscardRequests(reqs)
+ go func() {
+ for newChannel := range chans {
+ // Check the type of channel
+ t := newChannel.ChannelType()
+ switch t {
+ case GostSSHTunnelRequest:
+ channel, requests, err := newChannel.Accept()
+ if err != nil {
+ log.Log("[ssh] Could not accept channel:", err)
+ continue
+ }
+ go ssh.DiscardRequests(requests)
+ cc := &sshConn{conn: conn, channel: channel}
+ select {
+ case l.connChan <- cc:
+ default:
+ cc.Close()
+ log.Logf("[ssh] %s - %s: connection queue is full", conn.RemoteAddr(), l.Addr())
+ }
+
+ default:
+ log.Log("[ssh] Unknown channel type:", t)
+ newChannel.Reject(ssh.UnknownChannelType, fmt.Sprintf("unknown channel type: %s", t))
+ }
+ }
+ }()
+
+ log.Logf("[ssh] %s <-> %s", conn.RemoteAddr(), conn.LocalAddr())
+ sc.Wait()
+ log.Logf("[ssh] %s >-< %s", conn.RemoteAddr(), conn.LocalAddr())
+}
+
+func (l *sshTunnelListener) Accept() (conn net.Conn, err error) {
+ var ok bool
+ select {
+ case conn = <-l.connChan:
+ case err, ok = <-l.errChan:
+ if !ok {
+ err = errors.New("accpet on closed listener")
+ }
+ }
+ return
+}
+
+// directForward is structure for RFC 4254 7.2 - can be used for "forwarded-tcpip" and "direct-tcpip"
+type directForward struct {
+ Host1 string
+ Port1 uint32
+ Host2 string
+ Port2 uint32
+}
+
+func (p directForward) String() string {
+ return fmt.Sprintf("%s:%d -> %s:%d", p.Host2, p.Port2, p.Host1, p.Port1)
+}
+
+func getHostPortFromAddr(addr net.Addr) (host string, port int, err error) {
+ host, portString, err := net.SplitHostPort(addr.String())
+ if err != nil {
+ return
+ }
+ port, err = strconv.Atoi(portString)
+ return
+}
+
+type PasswordCallbackFunc func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error)
+
+func defaultSSHPasswordCallback(users ...*url.Userinfo) PasswordCallbackFunc {
+ return func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
+ for _, user := range users {
+ u := user.Username()
+ p, _ := user.Password()
+ if u == conn.User() && p == string(password) {
+ return nil, nil
+ }
+ }
+ log.Logf("[ssh] %s -> %s : password rejected for %s", conn.RemoteAddr(), conn.LocalAddr(), conn.User())
+ return nil, fmt.Errorf("password rejected for %s", conn.User())
+ }
+}
+
+type sshNopConn struct {
+ session *sshSession
+}
+
+func (c *sshNopConn) Read(b []byte) (n int, err error) {
+ return 0, &net.OpError{Op: "read", Net: "ssh", Source: nil, Addr: nil, Err: errors.New("read not supported")}
+}
+
+func (c *sshNopConn) Write(b []byte) (n int, err error) {
+ return 0, &net.OpError{Op: "write", Net: "ssh", Source: nil, Addr: nil, Err: errors.New("write not supported")}
+}
+
+func (c *sshNopConn) Close() error {
+ return nil
+}
+
+func (c *sshNopConn) LocalAddr() net.Addr {
+ return &net.TCPAddr{
+ IP: net.IPv4zero,
+ Port: 0,
+ }
+}
+
+func (c *sshNopConn) RemoteAddr() net.Addr {
+ return &net.TCPAddr{
+ IP: net.IPv4zero,
+ Port: 0,
+ }
+}
+
+func (c *sshNopConn) SetDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
+
+func (c *sshNopConn) SetReadDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
+
+func (c *sshNopConn) SetWriteDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "http2", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
+
+type sshConn struct {
+ channel ssh.Channel
+ conn net.Conn
+}
+
+func (c *sshConn) Read(b []byte) (n int, err error) {
+ return c.channel.Read(b)
+}
+
+func (c *sshConn) Write(b []byte) (n int, err error) {
+ return c.channel.Write(b)
+}
+
+func (c *sshConn) Close() error {
+ return c.channel.Close()
+}
+
+func (c *sshConn) LocalAddr() net.Addr {
+ return c.conn.LocalAddr()
+}
+
+func (c *sshConn) RemoteAddr() net.Addr {
+ return c.conn.RemoteAddr()
+}
+
+func (c *sshConn) SetDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "ssh", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
+
+func (c *sshConn) SetReadDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "ssh", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
+
+func (c *sshConn) SetWriteDeadline(t time.Time) error {
+ return &net.OpError{Op: "set", Net: "ssh", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
+}
diff --git a/tls.go b/tls.go
new file mode 100644
index 0000000..4bc55dd
--- /dev/null
+++ b/tls.go
@@ -0,0 +1,107 @@
+package gost
+
+import (
+ "crypto/tls"
+ "crypto/x509"
+ "net"
+ "time"
+)
+
+type tlsTransporter struct {
+ tcpTransporter
+}
+
+// TLSTransporter creates a Transporter that is used by TLS proxy client.
+// It accepts a TLS config for TLS handshake.
+func TLSTransporter() Transporter {
+ return &tlsTransporter{}
+}
+
+func (tr *tlsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
+ opts := &HandshakeOptions{}
+ for _, option := range options {
+ option(opts)
+ }
+ if opts.TLSConfig == nil {
+ opts.TLSConfig = &tls.Config{InsecureSkipVerify: true}
+ }
+ return wrapTLSClient(conn, opts.TLSConfig)
+}
+
+type tlsListener struct {
+ net.Listener
+}
+
+// TLSListener creates a Listener for TLS proxy server.
+func TLSListener(addr string, config *tls.Config) (Listener, error) {
+ if config == nil {
+ config = DefaultTLSConfig
+ }
+ ln, err := tls.Listen("tcp", addr, config)
+ if err != nil {
+ return nil, err
+ }
+ return &tlsListener{ln}, nil
+}
+
+// Wrap a net.Conn into a client tls connection, performing any
+// additional verification as needed.
+//
+// As of go 1.3, crypto/tls only supports either doing no certificate
+// verification, or doing full verification including of the peer's
+// DNS name. For consul, we want to validate that the certificate is
+// signed by a known CA, but because consul doesn't use DNS names for
+// node names, we don't verify the certificate DNS names. Since go 1.3
+// no longer supports this mode of operation, we have to do it
+// manually.
+//
+// This code is taken from consul:
+// https://github.com/hashicorp/consul/blob/master/tlsutil/config.go
+func wrapTLSClient(conn net.Conn, tlsConfig *tls.Config) (net.Conn, error) {
+ var err error
+ var tlsConn *tls.Conn
+
+ tlsConn = tls.Client(conn, tlsConfig)
+
+ // If crypto/tls is doing verification, there's no need to do our own.
+ if tlsConfig.InsecureSkipVerify == false {
+ return tlsConn, nil
+ }
+
+ // Similarly if we use host's CA, we can do full handshake
+ if tlsConfig.RootCAs == nil {
+ return tlsConn, nil
+ }
+
+ // Otherwise perform handshake, but don't verify the domain
+ //
+ // The following is lightly-modified from the doFullHandshake
+ // method in https://golang.org/src/crypto/tls/handshake_client.go
+ if err = tlsConn.Handshake(); err != nil {
+ tlsConn.Close()
+ return nil, err
+ }
+
+ opts := x509.VerifyOptions{
+ Roots: tlsConfig.RootCAs,
+ CurrentTime: time.Now(),
+ DNSName: "",
+ Intermediates: x509.NewCertPool(),
+ }
+
+ certs := tlsConn.ConnectionState().PeerCertificates
+ for i, cert := range certs {
+ if i == 0 {
+ continue
+ }
+ opts.Intermediates.AddCert(cert)
+ }
+
+ _, err = certs[0].Verify(opts)
+ if err != nil {
+ tlsConn.Close()
+ return nil, err
+ }
+
+ return tlsConn, err
+}
diff --git a/vendor/git.torproject.org/pluggable-transports/goptlib.git/COPYING b/vendor/git.torproject.org/pluggable-transports/goptlib.git/COPYING
new file mode 100644
index 0000000..0e259d4
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/goptlib.git/COPYING
@@ -0,0 +1,121 @@
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+ HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse of data
+ in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation
+ thereof, including any amended or successor version of such
+ directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy, or
+ the present or absence of errors, whether or not discoverable, all to
+ the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person's Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the
+ Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to
+ this CC0 or use of the Work.
diff --git a/vendor/git.torproject.org/pluggable-transports/goptlib.git/README b/vendor/git.torproject.org/pluggable-transports/goptlib.git/README
new file mode 100644
index 0000000..dc605d1
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/goptlib.git/README
@@ -0,0 +1,27 @@
+goptlib is a library for writing Tor pluggable transports in Go.
+
+https://spec.torproject.org/pt-spec
+https://gitweb.torproject.org/torspec.git/tree/proposals/196-transport-control-ports.txt
+https://gitweb.torproject.org/torspec.git/tree/proposals/217-ext-orport-auth.txt
+https://gitweb.torproject.org/torspec.git/tree/proposals/232-pluggable-transports-through-proxy.txt
+
+To download a copy of the library into $GOPATH:
+ go get git.torproject.org/pluggable-transports/goptlib.git
+
+See the included example programs for examples of how to use the
+library. To build them, enter their directory and run "go build".
+ examples/dummy-client/dummy-client.go
+ examples/dummy-server/dummy-server.go
+The recommended way to start writing a new transport plugin is to copy
+dummy-client or dummy-server and make changes to it.
+
+There is browseable documentation here:
+https://godoc.org/git.torproject.org/pluggable-transports/goptlib.git
+
+Report bugs to the tor-dev@lists.torproject.org mailing list or to the
+bug tracker at https://trac.torproject.org/projects/tor.
+
+To the extent possible under law, the authors have dedicated all
+copyright and related and neighboring rights to this software to the
+public domain worldwide. This software is distributed without any
+warranty. See COPYING.
diff --git a/vendor/git.torproject.org/pluggable-transports/goptlib.git/args.go b/vendor/git.torproject.org/pluggable-transports/goptlib.git/args.go
new file mode 100644
index 0000000..c50bc93
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/goptlib.git/args.go
@@ -0,0 +1,219 @@
+package pt
+
+import (
+ "bytes"
+ "fmt"
+ "sort"
+ "strings"
+)
+
+// Key–value mappings for the representation of client and server options.
+
+// Args maps a string key to a list of values. It is similar to url.Values.
+type Args map[string][]string
+
+// Get the first value associated with the given key. If there are any values
+// associated with the key, the value return has the value and ok is set to
+// true. If there are no values for the given key, value is "" and ok is false.
+// If you need access to multiple values, use the map directly.
+func (args Args) Get(key string) (value string, ok bool) {
+ if args == nil {
+ return "", false
+ }
+ vals, ok := args[key]
+ if !ok || len(vals) == 0 {
+ return "", false
+ }
+ return vals[0], true
+}
+
+// Append value to the list of values for key.
+func (args Args) Add(key, value string) {
+ args[key] = append(args[key], value)
+}
+
+// Return the index of the next unescaped byte in s that is in the term set, or
+// else the length of the string if no terminators appear. Additionally return
+// the unescaped string up to the returned index.
+func indexUnescaped(s string, term []byte) (int, string, error) {
+ var i int
+ unesc := make([]byte, 0)
+ for i = 0; i < len(s); i++ {
+ b := s[i]
+ // A terminator byte?
+ if bytes.IndexByte(term, b) != -1 {
+ break
+ }
+ if b == '\\' {
+ i++
+ if i >= len(s) {
+ return 0, "", fmt.Errorf("nothing following final escape in %q", s)
+ }
+ b = s[i]
+ }
+ unesc = append(unesc, b)
+ }
+ return i, string(unesc), nil
+}
+
+// Parse a name–value mapping as from an encoded SOCKS username/password.
+//
+// "First the '=' formatted arguments MUST be escaped, such that all
+// backslash, equal sign, and semicolon characters are escaped with a
+// backslash."
+func parseClientParameters(s string) (args Args, err error) {
+ args = make(Args)
+ if len(s) == 0 {
+ return
+ }
+ i := 0
+ for {
+ var key, value string
+ var offset, begin int
+
+ begin = i
+ // Read the key.
+ offset, key, err = indexUnescaped(s[i:], []byte{'=', ';'})
+ if err != nil {
+ return
+ }
+ i += offset
+ // End of string or no equals sign?
+ if i >= len(s) || s[i] != '=' {
+ err = fmt.Errorf("no equals sign in %q", s[begin:i])
+ return
+ }
+ // Skip the equals sign.
+ i++
+ // Read the value.
+ offset, value, err = indexUnescaped(s[i:], []byte{';'})
+ if err != nil {
+ return
+ }
+ i += offset
+ if len(key) == 0 {
+ err = fmt.Errorf("empty key in %q", s[begin:i])
+ return
+ }
+ args.Add(key, value)
+ if i >= len(s) {
+ break
+ }
+ // Skip the semicolon.
+ i++
+ }
+ return args, nil
+}
+
+// Parse a transport–name–value mapping as from TOR_PT_SERVER_TRANSPORT_OPTIONS.
+//
+// "...a semicolon-separated list of : pairs, where is a PT
+// name and is a k=v string value with options that are to be passed to
+// the transport. Colons, semicolons, equal signs and backslashes must be
+// escaped with a backslash."
+// Example: scramblesuit:key=banana;automata:rule=110;automata:depth=3
+func parseServerTransportOptions(s string) (opts map[string]Args, err error) {
+ opts = make(map[string]Args)
+ if len(s) == 0 {
+ return
+ }
+ i := 0
+ for {
+ var methodName, key, value string
+ var offset, begin int
+
+ begin = i
+ // Read the method name.
+ offset, methodName, err = indexUnescaped(s[i:], []byte{':', '=', ';'})
+ if err != nil {
+ return
+ }
+ i += offset
+ // End of string or no colon?
+ if i >= len(s) || s[i] != ':' {
+ err = fmt.Errorf("no colon in %q", s[begin:i])
+ return
+ }
+ // Skip the colon.
+ i++
+ // Read the key.
+ offset, key, err = indexUnescaped(s[i:], []byte{'=', ';'})
+ if err != nil {
+ return
+ }
+ i += offset
+ // End of string or no equals sign?
+ if i >= len(s) || s[i] != '=' {
+ err = fmt.Errorf("no equals sign in %q", s[begin:i])
+ return
+ }
+ // Skip the equals sign.
+ i++
+ // Read the value.
+ offset, value, err = indexUnescaped(s[i:], []byte{';'})
+ if err != nil {
+ return
+ }
+ i += offset
+ if len(methodName) == 0 {
+ err = fmt.Errorf("empty method name in %q", s[begin:i])
+ return
+ }
+ if len(key) == 0 {
+ err = fmt.Errorf("empty key in %q", s[begin:i])
+ return
+ }
+ if opts[methodName] == nil {
+ opts[methodName] = make(Args)
+ }
+ opts[methodName].Add(key, value)
+ if i >= len(s) {
+ break
+ }
+ // Skip the semicolon.
+ i++
+ }
+ return opts, nil
+}
+
+// Escape backslashes and all the bytes that are in set.
+func backslashEscape(s string, set []byte) string {
+ var buf bytes.Buffer
+ for _, b := range []byte(s) {
+ if b == '\\' || bytes.IndexByte(set, b) != -1 {
+ buf.WriteByte('\\')
+ }
+ buf.WriteByte(b)
+ }
+ return buf.String()
+}
+
+// Encode a name–value mapping so that it is suitable to go in the ARGS option
+// of an SMETHOD line. The output is sorted by key. The "ARGS:" prefix is not
+// added.
+//
+// "Equal signs and commas [and backslashes] MUST be escaped with a backslash."
+func encodeSmethodArgs(args Args) string {
+ if args == nil {
+ return ""
+ }
+
+ keys := make([]string, 0, len(args))
+ for key := range args {
+ keys = append(keys, key)
+ }
+ sort.Strings(keys)
+
+ escape := func(s string) string {
+ return backslashEscape(s, []byte{'=', ','})
+ }
+
+ var pairs []string
+ for _, key := range keys {
+ for _, value := range args[key] {
+ pairs = append(pairs, escape(key)+"="+escape(value))
+ }
+ }
+
+ return strings.Join(pairs, ",")
+}
diff --git a/vendor/git.torproject.org/pluggable-transports/goptlib.git/pt.go b/vendor/git.torproject.org/pluggable-transports/goptlib.git/pt.go
new file mode 100644
index 0000000..cc0ed8c
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/goptlib.git/pt.go
@@ -0,0 +1,949 @@
+// Package pt implements the Tor pluggable transports specification.
+//
+// Sample client usage:
+// var ptInfo pt.ClientInfo
+// ...
+// func handler(conn *pt.SocksConn) error {
+// defer conn.Close()
+// remote, err := net.Dial("tcp", conn.Req.Target)
+// if err != nil {
+// conn.Reject()
+// return err
+// }
+// defer remote.Close()
+// err = conn.Grant(remote.RemoteAddr().(*net.TCPAddr))
+// if err != nil {
+// return err
+// }
+// // do something with conn and remote.
+// return nil
+// }
+// func acceptLoop(ln *pt.SocksListener) error {
+// defer ln.Close()
+// for {
+// conn, err := ln.AcceptSocks()
+// if err != nil {
+// if e, ok := err.(net.Error); ok && e.Temporary() {
+// continue
+// }
+// return err
+// }
+// go handler(conn)
+// }
+// return nil
+// }
+// ...
+// func main() {
+// var err error
+// ptInfo, err = pt.ClientSetup(nil)
+// if err != nil {
+// os.Exit(1)
+// }
+// if ptInfo.ProxyURL != nil {
+// // you need to interpret the proxy URL yourself
+// // call pt.ProxyDone instead if it's a type you understand
+// pt.ProxyError(fmt.Sprintf("proxy %s is not supported", ptInfo.ProxyURL))
+// os.Exit(1)
+// }
+// for _, methodName := range ptInfo.MethodNames {
+// switch methodName {
+// case "foo":
+// ln, err := pt.ListenSocks("tcp", "127.0.0.1:0")
+// if err != nil {
+// pt.CmethodError(methodName, err.Error())
+// break
+// }
+// go acceptLoop(ln)
+// pt.Cmethod(methodName, ln.Version(), ln.Addr())
+// default:
+// pt.CmethodError(methodName, "no such method")
+// }
+// }
+// pt.CmethodsDone()
+// }
+//
+// Sample server usage:
+// var ptInfo pt.ServerInfo
+// ...
+// func handler(conn net.Conn) error {
+// defer conn.Close()
+// or, err := pt.DialOr(&ptInfo, conn.RemoteAddr().String(), "foo")
+// if err != nil {
+// return
+// }
+// defer or.Close()
+// // do something with or and conn
+// return nil
+// }
+// func acceptLoop(ln net.Listener) error {
+// defer ln.Close()
+// for {
+// conn, err := ln.Accept()
+// if err != nil {
+// if e, ok := err.(net.Error); ok && e.Temporary() {
+// continue
+// }
+// return err
+// }
+// go handler(conn)
+// }
+// return nil
+// }
+// ...
+// func main() {
+// var err error
+// ptInfo, err = pt.ServerSetup(nil)
+// if err != nil {
+// os.Exit(1)
+// }
+// for _, bindaddr := range ptInfo.Bindaddrs {
+// switch bindaddr.MethodName {
+// case "foo":
+// ln, err := net.ListenTCP("tcp", bindaddr.Addr)
+// if err != nil {
+// pt.SmethodError(bindaddr.MethodName, err.Error())
+// break
+// }
+// go acceptLoop(ln)
+// pt.Smethod(bindaddr.MethodName, ln.Addr())
+// default:
+// pt.SmethodError(bindaddr.MethodName, "no such method")
+// }
+// }
+// pt.SmethodsDone()
+// }
+//
+// Some additional care is needed to handle signals and shutdown properly. See
+// the example programs dummy-client and dummy-server.
+//
+// Tor pluggable transports specification:
+// https://spec.torproject.org/pt-spec
+//
+// Extended ORPort:
+// https://gitweb.torproject.org/torspec.git/tree/proposals/196-transport-control-ports.txt
+//
+// Extended ORPort Authentication:
+// https://gitweb.torproject.org/torspec.git/tree/proposals/217-ext-orport-auth.txt
+//
+// Pluggable Transport through SOCKS proxy:
+// https://gitweb.torproject.org/torspec.git/tree/proposals/232-pluggable-transports-through-proxy.txt
+//
+// The package implements a SOCKS5 server sufficient for a Tor client transport
+// plugin.
+//
+// https://www.ietf.org/rfc/rfc1928.txt
+// https://www.ietf.org/rfc/rfc1929.txt
+package pt
+
+import (
+ "bytes"
+ "crypto/hmac"
+ "crypto/rand"
+ "crypto/sha256"
+ "crypto/subtle"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "net"
+ "net/url"
+ "os"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// This type wraps a Write method and calls Sync after each Write.
+type syncWriter struct {
+ *os.File
+}
+
+// Call File.Write and then Sync. An error is returned if either operation
+// returns an error.
+func (w syncWriter) Write(p []byte) (n int, err error) {
+ n, err = w.File.Write(p)
+ if err != nil {
+ return
+ }
+ err = w.Sync()
+ return
+}
+
+// Writer to which pluggable transports negotiation messages are written. It
+// defaults to a Writer that writes to os.Stdout and calls Sync after each
+// write.
+//
+// You may, for example, log pluggable transports messages by defining a Writer
+// that logs what is written to it:
+// type logWriteWrapper struct {
+// io.Writer
+// }
+//
+// func (w logWriteWrapper) Write(p []byte) (int, error) {
+// log.Print(string(p))
+// return w.Writer.Write(p)
+// }
+// and then redefining Stdout:
+// pt.Stdout = logWriteWrapper{pt.Stdout}
+var Stdout io.Writer = syncWriter{os.Stdout}
+
+// Represents an error that can happen during negotiation, for example
+// ENV-ERROR. When an error occurs, we print it to stdout and also pass it up
+// the return chain.
+type ptErr struct {
+ Keyword string
+ Args []string
+}
+
+// Implements the error interface.
+func (err *ptErr) Error() string {
+ return formatline(err.Keyword, err.Args...)
+}
+
+func getenv(key string) string {
+ return os.Getenv(key)
+}
+
+// Returns an ENV-ERROR if the environment variable isn't set.
+func getenvRequired(key string) (string, error) {
+ value := os.Getenv(key)
+ if value == "" {
+ return "", envError(fmt.Sprintf("no %s environment variable", key))
+ }
+ return value, nil
+}
+
+// Returns true iff keyword contains only bytes allowed in a PT→Tor output line
+// keyword.
+// ::=
+func keywordIsSafe(keyword string) bool {
+ for _, b := range []byte(keyword) {
+ switch {
+ case '0' <= b && b <= '9':
+ continue
+ case 'A' <= b && b <= 'Z':
+ continue
+ case 'a' <= b && b <= 'z':
+ continue
+ case b == '-' || b == '_':
+ continue
+ default:
+ return false
+ }
+ }
+ return true
+}
+
+// Returns true iff arg contains only bytes allowed in a PT→Tor output line arg.
+// ::=
+func argIsSafe(arg string) bool {
+ for _, b := range []byte(arg) {
+ if b >= '\x80' || b == '\x00' || b == '\n' {
+ return false
+ }
+ }
+ return true
+}
+
+func formatline(keyword string, v ...string) string {
+ var buf bytes.Buffer
+ if !keywordIsSafe(keyword) {
+ panic(fmt.Sprintf("keyword %q contains forbidden bytes", keyword))
+ }
+ buf.WriteString(keyword)
+ for _, x := range v {
+ if !argIsSafe(x) {
+ panic(fmt.Sprintf("arg %q contains forbidden bytes", x))
+ }
+ buf.WriteString(" " + x)
+ }
+ return buf.String()
+}
+
+// Print a pluggable transports protocol line to Stdout. The line consists of a
+// keyword followed by any number of space-separated arg strings. Panics if
+// there are forbidden bytes in the keyword or the args (pt-spec.txt 2.2.1).
+func line(keyword string, v ...string) {
+ fmt.Fprintln(Stdout, formatline(keyword, v...))
+}
+
+// Emit and return the given error as a ptErr.
+func doError(keyword string, v ...string) *ptErr {
+ line(keyword, v...)
+ return &ptErr{keyword, v}
+}
+
+// Emit an ENV-ERROR line with explanation text. Returns a representation of the
+// error.
+func envError(msg string) error {
+ return doError("ENV-ERROR", msg)
+}
+
+// Emit a VERSION-ERROR line with explanation text. Returns a representation of
+// the error.
+func versionError(msg string) error {
+ return doError("VERSION-ERROR", msg)
+}
+
+// Emit a CMETHOD-ERROR line with explanation text. Returns a representation of
+// the error.
+func CmethodError(methodName, msg string) error {
+ return doError("CMETHOD-ERROR", methodName, msg)
+}
+
+// Emit an SMETHOD-ERROR line with explanation text. Returns a representation of
+// the error.
+func SmethodError(methodName, msg string) error {
+ return doError("SMETHOD-ERROR", methodName, msg)
+}
+
+// Emit a PROXY-ERROR line with explanation text. Returns a representation of
+// the error.
+func ProxyError(msg string) error {
+ return doError("PROXY-ERROR", msg)
+}
+
+// Emit a CMETHOD line. socks must be "socks4" or "socks5". Call this once for
+// each listening client SOCKS port.
+func Cmethod(name string, socks string, addr net.Addr) {
+ line("CMETHOD", name, socks, addr.String())
+}
+
+// Emit a CMETHODS DONE line. Call this after opening all client listeners.
+func CmethodsDone() {
+ line("CMETHODS", "DONE")
+}
+
+// Emit an SMETHOD line. Call this once for each listening server port.
+func Smethod(name string, addr net.Addr) {
+ line("SMETHOD", name, addr.String())
+}
+
+// Emit an SMETHOD line with an ARGS option. args is a name–value mapping that
+// will be added to the server's extrainfo document.
+//
+// This is an example of how to check for a required option:
+// secret, ok := bindaddr.Options.Get("shared-secret")
+// if ok {
+// args := pt.Args{}
+// args.Add("shared-secret", secret)
+// pt.SmethodArgs(bindaddr.MethodName, ln.Addr(), args)
+// } else {
+// pt.SmethodError(bindaddr.MethodName, "need a shared-secret option")
+// }
+// Or, if you just want to echo back the options provided by Tor from the
+// TransportServerOptions configuration,
+// pt.SmethodArgs(bindaddr.MethodName, ln.Addr(), bindaddr.Options)
+func SmethodArgs(name string, addr net.Addr, args Args) {
+ line("SMETHOD", name, addr.String(), "ARGS:"+encodeSmethodArgs(args))
+}
+
+// Emit an SMETHODS DONE line. Call this after opening all server listeners.
+func SmethodsDone() {
+ line("SMETHODS", "DONE")
+}
+
+// Emit a PROXY DONE line. Call this after parsing ClientInfo.ProxyURL.
+func ProxyDone() {
+ fmt.Fprintf(Stdout, "PROXY DONE\n")
+}
+
+// Get a pluggable transports version offered by Tor and understood by us, if
+// any. The only version we understand is "1". This function reads the
+// environment variable TOR_PT_MANAGED_TRANSPORT_VER.
+func getManagedTransportVer() (string, error) {
+ const transportVersion = "1"
+ managedTransportVer, err := getenvRequired("TOR_PT_MANAGED_TRANSPORT_VER")
+ if err != nil {
+ return "", err
+ }
+ for _, offered := range strings.Split(managedTransportVer, ",") {
+ if offered == transportVersion {
+ return offered, nil
+ }
+ }
+ return "", versionError("no-version")
+}
+
+// Return the directory name in the TOR_PT_STATE_LOCATION environment variable,
+// creating it if it doesn't exist. Returns non-nil error if
+// TOR_PT_STATE_LOCATION is not set or if there is an error creating the
+// directory.
+func MakeStateDir() (string, error) {
+ dir, err := getenvRequired("TOR_PT_STATE_LOCATION")
+ if err != nil {
+ return "", err
+ }
+ err = os.MkdirAll(dir, 0700)
+ return dir, err
+}
+
+// Get the list of method names requested by Tor. This function reads the
+// environment variable TOR_PT_CLIENT_TRANSPORTS.
+func getClientTransports() ([]string, error) {
+ clientTransports, err := getenvRequired("TOR_PT_CLIENT_TRANSPORTS")
+ if err != nil {
+ return nil, err
+ }
+ return strings.Split(clientTransports, ","), nil
+}
+
+// Get the upstream proxy URL. Returns nil if no proxy is requested. The
+// function ensures that the Scheme and Host fields are set; i.e., that the URL
+// is absolute. It additionally checks that the Host field contains both a host
+// and a port part. This function reads the environment variable TOR_PT_PROXY.
+//
+// This function doesn't check that the scheme is one of Tor's supported proxy
+// schemes; that is, one of "http", "socks5", or "socks4a". The caller must be
+// able to handle any returned scheme (which may be by calling ProxyError if
+// it doesn't know how to handle the scheme).
+func getProxyURL() (*url.URL, error) {
+ rawurl := os.Getenv("TOR_PT_PROXY")
+ if rawurl == "" {
+ return nil, nil
+ }
+ u, err := url.Parse(rawurl)
+ if err != nil {
+ return nil, err
+ }
+ if u.Scheme == "" {
+ return nil, fmt.Errorf("missing scheme")
+ }
+ if u.Host == "" {
+ return nil, fmt.Errorf("missing authority")
+ }
+ host, port, err := net.SplitHostPort(u.Host)
+ if err != nil {
+ return nil, err
+ }
+ if host == "" {
+ return nil, fmt.Errorf("missing host")
+ }
+ if port == "" {
+ return nil, fmt.Errorf("missing port")
+ }
+ return u, nil
+}
+
+// This structure is returned by ClientSetup. It consists of a list of method
+// names and the upstream proxy URL, if any.
+type ClientInfo struct {
+ MethodNames []string
+ ProxyURL *url.URL
+}
+
+// Check the client pluggable transports environment, emitting an error message
+// and returning a non-nil error if any error is encountered. Returns a
+// ClientInfo struct.
+//
+// If your program needs to know whether to call ClientSetup or ServerSetup
+// (i.e., if the same program can be run as either a client or a server), check
+// whether the TOR_PT_CLIENT_TRANSPORTS environment variable is set:
+// if os.Getenv("TOR_PT_CLIENT_TRANSPORTS") != "" {
+// // Client mode; call pt.ClientSetup.
+// } else {
+// // Server mode; call pt.ServerSetup.
+// }
+//
+// Always pass nil for the unused single parameter. In the past, the parameter
+// was a list of transport names to use in case Tor requested "*". That feature
+// was never implemented and has been removed from the pluggable transports
+// specification.
+// https://bugs.torproject.org/15612
+func ClientSetup(_ []string) (info ClientInfo, err error) {
+ ver, err := getManagedTransportVer()
+ if err != nil {
+ return
+ }
+ line("VERSION", ver)
+
+ info.MethodNames, err = getClientTransports()
+ if err != nil {
+ return
+ }
+
+ info.ProxyURL, err = getProxyURL()
+ if err != nil {
+ return
+ }
+
+ return info, nil
+}
+
+// A combination of a method name and an address, as extracted from
+// TOR_PT_SERVER_BINDADDR.
+type Bindaddr struct {
+ MethodName string
+ Addr *net.TCPAddr
+ // Options from TOR_PT_SERVER_TRANSPORT_OPTIONS that pertain to this
+ // transport.
+ Options Args
+}
+
+func parsePort(portStr string) (int, error) {
+ port, err := strconv.ParseUint(portStr, 10, 16)
+ return int(port), err
+}
+
+// Resolve an address string into a net.TCPAddr. We are a bit more strict than
+// net.ResolveTCPAddr; we don't allow an empty host or port, and the host part
+// must be a literal IP address.
+func resolveAddr(addrStr string) (*net.TCPAddr, error) {
+ ipStr, portStr, err := net.SplitHostPort(addrStr)
+ if err != nil {
+ // Before the fixing of bug #7011, tor doesn't put brackets around IPv6
+ // addresses. Split after the last colon, assuming it is a port
+ // separator, and try adding the brackets.
+ // https://bugs.torproject.org/7011
+ parts := strings.Split(addrStr, ":")
+ if len(parts) <= 2 {
+ return nil, err
+ }
+ addrStr := "[" + strings.Join(parts[:len(parts)-1], ":") + "]:" + parts[len(parts)-1]
+ ipStr, portStr, err = net.SplitHostPort(addrStr)
+ }
+ if err != nil {
+ return nil, err
+ }
+ if ipStr == "" {
+ return nil, net.InvalidAddrError(fmt.Sprintf("address string %q lacks a host part", addrStr))
+ }
+ if portStr == "" {
+ return nil, net.InvalidAddrError(fmt.Sprintf("address string %q lacks a port part", addrStr))
+ }
+ ip := net.ParseIP(ipStr)
+ if ip == nil {
+ return nil, net.InvalidAddrError(fmt.Sprintf("not an IP string: %q", ipStr))
+ }
+ port, err := parsePort(portStr)
+ if err != nil {
+ return nil, err
+ }
+ return &net.TCPAddr{IP: ip, Port: port}, nil
+}
+
+// Return a new slice, the members of which are those members of addrs having a
+// MethodName in methodNames.
+func filterBindaddrs(addrs []Bindaddr, methodNames []string) []Bindaddr {
+ var result []Bindaddr
+
+ for _, ba := range addrs {
+ for _, methodName := range methodNames {
+ if ba.MethodName == methodName {
+ result = append(result, ba)
+ break
+ }
+ }
+ }
+
+ return result
+}
+
+// Return an array of Bindaddrs, being the contents of TOR_PT_SERVER_BINDADDR
+// with keys filtered by TOR_PT_SERVER_TRANSPORTS. Transport-specific options
+// from TOR_PT_SERVER_TRANSPORT_OPTIONS are assigned to the Options member.
+func getServerBindaddrs() ([]Bindaddr, error) {
+ var result []Bindaddr
+
+ // Parse the list of server transport options.
+ serverTransportOptions := getenv("TOR_PT_SERVER_TRANSPORT_OPTIONS")
+ optionsMap, err := parseServerTransportOptions(serverTransportOptions)
+ if err != nil {
+ return nil, envError(fmt.Sprintf("TOR_PT_SERVER_TRANSPORT_OPTIONS: %q: %s", serverTransportOptions, err.Error()))
+ }
+
+ // Get the list of all requested bindaddrs.
+ serverBindaddr, err := getenvRequired("TOR_PT_SERVER_BINDADDR")
+ if err != nil {
+ return nil, err
+ }
+ seenMethods := make(map[string]bool)
+ for _, spec := range strings.Split(serverBindaddr, ",") {
+ var bindaddr Bindaddr
+
+ parts := strings.SplitN(spec, "-", 2)
+ if len(parts) != 2 {
+ return nil, envError(fmt.Sprintf("TOR_PT_SERVER_BINDADDR: %q: doesn't contain \"-\"", spec))
+ }
+ bindaddr.MethodName = parts[0]
+ // Check for duplicate method names: "Applications MUST NOT set
+ // more than one : pair per PT name."
+ if seenMethods[bindaddr.MethodName] {
+ return nil, envError(fmt.Sprintf("TOR_PT_SERVER_BINDADDR: %q: duplicate method name %q", spec, bindaddr.MethodName))
+ }
+ seenMethods[bindaddr.MethodName] = true
+ addr, err := resolveAddr(parts[1])
+ if err != nil {
+ return nil, envError(fmt.Sprintf("TOR_PT_SERVER_BINDADDR: %q: %s", spec, err.Error()))
+ }
+ bindaddr.Addr = addr
+ bindaddr.Options = optionsMap[bindaddr.MethodName]
+ result = append(result, bindaddr)
+ }
+
+ // Filter by TOR_PT_SERVER_TRANSPORTS.
+ serverTransports, err := getenvRequired("TOR_PT_SERVER_TRANSPORTS")
+ if err != nil {
+ return nil, err
+ }
+ result = filterBindaddrs(result, strings.Split(serverTransports, ","))
+
+ return result, nil
+}
+
+func readAuthCookie(f io.Reader) ([]byte, error) {
+ authCookieHeader := []byte("! Extended ORPort Auth Cookie !\x0a")
+ buf := make([]byte, 64)
+
+ n, err := io.ReadFull(f, buf)
+ if err != nil {
+ return nil, err
+ }
+ // Check that the file ends here.
+ n, err = f.Read(make([]byte, 1))
+ if n != 0 {
+ return nil, fmt.Errorf("file is longer than 64 bytes")
+ } else if err != io.EOF {
+ return nil, fmt.Errorf("did not find EOF at end of file")
+ }
+ header := buf[0:32]
+ cookie := buf[32:64]
+ if subtle.ConstantTimeCompare(header, authCookieHeader) != 1 {
+ return nil, fmt.Errorf("missing auth cookie header")
+ }
+
+ return cookie, nil
+}
+
+// Read and validate the contents of an auth cookie file. Returns the 32-byte
+// cookie. See section 4.2.1.2 of 217-ext-orport-auth.txt.
+func readAuthCookieFile(filename string) ([]byte, error) {
+ f, err := os.Open(filename)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ return readAuthCookie(f)
+}
+
+// This structure is returned by ServerSetup. It consists of a list of
+// Bindaddrs, an address for the ORPort, an address for the extended ORPort (if
+// any), and an authentication cookie (if any).
+type ServerInfo struct {
+ Bindaddrs []Bindaddr
+ OrAddr *net.TCPAddr
+ ExtendedOrAddr *net.TCPAddr
+ AuthCookiePath string
+}
+
+// Check the server pluggable transports environment, emitting an error message
+// and returning a non-nil error if any error is encountered. Resolves the
+// various requested bind addresses, the server ORPort and extended ORPort, and
+// reads the auth cookie file. Returns a ServerInfo struct.
+//
+// If your program needs to know whether to call ClientSetup or ServerSetup
+// (i.e., if the same program can be run as either a client or a server), check
+// whether the TOR_PT_CLIENT_TRANSPORTS environment variable is set:
+// if os.Getenv("TOR_PT_CLIENT_TRANSPORTS") != "" {
+// // Client mode; call pt.ClientSetup.
+// } else {
+// // Server mode; call pt.ServerSetup.
+// }
+//
+// Always pass nil for the unused single parameter. In the past, the parameter
+// was a list of transport names to use in case Tor requested "*". That feature
+// was never implemented and has been removed from the pluggable transports
+// specification.
+// https://bugs.torproject.org/15612
+func ServerSetup(_ []string) (info ServerInfo, err error) {
+ ver, err := getManagedTransportVer()
+ if err != nil {
+ return
+ }
+ line("VERSION", ver)
+
+ info.Bindaddrs, err = getServerBindaddrs()
+ if err != nil {
+ return
+ }
+
+ orPort := getenv("TOR_PT_ORPORT")
+ if orPort != "" {
+ info.OrAddr, err = resolveAddr(orPort)
+ if err != nil {
+ err = envError(fmt.Sprintf("cannot resolve TOR_PT_ORPORT %q: %s", orPort, err.Error()))
+ return
+ }
+ }
+
+ info.AuthCookiePath = getenv("TOR_PT_AUTH_COOKIE_FILE")
+
+ extendedOrPort := getenv("TOR_PT_EXTENDED_SERVER_PORT")
+ if extendedOrPort != "" {
+ if info.AuthCookiePath == "" {
+ err = envError("need TOR_PT_AUTH_COOKIE_FILE environment variable with TOR_PT_EXTENDED_SERVER_PORT")
+ return
+ }
+ info.ExtendedOrAddr, err = resolveAddr(extendedOrPort)
+ if err != nil {
+ err = envError(fmt.Sprintf("cannot resolve TOR_PT_EXTENDED_SERVER_PORT %q: %s", extendedOrPort, err.Error()))
+ return
+ }
+ }
+
+ // Need either OrAddr or ExtendedOrAddr.
+ if info.OrAddr == nil && info.ExtendedOrAddr == nil {
+ err = envError("need TOR_PT_ORPORT or TOR_PT_EXTENDED_SERVER_PORT environment variable")
+ return
+ }
+
+ return info, nil
+}
+
+// See 217-ext-orport-auth.txt section 4.2.1.3.
+func computeServerHash(authCookie, clientNonce, serverNonce []byte) []byte {
+ h := hmac.New(sha256.New, authCookie)
+ io.WriteString(h, "ExtORPort authentication server-to-client hash")
+ h.Write(clientNonce)
+ h.Write(serverNonce)
+ return h.Sum([]byte{})
+}
+
+// See 217-ext-orport-auth.txt section 4.2.1.3.
+func computeClientHash(authCookie, clientNonce, serverNonce []byte) []byte {
+ h := hmac.New(sha256.New, authCookie)
+ io.WriteString(h, "ExtORPort authentication client-to-server hash")
+ h.Write(clientNonce)
+ h.Write(serverNonce)
+ return h.Sum([]byte{})
+}
+
+func extOrPortAuthenticate(s io.ReadWriter, info *ServerInfo) error {
+ // Read auth types. 217-ext-orport-auth.txt section 4.1.
+ var authTypes [256]bool
+ var count int
+ for count = 0; count < 256; count++ {
+ buf := make([]byte, 1)
+ _, err := io.ReadFull(s, buf)
+ if err != nil {
+ return err
+ }
+ b := buf[0]
+ if b == 0 {
+ break
+ }
+ authTypes[b] = true
+ }
+ if count >= 256 {
+ return fmt.Errorf("read 256 auth types without seeing \\x00")
+ }
+
+ // We support only type 1, SAFE_COOKIE.
+ if !authTypes[1] {
+ return fmt.Errorf("server didn't offer auth type 1")
+ }
+ _, err := s.Write([]byte{1})
+ if err != nil {
+ return err
+ }
+
+ clientNonce := make([]byte, 32)
+ clientHash := make([]byte, 32)
+ serverNonce := make([]byte, 32)
+ serverHash := make([]byte, 32)
+
+ _, err = io.ReadFull(rand.Reader, clientNonce)
+ if err != nil {
+ return err
+ }
+ _, err = s.Write(clientNonce)
+ if err != nil {
+ return err
+ }
+
+ _, err = io.ReadFull(s, serverHash)
+ if err != nil {
+ return err
+ }
+ _, err = io.ReadFull(s, serverNonce)
+ if err != nil {
+ return err
+ }
+
+ // Work around tor bug #15240 where the auth cookie is generated after
+ // pluggable transports are launched, leading to a stale cookie getting
+ // cached forever if it is only read once as part of ServerSetup.
+ // https://bugs.torproject.org/15240
+ authCookie, err := readAuthCookieFile(info.AuthCookiePath)
+ if err != nil {
+ return fmt.Errorf("error reading TOR_PT_AUTH_COOKIE_FILE %q: %s", info.AuthCookiePath, err.Error())
+ }
+
+ expectedServerHash := computeServerHash(authCookie, clientNonce, serverNonce)
+ if subtle.ConstantTimeCompare(serverHash, expectedServerHash) != 1 {
+ return fmt.Errorf("mismatch in server hash")
+ }
+
+ clientHash = computeClientHash(authCookie, clientNonce, serverNonce)
+ _, err = s.Write(clientHash)
+ if err != nil {
+ return err
+ }
+
+ status := make([]byte, 1)
+ _, err = io.ReadFull(s, status)
+ if err != nil {
+ return err
+ }
+ if status[0] != 1 {
+ return fmt.Errorf("server rejected authentication")
+ }
+
+ return nil
+}
+
+// See section 3.1.1 of 196-transport-control-ports.txt.
+const (
+ extOrCmdDone = 0x0000
+ extOrCmdUserAddr = 0x0001
+ extOrCmdTransport = 0x0002
+ extOrCmdOkay = 0x1000
+ extOrCmdDeny = 0x1001
+)
+
+func extOrPortSendCommand(s io.Writer, cmd uint16, body []byte) error {
+ var buf bytes.Buffer
+ if len(body) > 65535 {
+ return fmt.Errorf("body length %d exceeds maximum of 65535", len(body))
+ }
+ err := binary.Write(&buf, binary.BigEndian, cmd)
+ if err != nil {
+ return err
+ }
+ err = binary.Write(&buf, binary.BigEndian, uint16(len(body)))
+ if err != nil {
+ return err
+ }
+ err = binary.Write(&buf, binary.BigEndian, body)
+ if err != nil {
+ return err
+ }
+ _, err = s.Write(buf.Bytes())
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Send a USERADDR command on s. See section 3.1.2.1 of
+// 196-transport-control-ports.txt.
+func extOrPortSendUserAddr(s io.Writer, addr string) error {
+ return extOrPortSendCommand(s, extOrCmdUserAddr, []byte(addr))
+}
+
+// Send a TRANSPORT command on s. See section 3.1.2.2 of
+// 196-transport-control-ports.txt.
+func extOrPortSendTransport(s io.Writer, methodName string) error {
+ return extOrPortSendCommand(s, extOrCmdTransport, []byte(methodName))
+}
+
+// Send a DONE command on s. See section 3.1 of 196-transport-control-ports.txt.
+func extOrPortSendDone(s io.Writer) error {
+ return extOrPortSendCommand(s, extOrCmdDone, []byte{})
+}
+
+func extOrPortRecvCommand(s io.Reader) (cmd uint16, body []byte, err error) {
+ var bodyLen uint16
+ data := make([]byte, 4)
+
+ _, err = io.ReadFull(s, data)
+ if err != nil {
+ return
+ }
+ buf := bytes.NewBuffer(data)
+ err = binary.Read(buf, binary.BigEndian, &cmd)
+ if err != nil {
+ return
+ }
+ err = binary.Read(buf, binary.BigEndian, &bodyLen)
+ if err != nil {
+ return
+ }
+ body = make([]byte, bodyLen)
+ _, err = io.ReadFull(s, body)
+ if err != nil {
+ return
+ }
+
+ return cmd, body, err
+}
+
+// Send USERADDR and TRANSPORT commands followed by a DONE command. Wait for an
+// OKAY or DENY response command from the server. If addr or methodName is "",
+// the corresponding command is not sent. Returns nil if and only if OKAY is
+// received.
+func extOrPortSetup(s io.ReadWriter, addr, methodName string) error {
+ var err error
+
+ if addr != "" {
+ err = extOrPortSendUserAddr(s, addr)
+ if err != nil {
+ return err
+ }
+ }
+ if methodName != "" {
+ err = extOrPortSendTransport(s, methodName)
+ if err != nil {
+ return err
+ }
+ }
+ err = extOrPortSendDone(s)
+ if err != nil {
+ return err
+ }
+ cmd, _, err := extOrPortRecvCommand(s)
+ if err != nil {
+ return err
+ }
+ if cmd == extOrCmdDeny {
+ return fmt.Errorf("server returned DENY after our USERADDR and DONE")
+ } else if cmd != extOrCmdOkay {
+ return fmt.Errorf("server returned unknown command 0x%04x after our USERADDR and DONE", cmd)
+ }
+
+ return nil
+}
+
+// Dial info.ExtendedOrAddr if defined, or else info.OrAddr, and return an open
+// *net.TCPConn. If connecting to the extended OR port, extended OR port
+// authentication à la 217-ext-orport-auth.txt is done before returning; an
+// error is returned if authentication fails.
+//
+// The addr and methodName arguments are put in USERADDR and TRANSPORT ExtOrPort
+// commands, respectively. If either is "", the corresponding command is not
+// sent.
+func DialOr(info *ServerInfo, addr, methodName string) (*net.TCPConn, error) {
+ if info.ExtendedOrAddr == nil || info.AuthCookiePath == "" {
+ return net.DialTCP("tcp", nil, info.OrAddr)
+ }
+
+ s, err := net.DialTCP("tcp", nil, info.ExtendedOrAddr)
+ if err != nil {
+ return nil, err
+ }
+ s.SetDeadline(time.Now().Add(5 * time.Second))
+ err = extOrPortAuthenticate(s, info)
+ if err != nil {
+ s.Close()
+ return nil, err
+ }
+ err = extOrPortSetup(s, addr, methodName)
+ if err != nil {
+ s.Close()
+ return nil, err
+ }
+ s.SetDeadline(time.Time{})
+
+ return s, nil
+}
diff --git a/vendor/git.torproject.org/pluggable-transports/goptlib.git/socks.go b/vendor/git.torproject.org/pluggable-transports/goptlib.git/socks.go
new file mode 100644
index 0000000..29827d9
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/goptlib.git/socks.go
@@ -0,0 +1,507 @@
+package pt
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "net"
+ "time"
+)
+
+const (
+ socksVersion = 0x05
+
+ socksAuthNoneRequired = 0x00
+ socksAuthUsernamePassword = 0x02
+ socksAuthNoAcceptableMethods = 0xff
+
+ socksCmdConnect = 0x01
+ socksRsv = 0x00
+
+ socksAtypeV4 = 0x01
+ socksAtypeDomainName = 0x03
+ socksAtypeV6 = 0x04
+
+ socksAuthRFC1929Ver = 0x01
+ socksAuthRFC1929Success = 0x00
+ socksAuthRFC1929Fail = 0x01
+
+ socksRepSucceeded = 0x00
+ // "general SOCKS server failure"
+ SocksRepGeneralFailure = 0x01
+ // "connection not allowed by ruleset"
+ SocksRepConnectionNotAllowed = 0x02
+ // "Network unreachable"
+ SocksRepNetworkUnreachable = 0x03
+ // "Host unreachable"
+ SocksRepHostUnreachable = 0x04
+ // "Connection refused"
+ SocksRepConnectionRefused = 0x05
+ // "TTL expired"
+ SocksRepTTLExpired = 0x06
+ // "Command not supported"
+ SocksRepCommandNotSupported = 0x07
+ // "Address type not supported"
+ SocksRepAddressNotSupported = 0x08
+)
+
+// Put a sanity timeout on how long we wait for a SOCKS request.
+const socksRequestTimeout = 5 * time.Second
+
+// SocksRequest describes a SOCKS request.
+type SocksRequest struct {
+ // The endpoint requested by the client as a "host:port" string.
+ Target string
+ // The userid string sent by the client.
+ Username string
+ // The password string sent by the client.
+ Password string
+ // The parsed contents of Username as a key–value mapping.
+ Args Args
+}
+
+// SocksConn encapsulates a net.Conn and information associated with a SOCKS request.
+type SocksConn struct {
+ net.Conn
+ Req SocksRequest
+}
+
+// Send a message to the proxy client that access to the given address is
+// granted. Addr is ignored, and "0.0.0.0:0" is always sent back for
+// BND.ADDR/BND.PORT in the SOCKS response.
+func (conn *SocksConn) Grant(addr *net.TCPAddr) error {
+ return sendSocks5ResponseGranted(conn)
+}
+
+// Send a message to the proxy client that access was rejected or failed. This
+// sends back a "General Failure" error code. RejectReason should be used if
+// more specific error reporting is desired.
+func (conn *SocksConn) Reject() error {
+ return conn.RejectReason(SocksRepGeneralFailure)
+}
+
+// Send a message to the proxy client that access was rejected, with the
+// specific error code indicating the reason behind the rejection.
+func (conn *SocksConn) RejectReason(reason byte) error {
+ return sendSocks5ResponseRejected(conn, reason)
+}
+
+// SocksListener wraps a net.Listener in order to read a SOCKS request on Accept.
+//
+// func handleConn(conn *pt.SocksConn) error {
+// defer conn.Close()
+// remote, err := net.Dial("tcp", conn.Req.Target)
+// if err != nil {
+// conn.Reject()
+// return err
+// }
+// defer remote.Close()
+// err = conn.Grant(remote.RemoteAddr().(*net.TCPAddr))
+// if err != nil {
+// return err
+// }
+// // do something with conn and remote
+// return nil
+// }
+// ...
+// ln, err := pt.ListenSocks("tcp", "127.0.0.1:0")
+// if err != nil {
+// panic(err.Error())
+// }
+// for {
+// conn, err := ln.AcceptSocks()
+// if err != nil {
+// log.Printf("accept error: %s", err)
+// if e, ok := err.(net.Error); ok && e.Temporary() {
+// continue
+// }
+// break
+// }
+// go handleConn(conn)
+// }
+type SocksListener struct {
+ net.Listener
+}
+
+// Open a net.Listener according to network and laddr, and return it as a
+// SocksListener.
+func ListenSocks(network, laddr string) (*SocksListener, error) {
+ ln, err := net.Listen(network, laddr)
+ if err != nil {
+ return nil, err
+ }
+ return NewSocksListener(ln), nil
+}
+
+// Create a new SocksListener wrapping the given net.Listener.
+func NewSocksListener(ln net.Listener) *SocksListener {
+ return &SocksListener{ln}
+}
+
+// Accept is the same as AcceptSocks, except that it returns a generic net.Conn.
+// It is present for the sake of satisfying the net.Listener interface.
+func (ln *SocksListener) Accept() (net.Conn, error) {
+ return ln.AcceptSocks()
+}
+
+// Call Accept on the wrapped net.Listener, do SOCKS negotiation, and return a
+// SocksConn. After accepting, you must call either conn.Grant or conn.Reject
+// (presumably after trying to connect to conn.Req.Target).
+//
+// Errors returned by AcceptSocks may be temporary (for example, EOF while
+// reading the request, or a badly formatted userid string), or permanent (e.g.,
+// the underlying socket is closed). You can determine whether an error is
+// temporary and take appropriate action with a type conversion to net.Error.
+// For example:
+//
+// for {
+// conn, err := ln.AcceptSocks()
+// if err != nil {
+// if e, ok := err.(net.Error); ok && e.Temporary() {
+// log.Printf("temporary accept error; trying again: %s", err)
+// continue
+// }
+// log.Printf("permanent accept error; giving up: %s", err)
+// break
+// }
+// go handleConn(conn)
+// }
+func (ln *SocksListener) AcceptSocks() (*SocksConn, error) {
+retry:
+ c, err := ln.Listener.Accept()
+ if err != nil {
+ return nil, err
+ }
+ conn := new(SocksConn)
+ conn.Conn = c
+ err = conn.SetDeadline(time.Now().Add(socksRequestTimeout))
+ if err != nil {
+ conn.Close()
+ goto retry
+ }
+ conn.Req, err = socks5Handshake(conn)
+ if err != nil {
+ conn.Close()
+ goto retry
+ }
+ err = conn.SetDeadline(time.Time{})
+ if err != nil {
+ conn.Close()
+ goto retry
+ }
+ return conn, nil
+}
+
+// Returns "socks5", suitable to be included in a call to Cmethod.
+func (ln *SocksListener) Version() string {
+ return "socks5"
+}
+
+// socks5handshake conducts the SOCKS5 handshake up to the point where the
+// client command is read and the proxy must open the outgoing connection.
+// Returns a SocksRequest.
+func socks5Handshake(s io.ReadWriter) (req SocksRequest, err error) {
+ rw := bufio.NewReadWriter(bufio.NewReader(s), bufio.NewWriter(s))
+
+ // Negotiate the authentication method.
+ var method byte
+ if method, err = socksNegotiateAuth(rw); err != nil {
+ return
+ }
+
+ // Authenticate the client.
+ if err = socksAuthenticate(rw, method, &req); err != nil {
+ return
+ }
+
+ // Read the command.
+ err = socksReadCommand(rw, &req)
+ return
+}
+
+// socksNegotiateAuth negotiates the authentication method and returns the
+// selected method as a byte. On negotiation failures an error is returned.
+func socksNegotiateAuth(rw *bufio.ReadWriter) (method byte, err error) {
+ // Validate the version.
+ if err = socksReadByteVerify(rw, "version", socksVersion); err != nil {
+ return
+ }
+
+ // Read the number of methods.
+ var nmethods byte
+ if nmethods, err = socksReadByte(rw); err != nil {
+ return
+ }
+
+ // Read the methods.
+ var methods []byte
+ if methods, err = socksReadBytes(rw, int(nmethods)); err != nil {
+ return
+ }
+
+ // Pick the most "suitable" method.
+ method = socksAuthNoAcceptableMethods
+ for _, m := range methods {
+ switch m {
+ case socksAuthNoneRequired:
+ // Pick Username/Password over None if the client happens to
+ // send both.
+ if method == socksAuthNoAcceptableMethods {
+ method = m
+ }
+
+ case socksAuthUsernamePassword:
+ method = m
+ }
+ }
+
+ // Send the negotiated method.
+ var msg [2]byte
+ msg[0] = socksVersion
+ msg[1] = method
+ if _, err = rw.Writer.Write(msg[:]); err != nil {
+ return
+ }
+
+ if err = socksFlushBuffers(rw); err != nil {
+ return
+ }
+ return
+}
+
+// socksAuthenticate authenticates the client via the chosen authentication
+// mechanism.
+func socksAuthenticate(rw *bufio.ReadWriter, method byte, req *SocksRequest) (err error) {
+ switch method {
+ case socksAuthNoneRequired:
+ // Straight into reading the connect.
+
+ case socksAuthUsernamePassword:
+ if err = socksAuthRFC1929(rw, req); err != nil {
+ return
+ }
+
+ case socksAuthNoAcceptableMethods:
+ err = fmt.Errorf("SOCKS method select had no compatible methods")
+ return
+
+ default:
+ err = fmt.Errorf("SOCKS method select picked a unsupported method 0x%02x", method)
+ return
+ }
+
+ if err = socksFlushBuffers(rw); err != nil {
+ return
+ }
+ return
+}
+
+// socksAuthRFC1929 authenticates the client via RFC 1929 username/password
+// auth. As a design decision any valid username/password is accepted as this
+// field is primarily used as an out-of-band argument passing mechanism for
+// pluggable transports.
+func socksAuthRFC1929(rw *bufio.ReadWriter, req *SocksRequest) (err error) {
+ sendErrResp := func() {
+ // Swallow the write/flush error here, we are going to close the
+ // connection and the original failure is more useful.
+ resp := []byte{socksAuthRFC1929Ver, socksAuthRFC1929Fail}
+ rw.Write(resp[:])
+ socksFlushBuffers(rw)
+ }
+
+ // Validate the fixed parts of the command message.
+ if err = socksReadByteVerify(rw, "auth version", socksAuthRFC1929Ver); err != nil {
+ sendErrResp()
+ return
+ }
+
+ // Read the username.
+ var ulen byte
+ if ulen, err = socksReadByte(rw); err != nil {
+ return
+ }
+ if ulen < 1 {
+ sendErrResp()
+ err = fmt.Errorf("RFC1929 username with 0 length")
+ return
+ }
+ var uname []byte
+ if uname, err = socksReadBytes(rw, int(ulen)); err != nil {
+ return
+ }
+ req.Username = string(uname)
+
+ // Read the password.
+ var plen byte
+ if plen, err = socksReadByte(rw); err != nil {
+ return
+ }
+ if plen < 1 {
+ sendErrResp()
+ err = fmt.Errorf("RFC1929 password with 0 length")
+ return
+ }
+ var passwd []byte
+ if passwd, err = socksReadBytes(rw, int(plen)); err != nil {
+ return
+ }
+ if !(plen == 1 && passwd[0] == 0x00) {
+ // tor will set the password to 'NUL' if there are no arguments.
+ req.Password = string(passwd)
+ }
+
+ // Mash the username/password together and parse it as a pluggable
+ // transport argument string.
+ if req.Args, err = parseClientParameters(req.Username + req.Password); err != nil {
+ sendErrResp()
+ } else {
+ resp := []byte{socksAuthRFC1929Ver, socksAuthRFC1929Success}
+ _, err = rw.Write(resp[:])
+ }
+ return
+}
+
+// socksReadCommand reads a SOCKS5 client command and parses out the relevant
+// fields into a SocksRequest. Only CMD_CONNECT is supported.
+func socksReadCommand(rw *bufio.ReadWriter, req *SocksRequest) (err error) {
+ sendErrResp := func(reason byte) {
+ // Swallow errors that occur when writing/flushing the response,
+ // connection will be closed anyway.
+ sendSocks5ResponseRejected(rw, reason)
+ socksFlushBuffers(rw)
+ }
+
+ // Validate the fixed parts of the command message.
+ if err = socksReadByteVerify(rw, "version", socksVersion); err != nil {
+ sendErrResp(SocksRepGeneralFailure)
+ return
+ }
+ if err = socksReadByteVerify(rw, "command", socksCmdConnect); err != nil {
+ sendErrResp(SocksRepCommandNotSupported)
+ return
+ }
+ if err = socksReadByteVerify(rw, "reserved", socksRsv); err != nil {
+ sendErrResp(SocksRepGeneralFailure)
+ return
+ }
+
+ // Read the destination address/port.
+ // XXX: This should probably eventually send socks 5 error messages instead
+ // of rudely closing connections on invalid addresses.
+ var atype byte
+ if atype, err = socksReadByte(rw); err != nil {
+ return
+ }
+ var host string
+ switch atype {
+ case socksAtypeV4:
+ var addr []byte
+ if addr, err = socksReadBytes(rw, net.IPv4len); err != nil {
+ return
+ }
+ host = net.IPv4(addr[0], addr[1], addr[2], addr[3]).String()
+
+ case socksAtypeDomainName:
+ var alen byte
+ if alen, err = socksReadByte(rw); err != nil {
+ return
+ }
+ if alen == 0 {
+ err = fmt.Errorf("SOCKS request had domain name with 0 length")
+ return
+ }
+ var addr []byte
+ if addr, err = socksReadBytes(rw, int(alen)); err != nil {
+ return
+ }
+ host = string(addr)
+
+ case socksAtypeV6:
+ var rawAddr []byte
+ if rawAddr, err = socksReadBytes(rw, net.IPv6len); err != nil {
+ return
+ }
+ addr := make(net.IP, net.IPv6len)
+ copy(addr[:], rawAddr[:])
+ host = fmt.Sprintf("[%s]", addr.String())
+
+ default:
+ sendErrResp(SocksRepAddressNotSupported)
+ err = fmt.Errorf("SOCKS request had unsupported address type 0x%02x", atype)
+ return
+ }
+ var rawPort []byte
+ if rawPort, err = socksReadBytes(rw, 2); err != nil {
+ return
+ }
+ port := int(rawPort[0])<<8 | int(rawPort[1])<<0
+
+ if err = socksFlushBuffers(rw); err != nil {
+ return
+ }
+
+ req.Target = fmt.Sprintf("%s:%d", host, port)
+ return
+}
+
+// Send a SOCKS5 response with the given code. BND.ADDR/BND.PORT is always the
+// IPv4 address/port "0.0.0.0:0".
+func sendSocks5Response(w io.Writer, code byte) error {
+ resp := make([]byte, 4+4+2)
+ resp[0] = socksVersion
+ resp[1] = code
+ resp[2] = socksRsv
+ resp[3] = socksAtypeV4
+
+ // BND.ADDR/BND.PORT should be the address and port that the outgoing
+ // connection is bound to on the proxy, but Tor does not use this
+ // information, so all zeroes are sent.
+
+ _, err := w.Write(resp[:])
+ return err
+}
+
+// Send a SOCKS5 response code 0x00.
+func sendSocks5ResponseGranted(w io.Writer) error {
+ return sendSocks5Response(w, socksRepSucceeded)
+}
+
+// Send a SOCKS5 response with the provided failure reason.
+func sendSocks5ResponseRejected(w io.Writer, reason byte) error {
+ return sendSocks5Response(w, reason)
+}
+
+func socksFlushBuffers(rw *bufio.ReadWriter) error {
+ if err := rw.Writer.Flush(); err != nil {
+ return err
+ }
+ if rw.Reader.Buffered() > 0 {
+ return fmt.Errorf("%d bytes left after SOCKS message", rw.Reader.Buffered())
+ }
+ return nil
+}
+
+func socksReadByte(rw *bufio.ReadWriter) (byte, error) {
+ return rw.Reader.ReadByte()
+}
+
+func socksReadBytes(rw *bufio.ReadWriter, n int) ([]byte, error) {
+ ret := make([]byte, n)
+ if _, err := io.ReadFull(rw.Reader, ret); err != nil {
+ return nil, err
+ }
+ return ret, nil
+}
+
+func socksReadByteVerify(rw *bufio.ReadWriter, descr string, expected byte) error {
+ val, err := socksReadByte(rw)
+ if err != nil {
+ return err
+ }
+ if val != expected {
+ return fmt.Errorf("SOCKS message field %s was 0x%02x, not 0x%02x", descr, val, expected)
+ }
+ return nil
+}
+
+var _ net.Listener = (*SocksListener)(nil)
diff --git a/vendor/git.torproject.org/pluggable-transports/obfs4.git/LICENSE b/vendor/git.torproject.org/pluggable-transports/obfs4.git/LICENSE
new file mode 100644
index 0000000..6b89f8c
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/obfs4.git/LICENSE
@@ -0,0 +1,55 @@
+Copyright (c) 2014, Yawning Angel
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+==============================================================================
+
+Copyright (c) 2012 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/csrand/csrand.go b/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/csrand/csrand.go
new file mode 100644
index 0000000..45849d3
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/csrand/csrand.go
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2014, Yawning Angel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Package csrand implements the math/rand interface over crypto/rand, along
+// with some utility functions for common random number/byte related tasks.
+//
+// Not all of the convinience routines are replicated, only those that are
+// immediately useful. The Rand variable provides access to the full math/rand
+// API.
+package csrand
+
+import (
+ cryptRand "crypto/rand"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "math/rand"
+)
+
+var (
+ csRandSourceInstance csRandSource
+
+ // Rand is a math/rand instance backed by crypto/rand CSPRNG.
+ Rand = rand.New(csRandSourceInstance)
+)
+
+type csRandSource struct {
+ // This does not keep any state as it is backed by crypto/rand.
+}
+
+func (r csRandSource) Int63() int64 {
+ var src [8]byte
+ if err := Bytes(src[:]); err != nil {
+ panic(err)
+ }
+ val := binary.BigEndian.Uint64(src[:])
+ val &= (1<<63 - 1)
+
+ return int64(val)
+}
+
+func (r csRandSource) Seed(seed int64) {
+ // No-op.
+}
+
+// Intn returns, as a int, a pseudo random number in [0, n).
+func Intn(n int) int {
+ return Rand.Intn(n)
+}
+
+// Float64 returns, as a float64, a pesudo random number in [0.0,1.0).
+func Float64() float64 {
+ return Rand.Float64()
+}
+
+// IntRange returns a uniformly distributed int [min, max].
+func IntRange(min, max int) int {
+ if max < min {
+ panic(fmt.Sprintf("IntRange: min > max (%d, %d)", min, max))
+ }
+
+ r := (max + 1) - min
+ ret := Rand.Intn(r)
+ return ret + min
+}
+
+// Bytes fills the slice with random data.
+func Bytes(buf []byte) error {
+ if _, err := io.ReadFull(cryptRand.Reader, buf); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Reader is a alias of rand.Reader.
+var Reader = cryptRand.Reader
diff --git a/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/drbg/hash_drbg.go b/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/drbg/hash_drbg.go
new file mode 100644
index 0000000..7feb9e8
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/drbg/hash_drbg.go
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2014, Yawning Angel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Package drbg implements a minimalistic DRBG based off SipHash-2-4 in OFB
+// mode.
+package drbg
+
+import (
+ "encoding/binary"
+ "encoding/hex"
+ "fmt"
+ "hash"
+
+ "github.com/dchest/siphash"
+
+ "git.torproject.org/pluggable-transports/obfs4.git/common/csrand"
+)
+
+// Size is the length of the HashDrbg output.
+const Size = siphash.Size
+
+// SeedLength is the length of the HashDrbg seed.
+const SeedLength = 16 + Size
+
+// Seed is the initial state for a HashDrbg. It consists of a SipHash-2-4
+// key, and 8 bytes of initial data.
+type Seed [SeedLength]byte
+
+// Bytes returns a pointer to the raw HashDrbg seed.
+func (seed *Seed) Bytes() *[SeedLength]byte {
+ return (*[SeedLength]byte)(seed)
+}
+
+// Hex returns the hexdecimal representation of the seed.
+func (seed *Seed) Hex() string {
+ return hex.EncodeToString(seed.Bytes()[:])
+}
+
+// NewSeed returns a Seed initialized with the runtime CSPRNG.
+func NewSeed() (seed *Seed, err error) {
+ seed = new(Seed)
+ if err = csrand.Bytes(seed.Bytes()[:]); err != nil {
+ return nil, err
+ }
+
+ return
+}
+
+// SeedFromBytes creates a Seed from the raw bytes, truncating to SeedLength as
+// appropriate.
+func SeedFromBytes(src []byte) (seed *Seed, err error) {
+ if len(src) < SeedLength {
+ return nil, InvalidSeedLengthError(len(src))
+ }
+
+ seed = new(Seed)
+ copy(seed.Bytes()[:], src)
+
+ return
+}
+
+// SeedFromHex creates a Seed from the hexdecimal representation, truncating to
+// SeedLength as appropriate.
+func SeedFromHex(encoded string) (seed *Seed, err error) {
+ var raw []byte
+ if raw, err = hex.DecodeString(encoded); err != nil {
+ return nil, err
+ }
+
+ return SeedFromBytes(raw)
+}
+
+// InvalidSeedLengthError is the error returned when the seed provided to the
+// DRBG is an invalid length.
+type InvalidSeedLengthError int
+
+func (e InvalidSeedLengthError) Error() string {
+ return fmt.Sprintf("invalid seed length: %d", int(e))
+}
+
+// HashDrbg is a CSDRBG based off of SipHash-2-4 in OFB mode.
+type HashDrbg struct {
+ sip hash.Hash64
+ ofb [Size]byte
+}
+
+// NewHashDrbg makes a HashDrbg instance based off an optional seed. The seed
+// is truncated to SeedLength.
+func NewHashDrbg(seed *Seed) (*HashDrbg, error) {
+ drbg := new(HashDrbg)
+ if seed == nil {
+ var err error
+ if seed, err = NewSeed(); err != nil {
+ return nil, err
+ }
+ }
+ drbg.sip = siphash.New(seed.Bytes()[:16])
+ copy(drbg.ofb[:], seed.Bytes()[16:])
+
+ return drbg, nil
+}
+
+// Int63 returns a uniformly distributed random integer [0, 1 << 63).
+func (drbg *HashDrbg) Int63() int64 {
+ block := drbg.NextBlock()
+ ret := binary.BigEndian.Uint64(block)
+ ret &= (1<<63 - 1)
+
+ return int64(ret)
+}
+
+// Seed does nothing, call NewHashDrbg if you want to reseed.
+func (drbg *HashDrbg) Seed(seed int64) {
+ // No-op.
+}
+
+// NextBlock returns the next 8 byte DRBG block.
+func (drbg *HashDrbg) NextBlock() []byte {
+ drbg.sip.Write(drbg.ofb[:])
+ copy(drbg.ofb[:], drbg.sip.Sum(nil))
+
+ ret := make([]byte, Size)
+ copy(ret, drbg.ofb[:])
+ return ret
+}
diff --git a/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/ntor/ntor.go b/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/ntor/ntor.go
new file mode 100644
index 0000000..4f6ab27
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/ntor/ntor.go
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 2014, Yawning Angel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Package ntor implements the Tor Project's ntor handshake as defined in
+// proposal 216 "Improved circuit-creation key exchange". It also supports
+// using Elligator to transform the Curve25519 public keys sent over the wire
+// to a form that is indistinguishable from random strings.
+//
+// Before using this package, it is strongly recommended that the specification
+// is read and understood.
+package ntor
+
+import (
+ "bytes"
+ "crypto/hmac"
+ "crypto/sha256"
+ "crypto/subtle"
+ "encoding/hex"
+ "fmt"
+ "io"
+
+ "golang.org/x/crypto/curve25519"
+ "golang.org/x/crypto/hkdf"
+
+ "github.com/agl/ed25519/extra25519"
+
+ "git.torproject.org/pluggable-transports/obfs4.git/common/csrand"
+)
+
+const (
+ // PublicKeyLength is the length of a Curve25519 public key.
+ PublicKeyLength = 32
+
+ // RepresentativeLength is the length of an Elligator representative.
+ RepresentativeLength = 32
+
+ // PrivateKeyLength is the length of a Curve25519 private key.
+ PrivateKeyLength = 32
+
+ // SharedSecretLength is the length of a Curve25519 shared secret.
+ SharedSecretLength = 32
+
+ // NodeIDLength is the length of a ntor node identifier.
+ NodeIDLength = 20
+
+ // KeySeedLength is the length of the derived KEY_SEED.
+ KeySeedLength = sha256.Size
+
+ // AuthLength is the lenght of the derived AUTH.
+ AuthLength = sha256.Size
+)
+
+var protoID = []byte("ntor-curve25519-sha256-1")
+var tMac = append(protoID, []byte(":mac")...)
+var tKey = append(protoID, []byte(":key_extract")...)
+var tVerify = append(protoID, []byte(":key_verify")...)
+var mExpand = append(protoID, []byte(":key_expand")...)
+
+// PublicKeyLengthError is the error returned when the public key being
+// imported is an invalid length.
+type PublicKeyLengthError int
+
+func (e PublicKeyLengthError) Error() string {
+ return fmt.Sprintf("ntor: Invalid Curve25519 public key length: %d",
+ int(e))
+}
+
+// PrivateKeyLengthError is the error returned when the private key being
+// imported is an invalid length.
+type PrivateKeyLengthError int
+
+func (e PrivateKeyLengthError) Error() string {
+ return fmt.Sprintf("ntor: Invalid Curve25519 private key length: %d",
+ int(e))
+}
+
+// NodeIDLengthError is the error returned when the node ID being imported is
+// an invalid length.
+type NodeIDLengthError int
+
+func (e NodeIDLengthError) Error() string {
+ return fmt.Sprintf("ntor: Invalid NodeID length: %d", int(e))
+}
+
+// KeySeed is the key material that results from a handshake (KEY_SEED).
+type KeySeed [KeySeedLength]byte
+
+// Bytes returns a pointer to the raw key material.
+func (key_seed *KeySeed) Bytes() *[KeySeedLength]byte {
+ return (*[KeySeedLength]byte)(key_seed)
+}
+
+// Auth is the verifier that results from a handshake (AUTH).
+type Auth [AuthLength]byte
+
+// Bytes returns a pointer to the raw auth.
+func (auth *Auth) Bytes() *[AuthLength]byte {
+ return (*[AuthLength]byte)(auth)
+}
+
+// NodeID is a ntor node identifier.
+type NodeID [NodeIDLength]byte
+
+// NewNodeID creates a NodeID from the raw bytes.
+func NewNodeID(raw []byte) (*NodeID, error) {
+ if len(raw) != NodeIDLength {
+ return nil, NodeIDLengthError(len(raw))
+ }
+
+ nodeID := new(NodeID)
+ copy(nodeID[:], raw)
+
+ return nodeID, nil
+}
+
+// NodeIDFromHex creates a new NodeID from the hexdecimal representation.
+func NodeIDFromHex(encoded string) (*NodeID, error) {
+ raw, err := hex.DecodeString(encoded)
+ if err != nil {
+ return nil, err
+ }
+
+ return NewNodeID(raw)
+}
+
+// Bytes returns a pointer to the raw NodeID.
+func (id *NodeID) Bytes() *[NodeIDLength]byte {
+ return (*[NodeIDLength]byte)(id)
+}
+
+// Hex returns the hexdecimal representation of the NodeID.
+func (id *NodeID) Hex() string {
+ return hex.EncodeToString(id[:])
+}
+
+// PublicKey is a Curve25519 public key in little-endian byte order.
+type PublicKey [PublicKeyLength]byte
+
+// Bytes returns a pointer to the raw Curve25519 public key.
+func (public *PublicKey) Bytes() *[PublicKeyLength]byte {
+ return (*[PublicKeyLength]byte)(public)
+}
+
+// Hex returns the hexdecimal representation of the Curve25519 public key.
+func (public *PublicKey) Hex() string {
+ return hex.EncodeToString(public.Bytes()[:])
+}
+
+// NewPublicKey creates a PublicKey from the raw bytes.
+func NewPublicKey(raw []byte) (*PublicKey, error) {
+ if len(raw) != PublicKeyLength {
+ return nil, PublicKeyLengthError(len(raw))
+ }
+
+ pubKey := new(PublicKey)
+ copy(pubKey[:], raw)
+
+ return pubKey, nil
+}
+
+// PublicKeyFromHex returns a PublicKey from the hexdecimal representation.
+func PublicKeyFromHex(encoded string) (*PublicKey, error) {
+ raw, err := hex.DecodeString(encoded)
+ if err != nil {
+ return nil, err
+ }
+
+ return NewPublicKey(raw)
+}
+
+// Representative is an Elligator representative of a Curve25519 public key
+// in little-endian byte order.
+type Representative [RepresentativeLength]byte
+
+// Bytes returns a pointer to the raw Elligator representative.
+func (repr *Representative) Bytes() *[RepresentativeLength]byte {
+ return (*[RepresentativeLength]byte)(repr)
+}
+
+// ToPublic converts a Elligator representative to a Curve25519 public key.
+func (repr *Representative) ToPublic() *PublicKey {
+ pub := new(PublicKey)
+
+ extra25519.RepresentativeToPublicKey(pub.Bytes(), repr.Bytes())
+ return pub
+}
+
+// PrivateKey is a Curve25519 private key in little-endian byte order.
+type PrivateKey [PrivateKeyLength]byte
+
+// Bytes returns a pointer to the raw Curve25519 private key.
+func (private *PrivateKey) Bytes() *[PrivateKeyLength]byte {
+ return (*[PrivateKeyLength]byte)(private)
+}
+
+// Hex returns the hexdecimal representation of the Curve25519 private key.
+func (private *PrivateKey) Hex() string {
+ return hex.EncodeToString(private.Bytes()[:])
+}
+
+// Keypair is a Curve25519 keypair with an optional Elligator representative.
+// As only certain Curve25519 keys can be obfuscated with Elligator, the
+// representative must be generated along with the keypair.
+type Keypair struct {
+ public *PublicKey
+ private *PrivateKey
+ representative *Representative
+}
+
+// Public returns the Curve25519 public key belonging to the Keypair.
+func (keypair *Keypair) Public() *PublicKey {
+ return keypair.public
+}
+
+// Private returns the Curve25519 private key belonging to the Keypair.
+func (keypair *Keypair) Private() *PrivateKey {
+ return keypair.private
+}
+
+// Representative returns the Elligator representative of the public key
+// belonging to the Keypair.
+func (keypair *Keypair) Representative() *Representative {
+ return keypair.representative
+}
+
+// HasElligator returns true if the Keypair has an Elligator representative.
+func (keypair *Keypair) HasElligator() bool {
+ return nil != keypair.representative
+}
+
+// NewKeypair generates a new Curve25519 keypair, and optionally also generates
+// an Elligator representative of the public key.
+func NewKeypair(elligator bool) (*Keypair, error) {
+ keypair := new(Keypair)
+ keypair.private = new(PrivateKey)
+ keypair.public = new(PublicKey)
+ if elligator {
+ keypair.representative = new(Representative)
+ }
+
+ for {
+ // Generate a Curve25519 private key. Like everyone who does this,
+ // run the CSPRNG output through SHA256 for extra tinfoil hattery.
+ priv := keypair.private.Bytes()[:]
+ if err := csrand.Bytes(priv); err != nil {
+ return nil, err
+ }
+ digest := sha256.Sum256(priv)
+ digest[0] &= 248
+ digest[31] &= 127
+ digest[31] |= 64
+ copy(priv, digest[:])
+
+ if elligator {
+ // Apply the Elligator transform. This fails ~50% of the time.
+ if !extra25519.ScalarBaseMult(keypair.public.Bytes(),
+ keypair.representative.Bytes(),
+ keypair.private.Bytes()) {
+ continue
+ }
+ } else {
+ // Generate the corresponding Curve25519 public key.
+ curve25519.ScalarBaseMult(keypair.public.Bytes(),
+ keypair.private.Bytes())
+ }
+
+ return keypair, nil
+ }
+}
+
+// KeypairFromHex returns a Keypair from the hexdecimal representation of the
+// private key.
+func KeypairFromHex(encoded string) (*Keypair, error) {
+ raw, err := hex.DecodeString(encoded)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(raw) != PrivateKeyLength {
+ return nil, PrivateKeyLengthError(len(raw))
+ }
+
+ keypair := new(Keypair)
+ keypair.private = new(PrivateKey)
+ keypair.public = new(PublicKey)
+
+ copy(keypair.private[:], raw)
+ curve25519.ScalarBaseMult(keypair.public.Bytes(),
+ keypair.private.Bytes())
+
+ return keypair, nil
+}
+
+// ServerHandshake does the server side of a ntor handshake and returns status,
+// KEY_SEED, and AUTH. If status is not true, the handshake MUST be aborted.
+func ServerHandshake(clientPublic *PublicKey, serverKeypair *Keypair, idKeypair *Keypair, id *NodeID) (ok bool, keySeed *KeySeed, auth *Auth) {
+ var notOk int
+ var secretInput bytes.Buffer
+
+ // Server side uses EXP(X,y) | EXP(X,b)
+ var exp [SharedSecretLength]byte
+ curve25519.ScalarMult(&exp, serverKeypair.private.Bytes(),
+ clientPublic.Bytes())
+ notOk |= constantTimeIsZero(exp[:])
+ secretInput.Write(exp[:])
+
+ curve25519.ScalarMult(&exp, idKeypair.private.Bytes(),
+ clientPublic.Bytes())
+ notOk |= constantTimeIsZero(exp[:])
+ secretInput.Write(exp[:])
+
+ keySeed, auth = ntorCommon(secretInput, id, idKeypair.public,
+ clientPublic, serverKeypair.public)
+ return notOk == 0, keySeed, auth
+}
+
+// ClientHandshake does the client side of a ntor handshake and returnes
+// status, KEY_SEED, and AUTH. If status is not true or AUTH does not match
+// the value recieved from the server, the handshake MUST be aborted.
+func ClientHandshake(clientKeypair *Keypair, serverPublic *PublicKey, idPublic *PublicKey, id *NodeID) (ok bool, keySeed *KeySeed, auth *Auth) {
+ var notOk int
+ var secretInput bytes.Buffer
+
+ // Client side uses EXP(Y,x) | EXP(B,x)
+ var exp [SharedSecretLength]byte
+ curve25519.ScalarMult(&exp, clientKeypair.private.Bytes(),
+ serverPublic.Bytes())
+ notOk |= constantTimeIsZero(exp[:])
+ secretInput.Write(exp[:])
+
+ curve25519.ScalarMult(&exp, clientKeypair.private.Bytes(),
+ idPublic.Bytes())
+ notOk |= constantTimeIsZero(exp[:])
+ secretInput.Write(exp[:])
+
+ keySeed, auth = ntorCommon(secretInput, id, idPublic,
+ clientKeypair.public, serverPublic)
+ return notOk == 0, keySeed, auth
+}
+
+// CompareAuth does a constant time compare of a Auth and a byte slice
+// (presumably received over a network).
+func CompareAuth(auth1 *Auth, auth2 []byte) bool {
+ auth1Bytes := auth1.Bytes()
+ return hmac.Equal(auth1Bytes[:], auth2)
+}
+
+func ntorCommon(secretInput bytes.Buffer, id *NodeID, b *PublicKey, x *PublicKey, y *PublicKey) (*KeySeed, *Auth) {
+ keySeed := new(KeySeed)
+ auth := new(Auth)
+
+ // secret_input/auth_input use this common bit, build it once.
+ suffix := bytes.NewBuffer(b.Bytes()[:])
+ suffix.Write(b.Bytes()[:])
+ suffix.Write(x.Bytes()[:])
+ suffix.Write(y.Bytes()[:])
+ suffix.Write(protoID)
+ suffix.Write(id[:])
+
+ // At this point secret_input has the 2 exponents, concatenated, append the
+ // client/server common suffix.
+ secretInput.Write(suffix.Bytes())
+
+ // KEY_SEED = H(secret_input, t_key)
+ h := hmac.New(sha256.New, tKey)
+ h.Write(secretInput.Bytes())
+ tmp := h.Sum(nil)
+ copy(keySeed[:], tmp)
+
+ // verify = H(secret_input, t_verify)
+ h = hmac.New(sha256.New, tVerify)
+ h.Write(secretInput.Bytes())
+ verify := h.Sum(nil)
+
+ // auth_input = verify | ID | B | Y | X | PROTOID | "Server"
+ authInput := bytes.NewBuffer(verify)
+ authInput.Write(suffix.Bytes())
+ authInput.Write([]byte("Server"))
+ h = hmac.New(sha256.New, tMac)
+ h.Write(authInput.Bytes())
+ tmp = h.Sum(nil)
+ copy(auth[:], tmp)
+
+ return keySeed, auth
+}
+
+func constantTimeIsZero(x []byte) int {
+ var ret byte
+ for _, v := range x {
+ ret |= v
+ }
+
+ return subtle.ConstantTimeByteEq(ret, 0)
+}
+
+// Kdf extracts and expands KEY_SEED via HKDF-SHA256 and returns `okm_len` bytes
+// of key material.
+func Kdf(keySeed []byte, okmLen int) []byte {
+ kdf := hkdf.New(sha256.New, keySeed, tKey, mExpand)
+ okm := make([]byte, okmLen)
+ n, err := io.ReadFull(kdf, okm)
+ if err != nil {
+ panic(fmt.Sprintf("BUG: Failed HKDF: %s", err.Error()))
+ } else if n != len(okm) {
+ panic(fmt.Sprintf("BUG: Got truncated HKDF output: %d", n))
+ }
+
+ return okm
+}
diff --git a/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/probdist/weighted_dist.go b/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/probdist/weighted_dist.go
new file mode 100644
index 0000000..5f8e88e
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/probdist/weighted_dist.go
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2014, Yawning Angel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Package probdist implements a weighted probability distribution suitable for
+// protocol parameterization. To allow for easy reproduction of a given
+// distribution, the drbg package is used as the random number source.
+package probdist
+
+import (
+ "bytes"
+ "container/list"
+ "fmt"
+ "math/rand"
+ "sync"
+
+ "git.torproject.org/pluggable-transports/obfs4.git/common/csrand"
+ "git.torproject.org/pluggable-transports/obfs4.git/common/drbg"
+)
+
+const (
+ minValues = 1
+ maxValues = 100
+)
+
+// WeightedDist is a weighted distribution.
+type WeightedDist struct {
+ sync.Mutex
+
+ minValue int
+ maxValue int
+ biased bool
+ values []int
+ weights []float64
+
+ alias []int
+ prob []float64
+}
+
+// New creates a weighted distribution of values ranging from min to max
+// based on a HashDrbg initialized with seed. Optionally, bias the weight
+// generation to match the ScrambleSuit non-uniform distribution from
+// obfsproxy.
+func New(seed *drbg.Seed, min, max int, biased bool) (w *WeightedDist) {
+ w = &WeightedDist{minValue: min, maxValue: max, biased: biased}
+
+ if max <= min {
+ panic(fmt.Sprintf("wDist.Reset(): min >= max (%d, %d)", min, max))
+ }
+
+ w.Reset(seed)
+
+ return
+}
+
+// genValues creates a slice containing a random number of random values
+// that when scaled by adding minValue will fall into [min, max].
+func (w *WeightedDist) genValues(rng *rand.Rand) {
+ nValues := (w.maxValue + 1) - w.minValue
+ values := rng.Perm(nValues)
+ if nValues < minValues {
+ nValues = minValues
+ }
+ if nValues > maxValues {
+ nValues = maxValues
+ }
+ nValues = rng.Intn(nValues) + 1
+ w.values = values[:nValues]
+}
+
+// genBiasedWeights generates a non-uniform weight list, similar to the
+// ScrambleSuit prob_dist module.
+func (w *WeightedDist) genBiasedWeights(rng *rand.Rand) {
+ w.weights = make([]float64, len(w.values))
+
+ culmProb := 0.0
+ for i := range w.weights {
+ p := (1.0 - culmProb) * rng.Float64()
+ w.weights[i] = p
+ culmProb += p
+ }
+}
+
+// genUniformWeights generates a uniform weight list.
+func (w *WeightedDist) genUniformWeights(rng *rand.Rand) {
+ w.weights = make([]float64, len(w.values))
+ for i := range w.weights {
+ w.weights[i] = rng.Float64()
+ }
+}
+
+// genTables calculates the alias and prob tables used for Vose's Alias method.
+// Algorithm taken from http://www.keithschwarz.com/darts-dice-coins/
+func (w *WeightedDist) genTables() {
+ n := len(w.weights)
+ var sum float64
+ for _, weight := range w.weights {
+ sum += weight
+ }
+
+ // Create arrays $Alias$ and $Prob$, each of size $n$.
+ alias := make([]int, n)
+ prob := make([]float64, n)
+
+ // Create two worklists, $Small$ and $Large$.
+ small := list.New()
+ large := list.New()
+
+ scaled := make([]float64, n)
+ for i, weight := range w.weights {
+ // Multiply each probability by $n$.
+ p_i := weight * float64(n) / sum
+ scaled[i] = p_i
+
+ // For each scaled probability $p_i$:
+ if scaled[i] < 1.0 {
+ // If $p_i < 1$, add $i$ to $Small$.
+ small.PushBack(i)
+ } else {
+ // Otherwise ($p_i \ge 1$), add $i$ to $Large$.
+ large.PushBack(i)
+ }
+ }
+
+ // While $Small$ and $Large$ are not empty: ($Large$ might be emptied first)
+ for small.Len() > 0 && large.Len() > 0 {
+ // Remove the first element from $Small$; call it $l$.
+ l := small.Remove(small.Front()).(int)
+ // Remove the first element from $Large$; call it $g$.
+ g := large.Remove(large.Front()).(int)
+
+ // Set $Prob[l] = p_l$.
+ prob[l] = scaled[l]
+ // Set $Alias[l] = g$.
+ alias[l] = g
+
+ // Set $p_g := (p_g + p_l) - 1$. (This is a more numerically stable option.)
+ scaled[g] = (scaled[g] + scaled[l]) - 1.0
+
+ if scaled[g] < 1.0 {
+ // If $p_g < 1$, add $g$ to $Small$.
+ small.PushBack(g)
+ } else {
+ // Otherwise ($p_g \ge 1$), add $g$ to $Large$.
+ large.PushBack(g)
+ }
+ }
+
+ // While $Large$ is not empty:
+ for large.Len() > 0 {
+ // Remove the first element from $Large$; call it $g$.
+ g := large.Remove(large.Front()).(int)
+ // Set $Prob[g] = 1$.
+ prob[g] = 1.0
+ }
+
+ // While $Small$ is not empty: This is only possible due to numerical instability.
+ for small.Len() > 0 {
+ // Remove the first element from $Small$; call it $l$.
+ l := small.Remove(small.Front()).(int)
+ // Set $Prob[l] = 1$.
+ prob[l] = 1.0
+ }
+
+ w.prob = prob
+ w.alias = alias
+}
+
+// Reset generates a new distribution with the same min/max based on a new
+// seed.
+func (w *WeightedDist) Reset(seed *drbg.Seed) {
+ // Initialize the deterministic random number generator.
+ drbg, _ := drbg.NewHashDrbg(seed)
+ rng := rand.New(drbg)
+
+ w.Lock()
+ defer w.Unlock()
+
+ w.genValues(rng)
+ if w.biased {
+ w.genBiasedWeights(rng)
+ } else {
+ w.genUniformWeights(rng)
+ }
+ w.genTables()
+}
+
+// Sample generates a random value according to the distribution.
+func (w *WeightedDist) Sample() int {
+ var idx int
+
+ w.Lock()
+ defer w.Unlock()
+
+ // Generate a fair die roll from an $n$-sided die; call the side $i$.
+ i := csrand.Intn(len(w.values))
+ // Flip a biased coin that comes up heads with probability $Prob[i]$.
+ if csrand.Float64() <= w.prob[i] {
+ // If the coin comes up "heads," return $i$.
+ idx = i
+ } else {
+ // Otherwise, return $Alias[i]$.
+ idx = w.alias[i]
+ }
+
+ return w.minValue + w.values[idx]
+}
+
+// String returns a dump of the distribution table.
+func (w *WeightedDist) String() string {
+ var buf bytes.Buffer
+
+ buf.WriteString("[ ")
+ for i, v := range w.values {
+ p := w.weights[i]
+ if p > 0.01 { // Squelch tiny probabilities.
+ buf.WriteString(fmt.Sprintf("%d: %f ", v, p))
+ }
+ }
+ buf.WriteString("]")
+ return buf.String()
+}
diff --git a/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/replayfilter/replay_filter.go b/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/replayfilter/replay_filter.go
new file mode 100644
index 0000000..95cc5d6
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/obfs4.git/common/replayfilter/replay_filter.go
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2014, Yawning Angel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Package replayfilter implements a generic replay detection filter with a
+// caller specifiable time-to-live. It only detects if a given byte sequence
+// has been seen before based on the SipHash-2-4 digest of the sequence.
+// Collisions are treated as positive matches, though the probability of this
+// happening is negligible.
+package replayfilter
+
+import (
+ "container/list"
+ "encoding/binary"
+ "sync"
+ "time"
+
+ "github.com/dchest/siphash"
+
+ "git.torproject.org/pluggable-transports/obfs4.git/common/csrand"
+)
+
+// maxFilterSize is the maximum capacity of a replay filter. This value is
+// more as a safeguard to prevent runaway filter growth, and is sized to be
+// serveral orders of magnitude greater than the number of connections a busy
+// bridge sees in one day, so in practice should never be reached.
+const maxFilterSize = 100 * 1024
+
+type entry struct {
+ digest uint64
+ firstSeen time.Time
+ element *list.Element
+}
+
+// ReplayFilter is a simple filter designed only to detect if a given byte
+// sequence has been seen before.
+type ReplayFilter struct {
+ sync.Mutex
+
+ filter map[uint64]*entry
+ fifo *list.List
+
+ key [2]uint64
+ ttl time.Duration
+}
+
+// New creates a new ReplayFilter instance.
+func New(ttl time.Duration) (filter *ReplayFilter, err error) {
+ // Initialize the SipHash-2-4 instance with a random key.
+ var key [16]byte
+ if err = csrand.Bytes(key[:]); err != nil {
+ return
+ }
+
+ filter = new(ReplayFilter)
+ filter.filter = make(map[uint64]*entry)
+ filter.fifo = list.New()
+ filter.key[0] = binary.BigEndian.Uint64(key[0:8])
+ filter.key[1] = binary.BigEndian.Uint64(key[8:16])
+ filter.ttl = ttl
+
+ return
+}
+
+// TestAndSet queries the filter for a given byte sequence, inserts the
+// sequence, and returns if it was present before the insertion operation.
+func (f *ReplayFilter) TestAndSet(now time.Time, buf []byte) bool {
+ digest := siphash.Hash(f.key[0], f.key[1], buf)
+
+ f.Lock()
+ defer f.Unlock()
+
+ f.compactFilter(now)
+
+ if e := f.filter[digest]; e != nil {
+ // Hit. Just return.
+ return true
+ }
+
+ // Miss. Add a new entry.
+ e := new(entry)
+ e.digest = digest
+ e.firstSeen = now
+ e.element = f.fifo.PushBack(e)
+ f.filter[digest] = e
+
+ return false
+}
+
+func (f *ReplayFilter) compactFilter(now time.Time) {
+ e := f.fifo.Front()
+ for e != nil {
+ ent, _ := e.Value.(*entry)
+
+ // If the filter is not full, only purge entries that exceed the TTL,
+ // otherwise purge at least one entry, then revert to TTL based
+ // compaction.
+ if f.fifo.Len() < maxFilterSize && f.ttl > 0 {
+ deltaT := now.Sub(ent.firstSeen)
+ if deltaT < 0 {
+ // Aeeeeeee, the system time jumped backwards, potentially by
+ // a lot. This will eventually self-correct, but "eventually"
+ // could be a long time. As much as this sucks, jettison the
+ // entire filter.
+ f.reset()
+ return
+ } else if deltaT < f.ttl {
+ return
+ }
+ }
+
+ // Remove the eldest entry.
+ eNext := e.Next()
+ delete(f.filter, ent.digest)
+ f.fifo.Remove(ent.element)
+ ent.element = nil
+ e = eNext
+ }
+}
+
+func (f *ReplayFilter) reset() {
+ f.filter = make(map[uint64]*entry)
+ f.fifo = list.New()
+}
diff --git a/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/base/base.go b/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/base/base.go
new file mode 100644
index 0000000..bb0902e
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/base/base.go
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014, Yawning Angel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Package base provides the common interface that each supported transport
+// protocol must implement.
+package base
+
+import (
+ "net"
+
+ "git.torproject.org/pluggable-transports/goptlib.git"
+)
+
+type DialFunc func(string, string) (net.Conn, error)
+
+// ClientFactory is the interface that defines the factory for creating
+// pluggable transport protocol client instances.
+type ClientFactory interface {
+ // Transport returns the Transport instance that this ClientFactory belongs
+ // to.
+ Transport() Transport
+
+ // ParseArgs parses the supplied arguments into an internal representation
+ // for use with WrapConn. This routine is called before the outgoing
+ // TCP/IP connection is created to allow doing things (like keypair
+ // generation) to be hidden from third parties.
+ ParseArgs(args *pt.Args) (interface{}, error)
+
+ // Dial creates an outbound net.Conn, and does whatever is required
+ // (eg: handshaking) to get the connection to the point where it is
+ // ready to relay data.
+ Dial(network, address string, dialFn DialFunc, args interface{}) (net.Conn, error)
+}
+
+// ServerFactory is the interface that defines the factory for creating
+// plugable transport protocol server instances. As the arguments are the
+// property of the factory, validation is done at factory creation time.
+type ServerFactory interface {
+ // Transport returns the Transport instance that this ServerFactory belongs
+ // to.
+ Transport() Transport
+
+ // Args returns the Args required on the client side to handshake with
+ // server connections created by this factory.
+ Args() *pt.Args
+
+ // WrapConn wraps the provided net.Conn with a transport protocol
+ // implementation, and does whatever is required (eg: handshaking) to get
+ // the connection to a point where it is ready to relay data.
+ WrapConn(conn net.Conn) (net.Conn, error)
+}
+
+// Transport is an interface that defines a pluggable transport protocol.
+type Transport interface {
+ // Name returns the name of the transport protocol. It MUST be a valid C
+ // identifier.
+ Name() string
+
+ // ClientFactory returns a ClientFactory instance for this transport
+ // protocol.
+ ClientFactory(stateDir string) (ClientFactory, error)
+
+ // ServerFactory returns a ServerFactory instance for this transport
+ // protocol. This can fail if the provided arguments are invalid.
+ ServerFactory(stateDir string, args *pt.Args) (ServerFactory, error)
+}
diff --git a/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/framing/framing.go b/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/framing/framing.go
new file mode 100644
index 0000000..815a990
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/framing/framing.go
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2014, Yawning Angel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// Package framing implements the obfs4 link framing and cryptography.
+//
+// The Encoder/Decoder shared secret format is:
+// uint8_t[32] NaCl secretbox key
+// uint8_t[16] NaCl Nonce prefix
+// uint8_t[16] SipHash-2-4 key (used to obfsucate length)
+// uint8_t[8] SipHash-2-4 IV
+//
+// The frame format is:
+// uint16_t length (obfsucated, big endian)
+// NaCl secretbox (Poly1305/XSalsa20) containing:
+// uint8_t[16] tag (Part of the secretbox construct)
+// uint8_t[] payload
+//
+// The length field is length of the NaCl secretbox XORed with the truncated
+// SipHash-2-4 digest ran in OFB mode.
+//
+// Initialize K, IV[0] with values from the shared secret.
+// On each packet, IV[n] = H(K, IV[n - 1])
+// mask[n] = IV[n][0:2]
+// obfsLen = length ^ mask[n]
+//
+// The NaCl secretbox (Poly1305/XSalsa20) nonce format is:
+// uint8_t[24] prefix (Fixed)
+// uint64_t counter (Big endian)
+//
+// The counter is initialized to 1, and is incremented on each frame. Since
+// the protocol is designed to be used over a reliable medium, the nonce is not
+// transmitted over the wire as both sides of the conversation know the prefix
+// and the initial counter value. It is imperative that the counter does not
+// wrap, and sessions MUST terminate before 2^64 frames are sent.
+//
+package framing
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+
+ "golang.org/x/crypto/nacl/secretbox"
+
+ "git.torproject.org/pluggable-transports/obfs4.git/common/csrand"
+ "git.torproject.org/pluggable-transports/obfs4.git/common/drbg"
+)
+
+const (
+ // MaximumSegmentLength is the length of the largest possible segment
+ // including overhead.
+ MaximumSegmentLength = 1500 - (40 + 12)
+
+ // FrameOverhead is the length of the framing overhead.
+ FrameOverhead = lengthLength + secretbox.Overhead
+
+ // MaximumFramePayloadLength is the length of the maximum allowed payload
+ // per frame.
+ MaximumFramePayloadLength = MaximumSegmentLength - FrameOverhead
+
+ // KeyLength is the length of the Encoder/Decoder secret key.
+ KeyLength = keyLength + noncePrefixLength + drbg.SeedLength
+
+ maxFrameLength = MaximumSegmentLength - lengthLength
+ minFrameLength = FrameOverhead - lengthLength
+
+ keyLength = 32
+
+ noncePrefixLength = 16
+ nonceCounterLength = 8
+ nonceLength = noncePrefixLength + nonceCounterLength
+
+ lengthLength = 2
+)
+
+// Error returned when Decoder.Decode() requires more data to continue.
+var ErrAgain = errors.New("framing: More data needed to decode")
+
+// Error returned when Decoder.Decode() failes to authenticate a frame.
+var ErrTagMismatch = errors.New("framing: Poly1305 tag mismatch")
+
+// Error returned when the NaCl secretbox nonce's counter wraps (FATAL).
+var ErrNonceCounterWrapped = errors.New("framing: Nonce counter wrapped")
+
+// InvalidPayloadLengthError is the error returned when Encoder.Encode()
+// rejects the payload length.
+type InvalidPayloadLengthError int
+
+func (e InvalidPayloadLengthError) Error() string {
+ return fmt.Sprintf("framing: Invalid payload length: %d", int(e))
+}
+
+type boxNonce struct {
+ prefix [noncePrefixLength]byte
+ counter uint64
+}
+
+func (nonce *boxNonce) init(prefix []byte) {
+ if noncePrefixLength != len(prefix) {
+ panic(fmt.Sprintf("BUG: Nonce prefix length invalid: %d", len(prefix)))
+ }
+
+ copy(nonce.prefix[:], prefix)
+ nonce.counter = 1
+}
+
+func (nonce boxNonce) bytes(out *[nonceLength]byte) error {
+ // The security guarantee of Poly1305 is broken if a nonce is ever reused
+ // for a given key. Detect this by checking for counter wraparound since
+ // we start each counter at 1. If it ever happens that more than 2^64 - 1
+ // frames are transmitted over a given connection, support for rekeying
+ // will be neccecary, but that's unlikely to happen.
+ if nonce.counter == 0 {
+ return ErrNonceCounterWrapped
+ }
+
+ copy(out[:], nonce.prefix[:])
+ binary.BigEndian.PutUint64(out[noncePrefixLength:], nonce.counter)
+
+ return nil
+}
+
+// Encoder is a frame encoder instance.
+type Encoder struct {
+ key [keyLength]byte
+ nonce boxNonce
+ drbg *drbg.HashDrbg
+}
+
+// NewEncoder creates a new Encoder instance. It must be supplied a slice
+// containing exactly KeyLength bytes of keying material.
+func NewEncoder(key []byte) *Encoder {
+ if len(key) != KeyLength {
+ panic(fmt.Sprintf("BUG: Invalid encoder key length: %d", len(key)))
+ }
+
+ encoder := new(Encoder)
+ copy(encoder.key[:], key[0:keyLength])
+ encoder.nonce.init(key[keyLength : keyLength+noncePrefixLength])
+ seed, err := drbg.SeedFromBytes(key[keyLength+noncePrefixLength:])
+ if err != nil {
+ panic(fmt.Sprintf("BUG: Failed to initialize DRBG: %s", err))
+ }
+ encoder.drbg, _ = drbg.NewHashDrbg(seed)
+
+ return encoder
+}
+
+// Encode encodes a single frame worth of payload and returns the encoded
+// length. InvalidPayloadLengthError is recoverable, all other errors MUST be
+// treated as fatal and the session aborted.
+func (encoder *Encoder) Encode(frame, payload []byte) (n int, err error) {
+ payloadLen := len(payload)
+ if MaximumFramePayloadLength < payloadLen {
+ return 0, InvalidPayloadLengthError(payloadLen)
+ }
+ if len(frame) < payloadLen+FrameOverhead {
+ return 0, io.ErrShortBuffer
+ }
+
+ // Generate a new nonce.
+ var nonce [nonceLength]byte
+ if err = encoder.nonce.bytes(&nonce); err != nil {
+ return 0, err
+ }
+ encoder.nonce.counter++
+
+ // Encrypt and MAC payload.
+ box := secretbox.Seal(frame[:lengthLength], payload, &nonce, &encoder.key)
+
+ // Obfuscate the length.
+ length := uint16(len(box) - lengthLength)
+ lengthMask := encoder.drbg.NextBlock()
+ length ^= binary.BigEndian.Uint16(lengthMask)
+ binary.BigEndian.PutUint16(frame[:2], length)
+
+ // Return the frame.
+ return len(box), nil
+}
+
+// Decoder is a frame decoder instance.
+type Decoder struct {
+ key [keyLength]byte
+ nonce boxNonce
+ drbg *drbg.HashDrbg
+
+ nextNonce [nonceLength]byte
+ nextLength uint16
+ nextLengthInvalid bool
+}
+
+// NewDecoder creates a new Decoder instance. It must be supplied a slice
+// containing exactly KeyLength bytes of keying material.
+func NewDecoder(key []byte) *Decoder {
+ if len(key) != KeyLength {
+ panic(fmt.Sprintf("BUG: Invalid decoder key length: %d", len(key)))
+ }
+
+ decoder := new(Decoder)
+ copy(decoder.key[:], key[0:keyLength])
+ decoder.nonce.init(key[keyLength : keyLength+noncePrefixLength])
+ seed, err := drbg.SeedFromBytes(key[keyLength+noncePrefixLength:])
+ if err != nil {
+ panic(fmt.Sprintf("BUG: Failed to initialize DRBG: %s", err))
+ }
+ decoder.drbg, _ = drbg.NewHashDrbg(seed)
+
+ return decoder
+}
+
+// Decode decodes a stream of data and returns the length if any. ErrAgain is
+// a temporary failure, all other errors MUST be treated as fatal and the
+// session aborted.
+func (decoder *Decoder) Decode(data []byte, frames *bytes.Buffer) (int, error) {
+ // A length of 0 indicates that we do not know how big the next frame is
+ // going to be.
+ if decoder.nextLength == 0 {
+ // Attempt to pull out the next frame length.
+ if lengthLength > frames.Len() {
+ return 0, ErrAgain
+ }
+
+ // Remove the length field from the buffer.
+ var obfsLen [lengthLength]byte
+ _, err := io.ReadFull(frames, obfsLen[:])
+ if err != nil {
+ return 0, err
+ }
+
+ // Derive the nonce the peer used.
+ if err = decoder.nonce.bytes(&decoder.nextNonce); err != nil {
+ return 0, err
+ }
+
+ // Deobfuscate the length field.
+ length := binary.BigEndian.Uint16(obfsLen[:])
+ lengthMask := decoder.drbg.NextBlock()
+ length ^= binary.BigEndian.Uint16(lengthMask)
+ if maxFrameLength < length || minFrameLength > length {
+ // Per "Plaintext Recovery Attacks Against SSH" by
+ // Martin R. Albrecht, Kenneth G. Paterson and Gaven J. Watson,
+ // there are a class of attacks againt protocols that use similar
+ // sorts of framing schemes.
+ //
+ // While obfs4 should not allow plaintext recovery (CBC mode is
+ // not used), attempt to mitigate out of bound frame length errors
+ // by pretending that the length was a random valid range as per
+ // the countermeasure suggested by Denis Bider in section 6 of the
+ // paper.
+
+ decoder.nextLengthInvalid = true
+ length = uint16(csrand.IntRange(minFrameLength, maxFrameLength))
+ }
+ decoder.nextLength = length
+ }
+
+ if int(decoder.nextLength) > frames.Len() {
+ return 0, ErrAgain
+ }
+
+ // Unseal the frame.
+ var box [maxFrameLength]byte
+ n, err := io.ReadFull(frames, box[:decoder.nextLength])
+ if err != nil {
+ return 0, err
+ }
+ out, ok := secretbox.Open(data[:0], box[:n], &decoder.nextNonce, &decoder.key)
+ if !ok || decoder.nextLengthInvalid {
+ // When a random length is used (on length error) the tag should always
+ // mismatch, but be paranoid.
+ return 0, ErrTagMismatch
+ }
+
+ // Clean up and prepare for the next frame.
+ decoder.nextLength = 0
+ decoder.nonce.counter++
+
+ return len(out), nil
+}
diff --git a/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/handshake_ntor.go b/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/handshake_ntor.go
new file mode 100644
index 0000000..ee1bca8
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/handshake_ntor.go
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2014, Yawning Angel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package obfs4
+
+import (
+ "bytes"
+ "crypto/hmac"
+ "crypto/sha256"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "hash"
+ "strconv"
+ "time"
+
+ "git.torproject.org/pluggable-transports/obfs4.git/common/csrand"
+ "git.torproject.org/pluggable-transports/obfs4.git/common/ntor"
+ "git.torproject.org/pluggable-transports/obfs4.git/common/replayfilter"
+ "git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/framing"
+)
+
+const (
+ maxHandshakeLength = 8192
+
+ clientMinPadLength = (serverMinHandshakeLength + inlineSeedFrameLength) -
+ clientMinHandshakeLength
+ clientMaxPadLength = maxHandshakeLength - clientMinHandshakeLength
+ clientMinHandshakeLength = ntor.RepresentativeLength + markLength + macLength
+
+ serverMinPadLength = 0
+ serverMaxPadLength = maxHandshakeLength - (serverMinHandshakeLength +
+ inlineSeedFrameLength)
+ serverMinHandshakeLength = ntor.RepresentativeLength + ntor.AuthLength +
+ markLength + macLength
+
+ markLength = sha256.Size / 2
+ macLength = sha256.Size / 2
+
+ inlineSeedFrameLength = framing.FrameOverhead + packetOverhead + seedPacketPayloadLength
+)
+
+// ErrMarkNotFoundYet is the error returned when the obfs4 handshake is
+// incomplete and requires more data to continue. This error is non-fatal and
+// is the equivalent to EAGAIN/EWOULDBLOCK.
+var ErrMarkNotFoundYet = errors.New("handshake: M_[C,S] not found yet")
+
+// ErrInvalidHandshake is the error returned when the obfs4 handshake fails due
+// to the peer not sending the correct mark. This error is fatal and the
+// connection MUST be dropped.
+var ErrInvalidHandshake = errors.New("handshake: Failed to find M_[C,S]")
+
+// ErrReplayedHandshake is the error returned when the obfs4 handshake fails
+// due it being replayed. This error is fatal and the connection MUST be
+// dropped.
+var ErrReplayedHandshake = errors.New("handshake: Replay detected")
+
+// ErrNtorFailed is the error returned when the ntor handshake fails. This
+// error is fatal and the connection MUST be dropped.
+var ErrNtorFailed = errors.New("handshake: ntor handshake failure")
+
+// InvalidMacError is the error returned when the handshake MACs do not match.
+// This error is fatal and the connection MUST be dropped.
+type InvalidMacError struct {
+ Derived []byte
+ Received []byte
+}
+
+func (e *InvalidMacError) Error() string {
+ return fmt.Sprintf("handshake: MAC mismatch: Dervied: %s Received: %s.",
+ hex.EncodeToString(e.Derived), hex.EncodeToString(e.Received))
+}
+
+// InvalidAuthError is the error returned when the ntor AUTH tags do not match.
+// This error is fatal and the connection MUST be dropped.
+type InvalidAuthError struct {
+ Derived *ntor.Auth
+ Received *ntor.Auth
+}
+
+func (e *InvalidAuthError) Error() string {
+ return fmt.Sprintf("handshake: ntor AUTH mismatch: Derived: %s Received:%s.",
+ hex.EncodeToString(e.Derived.Bytes()[:]),
+ hex.EncodeToString(e.Received.Bytes()[:]))
+}
+
+type clientHandshake struct {
+ keypair *ntor.Keypair
+ nodeID *ntor.NodeID
+ serverIdentity *ntor.PublicKey
+ epochHour []byte
+
+ padLen int
+ mac hash.Hash
+
+ serverRepresentative *ntor.Representative
+ serverAuth *ntor.Auth
+ serverMark []byte
+}
+
+func newClientHandshake(nodeID *ntor.NodeID, serverIdentity *ntor.PublicKey, sessionKey *ntor.Keypair) *clientHandshake {
+ hs := new(clientHandshake)
+ hs.keypair = sessionKey
+ hs.nodeID = nodeID
+ hs.serverIdentity = serverIdentity
+ hs.padLen = csrand.IntRange(clientMinPadLength, clientMaxPadLength)
+ hs.mac = hmac.New(sha256.New, append(hs.serverIdentity.Bytes()[:], hs.nodeID.Bytes()[:]...))
+
+ return hs
+}
+
+func (hs *clientHandshake) generateHandshake() ([]byte, error) {
+ var buf bytes.Buffer
+
+ hs.mac.Reset()
+ hs.mac.Write(hs.keypair.Representative().Bytes()[:])
+ mark := hs.mac.Sum(nil)[:markLength]
+
+ // The client handshake is X | P_C | M_C | MAC(X | P_C | M_C | E) where:
+ // * X is the client's ephemeral Curve25519 public key representative.
+ // * P_C is [clientMinPadLength,clientMaxPadLength] bytes of random padding.
+ // * M_C is HMAC-SHA256-128(serverIdentity | NodeID, X)
+ // * MAC is HMAC-SHA256-128(serverIdentity | NodeID, X .... E)
+ // * E is the string representation of the number of hours since the UNIX
+ // epoch.
+
+ // Generate the padding
+ pad, err := makePad(hs.padLen)
+ if err != nil {
+ return nil, err
+ }
+
+ // Write X, P_C, M_C.
+ buf.Write(hs.keypair.Representative().Bytes()[:])
+ buf.Write(pad)
+ buf.Write(mark)
+
+ // Calculate and write the MAC.
+ hs.mac.Reset()
+ hs.mac.Write(buf.Bytes())
+ hs.epochHour = []byte(strconv.FormatInt(getEpochHour(), 10))
+ hs.mac.Write(hs.epochHour)
+ buf.Write(hs.mac.Sum(nil)[:macLength])
+
+ return buf.Bytes(), nil
+}
+
+func (hs *clientHandshake) parseServerHandshake(resp []byte) (int, []byte, error) {
+ // No point in examining the data unless the miminum plausible response has
+ // been received.
+ if serverMinHandshakeLength > len(resp) {
+ return 0, nil, ErrMarkNotFoundYet
+ }
+
+ if hs.serverRepresentative == nil || hs.serverAuth == nil {
+ // Pull out the representative/AUTH. (XXX: Add ctors to ntor)
+ hs.serverRepresentative = new(ntor.Representative)
+ copy(hs.serverRepresentative.Bytes()[:], resp[0:ntor.RepresentativeLength])
+ hs.serverAuth = new(ntor.Auth)
+ copy(hs.serverAuth.Bytes()[:], resp[ntor.RepresentativeLength:])
+
+ // Derive the mark.
+ hs.mac.Reset()
+ hs.mac.Write(hs.serverRepresentative.Bytes()[:])
+ hs.serverMark = hs.mac.Sum(nil)[:markLength]
+ }
+
+ // Attempt to find the mark + MAC.
+ pos := findMarkMac(hs.serverMark, resp, ntor.RepresentativeLength+ntor.AuthLength+serverMinPadLength,
+ maxHandshakeLength, false)
+ if pos == -1 {
+ if len(resp) >= maxHandshakeLength {
+ return 0, nil, ErrInvalidHandshake
+ }
+ return 0, nil, ErrMarkNotFoundYet
+ }
+
+ // Validate the MAC.
+ hs.mac.Reset()
+ hs.mac.Write(resp[:pos+markLength])
+ hs.mac.Write(hs.epochHour)
+ macCmp := hs.mac.Sum(nil)[:macLength]
+ macRx := resp[pos+markLength : pos+markLength+macLength]
+ if !hmac.Equal(macCmp, macRx) {
+ return 0, nil, &InvalidMacError{macCmp, macRx}
+ }
+
+ // Complete the handshake.
+ serverPublic := hs.serverRepresentative.ToPublic()
+ ok, seed, auth := ntor.ClientHandshake(hs.keypair, serverPublic,
+ hs.serverIdentity, hs.nodeID)
+ if !ok {
+ return 0, nil, ErrNtorFailed
+ }
+ if !ntor.CompareAuth(auth, hs.serverAuth.Bytes()[:]) {
+ return 0, nil, &InvalidAuthError{auth, hs.serverAuth}
+ }
+
+ return pos + markLength + macLength, seed.Bytes()[:], nil
+}
+
+type serverHandshake struct {
+ keypair *ntor.Keypair
+ nodeID *ntor.NodeID
+ serverIdentity *ntor.Keypair
+ epochHour []byte
+ serverAuth *ntor.Auth
+
+ padLen int
+ mac hash.Hash
+
+ clientRepresentative *ntor.Representative
+ clientMark []byte
+}
+
+func newServerHandshake(nodeID *ntor.NodeID, serverIdentity *ntor.Keypair, sessionKey *ntor.Keypair) *serverHandshake {
+ hs := new(serverHandshake)
+ hs.keypair = sessionKey
+ hs.nodeID = nodeID
+ hs.serverIdentity = serverIdentity
+ hs.padLen = csrand.IntRange(serverMinPadLength, serverMaxPadLength)
+ hs.mac = hmac.New(sha256.New, append(hs.serverIdentity.Public().Bytes()[:], hs.nodeID.Bytes()[:]...))
+
+ return hs
+}
+
+func (hs *serverHandshake) parseClientHandshake(filter *replayfilter.ReplayFilter, resp []byte) ([]byte, error) {
+ // No point in examining the data unless the miminum plausible response has
+ // been received.
+ if clientMinHandshakeLength > len(resp) {
+ return nil, ErrMarkNotFoundYet
+ }
+
+ if hs.clientRepresentative == nil {
+ // Pull out the representative/AUTH. (XXX: Add ctors to ntor)
+ hs.clientRepresentative = new(ntor.Representative)
+ copy(hs.clientRepresentative.Bytes()[:], resp[0:ntor.RepresentativeLength])
+
+ // Derive the mark.
+ hs.mac.Reset()
+ hs.mac.Write(hs.clientRepresentative.Bytes()[:])
+ hs.clientMark = hs.mac.Sum(nil)[:markLength]
+ }
+
+ // Attempt to find the mark + MAC.
+ pos := findMarkMac(hs.clientMark, resp, ntor.RepresentativeLength+clientMinPadLength,
+ maxHandshakeLength, true)
+ if pos == -1 {
+ if len(resp) >= maxHandshakeLength {
+ return nil, ErrInvalidHandshake
+ }
+ return nil, ErrMarkNotFoundYet
+ }
+
+ // Validate the MAC.
+ macFound := false
+ for _, off := range []int64{0, -1, 1} {
+ // Allow epoch to be off by up to a hour in either direction.
+ epochHour := []byte(strconv.FormatInt(getEpochHour()+int64(off), 10))
+ hs.mac.Reset()
+ hs.mac.Write(resp[:pos+markLength])
+ hs.mac.Write(epochHour)
+ macCmp := hs.mac.Sum(nil)[:macLength]
+ macRx := resp[pos+markLength : pos+markLength+macLength]
+ if hmac.Equal(macCmp, macRx) {
+ // Ensure that this handshake has not been seen previously.
+ if filter.TestAndSet(time.Now(), macRx) {
+ // The client either happened to generate exactly the same
+ // session key and padding, or someone is replaying a previous
+ // handshake. In either case, fuck them.
+ return nil, ErrReplayedHandshake
+ }
+
+ macFound = true
+ hs.epochHour = epochHour
+
+ // We could break out here, but in the name of reducing timing
+ // variation, evaluate all 3 MACs.
+ }
+ }
+ if !macFound {
+ // This probably should be an InvalidMacError, but conveying the 3 MACS
+ // that would be accepted is annoying so just return a generic fatal
+ // failure.
+ return nil, ErrInvalidHandshake
+ }
+
+ // Client should never sent trailing garbage.
+ if len(resp) != pos+markLength+macLength {
+ return nil, ErrInvalidHandshake
+ }
+
+ clientPublic := hs.clientRepresentative.ToPublic()
+ ok, seed, auth := ntor.ServerHandshake(clientPublic, hs.keypair,
+ hs.serverIdentity, hs.nodeID)
+ if !ok {
+ return nil, ErrNtorFailed
+ }
+ hs.serverAuth = auth
+
+ return seed.Bytes()[:], nil
+}
+
+func (hs *serverHandshake) generateHandshake() ([]byte, error) {
+ var buf bytes.Buffer
+
+ hs.mac.Reset()
+ hs.mac.Write(hs.keypair.Representative().Bytes()[:])
+ mark := hs.mac.Sum(nil)[:markLength]
+
+ // The server handshake is Y | AUTH | P_S | M_S | MAC(Y | AUTH | P_S | M_S | E) where:
+ // * Y is the server's ephemeral Curve25519 public key representative.
+ // * AUTH is the ntor handshake AUTH value.
+ // * P_S is [serverMinPadLength,serverMaxPadLength] bytes of random padding.
+ // * M_S is HMAC-SHA256-128(serverIdentity | NodeID, Y)
+ // * MAC is HMAC-SHA256-128(serverIdentity | NodeID, Y .... E)
+ // * E is the string representation of the number of hours since the UNIX
+ // epoch.
+
+ // Generate the padding
+ pad, err := makePad(hs.padLen)
+ if err != nil {
+ return nil, err
+ }
+
+ // Write Y, AUTH, P_S, M_S.
+ buf.Write(hs.keypair.Representative().Bytes()[:])
+ buf.Write(hs.serverAuth.Bytes()[:])
+ buf.Write(pad)
+ buf.Write(mark)
+
+ // Calculate and write the MAC.
+ hs.mac.Reset()
+ hs.mac.Write(buf.Bytes())
+ hs.mac.Write(hs.epochHour) // Set in hs.parseClientHandshake()
+ buf.Write(hs.mac.Sum(nil)[:macLength])
+
+ return buf.Bytes(), nil
+}
+
+// getEpochHour returns the number of hours since the UNIX epoch.
+func getEpochHour() int64 {
+ return time.Now().Unix() / 3600
+}
+
+func findMarkMac(mark, buf []byte, startPos, maxPos int, fromTail bool) (pos int) {
+ if len(mark) != markLength {
+ panic(fmt.Sprintf("BUG: Invalid mark length: %d", len(mark)))
+ }
+
+ endPos := len(buf)
+ if startPos > len(buf) {
+ return -1
+ }
+ if endPos > maxPos {
+ endPos = maxPos
+ }
+ if endPos-startPos < markLength+macLength {
+ return -1
+ }
+
+ if fromTail {
+ // The server can optimize the search process by only examining the
+ // tail of the buffer. The client can't send valid data past M_C |
+ // MAC_C as it does not have the server's public key yet.
+ pos = endPos - (markLength + macLength)
+ if !hmac.Equal(buf[pos:pos+markLength], mark) {
+ return -1
+ }
+
+ return
+ }
+
+ // The client has to actually do a substring search since the server can
+ // and will send payload trailing the response.
+ //
+ // XXX: bytes.Index() uses a naive search, which kind of sucks.
+ pos = bytes.Index(buf[startPos:endPos], mark)
+ if pos == -1 {
+ return -1
+ }
+
+ // Ensure that there is enough trailing data for the MAC.
+ if startPos+pos+markLength+macLength > endPos {
+ return -1
+ }
+
+ // Return the index relative to the start of the slice.
+ pos += startPos
+ return
+}
+
+func makePad(padLen int) ([]byte, error) {
+ pad := make([]byte, padLen)
+ if err := csrand.Bytes(pad); err != nil {
+ return nil, err
+ }
+
+ return pad, nil
+}
diff --git a/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/obfs4.go b/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/obfs4.go
new file mode 100644
index 0000000..304097e
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/obfs4.go
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2014, Yawning Angel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Package obfs4 provides an implementation of the Tor Project's obfs4
+// obfuscation protocol.
+package obfs4
+
+import (
+ "bytes"
+ "crypto/sha256"
+ "flag"
+ "fmt"
+ "math/rand"
+ "net"
+ "strconv"
+ "syscall"
+ "time"
+
+ "git.torproject.org/pluggable-transports/goptlib.git"
+ "git.torproject.org/pluggable-transports/obfs4.git/common/drbg"
+ "git.torproject.org/pluggable-transports/obfs4.git/common/ntor"
+ "git.torproject.org/pluggable-transports/obfs4.git/common/probdist"
+ "git.torproject.org/pluggable-transports/obfs4.git/common/replayfilter"
+ "git.torproject.org/pluggable-transports/obfs4.git/transports/base"
+ "git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/framing"
+)
+
+const (
+ transportName = "obfs4"
+
+ nodeIDArg = "node-id"
+ publicKeyArg = "public-key"
+ privateKeyArg = "private-key"
+ seedArg = "drbg-seed"
+ iatArg = "iat-mode"
+ certArg = "cert"
+
+ biasCmdArg = "obfs4-distBias"
+
+ seedLength = drbg.SeedLength
+ headerLength = framing.FrameOverhead + packetOverhead
+ clientHandshakeTimeout = time.Duration(60) * time.Second
+ serverHandshakeTimeout = time.Duration(30) * time.Second
+ replayTTL = time.Duration(3) * time.Hour
+
+ maxIATDelay = 100
+ maxCloseDelayBytes = maxHandshakeLength
+ maxCloseDelay = 60
+)
+
+const (
+ iatNone = iota
+ iatEnabled
+ iatParanoid
+)
+
+// biasedDist controls if the probability table will be ScrambleSuit style or
+// uniformly distributed.
+var biasedDist bool
+
+type obfs4ClientArgs struct {
+ nodeID *ntor.NodeID
+ publicKey *ntor.PublicKey
+ sessionKey *ntor.Keypair
+ iatMode int
+}
+
+// Transport is the obfs4 implementation of the base.Transport interface.
+type Transport struct{}
+
+// Name returns the name of the obfs4 transport protocol.
+func (t *Transport) Name() string {
+ return transportName
+}
+
+// ClientFactory returns a new obfs4ClientFactory instance.
+func (t *Transport) ClientFactory(stateDir string) (base.ClientFactory, error) {
+ cf := &obfs4ClientFactory{transport: t}
+ return cf, nil
+}
+
+// ServerFactory returns a new obfs4ServerFactory instance.
+func (t *Transport) ServerFactory(stateDir string, args *pt.Args) (base.ServerFactory, error) {
+ st, err := serverStateFromArgs(stateDir, args)
+ if err != nil {
+ return nil, err
+ }
+
+ var iatSeed *drbg.Seed
+ if st.iatMode != iatNone {
+ iatSeedSrc := sha256.Sum256(st.drbgSeed.Bytes()[:])
+ var err error
+ iatSeed, err = drbg.SeedFromBytes(iatSeedSrc[:])
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // Store the arguments that should appear in our descriptor for the clients.
+ ptArgs := pt.Args{}
+ ptArgs.Add(certArg, st.cert.String())
+ ptArgs.Add(iatArg, strconv.Itoa(st.iatMode))
+
+ // Initialize the replay filter.
+ filter, err := replayfilter.New(replayTTL)
+ if err != nil {
+ return nil, err
+ }
+
+ // Initialize the close thresholds for failed connections.
+ drbg, err := drbg.NewHashDrbg(st.drbgSeed)
+ if err != nil {
+ return nil, err
+ }
+ rng := rand.New(drbg)
+
+ sf := &obfs4ServerFactory{t, &ptArgs, st.nodeID, st.identityKey, st.drbgSeed, iatSeed, st.iatMode, filter, rng.Intn(maxCloseDelayBytes), rng.Intn(maxCloseDelay)}
+ return sf, nil
+}
+
+type obfs4ClientFactory struct {
+ transport base.Transport
+}
+
+func (cf *obfs4ClientFactory) Transport() base.Transport {
+ return cf.transport
+}
+
+func (cf *obfs4ClientFactory) ParseArgs(args *pt.Args) (interface{}, error) {
+ var nodeID *ntor.NodeID
+ var publicKey *ntor.PublicKey
+
+ // The "new" (version >= 0.0.3) bridge lines use a unified "cert" argument
+ // for the Node ID and Public Key.
+ certStr, ok := args.Get(certArg)
+ if ok {
+ cert, err := serverCertFromString(certStr)
+ if err != nil {
+ return nil, err
+ }
+ nodeID, publicKey = cert.unpack()
+ } else {
+ // The "old" style (version <= 0.0.2) bridge lines use separate Node ID
+ // and Public Key arguments in Base16 encoding and are a UX disaster.
+ nodeIDStr, ok := args.Get(nodeIDArg)
+ if !ok {
+ return nil, fmt.Errorf("missing argument '%s'", nodeIDArg)
+ }
+ var err error
+ if nodeID, err = ntor.NodeIDFromHex(nodeIDStr); err != nil {
+ return nil, err
+ }
+
+ publicKeyStr, ok := args.Get(publicKeyArg)
+ if !ok {
+ return nil, fmt.Errorf("missing argument '%s'", publicKeyArg)
+ }
+ if publicKey, err = ntor.PublicKeyFromHex(publicKeyStr); err != nil {
+ return nil, err
+ }
+ }
+
+ // IAT config is common across the two bridge line formats.
+ iatStr, ok := args.Get(iatArg)
+ if !ok {
+ return nil, fmt.Errorf("missing argument '%s'", iatArg)
+ }
+ iatMode, err := strconv.Atoi(iatStr)
+ if err != nil || iatMode < iatNone || iatMode > iatParanoid {
+ return nil, fmt.Errorf("invalid iat-mode '%d'", iatMode)
+ }
+
+ // Generate the session key pair before connectiong to hide the Elligator2
+ // rejection sampling from network observers.
+ sessionKey, err := ntor.NewKeypair(true)
+ if err != nil {
+ return nil, err
+ }
+
+ return &obfs4ClientArgs{nodeID, publicKey, sessionKey, iatMode}, nil
+}
+
+func (cf *obfs4ClientFactory) Dial(network, addr string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
+ // Validate args before bothering to open connection.
+ ca, ok := args.(*obfs4ClientArgs)
+ if !ok {
+ return nil, fmt.Errorf("invalid argument type for args")
+ }
+ conn, err := dialFn(network, addr)
+ if err != nil {
+ return nil, err
+ }
+ dialConn := conn
+ if conn, err = newObfs4ClientConn(conn, ca); err != nil {
+ dialConn.Close()
+ return nil, err
+ }
+ return conn, nil
+}
+
+type obfs4ServerFactory struct {
+ transport base.Transport
+ args *pt.Args
+
+ nodeID *ntor.NodeID
+ identityKey *ntor.Keypair
+ lenSeed *drbg.Seed
+ iatSeed *drbg.Seed
+ iatMode int
+ replayFilter *replayfilter.ReplayFilter
+
+ closeDelayBytes int
+ closeDelay int
+}
+
+func (sf *obfs4ServerFactory) Transport() base.Transport {
+ return sf.transport
+}
+
+func (sf *obfs4ServerFactory) Args() *pt.Args {
+ return sf.args
+}
+
+func (sf *obfs4ServerFactory) WrapConn(conn net.Conn) (net.Conn, error) {
+ // Not much point in having a separate newObfs4ServerConn routine when
+ // wrapping requires using values from the factory instance.
+
+ // Generate the session keypair *before* consuming data from the peer, to
+ // attempt to mask the rejection sampling due to use of Elligator2. This
+ // might be futile, but the timing differential isn't very large on modern
+ // hardware, and there are far easier statistical attacks that can be
+ // mounted as a distinguisher.
+ sessionKey, err := ntor.NewKeypair(true)
+ if err != nil {
+ return nil, err
+ }
+
+ lenDist := probdist.New(sf.lenSeed, 0, framing.MaximumSegmentLength, biasedDist)
+ var iatDist *probdist.WeightedDist
+ if sf.iatSeed != nil {
+ iatDist = probdist.New(sf.iatSeed, 0, maxIATDelay, biasedDist)
+ }
+
+ c := &obfs4Conn{conn, true, lenDist, iatDist, sf.iatMode, bytes.NewBuffer(nil), bytes.NewBuffer(nil), make([]byte, consumeReadSize), nil, nil}
+
+ startTime := time.Now()
+
+ if err = c.serverHandshake(sf, sessionKey); err != nil {
+ c.closeAfterDelay(sf, startTime)
+ return nil, err
+ }
+
+ return c, nil
+}
+
+type obfs4Conn struct {
+ net.Conn
+
+ isServer bool
+
+ lenDist *probdist.WeightedDist
+ iatDist *probdist.WeightedDist
+ iatMode int
+
+ receiveBuffer *bytes.Buffer
+ receiveDecodedBuffer *bytes.Buffer
+ readBuffer []byte
+
+ encoder *framing.Encoder
+ decoder *framing.Decoder
+}
+
+func newObfs4ClientConn(conn net.Conn, args *obfs4ClientArgs) (c *obfs4Conn, err error) {
+ // Generate the initial protocol polymorphism distribution(s).
+ var seed *drbg.Seed
+ if seed, err = drbg.NewSeed(); err != nil {
+ return
+ }
+ lenDist := probdist.New(seed, 0, framing.MaximumSegmentLength, biasedDist)
+ var iatDist *probdist.WeightedDist
+ if args.iatMode != iatNone {
+ var iatSeed *drbg.Seed
+ iatSeedSrc := sha256.Sum256(seed.Bytes()[:])
+ if iatSeed, err = drbg.SeedFromBytes(iatSeedSrc[:]); err != nil {
+ return
+ }
+ iatDist = probdist.New(iatSeed, 0, maxIATDelay, biasedDist)
+ }
+
+ // Allocate the client structure.
+ c = &obfs4Conn{conn, false, lenDist, iatDist, args.iatMode, bytes.NewBuffer(nil), bytes.NewBuffer(nil), make([]byte, consumeReadSize), nil, nil}
+
+ // Start the handshake timeout.
+ deadline := time.Now().Add(clientHandshakeTimeout)
+ if err = conn.SetDeadline(deadline); err != nil {
+ return nil, err
+ }
+
+ if err = c.clientHandshake(args.nodeID, args.publicKey, args.sessionKey); err != nil {
+ return nil, err
+ }
+
+ // Stop the handshake timeout.
+ if err = conn.SetDeadline(time.Time{}); err != nil {
+ return nil, err
+ }
+
+ return
+}
+
+func (conn *obfs4Conn) clientHandshake(nodeID *ntor.NodeID, peerIdentityKey *ntor.PublicKey, sessionKey *ntor.Keypair) error {
+ if conn.isServer {
+ return fmt.Errorf("clientHandshake called on server connection")
+ }
+
+ // Generate and send the client handshake.
+ hs := newClientHandshake(nodeID, peerIdentityKey, sessionKey)
+ blob, err := hs.generateHandshake()
+ if err != nil {
+ return err
+ }
+ if _, err = conn.Conn.Write(blob); err != nil {
+ return err
+ }
+
+ // Consume the server handshake.
+ var hsBuf [maxHandshakeLength]byte
+ for {
+ n, err := conn.Conn.Read(hsBuf[:])
+ if err != nil {
+ // The Read() could have returned data and an error, but there is
+ // no point in continuing on an EOF or whatever.
+ return err
+ }
+ conn.receiveBuffer.Write(hsBuf[:n])
+
+ n, seed, err := hs.parseServerHandshake(conn.receiveBuffer.Bytes())
+ if err == ErrMarkNotFoundYet {
+ continue
+ } else if err != nil {
+ return err
+ }
+ _ = conn.receiveBuffer.Next(n)
+
+ // Use the derived key material to intialize the link crypto.
+ okm := ntor.Kdf(seed, framing.KeyLength*2)
+ conn.encoder = framing.NewEncoder(okm[:framing.KeyLength])
+ conn.decoder = framing.NewDecoder(okm[framing.KeyLength:])
+
+ return nil
+ }
+}
+
+func (conn *obfs4Conn) serverHandshake(sf *obfs4ServerFactory, sessionKey *ntor.Keypair) error {
+ if !conn.isServer {
+ return fmt.Errorf("serverHandshake called on client connection")
+ }
+
+ // Generate the server handshake, and arm the base timeout.
+ hs := newServerHandshake(sf.nodeID, sf.identityKey, sessionKey)
+ if err := conn.Conn.SetDeadline(time.Now().Add(serverHandshakeTimeout)); err != nil {
+ return err
+ }
+
+ // Consume the client handshake.
+ var hsBuf [maxHandshakeLength]byte
+ for {
+ n, err := conn.Conn.Read(hsBuf[:])
+ if err != nil {
+ // The Read() could have returned data and an error, but there is
+ // no point in continuing on an EOF or whatever.
+ return err
+ }
+ conn.receiveBuffer.Write(hsBuf[:n])
+
+ seed, err := hs.parseClientHandshake(sf.replayFilter, conn.receiveBuffer.Bytes())
+ if err == ErrMarkNotFoundYet {
+ continue
+ } else if err != nil {
+ return err
+ }
+ conn.receiveBuffer.Reset()
+
+ if err := conn.Conn.SetDeadline(time.Time{}); err != nil {
+ return nil
+ }
+
+ // Use the derived key material to intialize the link crypto.
+ okm := ntor.Kdf(seed, framing.KeyLength*2)
+ conn.encoder = framing.NewEncoder(okm[framing.KeyLength:])
+ conn.decoder = framing.NewDecoder(okm[:framing.KeyLength])
+
+ break
+ }
+
+ // Since the current and only implementation always sends a PRNG seed for
+ // the length obfuscation, this makes the amount of data received from the
+ // server inconsistent with the length sent from the client.
+ //
+ // Rebalance this by tweaking the client mimimum padding/server maximum
+ // padding, and sending the PRNG seed unpadded (As in, treat the PRNG seed
+ // as part of the server response). See inlineSeedFrameLength in
+ // handshake_ntor.go.
+
+ // Generate/send the response.
+ blob, err := hs.generateHandshake()
+ if err != nil {
+ return err
+ }
+ var frameBuf bytes.Buffer
+ if _, err = frameBuf.Write(blob); err != nil {
+ return err
+ }
+
+ // Send the PRNG seed as the first packet.
+ if err := conn.makePacket(&frameBuf, packetTypePrngSeed, sf.lenSeed.Bytes()[:], 0); err != nil {
+ return err
+ }
+ if _, err = conn.Conn.Write(frameBuf.Bytes()); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (conn *obfs4Conn) Read(b []byte) (n int, err error) {
+ // If there is no payload from the previous Read() calls, consume data off
+ // the network. Not all data received is guaranteed to be usable payload,
+ // so do this in a loop till data is present or an error occurs.
+ for conn.receiveDecodedBuffer.Len() == 0 {
+ err = conn.readPackets()
+ if err == framing.ErrAgain {
+ // Don't proagate this back up the call stack if we happen to break
+ // out of the loop.
+ err = nil
+ continue
+ } else if err != nil {
+ break
+ }
+ }
+
+ // Even if err is set, attempt to do the read anyway so that all decoded
+ // data gets relayed before the connection is torn down.
+ if conn.receiveDecodedBuffer.Len() > 0 {
+ var berr error
+ n, berr = conn.receiveDecodedBuffer.Read(b)
+ if err == nil {
+ // Only propagate berr if there are not more important (fatal)
+ // errors from the network/crypto/packet processing.
+ err = berr
+ }
+ }
+
+ return
+}
+
+func (conn *obfs4Conn) Write(b []byte) (n int, err error) {
+ chopBuf := bytes.NewBuffer(b)
+ var payload [maxPacketPayloadLength]byte
+ var frameBuf bytes.Buffer
+
+ // Chop the pending data into payload frames.
+ for chopBuf.Len() > 0 {
+ // Send maximum sized frames.
+ rdLen := 0
+ rdLen, err = chopBuf.Read(payload[:])
+ if err != nil {
+ return 0, err
+ } else if rdLen == 0 {
+ panic(fmt.Sprintf("BUG: Write(), chopping length was 0"))
+ }
+ n += rdLen
+
+ err = conn.makePacket(&frameBuf, packetTypePayload, payload[:rdLen], 0)
+ if err != nil {
+ return 0, err
+ }
+ }
+
+ if conn.iatMode != iatParanoid {
+ // For non-paranoid IAT, pad once per burst. Paranoid IAT handles
+ // things differently.
+ if err = conn.padBurst(&frameBuf, conn.lenDist.Sample()); err != nil {
+ return 0, err
+ }
+ }
+
+ // Write the pending data onto the network. Partial writes are fatal,
+ // because the frame encoder state is advanced, and the code doesn't keep
+ // frameBuf around. In theory, write timeouts and whatnot could be
+ // supported if this wasn't the case, but that complicates the code.
+ if conn.iatMode != iatNone {
+ var iatFrame [framing.MaximumSegmentLength]byte
+ for frameBuf.Len() > 0 {
+ iatWrLen := 0
+
+ switch conn.iatMode {
+ case iatEnabled:
+ // Standard (ScrambleSuit-style) IAT obfuscation optimizes for
+ // bulk transport and will write ~MTU sized frames when
+ // possible.
+ iatWrLen, err = frameBuf.Read(iatFrame[:])
+
+ case iatParanoid:
+ // Paranoid IAT obfuscation throws performance out of the
+ // window and will sample the length distribution every time a
+ // write is scheduled.
+ targetLen := conn.lenDist.Sample()
+ if frameBuf.Len() < targetLen {
+ // There's not enough data buffered for the target write,
+ // so padding must be inserted.
+ if err = conn.padBurst(&frameBuf, targetLen); err != nil {
+ return 0, err
+ }
+ if frameBuf.Len() != targetLen {
+ // Ugh, padding came out to a value that required more
+ // than one frame, this is relatively unlikely so just
+ // resample since there's enough data to ensure that
+ // the next sample will be written.
+ continue
+ }
+ }
+ iatWrLen, err = frameBuf.Read(iatFrame[:targetLen])
+ }
+ if err != nil {
+ return 0, err
+ } else if iatWrLen == 0 {
+ panic(fmt.Sprintf("BUG: Write(), iat length was 0"))
+ }
+
+ // Calculate the delay. The delay resolution is 100 usec, leading
+ // to a maximum delay of 10 msec.
+ iatDelta := time.Duration(conn.iatDist.Sample() * 100)
+
+ // Write then sleep.
+ _, err = conn.Conn.Write(iatFrame[:iatWrLen])
+ if err != nil {
+ return 0, err
+ }
+ time.Sleep(iatDelta * time.Microsecond)
+ }
+ } else {
+ _, err = conn.Conn.Write(frameBuf.Bytes())
+ }
+
+ return
+}
+
+func (conn *obfs4Conn) SetDeadline(t time.Time) error {
+ return syscall.ENOTSUP
+}
+
+func (conn *obfs4Conn) SetWriteDeadline(t time.Time) error {
+ return syscall.ENOTSUP
+}
+
+func (conn *obfs4Conn) closeAfterDelay(sf *obfs4ServerFactory, startTime time.Time) {
+ // I-it's not like I w-wanna handshake with you or anything. B-b-baka!
+ defer conn.Conn.Close()
+
+ delay := time.Duration(sf.closeDelay)*time.Second + serverHandshakeTimeout
+ deadline := startTime.Add(delay)
+ if time.Now().After(deadline) {
+ return
+ }
+
+ if err := conn.Conn.SetReadDeadline(deadline); err != nil {
+ return
+ }
+
+ // Consume and discard data on this connection until either the specified
+ // interval passes or a certain size has been reached.
+ discarded := 0
+ var buf [framing.MaximumSegmentLength]byte
+ for discarded < int(sf.closeDelayBytes) {
+ n, err := conn.Conn.Read(buf[:])
+ if err != nil {
+ return
+ }
+ discarded += n
+ }
+}
+
+func (conn *obfs4Conn) padBurst(burst *bytes.Buffer, toPadTo int) (err error) {
+ tailLen := burst.Len() % framing.MaximumSegmentLength
+
+ padLen := 0
+ if toPadTo >= tailLen {
+ padLen = toPadTo - tailLen
+ } else {
+ padLen = (framing.MaximumSegmentLength - tailLen) + toPadTo
+ }
+
+ if padLen > headerLength {
+ err = conn.makePacket(burst, packetTypePayload, []byte{},
+ uint16(padLen-headerLength))
+ if err != nil {
+ return
+ }
+ } else if padLen > 0 {
+ err = conn.makePacket(burst, packetTypePayload, []byte{},
+ maxPacketPayloadLength)
+ if err != nil {
+ return
+ }
+ err = conn.makePacket(burst, packetTypePayload, []byte{},
+ uint16(padLen))
+ if err != nil {
+ return
+ }
+ }
+
+ return
+}
+
+func init() {
+ flag.BoolVar(&biasedDist, biasCmdArg, false, "Enable obfs4 using ScrambleSuit style table generation")
+}
+
+var _ base.ClientFactory = (*obfs4ClientFactory)(nil)
+var _ base.ServerFactory = (*obfs4ServerFactory)(nil)
+var _ base.Transport = (*Transport)(nil)
+var _ net.Conn = (*obfs4Conn)(nil)
diff --git a/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/packet.go b/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/packet.go
new file mode 100644
index 0000000..5125be6
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/packet.go
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2014, Yawning Angel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package obfs4
+
+import (
+ "crypto/sha256"
+ "encoding/binary"
+ "fmt"
+ "io"
+
+ "git.torproject.org/pluggable-transports/obfs4.git/common/drbg"
+ "git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/framing"
+)
+
+const (
+ packetOverhead = 2 + 1
+ maxPacketPayloadLength = framing.MaximumFramePayloadLength - packetOverhead
+ maxPacketPaddingLength = maxPacketPayloadLength
+ seedPacketPayloadLength = seedLength
+
+ consumeReadSize = framing.MaximumSegmentLength * 16
+)
+
+const (
+ packetTypePayload = iota
+ packetTypePrngSeed
+)
+
+// InvalidPacketLengthError is the error returned when decodePacket detects a
+// invalid packet length/
+type InvalidPacketLengthError int
+
+func (e InvalidPacketLengthError) Error() string {
+ return fmt.Sprintf("packet: Invalid packet length: %d", int(e))
+}
+
+// InvalidPayloadLengthError is the error returned when decodePacket rejects the
+// payload length.
+type InvalidPayloadLengthError int
+
+func (e InvalidPayloadLengthError) Error() string {
+ return fmt.Sprintf("packet: Invalid payload length: %d", int(e))
+}
+
+var zeroPadBytes [maxPacketPaddingLength]byte
+
+func (conn *obfs4Conn) makePacket(w io.Writer, pktType uint8, data []byte, padLen uint16) error {
+ var pkt [framing.MaximumFramePayloadLength]byte
+
+ if len(data)+int(padLen) > maxPacketPayloadLength {
+ panic(fmt.Sprintf("BUG: makePacket() len(data) + padLen > maxPacketPayloadLength: %d + %d > %d",
+ len(data), padLen, maxPacketPayloadLength))
+ }
+
+ // Packets are:
+ // uint8_t type packetTypePayload (0x00)
+ // uint16_t length Length of the payload (Big Endian).
+ // uint8_t[] payload Data payload.
+ // uint8_t[] padding Padding.
+ pkt[0] = pktType
+ binary.BigEndian.PutUint16(pkt[1:], uint16(len(data)))
+ if len(data) > 0 {
+ copy(pkt[3:], data[:])
+ }
+ copy(pkt[3+len(data):], zeroPadBytes[:padLen])
+
+ pktLen := packetOverhead + len(data) + int(padLen)
+
+ // Encode the packet in an AEAD frame.
+ var frame [framing.MaximumSegmentLength]byte
+ frameLen, err := conn.encoder.Encode(frame[:], pkt[:pktLen])
+ if err != nil {
+ // All encoder errors are fatal.
+ return err
+ }
+ wrLen, err := w.Write(frame[:frameLen])
+ if err != nil {
+ return err
+ } else if wrLen < frameLen {
+ return io.ErrShortWrite
+ }
+
+ return nil
+}
+
+func (conn *obfs4Conn) readPackets() (err error) {
+ // Attempt to read off the network.
+ rdLen, rdErr := conn.Conn.Read(conn.readBuffer)
+ conn.receiveBuffer.Write(conn.readBuffer[:rdLen])
+
+ var decoded [framing.MaximumFramePayloadLength]byte
+ for conn.receiveBuffer.Len() > 0 {
+ // Decrypt an AEAD frame.
+ decLen := 0
+ decLen, err = conn.decoder.Decode(decoded[:], conn.receiveBuffer)
+ if err == framing.ErrAgain {
+ break
+ } else if err != nil {
+ break
+ } else if decLen < packetOverhead {
+ err = InvalidPacketLengthError(decLen)
+ break
+ }
+
+ // Decode the packet.
+ pkt := decoded[0:decLen]
+ pktType := pkt[0]
+ payloadLen := binary.BigEndian.Uint16(pkt[1:])
+ if int(payloadLen) > len(pkt)-packetOverhead {
+ err = InvalidPayloadLengthError(int(payloadLen))
+ break
+ }
+ payload := pkt[3 : 3+payloadLen]
+
+ switch pktType {
+ case packetTypePayload:
+ if payloadLen > 0 {
+ conn.receiveDecodedBuffer.Write(payload)
+ }
+ case packetTypePrngSeed:
+ // Only regenerate the distribution if we are the client.
+ if len(payload) == seedPacketPayloadLength && !conn.isServer {
+ var seed *drbg.Seed
+ seed, err = drbg.SeedFromBytes(payload)
+ if err != nil {
+ break
+ }
+ conn.lenDist.Reset(seed)
+ if conn.iatDist != nil {
+ iatSeedSrc := sha256.Sum256(seed.Bytes()[:])
+ iatSeed, err := drbg.SeedFromBytes(iatSeedSrc[:])
+ if err != nil {
+ break
+ }
+ conn.iatDist.Reset(iatSeed)
+ }
+ }
+ default:
+ // Ignore unknown packet types.
+ }
+ }
+
+ // Read errors (all fatal) take priority over various frame processing
+ // errors.
+ if rdErr != nil {
+ return rdErr
+ }
+
+ return
+}
diff --git a/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/statefile.go b/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/statefile.go
new file mode 100644
index 0000000..e4ff8bf
--- /dev/null
+++ b/vendor/git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/statefile.go
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2014, Yawning Angel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package obfs4
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path"
+ "strconv"
+ "strings"
+
+ "git.torproject.org/pluggable-transports/goptlib.git"
+ "git.torproject.org/pluggable-transports/obfs4.git/common/csrand"
+ "git.torproject.org/pluggable-transports/obfs4.git/common/drbg"
+ "git.torproject.org/pluggable-transports/obfs4.git/common/ntor"
+)
+
+const (
+ stateFile = "obfs4_state.json"
+ bridgeFile = "obfs4_bridgeline.txt"
+
+ certSuffix = "=="
+ certLength = ntor.NodeIDLength + ntor.PublicKeyLength
+)
+
+type jsonServerState struct {
+ NodeID string `json:"node-id"`
+ PrivateKey string `json:"private-key"`
+ PublicKey string `json:"public-key"`
+ DrbgSeed string `json:"drbg-seed"`
+ IATMode int `json:"iat-mode"`
+}
+
+type obfs4ServerCert struct {
+ raw []byte
+}
+
+func (cert *obfs4ServerCert) String() string {
+ return strings.TrimSuffix(base64.StdEncoding.EncodeToString(cert.raw), certSuffix)
+}
+
+func (cert *obfs4ServerCert) unpack() (*ntor.NodeID, *ntor.PublicKey) {
+ if len(cert.raw) != certLength {
+ panic(fmt.Sprintf("cert length %d is invalid", len(cert.raw)))
+ }
+
+ nodeID, _ := ntor.NewNodeID(cert.raw[:ntor.NodeIDLength])
+ pubKey, _ := ntor.NewPublicKey(cert.raw[ntor.NodeIDLength:])
+
+ return nodeID, pubKey
+}
+
+func serverCertFromString(encoded string) (*obfs4ServerCert, error) {
+ decoded, err := base64.StdEncoding.DecodeString(encoded + certSuffix)
+ if err != nil {
+ return nil, fmt.Errorf("failed to decode cert: %s", err)
+ }
+
+ if len(decoded) != certLength {
+ return nil, fmt.Errorf("cert length %d is invalid", len(decoded))
+ }
+
+ return &obfs4ServerCert{raw: decoded}, nil
+}
+
+func serverCertFromState(st *obfs4ServerState) *obfs4ServerCert {
+ cert := new(obfs4ServerCert)
+ cert.raw = append(st.nodeID.Bytes()[:], st.identityKey.Public().Bytes()[:]...)
+ return cert
+}
+
+type obfs4ServerState struct {
+ nodeID *ntor.NodeID
+ identityKey *ntor.Keypair
+ drbgSeed *drbg.Seed
+ iatMode int
+
+ cert *obfs4ServerCert
+}
+
+func (st *obfs4ServerState) clientString() string {
+ return fmt.Sprintf("%s=%s %s=%d", certArg, st.cert, iatArg, st.iatMode)
+}
+
+func serverStateFromArgs(stateDir string, args *pt.Args) (*obfs4ServerState, error) {
+ var js jsonServerState
+ var nodeIDOk, privKeyOk, seedOk bool
+
+ js.NodeID, nodeIDOk = args.Get(nodeIDArg)
+ js.PrivateKey, privKeyOk = args.Get(privateKeyArg)
+ js.DrbgSeed, seedOk = args.Get(seedArg)
+ iatStr, iatOk := args.Get(iatArg)
+
+ // Either a private key, node id, and seed are ALL specified, or
+ // they should be loaded from the state file.
+ if !privKeyOk && !nodeIDOk && !seedOk {
+ if err := jsonServerStateFromFile(stateDir, &js); err != nil {
+ return nil, err
+ }
+ } else if !privKeyOk {
+ return nil, fmt.Errorf("missing argument '%s'", privateKeyArg)
+ } else if !nodeIDOk {
+ return nil, fmt.Errorf("missing argument '%s'", nodeIDArg)
+ } else if !seedOk {
+ return nil, fmt.Errorf("missing argument '%s'", seedArg)
+ }
+
+ // The IAT mode should be independently configurable.
+ if iatOk {
+ // If the IAT mode is specified, attempt to parse and apply it
+ // as an override.
+ iatMode, err := strconv.Atoi(iatStr)
+ if err != nil {
+ return nil, fmt.Errorf("malformed iat-mode '%s'", iatStr)
+ }
+ js.IATMode = iatMode
+ }
+
+ return serverStateFromJSONServerState(stateDir, &js)
+}
+
+func serverStateFromJSONServerState(stateDir string, js *jsonServerState) (*obfs4ServerState, error) {
+ var err error
+
+ st := new(obfs4ServerState)
+ if st.nodeID, err = ntor.NodeIDFromHex(js.NodeID); err != nil {
+ return nil, err
+ }
+ if st.identityKey, err = ntor.KeypairFromHex(js.PrivateKey); err != nil {
+ return nil, err
+ }
+ if st.drbgSeed, err = drbg.SeedFromHex(js.DrbgSeed); err != nil {
+ return nil, err
+ }
+ if js.IATMode < iatNone || js.IATMode > iatParanoid {
+ return nil, fmt.Errorf("invalid iat-mode '%d'", js.IATMode)
+ }
+ st.iatMode = js.IATMode
+ st.cert = serverCertFromState(st)
+
+ // Generate a human readable summary of the configured endpoint.
+ if err = newBridgeFile(stateDir, st); err != nil {
+ return nil, err
+ }
+
+ // Write back the possibly updated server state.
+ return st, writeJSONServerState(stateDir, js)
+}
+
+func jsonServerStateFromFile(stateDir string, js *jsonServerState) error {
+ fPath := path.Join(stateDir, stateFile)
+ f, err := ioutil.ReadFile(fPath)
+ if err != nil {
+ if os.IsNotExist(err) {
+ if err = newJSONServerState(stateDir, js); err == nil {
+ return nil
+ }
+ }
+ return err
+ }
+
+ if err := json.Unmarshal(f, js); err != nil {
+ return fmt.Errorf("failed to load statefile '%s': %s", fPath, err)
+ }
+
+ return nil
+}
+
+func newJSONServerState(stateDir string, js *jsonServerState) (err error) {
+ // Generate everything a server needs, using the cryptographic PRNG.
+ var st obfs4ServerState
+ rawID := make([]byte, ntor.NodeIDLength)
+ if err = csrand.Bytes(rawID); err != nil {
+ return
+ }
+ if st.nodeID, err = ntor.NewNodeID(rawID); err != nil {
+ return
+ }
+ if st.identityKey, err = ntor.NewKeypair(false); err != nil {
+ return
+ }
+ if st.drbgSeed, err = drbg.NewSeed(); err != nil {
+ return
+ }
+ st.iatMode = iatNone
+
+ // Encode it into JSON format and write the state file.
+ js.NodeID = st.nodeID.Hex()
+ js.PrivateKey = st.identityKey.Private().Hex()
+ js.PublicKey = st.identityKey.Public().Hex()
+ js.DrbgSeed = st.drbgSeed.Hex()
+ js.IATMode = st.iatMode
+
+ return writeJSONServerState(stateDir, js)
+}
+
+func writeJSONServerState(stateDir string, js *jsonServerState) error {
+ var err error
+ var encoded []byte
+ if encoded, err = json.Marshal(js); err != nil {
+ return err
+ }
+ if err = ioutil.WriteFile(path.Join(stateDir, stateFile), encoded, 0600); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func newBridgeFile(stateDir string, st *obfs4ServerState) error {
+ const prefix = "# obfs4 torrc client bridge line\n" +
+ "#\n" +
+ "# This file is an automatically generated bridge line based on\n" +
+ "# the current obfs4proxy configuration. EDITING IT WILL HAVE\n" +
+ "# NO EFFECT.\n" +
+ "#\n" +
+ "# Before distributing this Bridge, edit the placeholder fields\n" +
+ "# to contain the actual values:\n" +
+ "# - The public IP address of your obfs4 bridge.\n" +
+ "# - The TCP/IP port of your obfs4 bridge.\n" +
+ "# - The bridge's fingerprint.\n\n"
+
+ bridgeLine := fmt.Sprintf("Bridge obfs4 : %s\n",
+ st.clientString())
+
+ tmp := []byte(prefix + bridgeLine)
+ if err := ioutil.WriteFile(path.Join(stateDir, bridgeFile), tmp, 0600); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/cmd/gost/vendor/github.com/Yawning/chacha20/LICENSE b/vendor/github.com/Yawning/chacha20/LICENSE
similarity index 100%
rename from cmd/gost/vendor/github.com/Yawning/chacha20/LICENSE
rename to vendor/github.com/Yawning/chacha20/LICENSE
diff --git a/cmd/gost/vendor/github.com/Yawning/chacha20/README.md b/vendor/github.com/Yawning/chacha20/README.md
similarity index 100%
rename from cmd/gost/vendor/github.com/Yawning/chacha20/README.md
rename to vendor/github.com/Yawning/chacha20/README.md
diff --git a/cmd/gost/vendor/github.com/Yawning/chacha20/chacha20.go b/vendor/github.com/Yawning/chacha20/chacha20.go
similarity index 100%
rename from cmd/gost/vendor/github.com/Yawning/chacha20/chacha20.go
rename to vendor/github.com/Yawning/chacha20/chacha20.go
diff --git a/cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.go b/vendor/github.com/Yawning/chacha20/chacha20_amd64.go
similarity index 100%
rename from cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.go
rename to vendor/github.com/Yawning/chacha20/chacha20_amd64.go
diff --git a/cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.py b/vendor/github.com/Yawning/chacha20/chacha20_amd64.py
similarity index 100%
rename from cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.py
rename to vendor/github.com/Yawning/chacha20/chacha20_amd64.py
diff --git a/cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.s b/vendor/github.com/Yawning/chacha20/chacha20_amd64.s
similarity index 100%
rename from cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.s
rename to vendor/github.com/Yawning/chacha20/chacha20_amd64.s
diff --git a/cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_ref.go b/vendor/github.com/Yawning/chacha20/chacha20_ref.go
similarity index 100%
rename from cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_ref.go
rename to vendor/github.com/Yawning/chacha20/chacha20_ref.go
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/LICENSE b/vendor/github.com/agl/ed25519/LICENSE
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/LICENSE
rename to vendor/github.com/agl/ed25519/LICENSE
diff --git a/vendor/github.com/agl/ed25519/edwards25519/const.go b/vendor/github.com/agl/ed25519/edwards25519/const.go
new file mode 100644
index 0000000..ea5b77a
--- /dev/null
+++ b/vendor/github.com/agl/ed25519/edwards25519/const.go
@@ -0,0 +1,1411 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package edwards25519
+
+var d = FieldElement{
+ -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116,
+}
+
+var d2 = FieldElement{
+ -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199,
+}
+
+var SqrtM1 = FieldElement{
+ -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482,
+}
+
+var A = FieldElement{
+ 486662, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+}
+
+var bi = [8]PreComputedGroupElement{
+ {
+ FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},
+ FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378},
+ FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546},
+ },
+ {
+ FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024},
+ FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574},
+ FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357},
+ },
+ {
+ FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380},
+ FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306},
+ FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942},
+ },
+ {
+ FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766},
+ FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701},
+ FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300},
+ },
+ {
+ FieldElement{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877},
+ FieldElement{-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951},
+ FieldElement{4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784},
+ },
+ {
+ FieldElement{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436},
+ FieldElement{25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918},
+ FieldElement{23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877},
+ },
+ {
+ FieldElement{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800},
+ FieldElement{-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305},
+ FieldElement{-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300},
+ },
+ {
+ FieldElement{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876},
+ FieldElement{-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619},
+ FieldElement{-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683},
+ },
+}
+
+var base = [32][8]PreComputedGroupElement{
+ {
+ {
+ FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},
+ FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378},
+ FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546},
+ },
+ {
+ FieldElement{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303},
+ FieldElement{-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081},
+ FieldElement{26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697},
+ },
+ {
+ FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024},
+ FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574},
+ FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357},
+ },
+ {
+ FieldElement{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540},
+ FieldElement{23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397},
+ FieldElement{7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325},
+ },
+ {
+ FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380},
+ FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306},
+ FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942},
+ },
+ {
+ FieldElement{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777},
+ FieldElement{-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737},
+ FieldElement{-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652},
+ },
+ {
+ FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766},
+ FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701},
+ FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300},
+ },
+ {
+ FieldElement{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726},
+ FieldElement{-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955},
+ FieldElement{27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425},
+ },
+ },
+ {
+ {
+ FieldElement{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171},
+ FieldElement{27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510},
+ FieldElement{17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660},
+ },
+ {
+ FieldElement{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639},
+ FieldElement{29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963},
+ FieldElement{5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950},
+ },
+ {
+ FieldElement{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568},
+ FieldElement{12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335},
+ FieldElement{25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628},
+ },
+ {
+ FieldElement{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007},
+ FieldElement{-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772},
+ FieldElement{-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653},
+ },
+ {
+ FieldElement{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567},
+ FieldElement{13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686},
+ FieldElement{21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372},
+ },
+ {
+ FieldElement{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887},
+ FieldElement{-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954},
+ FieldElement{-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953},
+ },
+ {
+ FieldElement{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833},
+ FieldElement{-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532},
+ FieldElement{-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876},
+ },
+ {
+ FieldElement{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268},
+ FieldElement{33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214},
+ FieldElement{1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038},
+ },
+ },
+ {
+ {
+ FieldElement{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800},
+ FieldElement{4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645},
+ FieldElement{-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664},
+ },
+ {
+ FieldElement{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933},
+ FieldElement{-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182},
+ FieldElement{-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222},
+ },
+ {
+ FieldElement{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991},
+ FieldElement{20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880},
+ FieldElement{9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092},
+ },
+ {
+ FieldElement{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295},
+ FieldElement{19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788},
+ FieldElement{8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553},
+ },
+ {
+ FieldElement{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026},
+ FieldElement{11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347},
+ FieldElement{-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033},
+ },
+ {
+ FieldElement{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395},
+ FieldElement{-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278},
+ FieldElement{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890},
+ },
+ {
+ FieldElement{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995},
+ FieldElement{-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596},
+ FieldElement{-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891},
+ },
+ {
+ FieldElement{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060},
+ FieldElement{11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608},
+ FieldElement{-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606},
+ },
+ },
+ {
+ {
+ FieldElement{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389},
+ FieldElement{-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016},
+ FieldElement{-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341},
+ },
+ {
+ FieldElement{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505},
+ FieldElement{14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553},
+ FieldElement{-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655},
+ },
+ {
+ FieldElement{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220},
+ FieldElement{12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631},
+ FieldElement{-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099},
+ },
+ {
+ FieldElement{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556},
+ FieldElement{14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749},
+ FieldElement{236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930},
+ },
+ {
+ FieldElement{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391},
+ FieldElement{5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253},
+ FieldElement{20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066},
+ },
+ {
+ FieldElement{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958},
+ FieldElement{-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082},
+ FieldElement{-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383},
+ },
+ {
+ FieldElement{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521},
+ FieldElement{-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807},
+ FieldElement{23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948},
+ },
+ {
+ FieldElement{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134},
+ FieldElement{-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455},
+ FieldElement{27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629},
+ },
+ },
+ {
+ {
+ FieldElement{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069},
+ FieldElement{-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746},
+ FieldElement{24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919},
+ },
+ {
+ FieldElement{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837},
+ FieldElement{8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906},
+ FieldElement{-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771},
+ },
+ {
+ FieldElement{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817},
+ FieldElement{10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098},
+ FieldElement{10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409},
+ },
+ {
+ FieldElement{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504},
+ FieldElement{-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727},
+ FieldElement{28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420},
+ },
+ {
+ FieldElement{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003},
+ FieldElement{-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605},
+ FieldElement{-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384},
+ },
+ {
+ FieldElement{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701},
+ FieldElement{-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683},
+ FieldElement{29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708},
+ },
+ {
+ FieldElement{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563},
+ FieldElement{-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260},
+ FieldElement{-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387},
+ },
+ {
+ FieldElement{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672},
+ FieldElement{23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686},
+ FieldElement{-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665},
+ },
+ },
+ {
+ {
+ FieldElement{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182},
+ FieldElement{-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277},
+ FieldElement{14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628},
+ },
+ {
+ FieldElement{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474},
+ FieldElement{-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539},
+ FieldElement{-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822},
+ },
+ {
+ FieldElement{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970},
+ FieldElement{19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756},
+ FieldElement{-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508},
+ },
+ {
+ FieldElement{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683},
+ FieldElement{-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655},
+ FieldElement{-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158},
+ },
+ {
+ FieldElement{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125},
+ FieldElement{-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839},
+ FieldElement{-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664},
+ },
+ {
+ FieldElement{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294},
+ FieldElement{-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899},
+ FieldElement{-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070},
+ },
+ {
+ FieldElement{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294},
+ FieldElement{-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949},
+ FieldElement{-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083},
+ },
+ {
+ FieldElement{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420},
+ FieldElement{-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940},
+ FieldElement{29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396},
+ },
+ },
+ {
+ {
+ FieldElement{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567},
+ FieldElement{20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127},
+ FieldElement{-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294},
+ },
+ {
+ FieldElement{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887},
+ FieldElement{22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964},
+ FieldElement{16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195},
+ },
+ {
+ FieldElement{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244},
+ FieldElement{24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999},
+ FieldElement{-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762},
+ },
+ {
+ FieldElement{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274},
+ FieldElement{-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236},
+ FieldElement{-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605},
+ },
+ {
+ FieldElement{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761},
+ FieldElement{-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884},
+ FieldElement{-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482},
+ },
+ {
+ FieldElement{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638},
+ FieldElement{-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490},
+ FieldElement{-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170},
+ },
+ {
+ FieldElement{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736},
+ FieldElement{10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124},
+ FieldElement{-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392},
+ },
+ {
+ FieldElement{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029},
+ FieldElement{6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048},
+ FieldElement{28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958},
+ },
+ },
+ {
+ {
+ FieldElement{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593},
+ FieldElement{26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071},
+ FieldElement{-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692},
+ },
+ {
+ FieldElement{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687},
+ FieldElement{-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441},
+ FieldElement{-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001},
+ },
+ {
+ FieldElement{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460},
+ FieldElement{-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007},
+ FieldElement{-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762},
+ },
+ {
+ FieldElement{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005},
+ FieldElement{-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674},
+ FieldElement{4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035},
+ },
+ {
+ FieldElement{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590},
+ FieldElement{-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957},
+ FieldElement{-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812},
+ },
+ {
+ FieldElement{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740},
+ FieldElement{-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122},
+ FieldElement{-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158},
+ },
+ {
+ FieldElement{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885},
+ FieldElement{26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140},
+ FieldElement{19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857},
+ },
+ {
+ FieldElement{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155},
+ FieldElement{19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260},
+ FieldElement{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483},
+ },
+ },
+ {
+ {
+ FieldElement{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677},
+ FieldElement{32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815},
+ FieldElement{22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751},
+ },
+ {
+ FieldElement{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203},
+ FieldElement{-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208},
+ FieldElement{1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230},
+ },
+ {
+ FieldElement{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850},
+ FieldElement{-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389},
+ FieldElement{-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968},
+ },
+ {
+ FieldElement{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689},
+ FieldElement{14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880},
+ FieldElement{5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304},
+ },
+ {
+ FieldElement{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632},
+ FieldElement{-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412},
+ FieldElement{20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566},
+ },
+ {
+ FieldElement{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038},
+ FieldElement{-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232},
+ FieldElement{-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943},
+ },
+ {
+ FieldElement{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856},
+ FieldElement{23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738},
+ FieldElement{15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971},
+ },
+ {
+ FieldElement{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718},
+ FieldElement{-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697},
+ FieldElement{-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883},
+ },
+ },
+ {
+ {
+ FieldElement{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912},
+ FieldElement{-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358},
+ FieldElement{3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849},
+ },
+ {
+ FieldElement{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307},
+ FieldElement{-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977},
+ FieldElement{-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335},
+ },
+ {
+ FieldElement{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644},
+ FieldElement{-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616},
+ FieldElement{-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735},
+ },
+ {
+ FieldElement{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099},
+ FieldElement{29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341},
+ FieldElement{-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336},
+ },
+ {
+ FieldElement{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646},
+ FieldElement{31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425},
+ FieldElement{-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388},
+ },
+ {
+ FieldElement{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743},
+ FieldElement{-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822},
+ FieldElement{-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462},
+ },
+ {
+ FieldElement{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985},
+ FieldElement{9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702},
+ FieldElement{-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797},
+ },
+ {
+ FieldElement{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293},
+ FieldElement{27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100},
+ FieldElement{19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688},
+ },
+ },
+ {
+ {
+ FieldElement{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186},
+ FieldElement{2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610},
+ FieldElement{-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707},
+ },
+ {
+ FieldElement{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220},
+ FieldElement{915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025},
+ FieldElement{32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044},
+ },
+ {
+ FieldElement{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992},
+ FieldElement{-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027},
+ FieldElement{21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197},
+ },
+ {
+ FieldElement{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901},
+ FieldElement{31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952},
+ FieldElement{19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878},
+ },
+ {
+ FieldElement{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390},
+ FieldElement{32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730},
+ FieldElement{2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730},
+ },
+ {
+ FieldElement{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180},
+ FieldElement{-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272},
+ FieldElement{-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715},
+ },
+ {
+ FieldElement{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970},
+ FieldElement{-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772},
+ FieldElement{-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865},
+ },
+ {
+ FieldElement{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750},
+ FieldElement{20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373},
+ FieldElement{32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348},
+ },
+ },
+ {
+ {
+ FieldElement{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144},
+ FieldElement{-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195},
+ FieldElement{5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086},
+ },
+ {
+ FieldElement{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684},
+ FieldElement{-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518},
+ FieldElement{-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233},
+ },
+ {
+ FieldElement{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793},
+ FieldElement{-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794},
+ FieldElement{580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435},
+ },
+ {
+ FieldElement{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921},
+ FieldElement{13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518},
+ FieldElement{2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563},
+ },
+ {
+ FieldElement{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278},
+ FieldElement{-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024},
+ FieldElement{4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030},
+ },
+ {
+ FieldElement{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783},
+ FieldElement{27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717},
+ FieldElement{6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844},
+ },
+ {
+ FieldElement{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333},
+ FieldElement{16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048},
+ FieldElement{22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760},
+ },
+ {
+ FieldElement{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760},
+ FieldElement{-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757},
+ FieldElement{-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112},
+ },
+ },
+ {
+ {
+ FieldElement{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468},
+ FieldElement{3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184},
+ FieldElement{10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289},
+ },
+ {
+ FieldElement{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066},
+ FieldElement{24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882},
+ FieldElement{13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226},
+ },
+ {
+ FieldElement{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101},
+ FieldElement{29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279},
+ FieldElement{-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811},
+ },
+ {
+ FieldElement{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709},
+ FieldElement{20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714},
+ FieldElement{-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121},
+ },
+ {
+ FieldElement{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464},
+ FieldElement{12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847},
+ FieldElement{13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400},
+ },
+ {
+ FieldElement{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414},
+ FieldElement{-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158},
+ FieldElement{17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045},
+ },
+ {
+ FieldElement{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415},
+ FieldElement{-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459},
+ FieldElement{-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079},
+ },
+ {
+ FieldElement{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412},
+ FieldElement{-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743},
+ FieldElement{-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836},
+ },
+ },
+ {
+ {
+ FieldElement{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022},
+ FieldElement{18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429},
+ FieldElement{-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065},
+ },
+ {
+ FieldElement{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861},
+ FieldElement{10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000},
+ FieldElement{-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101},
+ },
+ {
+ FieldElement{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815},
+ FieldElement{29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642},
+ FieldElement{10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966},
+ },
+ {
+ FieldElement{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574},
+ FieldElement{-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742},
+ FieldElement{-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689},
+ },
+ {
+ FieldElement{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020},
+ FieldElement{-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772},
+ FieldElement{3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982},
+ },
+ {
+ FieldElement{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953},
+ FieldElement{-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218},
+ FieldElement{-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265},
+ },
+ {
+ FieldElement{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073},
+ FieldElement{-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325},
+ FieldElement{-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798},
+ },
+ {
+ FieldElement{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870},
+ FieldElement{-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863},
+ FieldElement{-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927},
+ },
+ },
+ {
+ {
+ FieldElement{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267},
+ FieldElement{-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663},
+ FieldElement{22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862},
+ },
+ {
+ FieldElement{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673},
+ FieldElement{15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943},
+ FieldElement{15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020},
+ },
+ {
+ FieldElement{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238},
+ FieldElement{11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064},
+ FieldElement{14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795},
+ },
+ {
+ FieldElement{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052},
+ FieldElement{-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904},
+ FieldElement{29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531},
+ },
+ {
+ FieldElement{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979},
+ FieldElement{-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841},
+ FieldElement{10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431},
+ },
+ {
+ FieldElement{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324},
+ FieldElement{-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940},
+ FieldElement{10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320},
+ },
+ {
+ FieldElement{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184},
+ FieldElement{14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114},
+ FieldElement{30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878},
+ },
+ {
+ FieldElement{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784},
+ FieldElement{-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091},
+ FieldElement{-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585},
+ },
+ },
+ {
+ {
+ FieldElement{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208},
+ FieldElement{10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864},
+ FieldElement{17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661},
+ },
+ {
+ FieldElement{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233},
+ FieldElement{26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212},
+ FieldElement{-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525},
+ },
+ {
+ FieldElement{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068},
+ FieldElement{9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397},
+ FieldElement{-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988},
+ },
+ {
+ FieldElement{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889},
+ FieldElement{32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038},
+ FieldElement{14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697},
+ },
+ {
+ FieldElement{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875},
+ FieldElement{-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905},
+ FieldElement{-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656},
+ },
+ {
+ FieldElement{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818},
+ FieldElement{27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714},
+ FieldElement{10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203},
+ },
+ {
+ FieldElement{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931},
+ FieldElement{-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024},
+ FieldElement{-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084},
+ },
+ {
+ FieldElement{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204},
+ FieldElement{20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817},
+ FieldElement{27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667},
+ },
+ },
+ {
+ {
+ FieldElement{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504},
+ FieldElement{-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768},
+ FieldElement{-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255},
+ },
+ {
+ FieldElement{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790},
+ FieldElement{1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438},
+ FieldElement{-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333},
+ },
+ {
+ FieldElement{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971},
+ FieldElement{31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905},
+ FieldElement{29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409},
+ },
+ {
+ FieldElement{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409},
+ FieldElement{6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499},
+ FieldElement{-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363},
+ },
+ {
+ FieldElement{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664},
+ FieldElement{-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324},
+ FieldElement{-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940},
+ },
+ {
+ FieldElement{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990},
+ FieldElement{-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914},
+ FieldElement{-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290},
+ },
+ {
+ FieldElement{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257},
+ FieldElement{-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433},
+ FieldElement{-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236},
+ },
+ {
+ FieldElement{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045},
+ FieldElement{11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093},
+ FieldElement{-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347},
+ },
+ },
+ {
+ {
+ FieldElement{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191},
+ FieldElement{-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507},
+ FieldElement{-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906},
+ },
+ {
+ FieldElement{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018},
+ FieldElement{-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109},
+ FieldElement{-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926},
+ },
+ {
+ FieldElement{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528},
+ FieldElement{8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625},
+ FieldElement{-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286},
+ },
+ {
+ FieldElement{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033},
+ FieldElement{27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866},
+ FieldElement{21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896},
+ },
+ {
+ FieldElement{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075},
+ FieldElement{26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347},
+ FieldElement{-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437},
+ },
+ {
+ FieldElement{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165},
+ FieldElement{-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588},
+ FieldElement{-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193},
+ },
+ {
+ FieldElement{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017},
+ FieldElement{-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883},
+ FieldElement{21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961},
+ },
+ {
+ FieldElement{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043},
+ FieldElement{29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663},
+ FieldElement{-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362},
+ },
+ },
+ {
+ {
+ FieldElement{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860},
+ FieldElement{2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466},
+ FieldElement{-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063},
+ },
+ {
+ FieldElement{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997},
+ FieldElement{-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295},
+ FieldElement{-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369},
+ },
+ {
+ FieldElement{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385},
+ FieldElement{18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109},
+ FieldElement{2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906},
+ },
+ {
+ FieldElement{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424},
+ FieldElement{-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185},
+ FieldElement{7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962},
+ },
+ {
+ FieldElement{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325},
+ FieldElement{10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593},
+ FieldElement{696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404},
+ },
+ {
+ FieldElement{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644},
+ FieldElement{17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801},
+ FieldElement{26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804},
+ },
+ {
+ FieldElement{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884},
+ FieldElement{-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577},
+ FieldElement{-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849},
+ },
+ {
+ FieldElement{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473},
+ FieldElement{-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644},
+ FieldElement{-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319},
+ },
+ },
+ {
+ {
+ FieldElement{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599},
+ FieldElement{-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768},
+ FieldElement{-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084},
+ },
+ {
+ FieldElement{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328},
+ FieldElement{-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369},
+ FieldElement{20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920},
+ },
+ {
+ FieldElement{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815},
+ FieldElement{-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025},
+ FieldElement{-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397},
+ },
+ {
+ FieldElement{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448},
+ FieldElement{6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981},
+ FieldElement{30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165},
+ },
+ {
+ FieldElement{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501},
+ FieldElement{17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073},
+ FieldElement{-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861},
+ },
+ {
+ FieldElement{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845},
+ FieldElement{-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211},
+ FieldElement{18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870},
+ },
+ {
+ FieldElement{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096},
+ FieldElement{33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803},
+ FieldElement{-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168},
+ },
+ {
+ FieldElement{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965},
+ FieldElement{-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505},
+ FieldElement{18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598},
+ },
+ },
+ {
+ {
+ FieldElement{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782},
+ FieldElement{5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900},
+ FieldElement{-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479},
+ },
+ {
+ FieldElement{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208},
+ FieldElement{8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232},
+ FieldElement{17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719},
+ },
+ {
+ FieldElement{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271},
+ FieldElement{-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326},
+ FieldElement{-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132},
+ },
+ {
+ FieldElement{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300},
+ FieldElement{8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570},
+ FieldElement{15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670},
+ },
+ {
+ FieldElement{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994},
+ FieldElement{-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913},
+ FieldElement{31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317},
+ },
+ {
+ FieldElement{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730},
+ FieldElement{842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096},
+ FieldElement{-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078},
+ },
+ {
+ FieldElement{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411},
+ FieldElement{-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905},
+ FieldElement{-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654},
+ },
+ {
+ FieldElement{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870},
+ FieldElement{-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498},
+ FieldElement{12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579},
+ },
+ },
+ {
+ {
+ FieldElement{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677},
+ FieldElement{10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647},
+ FieldElement{-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743},
+ },
+ {
+ FieldElement{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468},
+ FieldElement{21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375},
+ FieldElement{-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155},
+ },
+ {
+ FieldElement{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725},
+ FieldElement{-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612},
+ FieldElement{-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943},
+ },
+ {
+ FieldElement{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944},
+ FieldElement{30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928},
+ FieldElement{9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406},
+ },
+ {
+ FieldElement{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139},
+ FieldElement{-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963},
+ FieldElement{-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693},
+ },
+ {
+ FieldElement{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734},
+ FieldElement{-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680},
+ FieldElement{-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410},
+ },
+ {
+ FieldElement{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931},
+ FieldElement{-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654},
+ FieldElement{22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710},
+ },
+ {
+ FieldElement{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180},
+ FieldElement{-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684},
+ FieldElement{-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895},
+ },
+ },
+ {
+ {
+ FieldElement{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501},
+ FieldElement{-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413},
+ FieldElement{6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880},
+ },
+ {
+ FieldElement{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874},
+ FieldElement{22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962},
+ FieldElement{-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899},
+ },
+ {
+ FieldElement{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152},
+ FieldElement{9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063},
+ FieldElement{7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080},
+ },
+ {
+ FieldElement{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146},
+ FieldElement{-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183},
+ FieldElement{-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133},
+ },
+ {
+ FieldElement{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421},
+ FieldElement{-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622},
+ FieldElement{-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197},
+ },
+ {
+ FieldElement{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663},
+ FieldElement{31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753},
+ FieldElement{4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755},
+ },
+ {
+ FieldElement{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862},
+ FieldElement{-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118},
+ FieldElement{26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171},
+ },
+ {
+ FieldElement{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380},
+ FieldElement{16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824},
+ FieldElement{28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270},
+ },
+ },
+ {
+ {
+ FieldElement{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438},
+ FieldElement{-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584},
+ FieldElement{-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562},
+ },
+ {
+ FieldElement{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471},
+ FieldElement{18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610},
+ FieldElement{19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269},
+ },
+ {
+ FieldElement{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650},
+ FieldElement{14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369},
+ FieldElement{19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461},
+ },
+ {
+ FieldElement{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462},
+ FieldElement{-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793},
+ FieldElement{-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218},
+ },
+ {
+ FieldElement{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226},
+ FieldElement{18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019},
+ FieldElement{-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037},
+ },
+ {
+ FieldElement{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171},
+ FieldElement{-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132},
+ FieldElement{-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841},
+ },
+ {
+ FieldElement{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181},
+ FieldElement{-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210},
+ FieldElement{-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040},
+ },
+ {
+ FieldElement{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935},
+ FieldElement{24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105},
+ FieldElement{-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814},
+ },
+ },
+ {
+ {
+ FieldElement{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852},
+ FieldElement{5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581},
+ FieldElement{-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646},
+ },
+ {
+ FieldElement{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844},
+ FieldElement{10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025},
+ FieldElement{27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453},
+ },
+ {
+ FieldElement{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068},
+ FieldElement{4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192},
+ FieldElement{-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921},
+ },
+ {
+ FieldElement{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259},
+ FieldElement{-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426},
+ FieldElement{-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072},
+ },
+ {
+ FieldElement{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305},
+ FieldElement{13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832},
+ FieldElement{28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943},
+ },
+ {
+ FieldElement{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011},
+ FieldElement{24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447},
+ FieldElement{17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494},
+ },
+ {
+ FieldElement{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245},
+ FieldElement{-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859},
+ FieldElement{28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915},
+ },
+ {
+ FieldElement{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707},
+ FieldElement{10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848},
+ FieldElement{-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224},
+ },
+ },
+ {
+ {
+ FieldElement{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391},
+ FieldElement{15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215},
+ FieldElement{-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101},
+ },
+ {
+ FieldElement{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713},
+ FieldElement{21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849},
+ FieldElement{-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930},
+ },
+ {
+ FieldElement{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940},
+ FieldElement{-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031},
+ FieldElement{-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404},
+ },
+ {
+ FieldElement{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243},
+ FieldElement{-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116},
+ FieldElement{-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525},
+ },
+ {
+ FieldElement{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509},
+ FieldElement{-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883},
+ FieldElement{15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865},
+ },
+ {
+ FieldElement{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660},
+ FieldElement{4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273},
+ FieldElement{-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138},
+ },
+ {
+ FieldElement{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560},
+ FieldElement{-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135},
+ FieldElement{2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941},
+ },
+ {
+ FieldElement{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739},
+ FieldElement{18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756},
+ FieldElement{-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819},
+ },
+ },
+ {
+ {
+ FieldElement{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347},
+ FieldElement{-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028},
+ FieldElement{21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075},
+ },
+ {
+ FieldElement{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799},
+ FieldElement{-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609},
+ FieldElement{-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817},
+ },
+ {
+ FieldElement{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989},
+ FieldElement{-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523},
+ FieldElement{4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278},
+ },
+ {
+ FieldElement{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045},
+ FieldElement{19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377},
+ FieldElement{24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480},
+ },
+ {
+ FieldElement{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016},
+ FieldElement{510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426},
+ FieldElement{18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525},
+ },
+ {
+ FieldElement{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396},
+ FieldElement{9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080},
+ FieldElement{12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892},
+ },
+ {
+ FieldElement{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275},
+ FieldElement{11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074},
+ FieldElement{20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140},
+ },
+ {
+ FieldElement{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717},
+ FieldElement{-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101},
+ FieldElement{24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127},
+ },
+ },
+ {
+ {
+ FieldElement{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632},
+ FieldElement{-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415},
+ FieldElement{-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160},
+ },
+ {
+ FieldElement{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876},
+ FieldElement{22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625},
+ FieldElement{-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478},
+ },
+ {
+ FieldElement{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164},
+ FieldElement{26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595},
+ FieldElement{-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248},
+ },
+ {
+ FieldElement{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858},
+ FieldElement{15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193},
+ FieldElement{8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184},
+ },
+ {
+ FieldElement{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942},
+ FieldElement{-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635},
+ FieldElement{21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948},
+ },
+ {
+ FieldElement{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935},
+ FieldElement{-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415},
+ FieldElement{-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416},
+ },
+ {
+ FieldElement{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018},
+ FieldElement{4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778},
+ FieldElement{366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659},
+ },
+ {
+ FieldElement{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385},
+ FieldElement{18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503},
+ FieldElement{476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329},
+ },
+ },
+ {
+ {
+ FieldElement{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056},
+ FieldElement{-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838},
+ FieldElement{24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948},
+ },
+ {
+ FieldElement{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691},
+ FieldElement{-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118},
+ FieldElement{-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517},
+ },
+ {
+ FieldElement{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269},
+ FieldElement{-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904},
+ FieldElement{-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589},
+ },
+ {
+ FieldElement{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193},
+ FieldElement{-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910},
+ FieldElement{-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930},
+ },
+ {
+ FieldElement{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667},
+ FieldElement{25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481},
+ FieldElement{-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876},
+ },
+ {
+ FieldElement{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640},
+ FieldElement{-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278},
+ FieldElement{-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112},
+ },
+ {
+ FieldElement{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272},
+ FieldElement{17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012},
+ FieldElement{-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221},
+ },
+ {
+ FieldElement{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046},
+ FieldElement{13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345},
+ FieldElement{-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310},
+ },
+ },
+ {
+ {
+ FieldElement{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937},
+ FieldElement{31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636},
+ FieldElement{-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008},
+ },
+ {
+ FieldElement{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429},
+ FieldElement{-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576},
+ FieldElement{31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066},
+ },
+ {
+ FieldElement{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490},
+ FieldElement{-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104},
+ FieldElement{33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053},
+ },
+ {
+ FieldElement{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275},
+ FieldElement{-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511},
+ FieldElement{22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095},
+ },
+ {
+ FieldElement{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439},
+ FieldElement{23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939},
+ FieldElement{-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424},
+ },
+ {
+ FieldElement{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310},
+ FieldElement{3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608},
+ FieldElement{-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079},
+ },
+ {
+ FieldElement{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101},
+ FieldElement{21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418},
+ FieldElement{18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576},
+ },
+ {
+ FieldElement{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356},
+ FieldElement{9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996},
+ FieldElement{-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099},
+ },
+ },
+ {
+ {
+ FieldElement{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728},
+ FieldElement{-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658},
+ FieldElement{-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242},
+ },
+ {
+ FieldElement{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001},
+ FieldElement{-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766},
+ FieldElement{18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373},
+ },
+ {
+ FieldElement{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458},
+ FieldElement{-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628},
+ FieldElement{-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657},
+ },
+ {
+ FieldElement{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062},
+ FieldElement{25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616},
+ FieldElement{31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014},
+ },
+ {
+ FieldElement{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383},
+ FieldElement{-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814},
+ FieldElement{-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718},
+ },
+ {
+ FieldElement{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417},
+ FieldElement{2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222},
+ FieldElement{33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444},
+ },
+ {
+ FieldElement{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597},
+ FieldElement{23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970},
+ FieldElement{1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799},
+ },
+ {
+ FieldElement{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647},
+ FieldElement{13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511},
+ FieldElement{-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032},
+ },
+ },
+ {
+ {
+ FieldElement{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834},
+ FieldElement{-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461},
+ FieldElement{29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062},
+ },
+ {
+ FieldElement{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516},
+ FieldElement{-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547},
+ FieldElement{-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240},
+ },
+ {
+ FieldElement{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038},
+ FieldElement{-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741},
+ FieldElement{16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103},
+ },
+ {
+ FieldElement{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747},
+ FieldElement{-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323},
+ FieldElement{31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016},
+ },
+ {
+ FieldElement{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373},
+ FieldElement{15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228},
+ FieldElement{-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141},
+ },
+ {
+ FieldElement{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399},
+ FieldElement{11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831},
+ FieldElement{-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376},
+ },
+ {
+ FieldElement{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313},
+ FieldElement{-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958},
+ FieldElement{-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577},
+ },
+ {
+ FieldElement{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743},
+ FieldElement{29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684},
+ FieldElement{-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476},
+ },
+ },
+}
diff --git a/vendor/github.com/agl/ed25519/edwards25519/edwards25519.go b/vendor/github.com/agl/ed25519/edwards25519/edwards25519.go
new file mode 100644
index 0000000..9079818
--- /dev/null
+++ b/vendor/github.com/agl/ed25519/edwards25519/edwards25519.go
@@ -0,0 +1,1773 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package edwards25519 implements operations in GF(2**255-19) and on an
+// Edwards curve that is isomorphic to curve25519. See
+// http://ed25519.cr.yp.to/.
+package edwards25519
+
+// This code is a port of the public domain, "ref10" implementation of ed25519
+// from SUPERCOP.
+
+// FieldElement represents an element of the field GF(2^255 - 19). An element
+// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
+// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
+// context.
+type FieldElement [10]int32
+
+var zero FieldElement
+
+func FeZero(fe *FieldElement) {
+ copy(fe[:], zero[:])
+}
+
+func FeOne(fe *FieldElement) {
+ FeZero(fe)
+ fe[0] = 1
+}
+
+func FeAdd(dst, a, b *FieldElement) {
+ dst[0] = a[0] + b[0]
+ dst[1] = a[1] + b[1]
+ dst[2] = a[2] + b[2]
+ dst[3] = a[3] + b[3]
+ dst[4] = a[4] + b[4]
+ dst[5] = a[5] + b[5]
+ dst[6] = a[6] + b[6]
+ dst[7] = a[7] + b[7]
+ dst[8] = a[8] + b[8]
+ dst[9] = a[9] + b[9]
+}
+
+func FeSub(dst, a, b *FieldElement) {
+ dst[0] = a[0] - b[0]
+ dst[1] = a[1] - b[1]
+ dst[2] = a[2] - b[2]
+ dst[3] = a[3] - b[3]
+ dst[4] = a[4] - b[4]
+ dst[5] = a[5] - b[5]
+ dst[6] = a[6] - b[6]
+ dst[7] = a[7] - b[7]
+ dst[8] = a[8] - b[8]
+ dst[9] = a[9] - b[9]
+}
+
+func FeCopy(dst, src *FieldElement) {
+ copy(dst[:], src[:])
+}
+
+// Replace (f,g) with (g,g) if b == 1;
+// replace (f,g) with (f,g) if b == 0.
+//
+// Preconditions: b in {0,1}.
+func FeCMove(f, g *FieldElement, b int32) {
+ b = -b
+ f[0] ^= b & (f[0] ^ g[0])
+ f[1] ^= b & (f[1] ^ g[1])
+ f[2] ^= b & (f[2] ^ g[2])
+ f[3] ^= b & (f[3] ^ g[3])
+ f[4] ^= b & (f[4] ^ g[4])
+ f[5] ^= b & (f[5] ^ g[5])
+ f[6] ^= b & (f[6] ^ g[6])
+ f[7] ^= b & (f[7] ^ g[7])
+ f[8] ^= b & (f[8] ^ g[8])
+ f[9] ^= b & (f[9] ^ g[9])
+}
+
+func load3(in []byte) int64 {
+ var r int64
+ r = int64(in[0])
+ r |= int64(in[1]) << 8
+ r |= int64(in[2]) << 16
+ return r
+}
+
+func load4(in []byte) int64 {
+ var r int64
+ r = int64(in[0])
+ r |= int64(in[1]) << 8
+ r |= int64(in[2]) << 16
+ r |= int64(in[3]) << 24
+ return r
+}
+
+func FeFromBytes(dst *FieldElement, src *[32]byte) {
+ h0 := load4(src[:])
+ h1 := load3(src[4:]) << 6
+ h2 := load3(src[7:]) << 5
+ h3 := load3(src[10:]) << 3
+ h4 := load3(src[13:]) << 2
+ h5 := load4(src[16:])
+ h6 := load3(src[20:]) << 7
+ h7 := load3(src[23:]) << 5
+ h8 := load3(src[26:]) << 4
+ h9 := (load3(src[29:]) & 8388607) << 2
+
+ FeCombine(dst, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+}
+
+// FeToBytes marshals h to s.
+// Preconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Write p=2^255-19; q=floor(h/p).
+// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
+//
+// Proof:
+// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
+// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
+//
+// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
+// Then 0> 25
+ q = (h[0] + q) >> 26
+ q = (h[1] + q) >> 25
+ q = (h[2] + q) >> 26
+ q = (h[3] + q) >> 25
+ q = (h[4] + q) >> 26
+ q = (h[5] + q) >> 25
+ q = (h[6] + q) >> 26
+ q = (h[7] + q) >> 25
+ q = (h[8] + q) >> 26
+ q = (h[9] + q) >> 25
+
+ // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
+ h[0] += 19 * q
+ // Goal: Output h-2^255 q, which is between 0 and 2^255-20.
+
+ carry[0] = h[0] >> 26
+ h[1] += carry[0]
+ h[0] -= carry[0] << 26
+ carry[1] = h[1] >> 25
+ h[2] += carry[1]
+ h[1] -= carry[1] << 25
+ carry[2] = h[2] >> 26
+ h[3] += carry[2]
+ h[2] -= carry[2] << 26
+ carry[3] = h[3] >> 25
+ h[4] += carry[3]
+ h[3] -= carry[3] << 25
+ carry[4] = h[4] >> 26
+ h[5] += carry[4]
+ h[4] -= carry[4] << 26
+ carry[5] = h[5] >> 25
+ h[6] += carry[5]
+ h[5] -= carry[5] << 25
+ carry[6] = h[6] >> 26
+ h[7] += carry[6]
+ h[6] -= carry[6] << 26
+ carry[7] = h[7] >> 25
+ h[8] += carry[7]
+ h[7] -= carry[7] << 25
+ carry[8] = h[8] >> 26
+ h[9] += carry[8]
+ h[8] -= carry[8] << 26
+ carry[9] = h[9] >> 25
+ h[9] -= carry[9] << 25
+ // h10 = carry9
+
+ // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
+ // Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
+ // evidently 2^255 h10-2^255 q = 0.
+ // Goal: Output h[0]+...+2^230 h[9].
+
+ s[0] = byte(h[0] >> 0)
+ s[1] = byte(h[0] >> 8)
+ s[2] = byte(h[0] >> 16)
+ s[3] = byte((h[0] >> 24) | (h[1] << 2))
+ s[4] = byte(h[1] >> 6)
+ s[5] = byte(h[1] >> 14)
+ s[6] = byte((h[1] >> 22) | (h[2] << 3))
+ s[7] = byte(h[2] >> 5)
+ s[8] = byte(h[2] >> 13)
+ s[9] = byte((h[2] >> 21) | (h[3] << 5))
+ s[10] = byte(h[3] >> 3)
+ s[11] = byte(h[3] >> 11)
+ s[12] = byte((h[3] >> 19) | (h[4] << 6))
+ s[13] = byte(h[4] >> 2)
+ s[14] = byte(h[4] >> 10)
+ s[15] = byte(h[4] >> 18)
+ s[16] = byte(h[5] >> 0)
+ s[17] = byte(h[5] >> 8)
+ s[18] = byte(h[5] >> 16)
+ s[19] = byte((h[5] >> 24) | (h[6] << 1))
+ s[20] = byte(h[6] >> 7)
+ s[21] = byte(h[6] >> 15)
+ s[22] = byte((h[6] >> 23) | (h[7] << 3))
+ s[23] = byte(h[7] >> 5)
+ s[24] = byte(h[7] >> 13)
+ s[25] = byte((h[7] >> 21) | (h[8] << 4))
+ s[26] = byte(h[8] >> 4)
+ s[27] = byte(h[8] >> 12)
+ s[28] = byte((h[8] >> 20) | (h[9] << 6))
+ s[29] = byte(h[9] >> 2)
+ s[30] = byte(h[9] >> 10)
+ s[31] = byte(h[9] >> 18)
+}
+
+func FeIsNegative(f *FieldElement) byte {
+ var s [32]byte
+ FeToBytes(&s, f)
+ return s[0] & 1
+}
+
+func FeIsNonZero(f *FieldElement) int32 {
+ var s [32]byte
+ FeToBytes(&s, f)
+ var x uint8
+ for _, b := range s {
+ x |= b
+ }
+ x |= x >> 4
+ x |= x >> 2
+ x |= x >> 1
+ return int32(x & 1)
+}
+
+// FeNeg sets h = -f
+//
+// Preconditions:
+// |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+func FeNeg(h, f *FieldElement) {
+ h[0] = -f[0]
+ h[1] = -f[1]
+ h[2] = -f[2]
+ h[3] = -f[3]
+ h[4] = -f[4]
+ h[5] = -f[5]
+ h[6] = -f[6]
+ h[7] = -f[7]
+ h[8] = -f[8]
+ h[9] = -f[9]
+}
+
+func FeCombine(h *FieldElement, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) {
+ var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 int64
+
+ /*
+ |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
+ i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
+ |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
+ i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
+ */
+
+ c0 = (h0 + (1 << 25)) >> 26
+ h1 += c0
+ h0 -= c0 << 26
+ c4 = (h4 + (1 << 25)) >> 26
+ h5 += c4
+ h4 -= c4 << 26
+ /* |h0| <= 2^25 */
+ /* |h4| <= 2^25 */
+ /* |h1| <= 1.51*2^58 */
+ /* |h5| <= 1.51*2^58 */
+
+ c1 = (h1 + (1 << 24)) >> 25
+ h2 += c1
+ h1 -= c1 << 25
+ c5 = (h5 + (1 << 24)) >> 25
+ h6 += c5
+ h5 -= c5 << 25
+ /* |h1| <= 2^24; from now on fits into int32 */
+ /* |h5| <= 2^24; from now on fits into int32 */
+ /* |h2| <= 1.21*2^59 */
+ /* |h6| <= 1.21*2^59 */
+
+ c2 = (h2 + (1 << 25)) >> 26
+ h3 += c2
+ h2 -= c2 << 26
+ c6 = (h6 + (1 << 25)) >> 26
+ h7 += c6
+ h6 -= c6 << 26
+ /* |h2| <= 2^25; from now on fits into int32 unchanged */
+ /* |h6| <= 2^25; from now on fits into int32 unchanged */
+ /* |h3| <= 1.51*2^58 */
+ /* |h7| <= 1.51*2^58 */
+
+ c3 = (h3 + (1 << 24)) >> 25
+ h4 += c3
+ h3 -= c3 << 25
+ c7 = (h7 + (1 << 24)) >> 25
+ h8 += c7
+ h7 -= c7 << 25
+ /* |h3| <= 2^24; from now on fits into int32 unchanged */
+ /* |h7| <= 2^24; from now on fits into int32 unchanged */
+ /* |h4| <= 1.52*2^33 */
+ /* |h8| <= 1.52*2^33 */
+
+ c4 = (h4 + (1 << 25)) >> 26
+ h5 += c4
+ h4 -= c4 << 26
+ c8 = (h8 + (1 << 25)) >> 26
+ h9 += c8
+ h8 -= c8 << 26
+ /* |h4| <= 2^25; from now on fits into int32 unchanged */
+ /* |h8| <= 2^25; from now on fits into int32 unchanged */
+ /* |h5| <= 1.01*2^24 */
+ /* |h9| <= 1.51*2^58 */
+
+ c9 = (h9 + (1 << 24)) >> 25
+ h0 += c9 * 19
+ h9 -= c9 << 25
+ /* |h9| <= 2^24; from now on fits into int32 unchanged */
+ /* |h0| <= 1.8*2^37 */
+
+ c0 = (h0 + (1 << 25)) >> 26
+ h1 += c0
+ h0 -= c0 << 26
+ /* |h0| <= 2^25; from now on fits into int32 unchanged */
+ /* |h1| <= 1.01*2^24 */
+
+ h[0] = int32(h0)
+ h[1] = int32(h1)
+ h[2] = int32(h2)
+ h[3] = int32(h3)
+ h[4] = int32(h4)
+ h[5] = int32(h5)
+ h[6] = int32(h6)
+ h[7] = int32(h7)
+ h[8] = int32(h8)
+ h[9] = int32(h9)
+}
+
+// FeMul calculates h = f * g
+// Can overlap h with f or g.
+//
+// Preconditions:
+// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Notes on implementation strategy:
+//
+// Using schoolbook multiplication.
+// Karatsuba would save a little in some cost models.
+//
+// Most multiplications by 2 and 19 are 32-bit precomputations;
+// cheaper than 64-bit postcomputations.
+//
+// There is one remaining multiplication by 19 in the carry chain;
+// one *19 precomputation can be merged into this,
+// but the resulting data flow is considerably less clean.
+//
+// There are 12 carries below.
+// 10 of them are 2-way parallelizable and vectorizable.
+// Can get away with 11 carries, but then data flow is much deeper.
+//
+// With tighter constraints on inputs can squeeze carries into int32.
+func FeMul(h, f, g *FieldElement) {
+ f0 := int64(f[0])
+ f1 := int64(f[1])
+ f2 := int64(f[2])
+ f3 := int64(f[3])
+ f4 := int64(f[4])
+ f5 := int64(f[5])
+ f6 := int64(f[6])
+ f7 := int64(f[7])
+ f8 := int64(f[8])
+ f9 := int64(f[9])
+
+ f1_2 := int64(2 * f[1])
+ f3_2 := int64(2 * f[3])
+ f5_2 := int64(2 * f[5])
+ f7_2 := int64(2 * f[7])
+ f9_2 := int64(2 * f[9])
+
+ g0 := int64(g[0])
+ g1 := int64(g[1])
+ g2 := int64(g[2])
+ g3 := int64(g[3])
+ g4 := int64(g[4])
+ g5 := int64(g[5])
+ g6 := int64(g[6])
+ g7 := int64(g[7])
+ g8 := int64(g[8])
+ g9 := int64(g[9])
+
+ g1_19 := int64(19 * g[1]) /* 1.4*2^29 */
+ g2_19 := int64(19 * g[2]) /* 1.4*2^30; still ok */
+ g3_19 := int64(19 * g[3])
+ g4_19 := int64(19 * g[4])
+ g5_19 := int64(19 * g[5])
+ g6_19 := int64(19 * g[6])
+ g7_19 := int64(19 * g[7])
+ g8_19 := int64(19 * g[8])
+ g9_19 := int64(19 * g[9])
+
+ h0 := f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19
+ h1 := f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19
+ h2 := f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19
+ h3 := f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19
+ h4 := f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19
+ h5 := f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19
+ h6 := f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19
+ h7 := f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19
+ h8 := f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19
+ h9 := f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0
+
+ FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+}
+
+func feSquare(f *FieldElement) (h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) {
+ f0 := int64(f[0])
+ f1 := int64(f[1])
+ f2 := int64(f[2])
+ f3 := int64(f[3])
+ f4 := int64(f[4])
+ f5 := int64(f[5])
+ f6 := int64(f[6])
+ f7 := int64(f[7])
+ f8 := int64(f[8])
+ f9 := int64(f[9])
+ f0_2 := int64(2 * f[0])
+ f1_2 := int64(2 * f[1])
+ f2_2 := int64(2 * f[2])
+ f3_2 := int64(2 * f[3])
+ f4_2 := int64(2 * f[4])
+ f5_2 := int64(2 * f[5])
+ f6_2 := int64(2 * f[6])
+ f7_2 := int64(2 * f[7])
+ f5_38 := 38 * f5 // 1.31*2^30
+ f6_19 := 19 * f6 // 1.31*2^30
+ f7_38 := 38 * f7 // 1.31*2^30
+ f8_19 := 19 * f8 // 1.31*2^30
+ f9_38 := 38 * f9 // 1.31*2^30
+
+ h0 = f0*f0 + f1_2*f9_38 + f2_2*f8_19 + f3_2*f7_38 + f4_2*f6_19 + f5*f5_38
+ h1 = f0_2*f1 + f2*f9_38 + f3_2*f8_19 + f4*f7_38 + f5_2*f6_19
+ h2 = f0_2*f2 + f1_2*f1 + f3_2*f9_38 + f4_2*f8_19 + f5_2*f7_38 + f6*f6_19
+ h3 = f0_2*f3 + f1_2*f2 + f4*f9_38 + f5_2*f8_19 + f6*f7_38
+ h4 = f0_2*f4 + f1_2*f3_2 + f2*f2 + f5_2*f9_38 + f6_2*f8_19 + f7*f7_38
+ h5 = f0_2*f5 + f1_2*f4 + f2_2*f3 + f6*f9_38 + f7_2*f8_19
+ h6 = f0_2*f6 + f1_2*f5_2 + f2_2*f4 + f3_2*f3 + f7_2*f9_38 + f8*f8_19
+ h7 = f0_2*f7 + f1_2*f6 + f2_2*f5 + f3_2*f4 + f8*f9_38
+ h8 = f0_2*f8 + f1_2*f7_2 + f2_2*f6 + f3_2*f5_2 + f4*f4 + f9*f9_38
+ h9 = f0_2*f9 + f1_2*f8 + f2_2*f7 + f3_2*f6 + f4_2*f5
+
+ return
+}
+
+// FeSquare calculates h = f*f. Can overlap h with f.
+//
+// Preconditions:
+// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+func FeSquare(h, f *FieldElement) {
+ h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f)
+ FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+}
+
+// FeSquare2 sets h = 2 * f * f
+//
+// Can overlap h with f.
+//
+// Preconditions:
+// |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+// See fe_mul.c for discussion of implementation strategy.
+func FeSquare2(h, f *FieldElement) {
+ h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f)
+
+ h0 += h0
+ h1 += h1
+ h2 += h2
+ h3 += h3
+ h4 += h4
+ h5 += h5
+ h6 += h6
+ h7 += h7
+ h8 += h8
+ h9 += h9
+
+ FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+}
+
+func FeInvert(out, z *FieldElement) {
+ var t0, t1, t2, t3 FieldElement
+ var i int
+
+ FeSquare(&t0, z) // 2^1
+ FeSquare(&t1, &t0) // 2^2
+ for i = 1; i < 2; i++ { // 2^3
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t1, z, &t1) // 2^3 + 2^0
+ FeMul(&t0, &t0, &t1) // 2^3 + 2^1 + 2^0
+ FeSquare(&t2, &t0) // 2^4 + 2^2 + 2^1
+ FeMul(&t1, &t1, &t2) // 2^4 + 2^3 + 2^2 + 2^1 + 2^0
+ FeSquare(&t2, &t1) // 5,4,3,2,1
+ for i = 1; i < 5; i++ { // 9,8,7,6,5
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1) // 9,8,7,6,5,4,3,2,1,0
+ FeSquare(&t2, &t1) // 10..1
+ for i = 1; i < 10; i++ { // 19..10
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t2, &t2, &t1) // 19..0
+ FeSquare(&t3, &t2) // 20..1
+ for i = 1; i < 20; i++ { // 39..20
+ FeSquare(&t3, &t3)
+ }
+ FeMul(&t2, &t3, &t2) // 39..0
+ FeSquare(&t2, &t2) // 40..1
+ for i = 1; i < 10; i++ { // 49..10
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1) // 49..0
+ FeSquare(&t2, &t1) // 50..1
+ for i = 1; i < 50; i++ { // 99..50
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t2, &t2, &t1) // 99..0
+ FeSquare(&t3, &t2) // 100..1
+ for i = 1; i < 100; i++ { // 199..100
+ FeSquare(&t3, &t3)
+ }
+ FeMul(&t2, &t3, &t2) // 199..0
+ FeSquare(&t2, &t2) // 200..1
+ for i = 1; i < 50; i++ { // 249..50
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1) // 249..0
+ FeSquare(&t1, &t1) // 250..1
+ for i = 1; i < 5; i++ { // 254..5
+ FeSquare(&t1, &t1)
+ }
+ FeMul(out, &t1, &t0) // 254..5,3,1,0
+}
+
+func fePow22523(out, z *FieldElement) {
+ var t0, t1, t2 FieldElement
+ var i int
+
+ FeSquare(&t0, z)
+ for i = 1; i < 1; i++ {
+ FeSquare(&t0, &t0)
+ }
+ FeSquare(&t1, &t0)
+ for i = 1; i < 2; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t1, z, &t1)
+ FeMul(&t0, &t0, &t1)
+ FeSquare(&t0, &t0)
+ for i = 1; i < 1; i++ {
+ FeSquare(&t0, &t0)
+ }
+ FeMul(&t0, &t1, &t0)
+ FeSquare(&t1, &t0)
+ for i = 1; i < 5; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t0, &t1, &t0)
+ FeSquare(&t1, &t0)
+ for i = 1; i < 10; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t1, &t1, &t0)
+ FeSquare(&t2, &t1)
+ for i = 1; i < 20; i++ {
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1)
+ FeSquare(&t1, &t1)
+ for i = 1; i < 10; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t0, &t1, &t0)
+ FeSquare(&t1, &t0)
+ for i = 1; i < 50; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t1, &t1, &t0)
+ FeSquare(&t2, &t1)
+ for i = 1; i < 100; i++ {
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1)
+ FeSquare(&t1, &t1)
+ for i = 1; i < 50; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t0, &t1, &t0)
+ FeSquare(&t0, &t0)
+ for i = 1; i < 2; i++ {
+ FeSquare(&t0, &t0)
+ }
+ FeMul(out, &t0, z)
+}
+
+// Group elements are members of the elliptic curve -x^2 + y^2 = 1 + d * x^2 *
+// y^2 where d = -121665/121666.
+//
+// Several representations are used:
+// ProjectiveGroupElement: (X:Y:Z) satisfying x=X/Z, y=Y/Z
+// ExtendedGroupElement: (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
+// CompletedGroupElement: ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
+// PreComputedGroupElement: (y+x,y-x,2dxy)
+
+type ProjectiveGroupElement struct {
+ X, Y, Z FieldElement
+}
+
+type ExtendedGroupElement struct {
+ X, Y, Z, T FieldElement
+}
+
+type CompletedGroupElement struct {
+ X, Y, Z, T FieldElement
+}
+
+type PreComputedGroupElement struct {
+ yPlusX, yMinusX, xy2d FieldElement
+}
+
+type CachedGroupElement struct {
+ yPlusX, yMinusX, Z, T2d FieldElement
+}
+
+func (p *ProjectiveGroupElement) Zero() {
+ FeZero(&p.X)
+ FeOne(&p.Y)
+ FeOne(&p.Z)
+}
+
+func (p *ProjectiveGroupElement) Double(r *CompletedGroupElement) {
+ var t0 FieldElement
+
+ FeSquare(&r.X, &p.X)
+ FeSquare(&r.Z, &p.Y)
+ FeSquare2(&r.T, &p.Z)
+ FeAdd(&r.Y, &p.X, &p.Y)
+ FeSquare(&t0, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.X)
+ FeSub(&r.Z, &r.Z, &r.X)
+ FeSub(&r.X, &t0, &r.Y)
+ FeSub(&r.T, &r.T, &r.Z)
+}
+
+func (p *ProjectiveGroupElement) ToBytes(s *[32]byte) {
+ var recip, x, y FieldElement
+
+ FeInvert(&recip, &p.Z)
+ FeMul(&x, &p.X, &recip)
+ FeMul(&y, &p.Y, &recip)
+ FeToBytes(s, &y)
+ s[31] ^= FeIsNegative(&x) << 7
+}
+
+func (p *ExtendedGroupElement) Zero() {
+ FeZero(&p.X)
+ FeOne(&p.Y)
+ FeOne(&p.Z)
+ FeZero(&p.T)
+}
+
+func (p *ExtendedGroupElement) Double(r *CompletedGroupElement) {
+ var q ProjectiveGroupElement
+ p.ToProjective(&q)
+ q.Double(r)
+}
+
+func (p *ExtendedGroupElement) ToCached(r *CachedGroupElement) {
+ FeAdd(&r.yPlusX, &p.Y, &p.X)
+ FeSub(&r.yMinusX, &p.Y, &p.X)
+ FeCopy(&r.Z, &p.Z)
+ FeMul(&r.T2d, &p.T, &d2)
+}
+
+func (p *ExtendedGroupElement) ToProjective(r *ProjectiveGroupElement) {
+ FeCopy(&r.X, &p.X)
+ FeCopy(&r.Y, &p.Y)
+ FeCopy(&r.Z, &p.Z)
+}
+
+func (p *ExtendedGroupElement) ToBytes(s *[32]byte) {
+ var recip, x, y FieldElement
+
+ FeInvert(&recip, &p.Z)
+ FeMul(&x, &p.X, &recip)
+ FeMul(&y, &p.Y, &recip)
+ FeToBytes(s, &y)
+ s[31] ^= FeIsNegative(&x) << 7
+}
+
+func (p *ExtendedGroupElement) FromBytes(s *[32]byte) bool {
+ var u, v, v3, vxx, check FieldElement
+
+ FeFromBytes(&p.Y, s)
+ FeOne(&p.Z)
+ FeSquare(&u, &p.Y)
+ FeMul(&v, &u, &d)
+ FeSub(&u, &u, &p.Z) // y = y^2-1
+ FeAdd(&v, &v, &p.Z) // v = dy^2+1
+
+ FeSquare(&v3, &v)
+ FeMul(&v3, &v3, &v) // v3 = v^3
+ FeSquare(&p.X, &v3)
+ FeMul(&p.X, &p.X, &v)
+ FeMul(&p.X, &p.X, &u) // x = uv^7
+
+ fePow22523(&p.X, &p.X) // x = (uv^7)^((q-5)/8)
+ FeMul(&p.X, &p.X, &v3)
+ FeMul(&p.X, &p.X, &u) // x = uv^3(uv^7)^((q-5)/8)
+
+ var tmpX, tmp2 [32]byte
+
+ FeSquare(&vxx, &p.X)
+ FeMul(&vxx, &vxx, &v)
+ FeSub(&check, &vxx, &u) // vx^2-u
+ if FeIsNonZero(&check) == 1 {
+ FeAdd(&check, &vxx, &u) // vx^2+u
+ if FeIsNonZero(&check) == 1 {
+ return false
+ }
+ FeMul(&p.X, &p.X, &SqrtM1)
+
+ FeToBytes(&tmpX, &p.X)
+ for i, v := range tmpX {
+ tmp2[31-i] = v
+ }
+ }
+
+ if FeIsNegative(&p.X) != (s[31] >> 7) {
+ FeNeg(&p.X, &p.X)
+ }
+
+ FeMul(&p.T, &p.X, &p.Y)
+ return true
+}
+
+func (p *CompletedGroupElement) ToProjective(r *ProjectiveGroupElement) {
+ FeMul(&r.X, &p.X, &p.T)
+ FeMul(&r.Y, &p.Y, &p.Z)
+ FeMul(&r.Z, &p.Z, &p.T)
+}
+
+func (p *CompletedGroupElement) ToExtended(r *ExtendedGroupElement) {
+ FeMul(&r.X, &p.X, &p.T)
+ FeMul(&r.Y, &p.Y, &p.Z)
+ FeMul(&r.Z, &p.Z, &p.T)
+ FeMul(&r.T, &p.X, &p.Y)
+}
+
+func (p *PreComputedGroupElement) Zero() {
+ FeOne(&p.yPlusX)
+ FeOne(&p.yMinusX)
+ FeZero(&p.xy2d)
+}
+
+func geAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) {
+ var t0 FieldElement
+
+ FeAdd(&r.X, &p.Y, &p.X)
+ FeSub(&r.Y, &p.Y, &p.X)
+ FeMul(&r.Z, &r.X, &q.yPlusX)
+ FeMul(&r.Y, &r.Y, &q.yMinusX)
+ FeMul(&r.T, &q.T2d, &p.T)
+ FeMul(&r.X, &p.Z, &q.Z)
+ FeAdd(&t0, &r.X, &r.X)
+ FeSub(&r.X, &r.Z, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.Y)
+ FeAdd(&r.Z, &t0, &r.T)
+ FeSub(&r.T, &t0, &r.T)
+}
+
+func geSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) {
+ var t0 FieldElement
+
+ FeAdd(&r.X, &p.Y, &p.X)
+ FeSub(&r.Y, &p.Y, &p.X)
+ FeMul(&r.Z, &r.X, &q.yMinusX)
+ FeMul(&r.Y, &r.Y, &q.yPlusX)
+ FeMul(&r.T, &q.T2d, &p.T)
+ FeMul(&r.X, &p.Z, &q.Z)
+ FeAdd(&t0, &r.X, &r.X)
+ FeSub(&r.X, &r.Z, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.Y)
+ FeSub(&r.Z, &t0, &r.T)
+ FeAdd(&r.T, &t0, &r.T)
+}
+
+func geMixedAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) {
+ var t0 FieldElement
+
+ FeAdd(&r.X, &p.Y, &p.X)
+ FeSub(&r.Y, &p.Y, &p.X)
+ FeMul(&r.Z, &r.X, &q.yPlusX)
+ FeMul(&r.Y, &r.Y, &q.yMinusX)
+ FeMul(&r.T, &q.xy2d, &p.T)
+ FeAdd(&t0, &p.Z, &p.Z)
+ FeSub(&r.X, &r.Z, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.Y)
+ FeAdd(&r.Z, &t0, &r.T)
+ FeSub(&r.T, &t0, &r.T)
+}
+
+func geMixedSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) {
+ var t0 FieldElement
+
+ FeAdd(&r.X, &p.Y, &p.X)
+ FeSub(&r.Y, &p.Y, &p.X)
+ FeMul(&r.Z, &r.X, &q.yMinusX)
+ FeMul(&r.Y, &r.Y, &q.yPlusX)
+ FeMul(&r.T, &q.xy2d, &p.T)
+ FeAdd(&t0, &p.Z, &p.Z)
+ FeSub(&r.X, &r.Z, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.Y)
+ FeSub(&r.Z, &t0, &r.T)
+ FeAdd(&r.T, &t0, &r.T)
+}
+
+func slide(r *[256]int8, a *[32]byte) {
+ for i := range r {
+ r[i] = int8(1 & (a[i>>3] >> uint(i&7)))
+ }
+
+ for i := range r {
+ if r[i] != 0 {
+ for b := 1; b <= 6 && i+b < 256; b++ {
+ if r[i+b] != 0 {
+ if r[i]+(r[i+b]<= -15 {
+ r[i] -= r[i+b] << uint(b)
+ for k := i + b; k < 256; k++ {
+ if r[k] == 0 {
+ r[k] = 1
+ break
+ }
+ r[k] = 0
+ }
+ } else {
+ break
+ }
+ }
+ }
+ }
+ }
+}
+
+// GeDoubleScalarMultVartime sets r = a*A + b*B
+// where a = a[0]+256*a[1]+...+256^31 a[31].
+// and b = b[0]+256*b[1]+...+256^31 b[31].
+// B is the Ed25519 base point (x,4/5) with x positive.
+func GeDoubleScalarMultVartime(r *ProjectiveGroupElement, a *[32]byte, A *ExtendedGroupElement, b *[32]byte) {
+ var aSlide, bSlide [256]int8
+ var Ai [8]CachedGroupElement // A,3A,5A,7A,9A,11A,13A,15A
+ var t CompletedGroupElement
+ var u, A2 ExtendedGroupElement
+ var i int
+
+ slide(&aSlide, a)
+ slide(&bSlide, b)
+
+ A.ToCached(&Ai[0])
+ A.Double(&t)
+ t.ToExtended(&A2)
+
+ for i := 0; i < 7; i++ {
+ geAdd(&t, &A2, &Ai[i])
+ t.ToExtended(&u)
+ u.ToCached(&Ai[i+1])
+ }
+
+ r.Zero()
+
+ for i = 255; i >= 0; i-- {
+ if aSlide[i] != 0 || bSlide[i] != 0 {
+ break
+ }
+ }
+
+ for ; i >= 0; i-- {
+ r.Double(&t)
+
+ if aSlide[i] > 0 {
+ t.ToExtended(&u)
+ geAdd(&t, &u, &Ai[aSlide[i]/2])
+ } else if aSlide[i] < 0 {
+ t.ToExtended(&u)
+ geSub(&t, &u, &Ai[(-aSlide[i])/2])
+ }
+
+ if bSlide[i] > 0 {
+ t.ToExtended(&u)
+ geMixedAdd(&t, &u, &bi[bSlide[i]/2])
+ } else if bSlide[i] < 0 {
+ t.ToExtended(&u)
+ geMixedSub(&t, &u, &bi[(-bSlide[i])/2])
+ }
+
+ t.ToProjective(r)
+ }
+}
+
+// equal returns 1 if b == c and 0 otherwise.
+func equal(b, c int32) int32 {
+ x := uint32(b ^ c)
+ x--
+ return int32(x >> 31)
+}
+
+// negative returns 1 if b < 0 and 0 otherwise.
+func negative(b int32) int32 {
+ return (b >> 31) & 1
+}
+
+func PreComputedGroupElementCMove(t, u *PreComputedGroupElement, b int32) {
+ FeCMove(&t.yPlusX, &u.yPlusX, b)
+ FeCMove(&t.yMinusX, &u.yMinusX, b)
+ FeCMove(&t.xy2d, &u.xy2d, b)
+}
+
+func selectPoint(t *PreComputedGroupElement, pos int32, b int32) {
+ var minusT PreComputedGroupElement
+ bNegative := negative(b)
+ bAbs := b - (((-bNegative) & b) << 1)
+
+ t.Zero()
+ for i := int32(0); i < 8; i++ {
+ PreComputedGroupElementCMove(t, &base[pos][i], equal(bAbs, i+1))
+ }
+ FeCopy(&minusT.yPlusX, &t.yMinusX)
+ FeCopy(&minusT.yMinusX, &t.yPlusX)
+ FeNeg(&minusT.xy2d, &t.xy2d)
+ PreComputedGroupElementCMove(t, &minusT, bNegative)
+}
+
+// GeScalarMultBase computes h = a*B, where
+// a = a[0]+256*a[1]+...+256^31 a[31]
+// B is the Ed25519 base point (x,4/5) with x positive.
+//
+// Preconditions:
+// a[31] <= 127
+func GeScalarMultBase(h *ExtendedGroupElement, a *[32]byte) {
+ var e [64]int8
+
+ for i, v := range a {
+ e[2*i] = int8(v & 15)
+ e[2*i+1] = int8((v >> 4) & 15)
+ }
+
+ // each e[i] is between 0 and 15 and e[63] is between 0 and 7.
+
+ carry := int8(0)
+ for i := 0; i < 63; i++ {
+ e[i] += carry
+ carry = (e[i] + 8) >> 4
+ e[i] -= carry << 4
+ }
+ e[63] += carry
+ // each e[i] is between -8 and 8.
+
+ h.Zero()
+ var t PreComputedGroupElement
+ var r CompletedGroupElement
+ for i := int32(1); i < 64; i += 2 {
+ selectPoint(&t, i/2, int32(e[i]))
+ geMixedAdd(&r, h, &t)
+ r.ToExtended(h)
+ }
+
+ var s ProjectiveGroupElement
+
+ h.Double(&r)
+ r.ToProjective(&s)
+ s.Double(&r)
+ r.ToProjective(&s)
+ s.Double(&r)
+ r.ToProjective(&s)
+ s.Double(&r)
+ r.ToExtended(h)
+
+ for i := int32(0); i < 64; i += 2 {
+ selectPoint(&t, i/2, int32(e[i]))
+ geMixedAdd(&r, h, &t)
+ r.ToExtended(h)
+ }
+}
+
+// The scalars are GF(2^252 + 27742317777372353535851937790883648493).
+
+// Input:
+// a[0]+256*a[1]+...+256^31*a[31] = a
+// b[0]+256*b[1]+...+256^31*b[31] = b
+// c[0]+256*c[1]+...+256^31*c[31] = c
+//
+// Output:
+// s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
+// where l = 2^252 + 27742317777372353535851937790883648493.
+func ScMulAdd(s, a, b, c *[32]byte) {
+ a0 := 2097151 & load3(a[:])
+ a1 := 2097151 & (load4(a[2:]) >> 5)
+ a2 := 2097151 & (load3(a[5:]) >> 2)
+ a3 := 2097151 & (load4(a[7:]) >> 7)
+ a4 := 2097151 & (load4(a[10:]) >> 4)
+ a5 := 2097151 & (load3(a[13:]) >> 1)
+ a6 := 2097151 & (load4(a[15:]) >> 6)
+ a7 := 2097151 & (load3(a[18:]) >> 3)
+ a8 := 2097151 & load3(a[21:])
+ a9 := 2097151 & (load4(a[23:]) >> 5)
+ a10 := 2097151 & (load3(a[26:]) >> 2)
+ a11 := (load4(a[28:]) >> 7)
+ b0 := 2097151 & load3(b[:])
+ b1 := 2097151 & (load4(b[2:]) >> 5)
+ b2 := 2097151 & (load3(b[5:]) >> 2)
+ b3 := 2097151 & (load4(b[7:]) >> 7)
+ b4 := 2097151 & (load4(b[10:]) >> 4)
+ b5 := 2097151 & (load3(b[13:]) >> 1)
+ b6 := 2097151 & (load4(b[15:]) >> 6)
+ b7 := 2097151 & (load3(b[18:]) >> 3)
+ b8 := 2097151 & load3(b[21:])
+ b9 := 2097151 & (load4(b[23:]) >> 5)
+ b10 := 2097151 & (load3(b[26:]) >> 2)
+ b11 := (load4(b[28:]) >> 7)
+ c0 := 2097151 & load3(c[:])
+ c1 := 2097151 & (load4(c[2:]) >> 5)
+ c2 := 2097151 & (load3(c[5:]) >> 2)
+ c3 := 2097151 & (load4(c[7:]) >> 7)
+ c4 := 2097151 & (load4(c[10:]) >> 4)
+ c5 := 2097151 & (load3(c[13:]) >> 1)
+ c6 := 2097151 & (load4(c[15:]) >> 6)
+ c7 := 2097151 & (load3(c[18:]) >> 3)
+ c8 := 2097151 & load3(c[21:])
+ c9 := 2097151 & (load4(c[23:]) >> 5)
+ c10 := 2097151 & (load3(c[26:]) >> 2)
+ c11 := (load4(c[28:]) >> 7)
+ var carry [23]int64
+
+ s0 := c0 + a0*b0
+ s1 := c1 + a0*b1 + a1*b0
+ s2 := c2 + a0*b2 + a1*b1 + a2*b0
+ s3 := c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0
+ s4 := c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0
+ s5 := c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0
+ s6 := c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0
+ s7 := c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0
+ s8 := c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0
+ s9 := c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0
+ s10 := c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0
+ s11 := c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0
+ s12 := a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1
+ s13 := a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2
+ s14 := a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3
+ s15 := a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4
+ s16 := a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5
+ s17 := a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6
+ s18 := a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7
+ s19 := a8*b11 + a9*b10 + a10*b9 + a11*b8
+ s20 := a9*b11 + a10*b10 + a11*b9
+ s21 := a10*b11 + a11*b10
+ s22 := a11 * b11
+ s23 := int64(0)
+
+ carry[0] = (s0 + (1 << 20)) >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[2] = (s2 + (1 << 20)) >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[4] = (s4 + (1 << 20)) >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[12] = (s12 + (1 << 20)) >> 21
+ s13 += carry[12]
+ s12 -= carry[12] << 21
+ carry[14] = (s14 + (1 << 20)) >> 21
+ s15 += carry[14]
+ s14 -= carry[14] << 21
+ carry[16] = (s16 + (1 << 20)) >> 21
+ s17 += carry[16]
+ s16 -= carry[16] << 21
+ carry[18] = (s18 + (1 << 20)) >> 21
+ s19 += carry[18]
+ s18 -= carry[18] << 21
+ carry[20] = (s20 + (1 << 20)) >> 21
+ s21 += carry[20]
+ s20 -= carry[20] << 21
+ carry[22] = (s22 + (1 << 20)) >> 21
+ s23 += carry[22]
+ s22 -= carry[22] << 21
+
+ carry[1] = (s1 + (1 << 20)) >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[3] = (s3 + (1 << 20)) >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[5] = (s5 + (1 << 20)) >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+ carry[13] = (s13 + (1 << 20)) >> 21
+ s14 += carry[13]
+ s13 -= carry[13] << 21
+ carry[15] = (s15 + (1 << 20)) >> 21
+ s16 += carry[15]
+ s15 -= carry[15] << 21
+ carry[17] = (s17 + (1 << 20)) >> 21
+ s18 += carry[17]
+ s17 -= carry[17] << 21
+ carry[19] = (s19 + (1 << 20)) >> 21
+ s20 += carry[19]
+ s19 -= carry[19] << 21
+ carry[21] = (s21 + (1 << 20)) >> 21
+ s22 += carry[21]
+ s21 -= carry[21] << 21
+
+ s11 += s23 * 666643
+ s12 += s23 * 470296
+ s13 += s23 * 654183
+ s14 -= s23 * 997805
+ s15 += s23 * 136657
+ s16 -= s23 * 683901
+ s23 = 0
+
+ s10 += s22 * 666643
+ s11 += s22 * 470296
+ s12 += s22 * 654183
+ s13 -= s22 * 997805
+ s14 += s22 * 136657
+ s15 -= s22 * 683901
+ s22 = 0
+
+ s9 += s21 * 666643
+ s10 += s21 * 470296
+ s11 += s21 * 654183
+ s12 -= s21 * 997805
+ s13 += s21 * 136657
+ s14 -= s21 * 683901
+ s21 = 0
+
+ s8 += s20 * 666643
+ s9 += s20 * 470296
+ s10 += s20 * 654183
+ s11 -= s20 * 997805
+ s12 += s20 * 136657
+ s13 -= s20 * 683901
+ s20 = 0
+
+ s7 += s19 * 666643
+ s8 += s19 * 470296
+ s9 += s19 * 654183
+ s10 -= s19 * 997805
+ s11 += s19 * 136657
+ s12 -= s19 * 683901
+ s19 = 0
+
+ s6 += s18 * 666643
+ s7 += s18 * 470296
+ s8 += s18 * 654183
+ s9 -= s18 * 997805
+ s10 += s18 * 136657
+ s11 -= s18 * 683901
+ s18 = 0
+
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[12] = (s12 + (1 << 20)) >> 21
+ s13 += carry[12]
+ s12 -= carry[12] << 21
+ carry[14] = (s14 + (1 << 20)) >> 21
+ s15 += carry[14]
+ s14 -= carry[14] << 21
+ carry[16] = (s16 + (1 << 20)) >> 21
+ s17 += carry[16]
+ s16 -= carry[16] << 21
+
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+ carry[13] = (s13 + (1 << 20)) >> 21
+ s14 += carry[13]
+ s13 -= carry[13] << 21
+ carry[15] = (s15 + (1 << 20)) >> 21
+ s16 += carry[15]
+ s15 -= carry[15] << 21
+
+ s5 += s17 * 666643
+ s6 += s17 * 470296
+ s7 += s17 * 654183
+ s8 -= s17 * 997805
+ s9 += s17 * 136657
+ s10 -= s17 * 683901
+ s17 = 0
+
+ s4 += s16 * 666643
+ s5 += s16 * 470296
+ s6 += s16 * 654183
+ s7 -= s16 * 997805
+ s8 += s16 * 136657
+ s9 -= s16 * 683901
+ s16 = 0
+
+ s3 += s15 * 666643
+ s4 += s15 * 470296
+ s5 += s15 * 654183
+ s6 -= s15 * 997805
+ s7 += s15 * 136657
+ s8 -= s15 * 683901
+ s15 = 0
+
+ s2 += s14 * 666643
+ s3 += s14 * 470296
+ s4 += s14 * 654183
+ s5 -= s14 * 997805
+ s6 += s14 * 136657
+ s7 -= s14 * 683901
+ s14 = 0
+
+ s1 += s13 * 666643
+ s2 += s13 * 470296
+ s3 += s13 * 654183
+ s4 -= s13 * 997805
+ s5 += s13 * 136657
+ s6 -= s13 * 683901
+ s13 = 0
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = (s0 + (1 << 20)) >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[2] = (s2 + (1 << 20)) >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[4] = (s4 + (1 << 20)) >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+
+ carry[1] = (s1 + (1 << 20)) >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[3] = (s3 + (1 << 20)) >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[5] = (s5 + (1 << 20)) >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = s0 >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[1] = s1 >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[2] = s2 >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[3] = s3 >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[4] = s4 >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[5] = s5 >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[6] = s6 >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[7] = s7 >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[8] = s8 >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[9] = s9 >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[10] = s10 >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[11] = s11 >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = s0 >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[1] = s1 >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[2] = s2 >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[3] = s3 >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[4] = s4 >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[5] = s5 >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[6] = s6 >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[7] = s7 >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[8] = s8 >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[9] = s9 >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[10] = s10 >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+
+ s[0] = byte(s0 >> 0)
+ s[1] = byte(s0 >> 8)
+ s[2] = byte((s0 >> 16) | (s1 << 5))
+ s[3] = byte(s1 >> 3)
+ s[4] = byte(s1 >> 11)
+ s[5] = byte((s1 >> 19) | (s2 << 2))
+ s[6] = byte(s2 >> 6)
+ s[7] = byte((s2 >> 14) | (s3 << 7))
+ s[8] = byte(s3 >> 1)
+ s[9] = byte(s3 >> 9)
+ s[10] = byte((s3 >> 17) | (s4 << 4))
+ s[11] = byte(s4 >> 4)
+ s[12] = byte(s4 >> 12)
+ s[13] = byte((s4 >> 20) | (s5 << 1))
+ s[14] = byte(s5 >> 7)
+ s[15] = byte((s5 >> 15) | (s6 << 6))
+ s[16] = byte(s6 >> 2)
+ s[17] = byte(s6 >> 10)
+ s[18] = byte((s6 >> 18) | (s7 << 3))
+ s[19] = byte(s7 >> 5)
+ s[20] = byte(s7 >> 13)
+ s[21] = byte(s8 >> 0)
+ s[22] = byte(s8 >> 8)
+ s[23] = byte((s8 >> 16) | (s9 << 5))
+ s[24] = byte(s9 >> 3)
+ s[25] = byte(s9 >> 11)
+ s[26] = byte((s9 >> 19) | (s10 << 2))
+ s[27] = byte(s10 >> 6)
+ s[28] = byte((s10 >> 14) | (s11 << 7))
+ s[29] = byte(s11 >> 1)
+ s[30] = byte(s11 >> 9)
+ s[31] = byte(s11 >> 17)
+}
+
+// Input:
+// s[0]+256*s[1]+...+256^63*s[63] = s
+//
+// Output:
+// s[0]+256*s[1]+...+256^31*s[31] = s mod l
+// where l = 2^252 + 27742317777372353535851937790883648493.
+func ScReduce(out *[32]byte, s *[64]byte) {
+ s0 := 2097151 & load3(s[:])
+ s1 := 2097151 & (load4(s[2:]) >> 5)
+ s2 := 2097151 & (load3(s[5:]) >> 2)
+ s3 := 2097151 & (load4(s[7:]) >> 7)
+ s4 := 2097151 & (load4(s[10:]) >> 4)
+ s5 := 2097151 & (load3(s[13:]) >> 1)
+ s6 := 2097151 & (load4(s[15:]) >> 6)
+ s7 := 2097151 & (load3(s[18:]) >> 3)
+ s8 := 2097151 & load3(s[21:])
+ s9 := 2097151 & (load4(s[23:]) >> 5)
+ s10 := 2097151 & (load3(s[26:]) >> 2)
+ s11 := 2097151 & (load4(s[28:]) >> 7)
+ s12 := 2097151 & (load4(s[31:]) >> 4)
+ s13 := 2097151 & (load3(s[34:]) >> 1)
+ s14 := 2097151 & (load4(s[36:]) >> 6)
+ s15 := 2097151 & (load3(s[39:]) >> 3)
+ s16 := 2097151 & load3(s[42:])
+ s17 := 2097151 & (load4(s[44:]) >> 5)
+ s18 := 2097151 & (load3(s[47:]) >> 2)
+ s19 := 2097151 & (load4(s[49:]) >> 7)
+ s20 := 2097151 & (load4(s[52:]) >> 4)
+ s21 := 2097151 & (load3(s[55:]) >> 1)
+ s22 := 2097151 & (load4(s[57:]) >> 6)
+ s23 := (load4(s[60:]) >> 3)
+
+ s11 += s23 * 666643
+ s12 += s23 * 470296
+ s13 += s23 * 654183
+ s14 -= s23 * 997805
+ s15 += s23 * 136657
+ s16 -= s23 * 683901
+ s23 = 0
+
+ s10 += s22 * 666643
+ s11 += s22 * 470296
+ s12 += s22 * 654183
+ s13 -= s22 * 997805
+ s14 += s22 * 136657
+ s15 -= s22 * 683901
+ s22 = 0
+
+ s9 += s21 * 666643
+ s10 += s21 * 470296
+ s11 += s21 * 654183
+ s12 -= s21 * 997805
+ s13 += s21 * 136657
+ s14 -= s21 * 683901
+ s21 = 0
+
+ s8 += s20 * 666643
+ s9 += s20 * 470296
+ s10 += s20 * 654183
+ s11 -= s20 * 997805
+ s12 += s20 * 136657
+ s13 -= s20 * 683901
+ s20 = 0
+
+ s7 += s19 * 666643
+ s8 += s19 * 470296
+ s9 += s19 * 654183
+ s10 -= s19 * 997805
+ s11 += s19 * 136657
+ s12 -= s19 * 683901
+ s19 = 0
+
+ s6 += s18 * 666643
+ s7 += s18 * 470296
+ s8 += s18 * 654183
+ s9 -= s18 * 997805
+ s10 += s18 * 136657
+ s11 -= s18 * 683901
+ s18 = 0
+
+ var carry [17]int64
+
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[12] = (s12 + (1 << 20)) >> 21
+ s13 += carry[12]
+ s12 -= carry[12] << 21
+ carry[14] = (s14 + (1 << 20)) >> 21
+ s15 += carry[14]
+ s14 -= carry[14] << 21
+ carry[16] = (s16 + (1 << 20)) >> 21
+ s17 += carry[16]
+ s16 -= carry[16] << 21
+
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+ carry[13] = (s13 + (1 << 20)) >> 21
+ s14 += carry[13]
+ s13 -= carry[13] << 21
+ carry[15] = (s15 + (1 << 20)) >> 21
+ s16 += carry[15]
+ s15 -= carry[15] << 21
+
+ s5 += s17 * 666643
+ s6 += s17 * 470296
+ s7 += s17 * 654183
+ s8 -= s17 * 997805
+ s9 += s17 * 136657
+ s10 -= s17 * 683901
+ s17 = 0
+
+ s4 += s16 * 666643
+ s5 += s16 * 470296
+ s6 += s16 * 654183
+ s7 -= s16 * 997805
+ s8 += s16 * 136657
+ s9 -= s16 * 683901
+ s16 = 0
+
+ s3 += s15 * 666643
+ s4 += s15 * 470296
+ s5 += s15 * 654183
+ s6 -= s15 * 997805
+ s7 += s15 * 136657
+ s8 -= s15 * 683901
+ s15 = 0
+
+ s2 += s14 * 666643
+ s3 += s14 * 470296
+ s4 += s14 * 654183
+ s5 -= s14 * 997805
+ s6 += s14 * 136657
+ s7 -= s14 * 683901
+ s14 = 0
+
+ s1 += s13 * 666643
+ s2 += s13 * 470296
+ s3 += s13 * 654183
+ s4 -= s13 * 997805
+ s5 += s13 * 136657
+ s6 -= s13 * 683901
+ s13 = 0
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = (s0 + (1 << 20)) >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[2] = (s2 + (1 << 20)) >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[4] = (s4 + (1 << 20)) >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+
+ carry[1] = (s1 + (1 << 20)) >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[3] = (s3 + (1 << 20)) >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[5] = (s5 + (1 << 20)) >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = s0 >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[1] = s1 >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[2] = s2 >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[3] = s3 >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[4] = s4 >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[5] = s5 >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[6] = s6 >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[7] = s7 >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[8] = s8 >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[9] = s9 >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[10] = s10 >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[11] = s11 >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = s0 >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[1] = s1 >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[2] = s2 >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[3] = s3 >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[4] = s4 >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[5] = s5 >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[6] = s6 >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[7] = s7 >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[8] = s8 >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[9] = s9 >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[10] = s10 >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+
+ out[0] = byte(s0 >> 0)
+ out[1] = byte(s0 >> 8)
+ out[2] = byte((s0 >> 16) | (s1 << 5))
+ out[3] = byte(s1 >> 3)
+ out[4] = byte(s1 >> 11)
+ out[5] = byte((s1 >> 19) | (s2 << 2))
+ out[6] = byte(s2 >> 6)
+ out[7] = byte((s2 >> 14) | (s3 << 7))
+ out[8] = byte(s3 >> 1)
+ out[9] = byte(s3 >> 9)
+ out[10] = byte((s3 >> 17) | (s4 << 4))
+ out[11] = byte(s4 >> 4)
+ out[12] = byte(s4 >> 12)
+ out[13] = byte((s4 >> 20) | (s5 << 1))
+ out[14] = byte(s5 >> 7)
+ out[15] = byte((s5 >> 15) | (s6 << 6))
+ out[16] = byte(s6 >> 2)
+ out[17] = byte(s6 >> 10)
+ out[18] = byte((s6 >> 18) | (s7 << 3))
+ out[19] = byte(s7 >> 5)
+ out[20] = byte(s7 >> 13)
+ out[21] = byte(s8 >> 0)
+ out[22] = byte(s8 >> 8)
+ out[23] = byte((s8 >> 16) | (s9 << 5))
+ out[24] = byte(s9 >> 3)
+ out[25] = byte(s9 >> 11)
+ out[26] = byte((s9 >> 19) | (s10 << 2))
+ out[27] = byte(s10 >> 6)
+ out[28] = byte((s10 >> 14) | (s11 << 7))
+ out[29] = byte(s11 >> 1)
+ out[30] = byte(s11 >> 9)
+ out[31] = byte(s11 >> 17)
+}
diff --git a/vendor/github.com/agl/ed25519/extra25519/extra25519.go b/vendor/github.com/agl/ed25519/extra25519/extra25519.go
new file mode 100644
index 0000000..b897ba5
--- /dev/null
+++ b/vendor/github.com/agl/ed25519/extra25519/extra25519.go
@@ -0,0 +1,340 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package extra25519
+
+import (
+ "crypto/sha512"
+
+ "github.com/agl/ed25519/edwards25519"
+)
+
+// PrivateKeyToCurve25519 converts an ed25519 private key into a corresponding
+// curve25519 private key such that the resulting curve25519 public key will
+// equal the result from PublicKeyToCurve25519.
+func PrivateKeyToCurve25519(curve25519Private *[32]byte, privateKey *[64]byte) {
+ h := sha512.New()
+ h.Write(privateKey[:32])
+ digest := h.Sum(nil)
+
+ digest[0] &= 248
+ digest[31] &= 127
+ digest[31] |= 64
+
+ copy(curve25519Private[:], digest)
+}
+
+func edwardsToMontgomeryX(outX, y *edwards25519.FieldElement) {
+ // We only need the x-coordinate of the curve25519 point, which I'll
+ // call u. The isomorphism is u=(y+1)/(1-y), since y=Y/Z, this gives
+ // u=(Y+Z)/(Z-Y). We know that Z=1, thus u=(Y+1)/(1-Y).
+ var oneMinusY edwards25519.FieldElement
+ edwards25519.FeOne(&oneMinusY)
+ edwards25519.FeSub(&oneMinusY, &oneMinusY, y)
+ edwards25519.FeInvert(&oneMinusY, &oneMinusY)
+
+ edwards25519.FeOne(outX)
+ edwards25519.FeAdd(outX, outX, y)
+
+ edwards25519.FeMul(outX, outX, &oneMinusY)
+}
+
+// PublicKeyToCurve25519 converts an Ed25519 public key into the curve25519
+// public key that would be generated from the same private key.
+func PublicKeyToCurve25519(curve25519Public *[32]byte, publicKey *[32]byte) bool {
+ var A edwards25519.ExtendedGroupElement
+ if !A.FromBytes(publicKey) {
+ return false
+ }
+
+ // A.Z = 1 as a postcondition of FromBytes.
+ var x edwards25519.FieldElement
+ edwardsToMontgomeryX(&x, &A.Y)
+ edwards25519.FeToBytes(curve25519Public, &x)
+ return true
+}
+
+// sqrtMinusAPlus2 is sqrt(-(486662+2))
+var sqrtMinusAPlus2 = edwards25519.FieldElement{
+ -12222970, -8312128, -11511410, 9067497, -15300785, -241793, 25456130, 14121551, -12187136, 3972024,
+}
+
+// sqrtMinusHalf is sqrt(-1/2)
+var sqrtMinusHalf = edwards25519.FieldElement{
+ -17256545, 3971863, 28865457, -1750208, 27359696, -16640980, 12573105, 1002827, -163343, 11073975,
+}
+
+// halfQMinus1Bytes is (2^255-20)/2 expressed in little endian form.
+var halfQMinus1Bytes = [32]byte{
+ 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
+}
+
+// feBytesLess returns one if a <= b and zero otherwise.
+func feBytesLE(a, b *[32]byte) int32 {
+ equalSoFar := int32(-1)
+ greater := int32(0)
+
+ for i := uint(31); i < 32; i-- {
+ x := int32(a[i])
+ y := int32(b[i])
+
+ greater = (^equalSoFar & greater) | (equalSoFar & ((x - y) >> 31))
+ equalSoFar = equalSoFar & (((x ^ y) - 1) >> 31)
+ }
+
+ return int32(^equalSoFar & 1 & greater)
+}
+
+// ScalarBaseMult computes a curve25519 public key from a private key and also
+// a uniform representative for that public key. Note that this function will
+// fail and return false for about half of private keys.
+// See http://elligator.cr.yp.to/elligator-20130828.pdf.
+func ScalarBaseMult(publicKey, representative, privateKey *[32]byte) bool {
+ var maskedPrivateKey [32]byte
+ copy(maskedPrivateKey[:], privateKey[:])
+
+ maskedPrivateKey[0] &= 248
+ maskedPrivateKey[31] &= 127
+ maskedPrivateKey[31] |= 64
+
+ var A edwards25519.ExtendedGroupElement
+ edwards25519.GeScalarMultBase(&A, &maskedPrivateKey)
+
+ var inv1 edwards25519.FieldElement
+ edwards25519.FeSub(&inv1, &A.Z, &A.Y)
+ edwards25519.FeMul(&inv1, &inv1, &A.X)
+ edwards25519.FeInvert(&inv1, &inv1)
+
+ var t0, u edwards25519.FieldElement
+ edwards25519.FeMul(&u, &inv1, &A.X)
+ edwards25519.FeAdd(&t0, &A.Y, &A.Z)
+ edwards25519.FeMul(&u, &u, &t0)
+
+ var v edwards25519.FieldElement
+ edwards25519.FeMul(&v, &t0, &inv1)
+ edwards25519.FeMul(&v, &v, &A.Z)
+ edwards25519.FeMul(&v, &v, &sqrtMinusAPlus2)
+
+ var b edwards25519.FieldElement
+ edwards25519.FeAdd(&b, &u, &edwards25519.A)
+
+ var c, b3, b7, b8 edwards25519.FieldElement
+ edwards25519.FeSquare(&b3, &b) // 2
+ edwards25519.FeMul(&b3, &b3, &b) // 3
+ edwards25519.FeSquare(&c, &b3) // 6
+ edwards25519.FeMul(&b7, &c, &b) // 7
+ edwards25519.FeMul(&b8, &b7, &b) // 8
+ edwards25519.FeMul(&c, &b7, &u)
+ q58(&c, &c)
+
+ var chi edwards25519.FieldElement
+ edwards25519.FeSquare(&chi, &c)
+ edwards25519.FeSquare(&chi, &chi)
+
+ edwards25519.FeSquare(&t0, &u)
+ edwards25519.FeMul(&chi, &chi, &t0)
+
+ edwards25519.FeSquare(&t0, &b7) // 14
+ edwards25519.FeMul(&chi, &chi, &t0)
+ edwards25519.FeNeg(&chi, &chi)
+
+ var chiBytes [32]byte
+ edwards25519.FeToBytes(&chiBytes, &chi)
+ // chi[1] is either 0 or 0xff
+ if chiBytes[1] == 0xff {
+ return false
+ }
+
+ // Calculate r1 = sqrt(-u/(2*(u+A)))
+ var r1 edwards25519.FieldElement
+ edwards25519.FeMul(&r1, &c, &u)
+ edwards25519.FeMul(&r1, &r1, &b3)
+ edwards25519.FeMul(&r1, &r1, &sqrtMinusHalf)
+
+ var maybeSqrtM1 edwards25519.FieldElement
+ edwards25519.FeSquare(&t0, &r1)
+ edwards25519.FeMul(&t0, &t0, &b)
+ edwards25519.FeAdd(&t0, &t0, &t0)
+ edwards25519.FeAdd(&t0, &t0, &u)
+
+ edwards25519.FeOne(&maybeSqrtM1)
+ edwards25519.FeCMove(&maybeSqrtM1, &edwards25519.SqrtM1, edwards25519.FeIsNonZero(&t0))
+ edwards25519.FeMul(&r1, &r1, &maybeSqrtM1)
+
+ // Calculate r = sqrt(-(u+A)/(2u))
+ var r edwards25519.FieldElement
+ edwards25519.FeSquare(&t0, &c) // 2
+ edwards25519.FeMul(&t0, &t0, &c) // 3
+ edwards25519.FeSquare(&t0, &t0) // 6
+ edwards25519.FeMul(&r, &t0, &c) // 7
+
+ edwards25519.FeSquare(&t0, &u) // 2
+ edwards25519.FeMul(&t0, &t0, &u) // 3
+ edwards25519.FeMul(&r, &r, &t0)
+
+ edwards25519.FeSquare(&t0, &b8) // 16
+ edwards25519.FeMul(&t0, &t0, &b8) // 24
+ edwards25519.FeMul(&t0, &t0, &b) // 25
+ edwards25519.FeMul(&r, &r, &t0)
+ edwards25519.FeMul(&r, &r, &sqrtMinusHalf)
+
+ edwards25519.FeSquare(&t0, &r)
+ edwards25519.FeMul(&t0, &t0, &u)
+ edwards25519.FeAdd(&t0, &t0, &t0)
+ edwards25519.FeAdd(&t0, &t0, &b)
+ edwards25519.FeOne(&maybeSqrtM1)
+ edwards25519.FeCMove(&maybeSqrtM1, &edwards25519.SqrtM1, edwards25519.FeIsNonZero(&t0))
+ edwards25519.FeMul(&r, &r, &maybeSqrtM1)
+
+ var vBytes [32]byte
+ edwards25519.FeToBytes(&vBytes, &v)
+ vInSquareRootImage := feBytesLE(&vBytes, &halfQMinus1Bytes)
+ edwards25519.FeCMove(&r, &r1, vInSquareRootImage)
+
+ edwards25519.FeToBytes(publicKey, &u)
+ edwards25519.FeToBytes(representative, &r)
+ return true
+}
+
+// q58 calculates out = z^((p-5)/8).
+func q58(out, z *edwards25519.FieldElement) {
+ var t1, t2, t3 edwards25519.FieldElement
+ var i int
+
+ edwards25519.FeSquare(&t1, z) // 2^1
+ edwards25519.FeMul(&t1, &t1, z) // 2^1 + 2^0
+ edwards25519.FeSquare(&t1, &t1) // 2^2 + 2^1
+ edwards25519.FeSquare(&t2, &t1) // 2^3 + 2^2
+ edwards25519.FeSquare(&t2, &t2) // 2^4 + 2^3
+ edwards25519.FeMul(&t2, &t2, &t1) // 4,3,2,1
+ edwards25519.FeMul(&t1, &t2, z) // 4..0
+ edwards25519.FeSquare(&t2, &t1) // 5..1
+ for i = 1; i < 5; i++ { // 9,8,7,6,5
+ edwards25519.FeSquare(&t2, &t2)
+ }
+ edwards25519.FeMul(&t1, &t2, &t1) // 9,8,7,6,5,4,3,2,1,0
+ edwards25519.FeSquare(&t2, &t1) // 10..1
+ for i = 1; i < 10; i++ { // 19..10
+ edwards25519.FeSquare(&t2, &t2)
+ }
+ edwards25519.FeMul(&t2, &t2, &t1) // 19..0
+ edwards25519.FeSquare(&t3, &t2) // 20..1
+ for i = 1; i < 20; i++ { // 39..20
+ edwards25519.FeSquare(&t3, &t3)
+ }
+ edwards25519.FeMul(&t2, &t3, &t2) // 39..0
+ edwards25519.FeSquare(&t2, &t2) // 40..1
+ for i = 1; i < 10; i++ { // 49..10
+ edwards25519.FeSquare(&t2, &t2)
+ }
+ edwards25519.FeMul(&t1, &t2, &t1) // 49..0
+ edwards25519.FeSquare(&t2, &t1) // 50..1
+ for i = 1; i < 50; i++ { // 99..50
+ edwards25519.FeSquare(&t2, &t2)
+ }
+ edwards25519.FeMul(&t2, &t2, &t1) // 99..0
+ edwards25519.FeSquare(&t3, &t2) // 100..1
+ for i = 1; i < 100; i++ { // 199..100
+ edwards25519.FeSquare(&t3, &t3)
+ }
+ edwards25519.FeMul(&t2, &t3, &t2) // 199..0
+ edwards25519.FeSquare(&t2, &t2) // 200..1
+ for i = 1; i < 50; i++ { // 249..50
+ edwards25519.FeSquare(&t2, &t2)
+ }
+ edwards25519.FeMul(&t1, &t2, &t1) // 249..0
+ edwards25519.FeSquare(&t1, &t1) // 250..1
+ edwards25519.FeSquare(&t1, &t1) // 251..2
+ edwards25519.FeMul(out, &t1, z) // 251..2,0
+}
+
+// chi calculates out = z^((p-1)/2). The result is either 1, 0, or -1 depending
+// on whether z is a non-zero square, zero, or a non-square.
+func chi(out, z *edwards25519.FieldElement) {
+ var t0, t1, t2, t3 edwards25519.FieldElement
+ var i int
+
+ edwards25519.FeSquare(&t0, z) // 2^1
+ edwards25519.FeMul(&t1, &t0, z) // 2^1 + 2^0
+ edwards25519.FeSquare(&t0, &t1) // 2^2 + 2^1
+ edwards25519.FeSquare(&t2, &t0) // 2^3 + 2^2
+ edwards25519.FeSquare(&t2, &t2) // 4,3
+ edwards25519.FeMul(&t2, &t2, &t0) // 4,3,2,1
+ edwards25519.FeMul(&t1, &t2, z) // 4..0
+ edwards25519.FeSquare(&t2, &t1) // 5..1
+ for i = 1; i < 5; i++ { // 9,8,7,6,5
+ edwards25519.FeSquare(&t2, &t2)
+ }
+ edwards25519.FeMul(&t1, &t2, &t1) // 9,8,7,6,5,4,3,2,1,0
+ edwards25519.FeSquare(&t2, &t1) // 10..1
+ for i = 1; i < 10; i++ { // 19..10
+ edwards25519.FeSquare(&t2, &t2)
+ }
+ edwards25519.FeMul(&t2, &t2, &t1) // 19..0
+ edwards25519.FeSquare(&t3, &t2) // 20..1
+ for i = 1; i < 20; i++ { // 39..20
+ edwards25519.FeSquare(&t3, &t3)
+ }
+ edwards25519.FeMul(&t2, &t3, &t2) // 39..0
+ edwards25519.FeSquare(&t2, &t2) // 40..1
+ for i = 1; i < 10; i++ { // 49..10
+ edwards25519.FeSquare(&t2, &t2)
+ }
+ edwards25519.FeMul(&t1, &t2, &t1) // 49..0
+ edwards25519.FeSquare(&t2, &t1) // 50..1
+ for i = 1; i < 50; i++ { // 99..50
+ edwards25519.FeSquare(&t2, &t2)
+ }
+ edwards25519.FeMul(&t2, &t2, &t1) // 99..0
+ edwards25519.FeSquare(&t3, &t2) // 100..1
+ for i = 1; i < 100; i++ { // 199..100
+ edwards25519.FeSquare(&t3, &t3)
+ }
+ edwards25519.FeMul(&t2, &t3, &t2) // 199..0
+ edwards25519.FeSquare(&t2, &t2) // 200..1
+ for i = 1; i < 50; i++ { // 249..50
+ edwards25519.FeSquare(&t2, &t2)
+ }
+ edwards25519.FeMul(&t1, &t2, &t1) // 249..0
+ edwards25519.FeSquare(&t1, &t1) // 250..1
+ for i = 1; i < 4; i++ { // 253..4
+ edwards25519.FeSquare(&t1, &t1)
+ }
+ edwards25519.FeMul(out, &t1, &t0) // 253..4,2,1
+}
+
+// RepresentativeToPublicKey converts a uniform representative value for a
+// curve25519 public key, as produced by ScalarBaseMult, to a curve25519 public
+// key.
+func RepresentativeToPublicKey(publicKey, representative *[32]byte) {
+ var rr2, v, e edwards25519.FieldElement
+ edwards25519.FeFromBytes(&rr2, representative)
+
+ edwards25519.FeSquare2(&rr2, &rr2)
+ rr2[0]++
+ edwards25519.FeInvert(&rr2, &rr2)
+ edwards25519.FeMul(&v, &edwards25519.A, &rr2)
+ edwards25519.FeNeg(&v, &v)
+
+ var v2, v3 edwards25519.FieldElement
+ edwards25519.FeSquare(&v2, &v)
+ edwards25519.FeMul(&v3, &v, &v2)
+ edwards25519.FeAdd(&e, &v3, &v)
+ edwards25519.FeMul(&v2, &v2, &edwards25519.A)
+ edwards25519.FeAdd(&e, &v2, &e)
+ chi(&e, &e)
+ var eBytes [32]byte
+ edwards25519.FeToBytes(&eBytes, &e)
+ // eBytes[1] is either 0 (for e = 1) or 0xff (for e = -1)
+ eIsMinus1 := int32(eBytes[1]) & 1
+ var negV edwards25519.FieldElement
+ edwards25519.FeNeg(&negV, &v)
+ edwards25519.FeCMove(&v, &negV, eIsMinus1)
+
+ edwards25519.FeZero(&v2)
+ edwards25519.FeCMove(&v2, &edwards25519.A, eIsMinus1)
+ edwards25519.FeSub(&v, &v, &v2)
+
+ edwards25519.FeToBytes(publicKey, &v)
+}
diff --git a/vendor/github.com/dchest/siphash/README.md b/vendor/github.com/dchest/siphash/README.md
new file mode 100644
index 0000000..a3645e1
--- /dev/null
+++ b/vendor/github.com/dchest/siphash/README.md
@@ -0,0 +1,69 @@
+SipHash (Go)
+============
+
+[](https://travis-ci.org/dchest/siphash)
+
+Go implementation of SipHash-2-4, a fast short-input PRF created by
+Jean-Philippe Aumasson and Daniel J. Bernstein (http://131002.net/siphash/).
+
+
+## Installation
+
+ $ go get github.com/dchest/siphash
+
+## Usage
+
+ import "github.com/dchest/siphash"
+
+There are two ways to use this package.
+The slower one is to use the standard hash.Hash64 interface:
+
+ h := siphash.New(key)
+ h.Write([]byte("Hello"))
+ sum := h.Sum(nil) // returns 8-byte []byte
+
+or
+
+ sum64 := h.Sum64() // returns uint64
+
+The faster one is to use Hash() function, which takes two uint64 parts of
+16-byte key and a byte slice, and returns uint64 hash:
+
+ sum64 := siphash.Hash(key0, key1, []byte("Hello"))
+
+The keys and output are little-endian.
+
+
+## Functions
+
+### func Hash(k0, k1 uint64, p []byte) uint64
+
+Hash returns the 64-bit SipHash-2-4 of the given byte slice with two
+64-bit parts of 128-bit key: k0 and k1.
+
+### func Hash128(k0, k1 uint64, p []byte) (uint64, uint64)
+
+Hash128 returns the 128-bit SipHash-2-4 of the given byte slice with two
+64-bit parts of 128-bit key: k0 and k1.
+
+Note that 128-bit SipHash is considered experimental by SipHash authors at this time.
+
+### func New(key []byte) hash.Hash64
+
+New returns a new hash.Hash64 computing SipHash-2-4 with 16-byte key.
+
+### func New128(key []byte) hash.Hash
+
+New128 returns a new hash.Hash computing SipHash-2-4 with 16-byte key and 16-byte output.
+
+Note that 16-byte output is considered experimental by SipHash authors at this time.
+
+
+## Public domain dedication
+
+Written by Dmitry Chestnykh and Damian Gryski.
+
+To the extent possible under law, the authors have dedicated all copyright
+and related and neighboring rights to this software to the public domain
+worldwide. This software is distributed without any warranty.
+http://creativecommons.org/publicdomain/zero/1.0/
diff --git a/vendor/github.com/dchest/siphash/blocks.go b/vendor/github.com/dchest/siphash/blocks.go
new file mode 100644
index 0000000..817b215
--- /dev/null
+++ b/vendor/github.com/dchest/siphash/blocks.go
@@ -0,0 +1,148 @@
+// +build !arm,!amd64 appengine gccgo
+
+package siphash
+
+func once(d *digest) {
+ blocks(d, d.x[:])
+}
+
+func finalize(d *digest) uint64 {
+ d0 := *d
+ once(&d0)
+
+ v0, v1, v2, v3 := d0.v0, d0.v1, d0.v2, d0.v3
+ v2 ^= 0xff
+
+ // Round 1.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 2.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 3.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 4.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ return v0 ^ v1 ^ v2 ^ v3
+}
+
+func blocks(d *digest, p []uint8) {
+ v0, v1, v2, v3 := d.v0, d.v1, d.v2, d.v3
+
+ for len(p) >= BlockSize {
+ m := uint64(p[0]) | uint64(p[1])<<8 | uint64(p[2])<<16 | uint64(p[3])<<24 |
+ uint64(p[4])<<32 | uint64(p[5])<<40 | uint64(p[6])<<48 | uint64(p[7])<<56
+
+ v3 ^= m
+
+ // Round 1.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 2.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ v0 ^= m
+
+ p = p[BlockSize:]
+ }
+
+ d.v0, d.v1, d.v2, d.v3 = v0, v1, v2, v3
+}
diff --git a/vendor/github.com/dchest/siphash/blocks_amd64.s b/vendor/github.com/dchest/siphash/blocks_amd64.s
new file mode 100644
index 0000000..2d4816f
--- /dev/null
+++ b/vendor/github.com/dchest/siphash/blocks_amd64.s
@@ -0,0 +1,86 @@
+// +build amd64,!appengine,!gccgo
+
+#define ROUND(v0, v1, v2, v3) \
+ ADDQ v1, v0; \
+ RORQ $51, v1; \
+ ADDQ v3, v2; \
+ XORQ v0, v1; \
+ RORQ $48, v3; \
+ RORQ $32, v0; \
+ XORQ v2, v3; \
+ ADDQ v1, v2; \
+ ADDQ v3, v0; \
+ RORQ $43, v3; \
+ RORQ $47, v1; \
+ XORQ v0, v3; \
+ XORQ v2, v1; \
+ RORQ $32, v2
+
+// blocks(d *digest, data []uint8)
+TEXT ·blocks(SB),4,$0-32
+ MOVQ d+0(FP), BX
+ MOVQ 0(BX), R9 // R9 = v0
+ MOVQ 8(BX), R10 // R10 = v1
+ MOVQ 16(BX), R11 // R11 = v2
+ MOVQ 24(BX), R12 // R12 = v3
+ MOVQ p_base+8(FP), DI // DI = *uint64
+ MOVQ p_len+16(FP), SI // SI = nblocks
+ XORL DX, DX // DX = index (0)
+ SHRQ $3, SI // SI /= 8
+body:
+ CMPQ DX, SI
+ JGE end
+ MOVQ 0(DI)(DX*8), CX // CX = m
+ XORQ CX, R12
+ ROUND(R9, R10, R11, R12)
+ ROUND(R9, R10, R11, R12)
+ XORQ CX, R9
+ ADDQ $1, DX
+ JMP body
+end:
+ MOVQ R9, 0(BX)
+ MOVQ R10, 8(BX)
+ MOVQ R11, 16(BX)
+ MOVQ R12, 24(BX)
+ RET
+
+// once(d *digest)
+TEXT ·once(SB),4,$0-8
+ MOVQ d+0(FP), BX
+ MOVQ 0(BX), R9 // R9 = v0
+ MOVQ 8(BX), R10 // R10 = v1
+ MOVQ 16(BX), R11 // R11 = v2
+ MOVQ 24(BX), R12 // R12 = v3
+ MOVQ 48(BX), CX // CX = d.x[:]
+ XORQ CX, R12
+ ROUND(R9, R10, R11, R12)
+ ROUND(R9, R10, R11, R12)
+ XORQ CX, R9
+ MOVQ R9, 0(BX)
+ MOVQ R10, 8(BX)
+ MOVQ R11, 16(BX)
+ MOVQ R12, 24(BX)
+ RET
+
+// finalize(d *digest) uint64
+TEXT ·finalize(SB),4,$0-16
+ MOVQ d+0(FP), BX
+ MOVQ 0(BX), R9 // R9 = v0
+ MOVQ 8(BX), R10 // R10 = v1
+ MOVQ 16(BX), R11 // R11 = v2
+ MOVQ 24(BX), R12 // R12 = v3
+ MOVQ 48(BX), CX // CX = d.x[:]
+ XORQ CX, R12
+ ROUND(R9, R10, R11, R12)
+ ROUND(R9, R10, R11, R12)
+ XORQ CX, R9
+ NOTB R11
+ ROUND(R9, R10, R11, R12)
+ ROUND(R9, R10, R11, R12)
+ ROUND(R9, R10, R11, R12)
+ ROUND(R9, R10, R11, R12)
+ XORQ R12, R11
+ XORQ R10, R9
+ XORQ R11, R9
+ MOVQ R9, ret+8(FP)
+ RET
diff --git a/vendor/github.com/dchest/siphash/blocks_arm.s b/vendor/github.com/dchest/siphash/blocks_arm.s
new file mode 100644
index 0000000..42dcd23
--- /dev/null
+++ b/vendor/github.com/dchest/siphash/blocks_arm.s
@@ -0,0 +1,144 @@
+#include "textflag.h"
+#define R10 g
+#define ROUND()\
+ ADD.S R2,R0,R0;\
+ ADC R3,R1,R1;\
+ EOR R2<<13,R0,R8;\
+ EOR R3>>19,R8,R8;\
+ EOR R2>>19,R1,R11;\
+ EOR R3<<13,R11,R11;\
+ ADD.S R6,R4,R4;\
+ ADC R7,R5,R5;\
+ EOR R6<<16,R4,R2;\
+ EOR R7>>16,R2,R2;\
+ EOR R6>>16,R5,R3;\
+ EOR R7<<16,R3,R3;\
+ ADD.S R2,R1,R1;\
+ ADC R3,R0,R0;\
+ EOR R2<<21,R1,R6;\
+ EOR R3>>11,R6,R6;\
+ EOR R2>>11,R0,R7;\
+ EOR R3<<21,R7,R7;\
+ ADD.S R8,R4,R4;\
+ ADC R11,R5,R5;\
+ EOR R8<<17,R4,R2;\
+ EOR R11>>15,R2,R2;\
+ EOR R8>>15,R5,R3;\
+ EOR R11<<17,R3,R3;\
+ ADD.S R2,R1,R1;\
+ ADC R3,R0,R0;\
+ EOR R2<<13,R1,R8;\
+ EOR R3>>19,R8,R8;\
+ EOR R2>>19,R0,R11;\
+ EOR R3<<13,R11,R11;\
+ ADD.S R6,R5,R5;\
+ ADC R7,R4,R4;\
+ EOR R6<<16,R5,R2;\
+ EOR R7>>16,R2,R2;\
+ EOR R6>>16,R4,R3;\
+ EOR R7<<16,R3,R3;\
+ ADD.S R2,R0,R0;\
+ ADC R3,R1,R1;\
+ EOR R2<<21,R0,R6;\
+ EOR R3>>11,R6,R6;\
+ EOR R2>>11,R1,R7;\
+ EOR R3<<21,R7,R7;\
+ ADD.S R8,R5,R5;\
+ ADC R11,R4,R4;\
+ EOR R8<<17,R5,R2;\
+ EOR R11>>15,R2,R2;\
+ EOR R8>>15,R4,R3;\
+ EOR R11<<17,R3,R3;\
+
+// once(d *digest)
+TEXT ·once(SB),NOSPLIT,$4-4
+ MOVW d+0(FP),R8
+ MOVM.IA (R8),[R0,R1,R2,R3,R4,R5,R6,R7]
+ MOVW 48(R8),R12
+ MOVW 52(R8),R14
+ EOR R12,R6,R6
+ EOR R14,R7,R7
+ ROUND()
+ EOR R12,R0,R0
+ EOR R14,R1,R1
+ MOVW d+0(FP),R8
+ MOVM.IA [R0,R1,R2,R3,R4,R5,R6,R7],(R8)
+ RET
+
+// finalize(d *digest) uint64
+TEXT ·finalize(SB),NOSPLIT,$4-12
+ MOVW d+0(FP),R8
+ MOVM.IA (R8),[R0,R1,R2,R3,R4,R5,R6,R7]
+ MOVW 48(R8),R12
+ MOVW 52(R8),R14
+ EOR R12,R6,R6
+ EOR R14,R7,R7
+ ROUND()
+ EOR R12,R0,R0
+ EOR R14,R1,R1
+ EOR $255,R4
+ ROUND()
+ ROUND()
+ EOR R2,R0,R0
+ EOR R3,R1,R1
+ EOR R6,R4,R4
+ EOR R7,R5,R5
+ EOR R4,R0,R0
+ EOR R5,R1,R1
+ MOVW R0,ret_lo+4(FP)
+ MOVW R1,ret_hi+8(FP)
+ RET
+
+// blocks(d *digest, data []uint8)
+TEXT ·blocks(SB),NOSPLIT,$8-16
+ MOVW R10,sav-8(SP)
+ MOVW d+0(FP),R8
+ MOVM.IA (R8),[R0,R1,R2,R3,R4,R5,R6,R7]
+ MOVW p+4(FP),R10
+ MOVW p_len+8(FP),R11
+ ADD R10,R11,R11
+ MOVW R11,endp-4(SP)
+ AND.S $3,R10,R8
+ BNE blocksunaligned
+blocksloop:
+ MOVM.IA.W (R10),[R12,R14]
+ EOR R12,R6,R6
+ EOR R14,R7,R7
+ ROUND()
+ EOR R12,R0,R0
+ EOR R14,R1,R1
+ MOVW endp-4(SP),R11
+ CMP R11,R10
+ BLO blocksloop
+ MOVW d+0(FP),R8
+ MOVM.IA [R0,R1,R2,R3,R4,R5,R6,R7],(R8)
+ MOVW sav-8(SP),R10
+ RET
+blocksunaligned:
+ MOVB (R10),R12
+ MOVB 1(R10),R11
+ ORR R11<<8,R12,R12
+ MOVB 2(R10),R11
+ ORR R11<<16,R12,R12
+ MOVB 3(R10),R11
+ ORR R11<<24,R12,R12
+ MOVB 4(R10),R14
+ MOVB 5(R10),R11
+ ORR R11<<8,R14,R14
+ MOVB 6(R10),R11
+ ORR R11<<16,R14,R14
+ MOVB 7(R10),R11
+ ORR R11<<24,R14,R14
+ ADD $8,R10,R10
+ EOR R12,R6,R6
+ EOR R14,R7,R7
+ ROUND()
+ EOR R12,R0,R0
+ EOR R14,R1,R1
+ MOVW endp-4(SP),R11
+ CMP R11,R10
+ BLO blocksunaligned
+ MOVW d+0(FP),R8
+ MOVM.IA [R0,R1,R2,R3,R4,R5,R6,R7],(R8)
+ MOVW sav-8(SP),R10
+ RET
diff --git a/vendor/github.com/dchest/siphash/hash.go b/vendor/github.com/dchest/siphash/hash.go
new file mode 100644
index 0000000..0de28d0
--- /dev/null
+++ b/vendor/github.com/dchest/siphash/hash.go
@@ -0,0 +1,216 @@
+// +build !arm,!amd64 appengine gccgo
+
+// Written in 2012 by Dmitry Chestnykh.
+//
+// To the extent possible under law, the author have dedicated all copyright
+// and related and neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+// http://creativecommons.org/publicdomain/zero/1.0/
+
+package siphash
+
+// Hash returns the 64-bit SipHash-2-4 of the given byte slice with two 64-bit
+// parts of 128-bit key: k0 and k1.
+func Hash(k0, k1 uint64, p []byte) uint64 {
+ // Initialization.
+ v0 := k0 ^ 0x736f6d6570736575
+ v1 := k1 ^ 0x646f72616e646f6d
+ v2 := k0 ^ 0x6c7967656e657261
+ v3 := k1 ^ 0x7465646279746573
+ t := uint64(len(p)) << 56
+
+ // Compression.
+ for len(p) >= BlockSize {
+ m := uint64(p[0]) | uint64(p[1])<<8 | uint64(p[2])<<16 | uint64(p[3])<<24 |
+ uint64(p[4])<<32 | uint64(p[5])<<40 | uint64(p[6])<<48 | uint64(p[7])<<56
+ v3 ^= m
+
+ // Round 1.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 2.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ v0 ^= m
+ p = p[BlockSize:]
+ }
+
+ // Compress last block.
+ switch len(p) {
+ case 7:
+ t |= uint64(p[6]) << 48
+ fallthrough
+ case 6:
+ t |= uint64(p[5]) << 40
+ fallthrough
+ case 5:
+ t |= uint64(p[4]) << 32
+ fallthrough
+ case 4:
+ t |= uint64(p[3]) << 24
+ fallthrough
+ case 3:
+ t |= uint64(p[2]) << 16
+ fallthrough
+ case 2:
+ t |= uint64(p[1]) << 8
+ fallthrough
+ case 1:
+ t |= uint64(p[0])
+ }
+
+ v3 ^= t
+
+ // Round 1.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 2.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ v0 ^= t
+
+ // Finalization.
+ v2 ^= 0xff
+
+ // Round 1.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 2.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 3.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 4.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ return v0 ^ v1 ^ v2 ^ v3
+}
diff --git a/vendor/github.com/dchest/siphash/hash128.go b/vendor/github.com/dchest/siphash/hash128.go
new file mode 100644
index 0000000..634ce57
--- /dev/null
+++ b/vendor/github.com/dchest/siphash/hash128.go
@@ -0,0 +1,302 @@
+// +build !arm,!amd64 appengine gccgo
+// Written in 2012 by Dmitry Chestnykh.
+// Modifications 2014 for 128-bit hash function by Damian Gryski.
+//
+// To the extent possible under law, the authors have dedicated all copyright
+// and related and neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+// http://creativecommons.org/publicdomain/zero/1.0/
+
+package siphash
+
+// Hash returns the 128-bit SipHash-2-4 of the given byte slice with two 64-bit
+// parts of 128-bit key: k0 and k1.
+//
+// Note that 128-bit SipHash is considered experimental by SipHash authors at this time.
+func Hash128(k0, k1 uint64, p []byte) (uint64, uint64) {
+ // Initialization.
+ v0 := k0 ^ 0x736f6d6570736575
+ v1 := k1 ^ 0x646f72616e646f6d
+ v2 := k0 ^ 0x6c7967656e657261
+ v3 := k1 ^ 0x7465646279746573
+ t := uint64(len(p)) << 56
+
+ v1 ^= 0xee
+
+ // Compression.
+ for len(p) >= BlockSize {
+ m := uint64(p[0]) | uint64(p[1])<<8 | uint64(p[2])<<16 | uint64(p[3])<<24 |
+ uint64(p[4])<<32 | uint64(p[5])<<40 | uint64(p[6])<<48 | uint64(p[7])<<56
+ v3 ^= m
+
+ // Round 1.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 2.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ v0 ^= m
+ p = p[BlockSize:]
+ }
+
+ // Compress last block.
+ switch len(p) {
+ case 7:
+ t |= uint64(p[6]) << 48
+ fallthrough
+ case 6:
+ t |= uint64(p[5]) << 40
+ fallthrough
+ case 5:
+ t |= uint64(p[4]) << 32
+ fallthrough
+ case 4:
+ t |= uint64(p[3]) << 24
+ fallthrough
+ case 3:
+ t |= uint64(p[2]) << 16
+ fallthrough
+ case 2:
+ t |= uint64(p[1]) << 8
+ fallthrough
+ case 1:
+ t |= uint64(p[0])
+ }
+
+ v3 ^= t
+
+ // Round 1.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 2.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ v0 ^= t
+
+ // Finalization.
+ v2 ^= 0xee
+
+ // Round 1.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 2.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 3.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 4.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ r0 := v0 ^ v1 ^ v2 ^ v3
+
+ v1 ^= 0xdd
+
+ // Round 1.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 2.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 3.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 4.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ r1 := v0 ^ v1 ^ v2 ^ v3
+
+ return r0, r1
+}
diff --git a/vendor/github.com/dchest/siphash/hash128_amd64.s b/vendor/github.com/dchest/siphash/hash128_amd64.s
new file mode 100644
index 0000000..86605cc
--- /dev/null
+++ b/vendor/github.com/dchest/siphash/hash128_amd64.s
@@ -0,0 +1,292 @@
+// +build amd64,!appengine,!gccgo
+
+// This is a translation of the gcc output of FloodyBerry's pure-C public
+// domain siphash implementation at https://github.com/floodyberry/siphash
+
+// This assembly code has been modified from the 64-bit output to the experiment 128-bit output.
+
+// SI = v0
+// AX = v1
+// CX = v2
+// DX = v3
+
+// func Hash128(k0, k1 uint64, b []byte) (r0 uint64, r1 uint64)
+TEXT ·Hash128(SB),4,$0-56
+ MOVQ k0+0(FP),CX
+ MOVQ $0x736F6D6570736575,R9
+ MOVQ k1+8(FP),DI
+ MOVQ $0x6C7967656E657261,BX
+ MOVQ $0x646F72616E646F6D,AX
+ MOVQ b_len+24(FP),DX
+ XORQ $0xEE,AX
+ MOVQ DX,R11
+ MOVQ DX,R10
+ XORQ CX,R9
+ XORQ CX,BX
+ MOVQ $0x7465646279746573,CX
+ XORQ DI,AX
+ XORQ DI,CX
+ SHLQ $0x38,R11
+ XORQ DI,DI
+ MOVQ b_base+16(FP),SI
+ ANDQ $0xFFFFFFFFFFFFFFF8,R10
+ JE afterLoop
+ XCHGQ AX,AX
+loopBody:
+ MOVQ 0(SI)(DI*1),R8
+ ADDQ AX,R9
+ RORQ $0x33,AX
+ XORQ R9,AX
+ RORQ $0x20,R9
+ ADDQ $0x8,DI
+ XORQ R8,CX
+ ADDQ CX,BX
+ RORQ $0x30,CX
+ XORQ BX,CX
+ ADDQ AX,BX
+ RORQ $0x2F,AX
+ ADDQ CX,R9
+ RORQ $0x2B,CX
+ XORQ BX,AX
+ XORQ R9,CX
+ RORQ $0x20,BX
+ ADDQ AX,R9
+ ADDQ CX,BX
+ RORQ $0x33,AX
+ RORQ $0x30,CX
+ XORQ R9,AX
+ XORQ BX,CX
+ RORQ $0x20,R9
+ ADDQ AX,BX
+ ADDQ CX,R9
+ RORQ $0x2F,AX
+ RORQ $0x2B,CX
+ XORQ BX,AX
+ RORQ $0x20,BX
+ XORQ R9,CX
+ XORQ R8,R9
+ CMPQ R10,DI
+ JA loopBody
+afterLoop:
+ SUBQ R10,DX
+
+ CMPQ DX,$0x7
+ JA afterSwitch
+
+ // no support for jump tables
+
+ CMPQ DX,$0x7
+ JE sw7
+
+ CMPQ DX,$0x6
+ JE sw6
+
+ CMPQ DX,$0x5
+ JE sw5
+
+ CMPQ DX,$0x4
+ JE sw4
+
+ CMPQ DX,$0x3
+ JE sw3
+
+ CMPQ DX,$0x2
+ JE sw2
+
+ CMPQ DX,$0x1
+ JE sw1
+
+ JMP afterSwitch
+
+sw7: MOVBQZX 6(SI)(DI*1),DX
+ SHLQ $0x30,DX
+ ORQ DX,R11
+sw6: MOVBQZX 0x5(SI)(DI*1),DX
+ SHLQ $0x28,DX
+ ORQ DX,R11
+sw5: MOVBQZX 0x4(SI)(DI*1),DX
+ SHLQ $0x20,DX
+ ORQ DX,R11
+sw4: MOVBQZX 0x3(SI)(DI*1),DX
+ SHLQ $0x18,DX
+ ORQ DX,R11
+sw3: MOVBQZX 0x2(SI)(DI*1),DX
+ SHLQ $0x10,DX
+ ORQ DX,R11
+sw2: MOVBQZX 0x1(SI)(DI*1),DX
+ SHLQ $0x8,DX
+ ORQ DX,R11
+sw1: MOVBQZX 0(SI)(DI*1),DX
+ ORQ DX,R11
+afterSwitch:
+ LEAQ (AX)(R9*1),SI
+ XORQ R11,CX
+ RORQ $0x33,AX
+ ADDQ CX,BX
+ MOVQ CX,DX
+ XORQ SI,AX
+ RORQ $0x30,DX
+ RORQ $0x20,SI
+ LEAQ 0(BX)(AX*1),CX
+ XORQ BX,DX
+ RORQ $0x2F,AX
+ ADDQ DX,SI
+ RORQ $0x2B,DX
+ XORQ CX,AX
+ XORQ SI,DX
+ RORQ $0x20,CX
+ ADDQ AX,SI
+ RORQ $0x33,AX
+ ADDQ DX,CX
+ XORQ SI,AX
+ RORQ $0x30,DX
+ RORQ $0x20,SI
+ XORQ CX,DX
+ ADDQ AX,CX
+ RORQ $0x2F,AX
+ ADDQ DX,SI
+ XORQ CX,AX
+ RORQ $0x2B,DX
+ RORQ $0x20,CX
+ XORQ SI,DX
+ XORQ R11,SI
+ XORB $0xEE,CL
+ ADDQ AX,SI
+ RORQ $0x33,AX
+ ADDQ DX,CX
+ RORQ $0x30,DX
+ XORQ SI,AX
+ XORQ CX,DX
+ RORQ $0x20,SI
+ ADDQ AX,CX
+ ADDQ DX,SI
+ RORQ $0x2F,AX
+ RORQ $0x2B,DX
+ XORQ CX,AX
+ XORQ SI,DX
+ RORQ $0x20,CX
+ ADDQ AX,SI
+ ADDQ DX,CX
+ RORQ $0x33,AX
+ RORQ $0x30,DX
+ XORQ SI,AX
+ RORQ $0x20,SI
+ XORQ CX,DX
+ ADDQ AX,CX
+ RORQ $0x2F,AX
+ ADDQ DX,SI
+ RORQ $0x2B,DX
+ XORQ CX,AX
+ XORQ SI,DX
+ RORQ $0x20,CX
+ ADDQ AX,SI
+ ADDQ DX,CX
+ RORQ $0x33,AX
+ RORQ $0x30,DX
+ XORQ CX,DX
+ XORQ SI,AX
+ RORQ $0x20,SI
+ ADDQ DX,SI
+ ADDQ AX,CX
+ RORQ $0x2F,AX
+ XORQ CX,AX
+ RORQ $0x2B,DX
+ RORQ $0x20,CX
+ XORQ SI,DX
+
+ // gcc optimized the tail end of this function differently. However,
+ // we need to preserve out registers to carry out the second stage of
+ // the finalization. This is a duplicate of an earlier finalization
+ // round.
+
+ ADDQ AX,SI
+ RORQ $0x33,AX
+ ADDQ DX,CX
+ RORQ $0x30,DX
+ XORQ SI,AX
+ XORQ CX,DX
+ RORQ $0x20,SI
+ ADDQ AX,CX
+ ADDQ DX,SI
+ RORQ $0x2F,AX
+ RORQ $0x2B,DX
+ XORQ CX,AX
+ XORQ SI,DX
+ RORQ $0x20,CX
+
+ // Stuff the result into BX instead of AX as gcc had done
+
+ MOVQ SI,BX
+ XORQ AX,BX
+ XORQ DX,BX
+ XORQ CX,BX
+ MOVQ BX,ret+40(FP)
+
+ // Start the second finalization round
+
+ XORB $0xDD,AL
+ ADDQ AX,SI
+ RORQ $0x33,AX
+ ADDQ DX,CX
+ RORQ $0x30,DX
+ XORQ SI,AX
+ XORQ CX,DX
+ RORQ $0x20,SI
+ ADDQ AX,CX
+ ADDQ DX,SI
+ RORQ $0x2F,AX
+ RORQ $0x2B,DX
+ XORQ CX,AX
+ XORQ SI,DX
+ RORQ $0x20,CX
+ ADDQ AX,SI
+ ADDQ DX,CX
+ RORQ $0x33,AX
+ RORQ $0x30,DX
+ XORQ SI,AX
+ RORQ $0x20,SI
+ XORQ CX,DX
+ ADDQ AX,CX
+ RORQ $0x2F,AX
+ ADDQ DX,SI
+ RORQ $0x2B,DX
+ XORQ CX,AX
+ XORQ SI,DX
+ RORQ $0x20,CX
+ ADDQ AX,SI
+ ADDQ DX,CX
+ RORQ $0x33,AX
+ RORQ $0x30,DX
+ XORQ CX,DX
+ XORQ SI,AX
+ RORQ $0x20,SI
+ ADDQ DX,SI
+ ADDQ AX,CX
+ RORQ $0x2F,AX
+ XORQ CX,AX
+ RORQ $0x2B,DX
+ RORQ $0x20,CX
+ XORQ SI,DX
+
+ ADDQ AX,SI
+ RORQ $0x33,AX
+ ADDQ DX,CX
+ RORQ $0x30,DX
+ XORQ SI,AX
+ XORQ CX,DX
+ RORQ $0x20,SI
+ ADDQ AX,CX
+ ADDQ DX,SI
+ RORQ $0x2F,AX
+ RORQ $0x2B,DX
+ XORQ CX,AX
+ XORQ SI,DX
+ RORQ $0x20,CX
+
+ MOVQ SI,BX
+ XORQ AX,BX
+ XORQ DX,BX
+ XORQ CX,BX
+ MOVQ BX,ret1+48(FP)
+
+ RET
diff --git a/vendor/github.com/dchest/siphash/hash128_arm.s b/vendor/github.com/dchest/siphash/hash128_arm.s
new file mode 100644
index 0000000..eca3529
--- /dev/null
+++ b/vendor/github.com/dchest/siphash/hash128_arm.s
@@ -0,0 +1,169 @@
+#include "textflag.h"
+#define R10 g
+#define ROUND()\
+ ADD.S R2,R0,R0;\
+ ADC R3,R1,R1;\
+ EOR R2<<13,R0,R8;\
+ EOR R3>>19,R8,R8;\
+ EOR R2>>19,R1,R11;\
+ EOR R3<<13,R11,R11;\
+ ADD.S R6,R4,R4;\
+ ADC R7,R5,R5;\
+ EOR R6<<16,R4,R2;\
+ EOR R7>>16,R2,R2;\
+ EOR R6>>16,R5,R3;\
+ EOR R7<<16,R3,R3;\
+ ADD.S R2,R1,R1;\
+ ADC R3,R0,R0;\
+ EOR R2<<21,R1,R6;\
+ EOR R3>>11,R6,R6;\
+ EOR R2>>11,R0,R7;\
+ EOR R3<<21,R7,R7;\
+ ADD.S R8,R4,R4;\
+ ADC R11,R5,R5;\
+ EOR R8<<17,R4,R2;\
+ EOR R11>>15,R2,R2;\
+ EOR R8>>15,R5,R3;\
+ EOR R11<<17,R3,R3;\
+ ADD.S R2,R1,R1;\
+ ADC R3,R0,R0;\
+ EOR R2<<13,R1,R8;\
+ EOR R3>>19,R8,R8;\
+ EOR R2>>19,R0,R11;\
+ EOR R3<<13,R11,R11;\
+ ADD.S R6,R5,R5;\
+ ADC R7,R4,R4;\
+ EOR R6<<16,R5,R2;\
+ EOR R7>>16,R2,R2;\
+ EOR R6>>16,R4,R3;\
+ EOR R7<<16,R3,R3;\
+ ADD.S R2,R0,R0;\
+ ADC R3,R1,R1;\
+ EOR R2<<21,R0,R6;\
+ EOR R3>>11,R6,R6;\
+ EOR R2>>11,R1,R7;\
+ EOR R3<<21,R7,R7;\
+ ADD.S R8,R5,R5;\
+ ADC R11,R4,R4;\
+ EOR R8<<17,R5,R2;\
+ EOR R11>>15,R2,R2;\
+ EOR R8>>15,R4,R3;\
+ EOR R11<<17,R3,R3;\
+
+// Hash128(k0, k1 uint64, b []byte) (uint64, uint64)
+TEXT ·Hash128(SB),NOSPLIT,$8-44
+ MOVW R10,sav-8(SP)
+ MOVW k0_lo+0(FP),R12
+ MOVW k0_hi+4(FP),R14
+ MOVW $0x70736575,R0
+ MOVW $0x736f6d65,R1
+ MOVW $0x6e657261,R4
+ MOVW $0x6c796765,R5
+ EOR R12,R0,R0
+ EOR R14,R1,R1
+ EOR R12,R4,R4
+ EOR R14,R5,R5
+ MOVW k1_lo+8(FP),R12
+ MOVW k1_hi+12(FP),R14
+ MOVW $0x6e646f83,R2
+ MOVW $0x646f7261,R3
+ MOVW $0x79746573,R6
+ MOVW $0x74656462,R7
+ EOR R12,R2,R2
+ EOR R14,R3,R3
+ EOR R12,R6,R6
+ EOR R14,R7,R7
+ MOVW b+16(FP),R10
+ MOVW b_len+20(FP),R11
+ ADD R10,R11,R11
+ MOVW R11,endb-4(SP)
+hashloop128:
+ MOVW endb-4(SP),R11
+ SUB R10,R11,R11
+ SUB.S $8,R11
+ BLO hashend128
+ MOVM.IA.W (R10),[R12,R14]
+ EOR R12,R6,R6
+ EOR R14,R7,R7
+ ROUND()
+ EOR R12,R0,R0
+ EOR R14,R1,R1
+ B hashloop128
+hashloop128unaligned:
+ MOVW endb-4(SP),R11
+ SUB R10,R11,R11
+ SUB.S $8,R11
+ BLO hashend128
+ MOVB (R10),R12
+ MOVB 1(R10),R11
+ ORR R11<<8,R12,R12
+ MOVB 2(R10),R11
+ ORR R11<<16,R12,R12
+ MOVB 3(R10),R11
+ ORR R11<<24,R12,R12
+ MOVB 4(R10),R14
+ MOVB 5(R10),R11
+ ORR R11<<8,R14,R14
+ MOVB 6(R10),R11
+ ORR R11<<16,R14,R14
+ MOVB 7(R10),R11
+ ORR R11<<24,R14,R14
+ ADD $8,R10,R10
+ EOR R12,R6,R6
+ EOR R14,R7,R7
+ ROUND()
+ EOR R12,R0,R0
+ EOR R14,R1,R1
+ B hashloop128unaligned
+hashend128:
+ MOVW $0x0,R12
+ MOVW $0x0,R14
+ RSB $0,R11,R11
+ AND.S $7,R11
+ BEQ hashlast128
+ MOVW (R10),R12
+ SLL $3,R11
+ AND $63,R11
+ SUB.S $32,R11,R11
+ BEQ hashlast128
+ BLO hashhi128
+ MOVW R12<>R11,R12
+ B hashlast128
+hashhi128:
+ ADD $32,R11
+ MOVW 4(R10),R14
+ MOVW R14<>R11,R14
+hashlast128:
+ MOVW b_len+20(FP),R11
+ ORR R11<<24,R14,R14
+ EOR R12,R6,R6
+ EOR R14,R7,R7
+ ROUND()
+ EOR R12,R0,R0
+ EOR R14,R1,R1
+ EOR $238,R4
+ ROUND()
+ ROUND()
+ EOR R0,R2,R12
+ EOR R1,R3,R14
+ EOR R4,R12,R12
+ EOR R5,R14,R14
+ EOR R6,R12,R12
+ EOR R7,R14,R14
+ MOVW R12,ret_lo+28(FP)
+ MOVW R14,ret_hi+32(FP)
+ EOR $221,R2
+ ROUND()
+ ROUND()
+ EOR R0,R2,R12
+ EOR R1,R3,R14
+ EOR R4,R12,R12
+ EOR R5,R14,R14
+ EOR R6,R12,R12
+ EOR R7,R14,R14
+ MOVW R12,unnamed_lo+36(FP)
+ MOVW R14,unnamed_hi+40(FP)
+ MOVW sav-8(SP),R10
+ RET
diff --git a/vendor/github.com/dchest/siphash/hash_amd64.s b/vendor/github.com/dchest/siphash/hash_amd64.s
new file mode 100644
index 0000000..0ca1631
--- /dev/null
+++ b/vendor/github.com/dchest/siphash/hash_amd64.s
@@ -0,0 +1,201 @@
+// +build amd64,!appengine,!gccgo
+
+// This is a translation of the gcc output of FloodyBerry's pure-C public
+// domain siphash implementation at https://github.com/floodyberry/siphash
+// func Hash(k0, k1 uint64, b []byte) uint64
+TEXT ·Hash(SB),4,$0-48
+ MOVQ k0+0(FP),CX
+ MOVQ $0x736F6D6570736575,R9
+ MOVQ k1+8(FP),DI
+ MOVQ $0x6C7967656E657261,BX
+ MOVQ $0x646F72616E646F6D,AX
+ MOVQ b_len+24(FP),DX
+ MOVQ DX,R11
+ MOVQ DX,R10
+ XORQ CX,R9
+ XORQ CX,BX
+ MOVQ $0x7465646279746573,CX
+ XORQ DI,AX
+ XORQ DI,CX
+ SHLQ $0x38,R11
+ XORQ DI,DI
+ MOVQ b_base+16(FP),SI
+ ANDQ $0xFFFFFFFFFFFFFFF8,R10
+ JE afterLoop
+ XCHGQ AX,AX
+loopBody:
+ MOVQ 0(SI)(DI*1),R8
+ ADDQ AX,R9
+ RORQ $0x33,AX
+ XORQ R9,AX
+ RORQ $0x20,R9
+ ADDQ $0x8,DI
+ XORQ R8,CX
+ ADDQ CX,BX
+ RORQ $0x30,CX
+ XORQ BX,CX
+ ADDQ AX,BX
+ RORQ $0x2F,AX
+ ADDQ CX,R9
+ RORQ $0x2B,CX
+ XORQ BX,AX
+ XORQ R9,CX
+ RORQ $0x20,BX
+ ADDQ AX,R9
+ ADDQ CX,BX
+ RORQ $0x33,AX
+ RORQ $0x30,CX
+ XORQ R9,AX
+ XORQ BX,CX
+ RORQ $0x20,R9
+ ADDQ AX,BX
+ ADDQ CX,R9
+ RORQ $0x2F,AX
+ RORQ $0x2B,CX
+ XORQ BX,AX
+ RORQ $0x20,BX
+ XORQ R9,CX
+ XORQ R8,R9
+ CMPQ R10,DI
+ JA loopBody
+afterLoop:
+ SUBQ R10,DX
+
+ CMPQ DX,$0x7
+ JA afterSwitch
+
+ // no support for jump tables
+
+ CMPQ DX,$0x7
+ JE sw7
+
+ CMPQ DX,$0x6
+ JE sw6
+
+ CMPQ DX,$0x5
+ JE sw5
+
+ CMPQ DX,$0x4
+ JE sw4
+
+ CMPQ DX,$0x3
+ JE sw3
+
+ CMPQ DX,$0x2
+ JE sw2
+
+ CMPQ DX,$0x1
+ JE sw1
+
+ JMP afterSwitch
+
+sw7: MOVBQZX 6(SI)(DI*1),DX
+ SHLQ $0x30,DX
+ ORQ DX,R11
+sw6: MOVBQZX 0x5(SI)(DI*1),DX
+ SHLQ $0x28,DX
+ ORQ DX,R11
+sw5: MOVBQZX 0x4(SI)(DI*1),DX
+ SHLQ $0x20,DX
+ ORQ DX,R11
+sw4: MOVBQZX 0x3(SI)(DI*1),DX
+ SHLQ $0x18,DX
+ ORQ DX,R11
+sw3: MOVBQZX 0x2(SI)(DI*1),DX
+ SHLQ $0x10,DX
+ ORQ DX,R11
+sw2: MOVBQZX 0x1(SI)(DI*1),DX
+ SHLQ $0x8,DX
+ ORQ DX,R11
+sw1: MOVBQZX 0(SI)(DI*1),DX
+ ORQ DX,R11
+afterSwitch:
+ LEAQ (AX)(R9*1),SI
+ XORQ R11,CX
+ RORQ $0x33,AX
+ ADDQ CX,BX
+ MOVQ CX,DX
+ XORQ SI,AX
+ RORQ $0x30,DX
+ RORQ $0x20,SI
+ LEAQ 0(BX)(AX*1),CX
+ XORQ BX,DX
+ RORQ $0x2F,AX
+ ADDQ DX,SI
+ RORQ $0x2B,DX
+ XORQ CX,AX
+ XORQ SI,DX
+ RORQ $0x20,CX
+ ADDQ AX,SI
+ RORQ $0x33,AX
+ ADDQ DX,CX
+ XORQ SI,AX
+ RORQ $0x30,DX
+ RORQ $0x20,SI
+ XORQ CX,DX
+ ADDQ AX,CX
+ RORQ $0x2F,AX
+ ADDQ DX,SI
+ XORQ CX,AX
+ RORQ $0x2B,DX
+ RORQ $0x20,CX
+ XORQ SI,DX
+ XORQ R11,SI
+ XORB $0xFF,CL
+ ADDQ AX,SI
+ RORQ $0x33,AX
+ ADDQ DX,CX
+ RORQ $0x30,DX
+ XORQ SI,AX
+ XORQ CX,DX
+ RORQ $0x20,SI
+ ADDQ AX,CX
+ ADDQ DX,SI
+ RORQ $0x2F,AX
+ RORQ $0x2B,DX
+ XORQ CX,AX
+ XORQ SI,DX
+ RORQ $0x20,CX
+ ADDQ AX,SI
+ ADDQ DX,CX
+ RORQ $0x33,AX
+ RORQ $0x30,DX
+ XORQ SI,AX
+ RORQ $0x20,SI
+ XORQ CX,DX
+ ADDQ AX,CX
+ RORQ $0x2F,AX
+ ADDQ DX,SI
+ RORQ $0x2B,DX
+ XORQ CX,AX
+ XORQ SI,DX
+ RORQ $0x20,CX
+ ADDQ AX,SI
+ ADDQ DX,CX
+ RORQ $0x33,AX
+ RORQ $0x30,DX
+ XORQ CX,DX
+ XORQ SI,AX
+ RORQ $0x20,SI
+ ADDQ DX,SI
+ ADDQ AX,CX
+ RORQ $0x2F,AX
+ XORQ CX,AX
+ RORQ $0x2B,DX
+ RORQ $0x20,CX
+ XORQ SI,DX
+ ADDQ AX,SI
+ RORQ $0x33,AX
+ ADDQ DX,CX
+ XORQ SI,AX
+ RORQ $0x30,DX
+ XORQ CX,DX
+ ADDQ AX,CX
+ RORQ $0x2F,AX
+ XORQ CX,AX
+ RORQ $0x2B,DX
+ RORQ $0x20,CX
+ XORQ DX,AX
+ XORQ CX,AX
+ MOVQ AX,ret+40(FP)
+ RET
diff --git a/vendor/github.com/dchest/siphash/hash_arm.s b/vendor/github.com/dchest/siphash/hash_arm.s
new file mode 100644
index 0000000..ddad8f8
--- /dev/null
+++ b/vendor/github.com/dchest/siphash/hash_arm.s
@@ -0,0 +1,160 @@
+#include "textflag.h"
+#define R10 g
+#define ROUND()\
+ ADD.S R2,R0,R0;\
+ ADC R3,R1,R1;\
+ EOR R2<<13,R0,R8;\
+ EOR R3>>19,R8,R8;\
+ EOR R2>>19,R1,R11;\
+ EOR R3<<13,R11,R11;\
+ ADD.S R6,R4,R4;\
+ ADC R7,R5,R5;\
+ EOR R6<<16,R4,R2;\
+ EOR R7>>16,R2,R2;\
+ EOR R6>>16,R5,R3;\
+ EOR R7<<16,R3,R3;\
+ ADD.S R2,R1,R1;\
+ ADC R3,R0,R0;\
+ EOR R2<<21,R1,R6;\
+ EOR R3>>11,R6,R6;\
+ EOR R2>>11,R0,R7;\
+ EOR R3<<21,R7,R7;\
+ ADD.S R8,R4,R4;\
+ ADC R11,R5,R5;\
+ EOR R8<<17,R4,R2;\
+ EOR R11>>15,R2,R2;\
+ EOR R8>>15,R5,R3;\
+ EOR R11<<17,R3,R3;\
+ ADD.S R2,R1,R1;\
+ ADC R3,R0,R0;\
+ EOR R2<<13,R1,R8;\
+ EOR R3>>19,R8,R8;\
+ EOR R2>>19,R0,R11;\
+ EOR R3<<13,R11,R11;\
+ ADD.S R6,R5,R5;\
+ ADC R7,R4,R4;\
+ EOR R6<<16,R5,R2;\
+ EOR R7>>16,R2,R2;\
+ EOR R6>>16,R4,R3;\
+ EOR R7<<16,R3,R3;\
+ ADD.S R2,R0,R0;\
+ ADC R3,R1,R1;\
+ EOR R2<<21,R0,R6;\
+ EOR R3>>11,R6,R6;\
+ EOR R2>>11,R1,R7;\
+ EOR R3<<21,R7,R7;\
+ ADD.S R8,R5,R5;\
+ ADC R11,R4,R4;\
+ EOR R8<<17,R5,R2;\
+ EOR R11>>15,R2,R2;\
+ EOR R8>>15,R4,R3;\
+ EOR R11<<17,R3,R3;\
+
+// Hash(k0, k1 uint64, b []byte) uint64
+TEXT ·Hash(SB),NOSPLIT,$8-36
+ MOVW R10,sav-8(SP)
+ MOVW k0_lo+0(FP),R12
+ MOVW k0_hi+4(FP),R14
+ MOVW $0x70736575,R0
+ MOVW $0x736f6d65,R1
+ MOVW $0x6e657261,R4
+ MOVW $0x6c796765,R5
+ EOR R12,R0,R0
+ EOR R14,R1,R1
+ EOR R12,R4,R4
+ EOR R14,R5,R5
+ MOVW k1_lo+8(FP),R12
+ MOVW k1_hi+12(FP),R14
+ MOVW $0x6e646f6d,R2
+ MOVW $0x646f7261,R3
+ MOVW $0x79746573,R6
+ MOVW $0x74656462,R7
+ EOR R12,R2,R2
+ EOR R14,R3,R3
+ EOR R12,R6,R6
+ EOR R14,R7,R7
+ MOVW b+16(FP),R10
+ MOVW b_len+20(FP),R11
+ ADD R10,R11,R11
+ MOVW R11,endb-4(SP)
+ AND.S $3,R10,R8
+ BNE hashloopunaligned
+hashloop:
+ MOVW endb-4(SP),R11
+ SUB R10,R11,R11
+ SUB.S $8,R11
+ BLO hashend
+ MOVM.IA.W (R10),[R12,R14]
+ EOR R12,R6,R6
+ EOR R14,R7,R7
+ ROUND()
+ EOR R12,R0,R0
+ EOR R14,R1,R1
+ B hashloop
+hashloopunaligned:
+ MOVW endb-4(SP),R11
+ SUB R10,R11,R11
+ SUB.S $8,R11
+ BLO hashend
+ MOVB (R10),R12
+ MOVB 1(R10),R11
+ ORR R11<<8,R12,R12
+ MOVB 2(R10),R11
+ ORR R11<<16,R12,R12
+ MOVB 3(R10),R11
+ ORR R11<<24,R12,R12
+ MOVB 4(R10),R14
+ MOVB 5(R10),R11
+ ORR R11<<8,R14,R14
+ MOVB 6(R10),R11
+ ORR R11<<16,R14,R14
+ MOVB 7(R10),R11
+ ORR R11<<24,R14,R14
+ ADD $8,R10,R10
+ EOR R12,R6,R6
+ EOR R14,R7,R7
+ ROUND()
+ EOR R12,R0,R0
+ EOR R14,R1,R1
+ B hashloopunaligned
+hashend:
+ MOVW $0x0,R12
+ MOVW $0x0,R14
+ RSB $0,R11,R11
+ AND.S $7,R11
+ BEQ hashlast
+ MOVW (R10),R12
+ SLL $3,R11
+ AND $63,R11
+ SUB.S $32,R11,R11
+ BEQ hashlast
+ BLO hashhi
+ MOVW R12<>R11,R12
+ B hashlast
+hashhi:
+ ADD $32,R11
+ MOVW 4(R10),R14
+ MOVW R14<>R11,R14
+hashlast:
+ MOVW b_len+20(FP),R11
+ ORR R11<<24,R14,R14
+ EOR R12,R6,R6
+ EOR R14,R7,R7
+ ROUND()
+ EOR R12,R0,R0
+ EOR R14,R1,R1
+ EOR $255,R4
+ ROUND()
+ ROUND()
+ EOR R2,R0,R0
+ EOR R3,R1,R1
+ EOR R6,R4,R4
+ EOR R7,R5,R5
+ EOR R4,R0,R0
+ EOR R5,R1,R1
+ MOVW sav-8(SP),R10
+ MOVW R0,ret_lo+28(FP)
+ MOVW R1,ret_hi+32(FP)
+ RET
diff --git a/vendor/github.com/dchest/siphash/hash_asm.go b/vendor/github.com/dchest/siphash/hash_asm.go
new file mode 100644
index 0000000..13f540c
--- /dev/null
+++ b/vendor/github.com/dchest/siphash/hash_asm.go
@@ -0,0 +1,33 @@
+// +build arm amd64,!appengine,!gccgo
+
+// Written in 2012 by Dmitry Chestnykh.
+//
+// To the extent possible under law, the author have dedicated all copyright
+// and related and neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+// http://creativecommons.org/publicdomain/zero/1.0/
+
+// This file contains a function definition for use with assembly implementations of Hash()
+
+package siphash
+
+//go:noescape
+
+// Hash returns the 64-bit SipHash-2-4 of the given byte slice with two 64-bit
+// parts of 128-bit key: k0 and k1.
+func Hash(k0, k1 uint64, b []byte) uint64
+
+//go:noescape
+
+// Hash128 returns the 128-bit SipHash-2-4 of the given byte slice with two
+// 64-bit parts of 128-bit key: k0 and k1.
+func Hash128(k0, k1 uint64, b []byte) (uint64, uint64)
+
+//go:noescape
+func blocks(d *digest, p []uint8)
+
+//go:noescape
+func finalize(d *digest) uint64
+
+//go:noescape
+func once(d *digest)
diff --git a/vendor/github.com/dchest/siphash/siphash.go b/vendor/github.com/dchest/siphash/siphash.go
new file mode 100644
index 0000000..4a3cb49
--- /dev/null
+++ b/vendor/github.com/dchest/siphash/siphash.go
@@ -0,0 +1,318 @@
+// Written in 2012-2014 by Dmitry Chestnykh.
+//
+// To the extent possible under law, the author have dedicated all copyright
+// and related and neighboring rights to this software to the public domain
+// worldwide. This software is distributed without any warranty.
+// http://creativecommons.org/publicdomain/zero/1.0/
+
+// Package siphash implements SipHash-2-4, a fast short-input PRF
+// created by Jean-Philippe Aumasson and Daniel J. Bernstein.
+package siphash
+
+import "hash"
+
+const (
+ // BlockSize is the block size of hash algorithm in bytes.
+ BlockSize = 8
+
+ // Size is the size of hash output in bytes.
+ Size = 8
+
+ // Size128 is the size of 128-bit hash output in bytes.
+ Size128 = 16
+)
+
+type digest struct {
+ v0, v1, v2, v3 uint64 // state
+ k0, k1 uint64 // two parts of key
+ x [8]byte // buffer for unprocessed bytes
+ nx int // number of bytes in buffer x
+ size int // output size in bytes (8 or 16)
+ t uint8 // message bytes counter (mod 256)
+}
+
+// newDigest returns a new digest with the given output size in bytes (must be 8 or 16).
+func newDigest(size int, key []byte) *digest {
+ if size != Size && size != Size128 {
+ panic("size must be 8 or 16")
+ }
+ d := new(digest)
+ d.k0 = uint64(key[0]) | uint64(key[1])<<8 | uint64(key[2])<<16 | uint64(key[3])<<24 |
+ uint64(key[4])<<32 | uint64(key[5])<<40 | uint64(key[6])<<48 | uint64(key[7])<<56
+ d.k1 = uint64(key[8]) | uint64(key[9])<<8 | uint64(key[10])<<16 | uint64(key[11])<<24 |
+ uint64(key[12])<<32 | uint64(key[13])<<40 | uint64(key[14])<<48 | uint64(key[15])<<56
+ d.size = size
+ d.Reset()
+ return d
+}
+
+// New returns a new hash.Hash64 computing SipHash-2-4 with 16-byte key and 8-byte output.
+func New(key []byte) hash.Hash64 {
+ return newDigest(Size, key)
+}
+
+// New128 returns a new hash.Hash computing SipHash-2-4 with 16-byte key and 16-byte output.
+//
+// Note that 16-byte output is considered experimental by SipHash authors at this time.
+func New128(key []byte) hash.Hash {
+ return newDigest(Size128, key)
+}
+
+func (d *digest) Reset() {
+ d.v0 = d.k0 ^ 0x736f6d6570736575
+ d.v1 = d.k1 ^ 0x646f72616e646f6d
+ d.v2 = d.k0 ^ 0x6c7967656e657261
+ d.v3 = d.k1 ^ 0x7465646279746573
+ d.t = 0
+ d.nx = 0
+ if d.size == Size128 {
+ d.v1 ^= 0xee
+ }
+}
+
+func (d *digest) Size() int { return d.size }
+
+func (d *digest) BlockSize() int { return BlockSize }
+
+func (d *digest) Write(p []byte) (nn int, err error) {
+ nn = len(p)
+ d.t += uint8(nn)
+ if d.nx > 0 {
+ n := len(p)
+ if n > BlockSize-d.nx {
+ n = BlockSize - d.nx
+ }
+ d.nx += copy(d.x[d.nx:], p)
+ if d.nx == BlockSize {
+ once(d)
+ d.nx = 0
+ }
+ p = p[n:]
+ }
+ if len(p) >= BlockSize {
+ n := len(p) &^ (BlockSize - 1)
+ blocks(d, p[:n])
+ p = p[n:]
+ }
+ if len(p) > 0 {
+ d.nx = copy(d.x[:], p)
+ }
+ return
+}
+
+func (d *digest) Sum64() uint64 {
+ for i := d.nx; i < BlockSize-1; i++ {
+ d.x[i] = 0
+ }
+ d.x[7] = d.t
+ return finalize(d)
+}
+
+func (d0 *digest) sum128() (r0, r1 uint64) {
+ // Make a copy of d0 so that caller can keep writing and summing.
+ d := *d0
+
+ for i := d.nx; i < BlockSize-1; i++ {
+ d.x[i] = 0
+ }
+ d.x[7] = d.t
+ blocks(&d, d.x[:])
+
+ v0, v1, v2, v3 := d.v0, d.v1, d.v2, d.v3
+ v2 ^= 0xee
+
+ // Round 1.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 2.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 3.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 4.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ r0 = v0 ^ v1 ^ v2 ^ v3
+
+ v1 ^= 0xdd
+
+ // Round 1.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 2.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 3.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ // Round 4.
+ v0 += v1
+ v1 = v1<<13 | v1>>(64-13)
+ v1 ^= v0
+ v0 = v0<<32 | v0>>(64-32)
+
+ v2 += v3
+ v3 = v3<<16 | v3>>(64-16)
+ v3 ^= v2
+
+ v0 += v3
+ v3 = v3<<21 | v3>>(64-21)
+ v3 ^= v0
+
+ v2 += v1
+ v1 = v1<<17 | v1>>(64-17)
+ v1 ^= v2
+ v2 = v2<<32 | v2>>(64-32)
+
+ r1 = v0 ^ v1 ^ v2 ^ v3
+
+ return r0, r1
+}
+
+func (d *digest) Sum(in []byte) []byte {
+ if d.size == Size {
+ r := d.Sum64()
+ in = append(in,
+ byte(r),
+ byte(r>>8),
+ byte(r>>16),
+ byte(r>>24),
+ byte(r>>32),
+ byte(r>>40),
+ byte(r>>48),
+ byte(r>>56))
+ } else {
+ r0, r1 := d.sum128()
+ in = append(in,
+ byte(r0),
+ byte(r0>>8),
+ byte(r0>>16),
+ byte(r0>>24),
+ byte(r0>>32),
+ byte(r0>>40),
+ byte(r0>>48),
+ byte(r0>>56),
+ byte(r1),
+ byte(r1>>8),
+ byte(r1>>16),
+ byte(r1>>24),
+ byte(r1>>32),
+ byte(r1>>40),
+ byte(r1>>48),
+ byte(r1>>56))
+ }
+ return in
+}
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gost/LICENSE b/vendor/github.com/ginuerzh/gosocks4/LICENSE
similarity index 97%
rename from cmd/gost/vendor/github.com/ginuerzh/gost/LICENSE
rename to vendor/github.com/ginuerzh/gosocks4/LICENSE
index 2033b3a..de5e3f4 100644
--- a/cmd/gost/vendor/github.com/ginuerzh/gost/LICENSE
+++ b/vendor/github.com/ginuerzh/gosocks4/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2016 ginuerzh
+Copyright (c) 2017 ginuerzh
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/github.com/ginuerzh/gosocks4/README.md b/vendor/github.com/ginuerzh/gosocks4/README.md
new file mode 100644
index 0000000..ddb0528
--- /dev/null
+++ b/vendor/github.com/ginuerzh/gosocks4/README.md
@@ -0,0 +1,2 @@
+# gosocks4
+golang and SOCKS4(a)
diff --git a/vendor/github.com/ginuerzh/gosocks4/socks4.go b/vendor/github.com/ginuerzh/gosocks4/socks4.go
new file mode 100644
index 0000000..52b32e4
--- /dev/null
+++ b/vendor/github.com/ginuerzh/gosocks4/socks4.go
@@ -0,0 +1,252 @@
+// SOCKS Protocol Version 4(a)
+// https://www.openssh.com/txt/socks4.protocol
+// https://www.openssh.com/txt/socks4a.protocol
+package gosocks4
+
+import (
+ "bufio"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "strconv"
+)
+
+const (
+ Ver4 = 4
+)
+
+const (
+ CmdConnect uint8 = 1
+ CmdBind = 2
+)
+
+const (
+ AddrIPv4 = 0
+ AddrDomain = 1
+)
+
+const (
+ Granted = 90
+ Failed = 91
+ Rejected = 92
+ RejectedUserid = 93
+)
+
+var (
+ ErrBadVersion = errors.New("Bad version")
+ ErrBadFormat = errors.New("Bad format")
+ ErrBadAddrType = errors.New("Bad address type")
+ ErrShortDataLength = errors.New("Short data length")
+ ErrBadCmd = errors.New("Bad Command")
+)
+
+type Addr struct {
+ Type int
+ Host string
+ Port uint16
+}
+
+func (addr *Addr) Decode(b []byte) error {
+ if len(b) < 6 {
+ return ErrShortDataLength
+ }
+
+ addr.Port = binary.BigEndian.Uint16(b[0:2])
+ addr.Host = net.IP(b[2 : 2+net.IPv4len]).String()
+
+ if b[2]|b[3]|b[4] == 0 {
+ addr.Type = AddrDomain
+ }
+
+ return nil
+}
+
+func (addr *Addr) Encode(b []byte) error {
+ if len(b) < 6 {
+ return ErrShortDataLength
+ }
+
+ binary.BigEndian.PutUint16(b[0:2], addr.Port)
+
+ switch addr.Type {
+ case AddrIPv4:
+ ip4 := net.ParseIP(addr.Host).To4()
+ if ip4 == nil {
+ return ErrBadAddrType
+ }
+ copy(b[2:], ip4)
+ case AddrDomain:
+ ip4 := net.IPv4(0, 0, 0, 1)
+ copy(b[2:], ip4)
+ default:
+ return ErrBadAddrType
+ }
+
+ return nil
+}
+
+func (addr *Addr) String() string {
+ return net.JoinHostPort(addr.Host, strconv.Itoa(int(addr.Port)))
+}
+
+/*
+ +----+----+----+----+----+----+----+----+----+----+....+----+
+ | VN | CD | DSTPORT | DSTIP | USERID |NULL|
+ +----+----+----+----+----+----+----+----+----+----+....+----+
+ 1 1 2 4 variable 1
+*/
+type Request struct {
+ Cmd uint8
+ Addr *Addr
+ Userid []byte
+}
+
+func NewRequest(cmd uint8, addr *Addr, userid []byte) *Request {
+ return &Request{
+ Cmd: cmd,
+ Addr: addr,
+ Userid: userid,
+ }
+}
+
+func ReadRequest(r io.Reader) (*Request, error) {
+ br := bufio.NewReader(r)
+ b, err := br.Peek(8)
+ if err != nil {
+ return nil, err
+ }
+
+ if b[0] != Ver4 {
+ return nil, ErrBadVersion
+ }
+
+ request := &Request{
+ Cmd: b[1],
+ }
+
+ addr := &Addr{}
+ if err := addr.Decode(b[2:8]); err != nil {
+ return nil, err
+ }
+ request.Addr = addr
+
+ if _, err := br.Discard(8); err != nil {
+ return nil, err
+ }
+ b, err = br.ReadBytes(0)
+ if err != nil {
+ return nil, err
+ }
+ request.Userid = b[:len(b)-1]
+
+ if request.Addr.Type == AddrDomain {
+ b, err = br.ReadBytes(0)
+ if err != nil {
+ return nil, err
+ }
+ request.Addr.Host = string(b[:len(b)-1])
+ }
+
+ return request, nil
+}
+
+func (r *Request) Write(w io.Writer) (err error) {
+ bw := bufio.NewWriter(w)
+ bw.Write([]byte{Ver4, r.Cmd})
+
+ if r.Addr == nil {
+ return ErrBadAddrType
+ }
+
+ var b [6]byte
+ if err = r.Addr.Encode(b[:]); err != nil {
+ return
+ }
+ bw.Write(b[:])
+
+ if len(r.Userid) > 0 {
+ bw.Write(r.Userid)
+ }
+ bw.WriteByte(0)
+
+ if r.Addr.Type == AddrDomain {
+ bw.WriteString(r.Addr.Host)
+ bw.WriteByte(0)
+ }
+
+ return bw.Flush()
+}
+
+func (r *Request) String() string {
+ addr := r.Addr
+ if addr == nil {
+ addr = &Addr{}
+ }
+ return fmt.Sprintf("%d %d %s", Ver4, r.Cmd, addr.String())
+}
+
+/*
+ +----+----+----+----+----+----+----+----+
+ | VN | CD | DSTPORT | DSTIP |
+ +----+----+----+----+----+----+----+----+
+ 1 1 2 4
+*/
+type Reply struct {
+ Code uint8
+ Addr *Addr
+}
+
+func NewReply(code uint8, addr *Addr) *Reply {
+ return &Reply{
+ Code: code,
+ Addr: addr,
+ }
+}
+
+func ReadReply(r io.Reader) (*Reply, error) {
+ var b [8]byte
+
+ _, err := io.ReadFull(r, b[:])
+ if err != nil {
+ return nil, err
+ }
+
+ if b[0] != 0 {
+ return nil, ErrBadVersion
+ }
+
+ reply := &Reply{
+ Code: b[1],
+ }
+
+ reply.Addr = &Addr{}
+ if err := reply.Addr.Decode(b[2:]); err != nil {
+ return nil, err
+ }
+
+ return reply, nil
+}
+
+func (r *Reply) Write(w io.Writer) (err error) {
+ var b [8]byte
+
+ b[1] = r.Code
+ if r.Addr != nil {
+ if err = r.Addr.Encode(b[2:]); err != nil {
+ return
+ }
+ }
+
+ _, err = w.Write(b[:])
+ return
+}
+
+func (r *Reply) String() string {
+ addr := r.Addr
+ if addr == nil {
+ addr = &Addr{}
+ }
+ return fmt.Sprintf("0 %d %s", r.Code, addr.String())
+}
diff --git a/vendor/github.com/ginuerzh/gosocks4/socks4.protocol.txt b/vendor/github.com/ginuerzh/gosocks4/socks4.protocol.txt
new file mode 100644
index 0000000..6bc0837
--- /dev/null
+++ b/vendor/github.com/ginuerzh/gosocks4/socks4.protocol.txt
@@ -0,0 +1,152 @@
+ SOCKS: A protocol for TCP proxy across firewalls
+
+ Ying-Da Lee
+ Principal Member Technical Staff
+ NEC Systems Laboratory, CSTC
+ ylee@syl.dl.nec.com
+
+SOCKS was originally developed by David Koblas and subsequently modified
+and extended by me to its current running version -- version 4. It is a
+protocol that relays TCP sessions at a firewall host to allow application
+users transparent access across the firewall. Because the protocol is
+independent of application protocols, it can be (and has been) used for
+many different services, such as telnet, ftp, finger, whois, gopher, WWW,
+etc. Access control can be applied at the beginning of each TCP session;
+thereafter the server simply relays the data between the client and the
+application server, incurring minimum processing overhead. Since SOCKS
+never has to know anything about the application protocol, it should also
+be easy for it to accommodate applications which use encryption to protect
+their traffic from nosey snoopers.
+
+Two operations are defined: CONNECT and BIND.
+
+1) CONNECT
+
+The client connects to the SOCKS server and sends a CONNECT request when
+it wants to establish a connection to an application server. The client
+includes in the request packet the IP address and the port number of the
+destination host, and userid, in the following format.
+
+ +----+----+----+----+----+----+----+----+----+----+....+----+
+ | VN | CD | DSTPORT | DSTIP | USERID |NULL|
+ +----+----+----+----+----+----+----+----+----+----+....+----+
+ # of bytes: 1 1 2 4 variable 1
+
+VN is the SOCKS protocol version number and should be 4. CD is the
+SOCKS command code and should be 1 for CONNECT request. NULL is a byte
+of all zero bits.
+
+The SOCKS server checks to see whether such a request should be granted
+based on any combination of source IP address, destination IP address,
+destination port number, the userid, and information it may obtain by
+consulting IDENT, cf. RFC 1413. If the request is granted, the SOCKS
+server makes a connection to the specified port of the destination host.
+A reply packet is sent to the client when this connection is established,
+or when the request is rejected or the operation fails.
+
+ +----+----+----+----+----+----+----+----+
+ | VN | CD | DSTPORT | DSTIP |
+ +----+----+----+----+----+----+----+----+
+ # of bytes: 1 1 2 4
+
+VN is the version of the reply code and should be 0. CD is the result
+code with one of the following values:
+
+ 90: request granted
+ 91: request rejected or failed
+ 92: request rejected becasue SOCKS server cannot connect to
+ identd on the client
+ 93: request rejected because the client program and identd
+ report different user-ids
+
+The remaining fields are ignored.
+
+The SOCKS server closes its connection immediately after notifying
+the client of a failed or rejected request. For a successful request,
+the SOCKS server gets ready to relay traffic on both directions. This
+enables the client to do I/O on its connection as if it were directly
+connected to the application server.
+
+
+2) BIND
+
+The client connects to the SOCKS server and sends a BIND request when
+it wants to prepare for an inbound connection from an application server.
+This should only happen after a primary connection to the application
+server has been established with a CONNECT. Typically, this is part of
+the sequence of actions:
+
+-bind(): obtain a socket
+-getsockname(): get the IP address and port number of the socket
+-listen(): ready to accept call from the application server
+-use the primary connection to inform the application server of
+ the IP address and the port number that it should connect to.
+-accept(): accept a connection from the application server
+
+The purpose of SOCKS BIND operation is to support such a sequence
+but using a socket on the SOCKS server rather than on the client.
+
+The client includes in the request packet the IP address of the
+application server, the destination port used in the primary connection,
+and the userid.
+
+ +----+----+----+----+----+----+----+----+----+----+....+----+
+ | VN | CD | DSTPORT | DSTIP | USERID |NULL|
+ +----+----+----+----+----+----+----+----+----+----+....+----+
+ # of bytes: 1 1 2 4 variable 1
+
+VN is again 4 for the SOCKS protocol version number. CD must be 2 to
+indicate BIND request.
+
+The SOCKS server uses the client information to decide whether the
+request is to be granted. The reply it sends back to the client has
+the same format as the reply for CONNECT request, i.e.,
+
+ +----+----+----+----+----+----+----+----+
+ | VN | CD | DSTPORT | DSTIP |
+ +----+----+----+----+----+----+----+----+
+ # of bytes: 1 1 2 4
+
+VN is the version of the reply code and should be 0. CD is the result
+code with one of the following values:
+
+ 90: request granted
+ 91: request rejected or failed
+ 92: request rejected becasue SOCKS server cannot connect to
+ identd on the client
+ 93: request rejected because the client program and identd
+ report different user-ids.
+
+However, for a granted request (CD is 90), the DSTPORT and DSTIP fields
+are meaningful. In that case, the SOCKS server obtains a socket to wait
+for an incoming connection and sends the port number and the IP address
+of that socket to the client in DSTPORT and DSTIP, respectively. If the
+DSTIP in the reply is 0 (the value of constant INADDR_ANY), then the
+client should replace it by the IP address of the SOCKS server to which
+the cleint is connected. (This happens if the SOCKS server is not a
+multi-homed host.) In the typical scenario, these two numbers are
+made available to the application client prgram via the result of the
+subsequent getsockname() call. The application protocol must provide a
+way for these two pieces of information to be sent from the client to
+the application server so that it can initiate the connection, which
+connects it to the SOCKS server rather than directly to the application
+client as it normally would.
+
+The SOCKS server sends a second reply packet to the client when the
+anticipated connection from the application server is established.
+The SOCKS server checks the IP address of the originating host against
+the value of DSTIP specified in the client's BIND request. If a mismatch
+is found, the CD field in the second reply is set to 91 and the SOCKS
+server closes both connections. If the two match, CD in the second
+reply is set to 90 and the SOCKS server gets ready to relay the traffic
+on its two connections. From then on the client does I/O on its connection
+to the SOCKS server as if it were directly connected to the application
+server.
+
+
+
+For both CONNECT and BIND operations, the server sets a time limit
+(2 minutes in current CSTC implementation) for the establishment of its
+connection with the application server. If the connection is still not
+establiched when the time limit expires, the server closes its connection
+to the client and gives up.
diff --git a/vendor/github.com/ginuerzh/gosocks4/socks4a.protocol.txt b/vendor/github.com/ginuerzh/gosocks4/socks4a.protocol.txt
new file mode 100644
index 0000000..f944218
--- /dev/null
+++ b/vendor/github.com/ginuerzh/gosocks4/socks4a.protocol.txt
@@ -0,0 +1,39 @@
+ SOCKS 4A: A Simple Extension to SOCKS 4 Protocol
+
+ Ying-Da Lee
+ yingda@best.com or yingda@esd.sgi.com
+
+Please read SOCKS4.protocol first for an description of the version 4
+protocol. This extension is intended to allow the use of SOCKS on hosts
+which are not capable of resolving all domain names.
+
+In version 4, the client sends the following packet to the SOCKS server
+to request a CONNECT or a BIND operation:
+
+ +----+----+----+----+----+----+----+----+----+----+....+----+
+ | VN | CD | DSTPORT | DSTIP | USERID |NULL|
+ +----+----+----+----+----+----+----+----+----+----+....+----+
+ # of bytes: 1 1 2 4 variable 1
+
+VN is the SOCKS protocol version number and should be 4. CD is the
+SOCKS command code and should be 1 for CONNECT or 2 for BIND. NULL
+is a byte of all zero bits.
+
+For version 4A, if the client cannot resolve the destination host's
+domain name to find its IP address, it should set the first three bytes
+of DSTIP to NULL and the last byte to a non-zero value. (This corresponds
+to IP address 0.0.0.x, with x nonzero. As decreed by IANA -- The
+Internet Assigned Numbers Authority -- such an address is inadmissible
+as a destination IP address and thus should never occur if the client
+can resolve the domain name.) Following the NULL byte terminating
+USERID, the client must sends the destination domain name and termiantes
+it with another NULL byte. This is used for both CONNECT and BIND requests.
+
+A server using protocol 4A must check the DSTIP in the request packet.
+If it represent address 0.0.0.x with nonzero x, the server must read
+in the domain name that the client sends in the packet. The server
+should resolve the domain name and make connection to the destination
+host if it can.
+
+SOCKSified sockd may pass domain names that it cannot resolve to
+the next-hop SOCKS server.
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gosocks5/LICENSE b/vendor/github.com/ginuerzh/gosocks5/LICENSE
similarity index 100%
rename from cmd/gost/vendor/github.com/ginuerzh/gosocks5/LICENSE
rename to vendor/github.com/ginuerzh/gosocks5/LICENSE
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gosocks5/README.md b/vendor/github.com/ginuerzh/gosocks5/README.md
similarity index 100%
rename from cmd/gost/vendor/github.com/ginuerzh/gosocks5/README.md
rename to vendor/github.com/ginuerzh/gosocks5/README.md
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gosocks5/conn.go b/vendor/github.com/ginuerzh/gosocks5/conn.go
similarity index 100%
rename from cmd/gost/vendor/github.com/ginuerzh/gosocks5/conn.go
rename to vendor/github.com/ginuerzh/gosocks5/conn.go
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gosocks5/rfc1928.txt b/vendor/github.com/ginuerzh/gosocks5/rfc1928.txt
similarity index 100%
rename from cmd/gost/vendor/github.com/ginuerzh/gosocks5/rfc1928.txt
rename to vendor/github.com/ginuerzh/gosocks5/rfc1928.txt
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gosocks5/rfc1929.txt b/vendor/github.com/ginuerzh/gosocks5/rfc1929.txt
similarity index 100%
rename from cmd/gost/vendor/github.com/ginuerzh/gosocks5/rfc1929.txt
rename to vendor/github.com/ginuerzh/gosocks5/rfc1929.txt
diff --git a/cmd/gost/vendor/github.com/ginuerzh/gosocks5/socks5.go b/vendor/github.com/ginuerzh/gosocks5/socks5.go
similarity index 98%
rename from cmd/gost/vendor/github.com/ginuerzh/gosocks5/socks5.go
rename to vendor/github.com/ginuerzh/gosocks5/socks5.go
index d492571..64709b2 100644
--- a/cmd/gost/vendor/github.com/ginuerzh/gosocks5/socks5.go
+++ b/vendor/github.com/ginuerzh/gosocks5/socks5.go
@@ -4,6 +4,7 @@
package gosocks5
import (
+ "bytes"
"encoding/binary"
"errors"
"fmt"
@@ -658,10 +659,14 @@ func (d *UDPDatagram) Write(w io.Writer) error {
if h == nil {
h = &UDPHeader{}
}
- if err := h.Write(w); err != nil {
+ buf := bytes.Buffer{}
+ if err := h.Write(&buf); err != nil {
+ return err
+ }
+ if _, err := buf.Write(d.Data); err != nil {
return err
}
- _, err := w.Write(d.Data)
+ _, err := buf.WriteTo(w)
return err
}
diff --git a/vendor/github.com/ginuerzh/pht/LICENSE b/vendor/github.com/ginuerzh/pht/LICENSE
new file mode 100644
index 0000000..de5e3f4
--- /dev/null
+++ b/vendor/github.com/ginuerzh/pht/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 ginuerzh
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/ginuerzh/pht/README.md b/vendor/github.com/ginuerzh/pht/README.md
new file mode 100644
index 0000000..35b25fa
--- /dev/null
+++ b/vendor/github.com/ginuerzh/pht/README.md
@@ -0,0 +1,2 @@
+# pht
+Plain HTTP Tunnel - Tunnel over HTTP using only GET and POST requests, NO Websocket, NO CONNECT method.
diff --git a/vendor/github.com/ginuerzh/pht/client.go b/vendor/github.com/ginuerzh/pht/client.go
new file mode 100644
index 0000000..dd09e91
--- /dev/null
+++ b/vendor/github.com/ginuerzh/pht/client.go
@@ -0,0 +1,162 @@
+package pht
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "strings"
+ "time"
+)
+
+type Client struct {
+ Host string
+ Key string
+ httpClient *http.Client
+ manager *sessionManager
+}
+
+func NewClient(host, key string) *Client {
+ return &Client{
+ Host: host,
+ Key: key,
+ httpClient: &http.Client{},
+ manager: newSessionManager(),
+ }
+}
+
+func (c *Client) Dial() (net.Conn, error) {
+ r, err := http.NewRequest(http.MethodPost, fmt.Sprintf("http://%s%s", c.Host, tokenURI), nil)
+ if err != nil {
+ return nil, err
+ }
+ r.Header.Set("Authorization", "key="+c.Key)
+ resp, err := c.httpClient.Do(r)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode != http.StatusOK {
+ return nil, errors.New(resp.Status)
+ }
+
+ data, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+ token := strings.TrimPrefix(string(data), "token=")
+ if token == "" {
+ return nil, errors.New("invalid token")
+ }
+
+ session := newSession(0, 0)
+ c.manager.SetSession(token, session)
+
+ go c.sendDataLoop(token)
+ go c.recvDataLoop(token)
+
+ return newConn(session), nil
+}
+
+func (c *Client) sendDataLoop(token string) error {
+ session := c.manager.GetSession(token)
+ if session == nil {
+ return errors.New("invalid token")
+ }
+
+ for {
+ select {
+ case b, ok := <-session.wchan:
+ var data string
+ if len(b) > 0 {
+ data = base64.StdEncoding.EncodeToString(b)
+ }
+ r, err := http.NewRequest(http.MethodPost, fmt.Sprintf("http://%s%s", c.Host, pushURI), bytes.NewBufferString(data+"\n"))
+ if err != nil {
+ return err
+ }
+ r.Header.Set("Authorization", fmt.Sprintf("key=%s; token=%s", c.Key, token))
+ if !ok {
+ c.manager.DelSession(token)
+ resp, err := c.httpClient.Do(r)
+ if err != nil { // TODO: retry
+ return err
+ }
+ resp.Body.Close()
+ return nil // session is closed
+ }
+
+ resp, err := c.httpClient.Do(r)
+ if err != nil { // TODO: retry
+ return err
+ }
+ resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ return errors.New(resp.Status)
+ }
+ }
+ }
+}
+
+func (c *Client) recvDataLoop(token string) error {
+ session := c.manager.GetSession(token)
+ if session == nil {
+ return errors.New("invalid token")
+ }
+
+ for {
+ err := c.recvData(token, session)
+ if err != nil {
+ close(session.rchan)
+ c.manager.DelSession(token)
+ return err
+ }
+ }
+}
+
+func (c *Client) recvData(token string, s *session) error {
+ r, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s%s", c.Host, pollURI), nil)
+ if err != nil {
+ return err
+ }
+ r.Header.Set("Authorization", fmt.Sprintf("key=%s; token=%s", c.Key, token))
+ resp, err := c.httpClient.Do(r)
+ if err != nil {
+ return err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ return errors.New(resp.Status)
+ }
+
+ scanner := bufio.NewScanner(resp.Body)
+ for scanner.Scan() {
+ select {
+ case <-s.closed:
+ return errors.New("session closed")
+ default:
+ }
+
+ b, err := base64.StdEncoding.DecodeString(scanner.Text())
+ if err != nil {
+ return err
+ }
+ select {
+ case s.rchan <- b:
+ case <-s.closed:
+ return errors.New("session closed")
+ case <-time.After(time.Second * 90):
+ return errors.New("timeout")
+ }
+
+ if err := scanner.Err(); err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/ginuerzh/pht/conn.go b/vendor/github.com/ginuerzh/pht/conn.go
new file mode 100644
index 0000000..3dd7f1e
--- /dev/null
+++ b/vendor/github.com/ginuerzh/pht/conn.go
@@ -0,0 +1,133 @@
+package pht
+
+import (
+ "errors"
+ "io"
+ "net"
+ "time"
+)
+
+type conn struct {
+ session *session
+ rb []byte // read buffer
+ remoteAddr net.Addr
+ localAddr net.Addr
+ rTimer, wTimer *time.Timer
+ closed chan interface{}
+}
+
+func newConn(session *session) *conn {
+ conn := &conn{
+ session: session,
+ rTimer: time.NewTimer(time.Hour * 65535),
+ wTimer: time.NewTimer(time.Hour * 65535),
+ closed: make(chan interface{}),
+ }
+ conn.rTimer.Stop()
+ conn.wTimer.Stop()
+
+ return conn
+}
+
+func (conn *conn) Read(b []byte) (n int, err error) {
+ select {
+ case <-conn.closed:
+ err = errors.New("read: use of closed network connection")
+ return
+ default:
+ }
+
+ if len(conn.rb) > 0 {
+ n = copy(b, conn.rb)
+ conn.rb = conn.rb[n:]
+ return
+ }
+
+ select {
+ case data, ok := <-conn.session.rchan:
+ if !ok {
+ err = io.EOF
+ return
+ }
+ n = copy(b, data)
+ conn.rb = data[n:]
+ case <-conn.rTimer.C:
+ err = errors.New("read timeout")
+ case <-conn.closed:
+ err = io.EOF
+ }
+
+ return
+}
+
+func (conn *conn) Write(b []byte) (n int, err error) {
+ select {
+ case <-conn.closed:
+ err = errors.New("write: use of closed network connection")
+ return
+ default:
+ }
+
+ if len(b) == 0 {
+ return
+ }
+
+ data := make([]byte, len(b))
+ copy(data, b)
+
+ select {
+ case conn.session.wchan <- data:
+ n = len(b)
+ case <-conn.wTimer.C:
+ err = errors.New("write timeout")
+ case <-conn.closed:
+ err = errors.New("connection is closed")
+ }
+
+ return
+}
+
+func (conn *conn) Close() error {
+ close(conn.closed)
+ close(conn.session.closed)
+ close(conn.session.wchan)
+ return nil
+}
+
+func (conn *conn) LocalAddr() net.Addr {
+ return conn.localAddr
+}
+
+func (conn *conn) RemoteAddr() net.Addr {
+ return conn.remoteAddr
+}
+
+func (conn *conn) SetReadDeadline(t time.Time) error {
+ if t.IsZero() {
+ conn.rTimer.Stop()
+ return nil
+ }
+ conn.rTimer.Reset(t.Sub(time.Now()))
+ return nil
+}
+
+func (conn *conn) SetWriteDeadline(t time.Time) error {
+ if t.IsZero() {
+ conn.wTimer.Stop()
+ return nil
+ }
+ conn.wTimer.Reset(t.Sub(time.Now()))
+ return nil
+}
+
+func (conn *conn) SetDeadline(t time.Time) error {
+ if t.IsZero() {
+ conn.rTimer.Stop()
+ conn.wTimer.Stop()
+ return nil
+ }
+ d := t.Sub(time.Now())
+ conn.rTimer.Reset(d)
+ conn.wTimer.Reset(d)
+ return nil
+}
diff --git a/vendor/github.com/ginuerzh/pht/server.go b/vendor/github.com/ginuerzh/pht/server.go
new file mode 100644
index 0000000..8aa7960
--- /dev/null
+++ b/vendor/github.com/ginuerzh/pht/server.go
@@ -0,0 +1,199 @@
+package pht
+
+import (
+ "bufio"
+ "encoding/base64"
+ "fmt"
+ "net"
+ "net/http"
+ "strings"
+ "time"
+)
+
+const (
+ tokenURI = "/token"
+ pushURI = "/push"
+ pollURI = "/poll"
+)
+
+type Server struct {
+ Addr string
+ Key string
+ Handler func(net.Conn)
+ manager *sessionManager
+}
+
+func (s *Server) ListenAndServe() error {
+ s.manager = newSessionManager()
+
+ mux := http.NewServeMux()
+ mux.Handle(tokenURI, http.HandlerFunc(s.tokenHandler))
+ mux.Handle(pushURI, http.HandlerFunc(s.pushHandler))
+ mux.Handle(pollURI, http.HandlerFunc(s.pollHandler))
+
+ return http.ListenAndServe(s.Addr, mux)
+}
+
+func (s *Server) tokenHandler(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodPost {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ m := parseAuth(r.Header.Get("Authorization"))
+ if m["key"] != s.Key {
+ w.WriteHeader(http.StatusForbidden)
+ return
+ }
+
+ token, session, err := s.manager.NewSession(0, 0)
+ if err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ conn, err := s.upgrade(session, r)
+ if err != nil {
+ s.manager.DelSession(token)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ if s.Handler != nil {
+ go s.Handler(conn)
+ }
+
+ w.Write([]byte(fmt.Sprintf("token=%s", token)))
+}
+
+func (s *Server) pushHandler(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodPost {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ m := parseAuth(r.Header.Get("Authorization"))
+ if m["key"] != s.Key {
+ w.WriteHeader(http.StatusForbidden)
+ return
+ }
+
+ token := m["token"]
+ session := s.manager.GetSession(token)
+ if session == nil {
+ w.WriteHeader(http.StatusUnauthorized)
+ return
+ }
+
+ br := bufio.NewReader(r.Body)
+ data, err := br.ReadString('\n')
+ if err != nil {
+ s.manager.DelSession(token)
+ close(session.rchan)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ data = strings.TrimSuffix(data, "\n")
+ if len(data) == 0 {
+ s.manager.DelSession(token)
+ close(session.rchan)
+ return
+ }
+
+ b, err := base64.StdEncoding.DecodeString(data)
+ if err != nil {
+ s.manager.DelSession(token)
+ close(session.rchan)
+ return
+ }
+
+ select {
+ case <-session.closed:
+ s.manager.DelSession(token)
+ return
+ case session.rchan <- b:
+ w.WriteHeader(http.StatusOK)
+ case <-time.After(time.Second * 90):
+ s.manager.DelSession(token)
+ w.WriteHeader(http.StatusRequestTimeout)
+ }
+}
+
+func (s *Server) pollHandler(w http.ResponseWriter, r *http.Request) {
+ if r.Method != http.MethodGet {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ m := parseAuth(r.Header.Get("Authorization"))
+ if m["key"] != s.Key {
+ w.WriteHeader(http.StatusForbidden)
+ return
+ }
+
+ token := m["token"]
+ session := s.manager.GetSession(token)
+ if session == nil {
+ w.WriteHeader(http.StatusUnauthorized)
+ return
+ }
+
+ w.WriteHeader(http.StatusOK)
+ if fw, ok := w.(http.Flusher); ok {
+ fw.Flush()
+ }
+
+ for {
+ select {
+ case data, ok := <-session.wchan:
+ if !ok {
+ s.manager.DelSession(token)
+ return // session is closed
+ }
+ bw := bufio.NewWriter(w)
+ bw.WriteString(base64.StdEncoding.EncodeToString(data))
+ bw.WriteString("\n")
+ if err := bw.Flush(); err != nil {
+ return
+ }
+
+ if fw, ok := w.(http.Flusher); ok {
+ fw.Flush()
+ }
+ case <-time.After(time.Second * 25):
+ return
+ }
+ }
+}
+
+func (s *Server) upgrade(sess *session, r *http.Request) (net.Conn, error) {
+ conn := newConn(sess)
+ raddr, err := net.ResolveTCPAddr("tcp", r.RemoteAddr)
+ if err != nil {
+ raddr = &net.TCPAddr{}
+ }
+ conn.remoteAddr = raddr
+
+ laddr, err := net.ResolveTCPAddr("tcp", s.Addr)
+ if err != nil {
+ laddr = &net.TCPAddr{}
+ }
+ conn.localAddr = laddr
+
+ return conn, nil
+}
+
+func parseAuth(auth string) map[string]string {
+ mkv := make(map[string]string)
+
+ for _, s := range strings.Split(auth, ";") {
+ n := strings.Index(s, "=")
+ if n < 0 {
+ continue
+ }
+ mkv[strings.TrimSpace(s[:n])] = strings.TrimSpace(s[n+1:])
+ }
+
+ return mkv
+}
diff --git a/vendor/github.com/ginuerzh/pht/session.go b/vendor/github.com/ginuerzh/pht/session.go
new file mode 100644
index 0000000..99b3a9f
--- /dev/null
+++ b/vendor/github.com/ginuerzh/pht/session.go
@@ -0,0 +1,80 @@
+package pht
+
+import (
+ "crypto/rand"
+ "encoding/hex"
+ "sync"
+)
+
+const (
+ defaultRChanLen = 64
+ defaultWChanLen = 64
+)
+
+type session struct {
+ rchan chan []byte
+ wchan chan []byte
+ closed chan interface{}
+}
+
+func newSession(rlen, wlen int) *session {
+ if rlen <= 0 {
+ rlen = defaultRChanLen
+ }
+ if wlen <= 0 {
+ wlen = defaultWChanLen
+ }
+
+ return &session{
+ rchan: make(chan []byte, rlen),
+ wchan: make(chan []byte, wlen),
+ closed: make(chan interface{}),
+ }
+}
+
+type sessionManager struct {
+ sessions map[string]*session
+ mux sync.Mutex
+}
+
+func newSessionManager() *sessionManager {
+ return &sessionManager{
+ sessions: make(map[string]*session),
+ mux: sync.Mutex{},
+ }
+}
+
+func (m *sessionManager) NewSession(rlen, wlen int) (token string, s *session, err error) {
+ var nonce [16]byte
+ if _, err = rand.Read(nonce[:]); err != nil {
+ return
+ }
+ token = hex.EncodeToString(nonce[:])
+ s = newSession(rlen, wlen)
+
+ m.mux.Lock()
+ defer m.mux.Unlock()
+ m.sessions[token] = s
+
+ return
+}
+
+func (m *sessionManager) SetSession(token string, session *session) {
+ m.mux.Lock()
+ defer m.mux.Unlock()
+ m.sessions[token] = session
+}
+
+func (m *sessionManager) GetSession(token string) *session {
+ m.mux.Lock()
+ defer m.mux.Unlock()
+
+ return m.sessions[token]
+}
+
+func (m *sessionManager) DelSession(token string) {
+ m.mux.Lock()
+ defer m.mux.Unlock()
+
+ delete(m.sessions, token)
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/LICENSE b/vendor/github.com/go-log/log/LICENSE
similarity index 97%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/LICENSE
rename to vendor/github.com/go-log/log/LICENSE
index 9cf1062..0522e07 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/LICENSE
+++ b/vendor/github.com/go-log/log/LICENSE
@@ -1,4 +1,4 @@
-MIT License
+Copyright (c) 2017 Go Log
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/github.com/go-log/log/README.md b/vendor/github.com/go-log/log/README.md
new file mode 100644
index 0000000..d324632
--- /dev/null
+++ b/vendor/github.com/go-log/log/README.md
@@ -0,0 +1,63 @@
+# Log [](https://godoc.org/github.com/go-log/log)
+
+Log is a logging interface for Go. That's it. Pass around the interface.
+
+## Rationale
+
+Users want to standardise logging. Sometimes libraries log. We leave the underlying logging implementation to the user
+while allowing libraries to log by simply expecting something that satisfies the Logger interface. This leaves
+the user free to pre-configure structure, output, etc.
+
+## Interface
+
+The interface is minimalistic on purpose
+
+```go
+type Logger interface {
+ Log(v ...interface{})
+ Logf(format string, v ...interface{})
+}
+```
+
+## Example
+
+Here's a logger that uses logrus and logs with predefined fields.
+
+```go
+import (
+ "github.com/go-log/log"
+ "github.com/sirupsen/logrus"
+)
+
+type logrusLogger struct {
+ *logrus.Entry
+}
+
+func (l *logrusLogger) Log(v ...interface{}) {
+ l.Entry.Print(v...)
+}
+
+func (l *logrusLogger) Logf(format string, v ...interface{}) {
+ l.Entry.Printf(format, v...)
+}
+
+func WithFields(f logrus.Fields) log.Logger {
+ return &logrusLogger{logrus.WithFields(f)}
+}
+```
+
+The `WithFields` func returns a struct that satisfies the Logger interface.
+
+Pre-configure a logger using WithFields and pass it as an option to a library.
+
+```go
+import "github.com/lib/foo"
+
+l := mylogger.WithFields(logrus.Fields{
+ "library": "github.com/lib/foo",
+})
+
+f := foo.New(
+ foo.WithLogger(l),
+)
+```
diff --git a/vendor/github.com/go-log/log/log.go b/vendor/github.com/go-log/log/log.go
new file mode 100644
index 0000000..443864f
--- /dev/null
+++ b/vendor/github.com/go-log/log/log.go
@@ -0,0 +1,30 @@
+// Package log provides a log interface
+package log
+
+// Logger is a generic logging interface
+type Logger interface {
+ Log(v ...interface{})
+ Logf(format string, v ...interface{})
+}
+
+var (
+ // The global default logger
+ DefaultLogger Logger = &noOpLogger{}
+)
+
+// noOpLogger is used as a placeholder for the default logger
+type noOpLogger struct{}
+
+func (n *noOpLogger) Log(v ...interface{}) {}
+
+func (n *noOpLogger) Logf(format string, v ...interface{}) {}
+
+// Log logs using the default logger
+func Log(v ...interface{}) {
+ DefaultLogger.Log(v...)
+}
+
+// Logf logs formatted using the default logger
+func Logf(format string, v ...interface{}) {
+ DefaultLogger.Logf(format, v...)
+}
diff --git a/cmd/gost/vendor/github.com/golang/glog/LICENSE b/vendor/github.com/golang/glog/LICENSE
similarity index 100%
rename from cmd/gost/vendor/github.com/golang/glog/LICENSE
rename to vendor/github.com/golang/glog/LICENSE
diff --git a/cmd/gost/vendor/github.com/golang/glog/README b/vendor/github.com/golang/glog/README
similarity index 97%
rename from cmd/gost/vendor/github.com/golang/glog/README
rename to vendor/github.com/golang/glog/README
index 5f9c114..387b4eb 100644
--- a/cmd/gost/vendor/github.com/golang/glog/README
+++ b/vendor/github.com/golang/glog/README
@@ -5,7 +5,7 @@ Leveled execution logs for Go.
This is an efficient pure Go implementation of leveled logs in the
manner of the open source C++ package
- http://code.google.com/p/google-glog
+ https://github.com/google/glog
By binding methods to booleans it is possible to use the log package
without paying the expense of evaluating the arguments to the log.
diff --git a/cmd/gost/vendor/github.com/golang/glog/glog.go b/vendor/github.com/golang/glog/glog.go
similarity index 99%
rename from cmd/gost/vendor/github.com/golang/glog/glog.go
rename to vendor/github.com/golang/glog/glog.go
index 3e63fff..54bd7af 100644
--- a/cmd/gost/vendor/github.com/golang/glog/glog.go
+++ b/vendor/github.com/golang/glog/glog.go
@@ -676,7 +676,10 @@ func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoTo
}
}
data := buf.Bytes()
- if l.toStderr {
+ if !flag.Parsed() {
+ os.Stderr.Write([]byte("ERROR: logging before flag.Parse: "))
+ os.Stderr.Write(data)
+ } else if l.toStderr {
os.Stderr.Write(data)
} else {
if alsoToStderr || l.alsoToStderr || s >= l.stderrThreshold.get() {
diff --git a/cmd/gost/vendor/github.com/golang/glog/glog_file.go b/vendor/github.com/golang/glog/glog_file.go
similarity index 100%
rename from cmd/gost/vendor/github.com/golang/glog/glog_file.go
rename to vendor/github.com/golang/glog/glog_file.go
diff --git a/cmd/gost/vendor/github.com/hashicorp/golang-lru/2q.go b/vendor/github.com/hashicorp/golang-lru/2q.go
similarity index 100%
rename from cmd/gost/vendor/github.com/hashicorp/golang-lru/2q.go
rename to vendor/github.com/hashicorp/golang-lru/2q.go
diff --git a/cmd/gost/vendor/github.com/hashicorp/golang-lru/LICENSE b/vendor/github.com/hashicorp/golang-lru/LICENSE
similarity index 100%
rename from cmd/gost/vendor/github.com/hashicorp/golang-lru/LICENSE
rename to vendor/github.com/hashicorp/golang-lru/LICENSE
diff --git a/cmd/gost/vendor/github.com/hashicorp/golang-lru/README.md b/vendor/github.com/hashicorp/golang-lru/README.md
similarity index 100%
rename from cmd/gost/vendor/github.com/hashicorp/golang-lru/README.md
rename to vendor/github.com/hashicorp/golang-lru/README.md
diff --git a/cmd/gost/vendor/github.com/hashicorp/golang-lru/arc.go b/vendor/github.com/hashicorp/golang-lru/arc.go
similarity index 100%
rename from cmd/gost/vendor/github.com/hashicorp/golang-lru/arc.go
rename to vendor/github.com/hashicorp/golang-lru/arc.go
diff --git a/cmd/gost/vendor/github.com/hashicorp/golang-lru/lru.go b/vendor/github.com/hashicorp/golang-lru/lru.go
similarity index 100%
rename from cmd/gost/vendor/github.com/hashicorp/golang-lru/lru.go
rename to vendor/github.com/hashicorp/golang-lru/lru.go
diff --git a/cmd/gost/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go b/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go
similarity index 100%
rename from cmd/gost/vendor/github.com/hashicorp/golang-lru/simplelru/lru.go
rename to vendor/github.com/hashicorp/golang-lru/simplelru/lru.go
diff --git a/cmd/gost/vendor/github.com/klauspost/crc32/LICENSE b/vendor/github.com/klauspost/compress/LICENSE
similarity index 98%
rename from cmd/gost/vendor/github.com/klauspost/crc32/LICENSE
rename to vendor/github.com/klauspost/compress/LICENSE
index 4fd5963..7448756 100644
--- a/cmd/gost/vendor/github.com/klauspost/crc32/LICENSE
+++ b/vendor/github.com/klauspost/compress/LICENSE
@@ -1,5 +1,4 @@
Copyright (c) 2012 The Go Authors. All rights reserved.
-Copyright (c) 2015 Klaus Post
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/snappy/AUTHORS b/vendor/github.com/klauspost/compress/snappy/AUTHORS
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/snappy/AUTHORS
rename to vendor/github.com/klauspost/compress/snappy/AUTHORS
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/snappy/CONTRIBUTORS b/vendor/github.com/klauspost/compress/snappy/CONTRIBUTORS
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/snappy/CONTRIBUTORS
rename to vendor/github.com/klauspost/compress/snappy/CONTRIBUTORS
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/snappy/LICENSE b/vendor/github.com/klauspost/compress/snappy/LICENSE
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/snappy/LICENSE
rename to vendor/github.com/klauspost/compress/snappy/LICENSE
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/snappy/README b/vendor/github.com/klauspost/compress/snappy/README
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/snappy/README
rename to vendor/github.com/klauspost/compress/snappy/README
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/snappy/decode.go b/vendor/github.com/klauspost/compress/snappy/decode.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/snappy/decode.go
rename to vendor/github.com/klauspost/compress/snappy/decode.go
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/snappy/decode_amd64.go b/vendor/github.com/klauspost/compress/snappy/decode_amd64.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/snappy/decode_amd64.go
rename to vendor/github.com/klauspost/compress/snappy/decode_amd64.go
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/snappy/decode_amd64.s b/vendor/github.com/klauspost/compress/snappy/decode_amd64.s
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/snappy/decode_amd64.s
rename to vendor/github.com/klauspost/compress/snappy/decode_amd64.s
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/snappy/decode_other.go b/vendor/github.com/klauspost/compress/snappy/decode_other.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/snappy/decode_other.go
rename to vendor/github.com/klauspost/compress/snappy/decode_other.go
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/snappy/encode.go b/vendor/github.com/klauspost/compress/snappy/encode.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/snappy/encode.go
rename to vendor/github.com/klauspost/compress/snappy/encode.go
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/snappy/encode_amd64.go b/vendor/github.com/klauspost/compress/snappy/encode_amd64.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/snappy/encode_amd64.go
rename to vendor/github.com/klauspost/compress/snappy/encode_amd64.go
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/snappy/encode_amd64.s b/vendor/github.com/klauspost/compress/snappy/encode_amd64.s
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/snappy/encode_amd64.s
rename to vendor/github.com/klauspost/compress/snappy/encode_amd64.s
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/snappy/encode_other.go b/vendor/github.com/klauspost/compress/snappy/encode_other.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/snappy/encode_other.go
rename to vendor/github.com/klauspost/compress/snappy/encode_other.go
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/snappy/runbench.cmd b/vendor/github.com/klauspost/compress/snappy/runbench.cmd
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/snappy/runbench.cmd
rename to vendor/github.com/klauspost/compress/snappy/runbench.cmd
diff --git a/cmd/gost/vendor/github.com/klauspost/compress/snappy/snappy.go b/vendor/github.com/klauspost/compress/snappy/snappy.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/compress/snappy/snappy.go
rename to vendor/github.com/klauspost/compress/snappy/snappy.go
diff --git a/cmd/gost/vendor/github.com/klauspost/cpuid/LICENSE b/vendor/github.com/klauspost/cpuid/LICENSE
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/cpuid/LICENSE
rename to vendor/github.com/klauspost/cpuid/LICENSE
diff --git a/cmd/gost/vendor/github.com/klauspost/cpuid/README.md b/vendor/github.com/klauspost/cpuid/README.md
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/cpuid/README.md
rename to vendor/github.com/klauspost/cpuid/README.md
diff --git a/cmd/gost/vendor/github.com/klauspost/cpuid/cpuid.go b/vendor/github.com/klauspost/cpuid/cpuid.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/cpuid/cpuid.go
rename to vendor/github.com/klauspost/cpuid/cpuid.go
diff --git a/cmd/gost/vendor/github.com/klauspost/cpuid/cpuid_386.s b/vendor/github.com/klauspost/cpuid/cpuid_386.s
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/cpuid/cpuid_386.s
rename to vendor/github.com/klauspost/cpuid/cpuid_386.s
diff --git a/cmd/gost/vendor/github.com/klauspost/cpuid/cpuid_amd64.s b/vendor/github.com/klauspost/cpuid/cpuid_amd64.s
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/cpuid/cpuid_amd64.s
rename to vendor/github.com/klauspost/cpuid/cpuid_amd64.s
diff --git a/cmd/gost/vendor/github.com/klauspost/cpuid/detect_intel.go b/vendor/github.com/klauspost/cpuid/detect_intel.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/cpuid/detect_intel.go
rename to vendor/github.com/klauspost/cpuid/detect_intel.go
diff --git a/cmd/gost/vendor/github.com/klauspost/cpuid/detect_ref.go b/vendor/github.com/klauspost/cpuid/detect_ref.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/cpuid/detect_ref.go
rename to vendor/github.com/klauspost/cpuid/detect_ref.go
diff --git a/cmd/gost/vendor/github.com/klauspost/cpuid/generate.go b/vendor/github.com/klauspost/cpuid/generate.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/cpuid/generate.go
rename to vendor/github.com/klauspost/cpuid/generate.go
diff --git a/cmd/gost/vendor/github.com/klauspost/cpuid/private-gen.go b/vendor/github.com/klauspost/cpuid/private-gen.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/cpuid/private-gen.go
rename to vendor/github.com/klauspost/cpuid/private-gen.go
diff --git a/cmd/gost/vendor/github.com/klauspost/reedsolomon/LICENSE b/vendor/github.com/klauspost/reedsolomon/LICENSE
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/reedsolomon/LICENSE
rename to vendor/github.com/klauspost/reedsolomon/LICENSE
diff --git a/cmd/gost/vendor/github.com/klauspost/reedsolomon/README.md b/vendor/github.com/klauspost/reedsolomon/README.md
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/reedsolomon/README.md
rename to vendor/github.com/klauspost/reedsolomon/README.md
diff --git a/cmd/gost/vendor/github.com/klauspost/reedsolomon/appveyor.yml b/vendor/github.com/klauspost/reedsolomon/appveyor.yml
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/reedsolomon/appveyor.yml
rename to vendor/github.com/klauspost/reedsolomon/appveyor.yml
diff --git a/cmd/gost/vendor/github.com/klauspost/reedsolomon/galois.go b/vendor/github.com/klauspost/reedsolomon/galois.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/reedsolomon/galois.go
rename to vendor/github.com/klauspost/reedsolomon/galois.go
diff --git a/cmd/gost/vendor/github.com/klauspost/reedsolomon/galois_amd64.go b/vendor/github.com/klauspost/reedsolomon/galois_amd64.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/reedsolomon/galois_amd64.go
rename to vendor/github.com/klauspost/reedsolomon/galois_amd64.go
diff --git a/cmd/gost/vendor/github.com/klauspost/reedsolomon/galois_amd64.s b/vendor/github.com/klauspost/reedsolomon/galois_amd64.s
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/reedsolomon/galois_amd64.s
rename to vendor/github.com/klauspost/reedsolomon/galois_amd64.s
diff --git a/cmd/gost/vendor/github.com/klauspost/reedsolomon/galois_noasm.go b/vendor/github.com/klauspost/reedsolomon/galois_noasm.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/reedsolomon/galois_noasm.go
rename to vendor/github.com/klauspost/reedsolomon/galois_noasm.go
diff --git a/cmd/gost/vendor/github.com/klauspost/reedsolomon/gentables.go b/vendor/github.com/klauspost/reedsolomon/gentables.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/reedsolomon/gentables.go
rename to vendor/github.com/klauspost/reedsolomon/gentables.go
diff --git a/cmd/gost/vendor/github.com/klauspost/reedsolomon/inversion_tree.go b/vendor/github.com/klauspost/reedsolomon/inversion_tree.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/reedsolomon/inversion_tree.go
rename to vendor/github.com/klauspost/reedsolomon/inversion_tree.go
diff --git a/cmd/gost/vendor/github.com/klauspost/reedsolomon/matrix.go b/vendor/github.com/klauspost/reedsolomon/matrix.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/reedsolomon/matrix.go
rename to vendor/github.com/klauspost/reedsolomon/matrix.go
diff --git a/cmd/gost/vendor/github.com/klauspost/reedsolomon/reedsolomon.go b/vendor/github.com/klauspost/reedsolomon/reedsolomon.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/reedsolomon/reedsolomon.go
rename to vendor/github.com/klauspost/reedsolomon/reedsolomon.go
diff --git a/cmd/gost/vendor/github.com/klauspost/reedsolomon/streaming.go b/vendor/github.com/klauspost/reedsolomon/streaming.go
similarity index 100%
rename from cmd/gost/vendor/github.com/klauspost/reedsolomon/streaming.go
rename to vendor/github.com/klauspost/reedsolomon/streaming.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/aes12/LICENSE b/vendor/github.com/lucas-clemente/aes12/LICENSE
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/aes12/LICENSE
rename to vendor/github.com/lucas-clemente/aes12/LICENSE
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/aes12/Readme.md b/vendor/github.com/lucas-clemente/aes12/Readme.md
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/aes12/Readme.md
rename to vendor/github.com/lucas-clemente/aes12/Readme.md
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/aes12/aes_gcm.go b/vendor/github.com/lucas-clemente/aes12/aes_gcm.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/aes12/aes_gcm.go
rename to vendor/github.com/lucas-clemente/aes12/aes_gcm.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/aes12/asm_amd64.s b/vendor/github.com/lucas-clemente/aes12/asm_amd64.s
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/aes12/asm_amd64.s
rename to vendor/github.com/lucas-clemente/aes12/asm_amd64.s
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/aes12/block.go b/vendor/github.com/lucas-clemente/aes12/block.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/aes12/block.go
rename to vendor/github.com/lucas-clemente/aes12/block.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/aes12/cipher.go b/vendor/github.com/lucas-clemente/aes12/cipher.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/aes12/cipher.go
rename to vendor/github.com/lucas-clemente/aes12/cipher.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/aes12/cipher 2.go b/vendor/github.com/lucas-clemente/aes12/cipher_2.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/aes12/cipher 2.go
rename to vendor/github.com/lucas-clemente/aes12/cipher_2.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/aes12/cipher_amd64.go b/vendor/github.com/lucas-clemente/aes12/cipher_amd64.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/aes12/cipher_amd64.go
rename to vendor/github.com/lucas-clemente/aes12/cipher_amd64.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/aes12/cipher_generic.go b/vendor/github.com/lucas-clemente/aes12/cipher_generic.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/aes12/cipher_generic.go
rename to vendor/github.com/lucas-clemente/aes12/cipher_generic.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/aes12/const.go b/vendor/github.com/lucas-clemente/aes12/const.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/aes12/const.go
rename to vendor/github.com/lucas-clemente/aes12/const.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/aes12/gcm.go b/vendor/github.com/lucas-clemente/aes12/gcm.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/aes12/gcm.go
rename to vendor/github.com/lucas-clemente/aes12/gcm.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/aes12/gcm_amd64.s b/vendor/github.com/lucas-clemente/aes12/gcm_amd64.s
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/aes12/gcm_amd64.s
rename to vendor/github.com/lucas-clemente/aes12/gcm_amd64.s
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/aes12/xor.go b/vendor/github.com/lucas-clemente/aes12/xor.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/aes12/xor.go
rename to vendor/github.com/lucas-clemente/aes12/xor.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/fnv128a/LICENSE b/vendor/github.com/lucas-clemente/fnv128a/LICENSE
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/fnv128a/LICENSE
rename to vendor/github.com/lucas-clemente/fnv128a/LICENSE
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/fnv128a/README.md b/vendor/github.com/lucas-clemente/fnv128a/README.md
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/fnv128a/README.md
rename to vendor/github.com/lucas-clemente/fnv128a/README.md
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/fnv128a/fnv128a.go b/vendor/github.com/lucas-clemente/fnv128a/fnv128a.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/fnv128a/fnv128a.go
rename to vendor/github.com/lucas-clemente/fnv128a/fnv128a.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go-certificates/LICENSE b/vendor/github.com/lucas-clemente/quic-go-certificates/LICENSE
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go-certificates/LICENSE
rename to vendor/github.com/lucas-clemente/quic-go-certificates/LICENSE
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go-certificates/README.md b/vendor/github.com/lucas-clemente/quic-go-certificates/README.md
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go-certificates/README.md
rename to vendor/github.com/lucas-clemente/quic-go-certificates/README.md
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go-certificates/cert_set_2.go b/vendor/github.com/lucas-clemente/quic-go-certificates/cert_set_2.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go-certificates/cert_set_2.go
rename to vendor/github.com/lucas-clemente/quic-go-certificates/cert_set_2.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go-certificates/cert_set_3.go b/vendor/github.com/lucas-clemente/quic-go-certificates/cert_set_3.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go-certificates/cert_set_3.go
rename to vendor/github.com/lucas-clemente/quic-go-certificates/cert_set_3.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go-certificates/createCertSets.rb b/vendor/github.com/lucas-clemente/quic-go-certificates/createCertSets.rb
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go-certificates/createCertSets.rb
rename to vendor/github.com/lucas-clemente/quic-go-certificates/createCertSets.rb
diff --git a/vendor/github.com/lucas-clemente/quic-go/Changelog.md b/vendor/github.com/lucas-clemente/quic-go/Changelog.md
new file mode 100644
index 0000000..0b357ab
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/Changelog.md
@@ -0,0 +1,17 @@
+# Changelog
+
+## v0.6.0 (unreleased)
+
+- Added `quic.Config` options for maximal flow control windows
+- Add a `quic.Config` option for QUIC versions
+- Add a `quic.Config` option to request truncation of the connection ID from a server
+- Add a `quic.Config` option to configure the source address validation
+- Add a `quic.Config` option to configure the handshake timeout
+- Add a `quic.Config` option to configure keep-alive
+- Implement `net.Conn`-style deadlines for streams
+- Remove the `tls.Config` from the `quic.Config`. The `tls.Config` must now be passed to the `Dial` and `Listen` functions as a separate parameter. See the [Godoc](https://godoc.org/github.com/lucas-clemente/quic-go) for details.
+- Changed the log level environment variable to only accept strings ("DEBUG", "INFO", "ERROR"), see [the wiki](https://github.com/lucas-clemente/quic-go/wiki/Logging) for more details.
+- Rename the `h2quic.QuicRoundTripper` to `h2quic.RoundTripper`
+- Changed `h2quic.Server.Serve()` to accept a `net.PacketConn`
+- Drop support for Go 1.7.
+- Various bugfixes
diff --git a/vendor/github.com/lucas-clemente/quic-go/LICENSE b/vendor/github.com/lucas-clemente/quic-go/LICENSE
new file mode 100644
index 0000000..51378be
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2016 the quic-go authors & Google, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/README.md b/vendor/github.com/lucas-clemente/quic-go/README.md
similarity index 52%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/README.md
rename to vendor/github.com/lucas-clemente/quic-go/README.md
index 93fe544..6f3a11e 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/README.md
+++ b/vendor/github.com/lucas-clemente/quic-go/README.md
@@ -1,4 +1,4 @@
-# A QUIC server implementation in pure Go
+# A QUIC implementation in pure Go
@@ -7,51 +7,49 @@
[](https://ci.appveyor.com/project/lucas-clemente/quic-go/branch/master)
[](https://codecov.io/gh/lucas-clemente/quic-go/)
-quic-go is an implementation of the [QUIC](https://en.wikipedia.org/wiki/QUIC) protocol in Go. While we're not far from being feature complete, there's still work to do regarding performance and security. At the moment, we do not recommend use in production systems. We appreciate any feedback :)
+quic-go is an implementation of the [QUIC](https://en.wikipedia.org/wiki/QUIC) protocol in Go.
## Roadmap
-Done:
-
-- Basic protocol with support for QUIC version 34-36
-- HTTP/2 support
-- Crypto (RSA / ECDSA certificates, Curve25519 for key exchange, AES-GCM or Chacha20-Poly1305 as stream cipher)
-- Loss detection and retransmission (currently fast retransmission & RTO)
-- Flow Control
-- Congestion control using cubic
-
-Major TODOs:
-
-- Security, especially DOS protections
-- Performance
-- Better packet loss detection
-- Connection migration
-- QUIC client
+quic-go is compatible with the current version(s) of Google Chrome and QUIC as deployed on Google's servers. We're actively tracking the development of the Chrome code to ensure compatibility as the protocol evolves. In that process, we're dropping support for old QUIC versions.
+As Google's QUIC versions are expected to converge towards the [IETF QUIC draft](https://github.com/quicwg/base-drafts), quic-go will eventually implement that draft.
## Guides
-Installing deps:
+We currently support Go 1.8+.
- go get -t
+Installing and updating dependencies:
+
+ go get -t -u ./...
Running tests:
go test ./...
-Running the example server:
+### Running the example server
go run example/main.go -www /var/www/
Using the `quic_client` from chromium:
- quic_client --quic-version=32 --host=127.0.0.1 --port=6121 --v=1 https://quic.clemente.io
+ quic_client --host=127.0.0.1 --port=6121 --v=1 https://quic.clemente.io
Using Chrome:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir=/tmp/chrome --no-proxy-server --enable-quic --origin-to-force-quic-on=quic.clemente.io:443 --host-resolver-rules='MAP quic.clemente.io:443 127.0.0.1:6121' https://quic.clemente.io
+### QUIC without HTTP/2
+
+Take a look at [this echo example](example/echo/echo.go).
+
+### Using the example client
+
+ go run example/client/main.go https://clemente.io
+
## Usage
+### As a server
+
See the [example server](example/main.go) or try out [Caddy](https://github.com/mholt/caddy) (from version 0.9, [instructions here](https://github.com/mholt/caddy/wiki/QUIC)). Starting a QUIC server is very similar to the standard lib http in go:
```go
@@ -59,6 +57,16 @@ http.Handle("/", http.FileServer(http.Dir(wwwDir)))
h2quic.ListenAndServeQUIC("localhost:4242", "/path/to/cert/chain.pem", "/path/to/privkey.pem", nil)
```
-## Building on Windows
+### As a client
-Due to the low Windows timer resolution (see [StackOverflow question](http://stackoverflow.com/questions/37706834/high-resolution-timers-millisecond-precision-in-go-on-windows)) available with Go 1.6.x, some optimizations might not work when compiled with this version of the compiler. Please use Go 1.7 on Windows.
+See the [example client](example/client/main.go). Use a `h2quic.RoundTripper` as a `Transport` in a `http.Client`.
+
+```go
+http.Client{
+ Transport: &h2quic.RoundTripper{},
+}
+```
+
+## Contributing
+
+We are always happy to welcome new contributors! We have a number of self-contained issues that are suitable for first-time contributors, they are tagged with [want-help](https://github.com/lucas-clemente/quic-go/issues?q=is%3Aopen+is%3Aissue+label%3Awant-help). If you have any questions, please feel free to reach out by opening an issue or leaving a comment.
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/_gen.go b/vendor/github.com/lucas-clemente/quic-go/ackhandler/_gen.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/_gen.go
rename to vendor/github.com/lucas-clemente/quic-go/ackhandler/_gen.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/interfaces.go b/vendor/github.com/lucas-clemente/quic-go/ackhandler/interfaces.go
similarity index 76%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/interfaces.go
rename to vendor/github.com/lucas-clemente/quic-go/ackhandler/interfaces.go
index ee7ac59..e100264 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/interfaces.go
+++ b/vendor/github.com/lucas-clemente/quic-go/ackhandler/interfaces.go
@@ -9,27 +9,24 @@ import (
// SentPacketHandler handles ACKs received for outgoing packets
type SentPacketHandler interface {
+ // SentPacket may modify the packet
SentPacket(packet *Packet) error
ReceivedAck(ackFrame *frames.AckFrame, withPacketNumber protocol.PacketNumber, recvTime time.Time) error
+ SendingAllowed() bool
GetStopWaitingFrame(force bool) *frames.StopWaitingFrame
-
- MaybeQueueRTOs()
DequeuePacketForRetransmission() (packet *Packet)
-
- BytesInFlight() protocol.ByteCount
GetLeastUnacked() protocol.PacketNumber
- SendingAllowed() bool
- CheckForError() error
-
- TimeOfFirstRTO() time.Time
+ GetAlarmTimeout() time.Time
+ OnAlarm()
}
// ReceivedPacketHandler handles ACKs needed to send for incoming packets
type ReceivedPacketHandler interface {
- ReceivedPacket(packetNumber protocol.PacketNumber) error
+ ReceivedPacket(packetNumber protocol.PacketNumber, shouldInstigateAck bool) error
ReceivedStopWaiting(*frames.StopWaitingFrame) error
- GetAckFrame(dequeue bool) (*frames.AckFrame, error)
+ GetAlarmTimeout() time.Time
+ GetAckFrame() *frames.AckFrame
}
diff --git a/vendor/github.com/lucas-clemente/quic-go/ackhandler/packet.go b/vendor/github.com/lucas-clemente/quic-go/ackhandler/packet.go
new file mode 100644
index 0000000..e9dbf6a
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/ackhandler/packet.go
@@ -0,0 +1,34 @@
+package ackhandler
+
+import (
+ "time"
+
+ "github.com/lucas-clemente/quic-go/frames"
+ "github.com/lucas-clemente/quic-go/protocol"
+)
+
+// A Packet is a packet
+// +gen linkedlist
+type Packet struct {
+ PacketNumber protocol.PacketNumber
+ Frames []frames.Frame
+ Length protocol.ByteCount
+ EncryptionLevel protocol.EncryptionLevel
+
+ SendTime time.Time
+}
+
+// GetFramesForRetransmission gets all the frames for retransmission
+func (p *Packet) GetFramesForRetransmission() []frames.Frame {
+ var fs []frames.Frame
+ for _, frame := range p.Frames {
+ switch frame.(type) {
+ case *frames.AckFrame:
+ continue
+ case *frames.StopWaitingFrame:
+ continue
+ }
+ fs = append(fs, frame)
+ }
+ return fs
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/packet_linkedlist.go b/vendor/github.com/lucas-clemente/quic-go/ackhandler/packet_linkedlist.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/packet_linkedlist.go
rename to vendor/github.com/lucas-clemente/quic-go/ackhandler/packet_linkedlist.go
diff --git a/vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_handler.go b/vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_handler.go
new file mode 100644
index 0000000..c5e9dc2
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_handler.go
@@ -0,0 +1,139 @@
+package ackhandler
+
+import (
+ "errors"
+ "time"
+
+ "github.com/lucas-clemente/quic-go/frames"
+ "github.com/lucas-clemente/quic-go/protocol"
+)
+
+var errInvalidPacketNumber = errors.New("ReceivedPacketHandler: Invalid packet number")
+
+type receivedPacketHandler struct {
+ largestObserved protocol.PacketNumber
+ ignorePacketsBelow protocol.PacketNumber
+ largestObservedReceivedTime time.Time
+
+ packetHistory *receivedPacketHistory
+
+ ackSendDelay time.Duration
+
+ packetsReceivedSinceLastAck int
+ retransmittablePacketsReceivedSinceLastAck int
+ ackQueued bool
+ ackAlarm time.Time
+ lastAck *frames.AckFrame
+}
+
+// NewReceivedPacketHandler creates a new receivedPacketHandler
+func NewReceivedPacketHandler() ReceivedPacketHandler {
+ return &receivedPacketHandler{
+ packetHistory: newReceivedPacketHistory(),
+ ackSendDelay: protocol.AckSendDelay,
+ }
+}
+
+func (h *receivedPacketHandler) ReceivedPacket(packetNumber protocol.PacketNumber, shouldInstigateAck bool) error {
+ if packetNumber == 0 {
+ return errInvalidPacketNumber
+ }
+
+ if packetNumber > h.ignorePacketsBelow {
+ if err := h.packetHistory.ReceivedPacket(packetNumber); err != nil {
+ return err
+ }
+ }
+
+ if packetNumber > h.largestObserved {
+ h.largestObserved = packetNumber
+ h.largestObservedReceivedTime = time.Now()
+ }
+
+ h.maybeQueueAck(packetNumber, shouldInstigateAck)
+ return nil
+}
+
+func (h *receivedPacketHandler) ReceivedStopWaiting(f *frames.StopWaitingFrame) error {
+ // ignore if StopWaiting is unneeded, because we already received a StopWaiting with a higher LeastUnacked
+ if h.ignorePacketsBelow >= f.LeastUnacked {
+ return nil
+ }
+
+ h.ignorePacketsBelow = f.LeastUnacked - 1
+
+ h.packetHistory.DeleteBelow(f.LeastUnacked)
+ return nil
+}
+
+func (h *receivedPacketHandler) maybeQueueAck(packetNumber protocol.PacketNumber, shouldInstigateAck bool) {
+ h.packetsReceivedSinceLastAck++
+
+ if shouldInstigateAck {
+ h.retransmittablePacketsReceivedSinceLastAck++
+ }
+
+ // always ack the first packet
+ if h.lastAck == nil {
+ h.ackQueued = true
+ }
+
+ // Always send an ack every 20 packets in order to allow the peer to discard
+ // information from the SentPacketManager and provide an RTT measurement.
+ if h.packetsReceivedSinceLastAck >= protocol.MaxPacketsReceivedBeforeAckSend {
+ h.ackQueued = true
+ }
+
+ // if the packet number is smaller than the largest acked packet, it must have been reported missing with the last ACK
+ // note that it cannot be a duplicate because they're already filtered out by ReceivedPacket()
+ if h.lastAck != nil && packetNumber < h.lastAck.LargestAcked {
+ h.ackQueued = true
+ }
+
+ // check if a new missing range above the previously was created
+ if h.lastAck != nil && h.packetHistory.GetHighestAckRange().FirstPacketNumber > h.lastAck.LargestAcked {
+ h.ackQueued = true
+ }
+
+ if !h.ackQueued && shouldInstigateAck {
+ if h.retransmittablePacketsReceivedSinceLastAck >= protocol.RetransmittablePacketsBeforeAck {
+ h.ackQueued = true
+ } else {
+ if h.ackAlarm.IsZero() {
+ h.ackAlarm = time.Now().Add(h.ackSendDelay)
+ }
+ }
+ }
+
+ if h.ackQueued {
+ // cancel the ack alarm
+ h.ackAlarm = time.Time{}
+ }
+}
+
+func (h *receivedPacketHandler) GetAckFrame() *frames.AckFrame {
+ if !h.ackQueued && (h.ackAlarm.IsZero() || h.ackAlarm.After(time.Now())) {
+ return nil
+ }
+
+ ackRanges := h.packetHistory.GetAckRanges()
+ ack := &frames.AckFrame{
+ LargestAcked: h.largestObserved,
+ LowestAcked: ackRanges[len(ackRanges)-1].FirstPacketNumber,
+ PacketReceivedTime: h.largestObservedReceivedTime,
+ }
+
+ if len(ackRanges) > 1 {
+ ack.AckRanges = ackRanges
+ }
+
+ h.lastAck = ack
+ h.ackAlarm = time.Time{}
+ h.ackQueued = false
+ h.packetsReceivedSinceLastAck = 0
+ h.retransmittablePacketsReceivedSinceLastAck = 0
+
+ return ack
+}
+
+func (h *receivedPacketHandler) GetAlarmTimeout() time.Time { return h.ackAlarm }
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_history.go b/vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_history.go
similarity index 50%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_history.go
rename to vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_history.go
index 14bb08f..791dec1 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_history.go
+++ b/vendor/github.com/lucas-clemente/quic-go/ackhandler/received_packet_history.go
@@ -1,40 +1,54 @@
package ackhandler
import (
- "sync"
-
"github.com/lucas-clemente/quic-go/frames"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
+ "github.com/lucas-clemente/quic-go/qerr"
)
type receivedPacketHistory struct {
ranges *utils.PacketIntervalList
- mutex sync.RWMutex
+ // the map is used as a replacement for a set here. The bool is always supposed to be set to true
+ receivedPacketNumbers map[protocol.PacketNumber]bool
+ lowestInReceivedPacketNumbers protocol.PacketNumber
}
+var (
+ errTooManyOutstandingReceivedAckRanges = qerr.Error(qerr.TooManyOutstandingReceivedPackets, "Too many outstanding received ACK ranges")
+ errTooManyOutstandingReceivedPackets = qerr.Error(qerr.TooManyOutstandingReceivedPackets, "Too many outstanding received packets")
+)
+
// newReceivedPacketHistory creates a new received packet history
func newReceivedPacketHistory() *receivedPacketHistory {
return &receivedPacketHistory{
- ranges: utils.NewPacketIntervalList(),
+ ranges: utils.NewPacketIntervalList(),
+ receivedPacketNumbers: make(map[protocol.PacketNumber]bool),
}
}
// ReceivedPacket registers a packet with PacketNumber p and updates the ranges
-func (h *receivedPacketHistory) ReceivedPacket(p protocol.PacketNumber) {
- h.mutex.Lock()
- defer h.mutex.Unlock()
+func (h *receivedPacketHistory) ReceivedPacket(p protocol.PacketNumber) error {
+ if h.ranges.Len() >= protocol.MaxTrackedReceivedAckRanges {
+ return errTooManyOutstandingReceivedAckRanges
+ }
+
+ if len(h.receivedPacketNumbers) >= protocol.MaxTrackedReceivedPackets {
+ return errTooManyOutstandingReceivedPackets
+ }
+
+ h.receivedPacketNumbers[p] = true
if h.ranges.Len() == 0 {
h.ranges.PushBack(utils.PacketInterval{Start: p, End: p})
- return
+ return nil
}
for el := h.ranges.Back(); el != nil; el = el.Prev() {
// p already included in an existing range. Nothing to do here
if p >= el.Value.Start && p <= el.Value.End {
- return
+ return nil
}
var rangeExtended bool
@@ -52,46 +66,61 @@ func (h *receivedPacketHistory) ReceivedPacket(p protocol.PacketNumber) {
if prev != nil && prev.Value.End+1 == el.Value.Start { // merge two ranges
prev.Value.End = el.Value.End
h.ranges.Remove(el)
- return
+ return nil
}
- return // if the two ranges were not merge, we're done here
+ return nil // if the two ranges were not merge, we're done here
}
// create a new range at the end
if p > el.Value.End {
h.ranges.InsertAfter(utils.PacketInterval{Start: p, End: p}, el)
- return
+ return nil
}
}
// create a new range at the beginning
h.ranges.InsertBefore(utils.PacketInterval{Start: p, End: p}, h.ranges.Front())
+
+ return nil
}
+// DeleteBelow deletes all entries below the leastUnacked packet number
func (h *receivedPacketHistory) DeleteBelow(leastUnacked protocol.PacketNumber) {
- h.mutex.Lock()
- defer h.mutex.Unlock()
+ h.lowestInReceivedPacketNumbers = utils.MaxPacketNumber(h.lowestInReceivedPacketNumbers, leastUnacked)
nextEl := h.ranges.Front()
for el := h.ranges.Front(); nextEl != nil; el = nextEl {
nextEl = el.Next()
if leastUnacked > el.Value.Start && leastUnacked <= el.Value.End {
+ for i := el.Value.Start; i < leastUnacked; i++ { // adjust start value of a range
+ delete(h.receivedPacketNumbers, i)
+ }
el.Value.Start = leastUnacked
- }
- if el.Value.End < leastUnacked { // delete a whole range
+ } else if el.Value.End < leastUnacked { // delete a whole range
+ for i := el.Value.Start; i <= el.Value.End; i++ {
+ delete(h.receivedPacketNumbers, i)
+ }
h.ranges.Remove(el)
- } else {
+ } else { // no ranges affected. Nothing to do
return
}
}
}
+// IsDuplicate determines if a packet should be regarded as a duplicate packet
+// note that after receiving a StopWaitingFrame, all packets below the LeastUnacked should be regarded as duplicates, even if the packet was just delayed
+func (h *receivedPacketHistory) IsDuplicate(p protocol.PacketNumber) bool {
+ if p < h.lowestInReceivedPacketNumbers {
+ return true
+ }
+
+ _, ok := h.receivedPacketNumbers[p]
+ return ok
+}
+
// GetAckRanges gets a slice of all AckRanges that can be used in an AckFrame
func (h *receivedPacketHistory) GetAckRanges() []frames.AckRange {
- h.mutex.RLock()
- defer h.mutex.RUnlock()
-
if h.ranges.Len() == 0 {
return nil
}
@@ -104,3 +133,13 @@ func (h *receivedPacketHistory) GetAckRanges() []frames.AckRange {
return ackRanges
}
+
+func (h *receivedPacketHistory) GetHighestAckRange() frames.AckRange {
+ ackRange := frames.AckRange{}
+ if h.ranges.Len() > 0 {
+ r := h.ranges.Back().Value
+ ackRange.FirstPacketNumber = r.Start
+ ackRange.LastPacketNumber = r.End
+ }
+ return ackRange
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/ackhandler/retransmittable.go b/vendor/github.com/lucas-clemente/quic-go/ackhandler/retransmittable.go
new file mode 100644
index 0000000..17437b8
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/ackhandler/retransmittable.go
@@ -0,0 +1,38 @@
+package ackhandler
+
+import (
+ "github.com/lucas-clemente/quic-go/frames"
+)
+
+// Returns a new slice with all non-retransmittable frames deleted.
+func stripNonRetransmittableFrames(fs []frames.Frame) []frames.Frame {
+ res := make([]frames.Frame, 0, len(fs))
+ for _, f := range fs {
+ if IsFrameRetransmittable(f) {
+ res = append(res, f)
+ }
+ }
+ return res
+}
+
+// IsFrameRetransmittable returns true if the frame should be retransmitted.
+func IsFrameRetransmittable(f frames.Frame) bool {
+ switch f.(type) {
+ case *frames.StopWaitingFrame:
+ return false
+ case *frames.AckFrame:
+ return false
+ default:
+ return true
+ }
+}
+
+// HasRetransmittableFrames returns true if at least one frame is retransmittable.
+func HasRetransmittableFrames(fs []frames.Frame) bool {
+ for _, f := range fs {
+ if IsFrameRetransmittable(f) {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/ackhandler/sent_packet_handler.go b/vendor/github.com/lucas-clemente/quic-go/ackhandler/sent_packet_handler.go
new file mode 100644
index 0000000..300b665
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/ackhandler/sent_packet_handler.go
@@ -0,0 +1,403 @@
+package ackhandler
+
+import (
+ "errors"
+ "fmt"
+ "time"
+
+ "github.com/lucas-clemente/quic-go/congestion"
+ "github.com/lucas-clemente/quic-go/frames"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+ "github.com/lucas-clemente/quic-go/qerr"
+)
+
+const (
+ // Maximum reordering in time space before time based loss detection considers a packet lost.
+ // In fraction of an RTT.
+ timeReorderingFraction = 1.0 / 8
+ // defaultRTOTimeout is the RTO time on new connections
+ defaultRTOTimeout = 500 * time.Millisecond
+ // Minimum time in the future an RTO alarm may be set for.
+ minRTOTimeout = 200 * time.Millisecond
+ // maxRTOTimeout is the maximum RTO time
+ maxRTOTimeout = 60 * time.Second
+)
+
+var (
+ // ErrDuplicateOrOutOfOrderAck occurs when a duplicate or an out-of-order ACK is received
+ ErrDuplicateOrOutOfOrderAck = errors.New("SentPacketHandler: Duplicate or out-of-order ACK")
+ // ErrTooManyTrackedSentPackets occurs when the sentPacketHandler has to keep track of too many packets
+ ErrTooManyTrackedSentPackets = errors.New("Too many outstanding non-acked and non-retransmitted packets")
+ // ErrAckForSkippedPacket occurs when the client sent an ACK for a packet number that we intentionally skipped
+ ErrAckForSkippedPacket = qerr.Error(qerr.InvalidAckData, "Received an ACK for a skipped packet number")
+ errAckForUnsentPacket = qerr.Error(qerr.InvalidAckData, "Received ACK for an unsent package")
+)
+
+var errPacketNumberNotIncreasing = errors.New("Already sent a packet with a higher packet number")
+
+type sentPacketHandler struct {
+ lastSentPacketNumber protocol.PacketNumber
+ skippedPackets []protocol.PacketNumber
+
+ LargestAcked protocol.PacketNumber
+
+ largestReceivedPacketWithAck protocol.PacketNumber
+
+ packetHistory *PacketList
+ stopWaitingManager stopWaitingManager
+
+ retransmissionQueue []*Packet
+
+ bytesInFlight protocol.ByteCount
+
+ congestion congestion.SendAlgorithm
+ rttStats *congestion.RTTStats
+
+ // The number of times an RTO has been sent without receiving an ack.
+ rtoCount uint32
+
+ // The time at which the next packet will be considered lost based on early transmit or exceeding the reordering window in time.
+ lossTime time.Time
+
+ // The alarm timeout
+ alarm time.Time
+}
+
+// NewSentPacketHandler creates a new sentPacketHandler
+func NewSentPacketHandler(rttStats *congestion.RTTStats) SentPacketHandler {
+ congestion := congestion.NewCubicSender(
+ congestion.DefaultClock{},
+ rttStats,
+ false, /* don't use reno since chromium doesn't (why?) */
+ protocol.InitialCongestionWindow,
+ protocol.DefaultMaxCongestionWindow,
+ )
+
+ return &sentPacketHandler{
+ packetHistory: NewPacketList(),
+ stopWaitingManager: stopWaitingManager{},
+ rttStats: rttStats,
+ congestion: congestion,
+ }
+}
+
+func (h *sentPacketHandler) largestInOrderAcked() protocol.PacketNumber {
+ if f := h.packetHistory.Front(); f != nil {
+ return f.Value.PacketNumber - 1
+ }
+ return h.LargestAcked
+}
+
+func (h *sentPacketHandler) SentPacket(packet *Packet) error {
+ if packet.PacketNumber <= h.lastSentPacketNumber {
+ return errPacketNumberNotIncreasing
+ }
+
+ if protocol.PacketNumber(len(h.retransmissionQueue)+h.packetHistory.Len()+1) > protocol.MaxTrackedSentPackets {
+ return ErrTooManyTrackedSentPackets
+ }
+
+ for p := h.lastSentPacketNumber + 1; p < packet.PacketNumber; p++ {
+ h.skippedPackets = append(h.skippedPackets, p)
+
+ if len(h.skippedPackets) > protocol.MaxTrackedSkippedPackets {
+ h.skippedPackets = h.skippedPackets[1:]
+ }
+ }
+
+ h.lastSentPacketNumber = packet.PacketNumber
+ now := time.Now()
+
+ packet.Frames = stripNonRetransmittableFrames(packet.Frames)
+ isRetransmittable := len(packet.Frames) != 0
+
+ if isRetransmittable {
+ packet.SendTime = now
+ h.bytesInFlight += packet.Length
+ h.packetHistory.PushBack(*packet)
+ }
+
+ h.congestion.OnPacketSent(
+ now,
+ h.bytesInFlight,
+ packet.PacketNumber,
+ packet.Length,
+ isRetransmittable,
+ )
+
+ h.updateLossDetectionAlarm()
+ return nil
+}
+
+func (h *sentPacketHandler) ReceivedAck(ackFrame *frames.AckFrame, withPacketNumber protocol.PacketNumber, rcvTime time.Time) error {
+ if ackFrame.LargestAcked > h.lastSentPacketNumber {
+ return errAckForUnsentPacket
+ }
+
+ // duplicate or out-of-order ACK
+ if withPacketNumber <= h.largestReceivedPacketWithAck {
+ return ErrDuplicateOrOutOfOrderAck
+ }
+ h.largestReceivedPacketWithAck = withPacketNumber
+
+ // ignore repeated ACK (ACKs that don't have a higher LargestAcked than the last ACK)
+ if ackFrame.LargestAcked <= h.largestInOrderAcked() {
+ return nil
+ }
+ h.LargestAcked = ackFrame.LargestAcked
+
+ if h.skippedPacketsAcked(ackFrame) {
+ return ErrAckForSkippedPacket
+ }
+
+ rttUpdated := h.maybeUpdateRTT(ackFrame.LargestAcked, ackFrame.DelayTime, rcvTime)
+
+ if rttUpdated {
+ h.congestion.MaybeExitSlowStart()
+ }
+
+ ackedPackets, err := h.determineNewlyAckedPackets(ackFrame)
+ if err != nil {
+ return err
+ }
+
+ if len(ackedPackets) > 0 {
+ for _, p := range ackedPackets {
+ h.onPacketAcked(p)
+ h.congestion.OnPacketAcked(p.Value.PacketNumber, p.Value.Length, h.bytesInFlight)
+ }
+ }
+
+ h.detectLostPackets()
+ h.updateLossDetectionAlarm()
+
+ h.garbageCollectSkippedPackets()
+ h.stopWaitingManager.ReceivedAck(ackFrame)
+
+ return nil
+}
+
+func (h *sentPacketHandler) determineNewlyAckedPackets(ackFrame *frames.AckFrame) ([]*PacketElement, error) {
+ var ackedPackets []*PacketElement
+ ackRangeIndex := 0
+ for el := h.packetHistory.Front(); el != nil; el = el.Next() {
+ packet := el.Value
+ packetNumber := packet.PacketNumber
+
+ // Ignore packets below the LowestAcked
+ if packetNumber < ackFrame.LowestAcked {
+ continue
+ }
+ // Break after LargestAcked is reached
+ if packetNumber > ackFrame.LargestAcked {
+ break
+ }
+
+ if ackFrame.HasMissingRanges() {
+ ackRange := ackFrame.AckRanges[len(ackFrame.AckRanges)-1-ackRangeIndex]
+
+ for packetNumber > ackRange.LastPacketNumber && ackRangeIndex < len(ackFrame.AckRanges)-1 {
+ ackRangeIndex++
+ ackRange = ackFrame.AckRanges[len(ackFrame.AckRanges)-1-ackRangeIndex]
+ }
+
+ if packetNumber >= ackRange.FirstPacketNumber { // packet i contained in ACK range
+ if packetNumber > ackRange.LastPacketNumber {
+ return nil, fmt.Errorf("BUG: ackhandler would have acked wrong packet 0x%x, while evaluating range 0x%x -> 0x%x", packetNumber, ackRange.FirstPacketNumber, ackRange.LastPacketNumber)
+ }
+ ackedPackets = append(ackedPackets, el)
+ }
+ } else {
+ ackedPackets = append(ackedPackets, el)
+ }
+ }
+
+ return ackedPackets, nil
+}
+
+func (h *sentPacketHandler) maybeUpdateRTT(largestAcked protocol.PacketNumber, ackDelay time.Duration, rcvTime time.Time) bool {
+ for el := h.packetHistory.Front(); el != nil; el = el.Next() {
+ packet := el.Value
+ if packet.PacketNumber == largestAcked {
+ h.rttStats.UpdateRTT(rcvTime.Sub(packet.SendTime), ackDelay, time.Now())
+ return true
+ }
+ // Packets are sorted by number, so we can stop searching
+ if packet.PacketNumber > largestAcked {
+ break
+ }
+ }
+ return false
+}
+
+func (h *sentPacketHandler) updateLossDetectionAlarm() {
+ // Cancel the alarm if no packets are outstanding
+ if h.packetHistory.Len() == 0 {
+ h.alarm = time.Time{}
+ return
+ }
+
+ // TODO(#496): Handle handshake packets separately
+ // TODO(#497): TLP
+ if !h.lossTime.IsZero() {
+ // Early retransmit timer or time loss detection.
+ h.alarm = h.lossTime
+ } else {
+ // RTO
+ h.alarm = time.Now().Add(h.computeRTOTimeout())
+ }
+}
+
+func (h *sentPacketHandler) detectLostPackets() {
+ h.lossTime = time.Time{}
+ now := time.Now()
+
+ maxRTT := float64(utils.MaxDuration(h.rttStats.LatestRTT(), h.rttStats.SmoothedRTT()))
+ delayUntilLost := time.Duration((1.0 + timeReorderingFraction) * maxRTT)
+
+ var lostPackets []*PacketElement
+ for el := h.packetHistory.Front(); el != nil; el = el.Next() {
+ packet := el.Value
+
+ if packet.PacketNumber > h.LargestAcked {
+ break
+ }
+
+ timeSinceSent := now.Sub(packet.SendTime)
+ if timeSinceSent > delayUntilLost {
+ lostPackets = append(lostPackets, el)
+ } else if h.lossTime.IsZero() {
+ // Note: This conditional is only entered once per call
+ h.lossTime = now.Add(delayUntilLost - timeSinceSent)
+ }
+ }
+
+ if len(lostPackets) > 0 {
+ for _, p := range lostPackets {
+ h.queuePacketForRetransmission(p)
+ h.congestion.OnPacketLost(p.Value.PacketNumber, p.Value.Length, h.bytesInFlight)
+ }
+ }
+}
+
+func (h *sentPacketHandler) OnAlarm() {
+ // TODO(#496): Handle handshake packets separately
+ // TODO(#497): TLP
+ if !h.lossTime.IsZero() {
+ // Early retransmit or time loss detection
+ h.detectLostPackets()
+ } else {
+ // RTO
+ h.retransmitOldestTwoPackets()
+ h.rtoCount++
+ }
+
+ h.updateLossDetectionAlarm()
+}
+
+func (h *sentPacketHandler) GetAlarmTimeout() time.Time {
+ return h.alarm
+}
+
+func (h *sentPacketHandler) onPacketAcked(packetElement *PacketElement) {
+ h.bytesInFlight -= packetElement.Value.Length
+ h.rtoCount = 0
+ // TODO(#497): h.tlpCount = 0
+ h.packetHistory.Remove(packetElement)
+}
+
+func (h *sentPacketHandler) DequeuePacketForRetransmission() *Packet {
+ if len(h.retransmissionQueue) == 0 {
+ return nil
+ }
+ packet := h.retransmissionQueue[0]
+ // Shift the slice and don't retain anything that isn't needed.
+ copy(h.retransmissionQueue, h.retransmissionQueue[1:])
+ h.retransmissionQueue[len(h.retransmissionQueue)-1] = nil
+ h.retransmissionQueue = h.retransmissionQueue[:len(h.retransmissionQueue)-1]
+ return packet
+}
+
+func (h *sentPacketHandler) GetLeastUnacked() protocol.PacketNumber {
+ return h.largestInOrderAcked() + 1
+}
+
+func (h *sentPacketHandler) GetStopWaitingFrame(force bool) *frames.StopWaitingFrame {
+ return h.stopWaitingManager.GetStopWaitingFrame(force)
+}
+
+func (h *sentPacketHandler) SendingAllowed() bool {
+ congestionLimited := h.bytesInFlight > h.congestion.GetCongestionWindow()
+ maxTrackedLimited := protocol.PacketNumber(len(h.retransmissionQueue)+h.packetHistory.Len()) >= protocol.MaxTrackedSentPackets
+ if congestionLimited {
+ utils.Debugf("Congestion limited: bytes in flight %d, window %d",
+ h.bytesInFlight,
+ h.congestion.GetCongestionWindow())
+ }
+ // Workaround for #555:
+ // Always allow sending of retransmissions. This should probably be limited
+ // to RTOs, but we currently don't have a nice way of distinguishing them.
+ haveRetransmissions := len(h.retransmissionQueue) > 0
+ return !maxTrackedLimited && (!congestionLimited || haveRetransmissions)
+}
+
+func (h *sentPacketHandler) retransmitOldestTwoPackets() {
+ if p := h.packetHistory.Front(); p != nil {
+ h.queueRTO(p)
+ }
+ if p := h.packetHistory.Front(); p != nil {
+ h.queueRTO(p)
+ }
+}
+
+func (h *sentPacketHandler) queueRTO(el *PacketElement) {
+ packet := &el.Value
+ utils.Debugf(
+ "\tQueueing packet 0x%x for retransmission (RTO), %d outstanding",
+ packet.PacketNumber,
+ h.packetHistory.Len(),
+ )
+ h.queuePacketForRetransmission(el)
+ h.congestion.OnPacketLost(packet.PacketNumber, packet.Length, h.bytesInFlight)
+ h.congestion.OnRetransmissionTimeout(true)
+}
+
+func (h *sentPacketHandler) queuePacketForRetransmission(packetElement *PacketElement) {
+ packet := &packetElement.Value
+ h.bytesInFlight -= packet.Length
+ h.retransmissionQueue = append(h.retransmissionQueue, packet)
+ h.packetHistory.Remove(packetElement)
+ h.stopWaitingManager.QueuedRetransmissionForPacketNumber(packet.PacketNumber)
+}
+
+func (h *sentPacketHandler) computeRTOTimeout() time.Duration {
+ rto := h.congestion.RetransmissionDelay()
+ if rto == 0 {
+ rto = defaultRTOTimeout
+ }
+ rto = utils.MaxDuration(rto, minRTOTimeout)
+ // Exponential backoff
+ rto = rto << h.rtoCount
+ return utils.MinDuration(rto, maxRTOTimeout)
+}
+
+func (h *sentPacketHandler) skippedPacketsAcked(ackFrame *frames.AckFrame) bool {
+ for _, p := range h.skippedPackets {
+ if ackFrame.AcksPacket(p) {
+ return true
+ }
+ }
+ return false
+}
+
+func (h *sentPacketHandler) garbageCollectSkippedPackets() {
+ lioa := h.largestInOrderAcked()
+ deleteIndex := 0
+ for i, p := range h.skippedPackets {
+ if p <= lioa {
+ deleteIndex = i + 1
+ }
+ }
+ h.skippedPackets = h.skippedPackets[deleteIndex:]
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/stop_waiting_manager.go b/vendor/github.com/lucas-clemente/quic-go/ackhandler/stop_waiting_manager.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/ackhandler/stop_waiting_manager.go
rename to vendor/github.com/lucas-clemente/quic-go/ackhandler/stop_waiting_manager.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/appveyor.yml b/vendor/github.com/lucas-clemente/quic-go/appveyor.yml
similarity index 76%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/appveyor.yml
rename to vendor/github.com/lucas-clemente/quic-go/appveyor.yml
index 837facc..8a3c907 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/appveyor.yml
+++ b/vendor/github.com/lucas-clemente/quic-go/appveyor.yml
@@ -5,6 +5,7 @@ os: Windows Server 2012 R2
environment:
GOPATH: c:\gopath
CGO_ENABLED: 0
+ TIMESCALE_FACTOR: 20
matrix:
- GOARCH: 386
- GOARCH: amd64
@@ -13,8 +14,8 @@ clone_folder: c:\gopath\src\github.com\lucas-clemente\quic-go
install:
- rmdir c:\go /s /q
- - appveyor DownloadFile https://storage.googleapis.com/golang/go1.7.1.windows-amd64.zip
- - 7z x go1.7.1.windows-amd64.zip -y -oC:\ > NUL
+ - appveyor DownloadFile https://storage.googleapis.com/golang/go1.8.3.windows-amd64.zip
+ - 7z x go1.8.3.windows-amd64.zip -y -oC:\ > NUL
- set PATH=%PATH%;%GOPATH%\bin\windows_%GOARCH%;%GOPATH%\bin
- echo %PATH%
- echo %GOPATH%
@@ -27,7 +28,8 @@ install:
build_script:
- rm -r integrationtests
- - ginkgo -r --randomizeAllSpecs --randomizeSuites --trace --progress
+ - ginkgo -r --randomizeAllSpecs --randomizeSuites --trace --progress -skipPackage benchmark
+ - ginkgo --randomizeAllSpecs --randomizeSuites --trace --progress benchmark -- -samples=1
test: off
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/buffer_pool.go b/vendor/github.com/lucas-clemente/quic-go/buffer_pool.go
similarity index 76%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/buffer_pool.go
rename to vendor/github.com/lucas-clemente/quic-go/buffer_pool.go
index bb4feb3..f592d47 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/buffer_pool.go
+++ b/vendor/github.com/lucas-clemente/quic-go/buffer_pool.go
@@ -13,7 +13,7 @@ func getPacketBuffer() []byte {
}
func putPacketBuffer(buf []byte) {
- if cap(buf) != int(protocol.MaxPacketSize) {
+ if cap(buf) != int(protocol.MaxReceivePacketSize) {
panic("putPacketBuffer called with packet of wrong size!")
}
bufferPool.Put(buf[:0])
@@ -21,6 +21,6 @@ func putPacketBuffer(buf []byte) {
func init() {
bufferPool.New = func() interface{} {
- return make([]byte, 0, protocol.MaxPacketSize)
+ return make([]byte, 0, protocol.MaxReceivePacketSize)
}
}
diff --git a/vendor/github.com/lucas-clemente/quic-go/client.go b/vendor/github.com/lucas-clemente/quic-go/client.go
new file mode 100644
index 0000000..2e18de8
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/client.go
@@ -0,0 +1,335 @@
+package quic
+
+import (
+ "bytes"
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "net"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+ "github.com/lucas-clemente/quic-go/qerr"
+)
+
+type client struct {
+ mutex sync.Mutex
+ listenErr error
+
+ conn connection
+ hostname string
+
+ errorChan chan struct{}
+ handshakeChan <-chan handshakeEvent
+
+ tlsConf *tls.Config
+ config *Config
+ versionNegotiated bool // has version negotiation completed yet
+
+ connectionID protocol.ConnectionID
+ version protocol.VersionNumber
+
+ session packetHandler
+}
+
+var (
+ errCloseSessionForNewVersion = errors.New("closing session in order to recreate it with a new version")
+)
+
+// DialAddr establishes a new QUIC connection to a server.
+// The hostname for SNI is taken from the given address.
+func DialAddr(addr string, tlsConf *tls.Config, config *Config) (Session, error) {
+ udpAddr, err := net.ResolveUDPAddr("udp", addr)
+ if err != nil {
+ return nil, err
+ }
+ udpConn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
+ if err != nil {
+ return nil, err
+ }
+ return Dial(udpConn, udpAddr, addr, tlsConf, config)
+}
+
+// DialAddrNonFWSecure establishes a new QUIC connection to a server.
+// The hostname for SNI is taken from the given address.
+func DialAddrNonFWSecure(
+ addr string,
+ tlsConf *tls.Config,
+ config *Config,
+) (NonFWSession, error) {
+ udpAddr, err := net.ResolveUDPAddr("udp", addr)
+ if err != nil {
+ return nil, err
+ }
+ udpConn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
+ if err != nil {
+ return nil, err
+ }
+ return DialNonFWSecure(udpConn, udpAddr, addr, tlsConf, config)
+}
+
+// DialNonFWSecure establishes a new non-forward-secure QUIC connection to a server using a net.PacketConn.
+// The host parameter is used for SNI.
+func DialNonFWSecure(
+ pconn net.PacketConn,
+ remoteAddr net.Addr,
+ host string,
+ tlsConf *tls.Config,
+ config *Config,
+) (NonFWSession, error) {
+ connID, err := utils.GenerateConnectionID()
+ if err != nil {
+ return nil, err
+ }
+
+ var hostname string
+ if tlsConf != nil {
+ hostname = tlsConf.ServerName
+ }
+
+ if hostname == "" {
+ hostname, _, err = net.SplitHostPort(host)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ clientConfig := populateClientConfig(config)
+ c := &client{
+ conn: &conn{pconn: pconn, currentAddr: remoteAddr},
+ connectionID: connID,
+ hostname: hostname,
+ tlsConf: tlsConf,
+ config: clientConfig,
+ version: clientConfig.Versions[0],
+ errorChan: make(chan struct{}),
+ }
+
+ err = c.createNewSession(nil)
+ if err != nil {
+ return nil, err
+ }
+
+ utils.Infof("Starting new connection to %s (%s -> %s), connectionID %x, version %d", hostname, c.conn.LocalAddr().String(), c.conn.RemoteAddr().String(), c.connectionID, c.version)
+
+ return c.session.(NonFWSession), c.establishSecureConnection()
+}
+
+// Dial establishes a new QUIC connection to a server using a net.PacketConn.
+// The host parameter is used for SNI.
+func Dial(
+ pconn net.PacketConn,
+ remoteAddr net.Addr,
+ host string,
+ tlsConf *tls.Config,
+ config *Config,
+) (Session, error) {
+ sess, err := DialNonFWSecure(pconn, remoteAddr, host, tlsConf, config)
+ if err != nil {
+ return nil, err
+ }
+ err = sess.WaitUntilHandshakeComplete()
+ if err != nil {
+ return nil, err
+ }
+ return sess, nil
+}
+
+// populateClientConfig populates fields in the quic.Config with their default values, if none are set
+// it may be called with nil
+func populateClientConfig(config *Config) *Config {
+ if config == nil {
+ config = &Config{}
+ }
+ versions := config.Versions
+ if len(versions) == 0 {
+ versions = protocol.SupportedVersions
+ }
+
+ handshakeTimeout := protocol.DefaultHandshakeTimeout
+ if config.HandshakeTimeout != 0 {
+ handshakeTimeout = config.HandshakeTimeout
+ }
+
+ maxReceiveStreamFlowControlWindow := config.MaxReceiveStreamFlowControlWindow
+ if maxReceiveStreamFlowControlWindow == 0 {
+ maxReceiveStreamFlowControlWindow = protocol.DefaultMaxReceiveStreamFlowControlWindowClient
+ }
+ maxReceiveConnectionFlowControlWindow := config.MaxReceiveConnectionFlowControlWindow
+ if maxReceiveConnectionFlowControlWindow == 0 {
+ maxReceiveConnectionFlowControlWindow = protocol.DefaultMaxReceiveConnectionFlowControlWindowClient
+ }
+
+ return &Config{
+ Versions: versions,
+ HandshakeTimeout: handshakeTimeout,
+ RequestConnectionIDTruncation: config.RequestConnectionIDTruncation,
+ MaxReceiveStreamFlowControlWindow: maxReceiveStreamFlowControlWindow,
+ MaxReceiveConnectionFlowControlWindow: maxReceiveConnectionFlowControlWindow,
+ KeepAlive: config.KeepAlive,
+ }
+}
+
+// establishSecureConnection returns as soon as the connection is secure (as opposed to forward-secure)
+func (c *client) establishSecureConnection() error {
+ go c.listen()
+
+ select {
+ case <-c.errorChan:
+ return c.listenErr
+ case ev := <-c.handshakeChan:
+ if ev.err != nil {
+ return ev.err
+ }
+ if ev.encLevel != protocol.EncryptionSecure {
+ return fmt.Errorf("Client BUG: Expected encryption level to be secure, was %s", ev.encLevel)
+ }
+ return nil
+ }
+}
+
+// Listen listens
+func (c *client) listen() {
+ var err error
+
+ for {
+ var n int
+ var addr net.Addr
+ data := getPacketBuffer()
+ data = data[:protocol.MaxReceivePacketSize]
+ // The packet size should not exceed protocol.MaxReceivePacketSize bytes
+ // If it does, we only read a truncated packet, which will then end up undecryptable
+ n, addr, err = c.conn.Read(data)
+ if err != nil {
+ if !strings.HasSuffix(err.Error(), "use of closed network connection") {
+ c.session.Close(err)
+ }
+ break
+ }
+ data = data[:n]
+
+ c.handlePacket(addr, data)
+ }
+}
+
+func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) {
+ rcvTime := time.Now()
+
+ r := bytes.NewReader(packet)
+ hdr, err := ParsePublicHeader(r, protocol.PerspectiveServer)
+ if err != nil {
+ utils.Errorf("error parsing packet from %s: %s", remoteAddr.String(), err.Error())
+ // drop this packet if we can't parse the Public Header
+ return
+ }
+ hdr.Raw = packet[:len(packet)-r.Len()]
+
+ c.mutex.Lock()
+ defer c.mutex.Unlock()
+
+ if hdr.ResetFlag {
+ cr := c.conn.RemoteAddr()
+ // check if the remote address and the connection ID match
+ // otherwise this might be an attacker trying to inject a PUBLIC_RESET to kill the connection
+ if cr.Network() != remoteAddr.Network() || cr.String() != remoteAddr.String() || hdr.ConnectionID != c.connectionID {
+ utils.Infof("Received a spoofed Public Reset. Ignoring.")
+ return
+ }
+ pr, err := parsePublicReset(r)
+ if err != nil {
+ utils.Infof("Received a Public Reset for connection %x. An error occurred parsing the packet.")
+ return
+ }
+ utils.Infof("Received Public Reset, rejected packet number: %#x.", pr.rejectedPacketNumber)
+ c.session.closeRemote(qerr.Error(qerr.PublicReset, fmt.Sprintf("Received a Public Reset for packet number %#x", pr.rejectedPacketNumber)))
+ return
+ }
+
+ // ignore delayed / duplicated version negotiation packets
+ if c.versionNegotiated && hdr.VersionFlag {
+ return
+ }
+
+ // this is the first packet after the client sent a packet with the VersionFlag set
+ // if the server doesn't send a version negotiation packet, it supports the suggested version
+ if !hdr.VersionFlag && !c.versionNegotiated {
+ c.versionNegotiated = true
+ }
+
+ if hdr.VersionFlag {
+ // version negotiation packets have no payload
+ if err := c.handlePacketWithVersionFlag(hdr); err != nil {
+ c.session.Close(err)
+ }
+ return
+ }
+
+ c.session.handlePacket(&receivedPacket{
+ remoteAddr: remoteAddr,
+ publicHeader: hdr,
+ data: packet[len(packet)-r.Len():],
+ rcvTime: rcvTime,
+ })
+}
+
+func (c *client) handlePacketWithVersionFlag(hdr *PublicHeader) error {
+ for _, v := range hdr.SupportedVersions {
+ if v == c.version {
+ // the version negotiation packet contains the version that we offered
+ // this might be a packet sent by an attacker (or by a terribly broken server implementation)
+ // ignore it
+ return nil
+ }
+ }
+
+ newVersion := protocol.ChooseSupportedVersion(c.config.Versions, hdr.SupportedVersions)
+ if newVersion == protocol.VersionUnsupported {
+ return qerr.InvalidVersion
+ }
+
+ // switch to negotiated version
+ c.version = newVersion
+ c.versionNegotiated = true
+ var err error
+ c.connectionID, err = utils.GenerateConnectionID()
+ if err != nil {
+ return err
+ }
+ utils.Infof("Switching to QUIC version %d. New connection ID: %x", newVersion, c.connectionID)
+
+ c.session.Close(errCloseSessionForNewVersion)
+ return c.createNewSession(hdr.SupportedVersions)
+}
+
+func (c *client) createNewSession(negotiatedVersions []protocol.VersionNumber) error {
+ var err error
+ c.session, c.handshakeChan, err = newClientSession(
+ c.conn,
+ c.hostname,
+ c.version,
+ c.connectionID,
+ c.tlsConf,
+ c.config,
+ negotiatedVersions,
+ )
+ if err != nil {
+ return err
+ }
+
+ go func() {
+ // session.run() returns as soon as the session is closed
+ err := c.session.run()
+ if err == errCloseSessionForNewVersion {
+ return
+ }
+ c.listenErr = err
+ close(c.errorChan)
+
+ utils.Infof("Connection %x closed.", c.connectionID)
+ c.conn.Close()
+ }()
+ return nil
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/codecov.yml b/vendor/github.com/lucas-clemente/quic-go/codecov.yml
similarity index 50%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/codecov.yml
rename to vendor/github.com/lucas-clemente/quic-go/codecov.yml
index 4e4e039..d85e781 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/codecov.yml
+++ b/vendor/github.com/lucas-clemente/quic-go/codecov.yml
@@ -2,8 +2,10 @@ coverage:
round: nearest
ignore:
- ackhandler/packet_linkedlist.go
- - utils/byteinterval_linkedlist.go
- - utils/packetinterval_linkedlist.go
+ - h2quic/gzipreader.go
+ - h2quic/response.go
+ - internal/utils/byteinterval_linkedlist.go
+ - internal/utils/packetinterval_linkedlist.go
status:
project:
default:
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/bandwidth.go b/vendor/github.com/lucas-clemente/quic-go/congestion/bandwidth.go
similarity index 76%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/bandwidth.go
rename to vendor/github.com/lucas-clemente/quic-go/congestion/bandwidth.go
index 2c7ff23..e76ea16 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/bandwidth.go
+++ b/vendor/github.com/lucas-clemente/quic-go/congestion/bandwidth.go
@@ -12,12 +12,8 @@ type Bandwidth uint64
const (
// BitsPerSecond is 1 bit per second
BitsPerSecond Bandwidth = 1
- // KBitsPerSecond is 1000 bits per second
- KBitsPerSecond = 1000 * BitsPerSecond
// BytesPerSecond is 1 byte per second
BytesPerSecond = 8 * BitsPerSecond
- // KBytesPerSecond is 1000 bytes per second
- KBytesPerSecond = 1000 * BytesPerSecond
)
// BandwidthFromDelta calculates the bandwidth from a number of bytes and a time delta
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/clock.go b/vendor/github.com/lucas-clemente/quic-go/congestion/clock.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/clock.go
rename to vendor/github.com/lucas-clemente/quic-go/congestion/clock.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/cubic.go b/vendor/github.com/lucas-clemente/quic-go/congestion/cubic.go
similarity index 94%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/cubic.go
rename to vendor/github.com/lucas-clemente/quic-go/congestion/cubic.go
index e6e8bf6..62e7355 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/cubic.go
+++ b/vendor/github.com/lucas-clemente/quic-go/congestion/cubic.go
@@ -4,8 +4,8 @@ import (
"math"
"time"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
)
// This cubic implementation is based on the one found in Chromiums's QUIC
@@ -184,9 +184,19 @@ func (c *Cubic) CongestionWindowAfterAck(currentCongestionWindow protocol.Packet
elapsedTime := int64((currentTime.Add(delayMin).Sub(c.epoch)/time.Microsecond)<<10) / 1000000
offset := int64(c.timeToOriginPoint) - elapsedTime
+ // Right-shifts of negative, signed numbers have
+ // implementation-dependent behavior. Force the offset to be
+ // positive, similar to the kernel implementation.
+ if offset < 0 {
+ offset = -offset
+ }
deltaCongestionWindow := protocol.PacketNumber((cubeCongestionWindowScale * offset * offset * offset) >> cubeScale)
- targetCongestionWindow := c.originPointCongestionWindow - deltaCongestionWindow
-
+ var targetCongestionWindow protocol.PacketNumber
+ if elapsedTime > int64(c.timeToOriginPoint) {
+ targetCongestionWindow = c.originPointCongestionWindow + deltaCongestionWindow
+ } else {
+ targetCongestionWindow = c.originPointCongestionWindow - deltaCongestionWindow
+ }
// With dynamic beta/alpha based on number of active streams, it is possible
// for the required_ack_count to become much lower than acked_packets_count_
// suddenly, leading to more than one iteration through the following loop.
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/cubic_sender.go b/vendor/github.com/lucas-clemente/quic-go/congestion/cubic_sender.go
similarity index 90%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/cubic_sender.go
rename to vendor/github.com/lucas-clemente/quic-go/congestion/cubic_sender.go
index a34a69d..02e4206 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/cubic_sender.go
+++ b/vendor/github.com/lucas-clemente/quic-go/congestion/cubic_sender.go
@@ -3,8 +3,8 @@ package congestion
import (
"time"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
)
const (
@@ -125,24 +125,13 @@ func (c *cubicSender) SlowstartThreshold() protocol.PacketNumber {
return c.slowstartThreshold
}
-// OnCongestionEvent indicates an update to the congestion state, caused either by an incoming
-// ack or loss event timeout. |rttUpdated| indicates whether a new
-// latest_rtt sample has been taken, |byte_in_flight| the bytes in flight
-// prior to the congestion event. |ackedPackets| and |lostPackets| are
-// any packets considered acked or lost as a result of the congestion event.
-func (c *cubicSender) OnCongestionEvent(rttUpdated bool, bytesInFlight protocol.ByteCount, ackedPackets PacketVector, lostPackets PacketVector) {
- if rttUpdated && c.InSlowStart() && c.hybridSlowStart.ShouldExitSlowStart(c.rttStats.LatestRTT(), c.rttStats.MinRTT(), c.GetCongestionWindow()/protocol.DefaultTCPMSS) {
+func (c *cubicSender) MaybeExitSlowStart() {
+ if c.InSlowStart() && c.hybridSlowStart.ShouldExitSlowStart(c.rttStats.LatestRTT(), c.rttStats.MinRTT(), c.GetCongestionWindow()/protocol.DefaultTCPMSS) {
c.ExitSlowstart()
}
- for _, i := range lostPackets {
- c.onPacketLost(i.Number, i.Length, bytesInFlight)
- }
- for _, i := range ackedPackets {
- c.onPacketAcked(i.Number, i.Length, bytesInFlight)
- }
}
-func (c *cubicSender) onPacketAcked(ackedPacketNumber protocol.PacketNumber, ackedBytes protocol.ByteCount, bytesInFlight protocol.ByteCount) {
+func (c *cubicSender) OnPacketAcked(ackedPacketNumber protocol.PacketNumber, ackedBytes protocol.ByteCount, bytesInFlight protocol.ByteCount) {
c.largestAckedPacketNumber = utils.MaxPacketNumber(ackedPacketNumber, c.largestAckedPacketNumber)
if c.InRecovery() {
// PRR is used when in recovery.
@@ -155,7 +144,7 @@ func (c *cubicSender) onPacketAcked(ackedPacketNumber protocol.PacketNumber, ack
}
}
-func (c *cubicSender) onPacketLost(packetNumber protocol.PacketNumber, lostBytes protocol.ByteCount, bytesInFlight protocol.ByteCount) {
+func (c *cubicSender) OnPacketLost(packetNumber protocol.PacketNumber, lostBytes protocol.ByteCount, bytesInFlight protocol.ByteCount) {
// TCP NewReno (RFC6582) says that once a loss occurs, any losses in packets
// already sent should be treated as a single loss event, since it's expected.
if packetNumber <= c.largestSentAtLastCutback {
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/hybrid_slow_start.go b/vendor/github.com/lucas-clemente/quic-go/congestion/hybrid_slow_start.go
similarity index 98%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/hybrid_slow_start.go
rename to vendor/github.com/lucas-clemente/quic-go/congestion/hybrid_slow_start.go
index 29204ff..01a64f8 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/hybrid_slow_start.go
+++ b/vendor/github.com/lucas-clemente/quic-go/congestion/hybrid_slow_start.go
@@ -3,8 +3,8 @@ package congestion
import (
"time"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
)
// Note(pwestin): the magic clamping numbers come from the original code in
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/interface.go b/vendor/github.com/lucas-clemente/quic-go/congestion/interface.go
similarity index 80%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/interface.go
rename to vendor/github.com/lucas-clemente/quic-go/congestion/interface.go
index 593c09e..bbce0a6 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/interface.go
+++ b/vendor/github.com/lucas-clemente/quic-go/congestion/interface.go
@@ -11,7 +11,9 @@ type SendAlgorithm interface {
TimeUntilSend(now time.Time, bytesInFlight protocol.ByteCount) time.Duration
OnPacketSent(sentTime time.Time, bytesInFlight protocol.ByteCount, packetNumber protocol.PacketNumber, bytes protocol.ByteCount, isRetransmittable bool) bool
GetCongestionWindow() protocol.ByteCount
- OnCongestionEvent(rttUpdated bool, bytesInFlight protocol.ByteCount, ackedPackets PacketVector, lostPackets PacketVector)
+ MaybeExitSlowStart()
+ OnPacketAcked(number protocol.PacketNumber, ackedBytes protocol.ByteCount, bytesInFlight protocol.ByteCount)
+ OnPacketLost(number protocol.PacketNumber, lostBytes protocol.ByteCount, bytesInFlight protocol.ByteCount)
SetNumEmulatedConnections(n int)
OnRetransmissionTimeout(packetsRetransmitted bool)
OnConnectionMigration()
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/prr_sender.go b/vendor/github.com/lucas-clemente/quic-go/congestion/prr_sender.go
similarity index 97%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/prr_sender.go
rename to vendor/github.com/lucas-clemente/quic-go/congestion/prr_sender.go
index f8e6d59..b8a0a10 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/prr_sender.go
+++ b/vendor/github.com/lucas-clemente/quic-go/congestion/prr_sender.go
@@ -3,8 +3,8 @@ package congestion
import (
"time"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
)
// PrrSender implements the Proportional Rate Reduction (PRR) per RFC 6937
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/rtt_stats.go b/vendor/github.com/lucas-clemente/quic-go/congestion/rtt_stats.go
similarity index 99%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/rtt_stats.go
rename to vendor/github.com/lucas-clemente/quic-go/congestion/rtt_stats.go
index 0bf7b05..546c1cb 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/rtt_stats.go
+++ b/vendor/github.com/lucas-clemente/quic-go/congestion/rtt_stats.go
@@ -3,7 +3,7 @@ package congestion
import (
"time"
- "github.com/lucas-clemente/quic-go/utils"
+ "github.com/lucas-clemente/quic-go/internal/utils"
)
const (
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/stats.go b/vendor/github.com/lucas-clemente/quic-go/congestion/stats.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/congestion/stats.go
rename to vendor/github.com/lucas-clemente/quic-go/congestion/stats.go
diff --git a/vendor/github.com/lucas-clemente/quic-go/conn.go b/vendor/github.com/lucas-clemente/quic-go/conn.go
new file mode 100644
index 0000000..700c147
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/conn.go
@@ -0,0 +1,54 @@
+package quic
+
+import (
+ "net"
+ "sync"
+)
+
+type connection interface {
+ Write([]byte) error
+ Read([]byte) (int, net.Addr, error)
+ Close() error
+ LocalAddr() net.Addr
+ RemoteAddr() net.Addr
+ SetCurrentRemoteAddr(net.Addr)
+}
+
+type conn struct {
+ mutex sync.RWMutex
+
+ pconn net.PacketConn
+ currentAddr net.Addr
+}
+
+var _ connection = &conn{}
+
+func (c *conn) Write(p []byte) error {
+ _, err := c.pconn.WriteTo(p, c.currentAddr)
+ return err
+}
+
+func (c *conn) Read(p []byte) (int, net.Addr, error) {
+ return c.pconn.ReadFrom(p)
+}
+
+func (c *conn) SetCurrentRemoteAddr(addr net.Addr) {
+ c.mutex.Lock()
+ c.currentAddr = addr
+ c.mutex.Unlock()
+}
+
+func (c *conn) LocalAddr() net.Addr {
+ return c.pconn.LocalAddr()
+}
+
+func (c *conn) RemoteAddr() net.Addr {
+ c.mutex.RLock()
+ addr := c.currentAddr
+ c.mutex.RUnlock()
+ return addr
+}
+
+func (c *conn) Close() error {
+ return c.pconn.Close()
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/AEAD.go b/vendor/github.com/lucas-clemente/quic-go/crypto/AEAD.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/AEAD.go
rename to vendor/github.com/lucas-clemente/quic-go/crypto/AEAD.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/aesgcm_aead.go b/vendor/github.com/lucas-clemente/quic-go/crypto/aesgcm_aead.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/aesgcm_aead.go
rename to vendor/github.com/lucas-clemente/quic-go/crypto/aesgcm_aead.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/cert_cache.go b/vendor/github.com/lucas-clemente/quic-go/crypto/cert_cache.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/cert_cache.go
rename to vendor/github.com/lucas-clemente/quic-go/crypto/cert_cache.go
diff --git a/vendor/github.com/lucas-clemente/quic-go/crypto/cert_chain.go b/vendor/github.com/lucas-clemente/quic-go/crypto/cert_chain.go
new file mode 100644
index 0000000..f3bc9fb
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/crypto/cert_chain.go
@@ -0,0 +1,113 @@
+package crypto
+
+import (
+ "crypto/tls"
+ "errors"
+ "strings"
+)
+
+// A CertChain holds a certificate and a private key
+type CertChain interface {
+ SignServerProof(sni string, chlo []byte, serverConfigData []byte) ([]byte, error)
+ GetCertsCompressed(sni string, commonSetHashes, cachedHashes []byte) ([]byte, error)
+ GetLeafCert(sni string) ([]byte, error)
+}
+
+// proofSource stores a key and a certificate for the server proof
+type certChain struct {
+ config *tls.Config
+}
+
+var _ CertChain = &certChain{}
+
+var errNoMatchingCertificate = errors.New("no matching certificate found")
+
+// NewCertChain loads the key and cert from files
+func NewCertChain(tlsConfig *tls.Config) CertChain {
+ return &certChain{config: tlsConfig}
+}
+
+// SignServerProof signs CHLO and server config for use in the server proof
+func (c *certChain) SignServerProof(sni string, chlo []byte, serverConfigData []byte) ([]byte, error) {
+ cert, err := c.getCertForSNI(sni)
+ if err != nil {
+ return nil, err
+ }
+
+ return signServerProof(cert, chlo, serverConfigData)
+}
+
+// GetCertsCompressed gets the certificate in the format described by the QUIC crypto doc
+func (c *certChain) GetCertsCompressed(sni string, pCommonSetHashes, pCachedHashes []byte) ([]byte, error) {
+ cert, err := c.getCertForSNI(sni)
+ if err != nil {
+ return nil, err
+ }
+ return getCompressedCert(cert.Certificate, pCommonSetHashes, pCachedHashes)
+}
+
+// GetLeafCert gets the leaf certificate
+func (c *certChain) GetLeafCert(sni string) ([]byte, error) {
+ cert, err := c.getCertForSNI(sni)
+ if err != nil {
+ return nil, err
+ }
+ return cert.Certificate[0], nil
+}
+
+func (cc *certChain) getCertForSNI(sni string) (*tls.Certificate, error) {
+ c := cc.config
+ c, err := maybeGetConfigForClient(c, sni)
+ if err != nil {
+ return nil, err
+ }
+ // The rest of this function is mostly copied from crypto/tls.getCertificate
+
+ if c.GetCertificate != nil {
+ cert, err := c.GetCertificate(&tls.ClientHelloInfo{ServerName: sni})
+ if cert != nil || err != nil {
+ return cert, err
+ }
+ }
+
+ if len(c.Certificates) == 0 {
+ return nil, errNoMatchingCertificate
+ }
+
+ if len(c.Certificates) == 1 || c.NameToCertificate == nil {
+ // There's only one choice, so no point doing any work.
+ return &c.Certificates[0], nil
+ }
+
+ name := strings.ToLower(sni)
+ for len(name) > 0 && name[len(name)-1] == '.' {
+ name = name[:len(name)-1]
+ }
+
+ if cert, ok := c.NameToCertificate[name]; ok {
+ return cert, nil
+ }
+
+ // try replacing labels in the name with wildcards until we get a
+ // match.
+ labels := strings.Split(name, ".")
+ for i := range labels {
+ labels[i] = "*"
+ candidate := strings.Join(labels, ".")
+ if cert, ok := c.NameToCertificate[candidate]; ok {
+ return cert, nil
+ }
+ }
+
+ // If nothing matches, return the first certificate.
+ return &c.Certificates[0], nil
+}
+
+func maybeGetConfigForClient(c *tls.Config, sni string) (*tls.Config, error) {
+ if c.GetConfigForClient == nil {
+ return c, nil
+ }
+ return c.GetConfigForClient(&tls.ClientHelloInfo{
+ ServerName: sni,
+ })
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/cert_compression.go b/vendor/github.com/lucas-clemente/quic-go/crypto/cert_compression.go
similarity index 53%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/cert_compression.go
rename to vendor/github.com/lucas-clemente/quic-go/crypto/cert_compression.go
index 8fdb257..ea5ecff 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/cert_compression.go
+++ b/vendor/github.com/lucas-clemente/quic-go/crypto/cert_compression.go
@@ -9,7 +9,7 @@ import (
"fmt"
"hash/fnv"
- "github.com/lucas-clemente/quic-go/utils"
+ "github.com/lucas-clemente/quic-go/internal/utils"
)
type entryType uint8
@@ -22,8 +22,8 @@ const (
type entry struct {
t entryType
- h uint64
- i uint32
+ h uint64 // set hash
+ i uint32 // index
}
func compressChain(chain [][]byte, pCommonSetHashes, pCachedHashes []byte) ([]byte, error) {
@@ -41,7 +41,7 @@ func compressChain(chain [][]byte, pCommonSetHashes, pCachedHashes []byte) ([]by
chainHashes := make([]uint64, len(chain))
for i := range chain {
- chainHashes[i] = hashCert(chain[i])
+ chainHashes[i] = HashCert(chain[i])
}
entries := buildEntries(chain, chainHashes, cachedHashes, setHashes)
@@ -89,6 +89,111 @@ func compressChain(chain [][]byte, pCommonSetHashes, pCachedHashes []byte) ([]by
return res.Bytes(), nil
}
+func decompressChain(data []byte) ([][]byte, error) {
+ var chain [][]byte
+ var entries []entry
+ r := bytes.NewReader(data)
+
+ var numCerts int
+ var hasCompressedCerts bool
+ for {
+ entryTypeByte, err := r.ReadByte()
+ if entryTypeByte == 0 {
+ break
+ }
+
+ et := entryType(entryTypeByte)
+ if err != nil {
+ return nil, err
+ }
+
+ numCerts++
+
+ switch et {
+ case entryCached:
+ // we're not sending any certificate hashes in the CHLO, so there shouldn't be any cached certificates in the chain
+ return nil, errors.New("unexpected cached certificate")
+ case entryCommon:
+ e := entry{t: entryCommon}
+ e.h, err = utils.ReadUint64(r)
+ if err != nil {
+ return nil, err
+ }
+ e.i, err = utils.ReadUint32(r)
+ if err != nil {
+ return nil, err
+ }
+ certSet, ok := certSets[e.h]
+ if !ok {
+ return nil, errors.New("unknown certSet")
+ }
+ if e.i >= uint32(len(certSet)) {
+ return nil, errors.New("certificate not found in certSet")
+ }
+ entries = append(entries, e)
+ chain = append(chain, certSet[e.i])
+ case entryCompressed:
+ hasCompressedCerts = true
+ entries = append(entries, entry{t: entryCompressed})
+ chain = append(chain, nil)
+ default:
+ return nil, errors.New("unknown entryType")
+ }
+ }
+
+ if numCerts == 0 {
+ return make([][]byte, 0), nil
+ }
+
+ if hasCompressedCerts {
+ uncompressedLength, err := utils.ReadUint32(r)
+ if err != nil {
+ fmt.Println(4)
+ return nil, err
+ }
+
+ zlibDict := buildZlibDictForEntries(entries, chain)
+ gz, err := zlib.NewReaderDict(r, zlibDict)
+ if err != nil {
+ return nil, err
+ }
+ defer gz.Close()
+
+ var totalLength uint32
+ var certIndex int
+ for totalLength < uncompressedLength {
+ lenBytes := make([]byte, 4)
+ _, err := gz.Read(lenBytes)
+ if err != nil {
+ return nil, err
+ }
+ certLen := binary.LittleEndian.Uint32(lenBytes)
+
+ cert := make([]byte, certLen)
+ n, err := gz.Read(cert)
+ if uint32(n) != certLen && err != nil {
+ return nil, err
+ }
+
+ for {
+ if certIndex >= len(entries) {
+ return nil, errors.New("CertCompression BUG: no element to save uncompressed certificate")
+ }
+ if entries[certIndex].t == entryCompressed {
+ chain[certIndex] = cert
+ certIndex++
+ break
+ }
+ certIndex++
+ }
+
+ totalLength += 4 + certLen
+ }
+ }
+
+ return chain, nil
+}
+
func buildEntries(chain [][]byte, chainHashes, cachedHashes, setHashes []uint64) []entry {
res := make([]entry, len(chain))
chainLoop:
@@ -149,8 +254,19 @@ func splitHashes(hashes []byte) ([]uint64, error) {
return res, nil
}
-func hashCert(cert []byte) uint64 {
- h := fnv.New64()
+func getCommonCertificateHashes() []byte {
+ ccs := make([]byte, 8*len(certSets))
+ i := 0
+ for certSetHash := range certSets {
+ binary.LittleEndian.PutUint64(ccs[i*8:(i+1)*8], certSetHash)
+ i++
+ }
+ return ccs
+}
+
+// HashCert calculates the FNV1a hash of a certificate
+func HashCert(cert []byte) uint64 {
+ h := fnv.New64a()
h.Write(cert)
return h.Sum64()
}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/cert_dict.go b/vendor/github.com/lucas-clemente/quic-go/crypto/cert_dict.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/cert_dict.go
rename to vendor/github.com/lucas-clemente/quic-go/crypto/cert_dict.go
diff --git a/vendor/github.com/lucas-clemente/quic-go/crypto/cert_manager.go b/vendor/github.com/lucas-clemente/quic-go/crypto/cert_manager.go
new file mode 100644
index 0000000..5aaa187
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/crypto/cert_manager.go
@@ -0,0 +1,130 @@
+package crypto
+
+import (
+ "crypto/tls"
+ "crypto/x509"
+ "errors"
+ "hash/fnv"
+ "time"
+
+ "github.com/lucas-clemente/quic-go/qerr"
+)
+
+// CertManager manages the certificates sent by the server
+type CertManager interface {
+ SetData([]byte) error
+ GetCommonCertificateHashes() []byte
+ GetLeafCert() []byte
+ GetLeafCertHash() (uint64, error)
+ VerifyServerProof(proof, chlo, serverConfigData []byte) bool
+ Verify(hostname string) error
+}
+
+type certManager struct {
+ chain []*x509.Certificate
+ config *tls.Config
+}
+
+var _ CertManager = &certManager{}
+
+var errNoCertificateChain = errors.New("CertManager BUG: No certicifate chain loaded")
+
+// NewCertManager creates a new CertManager
+func NewCertManager(tlsConfig *tls.Config) CertManager {
+ return &certManager{config: tlsConfig}
+}
+
+// SetData takes the byte-slice sent in the SHLO and decompresses it into the certificate chain
+func (c *certManager) SetData(data []byte) error {
+ byteChain, err := decompressChain(data)
+ if err != nil {
+ return qerr.Error(qerr.InvalidCryptoMessageParameter, "Certificate data invalid")
+ }
+
+ chain := make([]*x509.Certificate, len(byteChain))
+ for i, data := range byteChain {
+ cert, err := x509.ParseCertificate(data)
+ if err != nil {
+ return err
+ }
+ chain[i] = cert
+ }
+
+ c.chain = chain
+ return nil
+}
+
+func (c *certManager) GetCommonCertificateHashes() []byte {
+ return getCommonCertificateHashes()
+}
+
+// GetLeafCert returns the leaf certificate of the certificate chain
+// it returns nil if the certificate chain has not yet been set
+func (c *certManager) GetLeafCert() []byte {
+ if len(c.chain) == 0 {
+ return nil
+ }
+ return c.chain[0].Raw
+}
+
+// GetLeafCertHash calculates the FNV1a_64 hash of the leaf certificate
+func (c *certManager) GetLeafCertHash() (uint64, error) {
+ leafCert := c.GetLeafCert()
+ if leafCert == nil {
+ return 0, errNoCertificateChain
+ }
+
+ h := fnv.New64a()
+ _, err := h.Write(leafCert)
+ if err != nil {
+ return 0, err
+ }
+ return h.Sum64(), nil
+}
+
+// VerifyServerProof verifies the signature of the server config
+// it should only be called after the certificate chain has been set, otherwise it returns false
+func (c *certManager) VerifyServerProof(proof, chlo, serverConfigData []byte) bool {
+ if len(c.chain) == 0 {
+ return false
+ }
+
+ return verifyServerProof(proof, c.chain[0], chlo, serverConfigData)
+}
+
+// Verify verifies the certificate chain
+func (c *certManager) Verify(hostname string) error {
+ if len(c.chain) == 0 {
+ return errNoCertificateChain
+ }
+
+ if c.config != nil && c.config.InsecureSkipVerify {
+ return nil
+ }
+
+ leafCert := c.chain[0]
+
+ var opts x509.VerifyOptions
+ if c.config != nil {
+ opts.Roots = c.config.RootCAs
+ if c.config.Time == nil {
+ opts.CurrentTime = time.Now()
+ } else {
+ opts.CurrentTime = c.config.Time()
+ }
+ }
+ // we don't need to care about the tls.Config.ServerName here, since hostname has already been set to that value in the session setup
+ opts.DNSName = hostname
+
+ // the first certificate is the leaf certificate, all others are intermediates
+ if len(c.chain) > 1 {
+ intermediates := x509.NewCertPool()
+ for i := 1; i < len(c.chain); i++ {
+ intermediates.AddCert(c.chain[i])
+ }
+ opts.Intermediates = intermediates
+ }
+
+ _, err := leafCert.Verify(opts)
+ return err
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/cert_sets.go b/vendor/github.com/lucas-clemente/quic-go/crypto/cert_sets.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/cert_sets.go
rename to vendor/github.com/lucas-clemente/quic-go/crypto/cert_sets.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/chacha20poly1305_aead.go b/vendor/github.com/lucas-clemente/quic-go/crypto/chacha20poly1305_aead.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/chacha20poly1305_aead.go
rename to vendor/github.com/lucas-clemente/quic-go/crypto/chacha20poly1305_aead.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/chacha20poly1305_aead_test.go b/vendor/github.com/lucas-clemente/quic-go/crypto/chacha20poly1305_aead_test.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/chacha20poly1305_aead_test.go
rename to vendor/github.com/lucas-clemente/quic-go/crypto/chacha20poly1305_aead_test.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/curve_25519.go b/vendor/github.com/lucas-clemente/quic-go/crypto/curve_25519.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/curve_25519.go
rename to vendor/github.com/lucas-clemente/quic-go/crypto/curve_25519.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/key_derivation.go b/vendor/github.com/lucas-clemente/quic-go/crypto/key_derivation.go
similarity index 71%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/key_derivation.go
rename to vendor/github.com/lucas-clemente/quic-go/crypto/key_derivation.go
index 60648d8..accdbea 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/key_derivation.go
+++ b/vendor/github.com/lucas-clemente/quic-go/crypto/key_derivation.go
@@ -5,8 +5,8 @@ import (
"crypto/sha256"
"io"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
"golang.org/x/crypto/hkdf"
)
@@ -21,15 +21,21 @@ import (
// }
// DeriveKeysAESGCM derives the client and server keys and creates a matching AES-GCM AEAD instance
-func DeriveKeysAESGCM(forwardSecure bool, sharedSecret, nonces []byte, connID protocol.ConnectionID, chlo []byte, scfg []byte, cert []byte, divNonce []byte) (AEAD, error) {
- otherKey, myKey, otherIV, myIV, err := deriveKeys(forwardSecure, sharedSecret, nonces, connID, chlo, scfg, cert, divNonce, 16)
+func DeriveKeysAESGCM(forwardSecure bool, sharedSecret, nonces []byte, connID protocol.ConnectionID, chlo []byte, scfg []byte, cert []byte, divNonce []byte, pers protocol.Perspective) (AEAD, error) {
+ var swap bool
+ if pers == protocol.PerspectiveClient {
+ swap = true
+ }
+ otherKey, myKey, otherIV, myIV, err := deriveKeys(forwardSecure, sharedSecret, nonces, connID, chlo, scfg, cert, divNonce, 16, swap)
if err != nil {
return nil, err
}
return NewAEADAESGCM(otherKey, myKey, otherIV, myIV)
}
-func deriveKeys(forwardSecure bool, sharedSecret, nonces []byte, connID protocol.ConnectionID, chlo, scfg, cert, divNonce []byte, keyLen int) ([]byte, []byte, []byte, []byte, error) {
+// deriveKeys derives the keys and the IVs
+// swap should be set true if generating the values for the client, and false for the server
+func deriveKeys(forwardSecure bool, sharedSecret, nonces []byte, connID protocol.ConnectionID, chlo, scfg, cert, divNonce []byte, keyLen int, swap bool) ([]byte, []byte, []byte, []byte, error) {
var info bytes.Buffer
if forwardSecure {
info.Write([]byte("QUIC forward secure key expansion\x00"))
@@ -47,17 +53,33 @@ func deriveKeys(forwardSecure bool, sharedSecret, nonces []byte, connID protocol
if _, err := io.ReadFull(r, s); err != nil {
return nil, nil, nil, nil, err
}
- otherKey := s[:keyLen]
- myKey := s[keyLen : 2*keyLen]
- otherIV := s[2*keyLen : 2*keyLen+4]
- myIV := s[2*keyLen+4:]
+
+ key1 := s[:keyLen]
+ key2 := s[keyLen : 2*keyLen]
+ iv1 := s[2*keyLen : 2*keyLen+4]
+ iv2 := s[2*keyLen+4:]
+
+ var otherKey, myKey []byte
+ var otherIV, myIV []byte
if !forwardSecure {
- if err := diversify(myKey, myIV, divNonce); err != nil {
+ if err := diversify(key2, iv2, divNonce); err != nil {
return nil, nil, nil, nil, err
}
}
+ if swap {
+ otherKey = key2
+ myKey = key1
+ otherIV = iv2
+ myIV = iv1
+ } else {
+ otherKey = key1
+ myKey = key2
+ otherIV = iv1
+ myIV = iv2
+ }
+
return otherKey, myKey, otherIV, myIV, nil
}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/key_exchange.go b/vendor/github.com/lucas-clemente/quic-go/crypto/key_exchange.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/key_exchange.go
rename to vendor/github.com/lucas-clemente/quic-go/crypto/key_exchange.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/nonce.go b/vendor/github.com/lucas-clemente/quic-go/crypto/nonce.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/nonce.go
rename to vendor/github.com/lucas-clemente/quic-go/crypto/nonce.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/null_aead.go b/vendor/github.com/lucas-clemente/quic-go/crypto/null_aead.go
similarity index 53%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/null_aead.go
rename to vendor/github.com/lucas-clemente/quic-go/crypto/null_aead.go
index 5aa198c..ed85663 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/crypto/null_aead.go
+++ b/vendor/github.com/lucas-clemente/quic-go/crypto/null_aead.go
@@ -8,13 +8,24 @@ import (
"github.com/lucas-clemente/quic-go/protocol"
)
-// NullAEAD handles not-yet encrypted packets
-type NullAEAD struct{}
+// nullAEAD handles not-yet encrypted packets
+type nullAEAD struct {
+ perspective protocol.Perspective
+ version protocol.VersionNumber
+}
-var _ AEAD = &NullAEAD{}
+var _ AEAD = &nullAEAD{}
+
+// NewNullAEAD creates a NullAEAD
+func NewNullAEAD(p protocol.Perspective, v protocol.VersionNumber) AEAD {
+ return &nullAEAD{
+ perspective: p,
+ version: v,
+ }
+}
// Open and verify the ciphertext
-func (NullAEAD) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) {
+func (n *nullAEAD) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) {
if len(src) < 12 {
return nil, errors.New("NullAEAD: ciphertext cannot be less than 12 bytes long")
}
@@ -22,6 +33,13 @@ func (NullAEAD) Open(dst, src []byte, packetNumber protocol.PacketNumber, associ
hash := fnv128a.New()
hash.Write(associatedData)
hash.Write(src[12:])
+ if n.version >= protocol.Version37 {
+ if n.perspective == protocol.PerspectiveServer {
+ hash.Write([]byte("Client"))
+ } else {
+ hash.Write([]byte("Server"))
+ }
+ }
testHigh, testLow := hash.Sum128()
low := binary.LittleEndian.Uint64(src)
@@ -34,7 +52,7 @@ func (NullAEAD) Open(dst, src []byte, packetNumber protocol.PacketNumber, associ
}
// Seal writes hash and ciphertext to the buffer
-func (NullAEAD) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
+func (n *nullAEAD) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
if cap(dst) < 12+len(src) {
dst = make([]byte, 12+len(src))
} else {
@@ -44,6 +62,15 @@ func (NullAEAD) Seal(dst, src []byte, packetNumber protocol.PacketNumber, associ
hash := fnv128a.New()
hash.Write(associatedData)
hash.Write(src)
+
+ if n.version >= protocol.Version37 {
+ if n.perspective == protocol.PerspectiveServer {
+ hash.Write([]byte("Server"))
+ } else {
+ hash.Write([]byte("Client"))
+ }
+ }
+
high, low := hash.Sum128()
copy(dst[12:], src)
diff --git a/vendor/github.com/lucas-clemente/quic-go/crypto/server_proof.go b/vendor/github.com/lucas-clemente/quic-go/crypto/server_proof.go
new file mode 100644
index 0000000..456ad32
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/crypto/server_proof.go
@@ -0,0 +1,66 @@
+package crypto
+
+import (
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/sha256"
+ "crypto/tls"
+ "crypto/x509"
+ "encoding/asn1"
+ "errors"
+ "math/big"
+)
+
+type ecdsaSignature struct {
+ R, S *big.Int
+}
+
+// signServerProof signs CHLO and server config for use in the server proof
+func signServerProof(cert *tls.Certificate, chlo []byte, serverConfigData []byte) ([]byte, error) {
+ hash := sha256.New()
+ hash.Write([]byte("QUIC CHLO and server config signature\x00"))
+ chloHash := sha256.Sum256(chlo)
+ hash.Write([]byte{32, 0, 0, 0})
+ hash.Write(chloHash[:])
+ hash.Write(serverConfigData)
+
+ key, ok := cert.PrivateKey.(crypto.Signer)
+ if !ok {
+ return nil, errors.New("expected PrivateKey to implement crypto.Signer")
+ }
+
+ opts := crypto.SignerOpts(crypto.SHA256)
+
+ if _, ok = key.(*rsa.PrivateKey); ok {
+ opts = &rsa.PSSOptions{SaltLength: 32, Hash: crypto.SHA256}
+ }
+
+ return key.Sign(rand.Reader, hash.Sum(nil), opts)
+}
+
+// verifyServerProof verifies the server proof signature
+func verifyServerProof(proof []byte, cert *x509.Certificate, chlo []byte, serverConfigData []byte) bool {
+ hash := sha256.New()
+ hash.Write([]byte("QUIC CHLO and server config signature\x00"))
+ chloHash := sha256.Sum256(chlo)
+ hash.Write([]byte{32, 0, 0, 0})
+ hash.Write(chloHash[:])
+ hash.Write(serverConfigData)
+
+ // RSA
+ if cert.PublicKeyAlgorithm == x509.RSA {
+ opts := &rsa.PSSOptions{SaltLength: 32, Hash: crypto.SHA256}
+ err := rsa.VerifyPSS(cert.PublicKey.(*rsa.PublicKey), crypto.SHA256, hash.Sum(nil), proof, opts)
+ return err == nil
+ }
+
+ // ECDSA
+ signature := &ecdsaSignature{}
+ rest, err := asn1.Unmarshal(proof, signature)
+ if err != nil || len(rest) != 0 {
+ return false
+ }
+ return ecdsa.Verify(cert.PublicKey.(*ecdsa.PublicKey), hash.Sum(nil), signature.R, signature.S)
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/crypto/source_address_token.go b/vendor/github.com/lucas-clemente/quic-go/crypto/source_address_token.go
new file mode 100644
index 0000000..3dcb26a
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/crypto/source_address_token.go
@@ -0,0 +1,76 @@
+package crypto
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "crypto/sha256"
+ "fmt"
+ "io"
+
+ "golang.org/x/crypto/hkdf"
+)
+
+// StkSource is used to create and verify source address tokens
+type StkSource interface {
+ // NewToken creates a new token
+ NewToken([]byte) ([]byte, error)
+ // DecodeToken decodes a token
+ DecodeToken([]byte) ([]byte, error)
+}
+
+type stkSource struct {
+ aead cipher.AEAD
+}
+
+const stkKeySize = 16
+
+// Chrome currently sets this to 12, but discusses changing it to 16. We start
+// at 16 :)
+const stkNonceSize = 16
+
+// NewStkSource creates a source for source address tokens
+func NewStkSource() (StkSource, error) {
+ secret := make([]byte, 32)
+ if _, err := rand.Read(secret); err != nil {
+ return nil, err
+ }
+ key, err := deriveKey(secret)
+ if err != nil {
+ return nil, err
+ }
+ c, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+ aead, err := cipher.NewGCMWithNonceSize(c, stkNonceSize)
+ if err != nil {
+ return nil, err
+ }
+ return &stkSource{aead: aead}, nil
+}
+
+func (s *stkSource) NewToken(data []byte) ([]byte, error) {
+ nonce := make([]byte, stkNonceSize)
+ if _, err := rand.Read(nonce); err != nil {
+ return nil, err
+ }
+ return s.aead.Seal(nonce, nonce, data, nil), nil
+}
+
+func (s *stkSource) DecodeToken(p []byte) ([]byte, error) {
+ if len(p) < stkNonceSize {
+ return nil, fmt.Errorf("STK too short: %d", len(p))
+ }
+ nonce := p[:stkNonceSize]
+ return s.aead.Open(nil, nonce, p[stkNonceSize:], nil)
+}
+
+func deriveKey(secret []byte) ([]byte, error) {
+ r := hkdf.New(sha256.New, secret, nil, []byte("QUIC source address token key"))
+ key := make([]byte, stkKeySize)
+ if _, err := io.ReadFull(r, key); err != nil {
+ return nil, err
+ }
+ return key, nil
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_control_manager.go b/vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_control_manager.go
new file mode 100644
index 0000000..9362d60
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_control_manager.go
@@ -0,0 +1,240 @@
+package flowcontrol
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+
+ "github.com/lucas-clemente/quic-go/congestion"
+ "github.com/lucas-clemente/quic-go/handshake"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+ "github.com/lucas-clemente/quic-go/qerr"
+)
+
+type flowControlManager struct {
+ connectionParameters handshake.ConnectionParametersManager
+ rttStats *congestion.RTTStats
+
+ streamFlowController map[protocol.StreamID]*flowController
+ connFlowController *flowController
+ mutex sync.RWMutex
+}
+
+var _ FlowControlManager = &flowControlManager{}
+
+var errMapAccess = errors.New("Error accessing the flowController map.")
+
+// NewFlowControlManager creates a new flow control manager
+func NewFlowControlManager(connectionParameters handshake.ConnectionParametersManager, rttStats *congestion.RTTStats) FlowControlManager {
+ return &flowControlManager{
+ connectionParameters: connectionParameters,
+ rttStats: rttStats,
+ streamFlowController: make(map[protocol.StreamID]*flowController),
+ connFlowController: newFlowController(0, false, connectionParameters, rttStats),
+ }
+}
+
+// NewStream creates new flow controllers for a stream
+// it does nothing if the stream already exists
+func (f *flowControlManager) NewStream(streamID protocol.StreamID, contributesToConnection bool) {
+ f.mutex.Lock()
+ defer f.mutex.Unlock()
+
+ if _, ok := f.streamFlowController[streamID]; ok {
+ return
+ }
+
+ f.streamFlowController[streamID] = newFlowController(streamID, contributesToConnection, f.connectionParameters, f.rttStats)
+}
+
+// RemoveStream removes a closed stream from flow control
+func (f *flowControlManager) RemoveStream(streamID protocol.StreamID) {
+ f.mutex.Lock()
+ delete(f.streamFlowController, streamID)
+ f.mutex.Unlock()
+}
+
+// ResetStream should be called when receiving a RstStreamFrame
+// it updates the byte offset to the value in the RstStreamFrame
+// streamID must not be 0 here
+func (f *flowControlManager) ResetStream(streamID protocol.StreamID, byteOffset protocol.ByteCount) error {
+ f.mutex.Lock()
+ defer f.mutex.Unlock()
+
+ streamFlowController, err := f.getFlowController(streamID)
+ if err != nil {
+ return err
+ }
+ increment, err := streamFlowController.UpdateHighestReceived(byteOffset)
+ if err != nil {
+ return qerr.StreamDataAfterTermination
+ }
+
+ if streamFlowController.CheckFlowControlViolation() {
+ return qerr.Error(qerr.FlowControlReceivedTooMuchData, fmt.Sprintf("Received %d bytes on stream %d, allowed %d bytes", byteOffset, streamID, streamFlowController.receiveWindow))
+ }
+
+ if streamFlowController.ContributesToConnection() {
+ f.connFlowController.IncrementHighestReceived(increment)
+ if f.connFlowController.CheckFlowControlViolation() {
+ return qerr.Error(qerr.FlowControlReceivedTooMuchData, fmt.Sprintf("Received %d bytes for the connection, allowed %d bytes", f.connFlowController.highestReceived, f.connFlowController.receiveWindow))
+ }
+ }
+
+ return nil
+}
+
+// UpdateHighestReceived updates the highest received byte offset for a stream
+// it adds the number of additional bytes to connection level flow control
+// streamID must not be 0 here
+func (f *flowControlManager) UpdateHighestReceived(streamID protocol.StreamID, byteOffset protocol.ByteCount) error {
+ f.mutex.Lock()
+ defer f.mutex.Unlock()
+
+ streamFlowController, err := f.getFlowController(streamID)
+ if err != nil {
+ return err
+ }
+ // UpdateHighestReceived returns an ErrReceivedSmallerByteOffset when StreamFrames got reordered
+ // this error can be ignored here
+ increment, _ := streamFlowController.UpdateHighestReceived(byteOffset)
+
+ if streamFlowController.CheckFlowControlViolation() {
+ return qerr.Error(qerr.FlowControlReceivedTooMuchData, fmt.Sprintf("Received %d bytes on stream %d, allowed %d bytes", byteOffset, streamID, streamFlowController.receiveWindow))
+ }
+
+ if streamFlowController.ContributesToConnection() {
+ f.connFlowController.IncrementHighestReceived(increment)
+ if f.connFlowController.CheckFlowControlViolation() {
+ return qerr.Error(qerr.FlowControlReceivedTooMuchData, fmt.Sprintf("Received %d bytes for the connection, allowed %d bytes", f.connFlowController.highestReceived, f.connFlowController.receiveWindow))
+ }
+ }
+
+ return nil
+}
+
+// streamID must not be 0 here
+func (f *flowControlManager) AddBytesRead(streamID protocol.StreamID, n protocol.ByteCount) error {
+ f.mutex.Lock()
+ defer f.mutex.Unlock()
+
+ fc, err := f.getFlowController(streamID)
+ if err != nil {
+ return err
+ }
+
+ fc.AddBytesRead(n)
+ if fc.ContributesToConnection() {
+ f.connFlowController.AddBytesRead(n)
+ }
+
+ return nil
+}
+
+func (f *flowControlManager) GetWindowUpdates() (res []WindowUpdate) {
+ f.mutex.Lock()
+ defer f.mutex.Unlock()
+
+ // get WindowUpdates for streams
+ for id, fc := range f.streamFlowController {
+ if necessary, newIncrement, offset := fc.MaybeUpdateWindow(); necessary {
+ res = append(res, WindowUpdate{StreamID: id, Offset: offset})
+ if fc.ContributesToConnection() && newIncrement != 0 {
+ f.connFlowController.EnsureMinimumWindowIncrement(protocol.ByteCount(float64(newIncrement) * protocol.ConnectionFlowControlMultiplier))
+ }
+ }
+ }
+ // get a WindowUpdate for the connection
+ if necessary, _, offset := f.connFlowController.MaybeUpdateWindow(); necessary {
+ res = append(res, WindowUpdate{StreamID: 0, Offset: offset})
+ }
+
+ return
+}
+
+func (f *flowControlManager) GetReceiveWindow(streamID protocol.StreamID) (protocol.ByteCount, error) {
+ f.mutex.RLock()
+ defer f.mutex.RUnlock()
+
+ // StreamID can be 0 when retransmitting
+ if streamID == 0 {
+ return f.connFlowController.receiveWindow, nil
+ }
+
+ flowController, err := f.getFlowController(streamID)
+ if err != nil {
+ return 0, err
+ }
+ return flowController.receiveWindow, nil
+}
+
+// streamID must not be 0 here
+func (f *flowControlManager) AddBytesSent(streamID protocol.StreamID, n protocol.ByteCount) error {
+ f.mutex.Lock()
+ defer f.mutex.Unlock()
+
+ fc, err := f.getFlowController(streamID)
+ if err != nil {
+ return err
+ }
+
+ fc.AddBytesSent(n)
+ if fc.ContributesToConnection() {
+ f.connFlowController.AddBytesSent(n)
+ }
+
+ return nil
+}
+
+// must not be called with StreamID 0
+func (f *flowControlManager) SendWindowSize(streamID protocol.StreamID) (protocol.ByteCount, error) {
+ f.mutex.RLock()
+ defer f.mutex.RUnlock()
+
+ fc, err := f.getFlowController(streamID)
+ if err != nil {
+ return 0, err
+ }
+ res := fc.SendWindowSize()
+
+ if fc.ContributesToConnection() {
+ res = utils.MinByteCount(res, f.connFlowController.SendWindowSize())
+ }
+
+ return res, nil
+}
+
+func (f *flowControlManager) RemainingConnectionWindowSize() protocol.ByteCount {
+ f.mutex.RLock()
+ defer f.mutex.RUnlock()
+
+ return f.connFlowController.SendWindowSize()
+}
+
+// streamID may be 0 here
+func (f *flowControlManager) UpdateWindow(streamID protocol.StreamID, offset protocol.ByteCount) (bool, error) {
+ f.mutex.Lock()
+ defer f.mutex.Unlock()
+
+ var fc *flowController
+ if streamID == 0 {
+ fc = f.connFlowController
+ } else {
+ var err error
+ fc, err = f.getFlowController(streamID)
+ if err != nil {
+ return false, err
+ }
+ }
+
+ return fc.UpdateSendWindow(offset), nil
+}
+
+func (f *flowControlManager) getFlowController(streamID protocol.StreamID) (*flowController, error) {
+ streamFlowController, ok := f.streamFlowController[streamID]
+ if !ok {
+ return nil, errMapAccess
+ }
+ return streamFlowController, nil
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_controller.go b/vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_controller.go
new file mode 100644
index 0000000..387ee05
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/flowcontrol/flow_controller.go
@@ -0,0 +1,198 @@
+package flowcontrol
+
+import (
+ "errors"
+ "time"
+
+ "github.com/lucas-clemente/quic-go/congestion"
+ "github.com/lucas-clemente/quic-go/handshake"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+)
+
+type flowController struct {
+ streamID protocol.StreamID
+ contributesToConnection bool // does the stream contribute to connection level flow control
+
+ connectionParameters handshake.ConnectionParametersManager
+ rttStats *congestion.RTTStats
+
+ bytesSent protocol.ByteCount
+ sendWindow protocol.ByteCount
+
+ lastWindowUpdateTime time.Time
+
+ bytesRead protocol.ByteCount
+ highestReceived protocol.ByteCount
+ receiveWindow protocol.ByteCount
+ receiveWindowIncrement protocol.ByteCount
+ maxReceiveWindowIncrement protocol.ByteCount
+}
+
+// ErrReceivedSmallerByteOffset occurs if the ByteOffset received is smaller than a ByteOffset that was set previously
+var ErrReceivedSmallerByteOffset = errors.New("Received a smaller byte offset")
+
+// newFlowController gets a new flow controller
+func newFlowController(streamID protocol.StreamID, contributesToConnection bool, connectionParameters handshake.ConnectionParametersManager, rttStats *congestion.RTTStats) *flowController {
+ fc := flowController{
+ streamID: streamID,
+ contributesToConnection: contributesToConnection,
+ connectionParameters: connectionParameters,
+ rttStats: rttStats,
+ }
+
+ if streamID == 0 {
+ fc.receiveWindow = connectionParameters.GetReceiveConnectionFlowControlWindow()
+ fc.receiveWindowIncrement = fc.receiveWindow
+ fc.maxReceiveWindowIncrement = connectionParameters.GetMaxReceiveConnectionFlowControlWindow()
+ } else {
+ fc.receiveWindow = connectionParameters.GetReceiveStreamFlowControlWindow()
+ fc.receiveWindowIncrement = fc.receiveWindow
+ fc.maxReceiveWindowIncrement = connectionParameters.GetMaxReceiveStreamFlowControlWindow()
+ }
+
+ return &fc
+}
+
+func (c *flowController) ContributesToConnection() bool {
+ return c.contributesToConnection
+}
+
+func (c *flowController) getSendWindow() protocol.ByteCount {
+ if c.sendWindow == 0 {
+ if c.streamID == 0 {
+ return c.connectionParameters.GetSendConnectionFlowControlWindow()
+ }
+ return c.connectionParameters.GetSendStreamFlowControlWindow()
+ }
+ return c.sendWindow
+}
+
+func (c *flowController) AddBytesSent(n protocol.ByteCount) {
+ c.bytesSent += n
+}
+
+// UpdateSendWindow should be called after receiving a WindowUpdateFrame
+// it returns true if the window was actually updated
+func (c *flowController) UpdateSendWindow(newOffset protocol.ByteCount) bool {
+ if newOffset > c.sendWindow {
+ c.sendWindow = newOffset
+ return true
+ }
+ return false
+}
+
+func (c *flowController) SendWindowSize() protocol.ByteCount {
+ sendWindow := c.getSendWindow()
+
+ if c.bytesSent > sendWindow { // should never happen, but make sure we don't do an underflow here
+ return 0
+ }
+ return sendWindow - c.bytesSent
+}
+
+func (c *flowController) SendWindowOffset() protocol.ByteCount {
+ return c.getSendWindow()
+}
+
+// UpdateHighestReceived updates the highestReceived value, if the byteOffset is higher
+// Should **only** be used for the stream-level FlowController
+// it returns an ErrReceivedSmallerByteOffset if the received byteOffset is smaller than any byteOffset received before
+// This error occurs every time StreamFrames get reordered and has to be ignored in that case
+// It should only be treated as an error when resetting a stream
+func (c *flowController) UpdateHighestReceived(byteOffset protocol.ByteCount) (protocol.ByteCount, error) {
+ if byteOffset == c.highestReceived {
+ return 0, nil
+ }
+ if byteOffset > c.highestReceived {
+ increment := byteOffset - c.highestReceived
+ c.highestReceived = byteOffset
+ return increment, nil
+ }
+ return 0, ErrReceivedSmallerByteOffset
+}
+
+// IncrementHighestReceived adds an increment to the highestReceived value
+// Should **only** be used for the connection-level FlowController
+func (c *flowController) IncrementHighestReceived(increment protocol.ByteCount) {
+ c.highestReceived += increment
+}
+
+func (c *flowController) AddBytesRead(n protocol.ByteCount) {
+ // pretend we sent a WindowUpdate when reading the first byte
+ // this way auto-tuning of the window increment already works for the first WindowUpdate
+ if c.bytesRead == 0 {
+ c.lastWindowUpdateTime = time.Now()
+ }
+ c.bytesRead += n
+}
+
+// MaybeUpdateWindow updates the receive window, if necessary
+// if the receive window increment is changed, the new value is returned, otherwise a 0
+// the last return value is the new offset of the receive window
+func (c *flowController) MaybeUpdateWindow() (bool, protocol.ByteCount /* new increment */, protocol.ByteCount /* new offset */) {
+ diff := c.receiveWindow - c.bytesRead
+
+ // Chromium implements the same threshold
+ if diff < (c.receiveWindowIncrement / 2) {
+ var newWindowIncrement protocol.ByteCount
+ oldWindowIncrement := c.receiveWindowIncrement
+
+ c.maybeAdjustWindowIncrement()
+ if c.receiveWindowIncrement != oldWindowIncrement {
+ newWindowIncrement = c.receiveWindowIncrement
+ }
+
+ c.lastWindowUpdateTime = time.Now()
+ c.receiveWindow = c.bytesRead + c.receiveWindowIncrement
+ return true, newWindowIncrement, c.receiveWindow
+ }
+
+ return false, 0, 0
+}
+
+// maybeAdjustWindowIncrement increases the receiveWindowIncrement if we're sending WindowUpdates too often
+func (c *flowController) maybeAdjustWindowIncrement() {
+ if c.lastWindowUpdateTime.IsZero() {
+ return
+ }
+
+ rtt := c.rttStats.SmoothedRTT()
+ if rtt == 0 {
+ return
+ }
+
+ timeSinceLastWindowUpdate := time.Since(c.lastWindowUpdateTime)
+
+ // interval between the window updates is sufficiently large, no need to increase the increment
+ if timeSinceLastWindowUpdate >= 2*rtt {
+ return
+ }
+
+ oldWindowSize := c.receiveWindowIncrement
+ c.receiveWindowIncrement = utils.MinByteCount(2*c.receiveWindowIncrement, c.maxReceiveWindowIncrement)
+
+ // debug log, if the window size was actually increased
+ if oldWindowSize < c.receiveWindowIncrement {
+ newWindowSize := c.receiveWindowIncrement / (1 << 10)
+ if c.streamID == 0 {
+ utils.Debugf("Increasing receive flow control window for the connection to %d kB", newWindowSize)
+ } else {
+ utils.Debugf("Increasing receive flow control window increment for stream %d to %d kB", c.streamID, newWindowSize)
+ }
+ }
+}
+
+// EnsureMinimumWindowIncrement sets a minimum window increment
+// it is intended be used for the connection-level flow controller
+// it should make sure that the connection-level window is increased when a stream-level window grows
+func (c *flowController) EnsureMinimumWindowIncrement(inc protocol.ByteCount) {
+ if inc > c.receiveWindowIncrement {
+ c.receiveWindowIncrement = utils.MinByteCount(inc, c.maxReceiveWindowIncrement)
+ c.lastWindowUpdateTime = time.Time{} // disables autotuning for the next window update
+ }
+}
+
+func (c *flowController) CheckFlowControlViolation() bool {
+ return c.highestReceived > c.receiveWindow
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/flowcontrol/interface.go b/vendor/github.com/lucas-clemente/quic-go/flowcontrol/interface.go
similarity index 86%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/flowcontrol/interface.go
rename to vendor/github.com/lucas-clemente/quic-go/flowcontrol/interface.go
index 3f4b089..e1ea3fa 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/flowcontrol/interface.go
+++ b/vendor/github.com/lucas-clemente/quic-go/flowcontrol/interface.go
@@ -13,9 +13,11 @@ type FlowControlManager interface {
NewStream(streamID protocol.StreamID, contributesToConnectionFlow bool)
RemoveStream(streamID protocol.StreamID)
// methods needed for receiving data
+ ResetStream(streamID protocol.StreamID, byteOffset protocol.ByteCount) error
UpdateHighestReceived(streamID protocol.StreamID, byteOffset protocol.ByteCount) error
AddBytesRead(streamID protocol.StreamID, n protocol.ByteCount) error
GetWindowUpdates() []WindowUpdate
+ GetReceiveWindow(streamID protocol.StreamID) (protocol.ByteCount, error)
// methods needed for sending data
AddBytesSent(streamID protocol.StreamID, n protocol.ByteCount) error
SendWindowSize(streamID protocol.StreamID) (protocol.ByteCount, error)
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/ack_frame.go b/vendor/github.com/lucas-clemente/quic-go/frames/ack_frame.go
similarity index 95%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/ack_frame.go
rename to vendor/github.com/lucas-clemente/quic-go/frames/ack_frame.go
index b68b448..ceeba48 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/ack_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/frames/ack_frame.go
@@ -5,8 +5,8 @@ import (
"errors"
"time"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
)
var (
@@ -27,8 +27,10 @@ type AckFrame struct {
LowestAcked protocol.PacketNumber
AckRanges []AckRange // has to be ordered. The ACK range with the highest FirstPacketNumber goes first, the ACK range with the lowest FirstPacketNumber goes last
+ // time when the LargestAcked was receiveid
+ // this field Will not be set for received ACKs frames
+ PacketReceivedTime time.Time
DelayTime time.Duration
- PacketReceivedTime time.Time // only for received packets. Will not be modified for received ACKs frames
}
// ParseAckFrame reads an ACK frame
@@ -83,7 +85,7 @@ func ParseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame,
if err != nil {
return nil, err
}
- if ackBlockLength < 1 {
+ if frame.LargestAcked > 0 && ackBlockLength < 1 {
return nil, ErrInvalidFirstAckRange
}
@@ -141,7 +143,11 @@ func ParseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame,
frame.LowestAcked = frame.AckRanges[len(frame.AckRanges)-1].FirstPacketNumber
} else {
- frame.LowestAcked = protocol.PacketNumber(largestAcked + 1 - ackBlockLength)
+ if frame.LargestAcked == 0 {
+ frame.LowestAcked = 0
+ } else {
+ frame.LowestAcked = protocol.PacketNumber(largestAcked + 1 - ackBlockLength)
+ }
}
if !frame.validateAckRanges() {
@@ -216,7 +222,7 @@ func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error
utils.WriteUint48(b, uint64(f.LargestAcked))
}
- f.DelayTime = time.Now().Sub(f.PacketReceivedTime)
+ f.DelayTime = time.Since(f.PacketReceivedTime)
utils.WriteUfloat16(b, uint64(f.DelayTime/time.Microsecond))
var numRanges uint64
@@ -326,8 +332,7 @@ func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error
// MinLength of a written frame
func (f *AckFrame) MinLength(version protocol.VersionNumber) (protocol.ByteCount, error) {
- var length protocol.ByteCount
- length = 1 + 2 + 1 // 1 TypeByte, 2 ACK delay time, 1 Num Timestamp
+ length := protocol.ByteCount(1 + 2 + 1) // 1 TypeByte, 2 ACK delay time, 1 Num Timestamp
length += protocol.ByteCount(protocol.GetPacketNumberLength(f.LargestAcked))
missingSequenceNumberDeltaLen := protocol.ByteCount(f.getMissingSequenceNumberDeltaLen())
@@ -345,10 +350,7 @@ func (f *AckFrame) MinLength(version protocol.VersionNumber) (protocol.ByteCount
// HasMissingRanges returns if this frame reports any missing packets
func (f *AckFrame) HasMissingRanges() bool {
- if len(f.AckRanges) > 0 {
- return true
- }
- return false
+ return len(f.AckRanges) > 0
}
func (f *AckFrame) validateAckRanges() bool {
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/ack_range.go b/vendor/github.com/lucas-clemente/quic-go/frames/ack_range.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/ack_range.go
rename to vendor/github.com/lucas-clemente/quic-go/frames/ack_range.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/blocked_frame.go b/vendor/github.com/lucas-clemente/quic-go/frames/blocked_frame.go
similarity index 94%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/blocked_frame.go
rename to vendor/github.com/lucas-clemente/quic-go/frames/blocked_frame.go
index b7e640c..4464578 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/blocked_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/frames/blocked_frame.go
@@ -3,8 +3,8 @@ package frames
import (
"bytes"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
)
// A BlockedFrame in QUIC
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/connection_close_frame.go b/vendor/github.com/lucas-clemente/quic-go/frames/connection_close_frame.go
similarity index 97%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/connection_close_frame.go
rename to vendor/github.com/lucas-clemente/quic-go/frames/connection_close_frame.go
index 5681414..5a7ed04 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/connection_close_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/frames/connection_close_frame.go
@@ -6,9 +6,9 @@ import (
"io"
"math"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
)
// A ConnectionCloseFrame in QUIC
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/frame.go b/vendor/github.com/lucas-clemente/quic-go/frames/frame.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/frame.go
rename to vendor/github.com/lucas-clemente/quic-go/frames/frame.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/goaway_frame.go b/vendor/github.com/lucas-clemente/quic-go/frames/goaway_frame.go
similarity index 96%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/goaway_frame.go
rename to vendor/github.com/lucas-clemente/quic-go/frames/goaway_frame.go
index 7d452d5..e00a6cf 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/goaway_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/frames/goaway_frame.go
@@ -4,9 +4,9 @@ import (
"bytes"
"io"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
)
// A GoawayFrame is a GOAWAY frame
diff --git a/vendor/github.com/lucas-clemente/quic-go/frames/log.go b/vendor/github.com/lucas-clemente/quic-go/frames/log.go
new file mode 100644
index 0000000..6b7fdce
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/frames/log.go
@@ -0,0 +1,28 @@
+package frames
+
+import "github.com/lucas-clemente/quic-go/internal/utils"
+
+// LogFrame logs a frame, either sent or received
+func LogFrame(frame Frame, sent bool) {
+ if !utils.Debug() {
+ return
+ }
+ dir := "<-"
+ if sent {
+ dir = "->"
+ }
+ switch f := frame.(type) {
+ case *StreamFrame:
+ utils.Debugf("\t%s &frames.StreamFrame{StreamID: %d, FinBit: %t, Offset: 0x%x, Data length: 0x%x, Offset + Data length: 0x%x}", dir, f.StreamID, f.FinBit, f.Offset, f.DataLen(), f.Offset+f.DataLen())
+ case *StopWaitingFrame:
+ if sent {
+ utils.Debugf("\t%s &frames.StopWaitingFrame{LeastUnacked: 0x%x, PacketNumberLen: 0x%x}", dir, f.LeastUnacked, f.PacketNumberLen)
+ } else {
+ utils.Debugf("\t%s &frames.StopWaitingFrame{LeastUnacked: 0x%x}", dir, f.LeastUnacked)
+ }
+ case *AckFrame:
+ utils.Debugf("\t%s &frames.AckFrame{LargestAcked: 0x%x, LowestAcked: 0x%x, AckRanges: %#v, DelayTime: %s}", dir, f.LargestAcked, f.LowestAcked, f.AckRanges, f.DelayTime.String())
+ default:
+ utils.Debugf("\t%s %#v", dir, frame)
+ }
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/ping_frame.go b/vendor/github.com/lucas-clemente/quic-go/frames/ping_frame.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/ping_frame.go
rename to vendor/github.com/lucas-clemente/quic-go/frames/ping_frame.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/rst_stream_frame.go b/vendor/github.com/lucas-clemente/quic-go/frames/rst_stream_frame.go
similarity index 95%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/rst_stream_frame.go
rename to vendor/github.com/lucas-clemente/quic-go/frames/rst_stream_frame.go
index 8777875..ea2531c 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/rst_stream_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/frames/rst_stream_frame.go
@@ -3,8 +3,8 @@ package frames
import (
"bytes"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
)
// A RstStreamFrame in QUIC
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/stop_waiting_frame.go b/vendor/github.com/lucas-clemente/quic-go/frames/stop_waiting_frame.go
similarity index 96%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/stop_waiting_frame.go
rename to vendor/github.com/lucas-clemente/quic-go/frames/stop_waiting_frame.go
index 8267825..91f937a 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/stop_waiting_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/frames/stop_waiting_frame.go
@@ -4,9 +4,9 @@ import (
"bytes"
"errors"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
)
// A StopWaitingFrame in QUIC
@@ -56,8 +56,7 @@ func (f *StopWaitingFrame) Write(b *bytes.Buffer, version protocol.VersionNumber
// MinLength of a written frame
func (f *StopWaitingFrame) MinLength(version protocol.VersionNumber) (protocol.ByteCount, error) {
- var minLength protocol.ByteCount
- minLength = 1 // typeByte
+ minLength := protocol.ByteCount(1) // typeByte
if f.PacketNumberLen == protocol.PacketNumberLenInvalid {
return 0, errPacketNumberLenNotSet
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/stream_frame.go b/vendor/github.com/lucas-clemente/quic-go/frames/stream_frame.go
similarity index 94%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/stream_frame.go
rename to vendor/github.com/lucas-clemente/quic-go/frames/stream_frame.go
index fa833f8..7dd6223 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/stream_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/frames/stream_frame.go
@@ -4,9 +4,9 @@ import (
"bytes"
"errors"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
)
// A StreamFrame of QUIC
@@ -64,7 +64,7 @@ func ParseStreamFrame(r *bytes.Reader) (*StreamFrame, error) {
return nil, qerr.Error(qerr.InvalidStreamData, "data len too large")
}
- if dataLen == 0 {
+ if !frame.DataLenPresent {
// The rest of the packet is data
dataLen = uint16(r.Len())
}
@@ -79,7 +79,11 @@ func ParseStreamFrame(r *bytes.Reader) (*StreamFrame, error) {
}
}
- if !frame.FinBit && len(frame.Data) == 0 {
+ if frame.Offset+frame.DataLen() < frame.Offset {
+ return nil, qerr.Error(qerr.InvalidStreamData, "data overflows maximum offset")
+ }
+
+ if !frame.FinBit && frame.DataLen() == 0 {
return nil, qerr.EmptyStreamFrameNoFin
}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/window_update_frame.go b/vendor/github.com/lucas-clemente/quic-go/frames/window_update_frame.go
similarity index 95%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/window_update_frame.go
rename to vendor/github.com/lucas-clemente/quic-go/frames/window_update_frame.go
index 93e7f8c..9b8b459 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/frames/window_update_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/frames/window_update_frame.go
@@ -3,8 +3,8 @@ package frames
import (
"bytes"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
)
// A WindowUpdateFrame in QUIC
diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/client.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/client.go
new file mode 100644
index 0000000..866b11a
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/client.go
@@ -0,0 +1,296 @@
+package h2quic
+
+import (
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "strings"
+ "sync"
+
+ "golang.org/x/net/http2"
+ "golang.org/x/net/http2/hpack"
+ "golang.org/x/net/idna"
+
+ quic "github.com/lucas-clemente/quic-go"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+ "github.com/lucas-clemente/quic-go/qerr"
+)
+
+type roundTripperOpts struct {
+ DisableCompression bool
+}
+
+var dialAddr = quic.DialAddr
+
+// client is a HTTP2 client doing QUIC requests
+type client struct {
+ mutex sync.RWMutex
+
+ tlsConf *tls.Config
+ config *quic.Config
+ opts *roundTripperOpts
+
+ hostname string
+ encryptionLevel protocol.EncryptionLevel
+ handshakeErr error
+ dialOnce sync.Once
+
+ session quic.Session
+ headerStream quic.Stream
+ headerErr *qerr.QuicError
+ headerErrored chan struct{} // this channel is closed if an error occurs on the header stream
+ requestWriter *requestWriter
+
+ responses map[protocol.StreamID]chan *http.Response
+}
+
+var _ http.RoundTripper = &client{}
+
+var defaultQuicConfig = &quic.Config{
+ RequestConnectionIDTruncation: true,
+ KeepAlive: true,
+}
+
+// newClient creates a new client
+func newClient(
+ hostname string,
+ tlsConfig *tls.Config,
+ opts *roundTripperOpts,
+ quicConfig *quic.Config,
+) *client {
+ config := defaultQuicConfig
+ if quicConfig != nil {
+ config = quicConfig
+ }
+ return &client{
+ hostname: authorityAddr("https", hostname),
+ responses: make(map[protocol.StreamID]chan *http.Response),
+ encryptionLevel: protocol.EncryptionUnencrypted,
+ tlsConf: tlsConfig,
+ config: config,
+ opts: opts,
+ headerErrored: make(chan struct{}),
+ }
+}
+
+// dial dials the connection
+func (c *client) dial() error {
+ var err error
+ c.session, err = dialAddr(c.hostname, c.tlsConf, c.config)
+ if err != nil {
+ return err
+ }
+
+ // once the version has been negotiated, open the header stream
+ c.headerStream, err = c.session.OpenStream()
+ if err != nil {
+ return err
+ }
+ if c.headerStream.StreamID() != 3 {
+ return errors.New("h2quic Client BUG: StreamID of Header Stream is not 3")
+ }
+ c.requestWriter = newRequestWriter(c.headerStream)
+ go c.handleHeaderStream()
+ return nil
+}
+
+func (c *client) handleHeaderStream() {
+ decoder := hpack.NewDecoder(4096, func(hf hpack.HeaderField) {})
+ h2framer := http2.NewFramer(nil, c.headerStream)
+
+ var lastStream protocol.StreamID
+
+ for {
+ frame, err := h2framer.ReadFrame()
+ if err != nil {
+ c.headerErr = qerr.Error(qerr.HeadersStreamDataDecompressFailure, "cannot read frame")
+ break
+ }
+ lastStream = protocol.StreamID(frame.Header().StreamID)
+ hframe, ok := frame.(*http2.HeadersFrame)
+ if !ok {
+ c.headerErr = qerr.Error(qerr.InvalidHeadersStreamData, "not a headers frame")
+ break
+ }
+ mhframe := &http2.MetaHeadersFrame{HeadersFrame: hframe}
+ mhframe.Fields, err = decoder.DecodeFull(hframe.HeaderBlockFragment())
+ if err != nil {
+ c.headerErr = qerr.Error(qerr.InvalidHeadersStreamData, "cannot read header fields")
+ break
+ }
+
+ c.mutex.RLock()
+ responseChan, ok := c.responses[protocol.StreamID(hframe.StreamID)]
+ c.mutex.RUnlock()
+ if !ok {
+ c.headerErr = qerr.Error(qerr.InternalError, fmt.Sprintf("h2client BUG: response channel for stream %d not found", lastStream))
+ break
+ }
+
+ rsp, err := responseFromHeaders(mhframe)
+ if err != nil {
+ c.headerErr = qerr.Error(qerr.InternalError, err.Error())
+ }
+ responseChan <- rsp
+ }
+
+ // stop all running request
+ utils.Debugf("Error handling header stream %d: %s", lastStream, c.headerErr.Error())
+ close(c.headerErrored)
+}
+
+// Roundtrip executes a request and returns a response
+func (c *client) RoundTrip(req *http.Request) (*http.Response, error) {
+ // TODO: add port to address, if it doesn't have one
+ if req.URL.Scheme != "https" {
+ return nil, errors.New("quic http2: unsupported scheme")
+ }
+ if authorityAddr("https", hostnameFromRequest(req)) != c.hostname {
+ return nil, fmt.Errorf("h2quic Client BUG: RoundTrip called for the wrong client (expected %s, got %s)", c.hostname, req.Host)
+ }
+
+ c.dialOnce.Do(func() {
+ c.handshakeErr = c.dial()
+ })
+
+ if c.handshakeErr != nil {
+ return nil, c.handshakeErr
+ }
+
+ hasBody := (req.Body != nil)
+
+ responseChan := make(chan *http.Response)
+ dataStream, err := c.session.OpenStreamSync()
+ if err != nil {
+ _ = c.CloseWithError(err)
+ return nil, err
+ }
+ c.mutex.Lock()
+ c.responses[dataStream.StreamID()] = responseChan
+ c.mutex.Unlock()
+
+ var requestedGzip bool
+ if !c.opts.DisableCompression && req.Header.Get("Accept-Encoding") == "" && req.Header.Get("Range") == "" && req.Method != "HEAD" {
+ requestedGzip = true
+ }
+ // TODO: add support for trailers
+ endStream := !hasBody
+ err = c.requestWriter.WriteRequest(req, dataStream.StreamID(), endStream, requestedGzip)
+ if err != nil {
+ _ = c.CloseWithError(err)
+ return nil, err
+ }
+
+ resc := make(chan error, 1)
+ if hasBody {
+ go func() {
+ resc <- c.writeRequestBody(dataStream, req.Body)
+ }()
+ }
+
+ var res *http.Response
+
+ var receivedResponse bool
+ var bodySent bool
+
+ if !hasBody {
+ bodySent = true
+ }
+
+ for !(bodySent && receivedResponse) {
+ select {
+ case res = <-responseChan:
+ receivedResponse = true
+ c.mutex.Lock()
+ delete(c.responses, dataStream.StreamID())
+ c.mutex.Unlock()
+ case err := <-resc:
+ bodySent = true
+ if err != nil {
+ return nil, err
+ }
+ case <-c.headerErrored:
+ // an error occured on the header stream
+ _ = c.CloseWithError(c.headerErr)
+ return nil, c.headerErr
+ }
+ }
+
+ // TODO: correctly set this variable
+ var streamEnded bool
+ isHead := (req.Method == "HEAD")
+
+ res = setLength(res, isHead, streamEnded)
+
+ if streamEnded || isHead {
+ res.Body = noBody
+ } else {
+ res.Body = dataStream
+ if requestedGzip && res.Header.Get("Content-Encoding") == "gzip" {
+ res.Header.Del("Content-Encoding")
+ res.Header.Del("Content-Length")
+ res.ContentLength = -1
+ res.Body = &gzipReader{body: res.Body}
+ res.Uncompressed = true
+ }
+ }
+
+ res.Request = req
+ return res, nil
+}
+
+func (c *client) writeRequestBody(dataStream quic.Stream, body io.ReadCloser) (err error) {
+ defer func() {
+ cerr := body.Close()
+ if err == nil {
+ // TODO: what to do with dataStream here? Maybe reset it?
+ err = cerr
+ }
+ }()
+
+ _, err = io.Copy(dataStream, body)
+ if err != nil {
+ // TODO: what to do with dataStream here? Maybe reset it?
+ return err
+ }
+ return dataStream.Close()
+}
+
+// Close closes the client
+func (c *client) CloseWithError(e error) error {
+ if c.session == nil {
+ return nil
+ }
+ return c.session.Close(e)
+}
+
+func (c *client) Close() error {
+ return c.CloseWithError(nil)
+}
+
+// copied from net/transport.go
+
+// authorityAddr returns a given authority (a host/IP, or host:port / ip:port)
+// and returns a host:port. The port 443 is added if needed.
+func authorityAddr(scheme string, authority string) (addr string) {
+ host, port, err := net.SplitHostPort(authority)
+ if err != nil { // authority didn't have a port
+ port = "443"
+ if scheme == "http" {
+ port = "80"
+ }
+ host = authority
+ }
+ if a, err := idna.ToASCII(host); err == nil {
+ host = a
+ }
+ // IPv6 address literal, without a port:
+ if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
+ return host + ":" + port
+ }
+ return net.JoinHostPort(host, port)
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/gzipreader.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/gzipreader.go
new file mode 100644
index 0000000..91c226b
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/gzipreader.go
@@ -0,0 +1,35 @@
+package h2quic
+
+// copied from net/transport.go
+
+// gzipReader wraps a response body so it can lazily
+// call gzip.NewReader on the first call to Read
+import (
+ "compress/gzip"
+ "io"
+)
+
+// call gzip.NewReader on the first call to Read
+type gzipReader struct {
+ body io.ReadCloser // underlying Response.Body
+ zr *gzip.Reader // lazily-initialized gzip reader
+ zerr error // sticky error
+}
+
+func (gz *gzipReader) Read(p []byte) (n int, err error) {
+ if gz.zerr != nil {
+ return 0, gz.zerr
+ }
+ if gz.zr == nil {
+ gz.zr, err = gzip.NewReader(gz.body)
+ if err != nil {
+ gz.zerr = err
+ return 0, err
+ }
+ }
+ return gz.zr.Read(p)
+}
+
+func (gz *gzipReader) Close() error {
+ return gz.body.Close()
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/request.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/request.go
new file mode 100644
index 0000000..911485e
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/request.go
@@ -0,0 +1,80 @@
+package h2quic
+
+import (
+ "crypto/tls"
+ "errors"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+
+ "golang.org/x/net/http2/hpack"
+)
+
+func requestFromHeaders(headers []hpack.HeaderField) (*http.Request, error) {
+ var path, authority, method, contentLengthStr string
+ httpHeaders := http.Header{}
+
+ for _, h := range headers {
+ switch h.Name {
+ case ":path":
+ path = h.Value
+ case ":method":
+ method = h.Value
+ case ":authority":
+ authority = h.Value
+ case "content-length":
+ contentLengthStr = h.Value
+ default:
+ if !h.IsPseudo() {
+ httpHeaders.Add(h.Name, h.Value)
+ }
+ }
+ }
+
+ // concatenate cookie headers, see https://tools.ietf.org/html/rfc6265#section-5.4
+ if len(httpHeaders["Cookie"]) > 0 {
+ httpHeaders.Set("Cookie", strings.Join(httpHeaders["Cookie"], "; "))
+ }
+
+ if len(path) == 0 || len(authority) == 0 || len(method) == 0 {
+ return nil, errors.New(":path, :authority and :method must not be empty")
+ }
+
+ u, err := url.Parse(path)
+ if err != nil {
+ return nil, err
+ }
+
+ var contentLength int64
+ if len(contentLengthStr) > 0 {
+ contentLength, err = strconv.ParseInt(contentLengthStr, 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return &http.Request{
+ Method: method,
+ URL: u,
+ Proto: "HTTP/2.0",
+ ProtoMajor: 2,
+ ProtoMinor: 0,
+ Header: httpHeaders,
+ Body: nil,
+ ContentLength: contentLength,
+ Host: authority,
+ RequestURI: path,
+ TLS: &tls.ConnectionState{},
+ }, nil
+}
+
+func hostnameFromRequest(req *http.Request) string {
+ if len(req.Host) > 0 {
+ return req.Host
+ }
+ if req.URL != nil {
+ return req.URL.Host
+ }
+ return ""
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/request_body.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/request_body.go
new file mode 100644
index 0000000..2d4d595
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/request_body.go
@@ -0,0 +1,29 @@
+package h2quic
+
+import (
+ "io"
+
+ quic "github.com/lucas-clemente/quic-go"
+)
+
+type requestBody struct {
+ requestRead bool
+ dataStream quic.Stream
+}
+
+// make sure the requestBody can be used as a http.Request.Body
+var _ io.ReadCloser = &requestBody{}
+
+func newRequestBody(stream quic.Stream) *requestBody {
+ return &requestBody{dataStream: stream}
+}
+
+func (b *requestBody) Read(p []byte) (int, error) {
+ b.requestRead = true
+ return b.dataStream.Read(p)
+}
+
+func (b *requestBody) Close() error {
+ // stream's Close() closes the write side, not the read side
+ return nil
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/request_writer.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/request_writer.go
new file mode 100644
index 0000000..dad591c
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/request_writer.go
@@ -0,0 +1,201 @@
+package h2quic
+
+import (
+ "bytes"
+ "fmt"
+ "net/http"
+ "strconv"
+ "strings"
+ "sync"
+
+ "golang.org/x/net/http2"
+ "golang.org/x/net/http2/hpack"
+ "golang.org/x/net/lex/httplex"
+
+ quic "github.com/lucas-clemente/quic-go"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+)
+
+type requestWriter struct {
+ mutex sync.Mutex
+ headerStream quic.Stream
+
+ henc *hpack.Encoder
+ hbuf bytes.Buffer // HPACK encoder writes into this
+}
+
+const defaultUserAgent = "quic-go"
+
+func newRequestWriter(headerStream quic.Stream) *requestWriter {
+ rw := &requestWriter{
+ headerStream: headerStream,
+ }
+ rw.henc = hpack.NewEncoder(&rw.hbuf)
+ return rw
+}
+
+func (w *requestWriter) WriteRequest(req *http.Request, dataStreamID protocol.StreamID, endStream, requestGzip bool) error {
+ // TODO: add support for trailers
+ // TODO: add support for gzip compression
+ // TODO: write continuation frames, if the header frame is too long
+
+ w.mutex.Lock()
+ defer w.mutex.Unlock()
+
+ w.encodeHeaders(req, requestGzip, "", actualContentLength(req))
+ h2framer := http2.NewFramer(w.headerStream, nil)
+ return h2framer.WriteHeaders(http2.HeadersFrameParam{
+ StreamID: uint32(dataStreamID),
+ EndHeaders: true,
+ EndStream: endStream,
+ BlockFragment: w.hbuf.Bytes(),
+ Priority: http2.PriorityParam{Weight: 0xff},
+ })
+}
+
+// the rest of this files is copied from http2.Transport
+func (w *requestWriter) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) {
+ w.hbuf.Reset()
+
+ host := req.Host
+ if host == "" {
+ host = req.URL.Host
+ }
+ host, err := httplex.PunycodeHostPort(host)
+ if err != nil {
+ return nil, err
+ }
+
+ var path string
+ if req.Method != "CONNECT" {
+ path = req.URL.RequestURI()
+ if !validPseudoPath(path) {
+ orig := path
+ path = strings.TrimPrefix(path, req.URL.Scheme+"://"+host)
+ if !validPseudoPath(path) {
+ if req.URL.Opaque != "" {
+ return nil, fmt.Errorf("invalid request :path %q from URL.Opaque = %q", orig, req.URL.Opaque)
+ } else {
+ return nil, fmt.Errorf("invalid request :path %q", orig)
+ }
+ }
+ }
+ }
+
+ // Check for any invalid headers and return an error before we
+ // potentially pollute our hpack state. (We want to be able to
+ // continue to reuse the hpack encoder for future requests)
+ for k, vv := range req.Header {
+ if !httplex.ValidHeaderFieldName(k) {
+ return nil, fmt.Errorf("invalid HTTP header name %q", k)
+ }
+ for _, v := range vv {
+ if !httplex.ValidHeaderFieldValue(v) {
+ return nil, fmt.Errorf("invalid HTTP header value %q for header %q", v, k)
+ }
+ }
+ }
+
+ // 8.1.2.3 Request Pseudo-Header Fields
+ // The :path pseudo-header field includes the path and query parts of the
+ // target URI (the path-absolute production and optionally a '?' character
+ // followed by the query production (see Sections 3.3 and 3.4 of
+ // [RFC3986]).
+ w.writeHeader(":authority", host)
+ w.writeHeader(":method", req.Method)
+ if req.Method != "CONNECT" {
+ w.writeHeader(":path", path)
+ w.writeHeader(":scheme", req.URL.Scheme)
+ }
+ if trailers != "" {
+ w.writeHeader("trailer", trailers)
+ }
+
+ var didUA bool
+ for k, vv := range req.Header {
+ lowKey := strings.ToLower(k)
+ switch lowKey {
+ case "host", "content-length":
+ // Host is :authority, already sent.
+ // Content-Length is automatic, set below.
+ continue
+ case "connection", "proxy-connection", "transfer-encoding", "upgrade", "keep-alive":
+ // Per 8.1.2.2 Connection-Specific Header
+ // Fields, don't send connection-specific
+ // fields. We have already checked if any
+ // are error-worthy so just ignore the rest.
+ continue
+ case "user-agent":
+ // Match Go's http1 behavior: at most one
+ // User-Agent. If set to nil or empty string,
+ // then omit it. Otherwise if not mentioned,
+ // include the default (below).
+ didUA = true
+ if len(vv) < 1 {
+ continue
+ }
+ vv = vv[:1]
+ if vv[0] == "" {
+ continue
+ }
+ }
+ for _, v := range vv {
+ w.writeHeader(lowKey, v)
+ }
+ }
+ if shouldSendReqContentLength(req.Method, contentLength) {
+ w.writeHeader("content-length", strconv.FormatInt(contentLength, 10))
+ }
+ if addGzipHeader {
+ w.writeHeader("accept-encoding", "gzip")
+ }
+ if !didUA {
+ w.writeHeader("user-agent", defaultUserAgent)
+ }
+ return w.hbuf.Bytes(), nil
+}
+
+func (w *requestWriter) writeHeader(name, value string) {
+ utils.Debugf("http2: Transport encoding header %q = %q", name, value)
+ w.henc.WriteField(hpack.HeaderField{Name: name, Value: value})
+}
+
+// shouldSendReqContentLength reports whether the http2.Transport should send
+// a "content-length" request header. This logic is basically a copy of the net/http
+// transferWriter.shouldSendContentLength.
+// The contentLength is the corrected contentLength (so 0 means actually 0, not unknown).
+// -1 means unknown.
+func shouldSendReqContentLength(method string, contentLength int64) bool {
+ if contentLength > 0 {
+ return true
+ }
+ if contentLength < 0 {
+ return false
+ }
+ // For zero bodies, whether we send a content-length depends on the method.
+ // It also kinda doesn't matter for http2 either way, with END_STREAM.
+ switch method {
+ case "POST", "PUT", "PATCH":
+ return true
+ default:
+ return false
+ }
+}
+
+func validPseudoPath(v string) bool {
+ return (len(v) > 0 && v[0] == '/' && (len(v) == 1 || v[1] != '/')) || v == "*"
+}
+
+// actualContentLength returns a sanitized version of
+// req.ContentLength, where 0 actually means zero (not unknown) and -1
+// means unknown.
+func actualContentLength(req *http.Request) int64 {
+ if req.Body == nil {
+ return 0
+ }
+ if req.ContentLength != 0 {
+ return req.ContentLength
+ }
+ return -1
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/response.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/response.go
new file mode 100644
index 0000000..13efdf8
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/response.go
@@ -0,0 +1,111 @@
+package h2quic
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/textproto"
+ "strconv"
+ "strings"
+
+ "golang.org/x/net/http2"
+)
+
+// copied from net/http2/transport.go
+
+var errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
+var noBody io.ReadCloser = ioutil.NopCloser(bytes.NewReader(nil))
+
+// from the handleResponse function
+func responseFromHeaders(f *http2.MetaHeadersFrame) (*http.Response, error) {
+ if f.Truncated {
+ return nil, errResponseHeaderListSize
+ }
+
+ status := f.PseudoValue("status")
+ if status == "" {
+ return nil, errors.New("missing status pseudo header")
+ }
+ statusCode, err := strconv.Atoi(status)
+ if err != nil {
+ return nil, errors.New("malformed non-numeric status pseudo header")
+ }
+
+ if statusCode == 100 {
+ // TODO: handle this
+
+ // traceGot100Continue(cs.trace)
+ // if cs.on100 != nil {
+ // cs.on100() // forces any write delay timer to fire
+ // }
+ // cs.pastHeaders = false // do it all again
+ // return nil, nil
+ }
+
+ header := make(http.Header)
+ res := &http.Response{
+ Proto: "HTTP/2.0",
+ ProtoMajor: 2,
+ Header: header,
+ StatusCode: statusCode,
+ Status: status + " " + http.StatusText(statusCode),
+ }
+ for _, hf := range f.RegularFields() {
+ key := http.CanonicalHeaderKey(hf.Name)
+ if key == "Trailer" {
+ t := res.Trailer
+ if t == nil {
+ t = make(http.Header)
+ res.Trailer = t
+ }
+ foreachHeaderElement(hf.Value, func(v string) {
+ t[http.CanonicalHeaderKey(v)] = nil
+ })
+ } else {
+ header[key] = append(header[key], hf.Value)
+ }
+ }
+
+ return res, nil
+}
+
+// continuation of the handleResponse function
+func setLength(res *http.Response, isHead, streamEnded bool) *http.Response {
+ if !streamEnded || isHead {
+ res.ContentLength = -1
+ if clens := res.Header["Content-Length"]; len(clens) == 1 {
+ if clen64, err := strconv.ParseInt(clens[0], 10, 64); err == nil {
+ res.ContentLength = clen64
+ } else {
+ // TODO: care? unlike http/1, it won't mess up our framing, so it's
+ // more safe smuggling-wise to ignore.
+ }
+ } else if len(clens) > 1 {
+ // TODO: care? unlike http/1, it won't mess up our framing, so it's
+ // more safe smuggling-wise to ignore.
+ }
+ }
+ return res
+}
+
+// copied from net/http/server.go
+
+// foreachHeaderElement splits v according to the "#rule" construction
+// in RFC 2616 section 2.1 and calls fn for each non-empty element.
+func foreachHeaderElement(v string, fn func(string)) {
+ v = textproto.TrimString(v)
+ if v == "" {
+ return
+ }
+ if !strings.Contains(v, ",") {
+ fn(v)
+ return
+ }
+ for _, f := range strings.Split(v, ",") {
+ if f = textproto.TrimString(f); f != "" {
+ fn(f)
+ }
+ }
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go
similarity index 61%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go
rename to vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go
index 0b5e930..2468934 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go
+++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go
@@ -7,24 +7,26 @@ import (
"strings"
"sync"
+ quic "github.com/lucas-clemente/quic-go"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
"golang.org/x/net/http2"
"golang.org/x/net/http2/hpack"
)
type responseWriter struct {
dataStreamID protocol.StreamID
- dataStream utils.Stream
+ dataStream quic.Stream
- headerStream utils.Stream
+ headerStream quic.Stream
headerStreamMutex *sync.Mutex
header http.Header
+ status int // status code passed to WriteHeader
headerWritten bool
}
-func newResponseWriter(headerStream utils.Stream, headerStreamMutex *sync.Mutex, dataStream utils.Stream, dataStreamID protocol.StreamID) *responseWriter {
+func newResponseWriter(headerStream quic.Stream, headerStreamMutex *sync.Mutex, dataStream quic.Stream, dataStreamID protocol.StreamID) *responseWriter {
return &responseWriter{
header: http.Header{},
headerStream: headerStream,
@@ -43,6 +45,7 @@ func (w *responseWriter) WriteHeader(status int) {
return
}
w.headerWritten = true
+ w.status = status
var headers bytes.Buffer
enc := hpack.NewEncoder(&headers)
@@ -72,10 +75,34 @@ func (w *responseWriter) Write(p []byte) (int, error) {
if !w.headerWritten {
w.WriteHeader(200)
}
+ if !bodyAllowedForStatus(w.status) {
+ return 0, http.ErrBodyNotAllowed
+ }
return w.dataStream.Write(p)
}
func (w *responseWriter) Flush() {}
+// TODO: Implement a functional CloseNotify method.
+func (w *responseWriter) CloseNotify() <-chan bool { return make(<-chan bool) }
+
// test that we implement http.Flusher
var _ http.Flusher = &responseWriter{}
+
+// test that we implement http.CloseNotifier
+var _ http.CloseNotifier = &responseWriter{}
+
+// copied from http2/http2.go
+// bodyAllowedForStatus reports whether a given response status code
+// permits a body. See RFC 2616, section 4.4.
+func bodyAllowedForStatus(status int) bool {
+ switch {
+ case status >= 100 && status <= 199:
+ return false
+ case status == 204:
+ return false
+ case status == 304:
+ return false
+ }
+ return true
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/roundtrip.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/roundtrip.go
new file mode 100644
index 0000000..9ac5f19
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/roundtrip.go
@@ -0,0 +1,168 @@
+package h2quic
+
+import (
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "strings"
+ "sync"
+
+ quic "github.com/lucas-clemente/quic-go"
+
+ "golang.org/x/net/lex/httplex"
+)
+
+type roundTripCloser interface {
+ http.RoundTripper
+ io.Closer
+}
+
+// RoundTripper implements the http.RoundTripper interface
+type RoundTripper struct {
+ mutex sync.Mutex
+
+ // DisableCompression, if true, prevents the Transport from
+ // requesting compression with an "Accept-Encoding: gzip"
+ // request header when the Request contains no existing
+ // Accept-Encoding value. If the Transport requests gzip on
+ // its own and gets a gzipped response, it's transparently
+ // decoded in the Response.Body. However, if the user
+ // explicitly requested gzip it is not automatically
+ // uncompressed.
+ DisableCompression bool
+
+ // TLSClientConfig specifies the TLS configuration to use with
+ // tls.Client. If nil, the default configuration is used.
+ TLSClientConfig *tls.Config
+
+ // QuicConfig is the quic.Config used for dialing new connections.
+ // If nil, reasonable default values will be used.
+ QuicConfig *quic.Config
+
+ clients map[string]roundTripCloser
+}
+
+// RoundTripOpt are options for the Transport.RoundTripOpt method.
+type RoundTripOpt struct {
+ // OnlyCachedConn controls whether the RoundTripper may
+ // create a new QUIC connection. If set true and
+ // no cached connection is available, RoundTrip
+ // will return ErrNoCachedConn.
+ OnlyCachedConn bool
+}
+
+var _ roundTripCloser = &RoundTripper{}
+
+// ErrNoCachedConn is returned when RoundTripper.OnlyCachedConn is set
+var ErrNoCachedConn = errors.New("h2quic: no cached connection was available")
+
+// RoundTripOpt is like RoundTrip, but takes options.
+func (r *RoundTripper) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
+ if req.URL == nil {
+ closeRequestBody(req)
+ return nil, errors.New("quic: nil Request.URL")
+ }
+ if req.URL.Host == "" {
+ closeRequestBody(req)
+ return nil, errors.New("quic: no Host in request URL")
+ }
+ if req.Header == nil {
+ closeRequestBody(req)
+ return nil, errors.New("quic: nil Request.Header")
+ }
+
+ if req.URL.Scheme == "https" {
+ for k, vv := range req.Header {
+ if !httplex.ValidHeaderFieldName(k) {
+ return nil, fmt.Errorf("quic: invalid http header field name %q", k)
+ }
+ for _, v := range vv {
+ if !httplex.ValidHeaderFieldValue(v) {
+ return nil, fmt.Errorf("quic: invalid http header field value %q for key %v", v, k)
+ }
+ }
+ }
+ } else {
+ closeRequestBody(req)
+ return nil, fmt.Errorf("quic: unsupported protocol scheme: %s", req.URL.Scheme)
+ }
+
+ if req.Method != "" && !validMethod(req.Method) {
+ closeRequestBody(req)
+ return nil, fmt.Errorf("quic: invalid method %q", req.Method)
+ }
+
+ hostname := authorityAddr("https", hostnameFromRequest(req))
+ cl, err := r.getClient(hostname, opt.OnlyCachedConn)
+ if err != nil {
+ return nil, err
+ }
+ return cl.RoundTrip(req)
+}
+
+// RoundTrip does a round trip.
+func (r *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
+ return r.RoundTripOpt(req, RoundTripOpt{})
+}
+
+func (r *RoundTripper) getClient(hostname string, onlyCached bool) (http.RoundTripper, error) {
+ r.mutex.Lock()
+ defer r.mutex.Unlock()
+
+ if r.clients == nil {
+ r.clients = make(map[string]roundTripCloser)
+ }
+
+ client, ok := r.clients[hostname]
+ if !ok {
+ if onlyCached {
+ return nil, ErrNoCachedConn
+ }
+ client = newClient(hostname, r.TLSClientConfig, &roundTripperOpts{DisableCompression: r.DisableCompression}, r.QuicConfig)
+ r.clients[hostname] = client
+ }
+ return client, nil
+}
+
+// Close closes the QUIC connections that this RoundTripper has used
+func (r *RoundTripper) Close() error {
+ r.mutex.Lock()
+ defer r.mutex.Unlock()
+ for _, client := range r.clients {
+ if err := client.Close(); err != nil {
+ return err
+ }
+ }
+ r.clients = nil
+ return nil
+}
+
+func closeRequestBody(req *http.Request) {
+ if req.Body != nil {
+ req.Body.Close()
+ }
+}
+
+func validMethod(method string) bool {
+ /*
+ Method = "OPTIONS" ; Section 9.2
+ | "GET" ; Section 9.3
+ | "HEAD" ; Section 9.4
+ | "POST" ; Section 9.5
+ | "PUT" ; Section 9.6
+ | "DELETE" ; Section 9.7
+ | "TRACE" ; Section 9.8
+ | "CONNECT" ; Section 9.9
+ | extension-method
+ extension-method = token
+ token = 1*
+ */
+ return len(method) > 0 && strings.IndexFunc(method, isNotToken) == -1
+}
+
+// copied from net/http/http.go
+func isNotToken(r rune) bool {
+ return !httplex.IsTokenRune(r)
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/h2quic/server.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/server.go
similarity index 74%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/h2quic/server.go
rename to vendor/github.com/lucas-clemente/quic-go/h2quic/server.go
index 4e301b5..3647dc6 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/h2quic/server.go
+++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/server.go
@@ -4,39 +4,54 @@ import (
"crypto/tls"
"errors"
"fmt"
- "io/ioutil"
"net"
"net/http"
"runtime"
+ "strconv"
"sync"
"sync/atomic"
"time"
- "github.com/lucas-clemente/quic-go"
+ quic "github.com/lucas-clemente/quic-go"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
"golang.org/x/net/http2"
"golang.org/x/net/http2/hpack"
)
type streamCreator interface {
- GetOrOpenStream(protocol.StreamID) (utils.Stream, error)
- Close(error) error
- RemoteAddr() *net.UDPAddr
+ quic.Session
+ GetOrOpenStream(protocol.StreamID) (quic.Stream, error)
}
+type remoteCloser interface {
+ CloseRemote(protocol.ByteCount)
+}
+
+// allows mocking of quic.Listen and quic.ListenAddr
+var (
+ quicListen = quic.Listen
+ quicListenAddr = quic.ListenAddr
+)
+
// Server is a HTTP2 server listening for QUIC connections.
type Server struct {
*http.Server
+ // By providing a quic.Config, it is possible to set parameters of the QUIC connection.
+ // If nil, it uses reasonable default values.
+ QuicConfig *quic.Config
+
// Private flag for demo, do not use
CloseAfterFirstRequest bool
port uint32 // used atomically
- server *quic.Server
- serverMutex sync.Mutex
+ listenerMutex sync.Mutex
+ listener quic.Listener
+
+ supportedVersionsAsString string
}
// ListenAndServe listens on the UDP address s.Addr and calls s.Handler to handle HTTP/2 requests on incoming connections.
@@ -64,39 +79,51 @@ func (s *Server) ListenAndServeTLS(certFile, keyFile string) error {
}
// Serve an existing UDP connection.
-func (s *Server) Serve(conn *net.UDPConn) error {
+func (s *Server) Serve(conn net.PacketConn) error {
return s.serveImpl(s.TLSConfig, conn)
}
-func (s *Server) serveImpl(tlsConfig *tls.Config, conn *net.UDPConn) error {
+func (s *Server) serveImpl(tlsConfig *tls.Config, conn net.PacketConn) error {
if s.Server == nil {
return errors.New("use of h2quic.Server without http.Server")
}
- s.serverMutex.Lock()
- if s.server != nil {
- s.serverMutex.Unlock()
+ s.listenerMutex.Lock()
+ if s.listener != nil {
+ s.listenerMutex.Unlock()
return errors.New("ListenAndServe may only be called once")
}
+
+ var ln quic.Listener
var err error
- server, err := quic.NewServer(s.Addr, tlsConfig, s.handleStreamCb)
+ if conn == nil {
+ ln, err = quicListenAddr(s.Addr, tlsConfig, s.QuicConfig)
+ } else {
+ ln, err = quicListen(conn, tlsConfig, s.QuicConfig)
+ }
if err != nil {
- s.serverMutex.Unlock()
+ s.listenerMutex.Unlock()
return err
}
- s.server = server
- s.serverMutex.Unlock()
- if conn == nil {
- return server.ListenAndServe()
+ s.listener = ln
+ s.listenerMutex.Unlock()
+
+ for {
+ sess, err := ln.Accept()
+ if err != nil {
+ return err
+ }
+ go s.handleHeaderStream(sess.(streamCreator))
}
- return server.Serve(conn)
}
-func (s *Server) handleStreamCb(session *quic.Session, stream utils.Stream) {
- s.handleStream(session, stream)
-}
-
-func (s *Server) handleStream(session streamCreator, stream utils.Stream) {
+func (s *Server) handleHeaderStream(session streamCreator) {
+ stream, err := session.AcceptStream()
+ if err != nil {
+ session.Close(qerr.Error(qerr.InvalidHeadersStreamData, err.Error()))
+ return
+ }
if stream.StreamID() != 3 {
+ session.Close(qerr.Error(qerr.InternalError, "h2quic server BUG: header stream does not have stream ID 3"))
return
}
@@ -113,18 +140,22 @@ func (s *Server) handleStream(session streamCreator, stream utils.Stream) {
if _, ok := err.(*qerr.QuicError); !ok {
utils.Errorf("error handling h2 request: %s", err.Error())
}
+ session.Close(err)
return
}
}
}()
}
-func (s *Server) handleRequest(session streamCreator, headerStream utils.Stream, headerStreamMutex *sync.Mutex, hpackDecoder *hpack.Decoder, h2framer *http2.Framer) error {
+func (s *Server) handleRequest(session streamCreator, headerStream quic.Stream, headerStreamMutex *sync.Mutex, hpackDecoder *hpack.Decoder, h2framer *http2.Framer) error {
h2frame, err := h2framer.ReadFrame()
if err != nil {
- return err
+ return qerr.Error(qerr.HeadersStreamDataDecompressFailure, "cannot read frame")
+ }
+ h2headersFrame, ok := h2frame.(*http2.HeadersFrame)
+ if !ok {
+ return qerr.Error(qerr.InvalidHeadersStreamData, "expected a header frame")
}
- h2headersFrame := h2frame.(*http2.HeadersFrame)
if !h2headersFrame.HeadersEnded() {
return errors.New("http2 header continuation not implemented")
}
@@ -151,14 +182,20 @@ func (s *Server) handleRequest(session streamCreator, headerStream utils.Stream,
if err != nil {
return err
}
+ // this can happen if the client immediately closes the data stream after sending the request and the runtime processes the reset before the request
+ if dataStream == nil {
+ return nil
+ }
+ var streamEnded bool
if h2headersFrame.StreamEnded() {
- dataStream.CloseRemote(0)
+ dataStream.(remoteCloser).CloseRemote(0)
+ streamEnded = true
_, _ = dataStream.Read([]byte{0}) // read the eof
}
- // stream's Close() closes the write side, not the read side
- req.Body = ioutil.NopCloser(dataStream)
+ reqBody := newRequestBody(dataStream)
+ req.Body = reqBody
responseWriter := newResponseWriter(headerStream, headerStreamMutex, dataStream, protocol.StreamID(h2headersFrame.StreamID))
@@ -187,6 +224,9 @@ func (s *Server) handleRequest(session streamCreator, headerStream utils.Stream,
responseWriter.WriteHeader(200)
}
if responseWriter.dataStream != nil {
+ if !streamEnded && !reqBody.requestRead {
+ responseWriter.dataStream.Reset(nil)
+ }
responseWriter.dataStream.Close()
}
if s.CloseAfterFirstRequest {
@@ -201,11 +241,11 @@ func (s *Server) handleRequest(session streamCreator, headerStream utils.Stream,
// Close the server immediately, aborting requests and sending CONNECTION_CLOSE frames to connected clients.
// Close in combination with ListenAndServe() (instead of Serve()) may race if it is called before a UDP socket is established.
func (s *Server) Close() error {
- s.serverMutex.Lock()
- defer s.serverMutex.Unlock()
- if s.server != nil {
- err := s.server.Close()
- s.server = nil
+ s.listenerMutex.Lock()
+ defer s.listenerMutex.Unlock()
+ if s.listener != nil {
+ err := s.listener.Close()
+ s.listener = nil
return err
}
return nil
@@ -220,7 +260,6 @@ func (s *Server) CloseGracefully(timeout time.Duration) error {
// SetQuicHeaders can be used to set the proper headers that announce that this server supports QUIC.
// The values that are set depend on the port information from s.Server.Addr, and currently look like this (if Addr has port 443):
-// Alternate-Protocol: 443:quic
// Alt-Svc: quic=":443"; ma=2592000; v="33,32,31,30"
func (s *Server) SetQuicHeaders(hdr http.Header) error {
port := atomic.LoadUint32(&s.port)
@@ -239,8 +278,16 @@ func (s *Server) SetQuicHeaders(hdr http.Header) error {
atomic.StoreUint32(&s.port, port)
}
- hdr.Add("Alternate-Protocol", fmt.Sprintf("%d:quic", port))
- hdr.Add("Alt-Svc", fmt.Sprintf(`quic=":%d"; ma=2592000; v="%s"`, port, protocol.SupportedVersionsAsString))
+ if s.supportedVersionsAsString == "" {
+ for i, v := range protocol.SupportedVersions {
+ s.supportedVersionsAsString += strconv.Itoa(int(v))
+ if i != len(protocol.SupportedVersions)-1 {
+ s.supportedVersionsAsString += ","
+ }
+ }
+ }
+
+ hdr.Add("Alt-Svc", fmt.Sprintf(`quic=":%d"; ma=2592000; v="%s"`, port, s.supportedVersionsAsString))
return nil
}
diff --git a/vendor/github.com/lucas-clemente/quic-go/handshake/connection_parameters_manager.go b/vendor/github.com/lucas-clemente/quic-go/handshake/connection_parameters_manager.go
new file mode 100644
index 0000000..1ad9a3a
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/handshake/connection_parameters_manager.go
@@ -0,0 +1,265 @@
+package handshake
+
+import (
+ "bytes"
+ "sync"
+ "time"
+
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+ "github.com/lucas-clemente/quic-go/qerr"
+)
+
+// ConnectionParametersManager negotiates and stores the connection parameters
+// A ConnectionParametersManager can be used for a server as well as a client
+// For the server:
+// 1. call SetFromMap with the values received in the CHLO. This sets the corresponding values here, subject to negotiation
+// 2. call GetHelloMap to get the values to send in the SHLO
+// For the client:
+// 1. call GetHelloMap to get the values to send in a CHLO
+// 2. call SetFromMap with the values received in the SHLO
+type ConnectionParametersManager interface {
+ SetFromMap(map[Tag][]byte) error
+ GetHelloMap() (map[Tag][]byte, error)
+
+ GetSendStreamFlowControlWindow() protocol.ByteCount
+ GetSendConnectionFlowControlWindow() protocol.ByteCount
+ GetReceiveStreamFlowControlWindow() protocol.ByteCount
+ GetMaxReceiveStreamFlowControlWindow() protocol.ByteCount
+ GetReceiveConnectionFlowControlWindow() protocol.ByteCount
+ GetMaxReceiveConnectionFlowControlWindow() protocol.ByteCount
+ GetMaxOutgoingStreams() uint32
+ GetMaxIncomingStreams() uint32
+ GetIdleConnectionStateLifetime() time.Duration
+ TruncateConnectionID() bool
+}
+
+type connectionParametersManager struct {
+ mutex sync.RWMutex
+
+ version protocol.VersionNumber
+ perspective protocol.Perspective
+
+ flowControlNegotiated bool
+
+ truncateConnectionID bool
+ maxStreamsPerConnection uint32
+ maxIncomingDynamicStreamsPerConnection uint32
+ idleConnectionStateLifetime time.Duration
+ sendStreamFlowControlWindow protocol.ByteCount
+ sendConnectionFlowControlWindow protocol.ByteCount
+ receiveStreamFlowControlWindow protocol.ByteCount
+ receiveConnectionFlowControlWindow protocol.ByteCount
+ maxReceiveStreamFlowControlWindow protocol.ByteCount
+ maxReceiveConnectionFlowControlWindow protocol.ByteCount
+}
+
+var _ ConnectionParametersManager = &connectionParametersManager{}
+
+// ErrMalformedTag is returned when the tag value cannot be read
+var (
+ ErrMalformedTag = qerr.Error(qerr.InvalidCryptoMessageParameter, "malformed Tag value")
+ ErrFlowControlRenegotiationNotSupported = qerr.Error(qerr.InvalidCryptoMessageParameter, "renegotiation of flow control parameters not supported")
+)
+
+// NewConnectionParamatersManager creates a new connection parameters manager
+func NewConnectionParamatersManager(
+ pers protocol.Perspective, v protocol.VersionNumber,
+ maxReceiveStreamFlowControlWindow protocol.ByteCount, maxReceiveConnectionFlowControlWindow protocol.ByteCount,
+) ConnectionParametersManager {
+ h := &connectionParametersManager{
+ perspective: pers,
+ version: v,
+ sendStreamFlowControlWindow: protocol.InitialStreamFlowControlWindow, // can only be changed by the client
+ sendConnectionFlowControlWindow: protocol.InitialConnectionFlowControlWindow, // can only be changed by the client
+ receiveStreamFlowControlWindow: protocol.ReceiveStreamFlowControlWindow,
+ receiveConnectionFlowControlWindow: protocol.ReceiveConnectionFlowControlWindow,
+ maxReceiveStreamFlowControlWindow: maxReceiveStreamFlowControlWindow,
+ maxReceiveConnectionFlowControlWindow: maxReceiveConnectionFlowControlWindow,
+ }
+
+ if h.perspective == protocol.PerspectiveServer {
+ h.idleConnectionStateLifetime = protocol.DefaultIdleTimeout
+ h.maxStreamsPerConnection = protocol.MaxStreamsPerConnection // this is the value negotiated based on what the client sent
+ h.maxIncomingDynamicStreamsPerConnection = protocol.MaxStreamsPerConnection // "incoming" seen from the client's perspective
+ } else {
+ h.idleConnectionStateLifetime = protocol.MaxIdleTimeoutClient
+ h.maxStreamsPerConnection = protocol.MaxStreamsPerConnection // this is the value negotiated based on what the client sent
+ h.maxIncomingDynamicStreamsPerConnection = protocol.MaxStreamsPerConnection // "incoming" seen from the server's perspective
+ }
+
+ return h
+}
+
+// SetFromMap reads all params
+func (h *connectionParametersManager) SetFromMap(params map[Tag][]byte) error {
+ h.mutex.Lock()
+ defer h.mutex.Unlock()
+
+ if value, ok := params[TagTCID]; ok && h.perspective == protocol.PerspectiveServer {
+ clientValue, err := utils.ReadUint32(bytes.NewBuffer(value))
+ if err != nil {
+ return ErrMalformedTag
+ }
+ h.truncateConnectionID = (clientValue == 0)
+ }
+ if value, ok := params[TagMSPC]; ok {
+ clientValue, err := utils.ReadUint32(bytes.NewBuffer(value))
+ if err != nil {
+ return ErrMalformedTag
+ }
+ h.maxStreamsPerConnection = h.negotiateMaxStreamsPerConnection(clientValue)
+ }
+ if value, ok := params[TagMIDS]; ok {
+ clientValue, err := utils.ReadUint32(bytes.NewBuffer(value))
+ if err != nil {
+ return ErrMalformedTag
+ }
+ h.maxIncomingDynamicStreamsPerConnection = h.negotiateMaxIncomingDynamicStreamsPerConnection(clientValue)
+ }
+ if value, ok := params[TagICSL]; ok {
+ clientValue, err := utils.ReadUint32(bytes.NewBuffer(value))
+ if err != nil {
+ return ErrMalformedTag
+ }
+ h.idleConnectionStateLifetime = h.negotiateIdleConnectionStateLifetime(time.Duration(clientValue) * time.Second)
+ }
+ if value, ok := params[TagSFCW]; ok {
+ if h.flowControlNegotiated {
+ return ErrFlowControlRenegotiationNotSupported
+ }
+ sendStreamFlowControlWindow, err := utils.ReadUint32(bytes.NewBuffer(value))
+ if err != nil {
+ return ErrMalformedTag
+ }
+ h.sendStreamFlowControlWindow = protocol.ByteCount(sendStreamFlowControlWindow)
+ }
+ if value, ok := params[TagCFCW]; ok {
+ if h.flowControlNegotiated {
+ return ErrFlowControlRenegotiationNotSupported
+ }
+ sendConnectionFlowControlWindow, err := utils.ReadUint32(bytes.NewBuffer(value))
+ if err != nil {
+ return ErrMalformedTag
+ }
+ h.sendConnectionFlowControlWindow = protocol.ByteCount(sendConnectionFlowControlWindow)
+ }
+
+ _, containsSFCW := params[TagSFCW]
+ _, containsCFCW := params[TagCFCW]
+ if containsCFCW || containsSFCW {
+ h.flowControlNegotiated = true
+ }
+
+ return nil
+}
+
+func (h *connectionParametersManager) negotiateMaxStreamsPerConnection(clientValue uint32) uint32 {
+ return utils.MinUint32(clientValue, protocol.MaxStreamsPerConnection)
+}
+
+func (h *connectionParametersManager) negotiateMaxIncomingDynamicStreamsPerConnection(clientValue uint32) uint32 {
+ return utils.MinUint32(clientValue, protocol.MaxIncomingDynamicStreamsPerConnection)
+}
+
+func (h *connectionParametersManager) negotiateIdleConnectionStateLifetime(clientValue time.Duration) time.Duration {
+ if h.perspective == protocol.PerspectiveServer {
+ return utils.MinDuration(clientValue, protocol.MaxIdleTimeoutServer)
+ }
+ return utils.MinDuration(clientValue, protocol.MaxIdleTimeoutClient)
+}
+
+// GetHelloMap gets all parameters needed for the Hello message
+func (h *connectionParametersManager) GetHelloMap() (map[Tag][]byte, error) {
+ sfcw := bytes.NewBuffer([]byte{})
+ utils.WriteUint32(sfcw, uint32(h.GetReceiveStreamFlowControlWindow()))
+ cfcw := bytes.NewBuffer([]byte{})
+ utils.WriteUint32(cfcw, uint32(h.GetReceiveConnectionFlowControlWindow()))
+ mspc := bytes.NewBuffer([]byte{})
+ utils.WriteUint32(mspc, h.maxStreamsPerConnection)
+ mids := bytes.NewBuffer([]byte{})
+ utils.WriteUint32(mids, protocol.MaxIncomingDynamicStreamsPerConnection)
+ icsl := bytes.NewBuffer([]byte{})
+ utils.WriteUint32(icsl, uint32(h.GetIdleConnectionStateLifetime()/time.Second))
+
+ return map[Tag][]byte{
+ TagICSL: icsl.Bytes(),
+ TagMSPC: mspc.Bytes(),
+ TagMIDS: mids.Bytes(),
+ TagCFCW: cfcw.Bytes(),
+ TagSFCW: sfcw.Bytes(),
+ }, nil
+}
+
+// GetSendStreamFlowControlWindow gets the size of the stream-level flow control window for sending data
+func (h *connectionParametersManager) GetSendStreamFlowControlWindow() protocol.ByteCount {
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+ return h.sendStreamFlowControlWindow
+}
+
+// GetSendConnectionFlowControlWindow gets the size of the stream-level flow control window for sending data
+func (h *connectionParametersManager) GetSendConnectionFlowControlWindow() protocol.ByteCount {
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+ return h.sendConnectionFlowControlWindow
+}
+
+// GetReceiveStreamFlowControlWindow gets the size of the stream-level flow control window for receiving data
+func (h *connectionParametersManager) GetReceiveStreamFlowControlWindow() protocol.ByteCount {
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+ return h.receiveStreamFlowControlWindow
+}
+
+// GetMaxReceiveStreamFlowControlWindow gets the maximum size of the stream-level flow control window for sending data
+func (h *connectionParametersManager) GetMaxReceiveStreamFlowControlWindow() protocol.ByteCount {
+ return h.maxReceiveStreamFlowControlWindow
+}
+
+// GetReceiveConnectionFlowControlWindow gets the size of the stream-level flow control window for receiving data
+func (h *connectionParametersManager) GetReceiveConnectionFlowControlWindow() protocol.ByteCount {
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+ return h.receiveConnectionFlowControlWindow
+}
+
+// GetMaxReceiveConnectionFlowControlWindow gets the maximum size of the stream-level flow control window for sending data
+func (h *connectionParametersManager) GetMaxReceiveConnectionFlowControlWindow() protocol.ByteCount {
+ return h.maxReceiveConnectionFlowControlWindow
+}
+
+// GetMaxOutgoingStreams gets the maximum number of outgoing streams per connection
+func (h *connectionParametersManager) GetMaxOutgoingStreams() uint32 {
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+
+ return h.maxIncomingDynamicStreamsPerConnection
+}
+
+// GetMaxIncomingStreams get the maximum number of incoming streams per connection
+func (h *connectionParametersManager) GetMaxIncomingStreams() uint32 {
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+
+ maxStreams := protocol.MaxIncomingDynamicStreamsPerConnection
+ return utils.MaxUint32(uint32(maxStreams)+protocol.MaxStreamsMinimumIncrement, uint32(float64(maxStreams)*protocol.MaxStreamsMultiplier))
+}
+
+// GetIdleConnectionStateLifetime gets the idle timeout
+func (h *connectionParametersManager) GetIdleConnectionStateLifetime() time.Duration {
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+ return h.idleConnectionStateLifetime
+}
+
+// TruncateConnectionID determines if the client requests truncated ConnectionIDs
+func (h *connectionParametersManager) TruncateConnectionID() bool {
+ if h.perspective == protocol.PerspectiveClient {
+ return false
+ }
+
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+ return h.truncateConnectionID
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/handshake/crypto_setup_client.go b/vendor/github.com/lucas-clemente/quic-go/handshake/crypto_setup_client.go
new file mode 100644
index 0000000..a8d8812
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/handshake/crypto_setup_client.go
@@ -0,0 +1,539 @@
+package handshake
+
+import (
+ "bytes"
+ "crypto/rand"
+ "crypto/tls"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "sync"
+ "time"
+
+ "github.com/lucas-clemente/quic-go/crypto"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+ "github.com/lucas-clemente/quic-go/qerr"
+)
+
+type cryptoSetupClient struct {
+ mutex sync.RWMutex
+
+ hostname string
+ connID protocol.ConnectionID
+ version protocol.VersionNumber
+ negotiatedVersions []protocol.VersionNumber
+
+ cryptoStream io.ReadWriter
+
+ serverConfig *serverConfigClient
+
+ stk []byte
+ sno []byte
+ nonc []byte
+ proof []byte
+ chloForSignature []byte
+ lastSentCHLO []byte
+ certManager crypto.CertManager
+
+ divNonceChan chan []byte
+ diversificationNonce []byte
+
+ clientHelloCounter int
+ serverVerified bool // has the certificate chain and the proof already been verified
+ keyDerivation KeyDerivationFunction
+ keyExchange KeyExchangeFunction
+
+ receivedSecurePacket bool
+ nullAEAD crypto.AEAD
+ secureAEAD crypto.AEAD
+ forwardSecureAEAD crypto.AEAD
+ aeadChanged chan<- protocol.EncryptionLevel
+
+ params *TransportParameters
+ connectionParameters ConnectionParametersManager
+}
+
+var _ CryptoSetup = &cryptoSetupClient{}
+
+var (
+ errNoObitForClientNonce = errors.New("CryptoSetup BUG: No OBIT for client nonce available")
+ errClientNonceAlreadyExists = errors.New("CryptoSetup BUG: A client nonce was already generated")
+ errConflictingDiversificationNonces = errors.New("Received two different diversification nonces")
+)
+
+// NewCryptoSetupClient creates a new CryptoSetup instance for a client
+func NewCryptoSetupClient(
+ hostname string,
+ connID protocol.ConnectionID,
+ version protocol.VersionNumber,
+ cryptoStream io.ReadWriter,
+ tlsConfig *tls.Config,
+ connectionParameters ConnectionParametersManager,
+ aeadChanged chan<- protocol.EncryptionLevel,
+ params *TransportParameters,
+ negotiatedVersions []protocol.VersionNumber,
+) (CryptoSetup, error) {
+ return &cryptoSetupClient{
+ hostname: hostname,
+ connID: connID,
+ version: version,
+ cryptoStream: cryptoStream,
+ certManager: crypto.NewCertManager(tlsConfig),
+ connectionParameters: connectionParameters,
+ keyDerivation: crypto.DeriveKeysAESGCM,
+ keyExchange: getEphermalKEX,
+ nullAEAD: crypto.NewNullAEAD(protocol.PerspectiveClient, version),
+ aeadChanged: aeadChanged,
+ negotiatedVersions: negotiatedVersions,
+ divNonceChan: make(chan []byte),
+ params: params,
+ }, nil
+}
+
+func (h *cryptoSetupClient) HandleCryptoStream() error {
+ messageChan := make(chan HandshakeMessage)
+ errorChan := make(chan error)
+
+ go func() {
+ for {
+ message, err := ParseHandshakeMessage(h.cryptoStream)
+ if err != nil {
+ errorChan <- qerr.Error(qerr.HandshakeFailed, err.Error())
+ return
+ }
+ messageChan <- message
+ }
+ }()
+
+ for {
+ err := h.maybeUpgradeCrypto()
+ if err != nil {
+ return err
+ }
+
+ h.mutex.RLock()
+ sendCHLO := h.secureAEAD == nil
+ h.mutex.RUnlock()
+
+ if sendCHLO {
+ err = h.sendCHLO()
+ if err != nil {
+ return err
+ }
+ }
+
+ var message HandshakeMessage
+ select {
+ case divNonce := <-h.divNonceChan:
+ if len(h.diversificationNonce) != 0 && !bytes.Equal(h.diversificationNonce, divNonce) {
+ return errConflictingDiversificationNonces
+ }
+ h.diversificationNonce = divNonce
+ // there's no message to process, but we should try upgrading the crypto again
+ continue
+ case message = <-messageChan:
+ case err = <-errorChan:
+ return err
+ }
+
+ utils.Debugf("Got %s", message)
+ switch message.Tag {
+ case TagREJ:
+ err = h.handleREJMessage(message.Data)
+ case TagSHLO:
+ err = h.handleSHLOMessage(message.Data)
+ default:
+ return qerr.InvalidCryptoMessageType
+ }
+ if err != nil {
+ return err
+ }
+ }
+}
+
+func (h *cryptoSetupClient) handleREJMessage(cryptoData map[Tag][]byte) error {
+ var err error
+
+ if stk, ok := cryptoData[TagSTK]; ok {
+ h.stk = stk
+ }
+
+ if sno, ok := cryptoData[TagSNO]; ok {
+ h.sno = sno
+ }
+
+ // TODO: what happens if the server sends a different server config in two packets?
+ if scfg, ok := cryptoData[TagSCFG]; ok {
+ h.serverConfig, err = parseServerConfig(scfg)
+ if err != nil {
+ return err
+ }
+
+ if h.serverConfig.IsExpired() {
+ return qerr.CryptoServerConfigExpired
+ }
+
+ // now that we have a server config, we can use its OBIT value to generate a client nonce
+ if len(h.nonc) == 0 {
+ err = h.generateClientNonce()
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ if proof, ok := cryptoData[TagPROF]; ok {
+ h.proof = proof
+ h.chloForSignature = h.lastSentCHLO
+ }
+
+ if crt, ok := cryptoData[TagCERT]; ok {
+ err := h.certManager.SetData(crt)
+ if err != nil {
+ return qerr.Error(qerr.InvalidCryptoMessageParameter, "Certificate data invalid")
+ }
+
+ err = h.certManager.Verify(h.hostname)
+ if err != nil {
+ utils.Infof("Certificate validation failed: %s", err.Error())
+ return qerr.ProofInvalid
+ }
+ }
+
+ if h.serverConfig != nil && len(h.proof) != 0 && h.certManager.GetLeafCert() != nil {
+ validProof := h.certManager.VerifyServerProof(h.proof, h.chloForSignature, h.serverConfig.Get())
+ if !validProof {
+ utils.Infof("Server proof verification failed")
+ return qerr.ProofInvalid
+ }
+
+ h.serverVerified = true
+ }
+
+ return nil
+}
+
+func (h *cryptoSetupClient) handleSHLOMessage(cryptoData map[Tag][]byte) error {
+ h.mutex.Lock()
+ defer h.mutex.Unlock()
+
+ if !h.receivedSecurePacket {
+ return qerr.Error(qerr.CryptoEncryptionLevelIncorrect, "unencrypted SHLO message")
+ }
+
+ if sno, ok := cryptoData[TagSNO]; ok {
+ h.sno = sno
+ }
+
+ serverPubs, ok := cryptoData[TagPUBS]
+ if !ok {
+ return qerr.Error(qerr.CryptoMessageParameterNotFound, "PUBS")
+ }
+
+ verTag, ok := cryptoData[TagVER]
+ if !ok {
+ return qerr.Error(qerr.InvalidCryptoMessageParameter, "server hello missing version list")
+ }
+ if !h.validateVersionList(verTag) {
+ return qerr.Error(qerr.VersionNegotiationMismatch, "Downgrade attack detected")
+ }
+
+ nonce := append(h.nonc, h.sno...)
+
+ ephermalSharedSecret, err := h.serverConfig.kex.CalculateSharedKey(serverPubs)
+ if err != nil {
+ return err
+ }
+
+ leafCert := h.certManager.GetLeafCert()
+
+ h.forwardSecureAEAD, err = h.keyDerivation(
+ true,
+ ephermalSharedSecret,
+ nonce,
+ h.connID,
+ h.lastSentCHLO,
+ h.serverConfig.Get(),
+ leafCert,
+ nil,
+ protocol.PerspectiveClient,
+ )
+ if err != nil {
+ return err
+ }
+
+ err = h.connectionParameters.SetFromMap(cryptoData)
+ if err != nil {
+ return qerr.InvalidCryptoMessageParameter
+ }
+
+ h.aeadChanged <- protocol.EncryptionForwardSecure
+ close(h.aeadChanged)
+
+ return nil
+}
+
+func (h *cryptoSetupClient) validateVersionList(verTags []byte) bool {
+ if len(h.negotiatedVersions) == 0 {
+ return true
+ }
+ if len(verTags)%4 != 0 || len(verTags)/4 != len(h.negotiatedVersions) {
+ return false
+ }
+
+ b := bytes.NewReader(verTags)
+ for _, negotiatedVersion := range h.negotiatedVersions {
+ verTag, err := utils.ReadUint32(b)
+ if err != nil { // should never occur, since the length was already checked
+ return false
+ }
+ ver := protocol.VersionTagToNumber(verTag)
+ if !protocol.IsSupportedVersion(protocol.SupportedVersions, ver) {
+ ver = protocol.VersionUnsupported
+ }
+ if ver != negotiatedVersion {
+ return false
+ }
+ }
+ return true
+}
+
+func (h *cryptoSetupClient) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error) {
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+
+ if h.forwardSecureAEAD != nil {
+ data, err := h.forwardSecureAEAD.Open(dst, src, packetNumber, associatedData)
+ if err == nil {
+ return data, protocol.EncryptionForwardSecure, nil
+ }
+ return nil, protocol.EncryptionUnspecified, err
+ }
+
+ if h.secureAEAD != nil {
+ data, err := h.secureAEAD.Open(dst, src, packetNumber, associatedData)
+ if err == nil {
+ h.receivedSecurePacket = true
+ return data, protocol.EncryptionSecure, nil
+ }
+ if h.receivedSecurePacket {
+ return nil, protocol.EncryptionUnspecified, err
+ }
+ }
+ res, err := h.nullAEAD.Open(dst, src, packetNumber, associatedData)
+ if err != nil {
+ return nil, protocol.EncryptionUnspecified, err
+ }
+ return res, protocol.EncryptionUnencrypted, nil
+}
+
+func (h *cryptoSetupClient) GetSealer() (protocol.EncryptionLevel, Sealer) {
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+ if h.forwardSecureAEAD != nil {
+ return protocol.EncryptionForwardSecure, h.sealForwardSecure
+ } else if h.secureAEAD != nil {
+ return protocol.EncryptionSecure, h.sealSecure
+ } else {
+ return protocol.EncryptionUnencrypted, h.sealUnencrypted
+ }
+}
+
+func (h *cryptoSetupClient) GetSealerForCryptoStream() (protocol.EncryptionLevel, Sealer) {
+ return protocol.EncryptionUnencrypted, h.sealUnencrypted
+}
+
+func (h *cryptoSetupClient) GetSealerWithEncryptionLevel(encLevel protocol.EncryptionLevel) (Sealer, error) {
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+
+ switch encLevel {
+ case protocol.EncryptionUnencrypted:
+ return h.sealUnencrypted, nil
+ case protocol.EncryptionSecure:
+ if h.secureAEAD == nil {
+ return nil, errors.New("CryptoSetupClient: no secureAEAD")
+ }
+ return h.sealSecure, nil
+ case protocol.EncryptionForwardSecure:
+ if h.forwardSecureAEAD == nil {
+ return nil, errors.New("CryptoSetupClient: no forwardSecureAEAD")
+ }
+ return h.sealForwardSecure, nil
+ }
+ return nil, errors.New("CryptoSetupClient: no encryption level specified")
+}
+
+func (h *cryptoSetupClient) sealUnencrypted(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
+ return h.nullAEAD.Seal(dst, src, packetNumber, associatedData)
+}
+
+func (h *cryptoSetupClient) sealSecure(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
+ return h.secureAEAD.Seal(dst, src, packetNumber, associatedData)
+}
+
+func (h *cryptoSetupClient) sealForwardSecure(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
+ return h.forwardSecureAEAD.Seal(dst, src, packetNumber, associatedData)
+}
+
+func (h *cryptoSetupClient) DiversificationNonce() []byte {
+ panic("not needed for cryptoSetupClient")
+}
+
+func (h *cryptoSetupClient) SetDiversificationNonce(data []byte) {
+ h.divNonceChan <- data
+}
+
+func (h *cryptoSetupClient) sendCHLO() error {
+ h.clientHelloCounter++
+ if h.clientHelloCounter > protocol.MaxClientHellos {
+ return qerr.Error(qerr.CryptoTooManyRejects, fmt.Sprintf("More than %d rejects", protocol.MaxClientHellos))
+ }
+
+ b := &bytes.Buffer{}
+
+ tags, err := h.getTags()
+ if err != nil {
+ return err
+ }
+ h.addPadding(tags)
+ message := HandshakeMessage{
+ Tag: TagCHLO,
+ Data: tags,
+ }
+
+ utils.Debugf("Sending %s", message)
+ message.Write(b)
+
+ _, err = h.cryptoStream.Write(b.Bytes())
+ if err != nil {
+ return err
+ }
+
+ h.lastSentCHLO = b.Bytes()
+
+ return nil
+}
+
+func (h *cryptoSetupClient) getTags() (map[Tag][]byte, error) {
+ tags, err := h.connectionParameters.GetHelloMap()
+ if err != nil {
+ return nil, err
+ }
+ tags[TagSNI] = []byte(h.hostname)
+ tags[TagPDMD] = []byte("X509")
+
+ ccs := h.certManager.GetCommonCertificateHashes()
+ if len(ccs) > 0 {
+ tags[TagCCS] = ccs
+ }
+
+ versionTag := make([]byte, 4)
+ binary.LittleEndian.PutUint32(versionTag, protocol.VersionNumberToTag(h.version))
+ tags[TagVER] = versionTag
+
+ if h.params.RequestConnectionIDTruncation {
+ tags[TagTCID] = []byte{0, 0, 0, 0}
+ }
+ if len(h.stk) > 0 {
+ tags[TagSTK] = h.stk
+ }
+ if len(h.sno) > 0 {
+ tags[TagSNO] = h.sno
+ }
+
+ if h.serverConfig != nil {
+ tags[TagSCID] = h.serverConfig.ID
+
+ leafCert := h.certManager.GetLeafCert()
+ if leafCert != nil {
+ certHash, _ := h.certManager.GetLeafCertHash()
+ xlct := make([]byte, 8)
+ binary.LittleEndian.PutUint64(xlct, certHash)
+
+ tags[TagNONC] = h.nonc
+ tags[TagXLCT] = xlct
+ tags[TagKEXS] = []byte("C255")
+ tags[TagAEAD] = []byte("AESG")
+ tags[TagPUBS] = h.serverConfig.kex.PublicKey() // TODO: check if 3 bytes need to be prepended
+ }
+ }
+
+ return tags, nil
+}
+
+// add a TagPAD to a tagMap, such that the total size will be bigger than the ClientHelloMinimumSize
+func (h *cryptoSetupClient) addPadding(tags map[Tag][]byte) {
+ var size int
+ for _, tag := range tags {
+ size += 8 + len(tag) // 4 bytes for the tag + 4 bytes for the offset + the length of the data
+ }
+ paddingSize := protocol.ClientHelloMinimumSize - size
+ if paddingSize > 0 {
+ tags[TagPAD] = bytes.Repeat([]byte{0}, paddingSize)
+ }
+}
+
+func (h *cryptoSetupClient) maybeUpgradeCrypto() error {
+ if !h.serverVerified {
+ return nil
+ }
+
+ h.mutex.Lock()
+ defer h.mutex.Unlock()
+
+ leafCert := h.certManager.GetLeafCert()
+ if h.secureAEAD == nil && (h.serverConfig != nil && len(h.serverConfig.sharedSecret) > 0 && len(h.nonc) > 0 && len(leafCert) > 0 && len(h.diversificationNonce) > 0 && len(h.lastSentCHLO) > 0) {
+ var err error
+ var nonce []byte
+ if h.sno == nil {
+ nonce = h.nonc
+ } else {
+ nonce = append(h.nonc, h.sno...)
+ }
+
+ h.secureAEAD, err = h.keyDerivation(
+ false,
+ h.serverConfig.sharedSecret,
+ nonce,
+ h.connID,
+ h.lastSentCHLO,
+ h.serverConfig.Get(),
+ leafCert,
+ h.diversificationNonce,
+ protocol.PerspectiveClient,
+ )
+ if err != nil {
+ return err
+ }
+
+ h.aeadChanged <- protocol.EncryptionSecure
+ }
+
+ return nil
+}
+
+func (h *cryptoSetupClient) generateClientNonce() error {
+ if len(h.nonc) > 0 {
+ return errClientNonceAlreadyExists
+ }
+
+ nonc := make([]byte, 32)
+ binary.BigEndian.PutUint32(nonc, uint32(time.Now().Unix()))
+
+ if len(h.serverConfig.obit) != 8 {
+ return errNoObitForClientNonce
+ }
+
+ copy(nonc[4:12], h.serverConfig.obit)
+
+ _, err := rand.Read(nonc[12:])
+ if err != nil {
+ return err
+ }
+
+ h.nonc = nonc
+ return nil
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/handshake/crypto_setup_server.go b/vendor/github.com/lucas-clemente/quic-go/handshake/crypto_setup_server.go
new file mode 100644
index 0000000..f639f51
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/handshake/crypto_setup_server.go
@@ -0,0 +1,470 @@
+package handshake
+
+import (
+ "bytes"
+ "crypto/rand"
+ "encoding/binary"
+ "errors"
+ "io"
+ "net"
+ "sync"
+
+ "github.com/lucas-clemente/quic-go/crypto"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+ "github.com/lucas-clemente/quic-go/qerr"
+)
+
+// KeyDerivationFunction is used for key derivation
+type KeyDerivationFunction func(forwardSecure bool, sharedSecret, nonces []byte, connID protocol.ConnectionID, chlo []byte, scfg []byte, cert []byte, divNonce []byte, pers protocol.Perspective) (crypto.AEAD, error)
+
+// KeyExchangeFunction is used to make a new KEX
+type KeyExchangeFunction func() crypto.KeyExchange
+
+// The CryptoSetupServer handles all things crypto for the Session
+type cryptoSetupServer struct {
+ connID protocol.ConnectionID
+ remoteAddr net.Addr
+ scfg *ServerConfig
+ stkGenerator *STKGenerator
+ diversificationNonce []byte
+
+ version protocol.VersionNumber
+ supportedVersions []protocol.VersionNumber
+
+ acceptSTKCallback func(net.Addr, *STK) bool
+
+ nullAEAD crypto.AEAD
+ secureAEAD crypto.AEAD
+ forwardSecureAEAD crypto.AEAD
+ receivedForwardSecurePacket bool
+ sentSHLO bool
+ receivedSecurePacket bool
+ aeadChanged chan<- protocol.EncryptionLevel
+
+ keyDerivation KeyDerivationFunction
+ keyExchange KeyExchangeFunction
+
+ cryptoStream io.ReadWriter
+
+ connectionParameters ConnectionParametersManager
+
+ mutex sync.RWMutex
+}
+
+var _ CryptoSetup = &cryptoSetupServer{}
+
+// ErrHOLExperiment is returned when the client sends the FHL2 tag in the CHLO
+// this is an expiremnt implemented by Chrome in QUIC 36, which we don't support
+// TODO: remove this when dropping support for QUIC 36
+var ErrHOLExperiment = qerr.Error(qerr.InvalidCryptoMessageParameter, "HOL experiment. Unsupported")
+
+// NewCryptoSetup creates a new CryptoSetup instance for a server
+func NewCryptoSetup(
+ connID protocol.ConnectionID,
+ remoteAddr net.Addr,
+ version protocol.VersionNumber,
+ scfg *ServerConfig,
+ cryptoStream io.ReadWriter,
+ connectionParametersManager ConnectionParametersManager,
+ supportedVersions []protocol.VersionNumber,
+ acceptSTK func(net.Addr, *STK) bool,
+ aeadChanged chan<- protocol.EncryptionLevel,
+) (CryptoSetup, error) {
+ stkGenerator, err := NewSTKGenerator()
+ if err != nil {
+ return nil, err
+ }
+
+ return &cryptoSetupServer{
+ connID: connID,
+ remoteAddr: remoteAddr,
+ version: version,
+ supportedVersions: supportedVersions,
+ scfg: scfg,
+ stkGenerator: stkGenerator,
+ keyDerivation: crypto.DeriveKeysAESGCM,
+ keyExchange: getEphermalKEX,
+ nullAEAD: crypto.NewNullAEAD(protocol.PerspectiveServer, version),
+ cryptoStream: cryptoStream,
+ connectionParameters: connectionParametersManager,
+ acceptSTKCallback: acceptSTK,
+ aeadChanged: aeadChanged,
+ }, nil
+}
+
+// HandleCryptoStream reads and writes messages on the crypto stream
+func (h *cryptoSetupServer) HandleCryptoStream() error {
+ for {
+ var chloData bytes.Buffer
+ message, err := ParseHandshakeMessage(io.TeeReader(h.cryptoStream, &chloData))
+ if err != nil {
+ return qerr.HandshakeFailed
+ }
+ if message.Tag != TagCHLO {
+ return qerr.InvalidCryptoMessageType
+ }
+
+ utils.Debugf("Got %s", message)
+ done, err := h.handleMessage(chloData.Bytes(), message.Data)
+ if err != nil {
+ return err
+ }
+ if done {
+ return nil
+ }
+ }
+}
+
+func (h *cryptoSetupServer) handleMessage(chloData []byte, cryptoData map[Tag][]byte) (bool, error) {
+ if _, isHOLExperiment := cryptoData[TagFHL2]; isHOLExperiment {
+ return false, ErrHOLExperiment
+ }
+
+ sniSlice, ok := cryptoData[TagSNI]
+ if !ok {
+ return false, qerr.Error(qerr.CryptoMessageParameterNotFound, "SNI required")
+ }
+ sni := string(sniSlice)
+ if sni == "" {
+ return false, qerr.Error(qerr.CryptoMessageParameterNotFound, "SNI required")
+ }
+
+ // prevent version downgrade attacks
+ // see https://groups.google.com/a/chromium.org/forum/#!topic/proto-quic/N-de9j63tCk for a discussion and examples
+ verSlice, ok := cryptoData[TagVER]
+ if !ok {
+ return false, qerr.Error(qerr.InvalidCryptoMessageParameter, "client hello missing version tag")
+ }
+ if len(verSlice) != 4 {
+ return false, qerr.Error(qerr.InvalidCryptoMessageParameter, "incorrect version tag")
+ }
+ verTag := binary.LittleEndian.Uint32(verSlice)
+ ver := protocol.VersionTagToNumber(verTag)
+ // If the client's preferred version is not the version we are currently speaking, then the client went through a version negotiation. In this case, we need to make sure that we actually do not support this version and that it wasn't a downgrade attack.
+ if ver != h.version && protocol.IsSupportedVersion(h.supportedVersions, ver) {
+ return false, qerr.Error(qerr.VersionNegotiationMismatch, "Downgrade attack detected")
+ }
+
+ var reply []byte
+ var err error
+
+ certUncompressed, err := h.scfg.certChain.GetLeafCert(sni)
+ if err != nil {
+ return false, err
+ }
+
+ if !h.isInchoateCHLO(cryptoData, certUncompressed) {
+ // We have a CHLO with a proper server config ID, do a 0-RTT handshake
+ reply, err = h.handleCHLO(sni, chloData, cryptoData)
+ if err != nil {
+ return false, err
+ }
+ _, err = h.cryptoStream.Write(reply)
+ if err != nil {
+ return false, err
+ }
+ return true, nil
+ }
+
+ // We have an inchoate or non-matching CHLO, we now send a rejection
+ reply, err = h.handleInchoateCHLO(sni, chloData, cryptoData)
+ if err != nil {
+ return false, err
+ }
+ _, err = h.cryptoStream.Write(reply)
+ return false, err
+}
+
+// Open a message
+func (h *cryptoSetupServer) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error) {
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+
+ if h.forwardSecureAEAD != nil {
+ res, err := h.forwardSecureAEAD.Open(dst, src, packetNumber, associatedData)
+ if err == nil {
+ if !h.receivedForwardSecurePacket { // this is the first forward secure packet we receive from the client
+ h.receivedForwardSecurePacket = true
+ close(h.aeadChanged)
+ }
+ return res, protocol.EncryptionForwardSecure, nil
+ }
+ if h.receivedForwardSecurePacket {
+ return nil, protocol.EncryptionUnspecified, err
+ }
+ }
+ if h.secureAEAD != nil {
+ res, err := h.secureAEAD.Open(dst, src, packetNumber, associatedData)
+ if err == nil {
+ h.receivedSecurePacket = true
+ return res, protocol.EncryptionSecure, nil
+ }
+ if h.receivedSecurePacket {
+ return nil, protocol.EncryptionUnspecified, err
+ }
+ }
+ res, err := h.nullAEAD.Open(dst, src, packetNumber, associatedData)
+ if err != nil {
+ return res, protocol.EncryptionUnspecified, err
+ }
+ return res, protocol.EncryptionUnencrypted, err
+}
+
+func (h *cryptoSetupServer) GetSealer() (protocol.EncryptionLevel, Sealer) {
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+ if h.forwardSecureAEAD != nil {
+ return protocol.EncryptionForwardSecure, h.sealForwardSecure
+ }
+ return protocol.EncryptionUnencrypted, h.sealUnencrypted
+}
+
+func (h *cryptoSetupServer) GetSealerForCryptoStream() (protocol.EncryptionLevel, Sealer) {
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+ if h.secureAEAD != nil {
+ return protocol.EncryptionSecure, h.sealSecure
+ }
+ return protocol.EncryptionUnencrypted, h.sealUnencrypted
+}
+
+func (h *cryptoSetupServer) GetSealerWithEncryptionLevel(encLevel protocol.EncryptionLevel) (Sealer, error) {
+ h.mutex.RLock()
+ defer h.mutex.RUnlock()
+
+ switch encLevel {
+ case protocol.EncryptionUnencrypted:
+ return h.sealUnencrypted, nil
+ case protocol.EncryptionSecure:
+ if h.secureAEAD == nil {
+ return nil, errors.New("CryptoSetupServer: no secureAEAD")
+ }
+ return h.sealSecure, nil
+ case protocol.EncryptionForwardSecure:
+ if h.forwardSecureAEAD == nil {
+ return nil, errors.New("CryptoSetupServer: no forwardSecureAEAD")
+ }
+ return h.sealForwardSecure, nil
+ }
+ return nil, errors.New("CryptoSetupServer: no encryption level specified")
+}
+
+func (h *cryptoSetupServer) sealUnencrypted(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
+ return h.nullAEAD.Seal(dst, src, packetNumber, associatedData)
+}
+
+func (h *cryptoSetupServer) sealSecure(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
+ return h.secureAEAD.Seal(dst, src, packetNumber, associatedData)
+}
+
+func (h *cryptoSetupServer) sealForwardSecure(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte {
+ return h.forwardSecureAEAD.Seal(dst, src, packetNumber, associatedData)
+}
+
+func (h *cryptoSetupServer) isInchoateCHLO(cryptoData map[Tag][]byte, cert []byte) bool {
+ if _, ok := cryptoData[TagPUBS]; !ok {
+ return true
+ }
+ scid, ok := cryptoData[TagSCID]
+ if !ok || !bytes.Equal(h.scfg.ID, scid) {
+ return true
+ }
+ xlctTag, ok := cryptoData[TagXLCT]
+ if !ok || len(xlctTag) != 8 {
+ return true
+ }
+ xlct := binary.LittleEndian.Uint64(xlctTag)
+ if crypto.HashCert(cert) != xlct {
+ return true
+ }
+ return !h.acceptSTK(cryptoData[TagSTK])
+}
+
+func (h *cryptoSetupServer) acceptSTK(token []byte) bool {
+ stk, err := h.stkGenerator.DecodeToken(token)
+ if err != nil {
+ utils.Debugf("STK invalid: %s", err.Error())
+ return false
+ }
+ return h.acceptSTKCallback(h.remoteAddr, stk)
+}
+
+func (h *cryptoSetupServer) handleInchoateCHLO(sni string, chlo []byte, cryptoData map[Tag][]byte) ([]byte, error) {
+ if len(chlo) < protocol.ClientHelloMinimumSize {
+ return nil, qerr.Error(qerr.CryptoInvalidValueLength, "CHLO too small")
+ }
+
+ token, err := h.stkGenerator.NewToken(h.remoteAddr)
+ if err != nil {
+ return nil, err
+ }
+
+ replyMap := map[Tag][]byte{
+ TagSCFG: h.scfg.Get(),
+ TagSTK: token,
+ TagSVID: []byte("quic-go"),
+ }
+
+ if h.acceptSTK(cryptoData[TagSTK]) {
+ proof, err := h.scfg.Sign(sni, chlo)
+ if err != nil {
+ return nil, err
+ }
+
+ commonSetHashes := cryptoData[TagCCS]
+ cachedCertsHashes := cryptoData[TagCCRT]
+
+ certCompressed, err := h.scfg.GetCertsCompressed(sni, commonSetHashes, cachedCertsHashes)
+ if err != nil {
+ return nil, err
+ }
+ // Token was valid, send more details
+ replyMap[TagPROF] = proof
+ replyMap[TagCERT] = certCompressed
+ }
+
+ message := HandshakeMessage{
+ Tag: TagREJ,
+ Data: replyMap,
+ }
+
+ var serverReply bytes.Buffer
+ message.Write(&serverReply)
+ utils.Debugf("Sending %s", message)
+ return serverReply.Bytes(), nil
+}
+
+func (h *cryptoSetupServer) handleCHLO(sni string, data []byte, cryptoData map[Tag][]byte) ([]byte, error) {
+ // We have a CHLO matching our server config, we can continue with the 0-RTT handshake
+ sharedSecret, err := h.scfg.kex.CalculateSharedKey(cryptoData[TagPUBS])
+ if err != nil {
+ return nil, err
+ }
+
+ h.mutex.Lock()
+ defer h.mutex.Unlock()
+
+ certUncompressed, err := h.scfg.certChain.GetLeafCert(sni)
+ if err != nil {
+ return nil, err
+ }
+
+ serverNonce := make([]byte, 32)
+ if _, err = rand.Read(serverNonce); err != nil {
+ return nil, err
+ }
+
+ h.diversificationNonce = make([]byte, 32)
+ if _, err = rand.Read(h.diversificationNonce); err != nil {
+ return nil, err
+ }
+
+ clientNonce := cryptoData[TagNONC]
+ err = h.validateClientNonce(clientNonce)
+ if err != nil {
+ return nil, err
+ }
+
+ aead := cryptoData[TagAEAD]
+ if !bytes.Equal(aead, []byte("AESG")) {
+ return nil, qerr.Error(qerr.CryptoNoSupport, "Unsupported AEAD or KEXS")
+ }
+
+ kexs := cryptoData[TagKEXS]
+ if !bytes.Equal(kexs, []byte("C255")) {
+ return nil, qerr.Error(qerr.CryptoNoSupport, "Unsupported AEAD or KEXS")
+ }
+
+ h.secureAEAD, err = h.keyDerivation(
+ false,
+ sharedSecret,
+ clientNonce,
+ h.connID,
+ data,
+ h.scfg.Get(),
+ certUncompressed,
+ h.diversificationNonce,
+ protocol.PerspectiveServer,
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ h.aeadChanged <- protocol.EncryptionSecure
+
+ // Generate a new curve instance to derive the forward secure key
+ var fsNonce bytes.Buffer
+ fsNonce.Write(clientNonce)
+ fsNonce.Write(serverNonce)
+ ephermalKex := h.keyExchange()
+ ephermalSharedSecret, err := ephermalKex.CalculateSharedKey(cryptoData[TagPUBS])
+ if err != nil {
+ return nil, err
+ }
+
+ h.forwardSecureAEAD, err = h.keyDerivation(
+ true,
+ ephermalSharedSecret,
+ fsNonce.Bytes(),
+ h.connID,
+ data,
+ h.scfg.Get(),
+ certUncompressed,
+ nil,
+ protocol.PerspectiveServer,
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ err = h.connectionParameters.SetFromMap(cryptoData)
+ if err != nil {
+ return nil, err
+ }
+
+ replyMap, err := h.connectionParameters.GetHelloMap()
+ if err != nil {
+ return nil, err
+ }
+ // add crypto parameters
+ verTag := &bytes.Buffer{}
+ for _, v := range h.supportedVersions {
+ utils.WriteUint32(verTag, protocol.VersionNumberToTag(v))
+ }
+ replyMap[TagPUBS] = ephermalKex.PublicKey()
+ replyMap[TagSNO] = serverNonce
+ replyMap[TagVER] = verTag.Bytes()
+
+ // note that the SHLO *has* to fit into one packet
+ message := HandshakeMessage{
+ Tag: TagSHLO,
+ Data: replyMap,
+ }
+ var reply bytes.Buffer
+ message.Write(&reply)
+ utils.Debugf("Sending %s", message)
+
+ h.aeadChanged <- protocol.EncryptionForwardSecure
+
+ return reply.Bytes(), nil
+}
+
+// DiversificationNonce returns the diversification nonce
+func (h *cryptoSetupServer) DiversificationNonce() []byte {
+ return h.diversificationNonce
+}
+
+func (h *cryptoSetupServer) SetDiversificationNonce(data []byte) {
+ panic("not needed for cryptoSetupServer")
+}
+
+func (h *cryptoSetupServer) validateClientNonce(nonce []byte) error {
+ if len(nonce) != 32 {
+ return qerr.Error(qerr.InvalidCryptoMessageParameter, "invalid client nonce length")
+ }
+ if !bytes.Equal(nonce[4:12], h.scfg.obit) {
+ return qerr.Error(qerr.InvalidCryptoMessageParameter, "OBIT not matching")
+ }
+ return nil
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/ephermal_cache.go b/vendor/github.com/lucas-clemente/quic-go/handshake/ephermal_cache.go
similarity index 87%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/ephermal_cache.go
rename to vendor/github.com/lucas-clemente/quic-go/handshake/ephermal_cache.go
index 794bcbd..da6724f 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/ephermal_cache.go
+++ b/vendor/github.com/lucas-clemente/quic-go/handshake/ephermal_cache.go
@@ -5,8 +5,8 @@ import (
"time"
"github.com/lucas-clemente/quic-go/crypto"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
)
var (
@@ -29,14 +29,14 @@ func getEphermalKEX() (res crypto.KeyExchange) {
res = kexCurrent
t := kexCurrentTime
kexMutex.RUnlock()
- if res != nil && time.Now().Sub(t) < kexLifetime {
+ if res != nil && time.Since(t) < kexLifetime {
return res
}
kexMutex.Lock()
defer kexMutex.Unlock()
// Check if still unfulfilled
- if kexCurrent == nil || time.Now().Sub(kexCurrentTime) > kexLifetime {
+ if kexCurrent == nil || time.Since(kexCurrentTime) > kexLifetime {
kex, err := crypto.NewCurve25519KEX()
if err != nil {
utils.Errorf("could not set KEX: %s", err.Error())
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/handshake_message.go b/vendor/github.com/lucas-clemente/quic-go/handshake/handshake_message.go
similarity index 59%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/handshake_message.go
rename to vendor/github.com/lucas-clemente/quic-go/handshake/handshake_message.go
index 013c44b..0744cbd 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/handshake_message.go
+++ b/vendor/github.com/lucas-clemente/quic-go/handshake/handshake_message.go
@@ -7,32 +7,40 @@ import (
"io"
"sort"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
- "github.com/lucas-clemente/quic-go/utils"
)
+// A HandshakeMessage is a handshake message
+type HandshakeMessage struct {
+ Tag Tag
+ Data map[Tag][]byte
+}
+
+var _ fmt.Stringer = &HandshakeMessage{}
+
// ParseHandshakeMessage reads a crypto message
-func ParseHandshakeMessage(r io.Reader) (Tag, map[Tag][]byte, error) {
+func ParseHandshakeMessage(r io.Reader) (HandshakeMessage, error) {
slice4 := make([]byte, 4)
if _, err := io.ReadFull(r, slice4); err != nil {
- return 0, nil, err
+ return HandshakeMessage{}, err
}
messageTag := Tag(binary.LittleEndian.Uint32(slice4))
if _, err := io.ReadFull(r, slice4); err != nil {
- return 0, nil, err
+ return HandshakeMessage{}, err
}
nPairs := binary.LittleEndian.Uint32(slice4)
if nPairs > protocol.CryptoMaxParams {
- return 0, nil, qerr.CryptoTooManyEntries
+ return HandshakeMessage{}, qerr.CryptoTooManyEntries
}
index := make([]byte, nPairs*8)
if _, err := io.ReadFull(r, index); err != nil {
- return 0, nil, err
+ return HandshakeMessage{}, err
}
resultMap := map[Tag][]byte{}
@@ -44,24 +52,27 @@ func ParseHandshakeMessage(r io.Reader) (Tag, map[Tag][]byte, error) {
dataLen := dataEnd - dataStart
if dataLen > protocol.CryptoParameterMaxLength {
- return 0, nil, qerr.Error(qerr.CryptoInvalidValueLength, "value too long")
+ return HandshakeMessage{}, qerr.Error(qerr.CryptoInvalidValueLength, "value too long")
}
data := make([]byte, dataLen)
if _, err := io.ReadFull(r, data); err != nil {
- return 0, nil, err
+ return HandshakeMessage{}, err
}
resultMap[tag] = data
dataStart = dataEnd
}
- return messageTag, resultMap, nil
+ return HandshakeMessage{
+ Tag: messageTag,
+ Data: resultMap}, nil
}
-// WriteHandshakeMessage writes a crypto message
-func WriteHandshakeMessage(b *bytes.Buffer, messageTag Tag, data map[Tag][]byte) {
- utils.WriteUint32(b, uint32(messageTag))
+// Write writes a crypto message
+func (h HandshakeMessage) Write(b *bytes.Buffer) {
+ data := h.Data
+ utils.WriteUint32(b, uint32(h.Tag))
utils.WriteUint16(b, uint16(len(data)))
utils.WriteUint16(b, 0)
@@ -71,17 +82,8 @@ func WriteHandshakeMessage(b *bytes.Buffer, messageTag Tag, data map[Tag][]byte)
indexData := make([]byte, 8*len(data))
b.Write(indexData) // Will be updated later
- // Sort the tags
- tags := make([]uint32, len(data))
- i := 0
- for t := range data {
- tags[i] = uint32(t)
- i++
- }
- sort.Sort(utils.Uint32Slice(tags))
-
offset := uint32(0)
- for i, t := range tags {
+ for i, t := range h.getTagsSorted() {
v := data[Tag(t)]
b.Write(v)
offset += uint32(len(v))
@@ -93,13 +95,31 @@ func WriteHandshakeMessage(b *bytes.Buffer, messageTag Tag, data map[Tag][]byte)
copy(b.Bytes()[indexStart:], indexData)
}
-func printHandshakeMessage(data map[Tag][]byte) string {
- var res string
- for k, v := range data {
- if k == TagPAD {
- continue
+func (h *HandshakeMessage) getTagsSorted() []uint32 {
+ tags := make([]uint32, len(h.Data))
+ i := 0
+ for t := range h.Data {
+ tags[i] = uint32(t)
+ i++
+ }
+ sort.Sort(utils.Uint32Slice(tags))
+ return tags
+}
+
+func (h HandshakeMessage) String() string {
+ var pad string
+ res := tagToString(h.Tag) + ":\n"
+ for _, t := range h.getTagsSorted() {
+ tag := Tag(t)
+ if tag == TagPAD {
+ pad = fmt.Sprintf("\t%s: (%d bytes)\n", tagToString(tag), len(h.Data[tag]))
+ } else {
+ res += fmt.Sprintf("\t%s: %#v\n", tagToString(tag), string(h.Data[tag]))
}
- res += fmt.Sprintf("\t%s: %#v\n", tagToString(k), string(v))
+ }
+
+ if len(pad) > 0 {
+ res += pad
}
return res
}
diff --git a/vendor/github.com/lucas-clemente/quic-go/handshake/interface.go b/vendor/github.com/lucas-clemente/quic-go/handshake/interface.go
new file mode 100644
index 0000000..751aae1
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/handshake/interface.go
@@ -0,0 +1,24 @@
+package handshake
+
+import "github.com/lucas-clemente/quic-go/protocol"
+
+// Sealer seals a packet
+type Sealer func(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) []byte
+
+// CryptoSetup is a crypto setup
+type CryptoSetup interface {
+ Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error)
+ HandleCryptoStream() error
+ // TODO: clean up this interface
+ DiversificationNonce() []byte // only needed for cryptoSetupServer
+ SetDiversificationNonce([]byte) // only needed for cryptoSetupClient
+
+ GetSealer() (protocol.EncryptionLevel, Sealer)
+ GetSealerWithEncryptionLevel(protocol.EncryptionLevel) (Sealer, error)
+ GetSealerForCryptoStream() (protocol.EncryptionLevel, Sealer)
+}
+
+// TransportParameters are parameters sent to the peer during the handshake
+type TransportParameters struct {
+ RequestConnectionIDTruncation bool
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/server_config.go b/vendor/github.com/lucas-clemente/quic-go/handshake/server_config.go
similarity index 52%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/server_config.go
rename to vendor/github.com/lucas-clemente/quic-go/handshake/server_config.go
index dc33e97..fce66ef 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/server_config.go
+++ b/vendor/github.com/lucas-clemente/quic-go/handshake/server_config.go
@@ -10,56 +10,56 @@ import (
// ServerConfig is a server config
type ServerConfig struct {
kex crypto.KeyExchange
- signer crypto.Signer
+ certChain crypto.CertChain
ID []byte
- stkSource crypto.StkSource
+ obit []byte
}
// NewServerConfig creates a new server config
-func NewServerConfig(kex crypto.KeyExchange, signer crypto.Signer) (*ServerConfig, error) {
+func NewServerConfig(kex crypto.KeyExchange, certChain crypto.CertChain) (*ServerConfig, error) {
id := make([]byte, 16)
_, err := rand.Read(id)
if err != nil {
return nil, err
}
- stkSecret := make([]byte, 32)
- if _, err = rand.Read(stkSecret); err != nil {
- return nil, err
- }
- stkSource, err := crypto.NewStkSource(stkSecret)
- if err != nil {
+ obit := make([]byte, 8)
+ if _, err = rand.Read(obit); err != nil {
return nil, err
}
return &ServerConfig{
kex: kex,
- signer: signer,
+ certChain: certChain,
ID: id,
- stkSource: stkSource,
+ obit: obit,
}, nil
}
// Get the server config binary representation
func (s *ServerConfig) Get() []byte {
var serverConfig bytes.Buffer
- WriteHandshakeMessage(&serverConfig, TagSCFG, map[Tag][]byte{
- TagSCID: s.ID,
- TagKEXS: []byte("C255"),
- TagAEAD: []byte("AESG"),
- TagPUBS: append([]byte{0x20, 0x00, 0x00}, s.kex.PublicKey()...),
- TagOBIT: {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7},
- TagEXPY: {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
- })
+ msg := HandshakeMessage{
+ Tag: TagSCFG,
+ Data: map[Tag][]byte{
+ TagSCID: s.ID,
+ TagKEXS: []byte("C255"),
+ TagAEAD: []byte("AESG"),
+ TagPUBS: append([]byte{0x20, 0x00, 0x00}, s.kex.PublicKey()...),
+ TagOBIT: s.obit,
+ TagEXPY: {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+ },
+ }
+ msg.Write(&serverConfig)
return serverConfig.Bytes()
}
// Sign the server config and CHLO with the server's keyData
func (s *ServerConfig) Sign(sni string, chlo []byte) ([]byte, error) {
- return s.signer.SignServerProof(sni, chlo, s.Get())
+ return s.certChain.SignServerProof(sni, chlo, s.Get())
}
// GetCertsCompressed returns the certificate data
func (s *ServerConfig) GetCertsCompressed(sni string, commonSetHashes, compressedHashes []byte) ([]byte, error) {
- return s.signer.GetCertsCompressed(sni, commonSetHashes, compressedHashes)
+ return s.certChain.GetCertsCompressed(sni, commonSetHashes, compressedHashes)
}
diff --git a/vendor/github.com/lucas-clemente/quic-go/handshake/server_config_client.go b/vendor/github.com/lucas-clemente/quic-go/handshake/server_config_client.go
new file mode 100644
index 0000000..4201419
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/handshake/server_config_client.go
@@ -0,0 +1,180 @@
+package handshake
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "math"
+ "time"
+
+ "github.com/lucas-clemente/quic-go/crypto"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/qerr"
+)
+
+type serverConfigClient struct {
+ raw []byte
+ ID []byte
+ obit []byte
+ expiry time.Time
+
+ kex crypto.KeyExchange
+ sharedSecret []byte
+}
+
+var (
+ errMessageNotServerConfig = errors.New("ServerConfig must have TagSCFG")
+)
+
+// parseServerConfig parses a server config
+func parseServerConfig(data []byte) (*serverConfigClient, error) {
+ message, err := ParseHandshakeMessage(bytes.NewReader(data))
+ if err != nil {
+ return nil, err
+ }
+ if message.Tag != TagSCFG {
+ return nil, errMessageNotServerConfig
+ }
+
+ scfg := &serverConfigClient{raw: data}
+ err = scfg.parseValues(message.Data)
+ if err != nil {
+ return nil, err
+ }
+
+ return scfg, nil
+}
+
+func (s *serverConfigClient) parseValues(tagMap map[Tag][]byte) error {
+ // SCID
+ scfgID, ok := tagMap[TagSCID]
+ if !ok {
+ return qerr.Error(qerr.CryptoMessageParameterNotFound, "SCID")
+ }
+ if len(scfgID) != 16 {
+ return qerr.Error(qerr.CryptoInvalidValueLength, "SCID")
+ }
+ s.ID = scfgID
+
+ // KEXS
+ // TODO: setup Key Exchange
+ kexs, ok := tagMap[TagKEXS]
+ if !ok {
+ return qerr.Error(qerr.CryptoMessageParameterNotFound, "KEXS")
+ }
+ if len(kexs)%4 != 0 {
+ return qerr.Error(qerr.CryptoInvalidValueLength, "KEXS")
+ }
+ c255Foundat := -1
+
+ for i := 0; i < len(kexs)/4; i++ {
+ if bytes.Equal(kexs[4*i:4*i+4], []byte("C255")) {
+ c255Foundat = i
+ break
+ }
+ }
+ if c255Foundat < 0 {
+ return qerr.Error(qerr.CryptoNoSupport, "KEXS: Could not find C255, other key exchanges are not supported")
+ }
+
+ // AEAD
+ aead, ok := tagMap[TagAEAD]
+ if !ok {
+ return qerr.Error(qerr.CryptoMessageParameterNotFound, "AEAD")
+ }
+ if len(aead)%4 != 0 {
+ return qerr.Error(qerr.CryptoInvalidValueLength, "AEAD")
+ }
+ var aesgFound bool
+ for i := 0; i < len(aead)/4; i++ {
+ if bytes.Equal(aead[4*i:4*i+4], []byte("AESG")) {
+ aesgFound = true
+ break
+ }
+ }
+ if !aesgFound {
+ return qerr.Error(qerr.CryptoNoSupport, "AEAD")
+ }
+
+ // PUBS
+ pubs, ok := tagMap[TagPUBS]
+ if !ok {
+ return qerr.Error(qerr.CryptoMessageParameterNotFound, "PUBS")
+ }
+
+ var pubs_kexs []struct{Length uint32; Value []byte}
+ var last_len uint32
+
+ for i := 0; i < len(pubs)-3; i += int(last_len)+3 {
+ // the PUBS value is always prepended by 3 byte little endian length field
+
+ err := binary.Read(bytes.NewReader([]byte{pubs[i], pubs[i+1], pubs[i+2], 0x00}), binary.LittleEndian, &last_len);
+ if err != nil {
+ return qerr.Error(qerr.CryptoInvalidValueLength, "PUBS not decodable")
+ }
+ if last_len == 0 {
+ return qerr.Error(qerr.CryptoInvalidValueLength, "PUBS")
+ }
+
+ if i+3+int(last_len) > len(pubs) {
+ return qerr.Error(qerr.CryptoInvalidValueLength, "PUBS")
+ }
+
+ pubs_kexs = append(pubs_kexs, struct{Length uint32; Value []byte}{last_len, pubs[i+3:i+3+int(last_len)]})
+ }
+
+ if c255Foundat >= len(pubs_kexs) {
+ return qerr.Error(qerr.CryptoMessageParameterNotFound, "KEXS not in PUBS")
+ }
+
+ if pubs_kexs[c255Foundat].Length != 32 {
+ return qerr.Error(qerr.CryptoInvalidValueLength, "PUBS")
+ }
+
+ var err error
+ s.kex, err = crypto.NewCurve25519KEX()
+ if err != nil {
+ return err
+ }
+
+
+ s.sharedSecret, err = s.kex.CalculateSharedKey(pubs_kexs[c255Foundat].Value)
+ if err != nil {
+ return err
+ }
+
+ // OBIT
+ obit, ok := tagMap[TagOBIT]
+ if !ok {
+ return qerr.Error(qerr.CryptoMessageParameterNotFound, "OBIT")
+ }
+ if len(obit) != 8 {
+ return qerr.Error(qerr.CryptoInvalidValueLength, "OBIT")
+ }
+ s.obit = obit
+
+ // EXPY
+ expy, ok := tagMap[TagEXPY]
+ if !ok {
+ return qerr.Error(qerr.CryptoMessageParameterNotFound, "EXPY")
+ }
+ if len(expy) != 8 {
+ return qerr.Error(qerr.CryptoInvalidValueLength, "EXPY")
+ }
+ // make sure that the value doesn't overflow an int64
+ // furthermore, values close to MaxInt64 are not a valid input to time.Unix, thus set MaxInt64/2 as the maximum value here
+ expyTimestamp := utils.MinUint64(binary.LittleEndian.Uint64(expy), math.MaxInt64/2)
+ s.expiry = time.Unix(int64(expyTimestamp), 0)
+
+ // TODO: implement VER
+
+ return nil
+}
+
+func (s *serverConfigClient) IsExpired() bool {
+ return s.expiry.Before(time.Now())
+}
+
+func (s *serverConfigClient) Get() []byte {
+ return s.raw
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/handshake/stk_generator.go b/vendor/github.com/lucas-clemente/quic-go/handshake/stk_generator.go
new file mode 100644
index 0000000..c3caea3
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/handshake/stk_generator.go
@@ -0,0 +1,100 @@
+package handshake
+
+import (
+ "encoding/asn1"
+ "fmt"
+ "net"
+ "time"
+
+ "github.com/lucas-clemente/quic-go/crypto"
+)
+
+const (
+ stkPrefixIP byte = iota
+ stkPrefixString
+)
+
+// An STK is a source address token
+type STK struct {
+ RemoteAddr string
+ SentTime time.Time
+}
+
+// token is the struct that is used for ASN1 serialization and deserialization
+type token struct {
+ Data []byte
+ Timestamp int64
+}
+
+// An STKGenerator generates STKs
+type STKGenerator struct {
+ stkSource crypto.StkSource
+}
+
+// NewSTKGenerator initializes a new STKGenerator
+func NewSTKGenerator() (*STKGenerator, error) {
+ stkSource, err := crypto.NewStkSource()
+ if err != nil {
+ return nil, err
+ }
+ return &STKGenerator{
+ stkSource: stkSource,
+ }, nil
+}
+
+// NewToken generates a new STK token for a given source address
+func (g *STKGenerator) NewToken(raddr net.Addr) ([]byte, error) {
+ data, err := asn1.Marshal(token{
+ Data: encodeRemoteAddr(raddr),
+ Timestamp: time.Now().Unix(),
+ })
+ if err != nil {
+ return nil, err
+ }
+ return g.stkSource.NewToken(data)
+}
+
+// DecodeToken decodes an STK token
+func (g *STKGenerator) DecodeToken(encrypted []byte) (*STK, error) {
+ // if the client didn't send any STK, DecodeToken will be called with a nil-slice
+ if len(encrypted) == 0 {
+ return nil, nil
+ }
+
+ data, err := g.stkSource.DecodeToken(encrypted)
+ if err != nil {
+ return nil, err
+ }
+ t := &token{}
+ rest, err := asn1.Unmarshal(data, t)
+ if err != nil {
+ return nil, err
+ }
+ if len(rest) != 0 {
+ return nil, fmt.Errorf("rest when unpacking token: %d", len(rest))
+ }
+ return &STK{
+ RemoteAddr: decodeRemoteAddr(t.Data),
+ SentTime: time.Unix(t.Timestamp, 0),
+ }, nil
+}
+
+// encodeRemoteAddr encodes a remote address such that it can be saved in the STK
+func encodeRemoteAddr(remoteAddr net.Addr) []byte {
+ if udpAddr, ok := remoteAddr.(*net.UDPAddr); ok {
+ return append([]byte{stkPrefixIP}, udpAddr.IP...)
+ }
+ return append([]byte{stkPrefixString}, []byte(remoteAddr.String())...)
+}
+
+// decodeRemoteAddr decodes the remote address saved in the STK
+func decodeRemoteAddr(data []byte) string {
+ // data will never be empty for an STK that we generated. Check it to be on the safe side
+ if len(data) == 0 {
+ return ""
+ }
+ if data[0] == stkPrefixIP {
+ return net.IP(data[1:]).String()
+ }
+ return string(data[1:])
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/tags.go b/vendor/github.com/lucas-clemente/quic-go/handshake/tags.go
similarity index 92%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/tags.go
rename to vendor/github.com/lucas-clemente/quic-go/handshake/tags.go
index 92d4d84..2b3783f 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/handshake/tags.go
+++ b/vendor/github.com/lucas-clemente/quic-go/handshake/tags.go
@@ -50,6 +50,11 @@ const (
// TagSFCW is the initial stream flow control receive window.
TagSFCW Tag = 'S' + 'F'<<8 + 'C'<<16 + 'W'<<24
+ // TagFHL2 forces head of line blocking.
+ // Chrome experiment (see https://codereview.chromium.org/2115033002)
+ // unsupported by quic-go
+ TagFHL2 Tag = 'F' + 'H'<<8 + 'L'<<16 + '2'<<24
+
// TagSTK is the source-address token
TagSTK Tag = 'S' + 'T'<<8 + 'K'<<16
// TagSNO is the server nonce
@@ -59,6 +64,8 @@ const (
// TagNONC is the client nonce
TagNONC Tag = 'N' + 'O'<<8 + 'N'<<16 + 'C'<<24
+ // TagXLCT is the expected leaf certificate
+ TagXLCT Tag = 'X' + 'L'<<8 + 'C'<<16 + 'T'<<24
// TagSCID is the server config ID
TagSCID Tag = 'S' + 'C'<<8 + 'I'<<16 + 'D'<<24
diff --git a/vendor/github.com/lucas-clemente/quic-go/interface.go b/vendor/github.com/lucas-clemente/quic-go/interface.go
new file mode 100644
index 0000000..c4b7ed3
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/interface.go
@@ -0,0 +1,121 @@
+package quic
+
+import (
+ "io"
+ "net"
+ "time"
+
+ "github.com/lucas-clemente/quic-go/protocol"
+)
+
+// Stream is the interface implemented by QUIC streams
+type Stream interface {
+ // Read reads data from the stream.
+ // Read can be made to time out and return a net.Error with Timeout() == true
+ // after a fixed time limit; see SetDeadline and SetReadDeadline.
+ io.Reader
+ // Write writes data to the stream.
+ // Write can be made to time out and return a net.Error with Timeout() == true
+ // after a fixed time limit; see SetDeadline and SetWriteDeadline.
+ io.Writer
+ io.Closer
+ StreamID() protocol.StreamID
+ // Reset closes the stream with an error.
+ Reset(error)
+ // SetReadDeadline sets the deadline for future Read calls and
+ // any currently-blocked Read call.
+ // A zero value for t means Read will not time out.
+ SetReadDeadline(t time.Time) error
+ // SetWriteDeadline sets the deadline for future Write calls
+ // and any currently-blocked Write call.
+ // Even if write times out, it may return n > 0, indicating that
+ // some of the data was successfully written.
+ // A zero value for t means Write will not time out.
+ SetWriteDeadline(t time.Time) error
+ // SetDeadline sets the read and write deadlines associated
+ // with the connection. It is equivalent to calling both
+ // SetReadDeadline and SetWriteDeadline.
+ SetDeadline(t time.Time) error
+}
+
+// A Session is a QUIC connection between two peers.
+type Session interface {
+ // AcceptStream returns the next stream opened by the peer, blocking until one is available.
+ // Since stream 1 is reserved for the crypto stream, the first stream is either 2 (for a client) or 3 (for a server).
+ AcceptStream() (Stream, error)
+ // OpenStream opens a new QUIC stream, returning a special error when the peeer's concurrent stream limit is reached.
+ // New streams always have the smallest possible stream ID.
+ // TODO: Enable testing for the special error
+ OpenStream() (Stream, error)
+ // OpenStreamSync opens a new QUIC stream, blocking until the peer's concurrent stream limit allows a new stream to be opened.
+ // It always picks the smallest possible stream ID.
+ OpenStreamSync() (Stream, error)
+ // LocalAddr returns the local address.
+ LocalAddr() net.Addr
+ // RemoteAddr returns the address of the peer.
+ RemoteAddr() net.Addr
+ // Close closes the connection. The error will be sent to the remote peer in a CONNECTION_CLOSE frame. An error value of nil is allowed and will cause a normal PeerGoingAway to be sent.
+ Close(error) error
+ // WaitUntilClosed() blocks until the session is closed.
+ // Warning: This API should not be considered stable and might change soon.
+ WaitUntilClosed()
+}
+
+// A NonFWSession is a QUIC connection between two peers half-way through the handshake.
+// The communication is encrypted, but not yet forward secure.
+type NonFWSession interface {
+ Session
+ WaitUntilHandshakeComplete() error
+}
+
+// An STK is a Source Address token.
+// It is issued by the server and sent to the client. For the client, it is an opaque blob.
+// The client can send the STK in subsequent handshakes to prove ownership of its IP address.
+type STK struct {
+ // The remote address this token was issued for.
+ // If the server is run on a net.UDPConn, this is the string representation of the IP address (net.IP.String())
+ // Otherwise, this is the string representation of the net.Addr (net.Addr.String())
+ remoteAddr string
+ // The time that the STK was issued (resolution 1 second)
+ sentTime time.Time
+}
+
+// Config contains all configuration data needed for a QUIC server or client.
+// More config parameters (such as timeouts) will be added soon, see e.g. https://github.com/lucas-clemente/quic-go/issues/441.
+type Config struct {
+ // The QUIC versions that can be negotiated.
+ // If not set, it uses all versions available.
+ // Warning: This API should not be considered stable and will change soon.
+ Versions []protocol.VersionNumber
+ // Ask the server to truncate the connection ID sent in the Public Header.
+ // This saves 8 bytes in the Public Header in every packet. However, if the IP address of the server changes, the connection cannot be migrated.
+ // Currently only valid for the client.
+ RequestConnectionIDTruncation bool
+ // HandshakeTimeout is the maximum duration that the cryptographic handshake may take.
+ // If the timeout is exceeded, the connection is closed.
+ // If this value is zero, the timeout is set to 10 seconds.
+ HandshakeTimeout time.Duration
+ // AcceptSTK determines if an STK is accepted.
+ // It is called with stk = nil if the client didn't send an STK.
+ // If not set, it verifies that the address matches, and that the STK was issued within the last 24 hours.
+ // This option is only valid for the server.
+ AcceptSTK func(clientAddr net.Addr, stk *STK) bool
+ // MaxReceiveStreamFlowControlWindow is the maximum stream-level flow control window for receiving data.
+ // If this value is zero, it will default to 1 MB for the server and 6 MB for the client.
+ MaxReceiveStreamFlowControlWindow protocol.ByteCount
+ // MaxReceiveConnectionFlowControlWindow is the connection-level flow control window for receiving data.
+ // If this value is zero, it will default to 1.5 MB for the server and 15 MB for the client.
+ MaxReceiveConnectionFlowControlWindow protocol.ByteCount
+ // KeepAlive defines whether this peer will periodically send PING frames to keep the connection alive.
+ KeepAlive bool
+}
+
+// A Listener for incoming QUIC connections
+type Listener interface {
+ // Close the server, sending CONNECTION_CLOSE frames to each peer.
+ Close() error
+ // Addr returns the local network addr that the server is listening on.
+ Addr() net.Addr
+ // Accept returns new sessions. It should be called in a loop.
+ Accept() (Session, error)
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/_gen.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/_gen.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/_gen.go
rename to vendor/github.com/lucas-clemente/quic-go/internal/utils/_gen.go
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/atomic_bool.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/atomic_bool.go
new file mode 100644
index 0000000..cf46425
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/atomic_bool.go
@@ -0,0 +1,22 @@
+package utils
+
+import "sync/atomic"
+
+// An AtomicBool is an atomic bool
+type AtomicBool struct {
+ v int32
+}
+
+// Set sets the value
+func (a *AtomicBool) Set(value bool) {
+ var n int32
+ if value {
+ n = 1
+ }
+ atomic.StoreInt32(&a.v, n)
+}
+
+// Get gets the value
+func (a *AtomicBool) Get() bool {
+ return atomic.LoadInt32(&a.v) != 0
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/byteinterval_linkedlist.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/byteinterval_linkedlist.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/byteinterval_linkedlist.go
rename to vendor/github.com/lucas-clemente/quic-go/internal/utils/byteinterval_linkedlist.go
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/connection_id.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/connection_id.go
new file mode 100644
index 0000000..c2252e6
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/connection_id.go
@@ -0,0 +1,18 @@
+package utils
+
+import (
+ "crypto/rand"
+ "encoding/binary"
+
+ "github.com/lucas-clemente/quic-go/protocol"
+)
+
+// GenerateConnectionID generates a connection ID using cryptographic random
+func GenerateConnectionID() (protocol.ConnectionID, error) {
+ b := make([]byte, 8)
+ _, err := rand.Read(b)
+ if err != nil {
+ return 0, err
+ }
+ return protocol.ConnectionID(binary.LittleEndian.Uint64(b)), nil
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/float16.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/float16.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/float16.go
rename to vendor/github.com/lucas-clemente/quic-go/internal/utils/float16.go
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/host.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/host.go
new file mode 100644
index 0000000..a1d6453
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/host.go
@@ -0,0 +1,27 @@
+package utils
+
+import (
+ "net/url"
+ "strings"
+)
+
+// HostnameFromAddr determines the hostname in an address string
+func HostnameFromAddr(addr string) (string, error) {
+ p, err := url.Parse(addr)
+ if err != nil {
+ return "", err
+ }
+ h := p.Host
+
+ // copied from https://golang.org/src/net/http/transport.go
+ if hasPort(h) {
+ h = h[:strings.LastIndex(h, ":")]
+ }
+
+ return h, nil
+}
+
+// copied from https://golang.org/src/net/http/http.go
+func hasPort(s string) bool {
+ return strings.LastIndex(s, ":") > strings.LastIndex(s, "]")
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/log.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/log.go
new file mode 100644
index 0000000..9128510
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/log.go
@@ -0,0 +1,94 @@
+package utils
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "time"
+)
+
+// LogLevel of quic-go
+type LogLevel uint8
+
+const logEnv = "QUIC_GO_LOG_LEVEL"
+
+const (
+ // LogLevelNothing disables
+ LogLevelNothing LogLevel = iota
+ // LogLevelError enables err logs
+ LogLevelError
+ // LogLevelInfo enables info logs (e.g. packets)
+ LogLevelInfo
+ // LogLevelDebug enables debug logs (e.g. packet contents)
+ LogLevelDebug
+)
+
+var (
+ logLevel = LogLevelNothing
+ timeFormat = ""
+)
+
+// SetLogLevel sets the log level
+func SetLogLevel(level LogLevel) {
+ logLevel = level
+}
+
+// SetLogTimeFormat sets the format of the timestamp
+// an empty string disables the logging of timestamps
+func SetLogTimeFormat(format string) {
+ log.SetFlags(0) // disable timestamp logging done by the log package
+ timeFormat = format
+}
+
+// Debugf logs something
+func Debugf(format string, args ...interface{}) {
+ if logLevel == LogLevelDebug {
+ logMessage(format, args...)
+ }
+}
+
+// Infof logs something
+func Infof(format string, args ...interface{}) {
+ if logLevel >= LogLevelInfo {
+ logMessage(format, args...)
+ }
+}
+
+// Errorf logs something
+func Errorf(format string, args ...interface{}) {
+ if logLevel >= LogLevelError {
+ logMessage(format, args...)
+ }
+}
+
+func logMessage(format string, args ...interface{}) {
+ if len(timeFormat) > 0 {
+ log.Printf(time.Now().Format(timeFormat)+" "+format, args...)
+ } else {
+ log.Printf(format, args...)
+ }
+}
+
+// Debug returns true if the log level is LogLevelDebug
+func Debug() bool {
+ return logLevel == LogLevelDebug
+}
+
+func init() {
+ readLoggingEnv()
+}
+
+func readLoggingEnv() {
+ switch os.Getenv(logEnv) {
+ case "":
+ return
+ case "DEBUG":
+ logLevel = LogLevelDebug
+ case "INFO":
+ logLevel = LogLevelInfo
+ case "ERROR":
+ logLevel = LogLevelError
+ default:
+ fmt.Fprintln(os.Stderr, "invalid quic-go log level, see https://github.com/lucas-clemente/quic-go/wiki/Logging")
+ }
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/minmax.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/minmax.go
similarity index 94%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/minmax.go
rename to vendor/github.com/lucas-clemente/quic-go/internal/utils/minmax.go
index ec22139..6e23df5 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/minmax.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/minmax.go
@@ -34,6 +34,14 @@ func MaxUint64(a, b uint64) uint64 {
return a
}
+// MinUint64 returns the maximum of two uint64
+func MinUint64(a, b uint64) uint64 {
+ if a < b {
+ return a
+ }
+ return b
+}
+
// Min returns the minimum of two Ints
func Min(a, b int) int {
if a < b {
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/packet_interval.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/packet_interval.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/packet_interval.go
rename to vendor/github.com/lucas-clemente/quic-go/internal/utils/packet_interval.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/packetinterval_linkedlist.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/packetinterval_linkedlist.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/packetinterval_linkedlist.go
rename to vendor/github.com/lucas-clemente/quic-go/internal/utils/packetinterval_linkedlist.go
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/streamframe_interval.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/streamframe_interval.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/streamframe_interval.go
rename to vendor/github.com/lucas-clemente/quic-go/internal/utils/streamframe_interval.go
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/timer.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/timer.go
new file mode 100644
index 0000000..695ad3e
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/timer.go
@@ -0,0 +1,43 @@
+package utils
+
+import "time"
+
+// A Timer wrapper that behaves correctly when resetting
+type Timer struct {
+ t *time.Timer
+ read bool
+ deadline time.Time
+}
+
+// NewTimer creates a new timer that is not set
+func NewTimer() *Timer {
+ return &Timer{t: time.NewTimer(0)}
+}
+
+// Chan returns the channel of the wrapped timer
+func (t *Timer) Chan() <-chan time.Time {
+ return t.t.C
+}
+
+// Reset the timer, no matter whether the value was read or not
+func (t *Timer) Reset(deadline time.Time) {
+ if deadline.Equal(t.deadline) {
+ // No need to reset the timer
+ return
+ }
+
+ // We need to drain the timer if the value from its channel was not read yet.
+ // See https://groups.google.com/forum/#!topic/golang-dev/c9UUfASVPoU
+ if !t.t.Stop() && !t.read {
+ <-t.t.C
+ }
+ t.t.Reset(deadline.Sub(time.Now()))
+
+ t.read = false
+ t.deadline = deadline
+}
+
+// SetRead should be called after the value from the chan was read
+func (t *Timer) SetRead() {
+ t.read = true
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/utils.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/utils.go
similarity index 93%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/utils.go
rename to vendor/github.com/lucas-clemente/quic-go/internal/utils/utils.go
index cf25679..f6c4e03 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/utils/utils.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/utils.go
@@ -3,19 +3,8 @@ package utils
import (
"bytes"
"io"
-
- "github.com/lucas-clemente/quic-go/protocol"
)
-// Stream is the interface for QUIC streams
-type Stream interface {
- io.Reader
- io.Writer
- io.Closer
- StreamID() protocol.StreamID
- CloseRemote(offset protocol.ByteCount)
-}
-
// ReadUintN reads N bytes
func ReadUintN(b io.ByteReader, length uint8) (uint64, error) {
var res uint64
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/packet_number_generator.go b/vendor/github.com/lucas-clemente/quic-go/packet_number_generator.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/packet_number_generator.go
rename to vendor/github.com/lucas-clemente/quic-go/packet_number_generator.go
diff --git a/vendor/github.com/lucas-clemente/quic-go/packet_packer.go b/vendor/github.com/lucas-clemente/quic-go/packet_packer.go
new file mode 100644
index 0000000..28c29ac
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/packet_packer.go
@@ -0,0 +1,331 @@
+package quic
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+
+ "github.com/lucas-clemente/quic-go/ackhandler"
+ "github.com/lucas-clemente/quic-go/frames"
+ "github.com/lucas-clemente/quic-go/handshake"
+ "github.com/lucas-clemente/quic-go/protocol"
+)
+
+type packedPacket struct {
+ number protocol.PacketNumber
+ raw []byte
+ frames []frames.Frame
+ encryptionLevel protocol.EncryptionLevel
+}
+
+type packetPacker struct {
+ connectionID protocol.ConnectionID
+ perspective protocol.Perspective
+ version protocol.VersionNumber
+ cryptoSetup handshake.CryptoSetup
+
+ packetNumberGenerator *packetNumberGenerator
+ connectionParameters handshake.ConnectionParametersManager
+ streamFramer *streamFramer
+
+ controlFrames []frames.Frame
+ stopWaiting *frames.StopWaitingFrame
+ ackFrame *frames.AckFrame
+ leastUnacked protocol.PacketNumber
+}
+
+func newPacketPacker(connectionID protocol.ConnectionID,
+ cryptoSetup handshake.CryptoSetup,
+ connectionParameters handshake.ConnectionParametersManager,
+ streamFramer *streamFramer,
+ perspective protocol.Perspective,
+ version protocol.VersionNumber,
+) *packetPacker {
+ return &packetPacker{
+ cryptoSetup: cryptoSetup,
+ connectionID: connectionID,
+ connectionParameters: connectionParameters,
+ perspective: perspective,
+ version: version,
+ streamFramer: streamFramer,
+ packetNumberGenerator: newPacketNumberGenerator(protocol.SkipPacketAveragePeriodLength),
+ }
+}
+
+// PackConnectionClose packs a packet that ONLY contains a ConnectionCloseFrame
+func (p *packetPacker) PackConnectionClose(ccf *frames.ConnectionCloseFrame) (*packedPacket, error) {
+ frames := []frames.Frame{ccf}
+ encLevel, sealer := p.cryptoSetup.GetSealer()
+ ph := p.getPublicHeader(encLevel)
+ raw, err := p.writeAndSealPacket(ph, frames, sealer)
+ return &packedPacket{
+ number: ph.PacketNumber,
+ raw: raw,
+ frames: frames,
+ encryptionLevel: encLevel,
+ }, err
+}
+
+func (p *packetPacker) PackAckPacket() (*packedPacket, error) {
+ if p.ackFrame == nil {
+ return nil, errors.New("packet packer BUG: no ack frame queued")
+ }
+ encLevel, sealer := p.cryptoSetup.GetSealer()
+ ph := p.getPublicHeader(encLevel)
+ frames := []frames.Frame{p.ackFrame}
+ if p.stopWaiting != nil {
+ p.stopWaiting.PacketNumber = ph.PacketNumber
+ p.stopWaiting.PacketNumberLen = ph.PacketNumberLen
+ frames = append(frames, p.stopWaiting)
+ p.stopWaiting = nil
+ }
+ p.ackFrame = nil
+ raw, err := p.writeAndSealPacket(ph, frames, sealer)
+ return &packedPacket{
+ number: ph.PacketNumber,
+ raw: raw,
+ frames: frames,
+ encryptionLevel: encLevel,
+ }, err
+}
+
+// PackHandshakeRetransmission retransmits a handshake packet, that was sent with less than forward-secure encryption
+func (p *packetPacker) PackHandshakeRetransmission(packet *ackhandler.Packet) (*packedPacket, error) {
+ if packet.EncryptionLevel == protocol.EncryptionForwardSecure {
+ return nil, errors.New("PacketPacker BUG: forward-secure encrypted handshake packets don't need special treatment")
+ }
+ sealer, err := p.cryptoSetup.GetSealerWithEncryptionLevel(packet.EncryptionLevel)
+ if err != nil {
+ return nil, err
+ }
+ if p.stopWaiting == nil {
+ return nil, errors.New("PacketPacker BUG: Handshake retransmissions must contain a StopWaitingFrame")
+ }
+ ph := p.getPublicHeader(packet.EncryptionLevel)
+ p.stopWaiting.PacketNumber = ph.PacketNumber
+ p.stopWaiting.PacketNumberLen = ph.PacketNumberLen
+ frames := append([]frames.Frame{p.stopWaiting}, packet.Frames...)
+ p.stopWaiting = nil
+ raw, err := p.writeAndSealPacket(ph, frames, sealer)
+ return &packedPacket{
+ number: ph.PacketNumber,
+ raw: raw,
+ frames: frames,
+ encryptionLevel: packet.EncryptionLevel,
+ }, err
+}
+
+// PackPacket packs a new packet
+// the other controlFrames are sent in the next packet, but might be queued and sent in the next packet if the packet would overflow MaxPacketSize otherwise
+func (p *packetPacker) PackPacket() (*packedPacket, error) {
+ if p.streamFramer.HasCryptoStreamFrame() {
+ return p.packCryptoPacket()
+ }
+
+ encLevel, sealer := p.cryptoSetup.GetSealer()
+
+ publicHeader := p.getPublicHeader(encLevel)
+ publicHeaderLength, err := publicHeader.GetLength(p.perspective)
+ if err != nil {
+ return nil, err
+ }
+ if p.stopWaiting != nil {
+ p.stopWaiting.PacketNumber = publicHeader.PacketNumber
+ p.stopWaiting.PacketNumberLen = publicHeader.PacketNumberLen
+ }
+
+ maxSize := protocol.MaxFrameAndPublicHeaderSize - publicHeaderLength
+ payloadFrames, err := p.composeNextPacket(maxSize, p.canSendData(encLevel))
+ if err != nil {
+ return nil, err
+ }
+
+ // Check if we have enough frames to send
+ if len(payloadFrames) == 0 {
+ return nil, nil
+ }
+ // Don't send out packets that only contain a StopWaitingFrame
+ if len(payloadFrames) == 1 && p.stopWaiting != nil {
+ return nil, nil
+ }
+ p.stopWaiting = nil
+ p.ackFrame = nil
+
+ raw, err := p.writeAndSealPacket(publicHeader, payloadFrames, sealer)
+ if err != nil {
+ return nil, err
+ }
+ return &packedPacket{
+ number: publicHeader.PacketNumber,
+ raw: raw,
+ frames: payloadFrames,
+ encryptionLevel: encLevel,
+ }, nil
+}
+
+func (p *packetPacker) packCryptoPacket() (*packedPacket, error) {
+ encLevel, sealer := p.cryptoSetup.GetSealerForCryptoStream()
+ publicHeader := p.getPublicHeader(encLevel)
+ publicHeaderLength, err := publicHeader.GetLength(p.perspective)
+ if err != nil {
+ return nil, err
+ }
+ maxLen := protocol.MaxFrameAndPublicHeaderSize - protocol.NonForwardSecurePacketSizeReduction - publicHeaderLength
+ frames := []frames.Frame{p.streamFramer.PopCryptoStreamFrame(maxLen)}
+ raw, err := p.writeAndSealPacket(publicHeader, frames, sealer)
+ if err != nil {
+ return nil, err
+ }
+ return &packedPacket{
+ number: publicHeader.PacketNumber,
+ raw: raw,
+ frames: frames,
+ encryptionLevel: encLevel,
+ }, nil
+}
+
+func (p *packetPacker) composeNextPacket(
+ maxFrameSize protocol.ByteCount,
+ canSendStreamFrames bool,
+) ([]frames.Frame, error) {
+ var payloadLength protocol.ByteCount
+ var payloadFrames []frames.Frame
+
+ // STOP_WAITING and ACK will always fit
+ if p.stopWaiting != nil {
+ payloadFrames = append(payloadFrames, p.stopWaiting)
+ l, err := p.stopWaiting.MinLength(p.version)
+ if err != nil {
+ return nil, err
+ }
+ payloadLength += l
+ }
+ if p.ackFrame != nil {
+ payloadFrames = append(payloadFrames, p.ackFrame)
+ l, err := p.ackFrame.MinLength(p.version)
+ if err != nil {
+ return nil, err
+ }
+ payloadLength += l
+ }
+
+ for len(p.controlFrames) > 0 {
+ frame := p.controlFrames[len(p.controlFrames)-1]
+ minLength, err := frame.MinLength(p.version)
+ if err != nil {
+ return nil, err
+ }
+ if payloadLength+minLength > maxFrameSize {
+ break
+ }
+ payloadFrames = append(payloadFrames, frame)
+ payloadLength += minLength
+ p.controlFrames = p.controlFrames[:len(p.controlFrames)-1]
+ }
+
+ if payloadLength > maxFrameSize {
+ return nil, fmt.Errorf("Packet Packer BUG: packet payload (%d) too large (%d)", payloadLength, maxFrameSize)
+ }
+
+ if !canSendStreamFrames {
+ return payloadFrames, nil
+ }
+
+ // temporarily increase the maxFrameSize by 2 bytes
+ // this leads to a properly sized packet in all cases, since we do all the packet length calculations with StreamFrames that have the DataLen set
+ // however, for the last StreamFrame in the packet, we can omit the DataLen, thus saving 2 bytes and yielding a packet of exactly the correct size
+ maxFrameSize += 2
+
+ fs := p.streamFramer.PopStreamFrames(maxFrameSize - payloadLength)
+ if len(fs) != 0 {
+ fs[len(fs)-1].DataLenPresent = false
+ }
+
+ // TODO: Simplify
+ for _, f := range fs {
+ payloadFrames = append(payloadFrames, f)
+ }
+
+ for b := p.streamFramer.PopBlockedFrame(); b != nil; b = p.streamFramer.PopBlockedFrame() {
+ p.controlFrames = append(p.controlFrames, b)
+ }
+
+ return payloadFrames, nil
+}
+
+func (p *packetPacker) QueueControlFrame(frame frames.Frame) {
+ switch f := frame.(type) {
+ case *frames.StopWaitingFrame:
+ p.stopWaiting = f
+ case *frames.AckFrame:
+ p.ackFrame = f
+ default:
+ p.controlFrames = append(p.controlFrames, f)
+ }
+}
+
+func (p *packetPacker) getPublicHeader(encLevel protocol.EncryptionLevel) *PublicHeader {
+ pnum := p.packetNumberGenerator.Peek()
+ packetNumberLen := protocol.GetPacketNumberLengthForPublicHeader(pnum, p.leastUnacked)
+ publicHeader := &PublicHeader{
+ ConnectionID: p.connectionID,
+ PacketNumber: pnum,
+ PacketNumberLen: packetNumberLen,
+ TruncateConnectionID: p.connectionParameters.TruncateConnectionID(),
+ }
+
+ if p.perspective == protocol.PerspectiveServer && encLevel == protocol.EncryptionSecure {
+ publicHeader.DiversificationNonce = p.cryptoSetup.DiversificationNonce()
+ }
+ if p.perspective == protocol.PerspectiveClient && encLevel != protocol.EncryptionForwardSecure {
+ publicHeader.VersionFlag = true
+ publicHeader.VersionNumber = p.version
+ }
+
+ return publicHeader
+}
+
+func (p *packetPacker) writeAndSealPacket(
+ publicHeader *PublicHeader,
+ payloadFrames []frames.Frame,
+ sealer handshake.Sealer,
+) ([]byte, error) {
+ raw := getPacketBuffer()
+ buffer := bytes.NewBuffer(raw)
+
+ if err := publicHeader.Write(buffer, p.version, p.perspective); err != nil {
+ return nil, err
+ }
+ payloadStartIndex := buffer.Len()
+ for _, frame := range payloadFrames {
+ err := frame.Write(buffer, p.version)
+ if err != nil {
+ return nil, err
+ }
+ }
+ if protocol.ByteCount(buffer.Len()+12) > protocol.MaxPacketSize {
+ return nil, errors.New("PacketPacker BUG: packet too large")
+ }
+
+ raw = raw[0:buffer.Len()]
+ _ = sealer(raw[payloadStartIndex:payloadStartIndex], raw[payloadStartIndex:], publicHeader.PacketNumber, raw[:payloadStartIndex])
+ raw = raw[0 : buffer.Len()+12]
+
+ num := p.packetNumberGenerator.Pop()
+ if num != publicHeader.PacketNumber {
+ return nil, errors.New("packetPacker BUG: Peeked and Popped packet numbers do not match")
+ }
+
+ return raw, nil
+}
+
+func (p *packetPacker) canSendData(encLevel protocol.EncryptionLevel) bool {
+ if p.perspective == protocol.PerspectiveClient {
+ return encLevel >= protocol.EncryptionSecure
+ }
+ return encLevel == protocol.EncryptionForwardSecure
+}
+
+func (p *packetPacker) SetLeastUnacked(leastUnacked protocol.PacketNumber) {
+ p.leastUnacked = leastUnacked
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go b/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go
similarity index 77%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go
rename to vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go
index 3434751..c92e6a5 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go
+++ b/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go
@@ -5,25 +5,29 @@ import (
"errors"
"fmt"
- "github.com/lucas-clemente/quic-go/crypto"
"github.com/lucas-clemente/quic-go/frames"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
)
type unpackedPacket struct {
- frames []frames.Frame
+ encryptionLevel protocol.EncryptionLevel
+ frames []frames.Frame
+}
+
+type quicAEAD interface {
+ Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error)
}
type packetUnpacker struct {
version protocol.VersionNumber
- aead crypto.AEAD
+ aead quicAEAD
}
func (u *packetUnpacker) Unpack(publicHeaderBinary []byte, hdr *PublicHeader, data []byte) (*unpackedPacket, error) {
buf := getPacketBuffer()
defer putPacketBuffer(buf)
- decrypted, err := u.aead.Open(buf, data, hdr.PacketNumber, publicHeaderBinary)
+ decrypted, encryptionLevel, err := u.aead.Open(buf, data, hdr.PacketNumber, publicHeaderBinary)
if err != nil {
// Wrap err in quicError so that public reset is sent by session
return nil, qerr.Error(qerr.DecryptionFailure, err.Error())
@@ -37,9 +41,11 @@ func (u *packetUnpacker) Unpack(publicHeaderBinary []byte, hdr *PublicHeader, da
fs := make([]frames.Frame, 0, 2)
// Read all frames in the packet
-ReadLoop:
for r.Len() > 0 {
typeByte, _ := r.ReadByte()
+ if typeByte == 0x0 { // PADDING frame
+ continue
+ }
r.UnreadByte()
var frame frames.Frame
@@ -47,6 +53,11 @@ ReadLoop:
frame, err = frames.ParseStreamFrame(r)
if err != nil {
err = qerr.Error(qerr.InvalidStreamData, err.Error())
+ } else {
+ streamID := frame.(*frames.StreamFrame).StreamID
+ if streamID != 1 && encryptionLevel <= protocol.EncryptionUnencrypted {
+ err = qerr.Error(qerr.UnencryptedStreamData, fmt.Sprintf("received unencrypted stream data on stream %d", streamID))
+ }
}
} else if typeByte&0xc0 == 0x40 {
frame, err = frames.ParseAckFrame(r, u.version)
@@ -57,8 +68,6 @@ ReadLoop:
err = errors.New("unimplemented: CONGESTION_FEEDBACK")
} else {
switch typeByte {
- case 0x0: // PAD, end of frames
- break ReadLoop
case 0x01:
frame, err = frames.ParseRstStreamFrame(r)
if err != nil {
@@ -104,6 +113,7 @@ ReadLoop:
}
return &unpackedPacket{
- frames: fs,
+ encryptionLevel: encryptionLevel,
+ frames: fs,
}, nil
}
diff --git a/vendor/github.com/lucas-clemente/quic-go/protocol/encryption_level.go b/vendor/github.com/lucas-clemente/quic-go/protocol/encryption_level.go
new file mode 100644
index 0000000..19480b1
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/protocol/encryption_level.go
@@ -0,0 +1,28 @@
+package protocol
+
+// EncryptionLevel is the encryption level
+// Default value is Unencrypted
+type EncryptionLevel int
+
+const (
+ // EncryptionUnspecified is a not specified encryption level
+ EncryptionUnspecified EncryptionLevel = iota
+ // EncryptionUnencrypted is not encrypted
+ EncryptionUnencrypted
+ // EncryptionSecure is encrypted, but not forward secure
+ EncryptionSecure
+ // EncryptionForwardSecure is forward secure
+ EncryptionForwardSecure
+)
+
+func (e EncryptionLevel) String() string {
+ switch e {
+ case EncryptionUnencrypted:
+ return "unencrypted"
+ case EncryptionSecure:
+ return "encrypted (not forward-secure)"
+ case EncryptionForwardSecure:
+ return "forward-secure"
+ }
+ return "unknown"
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/protocol/packet_number.go b/vendor/github.com/lucas-clemente/quic-go/protocol/packet_number.go
similarity index 100%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/protocol/packet_number.go
rename to vendor/github.com/lucas-clemente/quic-go/protocol/packet_number.go
diff --git a/vendor/github.com/lucas-clemente/quic-go/protocol/perspective.go b/vendor/github.com/lucas-clemente/quic-go/protocol/perspective.go
new file mode 100644
index 0000000..6aa3b70
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/protocol/perspective.go
@@ -0,0 +1,10 @@
+package protocol
+
+// Perspective determines if we're acting as a server or a client
+type Perspective int
+
+// the perspectives
+const (
+ PerspectiveServer Perspective = 1
+ PerspectiveClient Perspective = 2
+)
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/protocol/protocol.go b/vendor/github.com/lucas-clemente/quic-go/protocol/protocol.go
similarity index 67%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/protocol/protocol.go
rename to vendor/github.com/lucas-clemente/quic-go/protocol/protocol.go
index aae2e0a..cf9cf05 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/protocol/protocol.go
+++ b/vendor/github.com/lucas-clemente/quic-go/protocol/protocol.go
@@ -1,9 +1,6 @@
package protocol
-import (
- "math"
- "time"
-)
+import "math"
// A PacketNumber in QUIC
type PacketNumber uint64
@@ -34,14 +31,13 @@ type StreamID uint32
type ByteCount uint64
// MaxByteCount is the maximum value of a ByteCount
-const MaxByteCount = math.MaxUint64
+const MaxByteCount = ByteCount(math.MaxUint64)
-// MaxPacketSize is the maximum packet size, including the public header
-// This is the value used by Chromium for a QUIC packet sent using IPv6 (for IPv4 it would be 1370)
-const MaxPacketSize ByteCount = 1350
-
-// MaxFrameAndPublicHeaderSize is the maximum size of a QUIC frame plus PublicHeader
-const MaxFrameAndPublicHeaderSize = MaxPacketSize - 12 /*crypto signature*/
+// MaxReceivePacketSize maximum packet size of any QUIC packet, based on
+// ethernet's max size, minus the IP and UDP headers. IPv6 has a 40 byte header,
+// UDP adds an additional 8 bytes. This is a total overhead of 48 bytes.
+// Ethernet's max packet size is 1500 bytes, 1500 - 48 = 1452.
+const MaxReceivePacketSize ByteCount = 1452
// DefaultTCPMSS is the default maximum packet size used in the Linux TCP implementation.
// Used in QUIC for congestion window computations in bytes.
@@ -53,14 +49,11 @@ const InitialStreamFlowControlWindow ByteCount = (1 << 14) // 16 kB
// InitialConnectionFlowControlWindow is the initial connection-level flow control window for sending
const InitialConnectionFlowControlWindow ByteCount = (1 << 14) // 16 kB
-// DefaultRetransmissionTime is the RTO time on new connections
-const DefaultRetransmissionTime = 500 * time.Millisecond
-
-// MinRetransmissionTime is the minimum RTO time
-const MinRetransmissionTime = 200 * time.Millisecond
-
-// MaxRetransmissionTime is the maximum RTO time
-const MaxRetransmissionTime = 60 * time.Second
-
// ClientHelloMinimumSize is the minimum size the server expects an inchoate CHLO to have.
const ClientHelloMinimumSize = 1024
+
+// MaxClientHellos is the maximum number of times we'll send a client hello
+// The value 3 accounts for:
+// * one failure due to an incorrect or missing source-address token
+// * one failure due the server's certificate chain being unavailible and the server being unwilling to send it without a valid source-address token
+const MaxClientHellos = 3
diff --git a/vendor/github.com/lucas-clemente/quic-go/protocol/server_parameters.go b/vendor/github.com/lucas-clemente/quic-go/protocol/server_parameters.go
new file mode 100644
index 0000000..8e632cc
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/protocol/server_parameters.go
@@ -0,0 +1,139 @@
+package protocol
+
+import "time"
+
+// MaxPacketSize is the maximum packet size, including the public header, that we use for sending packets
+// This is the value used by Chromium for a QUIC packet sent using IPv6 (for IPv4 it would be 1370)
+const MaxPacketSize ByteCount = 1350
+
+// MaxFrameAndPublicHeaderSize is the maximum size of a QUIC frame plus PublicHeader
+const MaxFrameAndPublicHeaderSize = MaxPacketSize - 12 /*crypto signature*/
+
+// NonForwardSecurePacketSizeReduction is the number of bytes a non forward-secure packet has to be smaller than a forward-secure packet
+// This makes sure that those packets can always be retransmitted without splitting the contained StreamFrames
+const NonForwardSecurePacketSizeReduction = 50
+
+// DefaultMaxCongestionWindow is the default for the max congestion window
+const DefaultMaxCongestionWindow = 1000
+
+// InitialCongestionWindow is the initial congestion window in QUIC packets
+const InitialCongestionWindow = 32
+
+// MaxUndecryptablePackets limits the number of undecryptable packets that a
+// session queues for later until it sends a public reset.
+const MaxUndecryptablePackets = 10
+
+// PublicResetTimeout is the time to wait before sending a Public Reset when receiving too many undecryptable packets during the handshake
+// This timeout allows the Go scheduler to switch to the Go rountine that reads the crypto stream and to escalate the crypto
+const PublicResetTimeout = 500 * time.Millisecond
+
+// AckSendDelay is the maximum delay that can be applied to an ACK for a retransmittable packet
+// This is the value Chromium is using
+const AckSendDelay = 25 * time.Millisecond
+
+// ReceiveStreamFlowControlWindow is the stream-level flow control window for receiving data
+// This is the value that Google servers are using
+const ReceiveStreamFlowControlWindow ByteCount = (1 << 10) * 32 // 32 kB
+
+// ReceiveConnectionFlowControlWindow is the connection-level flow control window for receiving data
+// This is the value that Google servers are using
+const ReceiveConnectionFlowControlWindow ByteCount = (1 << 10) * 48 // 48 kB
+
+// DefaultMaxReceiveStreamFlowControlWindowServer is the default maximum stream-level flow control window for receiving data, for the server
+// This is the value that Google servers are using
+const DefaultMaxReceiveStreamFlowControlWindowServer ByteCount = 1 * (1 << 20) // 1 MB
+
+// DefaultMaxReceiveConnectionFlowControlWindowServer is the default connection-level flow control window for receiving data, for the server
+// This is the value that Google servers are using
+const DefaultMaxReceiveConnectionFlowControlWindowServer ByteCount = 1.5 * (1 << 20) // 1.5 MB
+
+// DefaultMaxReceiveStreamFlowControlWindowClient is the default maximum stream-level flow control window for receiving data, for the client
+// This is the value that Chromium is using
+const DefaultMaxReceiveStreamFlowControlWindowClient ByteCount = 6 * (1 << 20) // 6 MB
+
+// DefaultMaxReceiveConnectionFlowControlWindowClient is the default connection-level flow control window for receiving data, for the client
+// This is the value that Google servers are using
+const DefaultMaxReceiveConnectionFlowControlWindowClient ByteCount = 15 * (1 << 20) // 15 MB
+
+// ConnectionFlowControlMultiplier determines how much larger the connection flow control windows needs to be relative to any stream's flow control window
+// This is the value that Chromium is using
+const ConnectionFlowControlMultiplier = 1.5
+
+// MaxStreamsPerConnection is the maximum value accepted for the number of streams per connection
+const MaxStreamsPerConnection = 100
+
+// MaxIncomingDynamicStreamsPerConnection is the maximum value accepted for the incoming number of dynamic streams per connection
+const MaxIncomingDynamicStreamsPerConnection = 100
+
+// MaxStreamsMultiplier is the slack the client is allowed for the maximum number of streams per connection, needed e.g. when packets are out of order or dropped. The minimum of this procentual increase and the absolute increment specified by MaxStreamsMinimumIncrement is used.
+const MaxStreamsMultiplier = 1.1
+
+// MaxStreamsMinimumIncrement is the slack the client is allowed for the maximum number of streams per connection, needed e.g. when packets are out of order or dropped. The minimum of this absolute increment and the procentual increase specified by MaxStreamsMultiplier is used.
+const MaxStreamsMinimumIncrement = 10
+
+// MaxNewStreamIDDelta is the maximum difference between and a newly opened Stream and the highest StreamID that a client has ever opened
+// note that the number of streams is half this value, since the client can only open streams with open StreamID
+const MaxNewStreamIDDelta = 4 * MaxStreamsPerConnection
+
+// MaxSessionUnprocessedPackets is the max number of packets stored in each session that are not yet processed.
+const MaxSessionUnprocessedPackets = DefaultMaxCongestionWindow
+
+// SkipPacketAveragePeriodLength is the average period length in which one packet number is skipped to prevent an Optimistic ACK attack
+const SkipPacketAveragePeriodLength PacketNumber = 500
+
+// MaxTrackedSkippedPackets is the maximum number of skipped packet numbers the SentPacketHandler keep track of for Optimistic ACK attack mitigation
+const MaxTrackedSkippedPackets = 10
+
+// STKExpiryTime is the valid time of a source address token
+const STKExpiryTime = 24 * time.Hour
+
+// MaxTrackedSentPackets is maximum number of sent packets saved for either later retransmission or entropy calculation
+const MaxTrackedSentPackets = 2 * DefaultMaxCongestionWindow
+
+// MaxTrackedReceivedPackets is the maximum number of received packets saved for doing the entropy calculations
+const MaxTrackedReceivedPackets = 2 * DefaultMaxCongestionWindow
+
+// MaxTrackedReceivedAckRanges is the maximum number of ACK ranges tracked
+const MaxTrackedReceivedAckRanges = DefaultMaxCongestionWindow
+
+// MaxPacketsReceivedBeforeAckSend is the number of packets that can be received before an ACK frame is sent
+const MaxPacketsReceivedBeforeAckSend = 20
+
+// RetransmittablePacketsBeforeAck is the number of retransmittable that an ACK is sent for
+const RetransmittablePacketsBeforeAck = 2
+
+// MaxStreamFrameSorterGaps is the maximum number of gaps between received StreamFrames
+// prevents DoS attacks against the streamFrameSorter
+const MaxStreamFrameSorterGaps = 1000
+
+// CryptoMaxParams is the upper limit for the number of parameters in a crypto message.
+// Value taken from Chrome.
+const CryptoMaxParams = 128
+
+// CryptoParameterMaxLength is the upper limit for the length of a parameter in a crypto message.
+const CryptoParameterMaxLength = 4000
+
+// EphermalKeyLifetime is the lifetime of the ephermal key during the handshake, see handshake.getEphermalKEX.
+const EphermalKeyLifetime = time.Minute
+
+// InitialIdleTimeout is the timeout before the handshake succeeds.
+const InitialIdleTimeout = 5 * time.Second
+
+// DefaultIdleTimeout is the default idle timeout, for the server
+const DefaultIdleTimeout = 30 * time.Second
+
+// MaxIdleTimeoutServer is the maximum idle timeout that can be negotiated, for the server
+const MaxIdleTimeoutServer = 1 * time.Minute
+
+// MaxIdleTimeoutClient is the idle timeout that the client suggests to the server
+const MaxIdleTimeoutClient = 2 * time.Minute
+
+// DefaultHandshakeTimeout is the default timeout for a connection until the crypto handshake succeeds.
+const DefaultHandshakeTimeout = 10 * time.Second
+
+// ClosedSessionDeleteTimeout the server ignores packets arriving on a connection that is already closed
+// after this time all information about the old connection will be deleted
+const ClosedSessionDeleteTimeout = time.Minute
+
+// NumCachedCertificates is the number of cached compressed certificate chains, each taking ~1K space
+const NumCachedCertificates = 128
diff --git a/vendor/github.com/lucas-clemente/quic-go/protocol/version.go b/vendor/github.com/lucas-clemente/quic-go/protocol/version.go
new file mode 100644
index 0000000..388162e
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/protocol/version.go
@@ -0,0 +1,55 @@
+package protocol
+
+// VersionNumber is a version number as int
+type VersionNumber int
+
+// The version numbers, making grepping easier
+const (
+ Version35 VersionNumber = 35 + iota
+ Version36
+ Version37
+ VersionWhatever VersionNumber = 0 // for when the version doesn't matter
+ VersionUnsupported VersionNumber = -1
+)
+
+// SupportedVersions lists the versions that the server supports
+// must be in sorted descending order
+var SupportedVersions = []VersionNumber{
+ Version37, Version36, Version35,
+}
+
+// VersionNumberToTag maps version numbers ('32') to tags ('Q032')
+func VersionNumberToTag(vn VersionNumber) uint32 {
+ v := uint32(vn)
+ return 'Q' + ((v/100%10)+'0')<<8 + ((v/10%10)+'0')<<16 + ((v%10)+'0')<<24
+}
+
+// VersionTagToNumber is built from VersionNumberToTag in init()
+func VersionTagToNumber(v uint32) VersionNumber {
+ return VersionNumber(((v>>8)&0xff-'0')*100 + ((v>>16)&0xff-'0')*10 + ((v>>24)&0xff - '0'))
+}
+
+// IsSupportedVersion returns true if the server supports this version
+func IsSupportedVersion(supported []VersionNumber, v VersionNumber) bool {
+ for _, t := range supported {
+ if t == v {
+ return true
+ }
+ }
+ return false
+}
+
+// ChooseSupportedVersion finds the best version in the overlap of ours and theirs
+// ours is a slice of versions that we support, sorted by our preference (descending)
+// theirs is a slice of versions offered by the peer. The order does not matter
+// if no suitable version is found, it returns VersionUnsupported
+func ChooseSupportedVersion(ours, theirs []VersionNumber) VersionNumber {
+ for _, ourVer := range ours {
+ for _, theirVer := range theirs {
+ if ourVer == theirVer {
+ return ourVer
+ }
+ }
+ }
+ return VersionUnsupported
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/public_header.go b/vendor/github.com/lucas-clemente/quic-go/public_header.go
new file mode 100644
index 0000000..59ddc6c
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/public_header.go
@@ -0,0 +1,261 @@
+package quic
+
+import (
+ "bytes"
+ "errors"
+
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+ "github.com/lucas-clemente/quic-go/qerr"
+)
+
+var (
+ errPacketNumberLenNotSet = errors.New("PublicHeader: PacketNumberLen not set")
+ errResetAndVersionFlagSet = errors.New("PublicHeader: Reset Flag and Version Flag should not be set at the same time")
+ errReceivedTruncatedConnectionID = qerr.Error(qerr.InvalidPacketHeader, "receiving packets with truncated ConnectionID is not supported")
+ errInvalidConnectionID = qerr.Error(qerr.InvalidPacketHeader, "connection ID cannot be 0")
+ errGetLengthNotForVersionNegotiation = errors.New("PublicHeader: GetLength cannot be called for VersionNegotiation packets")
+)
+
+// The PublicHeader of a QUIC packet. Warning: This struct should not be considered stable and will change soon.
+type PublicHeader struct {
+ Raw []byte
+ ConnectionID protocol.ConnectionID
+ VersionFlag bool
+ ResetFlag bool
+ TruncateConnectionID bool
+ PacketNumberLen protocol.PacketNumberLen
+ PacketNumber protocol.PacketNumber
+ VersionNumber protocol.VersionNumber // VersionNumber sent by the client
+ SupportedVersions []protocol.VersionNumber // VersionNumbers sent by the server
+ DiversificationNonce []byte
+}
+
+// Write writes a public header. Warning: This API should not be considered stable and will change soon.
+func (h *PublicHeader) Write(b *bytes.Buffer, version protocol.VersionNumber, pers protocol.Perspective) error {
+ publicFlagByte := uint8(0x00)
+
+ if h.VersionFlag && h.ResetFlag {
+ return errResetAndVersionFlagSet
+ }
+
+ if h.VersionFlag {
+ publicFlagByte |= 0x01
+ }
+ if h.ResetFlag {
+ publicFlagByte |= 0x02
+ }
+ if !h.TruncateConnectionID {
+ publicFlagByte |= 0x08
+ }
+
+ if len(h.DiversificationNonce) > 0 {
+ if len(h.DiversificationNonce) != 32 {
+ return errors.New("invalid diversification nonce length")
+ }
+ publicFlagByte |= 0x04
+ }
+
+ // only set PacketNumberLen bits if a packet number will be written
+ if h.hasPacketNumber(pers) {
+ switch h.PacketNumberLen {
+ case protocol.PacketNumberLen1:
+ publicFlagByte |= 0x00
+ case protocol.PacketNumberLen2:
+ publicFlagByte |= 0x10
+ case protocol.PacketNumberLen4:
+ publicFlagByte |= 0x20
+ case protocol.PacketNumberLen6:
+ publicFlagByte |= 0x30
+ }
+ }
+
+ b.WriteByte(publicFlagByte)
+
+ if !h.TruncateConnectionID {
+ utils.WriteUint64(b, uint64(h.ConnectionID))
+ }
+
+ if h.VersionFlag && pers == protocol.PerspectiveClient {
+ utils.WriteUint32(b, protocol.VersionNumberToTag(h.VersionNumber))
+ }
+
+ if len(h.DiversificationNonce) > 0 {
+ b.Write(h.DiversificationNonce)
+ }
+
+ // if we're a server, and the VersionFlag is set, we must not include anything else in the packet
+ if !h.hasPacketNumber(pers) {
+ return nil
+ }
+
+ if h.PacketNumberLen != protocol.PacketNumberLen1 && h.PacketNumberLen != protocol.PacketNumberLen2 && h.PacketNumberLen != protocol.PacketNumberLen4 && h.PacketNumberLen != protocol.PacketNumberLen6 {
+ return errPacketNumberLenNotSet
+ }
+
+ switch h.PacketNumberLen {
+ case protocol.PacketNumberLen1:
+ b.WriteByte(uint8(h.PacketNumber))
+ case protocol.PacketNumberLen2:
+ utils.WriteUint16(b, uint16(h.PacketNumber))
+ case protocol.PacketNumberLen4:
+ utils.WriteUint32(b, uint32(h.PacketNumber))
+ case protocol.PacketNumberLen6:
+ utils.WriteUint48(b, uint64(h.PacketNumber))
+ default:
+ return errPacketNumberLenNotSet
+ }
+
+ return nil
+}
+
+// ParsePublicHeader parses a QUIC packet's public header.
+// The packetSentBy is the perspective of the peer that sent this PublicHeader, i.e. if we're the server, packetSentBy should be PerspectiveClient.
+// Warning: This API should not be considered stable and will change soon.
+func ParsePublicHeader(b *bytes.Reader, packetSentBy protocol.Perspective) (*PublicHeader, error) {
+ header := &PublicHeader{}
+
+ // First byte
+ publicFlagByte, err := b.ReadByte()
+ if err != nil {
+ return nil, err
+ }
+ header.VersionFlag = publicFlagByte&0x01 > 0
+ header.ResetFlag = publicFlagByte&0x02 > 0
+
+ // TODO: activate this check once Chrome sends the correct value
+ // see https://github.com/lucas-clemente/quic-go/issues/232
+ // if publicFlagByte&0x04 > 0 {
+ // return nil, errors.New("diversification nonces should only be sent by servers")
+ // }
+
+ header.TruncateConnectionID = publicFlagByte&0x08 == 0
+ if header.TruncateConnectionID && packetSentBy == protocol.PerspectiveClient {
+ return nil, errReceivedTruncatedConnectionID
+ }
+
+ if header.hasPacketNumber(packetSentBy) {
+ switch publicFlagByte & 0x30 {
+ case 0x30:
+ header.PacketNumberLen = protocol.PacketNumberLen6
+ case 0x20:
+ header.PacketNumberLen = protocol.PacketNumberLen4
+ case 0x10:
+ header.PacketNumberLen = protocol.PacketNumberLen2
+ case 0x00:
+ header.PacketNumberLen = protocol.PacketNumberLen1
+ }
+ }
+
+ // Connection ID
+ if !header.TruncateConnectionID {
+ var connID uint64
+ connID, err = utils.ReadUint64(b)
+ if err != nil {
+ return nil, err
+ }
+ header.ConnectionID = protocol.ConnectionID(connID)
+ if header.ConnectionID == 0 {
+ return nil, errInvalidConnectionID
+ }
+ }
+
+ if packetSentBy == protocol.PerspectiveServer && publicFlagByte&0x04 > 0 {
+ // TODO: remove the if once the Google servers send the correct value
+ // assume that a packet doesn't contain a diversification nonce if the version flag or the reset flag is set, no matter what the public flag says
+ // see https://github.com/lucas-clemente/quic-go/issues/232
+ if !header.VersionFlag && !header.ResetFlag {
+ header.DiversificationNonce = make([]byte, 32)
+ // this Read can never return an EOF for a valid packet, since the diversification nonce is followed by the packet number
+ _, err = b.Read(header.DiversificationNonce)
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ // Version (optional)
+ if !header.ResetFlag {
+ if header.VersionFlag {
+ if packetSentBy == protocol.PerspectiveClient {
+ var versionTag uint32
+ versionTag, err = utils.ReadUint32(b)
+ if err != nil {
+ return nil, err
+ }
+ header.VersionNumber = protocol.VersionTagToNumber(versionTag)
+ } else { // parse the version negotiaton packet
+ if b.Len()%4 != 0 {
+ return nil, qerr.InvalidVersionNegotiationPacket
+ }
+ header.SupportedVersions = make([]protocol.VersionNumber, 0)
+ for {
+ var versionTag uint32
+ versionTag, err = utils.ReadUint32(b)
+ if err != nil {
+ break
+ }
+ v := protocol.VersionTagToNumber(versionTag)
+ header.SupportedVersions = append(header.SupportedVersions, v)
+ }
+ }
+ }
+ }
+
+ // Packet number
+ if header.hasPacketNumber(packetSentBy) {
+ packetNumber, err := utils.ReadUintN(b, uint8(header.PacketNumberLen))
+ if err != nil {
+ return nil, err
+ }
+ header.PacketNumber = protocol.PacketNumber(packetNumber)
+ }
+
+ return header, nil
+}
+
+// GetLength gets the length of the publicHeader in bytes.
+// It can only be called for regular packets.
+func (h *PublicHeader) GetLength(pers protocol.Perspective) (protocol.ByteCount, error) {
+ if h.VersionFlag && h.ResetFlag {
+ return 0, errResetAndVersionFlagSet
+ }
+
+ if h.VersionFlag && pers == protocol.PerspectiveServer {
+ return 0, errGetLengthNotForVersionNegotiation
+ }
+
+ length := protocol.ByteCount(1) // 1 byte for public flags
+
+ if h.hasPacketNumber(pers) {
+ if h.PacketNumberLen != protocol.PacketNumberLen1 && h.PacketNumberLen != protocol.PacketNumberLen2 && h.PacketNumberLen != protocol.PacketNumberLen4 && h.PacketNumberLen != protocol.PacketNumberLen6 {
+ return 0, errPacketNumberLenNotSet
+ }
+ length += protocol.ByteCount(h.PacketNumberLen)
+ }
+
+ if !h.TruncateConnectionID {
+ length += 8 // 8 bytes for the connection ID
+ }
+
+ // Version Number in packets sent by the client
+ if h.VersionFlag {
+ length += 4
+ }
+
+ length += protocol.ByteCount(len(h.DiversificationNonce))
+
+ return length, nil
+}
+
+// hasPacketNumber determines if this PublicHeader will contain a packet number
+// this depends on the ResetFlag, the VersionFlag and who sent the packet
+func (h *PublicHeader) hasPacketNumber(packetSentBy protocol.Perspective) bool {
+ if h.ResetFlag {
+ return false
+ }
+ if h.VersionFlag && packetSentBy == protocol.PerspectiveServer {
+ return false
+ }
+ return true
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/public_reset.go b/vendor/github.com/lucas-clemente/quic-go/public_reset.go
new file mode 100644
index 0000000..958db9c
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/public_reset.go
@@ -0,0 +1,62 @@
+package quic
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+
+ "github.com/lucas-clemente/quic-go/handshake"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+)
+
+type publicReset struct {
+ rejectedPacketNumber protocol.PacketNumber
+ nonce uint64
+}
+
+func writePublicReset(connectionID protocol.ConnectionID, rejectedPacketNumber protocol.PacketNumber, nonceProof uint64) []byte {
+ b := &bytes.Buffer{}
+ b.WriteByte(0x0a)
+ utils.WriteUint64(b, uint64(connectionID))
+ utils.WriteUint32(b, uint32(handshake.TagPRST))
+ utils.WriteUint32(b, 2)
+ utils.WriteUint32(b, uint32(handshake.TagRNON))
+ utils.WriteUint32(b, 8)
+ utils.WriteUint32(b, uint32(handshake.TagRSEQ))
+ utils.WriteUint32(b, 16)
+ utils.WriteUint64(b, nonceProof)
+ utils.WriteUint64(b, uint64(rejectedPacketNumber))
+ return b.Bytes()
+}
+
+func parsePublicReset(r *bytes.Reader) (*publicReset, error) {
+ pr := publicReset{}
+ msg, err := handshake.ParseHandshakeMessage(r)
+ if err != nil {
+ return nil, err
+ }
+ if msg.Tag != handshake.TagPRST {
+ return nil, errors.New("wrong public reset tag")
+ }
+
+ rseq, ok := msg.Data[handshake.TagRSEQ]
+ if !ok {
+ return nil, errors.New("RSEQ missing")
+ }
+ if len(rseq) != 8 {
+ return nil, errors.New("invalid RSEQ tag")
+ }
+ pr.rejectedPacketNumber = protocol.PacketNumber(binary.LittleEndian.Uint64(rseq))
+
+ rnon, ok := msg.Data[handshake.TagRNON]
+ if !ok {
+ return nil, errors.New("RNON missing")
+ }
+ if len(rnon) != 8 {
+ return nil, errors.New("invalid RNON tag")
+ }
+ pr.nonce = binary.LittleEndian.Uint64(rnon)
+
+ return &pr, nil
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/qerr/error_codes.go b/vendor/github.com/lucas-clemente/quic-go/qerr/error_codes.go
similarity index 98%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/qerr/error_codes.go
rename to vendor/github.com/lucas-clemente/quic-go/qerr/error_codes.go
index 4797530..f3e6dd9 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/qerr/error_codes.go
+++ b/vendor/github.com/lucas-clemente/quic-go/qerr/error_codes.go
@@ -89,6 +89,9 @@ const (
EmptyStreamFrameNoFin ErrorCode = 50
// We received invalid data on the headers stream.
InvalidHeadersStreamData ErrorCode = 56
+ // Invalid data on the headers stream received because of decompression
+ // failure.
+ HeadersStreamDataDecompressFailure ErrorCode = 97
// The peer received too much data, violating flow control.
FlowControlReceivedTooMuchData ErrorCode = 59
// The peer sent too much data, violating flow control.
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/qerr/errorcode_string.go b/vendor/github.com/lucas-clemente/quic-go/qerr/errorcode_string.go
similarity index 95%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/qerr/errorcode_string.go
rename to vendor/github.com/lucas-clemente/quic-go/qerr/errorcode_string.go
index aadd657..5a8e024 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/qerr/errorcode_string.go
+++ b/vendor/github.com/lucas-clemente/quic-go/qerr/errorcode_string.go
@@ -10,6 +10,7 @@ const (
_ErrorCode_name_2 = "InvalidHeaderIDInvalidNegotiatedValueDecompressionFailureNetworkIdleTimeoutErrorMigratingAddressPacketWriteErrorHandshakeFailedCryptoTagsOutOfOrderCryptoTooManyEntriesCryptoInvalidValueLengthCryptoMessageAfterHandshakeCompleteInvalidCryptoMessageTypeInvalidCryptoMessageParameterCryptoMessageParameterNotFoundCryptoMessageParameterNoOverlapCryptoMessageIndexNotFoundCryptoInternalErrorCryptoVersionNotSupportedCryptoNoSupportCryptoTooManyRejectsProofInvalidCryptoDuplicateTagCryptoEncryptionLevelIncorrectCryptoServerConfigExpiredInvalidStreamData"
_ErrorCode_name_3 = "MissingPayloadInvalidPriorityEmptyStreamFrameNoFinPacketReadErrorInvalidChannelIDSignatureCryptoSymmetricKeySetupFailedCryptoMessageWhileValidatingClientHelloVersionNegotiationMismatchInvalidHeadersStreamDataInvalidWindowUpdateDataInvalidBlockedDataFlowControlReceivedTooMuchDataInvalidStopWaitingDataUnencryptedStreamDataConnectionIPPooledFlowControlSentTooMuchDataFlowControlInvalidWindowCryptoUpdateBeforeHandshakeComplete"
_ErrorCode_name_4 = "HandshakeTimeoutTooManyOutstandingSentPacketsTooManyOutstandingReceivedPacketsConnectionCancelledBadPacketLossRateCryptoHandshakeStatelessRejectPublicResetsPostHandshakeTimeoutsWithOpenStreamsFailedToSerializePacketTooManyAvailableStreamsUnencryptedFecDataInvalidPathCloseDataBadMultipathFlagIPAddressChangedConnectionMigrationNoMigratableStreamsConnectionMigrationTooManyChangesConnectionMigrationNoNewNetworkConnectionMigrationNonMigratableStreamTooManyRtosErrorMigratingPortOverlappingStreamDataAttemptToSendUnencryptedStreamData"
+ _ErrorCode_name_5 = "HeadersStreamDataDecompressFailure"
)
var (
@@ -18,12 +19,13 @@ var (
_ErrorCode_index_2 = [...]uint16{0, 15, 37, 57, 75, 96, 112, 127, 147, 167, 191, 226, 250, 279, 309, 340, 366, 385, 410, 425, 445, 457, 475, 505, 530, 547}
_ErrorCode_index_3 = [...]uint16{0, 14, 29, 50, 65, 90, 119, 158, 184, 208, 231, 249, 279, 301, 322, 340, 366, 390, 425}
_ErrorCode_index_4 = [...]uint16{0, 16, 45, 78, 97, 114, 144, 169, 192, 215, 238, 256, 276, 292, 308, 346, 379, 410, 448, 459, 477, 498, 532}
+ _ErrorCode_index_5 = [...]uint8{0, 34}
)
func (i ErrorCode) String() string {
switch {
case 1 <= i && i <= 14:
- i--
+ i -= 1
return _ErrorCode_name_0[_ErrorCode_index_0[i]:_ErrorCode_index_0[i+1]]
case 16 <= i && i <= 20:
i -= 16
@@ -37,6 +39,8 @@ func (i ErrorCode) String() string {
case 67 <= i && i <= 88:
i -= 67
return _ErrorCode_name_4[_ErrorCode_index_4[i]:_ErrorCode_index_4[i+1]]
+ case i == 97:
+ return _ErrorCode_name_5
default:
return fmt.Sprintf("ErrorCode(%d)", i)
}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go b/vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go
similarity index 81%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go
rename to vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go
index 6259476..9e1956f 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go
+++ b/vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go
@@ -3,7 +3,7 @@ package qerr
import (
"fmt"
- "github.com/lucas-clemente/quic-go/utils"
+ "github.com/lucas-clemente/quic-go/internal/utils"
)
// ErrorCode can be used as a normal error without reason.
@@ -31,6 +31,16 @@ func (e *QuicError) Error() string {
return fmt.Sprintf("%s: %s", e.ErrorCode.String(), e.ErrorMessage)
}
+func (e *QuicError) Timeout() bool {
+ switch e.ErrorCode {
+ case NetworkIdleTimeout,
+ HandshakeTimeout,
+ TimeoutsWithOpenStreams:
+ return true
+ }
+ return false
+}
+
// ToQuicError converts an arbitrary error to a QuicError. It leaves QuicErrors
// unchanged, and properly handles `ErrorCode`s.
func ToQuicError(err error) *QuicError {
diff --git a/vendor/github.com/lucas-clemente/quic-go/server.go b/vendor/github.com/lucas-clemente/quic-go/server.go
new file mode 100644
index 0000000..76f07ba
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/server.go
@@ -0,0 +1,338 @@
+package quic
+
+import (
+ "bytes"
+ "crypto/tls"
+ "errors"
+ "net"
+ "sync"
+ "time"
+
+ "github.com/lucas-clemente/quic-go/crypto"
+ "github.com/lucas-clemente/quic-go/handshake"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+ "github.com/lucas-clemente/quic-go/qerr"
+)
+
+// packetHandler handles packets
+type packetHandler interface {
+ Session
+ handlePacket(*receivedPacket)
+ run() error
+ closeRemote(error)
+}
+
+// A Listener of QUIC
+type server struct {
+ tlsConf *tls.Config
+ config *Config
+
+ conn net.PacketConn
+
+ certChain crypto.CertChain
+ scfg *handshake.ServerConfig
+
+ sessions map[protocol.ConnectionID]packetHandler
+ sessionsMutex sync.RWMutex
+ deleteClosedSessionsAfter time.Duration
+
+ serverError error
+ sessionQueue chan Session
+ errorChan chan struct{}
+
+ newSession func(conn connection, v protocol.VersionNumber, connectionID protocol.ConnectionID, sCfg *handshake.ServerConfig, tlsConf *tls.Config, config *Config) (packetHandler, <-chan handshakeEvent, error)
+}
+
+var _ Listener = &server{}
+
+// ListenAddr creates a QUIC server listening on a given address.
+// The listener is not active until Serve() is called.
+// The tls.Config must not be nil, the quic.Config may be nil.
+func ListenAddr(addr string, tlsConf *tls.Config, config *Config) (Listener, error) {
+ udpAddr, err := net.ResolveUDPAddr("udp", addr)
+ if err != nil {
+ return nil, err
+ }
+ conn, err := net.ListenUDP("udp", udpAddr)
+ if err != nil {
+ return nil, err
+ }
+ return Listen(conn, tlsConf, config)
+}
+
+// Listen listens for QUIC connections on a given net.PacketConn.
+// The listener is not active until Serve() is called.
+// The tls.Config must not be nil, the quic.Config may be nil.
+func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener, error) {
+ certChain := crypto.NewCertChain(tlsConf)
+ kex, err := crypto.NewCurve25519KEX()
+ if err != nil {
+ return nil, err
+ }
+ scfg, err := handshake.NewServerConfig(kex, certChain)
+ if err != nil {
+ return nil, err
+ }
+
+ s := &server{
+ conn: conn,
+ tlsConf: tlsConf,
+ config: populateServerConfig(config),
+ certChain: certChain,
+ scfg: scfg,
+ sessions: map[protocol.ConnectionID]packetHandler{},
+ newSession: newSession,
+ deleteClosedSessionsAfter: protocol.ClosedSessionDeleteTimeout,
+ sessionQueue: make(chan Session, 5),
+ errorChan: make(chan struct{}),
+ }
+ go s.serve()
+ return s, nil
+}
+
+var defaultAcceptSTK = func(clientAddr net.Addr, stk *STK) bool {
+ if stk == nil {
+ return false
+ }
+ if time.Now().After(stk.sentTime.Add(protocol.STKExpiryTime)) {
+ return false
+ }
+ var sourceAddr string
+ if udpAddr, ok := clientAddr.(*net.UDPAddr); ok {
+ sourceAddr = udpAddr.IP.String()
+ } else {
+ sourceAddr = clientAddr.String()
+ }
+ return sourceAddr == stk.remoteAddr
+}
+
+// populateServerConfig populates fields in the quic.Config with their default values, if none are set
+// it may be called with nil
+func populateServerConfig(config *Config) *Config {
+ if config == nil {
+ config = &Config{}
+ }
+ versions := config.Versions
+ if len(versions) == 0 {
+ versions = protocol.SupportedVersions
+ }
+
+ vsa := defaultAcceptSTK
+ if config.AcceptSTK != nil {
+ vsa = config.AcceptSTK
+ }
+
+ handshakeTimeout := protocol.DefaultHandshakeTimeout
+ if config.HandshakeTimeout != 0 {
+ handshakeTimeout = config.HandshakeTimeout
+ }
+
+ maxReceiveStreamFlowControlWindow := config.MaxReceiveStreamFlowControlWindow
+ if maxReceiveStreamFlowControlWindow == 0 {
+ maxReceiveStreamFlowControlWindow = protocol.DefaultMaxReceiveStreamFlowControlWindowServer
+ }
+ maxReceiveConnectionFlowControlWindow := config.MaxReceiveConnectionFlowControlWindow
+ if maxReceiveConnectionFlowControlWindow == 0 {
+ maxReceiveConnectionFlowControlWindow = protocol.DefaultMaxReceiveConnectionFlowControlWindowServer
+ }
+
+ return &Config{
+ Versions: versions,
+ HandshakeTimeout: handshakeTimeout,
+ AcceptSTK: vsa,
+ MaxReceiveStreamFlowControlWindow: maxReceiveStreamFlowControlWindow,
+ MaxReceiveConnectionFlowControlWindow: maxReceiveConnectionFlowControlWindow,
+ }
+}
+
+// serve listens on an existing PacketConn
+func (s *server) serve() {
+ for {
+ data := getPacketBuffer()
+ data = data[:protocol.MaxReceivePacketSize]
+ // The packet size should not exceed protocol.MaxReceivePacketSize bytes
+ // If it does, we only read a truncated packet, which will then end up undecryptable
+ n, remoteAddr, err := s.conn.ReadFrom(data)
+ if err != nil {
+ s.serverError = err
+ close(s.errorChan)
+ _ = s.Close()
+ return
+ }
+ data = data[:n]
+ if err := s.handlePacket(s.conn, remoteAddr, data); err != nil {
+ utils.Errorf("error handling packet: %s", err.Error())
+ }
+ }
+}
+
+// Accept returns newly openend sessions
+func (s *server) Accept() (Session, error) {
+ var sess Session
+ select {
+ case sess = <-s.sessionQueue:
+ return sess, nil
+ case <-s.errorChan:
+ return nil, s.serverError
+ }
+}
+
+// Close the server
+func (s *server) Close() error {
+ s.sessionsMutex.Lock()
+ for _, session := range s.sessions {
+ if session != nil {
+ s.sessionsMutex.Unlock()
+ _ = session.Close(nil)
+ s.sessionsMutex.Lock()
+ }
+ }
+ s.sessionsMutex.Unlock()
+
+ if s.conn == nil {
+ return nil
+ }
+ return s.conn.Close()
+}
+
+// Addr returns the server's network address
+func (s *server) Addr() net.Addr {
+ return s.conn.LocalAddr()
+}
+
+func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet []byte) error {
+ rcvTime := time.Now()
+
+ r := bytes.NewReader(packet)
+ hdr, err := ParsePublicHeader(r, protocol.PerspectiveClient)
+ if err != nil {
+ return qerr.Error(qerr.InvalidPacketHeader, err.Error())
+ }
+ hdr.Raw = packet[:len(packet)-r.Len()]
+
+ s.sessionsMutex.RLock()
+ session, ok := s.sessions[hdr.ConnectionID]
+ s.sessionsMutex.RUnlock()
+
+ // ignore all Public Reset packets
+ if hdr.ResetFlag {
+ if ok {
+ var pr *publicReset
+ pr, err = parsePublicReset(r)
+ if err != nil {
+ utils.Infof("Received a Public Reset for connection %x. An error occurred parsing the packet.")
+ } else {
+ utils.Infof("Received a Public Reset for connection %x, rejected packet number: 0x%x.", hdr.ConnectionID, pr.rejectedPacketNumber)
+ }
+ } else {
+ utils.Infof("Received Public Reset for unknown connection %x.", hdr.ConnectionID)
+ }
+ return nil
+ }
+
+ // a session is only created once the client sent a supported version
+ // if we receive a packet for a connection that already has session, it's probably an old packet that was sent by the client before the version was negotiated
+ // it is safe to drop it
+ if ok && hdr.VersionFlag && !protocol.IsSupportedVersion(s.config.Versions, hdr.VersionNumber) {
+ return nil
+ }
+
+ // Send Version Negotiation Packet if the client is speaking a different protocol version
+ if hdr.VersionFlag && !protocol.IsSupportedVersion(s.config.Versions, hdr.VersionNumber) {
+ // drop packets that are too small to be valid first packets
+ if len(packet) < protocol.ClientHelloMinimumSize+len(hdr.Raw) {
+ return errors.New("dropping small packet with unknown version")
+ }
+ utils.Infof("Client offered version %d, sending VersionNegotiationPacket", hdr.VersionNumber)
+ _, err = pconn.WriteTo(composeVersionNegotiation(hdr.ConnectionID, s.config.Versions), remoteAddr)
+ return err
+ }
+
+ if !ok {
+ if !hdr.VersionFlag {
+ _, err = pconn.WriteTo(writePublicReset(hdr.ConnectionID, hdr.PacketNumber, 0), remoteAddr)
+ return err
+ }
+ version := hdr.VersionNumber
+ if !protocol.IsSupportedVersion(s.config.Versions, version) {
+ return errors.New("Server BUG: negotiated version not supported")
+ }
+
+ utils.Infof("Serving new connection: %x, version %d from %v", hdr.ConnectionID, version, remoteAddr)
+ var handshakeChan <-chan handshakeEvent
+ session, handshakeChan, err = s.newSession(
+ &conn{pconn: pconn, currentAddr: remoteAddr},
+ version,
+ hdr.ConnectionID,
+ s.scfg,
+ s.tlsConf,
+ s.config,
+ )
+ if err != nil {
+ return err
+ }
+ s.sessionsMutex.Lock()
+ s.sessions[hdr.ConnectionID] = session
+ s.sessionsMutex.Unlock()
+
+ go func() {
+ // session.run() returns as soon as the session is closed
+ _ = session.run()
+ s.removeConnection(hdr.ConnectionID)
+ }()
+
+ go func() {
+ for {
+ ev := <-handshakeChan
+ if ev.err != nil {
+ return
+ }
+ if ev.encLevel == protocol.EncryptionForwardSecure {
+ break
+ }
+ }
+ s.sessionQueue <- session
+ }()
+ }
+ if session == nil {
+ // Late packet for closed session
+ return nil
+ }
+ session.handlePacket(&receivedPacket{
+ remoteAddr: remoteAddr,
+ publicHeader: hdr,
+ data: packet[len(packet)-r.Len():],
+ rcvTime: rcvTime,
+ })
+ return nil
+}
+
+func (s *server) removeConnection(id protocol.ConnectionID) {
+ s.sessionsMutex.Lock()
+ s.sessions[id] = nil
+ s.sessionsMutex.Unlock()
+
+ time.AfterFunc(s.deleteClosedSessionsAfter, func() {
+ s.sessionsMutex.Lock()
+ delete(s.sessions, id)
+ s.sessionsMutex.Unlock()
+ })
+}
+
+func composeVersionNegotiation(connectionID protocol.ConnectionID, versions []protocol.VersionNumber) []byte {
+ fullReply := &bytes.Buffer{}
+ responsePublicHeader := PublicHeader{
+ ConnectionID: connectionID,
+ PacketNumber: 1,
+ VersionFlag: true,
+ }
+ err := responsePublicHeader.Write(fullReply, protocol.VersionWhatever, protocol.PerspectiveServer)
+ if err != nil {
+ utils.Errorf("error composing version negotiation packet: %s", err.Error())
+ }
+ for _, v := range versions {
+ utils.WriteUint32(fullReply, protocol.VersionNumberToTag(v))
+ }
+ return fullReply.Bytes()
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/session.go b/vendor/github.com/lucas-clemente/quic-go/session.go
new file mode 100644
index 0000000..376aa7f
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/session.go
@@ -0,0 +1,838 @@
+package quic
+
+import (
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "net"
+ "sync"
+ "time"
+
+ "github.com/lucas-clemente/quic-go/ackhandler"
+ "github.com/lucas-clemente/quic-go/congestion"
+ "github.com/lucas-clemente/quic-go/flowcontrol"
+ "github.com/lucas-clemente/quic-go/frames"
+ "github.com/lucas-clemente/quic-go/handshake"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+ "github.com/lucas-clemente/quic-go/qerr"
+)
+
+type unpacker interface {
+ Unpack(publicHeaderBinary []byte, hdr *PublicHeader, data []byte) (*unpackedPacket, error)
+}
+
+type receivedPacket struct {
+ remoteAddr net.Addr
+ publicHeader *PublicHeader
+ data []byte
+ rcvTime time.Time
+}
+
+var (
+ errRstStreamOnInvalidStream = errors.New("RST_STREAM received for unknown stream")
+ errWindowUpdateOnClosedStream = errors.New("WINDOW_UPDATE received for an already closed stream")
+)
+
+var (
+ newCryptoSetup = handshake.NewCryptoSetup
+ newCryptoSetupClient = handshake.NewCryptoSetupClient
+)
+
+type handshakeEvent struct {
+ encLevel protocol.EncryptionLevel
+ err error
+}
+
+type closeError struct {
+ err error
+ remote bool
+}
+
+// A Session is a QUIC session
+type session struct {
+ connectionID protocol.ConnectionID
+ perspective protocol.Perspective
+ version protocol.VersionNumber
+ tlsConf *tls.Config
+ config *Config
+
+ conn connection
+
+ streamsMap *streamsMap
+
+ rttStats *congestion.RTTStats
+
+ sentPacketHandler ackhandler.SentPacketHandler
+ receivedPacketHandler ackhandler.ReceivedPacketHandler
+ streamFramer *streamFramer
+
+ flowControlManager flowcontrol.FlowControlManager
+
+ unpacker unpacker
+ packer *packetPacker
+
+ cryptoSetup handshake.CryptoSetup
+
+ receivedPackets chan *receivedPacket
+ sendingScheduled chan struct{}
+ // closeChan is used to notify the run loop that it should terminate.
+ closeChan chan closeError
+ // runClosed is closed once the run loop exits
+ // it is used to block Close() and WaitUntilClosed()
+ runClosed chan struct{}
+ closeOnce sync.Once
+
+ // when we receive too many undecryptable packets during the handshake, we send a Public reset
+ // but only after a time of protocol.PublicResetTimeout has passed
+ undecryptablePackets []*receivedPacket
+ receivedTooManyUndecrytablePacketsTime time.Time
+
+ // this channel is passed to the CryptoSetup and receives the current encryption level
+ // it is closed as soon as the handshake is complete
+ aeadChanged <-chan protocol.EncryptionLevel
+ handshakeComplete bool
+ // will be closed as soon as the handshake completes, and receive any error that might occur until then
+ // it is used to block WaitUntilHandshakeComplete()
+ handshakeCompleteChan chan error
+ // handshakeChan receives handshake events and is closed as soon the handshake completes
+ // the receiving end of this channel is passed to the creator of the session
+ // it receives at most 3 handshake events: 2 when the encryption level changes, and one error
+ handshakeChan chan<- handshakeEvent
+
+ connectionParameters handshake.ConnectionParametersManager
+
+ lastRcvdPacketNumber protocol.PacketNumber
+ // Used to calculate the next packet number from the truncated wire
+ // representation, and sent back in public reset packets
+ largestRcvdPacketNumber protocol.PacketNumber
+
+ sessionCreationTime time.Time
+ lastNetworkActivityTime time.Time
+
+ timer *utils.Timer
+ // keepAlivePingSent stores whether a Ping frame was sent to the peer or not
+ // it is reset as soon as we receive a packet from the peer
+ keepAlivePingSent bool
+}
+
+var _ Session = &session{}
+
+// newSession makes a new session
+func newSession(
+ conn connection,
+ v protocol.VersionNumber,
+ connectionID protocol.ConnectionID,
+ sCfg *handshake.ServerConfig,
+ tlsConf *tls.Config,
+ config *Config,
+) (packetHandler, <-chan handshakeEvent, error) {
+ s := &session{
+ conn: conn,
+ connectionID: connectionID,
+ perspective: protocol.PerspectiveServer,
+ version: v,
+ config: config,
+ }
+ return s.setup(sCfg, "", nil)
+}
+
+// declare this as a variable, such that we can it mock it in the tests
+var newClientSession = func(
+ conn connection,
+ hostname string,
+ v protocol.VersionNumber,
+ connectionID protocol.ConnectionID,
+ tlsConf *tls.Config,
+ config *Config,
+ negotiatedVersions []protocol.VersionNumber,
+) (packetHandler, <-chan handshakeEvent, error) {
+ s := &session{
+ conn: conn,
+ connectionID: connectionID,
+ perspective: protocol.PerspectiveClient,
+ version: v,
+ tlsConf: tlsConf,
+ config: config,
+ }
+ return s.setup(nil, hostname, negotiatedVersions)
+}
+
+func (s *session) setup(
+ scfg *handshake.ServerConfig,
+ hostname string,
+ negotiatedVersions []protocol.VersionNumber,
+) (packetHandler, <-chan handshakeEvent, error) {
+ aeadChanged := make(chan protocol.EncryptionLevel, 2)
+ s.aeadChanged = aeadChanged
+ handshakeChan := make(chan handshakeEvent, 3)
+ s.handshakeChan = handshakeChan
+ s.runClosed = make(chan struct{})
+ s.handshakeCompleteChan = make(chan error, 1)
+ s.receivedPackets = make(chan *receivedPacket, protocol.MaxSessionUnprocessedPackets)
+ s.closeChan = make(chan closeError, 1)
+ s.sendingScheduled = make(chan struct{}, 1)
+ s.undecryptablePackets = make([]*receivedPacket, 0, protocol.MaxUndecryptablePackets)
+
+ s.timer = utils.NewTimer()
+ now := time.Now()
+ s.lastNetworkActivityTime = now
+ s.sessionCreationTime = now
+
+ s.rttStats = &congestion.RTTStats{}
+ s.connectionParameters = handshake.NewConnectionParamatersManager(s.perspective, s.version,
+ s.config.MaxReceiveStreamFlowControlWindow, s.config.MaxReceiveConnectionFlowControlWindow)
+ s.sentPacketHandler = ackhandler.NewSentPacketHandler(s.rttStats)
+ s.flowControlManager = flowcontrol.NewFlowControlManager(s.connectionParameters, s.rttStats)
+ s.receivedPacketHandler = ackhandler.NewReceivedPacketHandler()
+ s.streamsMap = newStreamsMap(s.newStream, s.perspective, s.connectionParameters)
+ s.streamFramer = newStreamFramer(s.streamsMap, s.flowControlManager)
+
+ var err error
+ if s.perspective == protocol.PerspectiveServer {
+ cryptoStream, _ := s.GetOrOpenStream(1)
+ _, _ = s.AcceptStream() // don't expose the crypto stream
+ verifySourceAddr := func(clientAddr net.Addr, hstk *handshake.STK) bool {
+ var stk *STK
+ if hstk != nil {
+ stk = &STK{remoteAddr: hstk.RemoteAddr, sentTime: hstk.SentTime}
+ }
+ return s.config.AcceptSTK(clientAddr, stk)
+ }
+ s.cryptoSetup, err = newCryptoSetup(
+ s.connectionID,
+ s.conn.RemoteAddr(),
+ s.version,
+ scfg,
+ cryptoStream,
+ s.connectionParameters,
+ s.config.Versions,
+ verifySourceAddr,
+ aeadChanged,
+ )
+ } else {
+ cryptoStream, _ := s.OpenStream()
+ s.cryptoSetup, err = newCryptoSetupClient(
+ hostname,
+ s.connectionID,
+ s.version,
+ cryptoStream,
+ s.tlsConf,
+ s.connectionParameters,
+ aeadChanged,
+ &handshake.TransportParameters{RequestConnectionIDTruncation: s.config.RequestConnectionIDTruncation},
+ negotiatedVersions,
+ )
+ }
+ if err != nil {
+ return nil, nil, err
+ }
+
+ s.packer = newPacketPacker(s.connectionID,
+ s.cryptoSetup,
+ s.connectionParameters,
+ s.streamFramer,
+ s.perspective,
+ s.version,
+ )
+ s.unpacker = &packetUnpacker{aead: s.cryptoSetup, version: s.version}
+
+ return s, handshakeChan, nil
+}
+
+// run the session main loop
+func (s *session) run() error {
+ // Start the crypto stream handler
+ go func() {
+ if err := s.cryptoSetup.HandleCryptoStream(); err != nil {
+ s.Close(err)
+ }
+ }()
+
+ var closeErr closeError
+ aeadChanged := s.aeadChanged
+
+runLoop:
+ for {
+ // Close immediately if requested
+ select {
+ case closeErr = <-s.closeChan:
+ break runLoop
+ default:
+ }
+
+ s.maybeResetTimer()
+
+ select {
+ case closeErr = <-s.closeChan:
+ break runLoop
+ case <-s.timer.Chan():
+ s.timer.SetRead()
+ // We do all the interesting stuff after the switch statement, so
+ // nothing to see here.
+ case <-s.sendingScheduled:
+ // We do all the interesting stuff after the switch statement, so
+ // nothing to see here.
+ case p := <-s.receivedPackets:
+ err := s.handlePacketImpl(p)
+ if err != nil {
+ if qErr, ok := err.(*qerr.QuicError); ok && qErr.ErrorCode == qerr.DecryptionFailure {
+ s.tryQueueingUndecryptablePacket(p)
+ continue
+ }
+ s.closeLocal(err)
+ continue
+ }
+ // This is a bit unclean, but works properly, since the packet always
+ // begins with the public header and we never copy it.
+ putPacketBuffer(p.publicHeader.Raw)
+ case l, ok := <-aeadChanged:
+ if !ok { // the aeadChanged chan was closed. This means that the handshake is completed.
+ s.handshakeComplete = true
+ aeadChanged = nil // prevent this case from ever being selected again
+ close(s.handshakeChan)
+ close(s.handshakeCompleteChan)
+ } else {
+ s.tryDecryptingQueuedPackets()
+ s.handshakeChan <- handshakeEvent{encLevel: l}
+ }
+ }
+
+ now := time.Now()
+ if timeout := s.sentPacketHandler.GetAlarmTimeout(); !timeout.IsZero() && timeout.Before(now) {
+ // This could cause packets to be retransmitted, so check it before trying
+ // to send packets.
+ s.sentPacketHandler.OnAlarm()
+ }
+
+ if s.config.KeepAlive && s.handshakeComplete && time.Since(s.lastNetworkActivityTime) >= s.idleTimeout()/2 {
+ // send the PING frame since there is no activity in the session
+ s.packer.QueueControlFrame(&frames.PingFrame{})
+ s.keepAlivePingSent = true
+ }
+
+ if err := s.sendPacket(); err != nil {
+ s.closeLocal(err)
+ }
+ if !s.receivedTooManyUndecrytablePacketsTime.IsZero() && s.receivedTooManyUndecrytablePacketsTime.Add(protocol.PublicResetTimeout).Before(now) && len(s.undecryptablePackets) != 0 {
+ s.closeLocal(qerr.Error(qerr.DecryptionFailure, "too many undecryptable packets received"))
+ }
+ if now.Sub(s.lastNetworkActivityTime) >= s.idleTimeout() {
+ s.closeLocal(qerr.Error(qerr.NetworkIdleTimeout, "No recent network activity."))
+ }
+ if !s.handshakeComplete && now.Sub(s.sessionCreationTime) >= s.config.HandshakeTimeout {
+ s.closeLocal(qerr.Error(qerr.HandshakeTimeout, "Crypto handshake did not complete in time."))
+ }
+ s.garbageCollectStreams()
+ }
+
+ // only send the error the handshakeChan when the handshake is not completed yet
+ // otherwise this chan will already be closed
+ if !s.handshakeComplete {
+ s.handshakeCompleteChan <- closeErr.err
+ s.handshakeChan <- handshakeEvent{err: closeErr.err}
+ }
+ s.handleCloseError(closeErr)
+ close(s.runClosed)
+ return closeErr.err
+}
+
+func (s *session) WaitUntilClosed() {
+ <-s.runClosed
+}
+
+func (s *session) maybeResetTimer() {
+ var deadline time.Time
+ if s.config.KeepAlive && s.handshakeComplete && !s.keepAlivePingSent {
+ deadline = s.lastNetworkActivityTime.Add(s.idleTimeout() / 2)
+ } else {
+ deadline = s.lastNetworkActivityTime.Add(s.idleTimeout())
+ }
+
+ if ackAlarm := s.receivedPacketHandler.GetAlarmTimeout(); !ackAlarm.IsZero() {
+ deadline = utils.MinTime(deadline, ackAlarm)
+ }
+ if lossTime := s.sentPacketHandler.GetAlarmTimeout(); !lossTime.IsZero() {
+ deadline = utils.MinTime(deadline, lossTime)
+ }
+ if !s.handshakeComplete {
+ handshakeDeadline := s.sessionCreationTime.Add(s.config.HandshakeTimeout)
+ deadline = utils.MinTime(deadline, handshakeDeadline)
+ }
+ if !s.receivedTooManyUndecrytablePacketsTime.IsZero() {
+ deadline = utils.MinTime(deadline, s.receivedTooManyUndecrytablePacketsTime.Add(protocol.PublicResetTimeout))
+ }
+
+ s.timer.Reset(deadline)
+}
+
+func (s *session) idleTimeout() time.Duration {
+ if s.handshakeComplete {
+ return s.connectionParameters.GetIdleConnectionStateLifetime()
+ }
+ return protocol.InitialIdleTimeout
+}
+
+func (s *session) handlePacketImpl(p *receivedPacket) error {
+ if s.perspective == protocol.PerspectiveClient {
+ diversificationNonce := p.publicHeader.DiversificationNonce
+ if len(diversificationNonce) > 0 {
+ s.cryptoSetup.SetDiversificationNonce(diversificationNonce)
+ }
+ }
+
+ if p.rcvTime.IsZero() {
+ // To simplify testing
+ p.rcvTime = time.Now()
+ }
+
+ s.lastNetworkActivityTime = p.rcvTime
+ s.keepAlivePingSent = false
+ hdr := p.publicHeader
+ data := p.data
+
+ // Calculate packet number
+ hdr.PacketNumber = protocol.InferPacketNumber(
+ hdr.PacketNumberLen,
+ s.largestRcvdPacketNumber,
+ hdr.PacketNumber,
+ )
+
+ packet, err := s.unpacker.Unpack(hdr.Raw, hdr, data)
+ if utils.Debug() {
+ if err != nil {
+ utils.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID)
+ } else {
+ utils.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x, %s", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID, packet.encryptionLevel)
+ }
+ }
+ // if the decryption failed, this might be a packet sent by an attacker
+ // don't update the remote address
+ if quicErr, ok := err.(*qerr.QuicError); ok && quicErr.ErrorCode == qerr.DecryptionFailure {
+ return err
+ }
+ if s.perspective == protocol.PerspectiveServer {
+ // update the remote address, even if unpacking failed for any other reason than a decryption error
+ s.conn.SetCurrentRemoteAddr(p.remoteAddr)
+ }
+ if err != nil {
+ return err
+ }
+
+ s.lastRcvdPacketNumber = hdr.PacketNumber
+ // Only do this after decrypting, so we are sure the packet is not attacker-controlled
+ s.largestRcvdPacketNumber = utils.MaxPacketNumber(s.largestRcvdPacketNumber, hdr.PacketNumber)
+
+ isRetransmittable := ackhandler.HasRetransmittableFrames(packet.frames)
+ if err = s.receivedPacketHandler.ReceivedPacket(hdr.PacketNumber, isRetransmittable); err != nil {
+ return err
+ }
+
+ return s.handleFrames(packet.frames)
+}
+
+func (s *session) handleFrames(fs []frames.Frame) error {
+ for _, ff := range fs {
+ var err error
+ frames.LogFrame(ff, false)
+ switch frame := ff.(type) {
+ case *frames.StreamFrame:
+ err = s.handleStreamFrame(frame)
+ case *frames.AckFrame:
+ err = s.handleAckFrame(frame)
+ case *frames.ConnectionCloseFrame:
+ s.closeRemote(qerr.Error(frame.ErrorCode, frame.ReasonPhrase))
+ case *frames.GoawayFrame:
+ err = errors.New("unimplemented: handling GOAWAY frames")
+ case *frames.StopWaitingFrame:
+ err = s.receivedPacketHandler.ReceivedStopWaiting(frame)
+ case *frames.RstStreamFrame:
+ err = s.handleRstStreamFrame(frame)
+ case *frames.WindowUpdateFrame:
+ err = s.handleWindowUpdateFrame(frame)
+ case *frames.BlockedFrame:
+ case *frames.PingFrame:
+ default:
+ return errors.New("Session BUG: unexpected frame type")
+ }
+
+ if err != nil {
+ switch err {
+ case ackhandler.ErrDuplicateOrOutOfOrderAck:
+ // Can happen e.g. when packets thought missing arrive late
+ case errRstStreamOnInvalidStream:
+ // Can happen when RST_STREAMs arrive early or late (?)
+ utils.Errorf("Ignoring error in session: %s", err.Error())
+ case errWindowUpdateOnClosedStream:
+ // Can happen when we already sent the last StreamFrame with the FinBit, but the client already sent a WindowUpdate for this Stream
+ default:
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// handlePacket is called by the server with a new packet
+func (s *session) handlePacket(p *receivedPacket) {
+ // Discard packets once the amount of queued packets is larger than
+ // the channel size, protocol.MaxSessionUnprocessedPackets
+ select {
+ case s.receivedPackets <- p:
+ default:
+ }
+}
+
+func (s *session) handleStreamFrame(frame *frames.StreamFrame) error {
+ str, err := s.streamsMap.GetOrOpenStream(frame.StreamID)
+ if err != nil {
+ return err
+ }
+ if str == nil {
+ // Stream is closed and already garbage collected
+ // ignore this StreamFrame
+ return nil
+ }
+ return str.AddStreamFrame(frame)
+}
+
+func (s *session) handleWindowUpdateFrame(frame *frames.WindowUpdateFrame) error {
+ if frame.StreamID != 0 {
+ str, err := s.streamsMap.GetOrOpenStream(frame.StreamID)
+ if err != nil {
+ return err
+ }
+ if str == nil {
+ return errWindowUpdateOnClosedStream
+ }
+ }
+ _, err := s.flowControlManager.UpdateWindow(frame.StreamID, frame.ByteOffset)
+ return err
+}
+
+func (s *session) handleRstStreamFrame(frame *frames.RstStreamFrame) error {
+ str, err := s.streamsMap.GetOrOpenStream(frame.StreamID)
+ if err != nil {
+ return err
+ }
+ if str == nil {
+ return errRstStreamOnInvalidStream
+ }
+
+ str.RegisterRemoteError(fmt.Errorf("RST_STREAM received with code %d", frame.ErrorCode))
+ return s.flowControlManager.ResetStream(frame.StreamID, frame.ByteOffset)
+}
+
+func (s *session) handleAckFrame(frame *frames.AckFrame) error {
+ return s.sentPacketHandler.ReceivedAck(frame, s.lastRcvdPacketNumber, s.lastNetworkActivityTime)
+}
+
+func (s *session) closeLocal(e error) {
+ s.closeOnce.Do(func() {
+ s.closeChan <- closeError{err: e, remote: false}
+ })
+}
+
+func (s *session) closeRemote(e error) {
+ s.closeOnce.Do(func() {
+ s.closeChan <- closeError{err: e, remote: true}
+ })
+}
+
+// Close the connection. If err is nil it will be set to qerr.PeerGoingAway.
+// It waits until the run loop has stopped before returning
+func (s *session) Close(e error) error {
+ s.closeLocal(e)
+ <-s.runClosed
+ return nil
+}
+
+func (s *session) handleCloseError(closeErr closeError) error {
+ if closeErr.err == nil {
+ closeErr.err = qerr.PeerGoingAway
+ }
+
+ var quicErr *qerr.QuicError
+ var ok bool
+ if quicErr, ok = closeErr.err.(*qerr.QuicError); !ok {
+ quicErr = qerr.ToQuicError(closeErr.err)
+ }
+ // Don't log 'normal' reasons
+ if quicErr.ErrorCode == qerr.PeerGoingAway || quicErr.ErrorCode == qerr.NetworkIdleTimeout {
+ utils.Infof("Closing connection %x", s.connectionID)
+ } else {
+ utils.Errorf("Closing session with error: %s", closeErr.err.Error())
+ }
+
+ s.streamsMap.CloseWithError(quicErr)
+
+ if closeErr.err == errCloseSessionForNewVersion {
+ return nil
+ }
+
+ // If this is a remote close we're done here
+ if closeErr.remote {
+ return nil
+ }
+
+ if quicErr.ErrorCode == qerr.DecryptionFailure || quicErr == handshake.ErrHOLExperiment {
+ return s.sendPublicReset(s.lastRcvdPacketNumber)
+ }
+ return s.sendConnectionClose(quicErr)
+}
+
+func (s *session) sendPacket() error {
+ s.packer.SetLeastUnacked(s.sentPacketHandler.GetLeastUnacked())
+
+ // Get WindowUpdate frames
+ // this call triggers the flow controller to increase the flow control windows, if necessary
+ windowUpdateFrames := s.getWindowUpdateFrames()
+ for _, wuf := range windowUpdateFrames {
+ s.packer.QueueControlFrame(wuf)
+ }
+
+ ack := s.receivedPacketHandler.GetAckFrame()
+ if ack != nil {
+ s.packer.QueueControlFrame(ack)
+ }
+
+ // Repeatedly try sending until we don't have any more data, or run out of the congestion window
+ for {
+ if !s.sentPacketHandler.SendingAllowed() {
+ if ack == nil {
+ return nil
+ }
+ // If we aren't allowed to send, at least try sending an ACK frame
+ swf := s.sentPacketHandler.GetStopWaitingFrame(false)
+ if swf != nil {
+ s.packer.QueueControlFrame(swf)
+ }
+ packet, err := s.packer.PackAckPacket()
+ if err != nil {
+ return err
+ }
+ return s.sendPackedPacket(packet)
+ }
+
+ // check for retransmissions first
+ for {
+ retransmitPacket := s.sentPacketHandler.DequeuePacketForRetransmission()
+ if retransmitPacket == nil {
+ break
+ }
+
+ if retransmitPacket.EncryptionLevel != protocol.EncryptionForwardSecure {
+ if s.handshakeComplete {
+ // Don't retransmit handshake packets when the handshake is complete
+ continue
+ }
+ utils.Debugf("\tDequeueing handshake retransmission for packet 0x%x", retransmitPacket.PacketNumber)
+ s.packer.QueueControlFrame(s.sentPacketHandler.GetStopWaitingFrame(true))
+ packet, err := s.packer.PackHandshakeRetransmission(retransmitPacket)
+ if err != nil {
+ return err
+ }
+ if err = s.sendPackedPacket(packet); err != nil {
+ return err
+ }
+ } else {
+ utils.Debugf("\tDequeueing retransmission for packet 0x%x", retransmitPacket.PacketNumber)
+ // resend the frames that were in the packet
+ for _, frame := range retransmitPacket.GetFramesForRetransmission() {
+ switch f := frame.(type) {
+ case *frames.StreamFrame:
+ s.streamFramer.AddFrameForRetransmission(f)
+ case *frames.WindowUpdateFrame:
+ // only retransmit WindowUpdates if the stream is not yet closed and the we haven't sent another WindowUpdate with a higher ByteOffset for the stream
+ currentOffset, err := s.flowControlManager.GetReceiveWindow(f.StreamID)
+ if err == nil && f.ByteOffset >= currentOffset {
+ s.packer.QueueControlFrame(f)
+ }
+ default:
+ s.packer.QueueControlFrame(frame)
+ }
+ }
+ }
+ }
+
+ hasRetransmission := s.streamFramer.HasFramesForRetransmission()
+ if ack != nil || hasRetransmission {
+ swf := s.sentPacketHandler.GetStopWaitingFrame(hasRetransmission)
+ if swf != nil {
+ s.packer.QueueControlFrame(swf)
+ }
+ }
+ packet, err := s.packer.PackPacket()
+ if err != nil || packet == nil {
+ return err
+ }
+ if err = s.sendPackedPacket(packet); err != nil {
+ return err
+ }
+
+ // send every window update twice
+ for _, f := range windowUpdateFrames {
+ s.packer.QueueControlFrame(f)
+ }
+ windowUpdateFrames = nil
+ ack = nil
+ }
+}
+
+func (s *session) sendPackedPacket(packet *packedPacket) error {
+ defer putPacketBuffer(packet.raw)
+ err := s.sentPacketHandler.SentPacket(&ackhandler.Packet{
+ PacketNumber: packet.number,
+ Frames: packet.frames,
+ Length: protocol.ByteCount(len(packet.raw)),
+ EncryptionLevel: packet.encryptionLevel,
+ })
+ if err != nil {
+ return err
+ }
+ s.logPacket(packet)
+ return s.conn.Write(packet.raw)
+}
+
+func (s *session) sendConnectionClose(quicErr *qerr.QuicError) error {
+ s.packer.SetLeastUnacked(s.sentPacketHandler.GetLeastUnacked())
+ packet, err := s.packer.PackConnectionClose(&frames.ConnectionCloseFrame{
+ ErrorCode: quicErr.ErrorCode,
+ ReasonPhrase: quicErr.ErrorMessage,
+ })
+ if err != nil {
+ return err
+ }
+ s.logPacket(packet)
+ return s.conn.Write(packet.raw)
+}
+
+func (s *session) logPacket(packet *packedPacket) {
+ if !utils.Debug() {
+ // We don't need to allocate the slices for calling the format functions
+ return
+ }
+ utils.Debugf("-> Sending packet 0x%x (%d bytes) for connection %x, %s", packet.number, len(packet.raw), s.connectionID, packet.encryptionLevel)
+ for _, frame := range packet.frames {
+ frames.LogFrame(frame, true)
+ }
+}
+
+// GetOrOpenStream either returns an existing stream, a newly opened stream, or nil if a stream with the provided ID is already closed.
+// Newly opened streams should only originate from the client. To open a stream from the server, OpenStream should be used.
+func (s *session) GetOrOpenStream(id protocol.StreamID) (Stream, error) {
+ str, err := s.streamsMap.GetOrOpenStream(id)
+ if str != nil {
+ return str, err
+ }
+ // make sure to return an actual nil value here, not an Stream with value nil
+ return nil, err
+}
+
+// AcceptStream returns the next stream openend by the peer
+func (s *session) AcceptStream() (Stream, error) {
+ return s.streamsMap.AcceptStream()
+}
+
+// OpenStream opens a stream
+func (s *session) OpenStream() (Stream, error) {
+ return s.streamsMap.OpenStream()
+}
+
+func (s *session) OpenStreamSync() (Stream, error) {
+ return s.streamsMap.OpenStreamSync()
+}
+
+func (s *session) WaitUntilHandshakeComplete() error {
+ return <-s.handshakeCompleteChan
+}
+
+func (s *session) queueResetStreamFrame(id protocol.StreamID, offset protocol.ByteCount) {
+ s.packer.QueueControlFrame(&frames.RstStreamFrame{
+ StreamID: id,
+ ByteOffset: offset,
+ })
+ s.scheduleSending()
+}
+
+func (s *session) newStream(id protocol.StreamID) *stream {
+ // TODO: find a better solution for determining which streams contribute to connection level flow control
+ if id == 1 || id == 3 {
+ s.flowControlManager.NewStream(id, false)
+ } else {
+ s.flowControlManager.NewStream(id, true)
+ }
+ return newStream(id, s.scheduleSending, s.queueResetStreamFrame, s.flowControlManager)
+}
+
+// garbageCollectStreams goes through all streams and removes EOF'ed streams
+// from the streams map.
+func (s *session) garbageCollectStreams() {
+ s.streamsMap.Iterate(func(str *stream) (bool, error) {
+ id := str.StreamID()
+ if str.finished() {
+ err := s.streamsMap.RemoveStream(id)
+ if err != nil {
+ return false, err
+ }
+ s.flowControlManager.RemoveStream(id)
+ }
+ return true, nil
+ })
+}
+
+func (s *session) sendPublicReset(rejectedPacketNumber protocol.PacketNumber) error {
+ utils.Infof("Sending public reset for connection %x, packet number %d", s.connectionID, rejectedPacketNumber)
+ return s.conn.Write(writePublicReset(s.connectionID, rejectedPacketNumber, 0))
+}
+
+// scheduleSending signals that we have data for sending
+func (s *session) scheduleSending() {
+ select {
+ case s.sendingScheduled <- struct{}{}:
+ default:
+ }
+}
+
+func (s *session) tryQueueingUndecryptablePacket(p *receivedPacket) {
+ if s.handshakeComplete {
+ utils.Debugf("Received undecryptable packet from %s after the handshake: %#v, %d bytes data", p.remoteAddr.String(), p.publicHeader, len(p.data))
+ return
+ }
+ if len(s.undecryptablePackets)+1 > protocol.MaxUndecryptablePackets {
+ // if this is the first time the undecryptablePackets runs full, start the timer to send a Public Reset
+ if s.receivedTooManyUndecrytablePacketsTime.IsZero() {
+ s.receivedTooManyUndecrytablePacketsTime = time.Now()
+ s.maybeResetTimer()
+ }
+ utils.Infof("Dropping undecrytable packet 0x%x (undecryptable packet queue full)", p.publicHeader.PacketNumber)
+ return
+ }
+ utils.Infof("Queueing packet 0x%x for later decryption", p.publicHeader.PacketNumber)
+ s.undecryptablePackets = append(s.undecryptablePackets, p)
+}
+
+func (s *session) tryDecryptingQueuedPackets() {
+ for _, p := range s.undecryptablePackets {
+ s.handlePacket(p)
+ }
+ s.undecryptablePackets = s.undecryptablePackets[:0]
+}
+
+func (s *session) getWindowUpdateFrames() []*frames.WindowUpdateFrame {
+ updates := s.flowControlManager.GetWindowUpdates()
+ res := make([]*frames.WindowUpdateFrame, len(updates))
+ for i, u := range updates {
+ res[i] = &frames.WindowUpdateFrame{StreamID: u.StreamID, ByteOffset: u.Offset}
+ }
+ return res
+}
+
+func (s *session) LocalAddr() net.Addr {
+ return s.conn.LocalAddr()
+}
+
+// RemoteAddr returns the net.Addr of the client
+func (s *session) RemoteAddr() net.Addr {
+ return s.conn.RemoteAddr()
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/stream.go b/vendor/github.com/lucas-clemente/quic-go/stream.go
new file mode 100644
index 0000000..45cf01a
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/stream.go
@@ -0,0 +1,417 @@
+package quic
+
+import (
+ "fmt"
+ "io"
+ "net"
+ "sync"
+ "time"
+
+ "github.com/lucas-clemente/quic-go/flowcontrol"
+ "github.com/lucas-clemente/quic-go/frames"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+)
+
+// A Stream assembles the data from StreamFrames and provides a super-convenient Read-Interface
+//
+// Read() and Write() may be called concurrently, but multiple calls to Read() or Write() individually must be synchronized manually.
+type stream struct {
+ mutex sync.Mutex
+
+ streamID protocol.StreamID
+ onData func()
+ // onReset is a callback that should send a RST_STREAM
+ onReset func(protocol.StreamID, protocol.ByteCount)
+
+ readPosInFrame int
+ writeOffset protocol.ByteCount
+ readOffset protocol.ByteCount
+
+ // Once set, the errors must not be changed!
+ err error
+
+ // cancelled is set when Cancel() is called
+ cancelled utils.AtomicBool
+ // finishedReading is set once we read a frame with a FinBit
+ finishedReading utils.AtomicBool
+ // finisedWriting is set once Close() is called
+ finishedWriting utils.AtomicBool
+ // resetLocally is set if Reset() is called
+ resetLocally utils.AtomicBool
+ // resetRemotely is set if RegisterRemoteError() is called
+ resetRemotely utils.AtomicBool
+
+ frameQueue *streamFrameSorter
+ readChan chan struct{}
+ readDeadline time.Time
+
+ dataForWriting []byte
+ finSent utils.AtomicBool
+ rstSent utils.AtomicBool
+ writeChan chan struct{}
+ writeDeadline time.Time
+
+ flowControlManager flowcontrol.FlowControlManager
+}
+
+type deadlineError struct{}
+
+func (deadlineError) Error() string { return "deadline exceeded" }
+func (deadlineError) Temporary() bool { return true }
+func (deadlineError) Timeout() bool { return true }
+
+var errDeadline net.Error = &deadlineError{}
+
+// newStream creates a new Stream
+func newStream(StreamID protocol.StreamID,
+ onData func(),
+ onReset func(protocol.StreamID, protocol.ByteCount),
+ flowControlManager flowcontrol.FlowControlManager) *stream {
+ return &stream{
+ onData: onData,
+ onReset: onReset,
+ streamID: StreamID,
+ flowControlManager: flowControlManager,
+ frameQueue: newStreamFrameSorter(),
+ readChan: make(chan struct{}, 1),
+ writeChan: make(chan struct{}, 1),
+ }
+}
+
+// Read implements io.Reader. It is not thread safe!
+func (s *stream) Read(p []byte) (int, error) {
+ s.mutex.Lock()
+ err := s.err
+ s.mutex.Unlock()
+ if s.cancelled.Get() || s.resetLocally.Get() {
+ return 0, err
+ }
+ if s.finishedReading.Get() {
+ return 0, io.EOF
+ }
+
+ bytesRead := 0
+ for bytesRead < len(p) {
+ s.mutex.Lock()
+ frame := s.frameQueue.Head()
+ if frame == nil && bytesRead > 0 {
+ err = s.err
+ s.mutex.Unlock()
+ return bytesRead, err
+ }
+
+ var err error
+ for {
+ // Stop waiting on errors
+ if s.resetLocally.Get() || s.cancelled.Get() {
+ err = s.err
+ break
+ }
+
+ deadline := s.readDeadline
+ if !deadline.IsZero() && !time.Now().Before(deadline) {
+ err = errDeadline
+ break
+ }
+
+ if frame != nil {
+ s.readPosInFrame = int(s.readOffset - frame.Offset)
+ break
+ }
+
+ s.mutex.Unlock()
+ if deadline.IsZero() {
+ <-s.readChan
+ } else {
+ select {
+ case <-s.readChan:
+ case <-time.After(deadline.Sub(time.Now())):
+ }
+ }
+ s.mutex.Lock()
+ frame = s.frameQueue.Head()
+ }
+ s.mutex.Unlock()
+
+ if err != nil {
+ return bytesRead, err
+ }
+
+ m := utils.Min(len(p)-bytesRead, int(frame.DataLen())-s.readPosInFrame)
+
+ if bytesRead > len(p) {
+ return bytesRead, fmt.Errorf("BUG: bytesRead (%d) > len(p) (%d) in stream.Read", bytesRead, len(p))
+ }
+ if s.readPosInFrame > int(frame.DataLen()) {
+ return bytesRead, fmt.Errorf("BUG: readPosInFrame (%d) > frame.DataLen (%d) in stream.Read", s.readPosInFrame, frame.DataLen())
+ }
+ copy(p[bytesRead:], frame.Data[s.readPosInFrame:])
+
+ s.readPosInFrame += m
+ bytesRead += m
+ s.readOffset += protocol.ByteCount(m)
+
+ // when a RST_STREAM was received, the was already informed about the final byteOffset for this stream
+ if !s.resetRemotely.Get() {
+ s.flowControlManager.AddBytesRead(s.streamID, protocol.ByteCount(m))
+ }
+ s.onData() // so that a possible WINDOW_UPDATE is sent
+
+ if s.readPosInFrame >= int(frame.DataLen()) {
+ fin := frame.FinBit
+ s.mutex.Lock()
+ s.frameQueue.Pop()
+ s.mutex.Unlock()
+ if fin {
+ s.finishedReading.Set(true)
+ return bytesRead, io.EOF
+ }
+ }
+ }
+
+ return bytesRead, nil
+}
+
+func (s *stream) Write(p []byte) (int, error) {
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
+
+ if s.resetLocally.Get() || s.err != nil {
+ return 0, s.err
+ }
+ if s.finishedWriting.Get() {
+ return 0, fmt.Errorf("write on closed stream %d", s.streamID)
+ }
+ if len(p) == 0 {
+ return 0, nil
+ }
+
+ s.dataForWriting = make([]byte, len(p))
+ copy(s.dataForWriting, p)
+ s.onData()
+
+ var err error
+ for {
+ deadline := s.writeDeadline
+ if !deadline.IsZero() && !time.Now().Before(deadline) {
+ err = errDeadline
+ break
+ }
+ if s.dataForWriting == nil || s.err != nil {
+ break
+ }
+
+ s.mutex.Unlock()
+ if deadline.IsZero() {
+ <-s.writeChan
+ } else {
+ select {
+ case <-s.writeChan:
+ case <-time.After(deadline.Sub(time.Now())):
+ }
+ }
+ s.mutex.Lock()
+ }
+
+ if err != nil {
+ return 0, err
+ }
+ if s.err != nil {
+ return len(p) - len(s.dataForWriting), s.err
+ }
+ return len(p), nil
+}
+
+func (s *stream) lenOfDataForWriting() protocol.ByteCount {
+ s.mutex.Lock()
+ var l protocol.ByteCount
+ if s.err == nil {
+ l = protocol.ByteCount(len(s.dataForWriting))
+ }
+ s.mutex.Unlock()
+ return l
+}
+
+func (s *stream) getDataForWriting(maxBytes protocol.ByteCount) []byte {
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
+
+ if s.err != nil || s.dataForWriting == nil {
+ return nil
+ }
+
+ var ret []byte
+ if protocol.ByteCount(len(s.dataForWriting)) > maxBytes {
+ ret = s.dataForWriting[:maxBytes]
+ s.dataForWriting = s.dataForWriting[maxBytes:]
+ } else {
+ ret = s.dataForWriting
+ s.dataForWriting = nil
+ s.signalWrite()
+ }
+ s.writeOffset += protocol.ByteCount(len(ret))
+ return ret
+}
+
+// Close implements io.Closer
+func (s *stream) Close() error {
+ s.finishedWriting.Set(true)
+ s.onData()
+ return nil
+}
+
+func (s *stream) shouldSendReset() bool {
+ if s.rstSent.Get() {
+ return false
+ }
+ return (s.resetLocally.Get() || s.resetRemotely.Get()) && !s.finishedWriteAndSentFin()
+}
+
+func (s *stream) shouldSendFin() bool {
+ s.mutex.Lock()
+ res := s.finishedWriting.Get() && !s.finSent.Get() && s.err == nil && s.dataForWriting == nil
+ s.mutex.Unlock()
+ return res
+}
+
+func (s *stream) sentFin() {
+ s.finSent.Set(true)
+}
+
+// AddStreamFrame adds a new stream frame
+func (s *stream) AddStreamFrame(frame *frames.StreamFrame) error {
+ maxOffset := frame.Offset + frame.DataLen()
+ err := s.flowControlManager.UpdateHighestReceived(s.streamID, maxOffset)
+ if err != nil {
+ return err
+ }
+
+ s.mutex.Lock()
+ defer s.mutex.Unlock()
+ err = s.frameQueue.Push(frame)
+ if err != nil && err != errDuplicateStreamData {
+ return err
+ }
+ s.signalRead()
+ return nil
+}
+
+// signalRead performs a non-blocking send on the readChan
+func (s *stream) signalRead() {
+ select {
+ case s.readChan <- struct{}{}:
+ default:
+ }
+}
+
+// signalRead performs a non-blocking send on the writeChan
+func (s *stream) signalWrite() {
+ select {
+ case s.writeChan <- struct{}{}:
+ default:
+ }
+}
+
+func (s *stream) SetReadDeadline(t time.Time) error {
+ s.mutex.Lock()
+ oldDeadline := s.readDeadline
+ s.readDeadline = t
+ s.mutex.Unlock()
+ // if the new deadline is before the currently set deadline, wake up Read()
+ if t.Before(oldDeadline) {
+ s.signalRead()
+ }
+ return nil
+}
+
+func (s *stream) SetWriteDeadline(t time.Time) error {
+ s.mutex.Lock()
+ oldDeadline := s.writeDeadline
+ s.writeDeadline = t
+ s.mutex.Unlock()
+ if t.Before(oldDeadline) {
+ s.signalWrite()
+ }
+ return nil
+}
+
+func (s *stream) SetDeadline(t time.Time) error {
+ _ = s.SetReadDeadline(t) // SetReadDeadline never errors
+ _ = s.SetWriteDeadline(t) // SetWriteDeadline never errors
+ return nil
+}
+
+// CloseRemote makes the stream receive a "virtual" FIN stream frame at a given offset
+func (s *stream) CloseRemote(offset protocol.ByteCount) {
+ s.AddStreamFrame(&frames.StreamFrame{FinBit: true, Offset: offset})
+}
+
+// Cancel is called by session to indicate that an error occurred
+// The stream should will be closed immediately
+func (s *stream) Cancel(err error) {
+ s.mutex.Lock()
+ s.cancelled.Set(true)
+ // errors must not be changed!
+ if s.err == nil {
+ s.err = err
+ s.signalRead()
+ s.signalWrite()
+ }
+ s.mutex.Unlock()
+}
+
+// resets the stream locally
+func (s *stream) Reset(err error) {
+ if s.resetLocally.Get() {
+ return
+ }
+ s.mutex.Lock()
+ s.resetLocally.Set(true)
+ // errors must not be changed!
+ if s.err == nil {
+ s.err = err
+ s.signalRead()
+ s.signalWrite()
+ }
+ if s.shouldSendReset() {
+ s.onReset(s.streamID, s.writeOffset)
+ s.rstSent.Set(true)
+ }
+ s.mutex.Unlock()
+}
+
+// resets the stream remotely
+func (s *stream) RegisterRemoteError(err error) {
+ if s.resetRemotely.Get() {
+ return
+ }
+ s.mutex.Lock()
+ s.resetRemotely.Set(true)
+ // errors must not be changed!
+ if s.err == nil {
+ s.err = err
+ s.signalWrite()
+ }
+ if s.shouldSendReset() {
+ s.onReset(s.streamID, s.writeOffset)
+ s.rstSent.Set(true)
+ }
+ s.mutex.Unlock()
+}
+
+func (s *stream) finishedWriteAndSentFin() bool {
+ return s.finishedWriting.Get() && s.finSent.Get()
+}
+
+func (s *stream) finished() bool {
+ return s.cancelled.Get() ||
+ (s.finishedReading.Get() && s.finishedWriteAndSentFin()) ||
+ (s.resetRemotely.Get() && s.rstSent.Get()) ||
+ (s.finishedReading.Get() && s.rstSent.Get()) ||
+ (s.finishedWriteAndSentFin() && s.resetRemotely.Get())
+}
+
+func (s *stream) StreamID() protocol.StreamID {
+ return s.streamID
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/stream_frame_sorter.go b/vendor/github.com/lucas-clemente/quic-go/stream_frame_sorter.go
new file mode 100644
index 0000000..4a50150
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/stream_frame_sorter.go
@@ -0,0 +1,161 @@
+package quic
+
+import (
+ "errors"
+
+ "github.com/lucas-clemente/quic-go/frames"
+ "github.com/lucas-clemente/quic-go/internal/utils"
+ "github.com/lucas-clemente/quic-go/protocol"
+)
+
+type streamFrameSorter struct {
+ queuedFrames map[protocol.ByteCount]*frames.StreamFrame
+ readPosition protocol.ByteCount
+ gaps *utils.ByteIntervalList
+}
+
+var (
+ errTooManyGapsInReceivedStreamData = errors.New("Too many gaps in received StreamFrame data")
+ errDuplicateStreamData = errors.New("Duplicate Stream Data")
+ errEmptyStreamData = errors.New("Stream Data empty")
+)
+
+func newStreamFrameSorter() *streamFrameSorter {
+ s := streamFrameSorter{
+ gaps: utils.NewByteIntervalList(),
+ queuedFrames: make(map[protocol.ByteCount]*frames.StreamFrame),
+ }
+ s.gaps.PushFront(utils.ByteInterval{Start: 0, End: protocol.MaxByteCount})
+ return &s
+}
+
+func (s *streamFrameSorter) Push(frame *frames.StreamFrame) error {
+ if frame.DataLen() == 0 {
+ if frame.FinBit {
+ s.queuedFrames[frame.Offset] = frame
+ return nil
+ }
+ return errEmptyStreamData
+ }
+
+ var wasCut bool
+ if oldFrame, ok := s.queuedFrames[frame.Offset]; ok {
+ if frame.DataLen() <= oldFrame.DataLen() {
+ return errDuplicateStreamData
+ }
+ frame.Data = frame.Data[oldFrame.DataLen():]
+ frame.Offset += oldFrame.DataLen()
+ wasCut = true
+ }
+
+ start := frame.Offset
+ end := frame.Offset + frame.DataLen()
+
+ // skip all gaps that are before this stream frame
+ var gap *utils.ByteIntervalElement
+ for gap = s.gaps.Front(); gap != nil; gap = gap.Next() {
+ // the frame is a duplicate. Ignore it
+ if end <= gap.Value.Start {
+ return errDuplicateStreamData
+ }
+ if end > gap.Value.Start && start <= gap.Value.End {
+ break
+ }
+ }
+
+ if gap == nil {
+ return errors.New("StreamFrameSorter BUG: no gap found")
+ }
+
+ if start < gap.Value.Start {
+ add := gap.Value.Start - start
+ frame.Offset += add
+ start += add
+ frame.Data = frame.Data[add:]
+ wasCut = true
+ }
+
+ // find the highest gaps whose Start lies before the end of the frame
+ endGap := gap
+ for end >= endGap.Value.End {
+ nextEndGap := endGap.Next()
+ if nextEndGap == nil {
+ return errors.New("StreamFrameSorter BUG: no end gap found")
+ }
+ if endGap != gap {
+ s.gaps.Remove(endGap)
+ }
+ if end <= nextEndGap.Value.Start {
+ break
+ }
+ // delete queued frames completely covered by the current frame
+ delete(s.queuedFrames, endGap.Value.End)
+ endGap = nextEndGap
+ }
+
+ if end > endGap.Value.End {
+ cutLen := end - endGap.Value.End
+ len := frame.DataLen() - cutLen
+ end -= cutLen
+ frame.Data = frame.Data[:len]
+ wasCut = true
+ }
+
+ if start == gap.Value.Start {
+ if end >= gap.Value.End {
+ // the frame completely fills this gap
+ // delete the gap
+ s.gaps.Remove(gap)
+ }
+ if end < endGap.Value.End {
+ // the frame covers the beginning of the gap
+ // adjust the Start value to shrink the gap
+ endGap.Value.Start = end
+ }
+ } else if end == endGap.Value.End {
+ // the frame covers the end of the gap
+ // adjust the End value to shrink the gap
+ gap.Value.End = start
+ } else {
+ if gap == endGap {
+ // the frame lies within the current gap, splitting it into two
+ // insert a new gap and adjust the current one
+ intv := utils.ByteInterval{Start: end, End: gap.Value.End}
+ s.gaps.InsertAfter(intv, gap)
+ gap.Value.End = start
+ } else {
+ gap.Value.End = start
+ endGap.Value.Start = end
+ }
+ }
+
+ if s.gaps.Len() > protocol.MaxStreamFrameSorterGaps {
+ return errTooManyGapsInReceivedStreamData
+ }
+
+ if wasCut {
+ data := make([]byte, frame.DataLen())
+ copy(data, frame.Data)
+ frame.Data = data
+ }
+
+ s.queuedFrames[frame.Offset] = frame
+ return nil
+}
+
+func (s *streamFrameSorter) Pop() *frames.StreamFrame {
+ frame := s.Head()
+ if frame != nil {
+ s.readPosition += frame.DataLen()
+ delete(s.queuedFrames, frame.Offset)
+ }
+ return frame
+}
+
+func (s *streamFrameSorter) Head() *frames.StreamFrame {
+ frame, ok := s.queuedFrames[s.readPosition]
+ if ok {
+ return frame
+ }
+ return nil
+}
diff --git a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/stream_framer.go b/vendor/github.com/lucas-clemente/quic-go/stream_framer.go
similarity index 79%
rename from cmd/gost/vendor/github.com/lucas-clemente/quic-go/stream_framer.go
rename to vendor/github.com/lucas-clemente/quic-go/stream_framer.go
index b702c28..20f82e3 100644
--- a/cmd/gost/vendor/github.com/lucas-clemente/quic-go/stream_framer.go
+++ b/vendor/github.com/lucas-clemente/quic-go/stream_framer.go
@@ -3,8 +3,8 @@ package quic
import (
"github.com/lucas-clemente/quic-go/flowcontrol"
"github.com/lucas-clemente/quic-go/frames"
+ "github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
- "github.com/lucas-clemente/quic-go/utils"
)
type streamFramer struct {
@@ -45,6 +45,28 @@ func (f *streamFramer) HasFramesForRetransmission() bool {
return len(f.retransmissionQueue) > 0
}
+func (f *streamFramer) HasCryptoStreamFrame() bool {
+ // TODO(#657): Flow control
+ cs, _ := f.streamsMap.GetOrOpenStream(1)
+ return cs.lenOfDataForWriting() > 0
+}
+
+// TODO(lclemente): This is somewhat duplicate with the normal path for generating frames.
+// TODO(#657): Flow control
+func (f *streamFramer) PopCryptoStreamFrame(maxLen protocol.ByteCount) *frames.StreamFrame {
+ if !f.HasCryptoStreamFrame() {
+ return nil
+ }
+ cs, _ := f.streamsMap.GetOrOpenStream(1)
+ frame := &frames.StreamFrame{
+ StreamID: 1,
+ Offset: cs.writeOffset,
+ }
+ frameHeaderBytes, _ := frame.MinLength(protocol.VersionWhatever) // can never error
+ frame.Data = cs.getDataForWriting(maxLen - frameHeaderBytes)
+ return frame
+}
+
func (f *streamFramer) maybePopFramesForRetransmission(maxLen protocol.ByteCount) (res []*frames.StreamFrame, currentLen protocol.ByteCount) {
for len(f.retransmissionQueue) > 0 {
frame := f.retransmissionQueue[0]
@@ -76,7 +98,7 @@ func (f *streamFramer) maybePopNormalFrames(maxBytes protocol.ByteCount) (res []
var currentLen protocol.ByteCount
fn := func(s *stream) (bool, error) {
- if s == nil {
+ if s == nil || s.streamID == 1 /* crypto stream is handled separately */ {
return true, nil
}
@@ -90,7 +112,8 @@ func (f *streamFramer) maybePopNormalFrames(maxBytes protocol.ByteCount) (res []
maxLen := maxBytes - currentLen - frameHeaderBytes
var sendWindowSize protocol.ByteCount
- if s.lenOfDataForWriting() != 0 {
+ lenStreamData := s.lenOfDataForWriting()
+ if lenStreamData != 0 {
sendWindowSize, _ = f.flowControlManager.SendWindowSize(s.streamID)
maxLen = utils.MinByteCount(maxLen, sendWindowSize)
}
@@ -99,7 +122,12 @@ func (f *streamFramer) maybePopNormalFrames(maxBytes protocol.ByteCount) (res []
return true, nil
}
- data := s.getDataForWriting(maxLen)
+ var data []byte
+ if lenStreamData != 0 {
+ // Only getDataForWriting() if we didn't have data earlier, so that we
+ // don't send without FC approval (if a Write() raced).
+ data = s.getDataForWriting(maxLen)
+ }
// This is unlikely, but check it nonetheless, the scheduler might have jumped in. Seems to happen in ~20% of cases in the tests.
shouldSendFin := s.shouldSendFin()
@@ -119,7 +147,7 @@ func (f *streamFramer) maybePopNormalFrames(maxBytes protocol.ByteCount) (res []
if f.flowControlManager.RemainingConnectionWindowSize() == 0 {
// We are now connection-level FC blocked
f.blockedFrameQueue = append(f.blockedFrameQueue, &frames.BlockedFrame{StreamID: 0})
- } else if sendWindowSize-frame.DataLen() == 0 {
+ } else if !frame.FinBit && sendWindowSize-frame.DataLen() == 0 {
// We are now stream-level FC blocked
f.blockedFrameQueue = append(f.blockedFrameQueue, &frames.BlockedFrame{StreamID: s.StreamID()})
}
diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map.go b/vendor/github.com/lucas-clemente/quic-go/streams_map.go
new file mode 100644
index 0000000..74be17e
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/streams_map.go
@@ -0,0 +1,333 @@
+package quic
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+
+ "github.com/lucas-clemente/quic-go/handshake"
+ "github.com/lucas-clemente/quic-go/protocol"
+ "github.com/lucas-clemente/quic-go/qerr"
+)
+
+type streamsMap struct {
+ mutex sync.RWMutex
+
+ perspective protocol.Perspective
+ connectionParameters handshake.ConnectionParametersManager
+
+ streams map[protocol.StreamID]*stream
+ // needed for round-robin scheduling
+ openStreams []protocol.StreamID
+ roundRobinIndex uint32
+
+ nextStream protocol.StreamID // StreamID of the next Stream that will be returned by OpenStream()
+ highestStreamOpenedByPeer protocol.StreamID
+ nextStreamOrErrCond sync.Cond
+ openStreamOrErrCond sync.Cond
+
+ closeErr error
+ nextStreamToAccept protocol.StreamID
+
+ newStream newStreamLambda
+
+ numOutgoingStreams uint32
+ numIncomingStreams uint32
+}
+
+type streamLambda func(*stream) (bool, error)
+type newStreamLambda func(protocol.StreamID) *stream
+
+var (
+ errMapAccess = errors.New("streamsMap: Error accessing the streams map")
+)
+
+func newStreamsMap(newStream newStreamLambda, pers protocol.Perspective, connectionParameters handshake.ConnectionParametersManager) *streamsMap {
+ sm := streamsMap{
+ perspective: pers,
+ streams: map[protocol.StreamID]*stream{},
+ openStreams: make([]protocol.StreamID, 0),
+ newStream: newStream,
+ connectionParameters: connectionParameters,
+ }
+ sm.nextStreamOrErrCond.L = &sm.mutex
+ sm.openStreamOrErrCond.L = &sm.mutex
+
+ if pers == protocol.PerspectiveClient {
+ sm.nextStream = 1
+ sm.nextStreamToAccept = 2
+ } else {
+ sm.nextStream = 2
+ sm.nextStreamToAccept = 1
+ }
+
+ return &sm
+}
+
+// GetOrOpenStream either returns an existing stream, a newly opened stream, or nil if a stream with the provided ID is already closed.
+// Newly opened streams should only originate from the client. To open a stream from the server, OpenStream should be used.
+func (m *streamsMap) GetOrOpenStream(id protocol.StreamID) (*stream, error) {
+ m.mutex.RLock()
+ s, ok := m.streams[id]
+ m.mutex.RUnlock()
+ if ok {
+ return s, nil // s may be nil
+ }
+
+ // ... we don't have an existing stream
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+ // We need to check whether another invocation has already created a stream (between RUnlock() and Lock()).
+ s, ok = m.streams[id]
+ if ok {
+ return s, nil
+ }
+
+ if m.perspective == protocol.PerspectiveServer {
+ if id%2 == 0 {
+ if id <= m.nextStream { // this is a server-side stream that we already opened. Must have been closed already
+ return nil, nil
+ }
+ return nil, qerr.Error(qerr.InvalidStreamID, fmt.Sprintf("attempted to open stream %d from client-side", id))
+ }
+ if id <= m.highestStreamOpenedByPeer { // this is a client-side stream that doesn't exist anymore. Must have been closed already
+ return nil, nil
+ }
+ }
+ if m.perspective == protocol.PerspectiveClient {
+ if id%2 == 1 {
+ if id <= m.nextStream { // this is a client-side stream that we already opened.
+ return nil, nil
+ }
+ return nil, qerr.Error(qerr.InvalidStreamID, fmt.Sprintf("attempted to open stream %d from server-side", id))
+ }
+ if id <= m.highestStreamOpenedByPeer { // this is a server-side stream that doesn't exist anymore. Must have been closed already
+ return nil, nil
+ }
+ }
+
+ // sid is the next stream that will be opened
+ sid := m.highestStreamOpenedByPeer + 2
+ // if there is no stream opened yet, and this is the server, stream 1 should be openend
+ if sid == 2 && m.perspective == protocol.PerspectiveServer {
+ sid = 1
+ }
+
+ for ; sid <= id; sid += 2 {
+ _, err := m.openRemoteStream(sid)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ m.nextStreamOrErrCond.Broadcast()
+ return m.streams[id], nil
+}
+
+func (m *streamsMap) openRemoteStream(id protocol.StreamID) (*stream, error) {
+ if m.numIncomingStreams >= m.connectionParameters.GetMaxIncomingStreams() {
+ return nil, qerr.TooManyOpenStreams
+ }
+ if id+protocol.MaxNewStreamIDDelta < m.highestStreamOpenedByPeer {
+ return nil, qerr.Error(qerr.InvalidStreamID, fmt.Sprintf("attempted to open stream %d, which is a lot smaller than the highest opened stream, %d", id, m.highestStreamOpenedByPeer))
+ }
+
+ if m.perspective == protocol.PerspectiveServer {
+ m.numIncomingStreams++
+ } else {
+ m.numOutgoingStreams++
+ }
+
+ if id > m.highestStreamOpenedByPeer {
+ m.highestStreamOpenedByPeer = id
+ }
+
+ s := m.newStream(id)
+ m.putStream(s)
+ return s, nil
+}
+
+func (m *streamsMap) openStreamImpl() (*stream, error) {
+ id := m.nextStream
+ if m.numOutgoingStreams >= m.connectionParameters.GetMaxOutgoingStreams() {
+ return nil, qerr.TooManyOpenStreams
+ }
+
+ if m.perspective == protocol.PerspectiveServer {
+ m.numOutgoingStreams++
+ } else {
+ m.numIncomingStreams++
+ }
+
+ m.nextStream += 2
+ s := m.newStream(id)
+ m.putStream(s)
+ return s, nil
+}
+
+// OpenStream opens the next available stream
+func (m *streamsMap) OpenStream() (*stream, error) {
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+
+ if m.closeErr != nil {
+ return nil, m.closeErr
+ }
+ return m.openStreamImpl()
+}
+
+func (m *streamsMap) OpenStreamSync() (*stream, error) {
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+
+ for {
+ if m.closeErr != nil {
+ return nil, m.closeErr
+ }
+ str, err := m.openStreamImpl()
+ if err == nil {
+ return str, err
+ }
+ if err != nil && err != qerr.TooManyOpenStreams {
+ return nil, err
+ }
+ m.openStreamOrErrCond.Wait()
+ }
+}
+
+// AcceptStream returns the next stream opened by the peer
+// it blocks until a new stream is opened
+func (m *streamsMap) AcceptStream() (*stream, error) {
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+ var str *stream
+ for {
+ var ok bool
+ if m.closeErr != nil {
+ return nil, m.closeErr
+ }
+ str, ok = m.streams[m.nextStreamToAccept]
+ if ok {
+ break
+ }
+ m.nextStreamOrErrCond.Wait()
+ }
+ m.nextStreamToAccept += 2
+ return str, nil
+}
+
+func (m *streamsMap) Iterate(fn streamLambda) error {
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+
+ openStreams := append([]protocol.StreamID{}, m.openStreams...)
+
+ for _, streamID := range openStreams {
+ cont, err := m.iterateFunc(streamID, fn)
+ if err != nil {
+ return err
+ }
+ if !cont {
+ break
+ }
+ }
+ return nil
+}
+
+// RoundRobinIterate executes the streamLambda for every open stream, until the streamLambda returns false
+// It uses a round-robin-like scheduling to ensure that every stream is considered fairly
+// It prioritizes the crypto- and the header-stream (StreamIDs 1 and 3)
+func (m *streamsMap) RoundRobinIterate(fn streamLambda) error {
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+
+ numStreams := uint32(len(m.streams))
+ startIndex := m.roundRobinIndex
+
+ for _, i := range []protocol.StreamID{1, 3} {
+ cont, err := m.iterateFunc(i, fn)
+ if err != nil && err != errMapAccess {
+ return err
+ }
+ if !cont {
+ return nil
+ }
+ }
+
+ for i := uint32(0); i < numStreams; i++ {
+ streamID := m.openStreams[(i+startIndex)%numStreams]
+ if streamID == 1 || streamID == 3 {
+ continue
+ }
+
+ cont, err := m.iterateFunc(streamID, fn)
+ if err != nil {
+ return err
+ }
+ m.roundRobinIndex = (m.roundRobinIndex + 1) % numStreams
+ if !cont {
+ break
+ }
+ }
+ return nil
+}
+
+func (m *streamsMap) iterateFunc(streamID protocol.StreamID, fn streamLambda) (bool, error) {
+ str, ok := m.streams[streamID]
+ if !ok {
+ return true, errMapAccess
+ }
+ return fn(str)
+}
+
+func (m *streamsMap) putStream(s *stream) error {
+ id := s.StreamID()
+ if _, ok := m.streams[id]; ok {
+ return fmt.Errorf("a stream with ID %d already exists", id)
+ }
+
+ m.streams[id] = s
+ m.openStreams = append(m.openStreams, id)
+ return nil
+}
+
+// Attention: this function must only be called if a mutex has been acquired previously
+func (m *streamsMap) RemoveStream(id protocol.StreamID) error {
+ s, ok := m.streams[id]
+ if !ok || s == nil {
+ return fmt.Errorf("attempted to remove non-existing stream: %d", id)
+ }
+
+ if id%2 == 0 {
+ m.numOutgoingStreams--
+ } else {
+ m.numIncomingStreams--
+ }
+
+ for i, s := range m.openStreams {
+ if s == id {
+ // delete the streamID from the openStreams slice
+ m.openStreams = m.openStreams[:i+copy(m.openStreams[i:], m.openStreams[i+1:])]
+ // adjust round-robin index, if necessary
+ if uint32(i) < m.roundRobinIndex {
+ m.roundRobinIndex--
+ }
+ break
+ }
+ }
+
+ delete(m.streams, id)
+ m.openStreamOrErrCond.Signal()
+ return nil
+}
+
+func (m *streamsMap) CloseWithError(err error) {
+ m.mutex.Lock()
+ defer m.mutex.Unlock()
+ m.closeErr = err
+ m.nextStreamOrErrCond.Broadcast()
+ m.openStreamOrErrCond.Broadcast()
+ for _, s := range m.openStreams {
+ m.streams[s].Cancel(err)
+ }
+}
diff --git a/cmd/gost/vendor/github.com/pkg/errors/LICENSE b/vendor/github.com/pkg/errors/LICENSE
similarity index 100%
rename from cmd/gost/vendor/github.com/pkg/errors/LICENSE
rename to vendor/github.com/pkg/errors/LICENSE
diff --git a/cmd/gost/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md
similarity index 100%
rename from cmd/gost/vendor/github.com/pkg/errors/README.md
rename to vendor/github.com/pkg/errors/README.md
diff --git a/cmd/gost/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml
similarity index 100%
rename from cmd/gost/vendor/github.com/pkg/errors/appveyor.yml
rename to vendor/github.com/pkg/errors/appveyor.yml
diff --git a/cmd/gost/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go
similarity index 100%
rename from cmd/gost/vendor/github.com/pkg/errors/errors.go
rename to vendor/github.com/pkg/errors/errors.go
diff --git a/cmd/gost/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go
similarity index 100%
rename from cmd/gost/vendor/github.com/pkg/errors/stack.go
rename to vendor/github.com/pkg/errors/stack.go
diff --git a/cmd/gost/vendor/github.com/codahale/chacha20/LICENSE b/vendor/github.com/ryanuber/go-glob/LICENSE
similarity index 89%
rename from cmd/gost/vendor/github.com/codahale/chacha20/LICENSE
rename to vendor/github.com/ryanuber/go-glob/LICENSE
index f9835c2..bdfbd95 100644
--- a/cmd/gost/vendor/github.com/codahale/chacha20/LICENSE
+++ b/vendor/github.com/ryanuber/go-glob/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2014 Coda Hale
+Copyright (c) 2014 Ryan Uber
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -9,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/ryanuber/go-glob/README.md b/vendor/github.com/ryanuber/go-glob/README.md
new file mode 100644
index 0000000..48f7fcb
--- /dev/null
+++ b/vendor/github.com/ryanuber/go-glob/README.md
@@ -0,0 +1,29 @@
+# String globbing in golang [](https://travis-ci.org/ryanuber/go-glob)
+
+`go-glob` is a single-function library implementing basic string glob support.
+
+Globs are an extremely user-friendly way of supporting string matching without
+requiring knowledge of regular expressions or Go's particular regex engine. Most
+people understand that if you put a `*` character somewhere in a string, it is
+treated as a wildcard. Surprisingly, this functionality isn't found in Go's
+standard library, except for `path.Match`, which is intended to be used while
+comparing paths (not arbitrary strings), and contains specialized logic for this
+use case. A better solution might be a POSIX basic (non-ERE) regular expression
+engine for Go, which doesn't exist currently.
+
+Example
+=======
+
+```
+package main
+
+import "github.com/ryanuber/go-glob"
+
+func main() {
+ glob.Glob("*World!", "Hello, World!") // true
+ glob.Glob("Hello,*", "Hello, World!") // true
+ glob.Glob("*ello,*", "Hello, World!") // true
+ glob.Glob("World!", "Hello, World!") // false
+ glob.Glob("/home/*", "/home/ryanuber/.bashrc") // true
+}
+```
diff --git a/vendor/github.com/ryanuber/go-glob/glob.go b/vendor/github.com/ryanuber/go-glob/glob.go
new file mode 100644
index 0000000..e67db3b
--- /dev/null
+++ b/vendor/github.com/ryanuber/go-glob/glob.go
@@ -0,0 +1,56 @@
+package glob
+
+import "strings"
+
+// The character which is treated like a glob
+const GLOB = "*"
+
+// Glob will test a string pattern, potentially containing globs, against a
+// subject string. The result is a simple true/false, determining whether or
+// not the glob pattern matched the subject text.
+func Glob(pattern, subj string) bool {
+ // Empty pattern can only match empty subject
+ if pattern == "" {
+ return subj == pattern
+ }
+
+ // If the pattern _is_ a glob, it matches everything
+ if pattern == GLOB {
+ return true
+ }
+
+ parts := strings.Split(pattern, GLOB)
+
+ if len(parts) == 1 {
+ // No globs in pattern, so test for equality
+ return subj == pattern
+ }
+
+ leadingGlob := strings.HasPrefix(pattern, GLOB)
+ trailingGlob := strings.HasSuffix(pattern, GLOB)
+ end := len(parts) - 1
+
+ // Go over the leading parts and ensure they match.
+ for i := 0; i < end; i++ {
+ idx := strings.Index(subj, parts[i])
+
+ switch i {
+ case 0:
+ // Check the first section. Requires special handling.
+ if !leadingGlob && idx != 0 {
+ return false
+ }
+ default:
+ // Check that the middle parts match.
+ if idx < 0 {
+ return false
+ }
+ }
+
+ // Trim evaluated text from subj as we loop over the pattern.
+ subj = subj[idx+len(parts[i]):]
+ }
+
+ // Reached the last section. Requires special handling.
+ return trailingGlob || strings.HasSuffix(subj, parts[end])
+}
diff --git a/cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/LICENSE b/vendor/github.com/shadowsocks/shadowsocks-go/LICENSE
similarity index 100%
rename from cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/LICENSE
rename to vendor/github.com/shadowsocks/shadowsocks-go/LICENSE
diff --git a/cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/config.go b/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/config.go
similarity index 100%
rename from cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/config.go
rename to vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/config.go
diff --git a/cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/conn.go b/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/conn.go
similarity index 100%
rename from cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/conn.go
rename to vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/conn.go
diff --git a/cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/encrypt.go b/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/encrypt.go
similarity index 100%
rename from cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/encrypt.go
rename to vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/encrypt.go
diff --git a/cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/leakybuf.go b/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/leakybuf.go
similarity index 100%
rename from cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/leakybuf.go
rename to vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/leakybuf.go
diff --git a/cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/log.go b/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/log.go
similarity index 100%
rename from cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/log.go
rename to vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/log.go
diff --git a/cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/mergesort.go b/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/mergesort.go
similarity index 100%
rename from cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/mergesort.go
rename to vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/mergesort.go
diff --git a/cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/pipe.go b/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/pipe.go
similarity index 100%
rename from cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/pipe.go
rename to vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/pipe.go
diff --git a/cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/proxy.go b/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/proxy.go
similarity index 100%
rename from cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/proxy.go
rename to vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/proxy.go
diff --git a/cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/udp.go b/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/udp.go
similarity index 100%
rename from cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/udp.go
rename to vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/udp.go
diff --git a/cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/udprelay.go b/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/udprelay.go
similarity index 100%
rename from cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/udprelay.go
rename to vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/udprelay.go
diff --git a/cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/util.go b/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/util.go
similarity index 100%
rename from cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/util.go
rename to vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/util.go
diff --git a/cmd/gost/vendor/golang.org/x/crypto/LICENSE b/vendor/golang.org/x/crypto/LICENSE
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/crypto/LICENSE
rename to vendor/golang.org/x/crypto/LICENSE
diff --git a/cmd/gost/vendor/golang.org/x/crypto/PATENTS b/vendor/golang.org/x/crypto/PATENTS
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/crypto/PATENTS
rename to vendor/golang.org/x/crypto/PATENTS
diff --git a/cmd/gost/vendor/golang.org/x/crypto/blowfish/block.go b/vendor/golang.org/x/crypto/blowfish/block.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/crypto/blowfish/block.go
rename to vendor/golang.org/x/crypto/blowfish/block.go
diff --git a/cmd/gost/vendor/golang.org/x/crypto/blowfish/cipher.go b/vendor/golang.org/x/crypto/blowfish/cipher.go
similarity index 98%
rename from cmd/gost/vendor/golang.org/x/crypto/blowfish/cipher.go
rename to vendor/golang.org/x/crypto/blowfish/cipher.go
index a73954f..2641dad 100644
--- a/cmd/gost/vendor/golang.org/x/crypto/blowfish/cipher.go
+++ b/vendor/golang.org/x/crypto/blowfish/cipher.go
@@ -6,7 +6,7 @@
package blowfish // import "golang.org/x/crypto/blowfish"
// The code is a port of Bruce Schneier's C implementation.
-// See http://www.schneier.com/blowfish.html.
+// See https://www.schneier.com/blowfish.html.
import "strconv"
diff --git a/cmd/gost/vendor/golang.org/x/crypto/blowfish/const.go b/vendor/golang.org/x/crypto/blowfish/const.go
similarity index 99%
rename from cmd/gost/vendor/golang.org/x/crypto/blowfish/const.go
rename to vendor/golang.org/x/crypto/blowfish/const.go
index 8c5ee4c..d040775 100644
--- a/cmd/gost/vendor/golang.org/x/crypto/blowfish/const.go
+++ b/vendor/golang.org/x/crypto/blowfish/const.go
@@ -4,7 +4,7 @@
// The startup permutation array and substitution boxes.
// They are the hexadecimal digits of PI; see:
-// http://www.schneier.com/code/constants.txt.
+// https://www.schneier.com/code/constants.txt.
package blowfish
diff --git a/cmd/gost/vendor/golang.org/x/crypto/cast5/cast5.go b/vendor/golang.org/x/crypto/cast5/cast5.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/crypto/cast5/cast5.go
rename to vendor/golang.org/x/crypto/cast5/cast5.go
diff --git a/vendor/golang.org/x/crypto/curve25519/const_amd64.h b/vendor/golang.org/x/crypto/curve25519/const_amd64.h
new file mode 100644
index 0000000..b3f7416
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/const_amd64.h
@@ -0,0 +1,8 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
+
+#define REDMASK51 0x0007FFFFFFFFFFFF
diff --git a/cmd/gost/vendor/golang.org/x/crypto/curve25519/const_amd64.s b/vendor/golang.org/x/crypto/curve25519/const_amd64.s
similarity index 72%
rename from cmd/gost/vendor/golang.org/x/crypto/curve25519/const_amd64.s
rename to vendor/golang.org/x/crypto/curve25519/const_amd64.s
index 797f9b0..ee7b4bd 100644
--- a/cmd/gost/vendor/golang.org/x/crypto/curve25519/const_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/const_amd64.s
@@ -3,12 +3,12 @@
// license that can be found in the LICENSE file.
// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
// +build amd64,!gccgo,!appengine
-DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF
-GLOBL ·REDMASK51(SB), 8, $8
+// These constants cannot be encoded in non-MOVQ immediates.
+// We access them directly from memory instead.
DATA ·_121666_213(SB)/8, $996687872
GLOBL ·_121666_213(SB), 8, $8
diff --git a/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s b/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
new file mode 100644
index 0000000..cd793a5
--- /dev/null
+++ b/vendor/golang.org/x/crypto/curve25519/cswap_amd64.s
@@ -0,0 +1,65 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64,!gccgo,!appengine
+
+// func cswap(inout *[4][5]uint64, v uint64)
+TEXT ·cswap(SB),7,$0
+ MOVQ inout+0(FP),DI
+ MOVQ v+8(FP),SI
+
+ SUBQ $1, SI
+ NOTQ SI
+ MOVQ SI, X15
+ PSHUFD $0x44, X15, X15
+
+ MOVOU 0(DI), X0
+ MOVOU 16(DI), X2
+ MOVOU 32(DI), X4
+ MOVOU 48(DI), X6
+ MOVOU 64(DI), X8
+ MOVOU 80(DI), X1
+ MOVOU 96(DI), X3
+ MOVOU 112(DI), X5
+ MOVOU 128(DI), X7
+ MOVOU 144(DI), X9
+
+ MOVO X1, X10
+ MOVO X3, X11
+ MOVO X5, X12
+ MOVO X7, X13
+ MOVO X9, X14
+
+ PXOR X0, X10
+ PXOR X2, X11
+ PXOR X4, X12
+ PXOR X6, X13
+ PXOR X8, X14
+ PAND X15, X10
+ PAND X15, X11
+ PAND X15, X12
+ PAND X15, X13
+ PAND X15, X14
+ PXOR X10, X0
+ PXOR X10, X1
+ PXOR X11, X2
+ PXOR X11, X3
+ PXOR X12, X4
+ PXOR X12, X5
+ PXOR X13, X6
+ PXOR X13, X7
+ PXOR X14, X8
+ PXOR X14, X9
+
+ MOVOU X0, 0(DI)
+ MOVOU X2, 16(DI)
+ MOVOU X4, 32(DI)
+ MOVOU X6, 48(DI)
+ MOVOU X8, 64(DI)
+ MOVOU X1, 80(DI)
+ MOVOU X3, 96(DI)
+ MOVOU X5, 112(DI)
+ MOVOU X7, 128(DI)
+ MOVOU X9, 144(DI)
+ RET
diff --git a/cmd/gost/vendor/golang.org/x/crypto/curve25519/curve25519.go b/vendor/golang.org/x/crypto/curve25519/curve25519.go
similarity index 98%
rename from cmd/gost/vendor/golang.org/x/crypto/curve25519/curve25519.go
rename to vendor/golang.org/x/crypto/curve25519/curve25519.go
index 6918c47..2d14c2a 100644
--- a/cmd/gost/vendor/golang.org/x/crypto/curve25519/curve25519.go
+++ b/vendor/golang.org/x/crypto/curve25519/curve25519.go
@@ -8,6 +8,10 @@
package curve25519
+import (
+ "encoding/binary"
+)
+
// This code is a port of the public domain, "ref10" implementation of
// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
@@ -50,17 +54,11 @@ func feCopy(dst, src *fieldElement) {
//
// Preconditions: b in {0,1}.
func feCSwap(f, g *fieldElement, b int32) {
- var x fieldElement
b = -b
- for i := range x {
- x[i] = b & (f[i] ^ g[i])
- }
-
for i := range f {
- f[i] ^= x[i]
- }
- for i := range g {
- g[i] ^= x[i]
+ t := b & (f[i] ^ g[i])
+ f[i] ^= t
+ g[i] ^= t
}
}
@@ -75,12 +73,7 @@ func load3(in []byte) int64 {
// load4 reads a 32-bit, little-endian value from in.
func load4(in []byte) int64 {
- var r int64
- r = int64(in[0])
- r |= int64(in[1]) << 8
- r |= int64(in[2]) << 16
- r |= int64(in[3]) << 24
- return r
+ return int64(binary.LittleEndian.Uint32(in))
}
func feFromBytes(dst *fieldElement, src *[32]byte) {
diff --git a/cmd/gost/vendor/golang.org/x/crypto/curve25519/doc.go b/vendor/golang.org/x/crypto/curve25519/doc.go
similarity index 92%
rename from cmd/gost/vendor/golang.org/x/crypto/curve25519/doc.go
rename to vendor/golang.org/x/crypto/curve25519/doc.go
index ebeea3c..da9b10d 100644
--- a/cmd/gost/vendor/golang.org/x/crypto/curve25519/doc.go
+++ b/vendor/golang.org/x/crypto/curve25519/doc.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// Package curve25519 provides an implementation of scalar multiplication on
-// the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html
+// the elliptic curve known as curve25519. See https://cr.yp.to/ecdh.html
package curve25519 // import "golang.org/x/crypto/curve25519"
// basePoint is the x coordinate of the generator of the curve.
diff --git a/cmd/gost/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s b/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
similarity index 90%
rename from cmd/gost/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
rename to vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
index 932800b..3908161 100644
--- a/cmd/gost/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/freeze_amd64.s
@@ -3,10 +3,12 @@
// license that can be found in the LICENSE file.
// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
// +build amd64,!gccgo,!appengine
+#include "const_amd64.h"
+
// func freeze(inout *[5]uint64)
TEXT ·freeze(SB),7,$0-8
MOVQ inout+0(FP), DI
@@ -16,7 +18,7 @@ TEXT ·freeze(SB),7,$0-8
MOVQ 16(DI),CX
MOVQ 24(DI),R8
MOVQ 32(DI),R9
- MOVQ ·REDMASK51(SB),AX
+ MOVQ $REDMASK51,AX
MOVQ AX,R10
SUBQ $18,R10
MOVQ $3,R11
diff --git a/cmd/gost/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s b/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
similarity index 98%
rename from cmd/gost/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
rename to vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
index ee7b36c..9e9040b 100644
--- a/cmd/gost/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/ladderstep_amd64.s
@@ -3,10 +3,12 @@
// license that can be found in the LICENSE file.
// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
// +build amd64,!gccgo,!appengine
+#include "const_amd64.h"
+
// func ladderstep(inout *[5][5]uint64)
TEXT ·ladderstep(SB),0,$296-8
MOVQ inout+0(FP),DI
@@ -118,7 +120,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 72(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -233,7 +235,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 32(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -438,7 +440,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 72(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -588,7 +590,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 32(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -728,7 +730,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 152(DI)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -843,7 +845,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 192(DI)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -993,7 +995,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 32(DI)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -1143,7 +1145,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 112(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
@@ -1329,7 +1331,7 @@ TEXT ·ladderstep(SB),0,$296-8
MULQ 192(SP)
ADDQ AX,R12
ADCQ DX,R13
- MOVQ ·REDMASK51(SB),DX
+ MOVQ $REDMASK51,DX
SHLQ $13,CX:SI
ANDQ DX,SI
SHLQ $13,R9:R8
diff --git a/cmd/gost/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go b/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go
rename to vendor/golang.org/x/crypto/curve25519/mont25519_amd64.go
diff --git a/cmd/gost/vendor/golang.org/x/crypto/curve25519/mul_amd64.s b/vendor/golang.org/x/crypto/curve25519/mul_amd64.s
similarity index 95%
rename from cmd/gost/vendor/golang.org/x/crypto/curve25519/mul_amd64.s
rename to vendor/golang.org/x/crypto/curve25519/mul_amd64.s
index 33ce57d..5ce80a2 100644
--- a/cmd/gost/vendor/golang.org/x/crypto/curve25519/mul_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/mul_amd64.s
@@ -3,10 +3,12 @@
// license that can be found in the LICENSE file.
// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
// +build amd64,!gccgo,!appengine
+#include "const_amd64.h"
+
// func mul(dest, a, b *[5]uint64)
TEXT ·mul(SB),0,$16-24
MOVQ dest+0(FP), DI
@@ -121,7 +123,7 @@ TEXT ·mul(SB),0,$16-24
MULQ 32(CX)
ADDQ AX,R14
ADCQ DX,R15
- MOVQ ·REDMASK51(SB),SI
+ MOVQ $REDMASK51,SI
SHLQ $13,R9:R8
ANDQ SI,R8
SHLQ $13,R11:R10
diff --git a/cmd/gost/vendor/golang.org/x/crypto/curve25519/square_amd64.s b/vendor/golang.org/x/crypto/curve25519/square_amd64.s
similarity index 94%
rename from cmd/gost/vendor/golang.org/x/crypto/curve25519/square_amd64.s
rename to vendor/golang.org/x/crypto/curve25519/square_amd64.s
index 3a92804..12f7373 100644
--- a/cmd/gost/vendor/golang.org/x/crypto/curve25519/square_amd64.s
+++ b/vendor/golang.org/x/crypto/curve25519/square_amd64.s
@@ -3,10 +3,12 @@
// license that can be found in the LICENSE file.
// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
// +build amd64,!gccgo,!appengine
+#include "const_amd64.h"
+
// func square(out, in *[5]uint64)
TEXT ·square(SB),7,$0-16
MOVQ out+0(FP), DI
@@ -84,7 +86,7 @@ TEXT ·square(SB),7,$0-16
MULQ 32(SI)
ADDQ AX,R13
ADCQ DX,R14
- MOVQ ·REDMASK51(SB),SI
+ MOVQ $REDMASK51,SI
SHLQ $13,R8:CX
ANDQ SI,CX
SHLQ $13,R10:R9
diff --git a/vendor/golang.org/x/crypto/ed25519/ed25519.go b/vendor/golang.org/x/crypto/ed25519/ed25519.go
new file mode 100644
index 0000000..9b07acc
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ed25519/ed25519.go
@@ -0,0 +1,181 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package ed25519 implements the Ed25519 signature algorithm. See
+// https://ed25519.cr.yp.to/.
+//
+// These functions are also compatible with the “Ed25519” function defined in
+// https://tools.ietf.org/html/draft-irtf-cfrg-eddsa-05.
+package ed25519
+
+// This code is a port of the public domain, “ref10” implementation of ed25519
+// from SUPERCOP.
+
+import (
+ "crypto"
+ cryptorand "crypto/rand"
+ "crypto/sha512"
+ "crypto/subtle"
+ "errors"
+ "io"
+ "strconv"
+
+ "golang.org/x/crypto/ed25519/internal/edwards25519"
+)
+
+const (
+ // PublicKeySize is the size, in bytes, of public keys as used in this package.
+ PublicKeySize = 32
+ // PrivateKeySize is the size, in bytes, of private keys as used in this package.
+ PrivateKeySize = 64
+ // SignatureSize is the size, in bytes, of signatures generated and verified by this package.
+ SignatureSize = 64
+)
+
+// PublicKey is the type of Ed25519 public keys.
+type PublicKey []byte
+
+// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
+type PrivateKey []byte
+
+// Public returns the PublicKey corresponding to priv.
+func (priv PrivateKey) Public() crypto.PublicKey {
+ publicKey := make([]byte, PublicKeySize)
+ copy(publicKey, priv[32:])
+ return PublicKey(publicKey)
+}
+
+// Sign signs the given message with priv.
+// Ed25519 performs two passes over messages to be signed and therefore cannot
+// handle pre-hashed messages. Thus opts.HashFunc() must return zero to
+// indicate the message hasn't been hashed. This can be achieved by passing
+// crypto.Hash(0) as the value for opts.
+func (priv PrivateKey) Sign(rand io.Reader, message []byte, opts crypto.SignerOpts) (signature []byte, err error) {
+ if opts.HashFunc() != crypto.Hash(0) {
+ return nil, errors.New("ed25519: cannot sign hashed message")
+ }
+
+ return Sign(priv, message), nil
+}
+
+// GenerateKey generates a public/private key pair using entropy from rand.
+// If rand is nil, crypto/rand.Reader will be used.
+func GenerateKey(rand io.Reader) (publicKey PublicKey, privateKey PrivateKey, err error) {
+ if rand == nil {
+ rand = cryptorand.Reader
+ }
+
+ privateKey = make([]byte, PrivateKeySize)
+ publicKey = make([]byte, PublicKeySize)
+ _, err = io.ReadFull(rand, privateKey[:32])
+ if err != nil {
+ return nil, nil, err
+ }
+
+ digest := sha512.Sum512(privateKey[:32])
+ digest[0] &= 248
+ digest[31] &= 127
+ digest[31] |= 64
+
+ var A edwards25519.ExtendedGroupElement
+ var hBytes [32]byte
+ copy(hBytes[:], digest[:])
+ edwards25519.GeScalarMultBase(&A, &hBytes)
+ var publicKeyBytes [32]byte
+ A.ToBytes(&publicKeyBytes)
+
+ copy(privateKey[32:], publicKeyBytes[:])
+ copy(publicKey, publicKeyBytes[:])
+
+ return publicKey, privateKey, nil
+}
+
+// Sign signs the message with privateKey and returns a signature. It will
+// panic if len(privateKey) is not PrivateKeySize.
+func Sign(privateKey PrivateKey, message []byte) []byte {
+ if l := len(privateKey); l != PrivateKeySize {
+ panic("ed25519: bad private key length: " + strconv.Itoa(l))
+ }
+
+ h := sha512.New()
+ h.Write(privateKey[:32])
+
+ var digest1, messageDigest, hramDigest [64]byte
+ var expandedSecretKey [32]byte
+ h.Sum(digest1[:0])
+ copy(expandedSecretKey[:], digest1[:])
+ expandedSecretKey[0] &= 248
+ expandedSecretKey[31] &= 63
+ expandedSecretKey[31] |= 64
+
+ h.Reset()
+ h.Write(digest1[32:])
+ h.Write(message)
+ h.Sum(messageDigest[:0])
+
+ var messageDigestReduced [32]byte
+ edwards25519.ScReduce(&messageDigestReduced, &messageDigest)
+ var R edwards25519.ExtendedGroupElement
+ edwards25519.GeScalarMultBase(&R, &messageDigestReduced)
+
+ var encodedR [32]byte
+ R.ToBytes(&encodedR)
+
+ h.Reset()
+ h.Write(encodedR[:])
+ h.Write(privateKey[32:])
+ h.Write(message)
+ h.Sum(hramDigest[:0])
+ var hramDigestReduced [32]byte
+ edwards25519.ScReduce(&hramDigestReduced, &hramDigest)
+
+ var s [32]byte
+ edwards25519.ScMulAdd(&s, &hramDigestReduced, &expandedSecretKey, &messageDigestReduced)
+
+ signature := make([]byte, SignatureSize)
+ copy(signature[:], encodedR[:])
+ copy(signature[32:], s[:])
+
+ return signature
+}
+
+// Verify reports whether sig is a valid signature of message by publicKey. It
+// will panic if len(publicKey) is not PublicKeySize.
+func Verify(publicKey PublicKey, message, sig []byte) bool {
+ if l := len(publicKey); l != PublicKeySize {
+ panic("ed25519: bad public key length: " + strconv.Itoa(l))
+ }
+
+ if len(sig) != SignatureSize || sig[63]&224 != 0 {
+ return false
+ }
+
+ var A edwards25519.ExtendedGroupElement
+ var publicKeyBytes [32]byte
+ copy(publicKeyBytes[:], publicKey)
+ if !A.FromBytes(&publicKeyBytes) {
+ return false
+ }
+ edwards25519.FeNeg(&A.X, &A.X)
+ edwards25519.FeNeg(&A.T, &A.T)
+
+ h := sha512.New()
+ h.Write(sig[:32])
+ h.Write(publicKey[:])
+ h.Write(message)
+ var digest [64]byte
+ h.Sum(digest[:0])
+
+ var hReduced [32]byte
+ edwards25519.ScReduce(&hReduced, &digest)
+
+ var R edwards25519.ProjectiveGroupElement
+ var b [32]byte
+ copy(b[:], sig[32:])
+ edwards25519.GeDoubleScalarMultVartime(&R, &hReduced, &A, &b)
+
+ var checkR [32]byte
+ R.ToBytes(&checkR)
+ return subtle.ConstantTimeCompare(sig[:32], checkR[:]) == 1
+}
diff --git a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
new file mode 100644
index 0000000..e39f086
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/const.go
@@ -0,0 +1,1422 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package edwards25519
+
+// These values are from the public domain, “ref10” implementation of ed25519
+// from SUPERCOP.
+
+// d is a constant in the Edwards curve equation.
+var d = FieldElement{
+ -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116,
+}
+
+// d2 is 2*d.
+var d2 = FieldElement{
+ -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199,
+}
+
+// SqrtM1 is the square-root of -1 in the field.
+var SqrtM1 = FieldElement{
+ -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482,
+}
+
+// A is a constant in the Montgomery-form of curve25519.
+var A = FieldElement{
+ 486662, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+}
+
+// bi contains precomputed multiples of the base-point. See the Ed25519 paper
+// for a discussion about how these values are used.
+var bi = [8]PreComputedGroupElement{
+ {
+ FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},
+ FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378},
+ FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546},
+ },
+ {
+ FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024},
+ FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574},
+ FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357},
+ },
+ {
+ FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380},
+ FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306},
+ FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942},
+ },
+ {
+ FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766},
+ FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701},
+ FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300},
+ },
+ {
+ FieldElement{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877},
+ FieldElement{-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951},
+ FieldElement{4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784},
+ },
+ {
+ FieldElement{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436},
+ FieldElement{25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918},
+ FieldElement{23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877},
+ },
+ {
+ FieldElement{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800},
+ FieldElement{-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305},
+ FieldElement{-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300},
+ },
+ {
+ FieldElement{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876},
+ FieldElement{-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619},
+ FieldElement{-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683},
+ },
+}
+
+// base contains precomputed multiples of the base-point. See the Ed25519 paper
+// for a discussion about how these values are used.
+var base = [32][8]PreComputedGroupElement{
+ {
+ {
+ FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},
+ FieldElement{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378},
+ FieldElement{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546},
+ },
+ {
+ FieldElement{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303},
+ FieldElement{-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081},
+ FieldElement{26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697},
+ },
+ {
+ FieldElement{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024},
+ FieldElement{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574},
+ FieldElement{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357},
+ },
+ {
+ FieldElement{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540},
+ FieldElement{23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397},
+ FieldElement{7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325},
+ },
+ {
+ FieldElement{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380},
+ FieldElement{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306},
+ FieldElement{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942},
+ },
+ {
+ FieldElement{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777},
+ FieldElement{-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737},
+ FieldElement{-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652},
+ },
+ {
+ FieldElement{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766},
+ FieldElement{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701},
+ FieldElement{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300},
+ },
+ {
+ FieldElement{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726},
+ FieldElement{-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955},
+ FieldElement{27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425},
+ },
+ },
+ {
+ {
+ FieldElement{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171},
+ FieldElement{27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510},
+ FieldElement{17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660},
+ },
+ {
+ FieldElement{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639},
+ FieldElement{29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963},
+ FieldElement{5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950},
+ },
+ {
+ FieldElement{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568},
+ FieldElement{12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335},
+ FieldElement{25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628},
+ },
+ {
+ FieldElement{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007},
+ FieldElement{-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772},
+ FieldElement{-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653},
+ },
+ {
+ FieldElement{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567},
+ FieldElement{13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686},
+ FieldElement{21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372},
+ },
+ {
+ FieldElement{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887},
+ FieldElement{-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954},
+ FieldElement{-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953},
+ },
+ {
+ FieldElement{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833},
+ FieldElement{-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532},
+ FieldElement{-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876},
+ },
+ {
+ FieldElement{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268},
+ FieldElement{33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214},
+ FieldElement{1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038},
+ },
+ },
+ {
+ {
+ FieldElement{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800},
+ FieldElement{4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645},
+ FieldElement{-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664},
+ },
+ {
+ FieldElement{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933},
+ FieldElement{-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182},
+ FieldElement{-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222},
+ },
+ {
+ FieldElement{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991},
+ FieldElement{20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880},
+ FieldElement{9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092},
+ },
+ {
+ FieldElement{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295},
+ FieldElement{19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788},
+ FieldElement{8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553},
+ },
+ {
+ FieldElement{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026},
+ FieldElement{11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347},
+ FieldElement{-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033},
+ },
+ {
+ FieldElement{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395},
+ FieldElement{-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278},
+ FieldElement{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890},
+ },
+ {
+ FieldElement{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995},
+ FieldElement{-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596},
+ FieldElement{-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891},
+ },
+ {
+ FieldElement{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060},
+ FieldElement{11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608},
+ FieldElement{-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606},
+ },
+ },
+ {
+ {
+ FieldElement{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389},
+ FieldElement{-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016},
+ FieldElement{-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341},
+ },
+ {
+ FieldElement{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505},
+ FieldElement{14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553},
+ FieldElement{-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655},
+ },
+ {
+ FieldElement{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220},
+ FieldElement{12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631},
+ FieldElement{-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099},
+ },
+ {
+ FieldElement{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556},
+ FieldElement{14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749},
+ FieldElement{236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930},
+ },
+ {
+ FieldElement{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391},
+ FieldElement{5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253},
+ FieldElement{20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066},
+ },
+ {
+ FieldElement{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958},
+ FieldElement{-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082},
+ FieldElement{-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383},
+ },
+ {
+ FieldElement{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521},
+ FieldElement{-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807},
+ FieldElement{23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948},
+ },
+ {
+ FieldElement{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134},
+ FieldElement{-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455},
+ FieldElement{27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629},
+ },
+ },
+ {
+ {
+ FieldElement{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069},
+ FieldElement{-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746},
+ FieldElement{24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919},
+ },
+ {
+ FieldElement{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837},
+ FieldElement{8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906},
+ FieldElement{-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771},
+ },
+ {
+ FieldElement{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817},
+ FieldElement{10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098},
+ FieldElement{10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409},
+ },
+ {
+ FieldElement{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504},
+ FieldElement{-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727},
+ FieldElement{28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420},
+ },
+ {
+ FieldElement{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003},
+ FieldElement{-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605},
+ FieldElement{-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384},
+ },
+ {
+ FieldElement{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701},
+ FieldElement{-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683},
+ FieldElement{29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708},
+ },
+ {
+ FieldElement{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563},
+ FieldElement{-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260},
+ FieldElement{-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387},
+ },
+ {
+ FieldElement{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672},
+ FieldElement{23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686},
+ FieldElement{-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665},
+ },
+ },
+ {
+ {
+ FieldElement{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182},
+ FieldElement{-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277},
+ FieldElement{14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628},
+ },
+ {
+ FieldElement{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474},
+ FieldElement{-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539},
+ FieldElement{-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822},
+ },
+ {
+ FieldElement{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970},
+ FieldElement{19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756},
+ FieldElement{-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508},
+ },
+ {
+ FieldElement{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683},
+ FieldElement{-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655},
+ FieldElement{-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158},
+ },
+ {
+ FieldElement{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125},
+ FieldElement{-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839},
+ FieldElement{-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664},
+ },
+ {
+ FieldElement{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294},
+ FieldElement{-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899},
+ FieldElement{-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070},
+ },
+ {
+ FieldElement{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294},
+ FieldElement{-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949},
+ FieldElement{-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083},
+ },
+ {
+ FieldElement{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420},
+ FieldElement{-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940},
+ FieldElement{29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396},
+ },
+ },
+ {
+ {
+ FieldElement{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567},
+ FieldElement{20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127},
+ FieldElement{-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294},
+ },
+ {
+ FieldElement{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887},
+ FieldElement{22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964},
+ FieldElement{16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195},
+ },
+ {
+ FieldElement{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244},
+ FieldElement{24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999},
+ FieldElement{-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762},
+ },
+ {
+ FieldElement{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274},
+ FieldElement{-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236},
+ FieldElement{-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605},
+ },
+ {
+ FieldElement{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761},
+ FieldElement{-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884},
+ FieldElement{-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482},
+ },
+ {
+ FieldElement{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638},
+ FieldElement{-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490},
+ FieldElement{-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170},
+ },
+ {
+ FieldElement{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736},
+ FieldElement{10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124},
+ FieldElement{-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392},
+ },
+ {
+ FieldElement{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029},
+ FieldElement{6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048},
+ FieldElement{28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958},
+ },
+ },
+ {
+ {
+ FieldElement{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593},
+ FieldElement{26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071},
+ FieldElement{-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692},
+ },
+ {
+ FieldElement{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687},
+ FieldElement{-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441},
+ FieldElement{-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001},
+ },
+ {
+ FieldElement{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460},
+ FieldElement{-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007},
+ FieldElement{-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762},
+ },
+ {
+ FieldElement{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005},
+ FieldElement{-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674},
+ FieldElement{4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035},
+ },
+ {
+ FieldElement{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590},
+ FieldElement{-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957},
+ FieldElement{-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812},
+ },
+ {
+ FieldElement{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740},
+ FieldElement{-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122},
+ FieldElement{-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158},
+ },
+ {
+ FieldElement{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885},
+ FieldElement{26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140},
+ FieldElement{19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857},
+ },
+ {
+ FieldElement{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155},
+ FieldElement{19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260},
+ FieldElement{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483},
+ },
+ },
+ {
+ {
+ FieldElement{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677},
+ FieldElement{32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815},
+ FieldElement{22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751},
+ },
+ {
+ FieldElement{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203},
+ FieldElement{-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208},
+ FieldElement{1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230},
+ },
+ {
+ FieldElement{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850},
+ FieldElement{-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389},
+ FieldElement{-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968},
+ },
+ {
+ FieldElement{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689},
+ FieldElement{14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880},
+ FieldElement{5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304},
+ },
+ {
+ FieldElement{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632},
+ FieldElement{-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412},
+ FieldElement{20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566},
+ },
+ {
+ FieldElement{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038},
+ FieldElement{-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232},
+ FieldElement{-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943},
+ },
+ {
+ FieldElement{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856},
+ FieldElement{23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738},
+ FieldElement{15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971},
+ },
+ {
+ FieldElement{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718},
+ FieldElement{-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697},
+ FieldElement{-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883},
+ },
+ },
+ {
+ {
+ FieldElement{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912},
+ FieldElement{-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358},
+ FieldElement{3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849},
+ },
+ {
+ FieldElement{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307},
+ FieldElement{-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977},
+ FieldElement{-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335},
+ },
+ {
+ FieldElement{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644},
+ FieldElement{-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616},
+ FieldElement{-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735},
+ },
+ {
+ FieldElement{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099},
+ FieldElement{29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341},
+ FieldElement{-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336},
+ },
+ {
+ FieldElement{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646},
+ FieldElement{31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425},
+ FieldElement{-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388},
+ },
+ {
+ FieldElement{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743},
+ FieldElement{-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822},
+ FieldElement{-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462},
+ },
+ {
+ FieldElement{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985},
+ FieldElement{9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702},
+ FieldElement{-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797},
+ },
+ {
+ FieldElement{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293},
+ FieldElement{27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100},
+ FieldElement{19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688},
+ },
+ },
+ {
+ {
+ FieldElement{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186},
+ FieldElement{2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610},
+ FieldElement{-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707},
+ },
+ {
+ FieldElement{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220},
+ FieldElement{915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025},
+ FieldElement{32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044},
+ },
+ {
+ FieldElement{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992},
+ FieldElement{-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027},
+ FieldElement{21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197},
+ },
+ {
+ FieldElement{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901},
+ FieldElement{31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952},
+ FieldElement{19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878},
+ },
+ {
+ FieldElement{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390},
+ FieldElement{32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730},
+ FieldElement{2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730},
+ },
+ {
+ FieldElement{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180},
+ FieldElement{-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272},
+ FieldElement{-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715},
+ },
+ {
+ FieldElement{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970},
+ FieldElement{-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772},
+ FieldElement{-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865},
+ },
+ {
+ FieldElement{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750},
+ FieldElement{20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373},
+ FieldElement{32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348},
+ },
+ },
+ {
+ {
+ FieldElement{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144},
+ FieldElement{-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195},
+ FieldElement{5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086},
+ },
+ {
+ FieldElement{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684},
+ FieldElement{-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518},
+ FieldElement{-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233},
+ },
+ {
+ FieldElement{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793},
+ FieldElement{-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794},
+ FieldElement{580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435},
+ },
+ {
+ FieldElement{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921},
+ FieldElement{13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518},
+ FieldElement{2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563},
+ },
+ {
+ FieldElement{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278},
+ FieldElement{-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024},
+ FieldElement{4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030},
+ },
+ {
+ FieldElement{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783},
+ FieldElement{27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717},
+ FieldElement{6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844},
+ },
+ {
+ FieldElement{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333},
+ FieldElement{16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048},
+ FieldElement{22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760},
+ },
+ {
+ FieldElement{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760},
+ FieldElement{-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757},
+ FieldElement{-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112},
+ },
+ },
+ {
+ {
+ FieldElement{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468},
+ FieldElement{3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184},
+ FieldElement{10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289},
+ },
+ {
+ FieldElement{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066},
+ FieldElement{24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882},
+ FieldElement{13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226},
+ },
+ {
+ FieldElement{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101},
+ FieldElement{29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279},
+ FieldElement{-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811},
+ },
+ {
+ FieldElement{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709},
+ FieldElement{20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714},
+ FieldElement{-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121},
+ },
+ {
+ FieldElement{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464},
+ FieldElement{12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847},
+ FieldElement{13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400},
+ },
+ {
+ FieldElement{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414},
+ FieldElement{-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158},
+ FieldElement{17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045},
+ },
+ {
+ FieldElement{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415},
+ FieldElement{-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459},
+ FieldElement{-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079},
+ },
+ {
+ FieldElement{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412},
+ FieldElement{-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743},
+ FieldElement{-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836},
+ },
+ },
+ {
+ {
+ FieldElement{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022},
+ FieldElement{18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429},
+ FieldElement{-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065},
+ },
+ {
+ FieldElement{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861},
+ FieldElement{10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000},
+ FieldElement{-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101},
+ },
+ {
+ FieldElement{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815},
+ FieldElement{29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642},
+ FieldElement{10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966},
+ },
+ {
+ FieldElement{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574},
+ FieldElement{-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742},
+ FieldElement{-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689},
+ },
+ {
+ FieldElement{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020},
+ FieldElement{-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772},
+ FieldElement{3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982},
+ },
+ {
+ FieldElement{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953},
+ FieldElement{-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218},
+ FieldElement{-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265},
+ },
+ {
+ FieldElement{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073},
+ FieldElement{-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325},
+ FieldElement{-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798},
+ },
+ {
+ FieldElement{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870},
+ FieldElement{-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863},
+ FieldElement{-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927},
+ },
+ },
+ {
+ {
+ FieldElement{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267},
+ FieldElement{-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663},
+ FieldElement{22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862},
+ },
+ {
+ FieldElement{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673},
+ FieldElement{15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943},
+ FieldElement{15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020},
+ },
+ {
+ FieldElement{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238},
+ FieldElement{11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064},
+ FieldElement{14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795},
+ },
+ {
+ FieldElement{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052},
+ FieldElement{-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904},
+ FieldElement{29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531},
+ },
+ {
+ FieldElement{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979},
+ FieldElement{-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841},
+ FieldElement{10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431},
+ },
+ {
+ FieldElement{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324},
+ FieldElement{-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940},
+ FieldElement{10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320},
+ },
+ {
+ FieldElement{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184},
+ FieldElement{14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114},
+ FieldElement{30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878},
+ },
+ {
+ FieldElement{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784},
+ FieldElement{-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091},
+ FieldElement{-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585},
+ },
+ },
+ {
+ {
+ FieldElement{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208},
+ FieldElement{10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864},
+ FieldElement{17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661},
+ },
+ {
+ FieldElement{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233},
+ FieldElement{26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212},
+ FieldElement{-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525},
+ },
+ {
+ FieldElement{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068},
+ FieldElement{9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397},
+ FieldElement{-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988},
+ },
+ {
+ FieldElement{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889},
+ FieldElement{32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038},
+ FieldElement{14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697},
+ },
+ {
+ FieldElement{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875},
+ FieldElement{-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905},
+ FieldElement{-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656},
+ },
+ {
+ FieldElement{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818},
+ FieldElement{27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714},
+ FieldElement{10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203},
+ },
+ {
+ FieldElement{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931},
+ FieldElement{-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024},
+ FieldElement{-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084},
+ },
+ {
+ FieldElement{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204},
+ FieldElement{20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817},
+ FieldElement{27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667},
+ },
+ },
+ {
+ {
+ FieldElement{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504},
+ FieldElement{-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768},
+ FieldElement{-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255},
+ },
+ {
+ FieldElement{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790},
+ FieldElement{1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438},
+ FieldElement{-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333},
+ },
+ {
+ FieldElement{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971},
+ FieldElement{31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905},
+ FieldElement{29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409},
+ },
+ {
+ FieldElement{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409},
+ FieldElement{6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499},
+ FieldElement{-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363},
+ },
+ {
+ FieldElement{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664},
+ FieldElement{-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324},
+ FieldElement{-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940},
+ },
+ {
+ FieldElement{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990},
+ FieldElement{-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914},
+ FieldElement{-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290},
+ },
+ {
+ FieldElement{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257},
+ FieldElement{-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433},
+ FieldElement{-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236},
+ },
+ {
+ FieldElement{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045},
+ FieldElement{11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093},
+ FieldElement{-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347},
+ },
+ },
+ {
+ {
+ FieldElement{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191},
+ FieldElement{-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507},
+ FieldElement{-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906},
+ },
+ {
+ FieldElement{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018},
+ FieldElement{-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109},
+ FieldElement{-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926},
+ },
+ {
+ FieldElement{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528},
+ FieldElement{8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625},
+ FieldElement{-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286},
+ },
+ {
+ FieldElement{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033},
+ FieldElement{27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866},
+ FieldElement{21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896},
+ },
+ {
+ FieldElement{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075},
+ FieldElement{26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347},
+ FieldElement{-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437},
+ },
+ {
+ FieldElement{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165},
+ FieldElement{-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588},
+ FieldElement{-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193},
+ },
+ {
+ FieldElement{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017},
+ FieldElement{-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883},
+ FieldElement{21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961},
+ },
+ {
+ FieldElement{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043},
+ FieldElement{29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663},
+ FieldElement{-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362},
+ },
+ },
+ {
+ {
+ FieldElement{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860},
+ FieldElement{2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466},
+ FieldElement{-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063},
+ },
+ {
+ FieldElement{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997},
+ FieldElement{-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295},
+ FieldElement{-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369},
+ },
+ {
+ FieldElement{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385},
+ FieldElement{18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109},
+ FieldElement{2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906},
+ },
+ {
+ FieldElement{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424},
+ FieldElement{-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185},
+ FieldElement{7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962},
+ },
+ {
+ FieldElement{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325},
+ FieldElement{10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593},
+ FieldElement{696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404},
+ },
+ {
+ FieldElement{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644},
+ FieldElement{17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801},
+ FieldElement{26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804},
+ },
+ {
+ FieldElement{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884},
+ FieldElement{-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577},
+ FieldElement{-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849},
+ },
+ {
+ FieldElement{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473},
+ FieldElement{-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644},
+ FieldElement{-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319},
+ },
+ },
+ {
+ {
+ FieldElement{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599},
+ FieldElement{-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768},
+ FieldElement{-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084},
+ },
+ {
+ FieldElement{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328},
+ FieldElement{-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369},
+ FieldElement{20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920},
+ },
+ {
+ FieldElement{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815},
+ FieldElement{-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025},
+ FieldElement{-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397},
+ },
+ {
+ FieldElement{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448},
+ FieldElement{6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981},
+ FieldElement{30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165},
+ },
+ {
+ FieldElement{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501},
+ FieldElement{17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073},
+ FieldElement{-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861},
+ },
+ {
+ FieldElement{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845},
+ FieldElement{-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211},
+ FieldElement{18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870},
+ },
+ {
+ FieldElement{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096},
+ FieldElement{33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803},
+ FieldElement{-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168},
+ },
+ {
+ FieldElement{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965},
+ FieldElement{-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505},
+ FieldElement{18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598},
+ },
+ },
+ {
+ {
+ FieldElement{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782},
+ FieldElement{5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900},
+ FieldElement{-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479},
+ },
+ {
+ FieldElement{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208},
+ FieldElement{8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232},
+ FieldElement{17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719},
+ },
+ {
+ FieldElement{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271},
+ FieldElement{-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326},
+ FieldElement{-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132},
+ },
+ {
+ FieldElement{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300},
+ FieldElement{8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570},
+ FieldElement{15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670},
+ },
+ {
+ FieldElement{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994},
+ FieldElement{-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913},
+ FieldElement{31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317},
+ },
+ {
+ FieldElement{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730},
+ FieldElement{842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096},
+ FieldElement{-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078},
+ },
+ {
+ FieldElement{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411},
+ FieldElement{-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905},
+ FieldElement{-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654},
+ },
+ {
+ FieldElement{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870},
+ FieldElement{-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498},
+ FieldElement{12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579},
+ },
+ },
+ {
+ {
+ FieldElement{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677},
+ FieldElement{10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647},
+ FieldElement{-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743},
+ },
+ {
+ FieldElement{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468},
+ FieldElement{21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375},
+ FieldElement{-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155},
+ },
+ {
+ FieldElement{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725},
+ FieldElement{-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612},
+ FieldElement{-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943},
+ },
+ {
+ FieldElement{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944},
+ FieldElement{30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928},
+ FieldElement{9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406},
+ },
+ {
+ FieldElement{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139},
+ FieldElement{-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963},
+ FieldElement{-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693},
+ },
+ {
+ FieldElement{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734},
+ FieldElement{-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680},
+ FieldElement{-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410},
+ },
+ {
+ FieldElement{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931},
+ FieldElement{-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654},
+ FieldElement{22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710},
+ },
+ {
+ FieldElement{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180},
+ FieldElement{-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684},
+ FieldElement{-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895},
+ },
+ },
+ {
+ {
+ FieldElement{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501},
+ FieldElement{-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413},
+ FieldElement{6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880},
+ },
+ {
+ FieldElement{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874},
+ FieldElement{22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962},
+ FieldElement{-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899},
+ },
+ {
+ FieldElement{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152},
+ FieldElement{9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063},
+ FieldElement{7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080},
+ },
+ {
+ FieldElement{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146},
+ FieldElement{-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183},
+ FieldElement{-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133},
+ },
+ {
+ FieldElement{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421},
+ FieldElement{-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622},
+ FieldElement{-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197},
+ },
+ {
+ FieldElement{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663},
+ FieldElement{31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753},
+ FieldElement{4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755},
+ },
+ {
+ FieldElement{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862},
+ FieldElement{-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118},
+ FieldElement{26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171},
+ },
+ {
+ FieldElement{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380},
+ FieldElement{16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824},
+ FieldElement{28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270},
+ },
+ },
+ {
+ {
+ FieldElement{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438},
+ FieldElement{-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584},
+ FieldElement{-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562},
+ },
+ {
+ FieldElement{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471},
+ FieldElement{18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610},
+ FieldElement{19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269},
+ },
+ {
+ FieldElement{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650},
+ FieldElement{14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369},
+ FieldElement{19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461},
+ },
+ {
+ FieldElement{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462},
+ FieldElement{-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793},
+ FieldElement{-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218},
+ },
+ {
+ FieldElement{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226},
+ FieldElement{18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019},
+ FieldElement{-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037},
+ },
+ {
+ FieldElement{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171},
+ FieldElement{-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132},
+ FieldElement{-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841},
+ },
+ {
+ FieldElement{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181},
+ FieldElement{-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210},
+ FieldElement{-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040},
+ },
+ {
+ FieldElement{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935},
+ FieldElement{24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105},
+ FieldElement{-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814},
+ },
+ },
+ {
+ {
+ FieldElement{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852},
+ FieldElement{5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581},
+ FieldElement{-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646},
+ },
+ {
+ FieldElement{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844},
+ FieldElement{10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025},
+ FieldElement{27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453},
+ },
+ {
+ FieldElement{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068},
+ FieldElement{4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192},
+ FieldElement{-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921},
+ },
+ {
+ FieldElement{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259},
+ FieldElement{-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426},
+ FieldElement{-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072},
+ },
+ {
+ FieldElement{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305},
+ FieldElement{13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832},
+ FieldElement{28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943},
+ },
+ {
+ FieldElement{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011},
+ FieldElement{24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447},
+ FieldElement{17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494},
+ },
+ {
+ FieldElement{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245},
+ FieldElement{-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859},
+ FieldElement{28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915},
+ },
+ {
+ FieldElement{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707},
+ FieldElement{10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848},
+ FieldElement{-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224},
+ },
+ },
+ {
+ {
+ FieldElement{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391},
+ FieldElement{15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215},
+ FieldElement{-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101},
+ },
+ {
+ FieldElement{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713},
+ FieldElement{21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849},
+ FieldElement{-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930},
+ },
+ {
+ FieldElement{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940},
+ FieldElement{-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031},
+ FieldElement{-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404},
+ },
+ {
+ FieldElement{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243},
+ FieldElement{-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116},
+ FieldElement{-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525},
+ },
+ {
+ FieldElement{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509},
+ FieldElement{-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883},
+ FieldElement{15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865},
+ },
+ {
+ FieldElement{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660},
+ FieldElement{4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273},
+ FieldElement{-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138},
+ },
+ {
+ FieldElement{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560},
+ FieldElement{-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135},
+ FieldElement{2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941},
+ },
+ {
+ FieldElement{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739},
+ FieldElement{18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756},
+ FieldElement{-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819},
+ },
+ },
+ {
+ {
+ FieldElement{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347},
+ FieldElement{-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028},
+ FieldElement{21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075},
+ },
+ {
+ FieldElement{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799},
+ FieldElement{-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609},
+ FieldElement{-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817},
+ },
+ {
+ FieldElement{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989},
+ FieldElement{-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523},
+ FieldElement{4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278},
+ },
+ {
+ FieldElement{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045},
+ FieldElement{19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377},
+ FieldElement{24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480},
+ },
+ {
+ FieldElement{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016},
+ FieldElement{510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426},
+ FieldElement{18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525},
+ },
+ {
+ FieldElement{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396},
+ FieldElement{9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080},
+ FieldElement{12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892},
+ },
+ {
+ FieldElement{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275},
+ FieldElement{11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074},
+ FieldElement{20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140},
+ },
+ {
+ FieldElement{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717},
+ FieldElement{-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101},
+ FieldElement{24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127},
+ },
+ },
+ {
+ {
+ FieldElement{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632},
+ FieldElement{-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415},
+ FieldElement{-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160},
+ },
+ {
+ FieldElement{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876},
+ FieldElement{22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625},
+ FieldElement{-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478},
+ },
+ {
+ FieldElement{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164},
+ FieldElement{26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595},
+ FieldElement{-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248},
+ },
+ {
+ FieldElement{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858},
+ FieldElement{15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193},
+ FieldElement{8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184},
+ },
+ {
+ FieldElement{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942},
+ FieldElement{-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635},
+ FieldElement{21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948},
+ },
+ {
+ FieldElement{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935},
+ FieldElement{-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415},
+ FieldElement{-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416},
+ },
+ {
+ FieldElement{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018},
+ FieldElement{4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778},
+ FieldElement{366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659},
+ },
+ {
+ FieldElement{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385},
+ FieldElement{18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503},
+ FieldElement{476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329},
+ },
+ },
+ {
+ {
+ FieldElement{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056},
+ FieldElement{-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838},
+ FieldElement{24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948},
+ },
+ {
+ FieldElement{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691},
+ FieldElement{-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118},
+ FieldElement{-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517},
+ },
+ {
+ FieldElement{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269},
+ FieldElement{-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904},
+ FieldElement{-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589},
+ },
+ {
+ FieldElement{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193},
+ FieldElement{-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910},
+ FieldElement{-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930},
+ },
+ {
+ FieldElement{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667},
+ FieldElement{25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481},
+ FieldElement{-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876},
+ },
+ {
+ FieldElement{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640},
+ FieldElement{-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278},
+ FieldElement{-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112},
+ },
+ {
+ FieldElement{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272},
+ FieldElement{17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012},
+ FieldElement{-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221},
+ },
+ {
+ FieldElement{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046},
+ FieldElement{13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345},
+ FieldElement{-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310},
+ },
+ },
+ {
+ {
+ FieldElement{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937},
+ FieldElement{31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636},
+ FieldElement{-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008},
+ },
+ {
+ FieldElement{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429},
+ FieldElement{-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576},
+ FieldElement{31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066},
+ },
+ {
+ FieldElement{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490},
+ FieldElement{-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104},
+ FieldElement{33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053},
+ },
+ {
+ FieldElement{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275},
+ FieldElement{-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511},
+ FieldElement{22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095},
+ },
+ {
+ FieldElement{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439},
+ FieldElement{23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939},
+ FieldElement{-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424},
+ },
+ {
+ FieldElement{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310},
+ FieldElement{3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608},
+ FieldElement{-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079},
+ },
+ {
+ FieldElement{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101},
+ FieldElement{21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418},
+ FieldElement{18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576},
+ },
+ {
+ FieldElement{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356},
+ FieldElement{9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996},
+ FieldElement{-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099},
+ },
+ },
+ {
+ {
+ FieldElement{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728},
+ FieldElement{-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658},
+ FieldElement{-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242},
+ },
+ {
+ FieldElement{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001},
+ FieldElement{-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766},
+ FieldElement{18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373},
+ },
+ {
+ FieldElement{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458},
+ FieldElement{-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628},
+ FieldElement{-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657},
+ },
+ {
+ FieldElement{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062},
+ FieldElement{25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616},
+ FieldElement{31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014},
+ },
+ {
+ FieldElement{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383},
+ FieldElement{-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814},
+ FieldElement{-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718},
+ },
+ {
+ FieldElement{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417},
+ FieldElement{2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222},
+ FieldElement{33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444},
+ },
+ {
+ FieldElement{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597},
+ FieldElement{23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970},
+ FieldElement{1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799},
+ },
+ {
+ FieldElement{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647},
+ FieldElement{13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511},
+ FieldElement{-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032},
+ },
+ },
+ {
+ {
+ FieldElement{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834},
+ FieldElement{-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461},
+ FieldElement{29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062},
+ },
+ {
+ FieldElement{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516},
+ FieldElement{-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547},
+ FieldElement{-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240},
+ },
+ {
+ FieldElement{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038},
+ FieldElement{-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741},
+ FieldElement{16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103},
+ },
+ {
+ FieldElement{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747},
+ FieldElement{-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323},
+ FieldElement{31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016},
+ },
+ {
+ FieldElement{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373},
+ FieldElement{15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228},
+ FieldElement{-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141},
+ },
+ {
+ FieldElement{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399},
+ FieldElement{11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831},
+ FieldElement{-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376},
+ },
+ {
+ FieldElement{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313},
+ FieldElement{-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958},
+ FieldElement{-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577},
+ },
+ {
+ FieldElement{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743},
+ FieldElement{29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684},
+ FieldElement{-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476},
+ },
+ },
+}
diff --git a/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
new file mode 100644
index 0000000..5f8b994
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ed25519/internal/edwards25519/edwards25519.go
@@ -0,0 +1,1771 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package edwards25519
+
+// This code is a port of the public domain, “ref10” implementation of ed25519
+// from SUPERCOP.
+
+// FieldElement represents an element of the field GF(2^255 - 19). An element
+// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
+// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
+// context.
+type FieldElement [10]int32
+
+var zero FieldElement
+
+func FeZero(fe *FieldElement) {
+ copy(fe[:], zero[:])
+}
+
+func FeOne(fe *FieldElement) {
+ FeZero(fe)
+ fe[0] = 1
+}
+
+func FeAdd(dst, a, b *FieldElement) {
+ dst[0] = a[0] + b[0]
+ dst[1] = a[1] + b[1]
+ dst[2] = a[2] + b[2]
+ dst[3] = a[3] + b[3]
+ dst[4] = a[4] + b[4]
+ dst[5] = a[5] + b[5]
+ dst[6] = a[6] + b[6]
+ dst[7] = a[7] + b[7]
+ dst[8] = a[8] + b[8]
+ dst[9] = a[9] + b[9]
+}
+
+func FeSub(dst, a, b *FieldElement) {
+ dst[0] = a[0] - b[0]
+ dst[1] = a[1] - b[1]
+ dst[2] = a[2] - b[2]
+ dst[3] = a[3] - b[3]
+ dst[4] = a[4] - b[4]
+ dst[5] = a[5] - b[5]
+ dst[6] = a[6] - b[6]
+ dst[7] = a[7] - b[7]
+ dst[8] = a[8] - b[8]
+ dst[9] = a[9] - b[9]
+}
+
+func FeCopy(dst, src *FieldElement) {
+ copy(dst[:], src[:])
+}
+
+// Replace (f,g) with (g,g) if b == 1;
+// replace (f,g) with (f,g) if b == 0.
+//
+// Preconditions: b in {0,1}.
+func FeCMove(f, g *FieldElement, b int32) {
+ b = -b
+ f[0] ^= b & (f[0] ^ g[0])
+ f[1] ^= b & (f[1] ^ g[1])
+ f[2] ^= b & (f[2] ^ g[2])
+ f[3] ^= b & (f[3] ^ g[3])
+ f[4] ^= b & (f[4] ^ g[4])
+ f[5] ^= b & (f[5] ^ g[5])
+ f[6] ^= b & (f[6] ^ g[6])
+ f[7] ^= b & (f[7] ^ g[7])
+ f[8] ^= b & (f[8] ^ g[8])
+ f[9] ^= b & (f[9] ^ g[9])
+}
+
+func load3(in []byte) int64 {
+ var r int64
+ r = int64(in[0])
+ r |= int64(in[1]) << 8
+ r |= int64(in[2]) << 16
+ return r
+}
+
+func load4(in []byte) int64 {
+ var r int64
+ r = int64(in[0])
+ r |= int64(in[1]) << 8
+ r |= int64(in[2]) << 16
+ r |= int64(in[3]) << 24
+ return r
+}
+
+func FeFromBytes(dst *FieldElement, src *[32]byte) {
+ h0 := load4(src[:])
+ h1 := load3(src[4:]) << 6
+ h2 := load3(src[7:]) << 5
+ h3 := load3(src[10:]) << 3
+ h4 := load3(src[13:]) << 2
+ h5 := load4(src[16:])
+ h6 := load3(src[20:]) << 7
+ h7 := load3(src[23:]) << 5
+ h8 := load3(src[26:]) << 4
+ h9 := (load3(src[29:]) & 8388607) << 2
+
+ FeCombine(dst, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+}
+
+// FeToBytes marshals h to s.
+// Preconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Write p=2^255-19; q=floor(h/p).
+// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
+//
+// Proof:
+// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
+// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
+//
+// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
+// Then 0> 25
+ q = (h[0] + q) >> 26
+ q = (h[1] + q) >> 25
+ q = (h[2] + q) >> 26
+ q = (h[3] + q) >> 25
+ q = (h[4] + q) >> 26
+ q = (h[5] + q) >> 25
+ q = (h[6] + q) >> 26
+ q = (h[7] + q) >> 25
+ q = (h[8] + q) >> 26
+ q = (h[9] + q) >> 25
+
+ // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
+ h[0] += 19 * q
+ // Goal: Output h-2^255 q, which is between 0 and 2^255-20.
+
+ carry[0] = h[0] >> 26
+ h[1] += carry[0]
+ h[0] -= carry[0] << 26
+ carry[1] = h[1] >> 25
+ h[2] += carry[1]
+ h[1] -= carry[1] << 25
+ carry[2] = h[2] >> 26
+ h[3] += carry[2]
+ h[2] -= carry[2] << 26
+ carry[3] = h[3] >> 25
+ h[4] += carry[3]
+ h[3] -= carry[3] << 25
+ carry[4] = h[4] >> 26
+ h[5] += carry[4]
+ h[4] -= carry[4] << 26
+ carry[5] = h[5] >> 25
+ h[6] += carry[5]
+ h[5] -= carry[5] << 25
+ carry[6] = h[6] >> 26
+ h[7] += carry[6]
+ h[6] -= carry[6] << 26
+ carry[7] = h[7] >> 25
+ h[8] += carry[7]
+ h[7] -= carry[7] << 25
+ carry[8] = h[8] >> 26
+ h[9] += carry[8]
+ h[8] -= carry[8] << 26
+ carry[9] = h[9] >> 25
+ h[9] -= carry[9] << 25
+ // h10 = carry9
+
+ // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
+ // Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
+ // evidently 2^255 h10-2^255 q = 0.
+ // Goal: Output h[0]+...+2^230 h[9].
+
+ s[0] = byte(h[0] >> 0)
+ s[1] = byte(h[0] >> 8)
+ s[2] = byte(h[0] >> 16)
+ s[3] = byte((h[0] >> 24) | (h[1] << 2))
+ s[4] = byte(h[1] >> 6)
+ s[5] = byte(h[1] >> 14)
+ s[6] = byte((h[1] >> 22) | (h[2] << 3))
+ s[7] = byte(h[2] >> 5)
+ s[8] = byte(h[2] >> 13)
+ s[9] = byte((h[2] >> 21) | (h[3] << 5))
+ s[10] = byte(h[3] >> 3)
+ s[11] = byte(h[3] >> 11)
+ s[12] = byte((h[3] >> 19) | (h[4] << 6))
+ s[13] = byte(h[4] >> 2)
+ s[14] = byte(h[4] >> 10)
+ s[15] = byte(h[4] >> 18)
+ s[16] = byte(h[5] >> 0)
+ s[17] = byte(h[5] >> 8)
+ s[18] = byte(h[5] >> 16)
+ s[19] = byte((h[5] >> 24) | (h[6] << 1))
+ s[20] = byte(h[6] >> 7)
+ s[21] = byte(h[6] >> 15)
+ s[22] = byte((h[6] >> 23) | (h[7] << 3))
+ s[23] = byte(h[7] >> 5)
+ s[24] = byte(h[7] >> 13)
+ s[25] = byte((h[7] >> 21) | (h[8] << 4))
+ s[26] = byte(h[8] >> 4)
+ s[27] = byte(h[8] >> 12)
+ s[28] = byte((h[8] >> 20) | (h[9] << 6))
+ s[29] = byte(h[9] >> 2)
+ s[30] = byte(h[9] >> 10)
+ s[31] = byte(h[9] >> 18)
+}
+
+func FeIsNegative(f *FieldElement) byte {
+ var s [32]byte
+ FeToBytes(&s, f)
+ return s[0] & 1
+}
+
+func FeIsNonZero(f *FieldElement) int32 {
+ var s [32]byte
+ FeToBytes(&s, f)
+ var x uint8
+ for _, b := range s {
+ x |= b
+ }
+ x |= x >> 4
+ x |= x >> 2
+ x |= x >> 1
+ return int32(x & 1)
+}
+
+// FeNeg sets h = -f
+//
+// Preconditions:
+// |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+func FeNeg(h, f *FieldElement) {
+ h[0] = -f[0]
+ h[1] = -f[1]
+ h[2] = -f[2]
+ h[3] = -f[3]
+ h[4] = -f[4]
+ h[5] = -f[5]
+ h[6] = -f[6]
+ h[7] = -f[7]
+ h[8] = -f[8]
+ h[9] = -f[9]
+}
+
+func FeCombine(h *FieldElement, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) {
+ var c0, c1, c2, c3, c4, c5, c6, c7, c8, c9 int64
+
+ /*
+ |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
+ i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
+ |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
+ i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
+ */
+
+ c0 = (h0 + (1 << 25)) >> 26
+ h1 += c0
+ h0 -= c0 << 26
+ c4 = (h4 + (1 << 25)) >> 26
+ h5 += c4
+ h4 -= c4 << 26
+ /* |h0| <= 2^25 */
+ /* |h4| <= 2^25 */
+ /* |h1| <= 1.51*2^58 */
+ /* |h5| <= 1.51*2^58 */
+
+ c1 = (h1 + (1 << 24)) >> 25
+ h2 += c1
+ h1 -= c1 << 25
+ c5 = (h5 + (1 << 24)) >> 25
+ h6 += c5
+ h5 -= c5 << 25
+ /* |h1| <= 2^24; from now on fits into int32 */
+ /* |h5| <= 2^24; from now on fits into int32 */
+ /* |h2| <= 1.21*2^59 */
+ /* |h6| <= 1.21*2^59 */
+
+ c2 = (h2 + (1 << 25)) >> 26
+ h3 += c2
+ h2 -= c2 << 26
+ c6 = (h6 + (1 << 25)) >> 26
+ h7 += c6
+ h6 -= c6 << 26
+ /* |h2| <= 2^25; from now on fits into int32 unchanged */
+ /* |h6| <= 2^25; from now on fits into int32 unchanged */
+ /* |h3| <= 1.51*2^58 */
+ /* |h7| <= 1.51*2^58 */
+
+ c3 = (h3 + (1 << 24)) >> 25
+ h4 += c3
+ h3 -= c3 << 25
+ c7 = (h7 + (1 << 24)) >> 25
+ h8 += c7
+ h7 -= c7 << 25
+ /* |h3| <= 2^24; from now on fits into int32 unchanged */
+ /* |h7| <= 2^24; from now on fits into int32 unchanged */
+ /* |h4| <= 1.52*2^33 */
+ /* |h8| <= 1.52*2^33 */
+
+ c4 = (h4 + (1 << 25)) >> 26
+ h5 += c4
+ h4 -= c4 << 26
+ c8 = (h8 + (1 << 25)) >> 26
+ h9 += c8
+ h8 -= c8 << 26
+ /* |h4| <= 2^25; from now on fits into int32 unchanged */
+ /* |h8| <= 2^25; from now on fits into int32 unchanged */
+ /* |h5| <= 1.01*2^24 */
+ /* |h9| <= 1.51*2^58 */
+
+ c9 = (h9 + (1 << 24)) >> 25
+ h0 += c9 * 19
+ h9 -= c9 << 25
+ /* |h9| <= 2^24; from now on fits into int32 unchanged */
+ /* |h0| <= 1.8*2^37 */
+
+ c0 = (h0 + (1 << 25)) >> 26
+ h1 += c0
+ h0 -= c0 << 26
+ /* |h0| <= 2^25; from now on fits into int32 unchanged */
+ /* |h1| <= 1.01*2^24 */
+
+ h[0] = int32(h0)
+ h[1] = int32(h1)
+ h[2] = int32(h2)
+ h[3] = int32(h3)
+ h[4] = int32(h4)
+ h[5] = int32(h5)
+ h[6] = int32(h6)
+ h[7] = int32(h7)
+ h[8] = int32(h8)
+ h[9] = int32(h9)
+}
+
+// FeMul calculates h = f * g
+// Can overlap h with f or g.
+//
+// Preconditions:
+// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Notes on implementation strategy:
+//
+// Using schoolbook multiplication.
+// Karatsuba would save a little in some cost models.
+//
+// Most multiplications by 2 and 19 are 32-bit precomputations;
+// cheaper than 64-bit postcomputations.
+//
+// There is one remaining multiplication by 19 in the carry chain;
+// one *19 precomputation can be merged into this,
+// but the resulting data flow is considerably less clean.
+//
+// There are 12 carries below.
+// 10 of them are 2-way parallelizable and vectorizable.
+// Can get away with 11 carries, but then data flow is much deeper.
+//
+// With tighter constraints on inputs, can squeeze carries into int32.
+func FeMul(h, f, g *FieldElement) {
+ f0 := int64(f[0])
+ f1 := int64(f[1])
+ f2 := int64(f[2])
+ f3 := int64(f[3])
+ f4 := int64(f[4])
+ f5 := int64(f[5])
+ f6 := int64(f[6])
+ f7 := int64(f[7])
+ f8 := int64(f[8])
+ f9 := int64(f[9])
+
+ f1_2 := int64(2 * f[1])
+ f3_2 := int64(2 * f[3])
+ f5_2 := int64(2 * f[5])
+ f7_2 := int64(2 * f[7])
+ f9_2 := int64(2 * f[9])
+
+ g0 := int64(g[0])
+ g1 := int64(g[1])
+ g2 := int64(g[2])
+ g3 := int64(g[3])
+ g4 := int64(g[4])
+ g5 := int64(g[5])
+ g6 := int64(g[6])
+ g7 := int64(g[7])
+ g8 := int64(g[8])
+ g9 := int64(g[9])
+
+ g1_19 := int64(19 * g[1]) /* 1.4*2^29 */
+ g2_19 := int64(19 * g[2]) /* 1.4*2^30; still ok */
+ g3_19 := int64(19 * g[3])
+ g4_19 := int64(19 * g[4])
+ g5_19 := int64(19 * g[5])
+ g6_19 := int64(19 * g[6])
+ g7_19 := int64(19 * g[7])
+ g8_19 := int64(19 * g[8])
+ g9_19 := int64(19 * g[9])
+
+ h0 := f0*g0 + f1_2*g9_19 + f2*g8_19 + f3_2*g7_19 + f4*g6_19 + f5_2*g5_19 + f6*g4_19 + f7_2*g3_19 + f8*g2_19 + f9_2*g1_19
+ h1 := f0*g1 + f1*g0 + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19
+ h2 := f0*g2 + f1_2*g1 + f2*g0 + f3_2*g9_19 + f4*g8_19 + f5_2*g7_19 + f6*g6_19 + f7_2*g5_19 + f8*g4_19 + f9_2*g3_19
+ h3 := f0*g3 + f1*g2 + f2*g1 + f3*g0 + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19
+ h4 := f0*g4 + f1_2*g3 + f2*g2 + f3_2*g1 + f4*g0 + f5_2*g9_19 + f6*g8_19 + f7_2*g7_19 + f8*g6_19 + f9_2*g5_19
+ h5 := f0*g5 + f1*g4 + f2*g3 + f3*g2 + f4*g1 + f5*g0 + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19
+ h6 := f0*g6 + f1_2*g5 + f2*g4 + f3_2*g3 + f4*g2 + f5_2*g1 + f6*g0 + f7_2*g9_19 + f8*g8_19 + f9_2*g7_19
+ h7 := f0*g7 + f1*g6 + f2*g5 + f3*g4 + f4*g3 + f5*g2 + f6*g1 + f7*g0 + f8*g9_19 + f9*g8_19
+ h8 := f0*g8 + f1_2*g7 + f2*g6 + f3_2*g5 + f4*g4 + f5_2*g3 + f6*g2 + f7_2*g1 + f8*g0 + f9_2*g9_19
+ h9 := f0*g9 + f1*g8 + f2*g7 + f3*g6 + f4*g5 + f5*g4 + f6*g3 + f7*g2 + f8*g1 + f9*g0
+
+ FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+}
+
+func feSquare(f *FieldElement) (h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 int64) {
+ f0 := int64(f[0])
+ f1 := int64(f[1])
+ f2 := int64(f[2])
+ f3 := int64(f[3])
+ f4 := int64(f[4])
+ f5 := int64(f[5])
+ f6 := int64(f[6])
+ f7 := int64(f[7])
+ f8 := int64(f[8])
+ f9 := int64(f[9])
+ f0_2 := int64(2 * f[0])
+ f1_2 := int64(2 * f[1])
+ f2_2 := int64(2 * f[2])
+ f3_2 := int64(2 * f[3])
+ f4_2 := int64(2 * f[4])
+ f5_2 := int64(2 * f[5])
+ f6_2 := int64(2 * f[6])
+ f7_2 := int64(2 * f[7])
+ f5_38 := 38 * f5 // 1.31*2^30
+ f6_19 := 19 * f6 // 1.31*2^30
+ f7_38 := 38 * f7 // 1.31*2^30
+ f8_19 := 19 * f8 // 1.31*2^30
+ f9_38 := 38 * f9 // 1.31*2^30
+
+ h0 = f0*f0 + f1_2*f9_38 + f2_2*f8_19 + f3_2*f7_38 + f4_2*f6_19 + f5*f5_38
+ h1 = f0_2*f1 + f2*f9_38 + f3_2*f8_19 + f4*f7_38 + f5_2*f6_19
+ h2 = f0_2*f2 + f1_2*f1 + f3_2*f9_38 + f4_2*f8_19 + f5_2*f7_38 + f6*f6_19
+ h3 = f0_2*f3 + f1_2*f2 + f4*f9_38 + f5_2*f8_19 + f6*f7_38
+ h4 = f0_2*f4 + f1_2*f3_2 + f2*f2 + f5_2*f9_38 + f6_2*f8_19 + f7*f7_38
+ h5 = f0_2*f5 + f1_2*f4 + f2_2*f3 + f6*f9_38 + f7_2*f8_19
+ h6 = f0_2*f6 + f1_2*f5_2 + f2_2*f4 + f3_2*f3 + f7_2*f9_38 + f8*f8_19
+ h7 = f0_2*f7 + f1_2*f6 + f2_2*f5 + f3_2*f4 + f8*f9_38
+ h8 = f0_2*f8 + f1_2*f7_2 + f2_2*f6 + f3_2*f5_2 + f4*f4 + f9*f9_38
+ h9 = f0_2*f9 + f1_2*f8 + f2_2*f7 + f3_2*f6 + f4_2*f5
+
+ return
+}
+
+// FeSquare calculates h = f*f. Can overlap h with f.
+//
+// Preconditions:
+// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+func FeSquare(h, f *FieldElement) {
+ h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f)
+ FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+}
+
+// FeSquare2 sets h = 2 * f * f
+//
+// Can overlap h with f.
+//
+// Preconditions:
+// |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+// See fe_mul.c for discussion of implementation strategy.
+func FeSquare2(h, f *FieldElement) {
+ h0, h1, h2, h3, h4, h5, h6, h7, h8, h9 := feSquare(f)
+
+ h0 += h0
+ h1 += h1
+ h2 += h2
+ h3 += h3
+ h4 += h4
+ h5 += h5
+ h6 += h6
+ h7 += h7
+ h8 += h8
+ h9 += h9
+
+ FeCombine(h, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9)
+}
+
+func FeInvert(out, z *FieldElement) {
+ var t0, t1, t2, t3 FieldElement
+ var i int
+
+ FeSquare(&t0, z) // 2^1
+ FeSquare(&t1, &t0) // 2^2
+ for i = 1; i < 2; i++ { // 2^3
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t1, z, &t1) // 2^3 + 2^0
+ FeMul(&t0, &t0, &t1) // 2^3 + 2^1 + 2^0
+ FeSquare(&t2, &t0) // 2^4 + 2^2 + 2^1
+ FeMul(&t1, &t1, &t2) // 2^4 + 2^3 + 2^2 + 2^1 + 2^0
+ FeSquare(&t2, &t1) // 5,4,3,2,1
+ for i = 1; i < 5; i++ { // 9,8,7,6,5
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1) // 9,8,7,6,5,4,3,2,1,0
+ FeSquare(&t2, &t1) // 10..1
+ for i = 1; i < 10; i++ { // 19..10
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t2, &t2, &t1) // 19..0
+ FeSquare(&t3, &t2) // 20..1
+ for i = 1; i < 20; i++ { // 39..20
+ FeSquare(&t3, &t3)
+ }
+ FeMul(&t2, &t3, &t2) // 39..0
+ FeSquare(&t2, &t2) // 40..1
+ for i = 1; i < 10; i++ { // 49..10
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1) // 49..0
+ FeSquare(&t2, &t1) // 50..1
+ for i = 1; i < 50; i++ { // 99..50
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t2, &t2, &t1) // 99..0
+ FeSquare(&t3, &t2) // 100..1
+ for i = 1; i < 100; i++ { // 199..100
+ FeSquare(&t3, &t3)
+ }
+ FeMul(&t2, &t3, &t2) // 199..0
+ FeSquare(&t2, &t2) // 200..1
+ for i = 1; i < 50; i++ { // 249..50
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1) // 249..0
+ FeSquare(&t1, &t1) // 250..1
+ for i = 1; i < 5; i++ { // 254..5
+ FeSquare(&t1, &t1)
+ }
+ FeMul(out, &t1, &t0) // 254..5,3,1,0
+}
+
+func fePow22523(out, z *FieldElement) {
+ var t0, t1, t2 FieldElement
+ var i int
+
+ FeSquare(&t0, z)
+ for i = 1; i < 1; i++ {
+ FeSquare(&t0, &t0)
+ }
+ FeSquare(&t1, &t0)
+ for i = 1; i < 2; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t1, z, &t1)
+ FeMul(&t0, &t0, &t1)
+ FeSquare(&t0, &t0)
+ for i = 1; i < 1; i++ {
+ FeSquare(&t0, &t0)
+ }
+ FeMul(&t0, &t1, &t0)
+ FeSquare(&t1, &t0)
+ for i = 1; i < 5; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t0, &t1, &t0)
+ FeSquare(&t1, &t0)
+ for i = 1; i < 10; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t1, &t1, &t0)
+ FeSquare(&t2, &t1)
+ for i = 1; i < 20; i++ {
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1)
+ FeSquare(&t1, &t1)
+ for i = 1; i < 10; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t0, &t1, &t0)
+ FeSquare(&t1, &t0)
+ for i = 1; i < 50; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t1, &t1, &t0)
+ FeSquare(&t2, &t1)
+ for i = 1; i < 100; i++ {
+ FeSquare(&t2, &t2)
+ }
+ FeMul(&t1, &t2, &t1)
+ FeSquare(&t1, &t1)
+ for i = 1; i < 50; i++ {
+ FeSquare(&t1, &t1)
+ }
+ FeMul(&t0, &t1, &t0)
+ FeSquare(&t0, &t0)
+ for i = 1; i < 2; i++ {
+ FeSquare(&t0, &t0)
+ }
+ FeMul(out, &t0, z)
+}
+
+// Group elements are members of the elliptic curve -x^2 + y^2 = 1 + d * x^2 *
+// y^2 where d = -121665/121666.
+//
+// Several representations are used:
+// ProjectiveGroupElement: (X:Y:Z) satisfying x=X/Z, y=Y/Z
+// ExtendedGroupElement: (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
+// CompletedGroupElement: ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
+// PreComputedGroupElement: (y+x,y-x,2dxy)
+
+type ProjectiveGroupElement struct {
+ X, Y, Z FieldElement
+}
+
+type ExtendedGroupElement struct {
+ X, Y, Z, T FieldElement
+}
+
+type CompletedGroupElement struct {
+ X, Y, Z, T FieldElement
+}
+
+type PreComputedGroupElement struct {
+ yPlusX, yMinusX, xy2d FieldElement
+}
+
+type CachedGroupElement struct {
+ yPlusX, yMinusX, Z, T2d FieldElement
+}
+
+func (p *ProjectiveGroupElement) Zero() {
+ FeZero(&p.X)
+ FeOne(&p.Y)
+ FeOne(&p.Z)
+}
+
+func (p *ProjectiveGroupElement) Double(r *CompletedGroupElement) {
+ var t0 FieldElement
+
+ FeSquare(&r.X, &p.X)
+ FeSquare(&r.Z, &p.Y)
+ FeSquare2(&r.T, &p.Z)
+ FeAdd(&r.Y, &p.X, &p.Y)
+ FeSquare(&t0, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.X)
+ FeSub(&r.Z, &r.Z, &r.X)
+ FeSub(&r.X, &t0, &r.Y)
+ FeSub(&r.T, &r.T, &r.Z)
+}
+
+func (p *ProjectiveGroupElement) ToBytes(s *[32]byte) {
+ var recip, x, y FieldElement
+
+ FeInvert(&recip, &p.Z)
+ FeMul(&x, &p.X, &recip)
+ FeMul(&y, &p.Y, &recip)
+ FeToBytes(s, &y)
+ s[31] ^= FeIsNegative(&x) << 7
+}
+
+func (p *ExtendedGroupElement) Zero() {
+ FeZero(&p.X)
+ FeOne(&p.Y)
+ FeOne(&p.Z)
+ FeZero(&p.T)
+}
+
+func (p *ExtendedGroupElement) Double(r *CompletedGroupElement) {
+ var q ProjectiveGroupElement
+ p.ToProjective(&q)
+ q.Double(r)
+}
+
+func (p *ExtendedGroupElement) ToCached(r *CachedGroupElement) {
+ FeAdd(&r.yPlusX, &p.Y, &p.X)
+ FeSub(&r.yMinusX, &p.Y, &p.X)
+ FeCopy(&r.Z, &p.Z)
+ FeMul(&r.T2d, &p.T, &d2)
+}
+
+func (p *ExtendedGroupElement) ToProjective(r *ProjectiveGroupElement) {
+ FeCopy(&r.X, &p.X)
+ FeCopy(&r.Y, &p.Y)
+ FeCopy(&r.Z, &p.Z)
+}
+
+func (p *ExtendedGroupElement) ToBytes(s *[32]byte) {
+ var recip, x, y FieldElement
+
+ FeInvert(&recip, &p.Z)
+ FeMul(&x, &p.X, &recip)
+ FeMul(&y, &p.Y, &recip)
+ FeToBytes(s, &y)
+ s[31] ^= FeIsNegative(&x) << 7
+}
+
+func (p *ExtendedGroupElement) FromBytes(s *[32]byte) bool {
+ var u, v, v3, vxx, check FieldElement
+
+ FeFromBytes(&p.Y, s)
+ FeOne(&p.Z)
+ FeSquare(&u, &p.Y)
+ FeMul(&v, &u, &d)
+ FeSub(&u, &u, &p.Z) // y = y^2-1
+ FeAdd(&v, &v, &p.Z) // v = dy^2+1
+
+ FeSquare(&v3, &v)
+ FeMul(&v3, &v3, &v) // v3 = v^3
+ FeSquare(&p.X, &v3)
+ FeMul(&p.X, &p.X, &v)
+ FeMul(&p.X, &p.X, &u) // x = uv^7
+
+ fePow22523(&p.X, &p.X) // x = (uv^7)^((q-5)/8)
+ FeMul(&p.X, &p.X, &v3)
+ FeMul(&p.X, &p.X, &u) // x = uv^3(uv^7)^((q-5)/8)
+
+ var tmpX, tmp2 [32]byte
+
+ FeSquare(&vxx, &p.X)
+ FeMul(&vxx, &vxx, &v)
+ FeSub(&check, &vxx, &u) // vx^2-u
+ if FeIsNonZero(&check) == 1 {
+ FeAdd(&check, &vxx, &u) // vx^2+u
+ if FeIsNonZero(&check) == 1 {
+ return false
+ }
+ FeMul(&p.X, &p.X, &SqrtM1)
+
+ FeToBytes(&tmpX, &p.X)
+ for i, v := range tmpX {
+ tmp2[31-i] = v
+ }
+ }
+
+ if FeIsNegative(&p.X) != (s[31] >> 7) {
+ FeNeg(&p.X, &p.X)
+ }
+
+ FeMul(&p.T, &p.X, &p.Y)
+ return true
+}
+
+func (p *CompletedGroupElement) ToProjective(r *ProjectiveGroupElement) {
+ FeMul(&r.X, &p.X, &p.T)
+ FeMul(&r.Y, &p.Y, &p.Z)
+ FeMul(&r.Z, &p.Z, &p.T)
+}
+
+func (p *CompletedGroupElement) ToExtended(r *ExtendedGroupElement) {
+ FeMul(&r.X, &p.X, &p.T)
+ FeMul(&r.Y, &p.Y, &p.Z)
+ FeMul(&r.Z, &p.Z, &p.T)
+ FeMul(&r.T, &p.X, &p.Y)
+}
+
+func (p *PreComputedGroupElement) Zero() {
+ FeOne(&p.yPlusX)
+ FeOne(&p.yMinusX)
+ FeZero(&p.xy2d)
+}
+
+func geAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) {
+ var t0 FieldElement
+
+ FeAdd(&r.X, &p.Y, &p.X)
+ FeSub(&r.Y, &p.Y, &p.X)
+ FeMul(&r.Z, &r.X, &q.yPlusX)
+ FeMul(&r.Y, &r.Y, &q.yMinusX)
+ FeMul(&r.T, &q.T2d, &p.T)
+ FeMul(&r.X, &p.Z, &q.Z)
+ FeAdd(&t0, &r.X, &r.X)
+ FeSub(&r.X, &r.Z, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.Y)
+ FeAdd(&r.Z, &t0, &r.T)
+ FeSub(&r.T, &t0, &r.T)
+}
+
+func geSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *CachedGroupElement) {
+ var t0 FieldElement
+
+ FeAdd(&r.X, &p.Y, &p.X)
+ FeSub(&r.Y, &p.Y, &p.X)
+ FeMul(&r.Z, &r.X, &q.yMinusX)
+ FeMul(&r.Y, &r.Y, &q.yPlusX)
+ FeMul(&r.T, &q.T2d, &p.T)
+ FeMul(&r.X, &p.Z, &q.Z)
+ FeAdd(&t0, &r.X, &r.X)
+ FeSub(&r.X, &r.Z, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.Y)
+ FeSub(&r.Z, &t0, &r.T)
+ FeAdd(&r.T, &t0, &r.T)
+}
+
+func geMixedAdd(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) {
+ var t0 FieldElement
+
+ FeAdd(&r.X, &p.Y, &p.X)
+ FeSub(&r.Y, &p.Y, &p.X)
+ FeMul(&r.Z, &r.X, &q.yPlusX)
+ FeMul(&r.Y, &r.Y, &q.yMinusX)
+ FeMul(&r.T, &q.xy2d, &p.T)
+ FeAdd(&t0, &p.Z, &p.Z)
+ FeSub(&r.X, &r.Z, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.Y)
+ FeAdd(&r.Z, &t0, &r.T)
+ FeSub(&r.T, &t0, &r.T)
+}
+
+func geMixedSub(r *CompletedGroupElement, p *ExtendedGroupElement, q *PreComputedGroupElement) {
+ var t0 FieldElement
+
+ FeAdd(&r.X, &p.Y, &p.X)
+ FeSub(&r.Y, &p.Y, &p.X)
+ FeMul(&r.Z, &r.X, &q.yMinusX)
+ FeMul(&r.Y, &r.Y, &q.yPlusX)
+ FeMul(&r.T, &q.xy2d, &p.T)
+ FeAdd(&t0, &p.Z, &p.Z)
+ FeSub(&r.X, &r.Z, &r.Y)
+ FeAdd(&r.Y, &r.Z, &r.Y)
+ FeSub(&r.Z, &t0, &r.T)
+ FeAdd(&r.T, &t0, &r.T)
+}
+
+func slide(r *[256]int8, a *[32]byte) {
+ for i := range r {
+ r[i] = int8(1 & (a[i>>3] >> uint(i&7)))
+ }
+
+ for i := range r {
+ if r[i] != 0 {
+ for b := 1; b <= 6 && i+b < 256; b++ {
+ if r[i+b] != 0 {
+ if r[i]+(r[i+b]<= -15 {
+ r[i] -= r[i+b] << uint(b)
+ for k := i + b; k < 256; k++ {
+ if r[k] == 0 {
+ r[k] = 1
+ break
+ }
+ r[k] = 0
+ }
+ } else {
+ break
+ }
+ }
+ }
+ }
+ }
+}
+
+// GeDoubleScalarMultVartime sets r = a*A + b*B
+// where a = a[0]+256*a[1]+...+256^31 a[31].
+// and b = b[0]+256*b[1]+...+256^31 b[31].
+// B is the Ed25519 base point (x,4/5) with x positive.
+func GeDoubleScalarMultVartime(r *ProjectiveGroupElement, a *[32]byte, A *ExtendedGroupElement, b *[32]byte) {
+ var aSlide, bSlide [256]int8
+ var Ai [8]CachedGroupElement // A,3A,5A,7A,9A,11A,13A,15A
+ var t CompletedGroupElement
+ var u, A2 ExtendedGroupElement
+ var i int
+
+ slide(&aSlide, a)
+ slide(&bSlide, b)
+
+ A.ToCached(&Ai[0])
+ A.Double(&t)
+ t.ToExtended(&A2)
+
+ for i := 0; i < 7; i++ {
+ geAdd(&t, &A2, &Ai[i])
+ t.ToExtended(&u)
+ u.ToCached(&Ai[i+1])
+ }
+
+ r.Zero()
+
+ for i = 255; i >= 0; i-- {
+ if aSlide[i] != 0 || bSlide[i] != 0 {
+ break
+ }
+ }
+
+ for ; i >= 0; i-- {
+ r.Double(&t)
+
+ if aSlide[i] > 0 {
+ t.ToExtended(&u)
+ geAdd(&t, &u, &Ai[aSlide[i]/2])
+ } else if aSlide[i] < 0 {
+ t.ToExtended(&u)
+ geSub(&t, &u, &Ai[(-aSlide[i])/2])
+ }
+
+ if bSlide[i] > 0 {
+ t.ToExtended(&u)
+ geMixedAdd(&t, &u, &bi[bSlide[i]/2])
+ } else if bSlide[i] < 0 {
+ t.ToExtended(&u)
+ geMixedSub(&t, &u, &bi[(-bSlide[i])/2])
+ }
+
+ t.ToProjective(r)
+ }
+}
+
+// equal returns 1 if b == c and 0 otherwise, assuming that b and c are
+// non-negative.
+func equal(b, c int32) int32 {
+ x := uint32(b ^ c)
+ x--
+ return int32(x >> 31)
+}
+
+// negative returns 1 if b < 0 and 0 otherwise.
+func negative(b int32) int32 {
+ return (b >> 31) & 1
+}
+
+func PreComputedGroupElementCMove(t, u *PreComputedGroupElement, b int32) {
+ FeCMove(&t.yPlusX, &u.yPlusX, b)
+ FeCMove(&t.yMinusX, &u.yMinusX, b)
+ FeCMove(&t.xy2d, &u.xy2d, b)
+}
+
+func selectPoint(t *PreComputedGroupElement, pos int32, b int32) {
+ var minusT PreComputedGroupElement
+ bNegative := negative(b)
+ bAbs := b - (((-bNegative) & b) << 1)
+
+ t.Zero()
+ for i := int32(0); i < 8; i++ {
+ PreComputedGroupElementCMove(t, &base[pos][i], equal(bAbs, i+1))
+ }
+ FeCopy(&minusT.yPlusX, &t.yMinusX)
+ FeCopy(&minusT.yMinusX, &t.yPlusX)
+ FeNeg(&minusT.xy2d, &t.xy2d)
+ PreComputedGroupElementCMove(t, &minusT, bNegative)
+}
+
+// GeScalarMultBase computes h = a*B, where
+// a = a[0]+256*a[1]+...+256^31 a[31]
+// B is the Ed25519 base point (x,4/5) with x positive.
+//
+// Preconditions:
+// a[31] <= 127
+func GeScalarMultBase(h *ExtendedGroupElement, a *[32]byte) {
+ var e [64]int8
+
+ for i, v := range a {
+ e[2*i] = int8(v & 15)
+ e[2*i+1] = int8((v >> 4) & 15)
+ }
+
+ // each e[i] is between 0 and 15 and e[63] is between 0 and 7.
+
+ carry := int8(0)
+ for i := 0; i < 63; i++ {
+ e[i] += carry
+ carry = (e[i] + 8) >> 4
+ e[i] -= carry << 4
+ }
+ e[63] += carry
+ // each e[i] is between -8 and 8.
+
+ h.Zero()
+ var t PreComputedGroupElement
+ var r CompletedGroupElement
+ for i := int32(1); i < 64; i += 2 {
+ selectPoint(&t, i/2, int32(e[i]))
+ geMixedAdd(&r, h, &t)
+ r.ToExtended(h)
+ }
+
+ var s ProjectiveGroupElement
+
+ h.Double(&r)
+ r.ToProjective(&s)
+ s.Double(&r)
+ r.ToProjective(&s)
+ s.Double(&r)
+ r.ToProjective(&s)
+ s.Double(&r)
+ r.ToExtended(h)
+
+ for i := int32(0); i < 64; i += 2 {
+ selectPoint(&t, i/2, int32(e[i]))
+ geMixedAdd(&r, h, &t)
+ r.ToExtended(h)
+ }
+}
+
+// The scalars are GF(2^252 + 27742317777372353535851937790883648493).
+
+// Input:
+// a[0]+256*a[1]+...+256^31*a[31] = a
+// b[0]+256*b[1]+...+256^31*b[31] = b
+// c[0]+256*c[1]+...+256^31*c[31] = c
+//
+// Output:
+// s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
+// where l = 2^252 + 27742317777372353535851937790883648493.
+func ScMulAdd(s, a, b, c *[32]byte) {
+ a0 := 2097151 & load3(a[:])
+ a1 := 2097151 & (load4(a[2:]) >> 5)
+ a2 := 2097151 & (load3(a[5:]) >> 2)
+ a3 := 2097151 & (load4(a[7:]) >> 7)
+ a4 := 2097151 & (load4(a[10:]) >> 4)
+ a5 := 2097151 & (load3(a[13:]) >> 1)
+ a6 := 2097151 & (load4(a[15:]) >> 6)
+ a7 := 2097151 & (load3(a[18:]) >> 3)
+ a8 := 2097151 & load3(a[21:])
+ a9 := 2097151 & (load4(a[23:]) >> 5)
+ a10 := 2097151 & (load3(a[26:]) >> 2)
+ a11 := (load4(a[28:]) >> 7)
+ b0 := 2097151 & load3(b[:])
+ b1 := 2097151 & (load4(b[2:]) >> 5)
+ b2 := 2097151 & (load3(b[5:]) >> 2)
+ b3 := 2097151 & (load4(b[7:]) >> 7)
+ b4 := 2097151 & (load4(b[10:]) >> 4)
+ b5 := 2097151 & (load3(b[13:]) >> 1)
+ b6 := 2097151 & (load4(b[15:]) >> 6)
+ b7 := 2097151 & (load3(b[18:]) >> 3)
+ b8 := 2097151 & load3(b[21:])
+ b9 := 2097151 & (load4(b[23:]) >> 5)
+ b10 := 2097151 & (load3(b[26:]) >> 2)
+ b11 := (load4(b[28:]) >> 7)
+ c0 := 2097151 & load3(c[:])
+ c1 := 2097151 & (load4(c[2:]) >> 5)
+ c2 := 2097151 & (load3(c[5:]) >> 2)
+ c3 := 2097151 & (load4(c[7:]) >> 7)
+ c4 := 2097151 & (load4(c[10:]) >> 4)
+ c5 := 2097151 & (load3(c[13:]) >> 1)
+ c6 := 2097151 & (load4(c[15:]) >> 6)
+ c7 := 2097151 & (load3(c[18:]) >> 3)
+ c8 := 2097151 & load3(c[21:])
+ c9 := 2097151 & (load4(c[23:]) >> 5)
+ c10 := 2097151 & (load3(c[26:]) >> 2)
+ c11 := (load4(c[28:]) >> 7)
+ var carry [23]int64
+
+ s0 := c0 + a0*b0
+ s1 := c1 + a0*b1 + a1*b0
+ s2 := c2 + a0*b2 + a1*b1 + a2*b0
+ s3 := c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0
+ s4 := c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0
+ s5 := c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0
+ s6 := c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0
+ s7 := c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0
+ s8 := c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0
+ s9 := c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0
+ s10 := c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0
+ s11 := c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0
+ s12 := a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1
+ s13 := a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2
+ s14 := a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3
+ s15 := a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4
+ s16 := a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5
+ s17 := a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6
+ s18 := a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7
+ s19 := a8*b11 + a9*b10 + a10*b9 + a11*b8
+ s20 := a9*b11 + a10*b10 + a11*b9
+ s21 := a10*b11 + a11*b10
+ s22 := a11 * b11
+ s23 := int64(0)
+
+ carry[0] = (s0 + (1 << 20)) >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[2] = (s2 + (1 << 20)) >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[4] = (s4 + (1 << 20)) >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[12] = (s12 + (1 << 20)) >> 21
+ s13 += carry[12]
+ s12 -= carry[12] << 21
+ carry[14] = (s14 + (1 << 20)) >> 21
+ s15 += carry[14]
+ s14 -= carry[14] << 21
+ carry[16] = (s16 + (1 << 20)) >> 21
+ s17 += carry[16]
+ s16 -= carry[16] << 21
+ carry[18] = (s18 + (1 << 20)) >> 21
+ s19 += carry[18]
+ s18 -= carry[18] << 21
+ carry[20] = (s20 + (1 << 20)) >> 21
+ s21 += carry[20]
+ s20 -= carry[20] << 21
+ carry[22] = (s22 + (1 << 20)) >> 21
+ s23 += carry[22]
+ s22 -= carry[22] << 21
+
+ carry[1] = (s1 + (1 << 20)) >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[3] = (s3 + (1 << 20)) >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[5] = (s5 + (1 << 20)) >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+ carry[13] = (s13 + (1 << 20)) >> 21
+ s14 += carry[13]
+ s13 -= carry[13] << 21
+ carry[15] = (s15 + (1 << 20)) >> 21
+ s16 += carry[15]
+ s15 -= carry[15] << 21
+ carry[17] = (s17 + (1 << 20)) >> 21
+ s18 += carry[17]
+ s17 -= carry[17] << 21
+ carry[19] = (s19 + (1 << 20)) >> 21
+ s20 += carry[19]
+ s19 -= carry[19] << 21
+ carry[21] = (s21 + (1 << 20)) >> 21
+ s22 += carry[21]
+ s21 -= carry[21] << 21
+
+ s11 += s23 * 666643
+ s12 += s23 * 470296
+ s13 += s23 * 654183
+ s14 -= s23 * 997805
+ s15 += s23 * 136657
+ s16 -= s23 * 683901
+ s23 = 0
+
+ s10 += s22 * 666643
+ s11 += s22 * 470296
+ s12 += s22 * 654183
+ s13 -= s22 * 997805
+ s14 += s22 * 136657
+ s15 -= s22 * 683901
+ s22 = 0
+
+ s9 += s21 * 666643
+ s10 += s21 * 470296
+ s11 += s21 * 654183
+ s12 -= s21 * 997805
+ s13 += s21 * 136657
+ s14 -= s21 * 683901
+ s21 = 0
+
+ s8 += s20 * 666643
+ s9 += s20 * 470296
+ s10 += s20 * 654183
+ s11 -= s20 * 997805
+ s12 += s20 * 136657
+ s13 -= s20 * 683901
+ s20 = 0
+
+ s7 += s19 * 666643
+ s8 += s19 * 470296
+ s9 += s19 * 654183
+ s10 -= s19 * 997805
+ s11 += s19 * 136657
+ s12 -= s19 * 683901
+ s19 = 0
+
+ s6 += s18 * 666643
+ s7 += s18 * 470296
+ s8 += s18 * 654183
+ s9 -= s18 * 997805
+ s10 += s18 * 136657
+ s11 -= s18 * 683901
+ s18 = 0
+
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[12] = (s12 + (1 << 20)) >> 21
+ s13 += carry[12]
+ s12 -= carry[12] << 21
+ carry[14] = (s14 + (1 << 20)) >> 21
+ s15 += carry[14]
+ s14 -= carry[14] << 21
+ carry[16] = (s16 + (1 << 20)) >> 21
+ s17 += carry[16]
+ s16 -= carry[16] << 21
+
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+ carry[13] = (s13 + (1 << 20)) >> 21
+ s14 += carry[13]
+ s13 -= carry[13] << 21
+ carry[15] = (s15 + (1 << 20)) >> 21
+ s16 += carry[15]
+ s15 -= carry[15] << 21
+
+ s5 += s17 * 666643
+ s6 += s17 * 470296
+ s7 += s17 * 654183
+ s8 -= s17 * 997805
+ s9 += s17 * 136657
+ s10 -= s17 * 683901
+ s17 = 0
+
+ s4 += s16 * 666643
+ s5 += s16 * 470296
+ s6 += s16 * 654183
+ s7 -= s16 * 997805
+ s8 += s16 * 136657
+ s9 -= s16 * 683901
+ s16 = 0
+
+ s3 += s15 * 666643
+ s4 += s15 * 470296
+ s5 += s15 * 654183
+ s6 -= s15 * 997805
+ s7 += s15 * 136657
+ s8 -= s15 * 683901
+ s15 = 0
+
+ s2 += s14 * 666643
+ s3 += s14 * 470296
+ s4 += s14 * 654183
+ s5 -= s14 * 997805
+ s6 += s14 * 136657
+ s7 -= s14 * 683901
+ s14 = 0
+
+ s1 += s13 * 666643
+ s2 += s13 * 470296
+ s3 += s13 * 654183
+ s4 -= s13 * 997805
+ s5 += s13 * 136657
+ s6 -= s13 * 683901
+ s13 = 0
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = (s0 + (1 << 20)) >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[2] = (s2 + (1 << 20)) >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[4] = (s4 + (1 << 20)) >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+
+ carry[1] = (s1 + (1 << 20)) >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[3] = (s3 + (1 << 20)) >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[5] = (s5 + (1 << 20)) >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = s0 >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[1] = s1 >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[2] = s2 >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[3] = s3 >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[4] = s4 >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[5] = s5 >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[6] = s6 >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[7] = s7 >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[8] = s8 >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[9] = s9 >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[10] = s10 >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[11] = s11 >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = s0 >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[1] = s1 >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[2] = s2 >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[3] = s3 >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[4] = s4 >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[5] = s5 >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[6] = s6 >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[7] = s7 >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[8] = s8 >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[9] = s9 >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[10] = s10 >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+
+ s[0] = byte(s0 >> 0)
+ s[1] = byte(s0 >> 8)
+ s[2] = byte((s0 >> 16) | (s1 << 5))
+ s[3] = byte(s1 >> 3)
+ s[4] = byte(s1 >> 11)
+ s[5] = byte((s1 >> 19) | (s2 << 2))
+ s[6] = byte(s2 >> 6)
+ s[7] = byte((s2 >> 14) | (s3 << 7))
+ s[8] = byte(s3 >> 1)
+ s[9] = byte(s3 >> 9)
+ s[10] = byte((s3 >> 17) | (s4 << 4))
+ s[11] = byte(s4 >> 4)
+ s[12] = byte(s4 >> 12)
+ s[13] = byte((s4 >> 20) | (s5 << 1))
+ s[14] = byte(s5 >> 7)
+ s[15] = byte((s5 >> 15) | (s6 << 6))
+ s[16] = byte(s6 >> 2)
+ s[17] = byte(s6 >> 10)
+ s[18] = byte((s6 >> 18) | (s7 << 3))
+ s[19] = byte(s7 >> 5)
+ s[20] = byte(s7 >> 13)
+ s[21] = byte(s8 >> 0)
+ s[22] = byte(s8 >> 8)
+ s[23] = byte((s8 >> 16) | (s9 << 5))
+ s[24] = byte(s9 >> 3)
+ s[25] = byte(s9 >> 11)
+ s[26] = byte((s9 >> 19) | (s10 << 2))
+ s[27] = byte(s10 >> 6)
+ s[28] = byte((s10 >> 14) | (s11 << 7))
+ s[29] = byte(s11 >> 1)
+ s[30] = byte(s11 >> 9)
+ s[31] = byte(s11 >> 17)
+}
+
+// Input:
+// s[0]+256*s[1]+...+256^63*s[63] = s
+//
+// Output:
+// s[0]+256*s[1]+...+256^31*s[31] = s mod l
+// where l = 2^252 + 27742317777372353535851937790883648493.
+func ScReduce(out *[32]byte, s *[64]byte) {
+ s0 := 2097151 & load3(s[:])
+ s1 := 2097151 & (load4(s[2:]) >> 5)
+ s2 := 2097151 & (load3(s[5:]) >> 2)
+ s3 := 2097151 & (load4(s[7:]) >> 7)
+ s4 := 2097151 & (load4(s[10:]) >> 4)
+ s5 := 2097151 & (load3(s[13:]) >> 1)
+ s6 := 2097151 & (load4(s[15:]) >> 6)
+ s7 := 2097151 & (load3(s[18:]) >> 3)
+ s8 := 2097151 & load3(s[21:])
+ s9 := 2097151 & (load4(s[23:]) >> 5)
+ s10 := 2097151 & (load3(s[26:]) >> 2)
+ s11 := 2097151 & (load4(s[28:]) >> 7)
+ s12 := 2097151 & (load4(s[31:]) >> 4)
+ s13 := 2097151 & (load3(s[34:]) >> 1)
+ s14 := 2097151 & (load4(s[36:]) >> 6)
+ s15 := 2097151 & (load3(s[39:]) >> 3)
+ s16 := 2097151 & load3(s[42:])
+ s17 := 2097151 & (load4(s[44:]) >> 5)
+ s18 := 2097151 & (load3(s[47:]) >> 2)
+ s19 := 2097151 & (load4(s[49:]) >> 7)
+ s20 := 2097151 & (load4(s[52:]) >> 4)
+ s21 := 2097151 & (load3(s[55:]) >> 1)
+ s22 := 2097151 & (load4(s[57:]) >> 6)
+ s23 := (load4(s[60:]) >> 3)
+
+ s11 += s23 * 666643
+ s12 += s23 * 470296
+ s13 += s23 * 654183
+ s14 -= s23 * 997805
+ s15 += s23 * 136657
+ s16 -= s23 * 683901
+ s23 = 0
+
+ s10 += s22 * 666643
+ s11 += s22 * 470296
+ s12 += s22 * 654183
+ s13 -= s22 * 997805
+ s14 += s22 * 136657
+ s15 -= s22 * 683901
+ s22 = 0
+
+ s9 += s21 * 666643
+ s10 += s21 * 470296
+ s11 += s21 * 654183
+ s12 -= s21 * 997805
+ s13 += s21 * 136657
+ s14 -= s21 * 683901
+ s21 = 0
+
+ s8 += s20 * 666643
+ s9 += s20 * 470296
+ s10 += s20 * 654183
+ s11 -= s20 * 997805
+ s12 += s20 * 136657
+ s13 -= s20 * 683901
+ s20 = 0
+
+ s7 += s19 * 666643
+ s8 += s19 * 470296
+ s9 += s19 * 654183
+ s10 -= s19 * 997805
+ s11 += s19 * 136657
+ s12 -= s19 * 683901
+ s19 = 0
+
+ s6 += s18 * 666643
+ s7 += s18 * 470296
+ s8 += s18 * 654183
+ s9 -= s18 * 997805
+ s10 += s18 * 136657
+ s11 -= s18 * 683901
+ s18 = 0
+
+ var carry [17]int64
+
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[12] = (s12 + (1 << 20)) >> 21
+ s13 += carry[12]
+ s12 -= carry[12] << 21
+ carry[14] = (s14 + (1 << 20)) >> 21
+ s15 += carry[14]
+ s14 -= carry[14] << 21
+ carry[16] = (s16 + (1 << 20)) >> 21
+ s17 += carry[16]
+ s16 -= carry[16] << 21
+
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+ carry[13] = (s13 + (1 << 20)) >> 21
+ s14 += carry[13]
+ s13 -= carry[13] << 21
+ carry[15] = (s15 + (1 << 20)) >> 21
+ s16 += carry[15]
+ s15 -= carry[15] << 21
+
+ s5 += s17 * 666643
+ s6 += s17 * 470296
+ s7 += s17 * 654183
+ s8 -= s17 * 997805
+ s9 += s17 * 136657
+ s10 -= s17 * 683901
+ s17 = 0
+
+ s4 += s16 * 666643
+ s5 += s16 * 470296
+ s6 += s16 * 654183
+ s7 -= s16 * 997805
+ s8 += s16 * 136657
+ s9 -= s16 * 683901
+ s16 = 0
+
+ s3 += s15 * 666643
+ s4 += s15 * 470296
+ s5 += s15 * 654183
+ s6 -= s15 * 997805
+ s7 += s15 * 136657
+ s8 -= s15 * 683901
+ s15 = 0
+
+ s2 += s14 * 666643
+ s3 += s14 * 470296
+ s4 += s14 * 654183
+ s5 -= s14 * 997805
+ s6 += s14 * 136657
+ s7 -= s14 * 683901
+ s14 = 0
+
+ s1 += s13 * 666643
+ s2 += s13 * 470296
+ s3 += s13 * 654183
+ s4 -= s13 * 997805
+ s5 += s13 * 136657
+ s6 -= s13 * 683901
+ s13 = 0
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = (s0 + (1 << 20)) >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[2] = (s2 + (1 << 20)) >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[4] = (s4 + (1 << 20)) >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[6] = (s6 + (1 << 20)) >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[8] = (s8 + (1 << 20)) >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[10] = (s10 + (1 << 20)) >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+
+ carry[1] = (s1 + (1 << 20)) >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[3] = (s3 + (1 << 20)) >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[5] = (s5 + (1 << 20)) >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[7] = (s7 + (1 << 20)) >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[9] = (s9 + (1 << 20)) >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[11] = (s11 + (1 << 20)) >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = s0 >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[1] = s1 >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[2] = s2 >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[3] = s3 >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[4] = s4 >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[5] = s5 >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[6] = s6 >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[7] = s7 >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[8] = s8 >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[9] = s9 >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[10] = s10 >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+ carry[11] = s11 >> 21
+ s12 += carry[11]
+ s11 -= carry[11] << 21
+
+ s0 += s12 * 666643
+ s1 += s12 * 470296
+ s2 += s12 * 654183
+ s3 -= s12 * 997805
+ s4 += s12 * 136657
+ s5 -= s12 * 683901
+ s12 = 0
+
+ carry[0] = s0 >> 21
+ s1 += carry[0]
+ s0 -= carry[0] << 21
+ carry[1] = s1 >> 21
+ s2 += carry[1]
+ s1 -= carry[1] << 21
+ carry[2] = s2 >> 21
+ s3 += carry[2]
+ s2 -= carry[2] << 21
+ carry[3] = s3 >> 21
+ s4 += carry[3]
+ s3 -= carry[3] << 21
+ carry[4] = s4 >> 21
+ s5 += carry[4]
+ s4 -= carry[4] << 21
+ carry[5] = s5 >> 21
+ s6 += carry[5]
+ s5 -= carry[5] << 21
+ carry[6] = s6 >> 21
+ s7 += carry[6]
+ s6 -= carry[6] << 21
+ carry[7] = s7 >> 21
+ s8 += carry[7]
+ s7 -= carry[7] << 21
+ carry[8] = s8 >> 21
+ s9 += carry[8]
+ s8 -= carry[8] << 21
+ carry[9] = s9 >> 21
+ s10 += carry[9]
+ s9 -= carry[9] << 21
+ carry[10] = s10 >> 21
+ s11 += carry[10]
+ s10 -= carry[10] << 21
+
+ out[0] = byte(s0 >> 0)
+ out[1] = byte(s0 >> 8)
+ out[2] = byte((s0 >> 16) | (s1 << 5))
+ out[3] = byte(s1 >> 3)
+ out[4] = byte(s1 >> 11)
+ out[5] = byte((s1 >> 19) | (s2 << 2))
+ out[6] = byte(s2 >> 6)
+ out[7] = byte((s2 >> 14) | (s3 << 7))
+ out[8] = byte(s3 >> 1)
+ out[9] = byte(s3 >> 9)
+ out[10] = byte((s3 >> 17) | (s4 << 4))
+ out[11] = byte(s4 >> 4)
+ out[12] = byte(s4 >> 12)
+ out[13] = byte((s4 >> 20) | (s5 << 1))
+ out[14] = byte(s5 >> 7)
+ out[15] = byte((s5 >> 15) | (s6 << 6))
+ out[16] = byte(s6 >> 2)
+ out[17] = byte(s6 >> 10)
+ out[18] = byte((s6 >> 18) | (s7 << 3))
+ out[19] = byte(s7 >> 5)
+ out[20] = byte(s7 >> 13)
+ out[21] = byte(s8 >> 0)
+ out[22] = byte(s8 >> 8)
+ out[23] = byte((s8 >> 16) | (s9 << 5))
+ out[24] = byte(s9 >> 3)
+ out[25] = byte(s9 >> 11)
+ out[26] = byte((s9 >> 19) | (s10 << 2))
+ out[27] = byte(s10 >> 6)
+ out[28] = byte((s10 >> 14) | (s11 << 7))
+ out[29] = byte(s11 >> 1)
+ out[30] = byte(s11 >> 9)
+ out[31] = byte(s11 >> 17)
+}
diff --git a/cmd/gost/vendor/golang.org/x/crypto/hkdf/hkdf.go b/vendor/golang.org/x/crypto/hkdf/hkdf.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/crypto/hkdf/hkdf.go
rename to vendor/golang.org/x/crypto/hkdf/hkdf.go
diff --git a/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go
new file mode 100644
index 0000000..1e1dff5
--- /dev/null
+++ b/vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go
@@ -0,0 +1,149 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package secretbox encrypts and authenticates small messages.
+
+Secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with
+secret-key cryptography. The length of messages is not hidden.
+
+It is the caller's responsibility to ensure the uniqueness of nonces—for
+example, by using nonce 1 for the first message, nonce 2 for the second
+message, etc. Nonces are long enough that randomly generated nonces have
+negligible risk of collision.
+
+This package is interoperable with NaCl: https://nacl.cr.yp.to/secretbox.html.
+*/
+package secretbox // import "golang.org/x/crypto/nacl/secretbox"
+
+import (
+ "golang.org/x/crypto/poly1305"
+ "golang.org/x/crypto/salsa20/salsa"
+)
+
+// Overhead is the number of bytes of overhead when boxing a message.
+const Overhead = poly1305.TagSize
+
+// setup produces a sub-key and Salsa20 counter given a nonce and key.
+func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) {
+ // We use XSalsa20 for encryption so first we need to generate a
+ // key and nonce with HSalsa20.
+ var hNonce [16]byte
+ copy(hNonce[:], nonce[:])
+ salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma)
+
+ // The final 8 bytes of the original nonce form the new nonce.
+ copy(counter[:], nonce[16:])
+}
+
+// sliceForAppend takes a slice and a requested number of bytes. It returns a
+// slice with the contents of the given slice followed by that many bytes and a
+// second slice that aliases into it and contains only the extra bytes. If the
+// original slice has sufficient capacity then no allocation is performed.
+func sliceForAppend(in []byte, n int) (head, tail []byte) {
+ if total := len(in) + n; cap(in) >= total {
+ head = in[:total]
+ } else {
+ head = make([]byte, total)
+ copy(head, in)
+ }
+ tail = head[len(in):]
+ return
+}
+
+// Seal appends an encrypted and authenticated copy of message to out, which
+// must not overlap message. The key and nonce pair must be unique for each
+// distinct message and the output will be Overhead bytes longer than message.
+func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte {
+ var subKey [32]byte
+ var counter [16]byte
+ setup(&subKey, &counter, nonce, key)
+
+ // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since
+ // Salsa20 works with 64-byte blocks, we also generate 32 bytes of
+ // keystream as a side effect.
+ var firstBlock [64]byte
+ salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey)
+
+ var poly1305Key [32]byte
+ copy(poly1305Key[:], firstBlock[:])
+
+ ret, out := sliceForAppend(out, len(message)+poly1305.TagSize)
+
+ // We XOR up to 32 bytes of message with the keystream generated from
+ // the first block.
+ firstMessageBlock := message
+ if len(firstMessageBlock) > 32 {
+ firstMessageBlock = firstMessageBlock[:32]
+ }
+
+ tagOut := out
+ out = out[poly1305.TagSize:]
+ for i, x := range firstMessageBlock {
+ out[i] = firstBlock[32+i] ^ x
+ }
+ message = message[len(firstMessageBlock):]
+ ciphertext := out
+ out = out[len(firstMessageBlock):]
+
+ // Now encrypt the rest.
+ counter[8] = 1
+ salsa.XORKeyStream(out, message, &counter, &subKey)
+
+ var tag [poly1305.TagSize]byte
+ poly1305.Sum(&tag, ciphertext, &poly1305Key)
+ copy(tagOut, tag[:])
+
+ return ret
+}
+
+// Open authenticates and decrypts a box produced by Seal and appends the
+// message to out, which must not overlap box. The output will be Overhead
+// bytes smaller than box.
+func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) {
+ if len(box) < Overhead {
+ return nil, false
+ }
+
+ var subKey [32]byte
+ var counter [16]byte
+ setup(&subKey, &counter, nonce, key)
+
+ // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since
+ // Salsa20 works with 64-byte blocks, we also generate 32 bytes of
+ // keystream as a side effect.
+ var firstBlock [64]byte
+ salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey)
+
+ var poly1305Key [32]byte
+ copy(poly1305Key[:], firstBlock[:])
+ var tag [poly1305.TagSize]byte
+ copy(tag[:], box)
+
+ if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) {
+ return nil, false
+ }
+
+ ret, out := sliceForAppend(out, len(box)-Overhead)
+
+ // We XOR up to 32 bytes of box with the keystream generated from
+ // the first block.
+ box = box[Overhead:]
+ firstMessageBlock := box
+ if len(firstMessageBlock) > 32 {
+ firstMessageBlock = firstMessageBlock[:32]
+ }
+ for i, x := range firstMessageBlock {
+ out[i] = firstBlock[32+i] ^ x
+ }
+
+ box = box[len(firstMessageBlock):]
+ out = out[len(firstMessageBlock):]
+
+ // Now decrypt the rest.
+ counter[8] = 1
+ salsa.XORKeyStream(out, box, &counter, &subKey)
+
+ return ret, true
+}
diff --git a/cmd/gost/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go b/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
rename to vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go
diff --git a/vendor/golang.org/x/crypto/poly1305/poly1305.go b/vendor/golang.org/x/crypto/poly1305/poly1305.go
new file mode 100644
index 0000000..f562fa5
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/poly1305.go
@@ -0,0 +1,33 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package poly1305 implements Poly1305 one-time message authentication code as
+specified in https://cr.yp.to/mac/poly1305-20050329.pdf.
+
+Poly1305 is a fast, one-time authentication function. It is infeasible for an
+attacker to generate an authenticator for a message without the key. However, a
+key must only be used for a single message. Authenticating two different
+messages with the same key allows an attacker to forge authenticators for other
+messages with the same key.
+
+Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was
+used with a fixed key in order to generate one-time keys from an nonce.
+However, in this package AES isn't used and the one-time key is specified
+directly.
+*/
+package poly1305 // import "golang.org/x/crypto/poly1305"
+
+import "crypto/subtle"
+
+// TagSize is the size, in bytes, of a poly1305 authenticator.
+const TagSize = 16
+
+// Verify returns true if mac is a valid authenticator for m with the given
+// key.
+func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
+ var tmp [16]byte
+ Sum(&tmp, m, key)
+ return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1
+}
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.go b/vendor/golang.org/x/crypto/poly1305/sum_amd64.go
new file mode 100644
index 0000000..4dd72fe
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/sum_amd64.go
@@ -0,0 +1,22 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64,!gccgo,!appengine
+
+package poly1305
+
+// This function is implemented in sum_amd64.s
+//go:noescape
+func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
+
+// Sum generates an authenticator for m using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
+ var mPtr *byte
+ if len(m) > 0 {
+ mPtr = &m[0]
+ }
+ poly1305(out, mPtr, uint64(len(m)), key)
+}
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_amd64.s b/vendor/golang.org/x/crypto/poly1305/sum_amd64.s
new file mode 100644
index 0000000..2edae63
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/sum_amd64.s
@@ -0,0 +1,125 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64,!gccgo,!appengine
+
+#include "textflag.h"
+
+#define POLY1305_ADD(msg, h0, h1, h2) \
+ ADDQ 0(msg), h0; \
+ ADCQ 8(msg), h1; \
+ ADCQ $1, h2; \
+ LEAQ 16(msg), msg
+
+#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \
+ MOVQ r0, AX; \
+ MULQ h0; \
+ MOVQ AX, t0; \
+ MOVQ DX, t1; \
+ MOVQ r0, AX; \
+ MULQ h1; \
+ ADDQ AX, t1; \
+ ADCQ $0, DX; \
+ MOVQ r0, t2; \
+ IMULQ h2, t2; \
+ ADDQ DX, t2; \
+ \
+ MOVQ r1, AX; \
+ MULQ h0; \
+ ADDQ AX, t1; \
+ ADCQ $0, DX; \
+ MOVQ DX, h0; \
+ MOVQ r1, t3; \
+ IMULQ h2, t3; \
+ MOVQ r1, AX; \
+ MULQ h1; \
+ ADDQ AX, t2; \
+ ADCQ DX, t3; \
+ ADDQ h0, t2; \
+ ADCQ $0, t3; \
+ \
+ MOVQ t0, h0; \
+ MOVQ t1, h1; \
+ MOVQ t2, h2; \
+ ANDQ $3, h2; \
+ MOVQ t2, t0; \
+ ANDQ $0xFFFFFFFFFFFFFFFC, t0; \
+ ADDQ t0, h0; \
+ ADCQ t3, h1; \
+ ADCQ $0, h2; \
+ SHRQ $2, t3, t2; \
+ SHRQ $2, t3; \
+ ADDQ t2, h0; \
+ ADCQ t3, h1; \
+ ADCQ $0, h2
+
+DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
+DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
+GLOBL ·poly1305Mask<>(SB), RODATA, $16
+
+// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
+TEXT ·poly1305(SB), $0-32
+ MOVQ out+0(FP), DI
+ MOVQ m+8(FP), SI
+ MOVQ mlen+16(FP), R15
+ MOVQ key+24(FP), AX
+
+ MOVQ 0(AX), R11
+ MOVQ 8(AX), R12
+ ANDQ ·poly1305Mask<>(SB), R11 // r0
+ ANDQ ·poly1305Mask<>+8(SB), R12 // r1
+ XORQ R8, R8 // h0
+ XORQ R9, R9 // h1
+ XORQ R10, R10 // h2
+
+ CMPQ R15, $16
+ JB bytes_between_0_and_15
+
+loop:
+ POLY1305_ADD(SI, R8, R9, R10)
+
+multiply:
+ POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14)
+ SUBQ $16, R15
+ CMPQ R15, $16
+ JAE loop
+
+bytes_between_0_and_15:
+ TESTQ R15, R15
+ JZ done
+ MOVQ $1, BX
+ XORQ CX, CX
+ XORQ R13, R13
+ ADDQ R15, SI
+
+flush_buffer:
+ SHLQ $8, BX, CX
+ SHLQ $8, BX
+ MOVB -1(SI), R13
+ XORQ R13, BX
+ DECQ SI
+ DECQ R15
+ JNZ flush_buffer
+
+ ADDQ BX, R8
+ ADCQ CX, R9
+ ADCQ $0, R10
+ MOVQ $16, R15
+ JMP multiply
+
+done:
+ MOVQ R8, AX
+ MOVQ R9, BX
+ SUBQ $0xFFFFFFFFFFFFFFFB, AX
+ SBBQ $0xFFFFFFFFFFFFFFFF, BX
+ SBBQ $3, R10
+ CMOVQCS R8, AX
+ CMOVQCS R9, BX
+ MOVQ key+24(FP), R8
+ ADDQ 16(R8), AX
+ ADCQ 24(R8), BX
+
+ MOVQ AX, 0(DI)
+ MOVQ BX, 8(DI)
+ RET
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_arm.go b/vendor/golang.org/x/crypto/poly1305/sum_arm.go
new file mode 100644
index 0000000..5dc321c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/sum_arm.go
@@ -0,0 +1,22 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build arm,!gccgo,!appengine,!nacl
+
+package poly1305
+
+// This function is implemented in sum_arm.s
+//go:noescape
+func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte)
+
+// Sum generates an authenticator for m using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
+ var mPtr *byte
+ if len(m) > 0 {
+ mPtr = &m[0]
+ }
+ poly1305_auth_armv6(out, mPtr, uint32(len(m)), key)
+}
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_arm.s b/vendor/golang.org/x/crypto/poly1305/sum_arm.s
new file mode 100644
index 0000000..f70b4ac
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/sum_arm.s
@@ -0,0 +1,427 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build arm,!gccgo,!appengine,!nacl
+
+#include "textflag.h"
+
+// This code was translated into a form compatible with 5a from the public
+// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305.
+
+DATA ·poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff
+DATA ·poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03
+DATA ·poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
+DATA ·poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
+DATA ·poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff
+GLOBL ·poly1305_init_constants_armv6<>(SB), 8, $20
+
+// Warning: the linker may use R11 to synthesize certain instructions. Please
+// take care and verify that no synthetic instructions use it.
+
+TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0
+ // Needs 16 bytes of stack and 64 bytes of space pointed to by R0. (It
+ // might look like it's only 60 bytes of space but the final four bytes
+ // will be written by another function.) We need to skip over four
+ // bytes of stack because that's saving the value of 'g'.
+ ADD $4, R13, R8
+ MOVM.IB [R4-R7], (R8)
+ MOVM.IA.W (R1), [R2-R5]
+ MOVW $·poly1305_init_constants_armv6<>(SB), R7
+ MOVW R2, R8
+ MOVW R2>>26, R9
+ MOVW R3>>20, g
+ MOVW R4>>14, R11
+ MOVW R5>>8, R12
+ ORR R3<<6, R9, R9
+ ORR R4<<12, g, g
+ ORR R5<<18, R11, R11
+ MOVM.IA (R7), [R2-R6]
+ AND R8, R2, R2
+ AND R9, R3, R3
+ AND g, R4, R4
+ AND R11, R5, R5
+ AND R12, R6, R6
+ MOVM.IA.W [R2-R6], (R0)
+ EOR R2, R2, R2
+ EOR R3, R3, R3
+ EOR R4, R4, R4
+ EOR R5, R5, R5
+ EOR R6, R6, R6
+ MOVM.IA.W [R2-R6], (R0)
+ MOVM.IA.W (R1), [R2-R5]
+ MOVM.IA [R2-R6], (R0)
+ ADD $20, R13, R0
+ MOVM.DA (R0), [R4-R7]
+ RET
+
+#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \
+ MOVBU (offset+0)(Rsrc), Rtmp; \
+ MOVBU Rtmp, (offset+0)(Rdst); \
+ MOVBU (offset+1)(Rsrc), Rtmp; \
+ MOVBU Rtmp, (offset+1)(Rdst); \
+ MOVBU (offset+2)(Rsrc), Rtmp; \
+ MOVBU Rtmp, (offset+2)(Rdst); \
+ MOVBU (offset+3)(Rsrc), Rtmp; \
+ MOVBU Rtmp, (offset+3)(Rdst)
+
+TEXT poly1305_blocks_armv6<>(SB), NOSPLIT, $0
+ // Needs 24 bytes of stack for saved registers and then 88 bytes of
+ // scratch space after that. We assume that 24 bytes at (R13) have
+ // already been used: four bytes for the link register saved in the
+ // prelude of poly1305_auth_armv6, four bytes for saving the value of g
+ // in that function and 16 bytes of scratch space used around
+ // poly1305_finish_ext_armv6_skip1.
+ ADD $24, R13, R12
+ MOVM.IB [R4-R8, R14], (R12)
+ MOVW R0, 88(R13)
+ MOVW R1, 92(R13)
+ MOVW R2, 96(R13)
+ MOVW R1, R14
+ MOVW R2, R12
+ MOVW 56(R0), R8
+ WORD $0xe1180008 // TST R8, R8 not working see issue 5921
+ EOR R6, R6, R6
+ MOVW.EQ $(1<<24), R6
+ MOVW R6, 84(R13)
+ ADD $116, R13, g
+ MOVM.IA (R0), [R0-R9]
+ MOVM.IA [R0-R4], (g)
+ CMP $16, R12
+ BLO poly1305_blocks_armv6_done
+
+poly1305_blocks_armv6_mainloop:
+ WORD $0xe31e0003 // TST R14, #3 not working see issue 5921
+ BEQ poly1305_blocks_armv6_mainloop_aligned
+ ADD $100, R13, g
+ MOVW_UNALIGNED(R14, g, R0, 0)
+ MOVW_UNALIGNED(R14, g, R0, 4)
+ MOVW_UNALIGNED(R14, g, R0, 8)
+ MOVW_UNALIGNED(R14, g, R0, 12)
+ MOVM.IA (g), [R0-R3]
+ ADD $16, R14
+ B poly1305_blocks_armv6_mainloop_loaded
+
+poly1305_blocks_armv6_mainloop_aligned:
+ MOVM.IA.W (R14), [R0-R3]
+
+poly1305_blocks_armv6_mainloop_loaded:
+ MOVW R0>>26, g
+ MOVW R1>>20, R11
+ MOVW R2>>14, R12
+ MOVW R14, 92(R13)
+ MOVW R3>>8, R4
+ ORR R1<<6, g, g
+ ORR R2<<12, R11, R11
+ ORR R3<<18, R12, R12
+ BIC $0xfc000000, R0, R0
+ BIC $0xfc000000, g, g
+ MOVW 84(R13), R3
+ BIC $0xfc000000, R11, R11
+ BIC $0xfc000000, R12, R12
+ ADD R0, R5, R5
+ ADD g, R6, R6
+ ORR R3, R4, R4
+ ADD R11, R7, R7
+ ADD $116, R13, R14
+ ADD R12, R8, R8
+ ADD R4, R9, R9
+ MOVM.IA (R14), [R0-R4]
+ MULLU R4, R5, (R11, g)
+ MULLU R3, R5, (R14, R12)
+ MULALU R3, R6, (R11, g)
+ MULALU R2, R6, (R14, R12)
+ MULALU R2, R7, (R11, g)
+ MULALU R1, R7, (R14, R12)
+ ADD R4<<2, R4, R4
+ ADD R3<<2, R3, R3
+ MULALU R1, R8, (R11, g)
+ MULALU R0, R8, (R14, R12)
+ MULALU R0, R9, (R11, g)
+ MULALU R4, R9, (R14, R12)
+ MOVW g, 76(R13)
+ MOVW R11, 80(R13)
+ MOVW R12, 68(R13)
+ MOVW R14, 72(R13)
+ MULLU R2, R5, (R11, g)
+ MULLU R1, R5, (R14, R12)
+ MULALU R1, R6, (R11, g)
+ MULALU R0, R6, (R14, R12)
+ MULALU R0, R7, (R11, g)
+ MULALU R4, R7, (R14, R12)
+ ADD R2<<2, R2, R2
+ ADD R1<<2, R1, R1
+ MULALU R4, R8, (R11, g)
+ MULALU R3, R8, (R14, R12)
+ MULALU R3, R9, (R11, g)
+ MULALU R2, R9, (R14, R12)
+ MOVW g, 60(R13)
+ MOVW R11, 64(R13)
+ MOVW R12, 52(R13)
+ MOVW R14, 56(R13)
+ MULLU R0, R5, (R11, g)
+ MULALU R4, R6, (R11, g)
+ MULALU R3, R7, (R11, g)
+ MULALU R2, R8, (R11, g)
+ MULALU R1, R9, (R11, g)
+ ADD $52, R13, R0
+ MOVM.IA (R0), [R0-R7]
+ MOVW g>>26, R12
+ MOVW R4>>26, R14
+ ORR R11<<6, R12, R12
+ ORR R5<<6, R14, R14
+ BIC $0xfc000000, g, g
+ BIC $0xfc000000, R4, R4
+ ADD.S R12, R0, R0
+ ADC $0, R1, R1
+ ADD.S R14, R6, R6
+ ADC $0, R7, R7
+ MOVW R0>>26, R12
+ MOVW R6>>26, R14
+ ORR R1<<6, R12, R12
+ ORR R7<<6, R14, R14
+ BIC $0xfc000000, R0, R0
+ BIC $0xfc000000, R6, R6
+ ADD R14<<2, R14, R14
+ ADD.S R12, R2, R2
+ ADC $0, R3, R3
+ ADD R14, g, g
+ MOVW R2>>26, R12
+ MOVW g>>26, R14
+ ORR R3<<6, R12, R12
+ BIC $0xfc000000, g, R5
+ BIC $0xfc000000, R2, R7
+ ADD R12, R4, R4
+ ADD R14, R0, R0
+ MOVW R4>>26, R12
+ BIC $0xfc000000, R4, R8
+ ADD R12, R6, R9
+ MOVW 96(R13), R12
+ MOVW 92(R13), R14
+ MOVW R0, R6
+ CMP $32, R12
+ SUB $16, R12, R12
+ MOVW R12, 96(R13)
+ BHS poly1305_blocks_armv6_mainloop
+
+poly1305_blocks_armv6_done:
+ MOVW 88(R13), R12
+ MOVW R5, 20(R12)
+ MOVW R6, 24(R12)
+ MOVW R7, 28(R12)
+ MOVW R8, 32(R12)
+ MOVW R9, 36(R12)
+ ADD $48, R13, R0
+ MOVM.DA (R0), [R4-R8, R14]
+ RET
+
+#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \
+ MOVBU.P 1(Rsrc), Rtmp; \
+ MOVBU.P Rtmp, 1(Rdst); \
+ MOVBU.P 1(Rsrc), Rtmp; \
+ MOVBU.P Rtmp, 1(Rdst)
+
+#define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \
+ MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \
+ MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp)
+
+// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key)
+TEXT ·poly1305_auth_armv6(SB), $196-16
+ // The value 196, just above, is the sum of 64 (the size of the context
+ // structure) and 132 (the amount of stack needed).
+ //
+ // At this point, the stack pointer (R13) has been moved down. It
+ // points to the saved link register and there's 196 bytes of free
+ // space above it.
+ //
+ // The stack for this function looks like:
+ //
+ // +---------------------
+ // |
+ // | 64 bytes of context structure
+ // |
+ // +---------------------
+ // |
+ // | 112 bytes for poly1305_blocks_armv6
+ // |
+ // +---------------------
+ // | 16 bytes of final block, constructed at
+ // | poly1305_finish_ext_armv6_skip8
+ // +---------------------
+ // | four bytes of saved 'g'
+ // +---------------------
+ // | lr, saved by prelude <- R13 points here
+ // +---------------------
+ MOVW g, 4(R13)
+
+ MOVW out+0(FP), R4
+ MOVW m+4(FP), R5
+ MOVW mlen+8(FP), R6
+ MOVW key+12(FP), R7
+
+ ADD $136, R13, R0 // 136 = 4 + 4 + 16 + 112
+ MOVW R7, R1
+
+ // poly1305_init_ext_armv6 will write to the stack from R13+4, but
+ // that's ok because none of the other values have been written yet.
+ BL poly1305_init_ext_armv6<>(SB)
+ BIC.S $15, R6, R2
+ BEQ poly1305_auth_armv6_noblocks
+ ADD $136, R13, R0
+ MOVW R5, R1
+ ADD R2, R5, R5
+ SUB R2, R6, R6
+ BL poly1305_blocks_armv6<>(SB)
+
+poly1305_auth_armv6_noblocks:
+ ADD $136, R13, R0
+ MOVW R5, R1
+ MOVW R6, R2
+ MOVW R4, R3
+
+ MOVW R0, R5
+ MOVW R1, R6
+ MOVW R2, R7
+ MOVW R3, R8
+ AND.S R2, R2, R2
+ BEQ poly1305_finish_ext_armv6_noremaining
+ EOR R0, R0
+ ADD $8, R13, R9 // 8 = offset to 16 byte scratch space
+ MOVW R0, (R9)
+ MOVW R0, 4(R9)
+ MOVW R0, 8(R9)
+ MOVW R0, 12(R9)
+ WORD $0xe3110003 // TST R1, #3 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_aligned
+ WORD $0xe3120008 // TST R2, #8 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip8
+ MOVWP_UNALIGNED(R1, R9, g)
+ MOVWP_UNALIGNED(R1, R9, g)
+
+poly1305_finish_ext_armv6_skip8:
+ WORD $0xe3120004 // TST $4, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip4
+ MOVWP_UNALIGNED(R1, R9, g)
+
+poly1305_finish_ext_armv6_skip4:
+ WORD $0xe3120002 // TST $2, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip2
+ MOVHUP_UNALIGNED(R1, R9, g)
+ B poly1305_finish_ext_armv6_skip2
+
+poly1305_finish_ext_armv6_aligned:
+ WORD $0xe3120008 // TST R2, #8 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip8_aligned
+ MOVM.IA.W (R1), [g-R11]
+ MOVM.IA.W [g-R11], (R9)
+
+poly1305_finish_ext_armv6_skip8_aligned:
+ WORD $0xe3120004 // TST $4, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip4_aligned
+ MOVW.P 4(R1), g
+ MOVW.P g, 4(R9)
+
+poly1305_finish_ext_armv6_skip4_aligned:
+ WORD $0xe3120002 // TST $2, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip2
+ MOVHU.P 2(R1), g
+ MOVH.P g, 2(R9)
+
+poly1305_finish_ext_armv6_skip2:
+ WORD $0xe3120001 // TST $1, R2 not working see issue 5921
+ BEQ poly1305_finish_ext_armv6_skip1
+ MOVBU.P 1(R1), g
+ MOVBU.P g, 1(R9)
+
+poly1305_finish_ext_armv6_skip1:
+ MOVW $1, R11
+ MOVBU R11, 0(R9)
+ MOVW R11, 56(R5)
+ MOVW R5, R0
+ ADD $8, R13, R1
+ MOVW $16, R2
+ BL poly1305_blocks_armv6<>(SB)
+
+poly1305_finish_ext_armv6_noremaining:
+ MOVW 20(R5), R0
+ MOVW 24(R5), R1
+ MOVW 28(R5), R2
+ MOVW 32(R5), R3
+ MOVW 36(R5), R4
+ MOVW R4>>26, R12
+ BIC $0xfc000000, R4, R4
+ ADD R12<<2, R12, R12
+ ADD R12, R0, R0
+ MOVW R0>>26, R12
+ BIC $0xfc000000, R0, R0
+ ADD R12, R1, R1
+ MOVW R1>>26, R12
+ BIC $0xfc000000, R1, R1
+ ADD R12, R2, R2
+ MOVW R2>>26, R12
+ BIC $0xfc000000, R2, R2
+ ADD R12, R3, R3
+ MOVW R3>>26, R12
+ BIC $0xfc000000, R3, R3
+ ADD R12, R4, R4
+ ADD $5, R0, R6
+ MOVW R6>>26, R12
+ BIC $0xfc000000, R6, R6
+ ADD R12, R1, R7
+ MOVW R7>>26, R12
+ BIC $0xfc000000, R7, R7
+ ADD R12, R2, g
+ MOVW g>>26, R12
+ BIC $0xfc000000, g, g
+ ADD R12, R3, R11
+ MOVW $-(1<<26), R12
+ ADD R11>>26, R12, R12
+ BIC $0xfc000000, R11, R11
+ ADD R12, R4, R9
+ MOVW R9>>31, R12
+ SUB $1, R12
+ AND R12, R6, R6
+ AND R12, R7, R7
+ AND R12, g, g
+ AND R12, R11, R11
+ AND R12, R9, R9
+ MVN R12, R12
+ AND R12, R0, R0
+ AND R12, R1, R1
+ AND R12, R2, R2
+ AND R12, R3, R3
+ AND R12, R4, R4
+ ORR R6, R0, R0
+ ORR R7, R1, R1
+ ORR g, R2, R2
+ ORR R11, R3, R3
+ ORR R9, R4, R4
+ ORR R1<<26, R0, R0
+ MOVW R1>>6, R1
+ ORR R2<<20, R1, R1
+ MOVW R2>>12, R2
+ ORR R3<<14, R2, R2
+ MOVW R3>>18, R3
+ ORR R4<<8, R3, R3
+ MOVW 40(R5), R6
+ MOVW 44(R5), R7
+ MOVW 48(R5), g
+ MOVW 52(R5), R11
+ ADD.S R6, R0, R0
+ ADC.S R7, R1, R1
+ ADC.S g, R2, R2
+ ADC.S R11, R3, R3
+ MOVM.IA [R0-R3], (R8)
+ MOVW R5, R12
+ EOR R0, R0, R0
+ EOR R1, R1, R1
+ EOR R2, R2, R2
+ EOR R3, R3, R3
+ EOR R4, R4, R4
+ EOR R5, R5, R5
+ EOR R6, R6, R6
+ EOR R7, R7, R7
+ MOVM.IA.W [R0-R7], (R12)
+ MOVM.IA [R0-R7], (R12)
+ MOVW 4(R13), g
+ RET
diff --git a/vendor/golang.org/x/crypto/poly1305/sum_ref.go b/vendor/golang.org/x/crypto/poly1305/sum_ref.go
new file mode 100644
index 0000000..b2805a5
--- /dev/null
+++ b/vendor/golang.org/x/crypto/poly1305/sum_ref.go
@@ -0,0 +1,141 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !amd64,!arm gccgo appengine nacl
+
+package poly1305
+
+import "encoding/binary"
+
+// Sum generates an authenticator for msg using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) {
+ var (
+ h0, h1, h2, h3, h4 uint32 // the hash accumulators
+ r0, r1, r2, r3, r4 uint64 // the r part of the key
+ )
+
+ r0 = uint64(binary.LittleEndian.Uint32(key[0:]) & 0x3ffffff)
+ r1 = uint64((binary.LittleEndian.Uint32(key[3:]) >> 2) & 0x3ffff03)
+ r2 = uint64((binary.LittleEndian.Uint32(key[6:]) >> 4) & 0x3ffc0ff)
+ r3 = uint64((binary.LittleEndian.Uint32(key[9:]) >> 6) & 0x3f03fff)
+ r4 = uint64((binary.LittleEndian.Uint32(key[12:]) >> 8) & 0x00fffff)
+
+ R1, R2, R3, R4 := r1*5, r2*5, r3*5, r4*5
+
+ for len(msg) >= TagSize {
+ // h += msg
+ h0 += binary.LittleEndian.Uint32(msg[0:]) & 0x3ffffff
+ h1 += (binary.LittleEndian.Uint32(msg[3:]) >> 2) & 0x3ffffff
+ h2 += (binary.LittleEndian.Uint32(msg[6:]) >> 4) & 0x3ffffff
+ h3 += (binary.LittleEndian.Uint32(msg[9:]) >> 6) & 0x3ffffff
+ h4 += (binary.LittleEndian.Uint32(msg[12:]) >> 8) | (1 << 24)
+
+ // h *= r
+ d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
+ d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
+ d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
+ d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
+ d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
+
+ // h %= p
+ h0 = uint32(d0) & 0x3ffffff
+ h1 = uint32(d1) & 0x3ffffff
+ h2 = uint32(d2) & 0x3ffffff
+ h3 = uint32(d3) & 0x3ffffff
+ h4 = uint32(d4) & 0x3ffffff
+
+ h0 += uint32(d4>>26) * 5
+ h1 += h0 >> 26
+ h0 = h0 & 0x3ffffff
+
+ msg = msg[TagSize:]
+ }
+
+ if len(msg) > 0 {
+ var block [TagSize]byte
+ off := copy(block[:], msg)
+ block[off] = 0x01
+
+ // h += msg
+ h0 += binary.LittleEndian.Uint32(block[0:]) & 0x3ffffff
+ h1 += (binary.LittleEndian.Uint32(block[3:]) >> 2) & 0x3ffffff
+ h2 += (binary.LittleEndian.Uint32(block[6:]) >> 4) & 0x3ffffff
+ h3 += (binary.LittleEndian.Uint32(block[9:]) >> 6) & 0x3ffffff
+ h4 += (binary.LittleEndian.Uint32(block[12:]) >> 8)
+
+ // h *= r
+ d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
+ d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
+ d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
+ d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
+ d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
+
+ // h %= p
+ h0 = uint32(d0) & 0x3ffffff
+ h1 = uint32(d1) & 0x3ffffff
+ h2 = uint32(d2) & 0x3ffffff
+ h3 = uint32(d3) & 0x3ffffff
+ h4 = uint32(d4) & 0x3ffffff
+
+ h0 += uint32(d4>>26) * 5
+ h1 += h0 >> 26
+ h0 = h0 & 0x3ffffff
+ }
+
+ // h %= p reduction
+ h2 += h1 >> 26
+ h1 &= 0x3ffffff
+ h3 += h2 >> 26
+ h2 &= 0x3ffffff
+ h4 += h3 >> 26
+ h3 &= 0x3ffffff
+ h0 += 5 * (h4 >> 26)
+ h4 &= 0x3ffffff
+ h1 += h0 >> 26
+ h0 &= 0x3ffffff
+
+ // h - p
+ t0 := h0 + 5
+ t1 := h1 + (t0 >> 26)
+ t2 := h2 + (t1 >> 26)
+ t3 := h3 + (t2 >> 26)
+ t4 := h4 + (t3 >> 26) - (1 << 26)
+ t0 &= 0x3ffffff
+ t1 &= 0x3ffffff
+ t2 &= 0x3ffffff
+ t3 &= 0x3ffffff
+
+ // select h if h < p else h - p
+ t_mask := (t4 >> 31) - 1
+ h_mask := ^t_mask
+ h0 = (h0 & h_mask) | (t0 & t_mask)
+ h1 = (h1 & h_mask) | (t1 & t_mask)
+ h2 = (h2 & h_mask) | (t2 & t_mask)
+ h3 = (h3 & h_mask) | (t3 & t_mask)
+ h4 = (h4 & h_mask) | (t4 & t_mask)
+
+ // h %= 2^128
+ h0 |= h1 << 26
+ h1 = ((h1 >> 6) | (h2 << 20))
+ h2 = ((h2 >> 12) | (h3 << 14))
+ h3 = ((h3 >> 18) | (h4 << 8))
+
+ // s: the s part of the key
+ // tag = (h + s) % (2^128)
+ t := uint64(h0) + uint64(binary.LittleEndian.Uint32(key[16:]))
+ h0 = uint32(t)
+ t = uint64(h1) + uint64(binary.LittleEndian.Uint32(key[20:])) + (t >> 32)
+ h1 = uint32(t)
+ t = uint64(h2) + uint64(binary.LittleEndian.Uint32(key[24:])) + (t >> 32)
+ h2 = uint32(t)
+ t = uint64(h3) + uint64(binary.LittleEndian.Uint32(key[28:])) + (t >> 32)
+ h3 = uint32(t)
+
+ binary.LittleEndian.PutUint32(out[0:], h0)
+ binary.LittleEndian.PutUint32(out[4:], h1)
+ binary.LittleEndian.PutUint32(out[8:], h2)
+ binary.LittleEndian.PutUint32(out[12:], h3)
+}
diff --git a/cmd/gost/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go b/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go
rename to vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go
diff --git a/cmd/gost/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s b/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s
similarity index 99%
rename from cmd/gost/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s
rename to vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s
index 083fe38..22afbdc 100644
--- a/cmd/gost/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s
+++ b/vendor/golang.org/x/crypto/salsa20/salsa/salsa2020_amd64.s
@@ -5,7 +5,7 @@
// +build amd64,!appengine,!gccgo
// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+// domain sources in SUPERCOP: https://bench.cr.yp.to/supercop.html
// func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte)
// This needs up to 64 bytes at 360(SP); hence the non-obvious frame size.
diff --git a/cmd/gost/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go
rename to vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go
diff --git a/cmd/gost/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go
rename to vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go
diff --git a/cmd/gost/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go b/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go
rename to vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go
diff --git a/cmd/gost/vendor/golang.org/x/crypto/salsa20/salsa20.go b/vendor/golang.org/x/crypto/salsa20/salsa20.go
similarity index 90%
rename from cmd/gost/vendor/golang.org/x/crypto/salsa20/salsa20.go
rename to vendor/golang.org/x/crypto/salsa20/salsa20.go
index fde9846..a8ddd76 100644
--- a/cmd/gost/vendor/golang.org/x/crypto/salsa20/salsa20.go
+++ b/vendor/golang.org/x/crypto/salsa20/salsa20.go
@@ -3,20 +3,20 @@
// license that can be found in the LICENSE file.
/*
-Package salsa20 implements the Salsa20 stream cipher as specified in http://cr.yp.to/snuffle/spec.pdf.
+Package salsa20 implements the Salsa20 stream cipher as specified in https://cr.yp.to/snuffle/spec.pdf.
Salsa20 differs from many other stream ciphers in that it is message orientated
rather than byte orientated. Keystream blocks are not preserved between calls,
therefore each side must encrypt/decrypt data with the same segmentation.
Another aspect of this difference is that part of the counter is exposed as
-an nonce in each call. Encrypting two different messages with the same (key,
+a nonce in each call. Encrypting two different messages with the same (key,
nonce) pair leads to trivial plaintext recovery. This is analogous to
encrypting two different messages with the same key with a traditional stream
cipher.
This package also implements XSalsa20: a version of Salsa20 with a 24-byte
-nonce as specified in http://cr.yp.to/snuffle/xsalsa-20081128.pdf. Simply
+nonce as specified in https://cr.yp.to/snuffle/xsalsa-20081128.pdf. Simply
passing a 24-byte slice as the nonce triggers XSalsa20.
*/
package salsa20 // import "golang.org/x/crypto/salsa20"
diff --git a/vendor/golang.org/x/crypto/ssh/buffer.go b/vendor/golang.org/x/crypto/ssh/buffer.go
new file mode 100644
index 0000000..6931b51
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/buffer.go
@@ -0,0 +1,98 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "io"
+ "sync"
+)
+
+// buffer provides a linked list buffer for data exchange
+// between producer and consumer. Theoretically the buffer is
+// of unlimited capacity as it does no allocation of its own.
+type buffer struct {
+ // protects concurrent access to head, tail and closed
+ *sync.Cond
+
+ head *element // the buffer that will be read first
+ tail *element // the buffer that will be read last
+
+ closed bool
+}
+
+// An element represents a single link in a linked list.
+type element struct {
+ buf []byte
+ next *element
+}
+
+// newBuffer returns an empty buffer that is not closed.
+func newBuffer() *buffer {
+ e := new(element)
+ b := &buffer{
+ Cond: newCond(),
+ head: e,
+ tail: e,
+ }
+ return b
+}
+
+// write makes buf available for Read to receive.
+// buf must not be modified after the call to write.
+func (b *buffer) write(buf []byte) {
+ b.Cond.L.Lock()
+ e := &element{buf: buf}
+ b.tail.next = e
+ b.tail = e
+ b.Cond.Signal()
+ b.Cond.L.Unlock()
+}
+
+// eof closes the buffer. Reads from the buffer once all
+// the data has been consumed will receive os.EOF.
+func (b *buffer) eof() error {
+ b.Cond.L.Lock()
+ b.closed = true
+ b.Cond.Signal()
+ b.Cond.L.Unlock()
+ return nil
+}
+
+// Read reads data from the internal buffer in buf. Reads will block
+// if no data is available, or until the buffer is closed.
+func (b *buffer) Read(buf []byte) (n int, err error) {
+ b.Cond.L.Lock()
+ defer b.Cond.L.Unlock()
+
+ for len(buf) > 0 {
+ // if there is data in b.head, copy it
+ if len(b.head.buf) > 0 {
+ r := copy(buf, b.head.buf)
+ buf, b.head.buf = buf[r:], b.head.buf[r:]
+ n += r
+ continue
+ }
+ // if there is a next buffer, make it the head
+ if len(b.head.buf) == 0 && b.head != b.tail {
+ b.head = b.head.next
+ continue
+ }
+
+ // if at least one byte has been copied, return
+ if n > 0 {
+ break
+ }
+
+ // if nothing was read, and there is nothing outstanding
+ // check to see if the buffer is closed.
+ if b.closed {
+ err = io.EOF
+ break
+ }
+ // out of buffers, wait for producer
+ b.Cond.Wait()
+ }
+ return
+}
diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go
new file mode 100644
index 0000000..b1f0220
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/certs.go
@@ -0,0 +1,519 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "sort"
+ "time"
+)
+
+// These constants from [PROTOCOL.certkeys] represent the algorithm names
+// for certificate types supported by this package.
+const (
+ CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
+ CertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com"
+ CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
+ CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
+ CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
+ CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com"
+)
+
+// Certificate types distinguish between host and user
+// certificates. The values can be set in the CertType field of
+// Certificate.
+const (
+ UserCert = 1
+ HostCert = 2
+)
+
+// Signature represents a cryptographic signature.
+type Signature struct {
+ Format string
+ Blob []byte
+}
+
+// CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that
+// a certificate does not expire.
+const CertTimeInfinity = 1<<64 - 1
+
+// An Certificate represents an OpenSSH certificate as defined in
+// [PROTOCOL.certkeys]?rev=1.8.
+type Certificate struct {
+ Nonce []byte
+ Key PublicKey
+ Serial uint64
+ CertType uint32
+ KeyId string
+ ValidPrincipals []string
+ ValidAfter uint64
+ ValidBefore uint64
+ Permissions
+ Reserved []byte
+ SignatureKey PublicKey
+ Signature *Signature
+}
+
+// genericCertData holds the key-independent part of the certificate data.
+// Overall, certificates contain an nonce, public key fields and
+// key-independent fields.
+type genericCertData struct {
+ Serial uint64
+ CertType uint32
+ KeyId string
+ ValidPrincipals []byte
+ ValidAfter uint64
+ ValidBefore uint64
+ CriticalOptions []byte
+ Extensions []byte
+ Reserved []byte
+ SignatureKey []byte
+ Signature []byte
+}
+
+func marshalStringList(namelist []string) []byte {
+ var to []byte
+ for _, name := range namelist {
+ s := struct{ N string }{name}
+ to = append(to, Marshal(&s)...)
+ }
+ return to
+}
+
+type optionsTuple struct {
+ Key string
+ Value []byte
+}
+
+type optionsTupleValue struct {
+ Value string
+}
+
+// serialize a map of critical options or extensions
+// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation,
+// we need two length prefixes for a non-empty string value
+func marshalTuples(tups map[string]string) []byte {
+ keys := make([]string, 0, len(tups))
+ for key := range tups {
+ keys = append(keys, key)
+ }
+ sort.Strings(keys)
+
+ var ret []byte
+ for _, key := range keys {
+ s := optionsTuple{Key: key}
+ if value := tups[key]; len(value) > 0 {
+ s.Value = Marshal(&optionsTupleValue{value})
+ }
+ ret = append(ret, Marshal(&s)...)
+ }
+ return ret
+}
+
+// issue #10569 - per [PROTOCOL.certkeys] and SSH implementation,
+// we need two length prefixes for a non-empty option value
+func parseTuples(in []byte) (map[string]string, error) {
+ tups := map[string]string{}
+ var lastKey string
+ var haveLastKey bool
+
+ for len(in) > 0 {
+ var key, val, extra []byte
+ var ok bool
+
+ if key, in, ok = parseString(in); !ok {
+ return nil, errShortRead
+ }
+ keyStr := string(key)
+ // according to [PROTOCOL.certkeys], the names must be in
+ // lexical order.
+ if haveLastKey && keyStr <= lastKey {
+ return nil, fmt.Errorf("ssh: certificate options are not in lexical order")
+ }
+ lastKey, haveLastKey = keyStr, true
+ // the next field is a data field, which if non-empty has a string embedded
+ if val, in, ok = parseString(in); !ok {
+ return nil, errShortRead
+ }
+ if len(val) > 0 {
+ val, extra, ok = parseString(val)
+ if !ok {
+ return nil, errShortRead
+ }
+ if len(extra) > 0 {
+ return nil, fmt.Errorf("ssh: unexpected trailing data after certificate option value")
+ }
+ tups[keyStr] = string(val)
+ } else {
+ tups[keyStr] = ""
+ }
+ }
+ return tups, nil
+}
+
+func parseCert(in []byte, privAlgo string) (*Certificate, error) {
+ nonce, rest, ok := parseString(in)
+ if !ok {
+ return nil, errShortRead
+ }
+
+ key, rest, err := parsePubKey(rest, privAlgo)
+ if err != nil {
+ return nil, err
+ }
+
+ var g genericCertData
+ if err := Unmarshal(rest, &g); err != nil {
+ return nil, err
+ }
+
+ c := &Certificate{
+ Nonce: nonce,
+ Key: key,
+ Serial: g.Serial,
+ CertType: g.CertType,
+ KeyId: g.KeyId,
+ ValidAfter: g.ValidAfter,
+ ValidBefore: g.ValidBefore,
+ }
+
+ for principals := g.ValidPrincipals; len(principals) > 0; {
+ principal, rest, ok := parseString(principals)
+ if !ok {
+ return nil, errShortRead
+ }
+ c.ValidPrincipals = append(c.ValidPrincipals, string(principal))
+ principals = rest
+ }
+
+ c.CriticalOptions, err = parseTuples(g.CriticalOptions)
+ if err != nil {
+ return nil, err
+ }
+ c.Extensions, err = parseTuples(g.Extensions)
+ if err != nil {
+ return nil, err
+ }
+ c.Reserved = g.Reserved
+ k, err := ParsePublicKey(g.SignatureKey)
+ if err != nil {
+ return nil, err
+ }
+
+ c.SignatureKey = k
+ c.Signature, rest, ok = parseSignatureBody(g.Signature)
+ if !ok || len(rest) > 0 {
+ return nil, errors.New("ssh: signature parse error")
+ }
+
+ return c, nil
+}
+
+type openSSHCertSigner struct {
+ pub *Certificate
+ signer Signer
+}
+
+// NewCertSigner returns a Signer that signs with the given Certificate, whose
+// private key is held by signer. It returns an error if the public key in cert
+// doesn't match the key used by signer.
+func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) {
+ if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 {
+ return nil, errors.New("ssh: signer and cert have different public key")
+ }
+
+ return &openSSHCertSigner{cert, signer}, nil
+}
+
+func (s *openSSHCertSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
+ return s.signer.Sign(rand, data)
+}
+
+func (s *openSSHCertSigner) PublicKey() PublicKey {
+ return s.pub
+}
+
+const sourceAddressCriticalOption = "source-address"
+
+// CertChecker does the work of verifying a certificate. Its methods
+// can be plugged into ClientConfig.HostKeyCallback and
+// ServerConfig.PublicKeyCallback. For the CertChecker to work,
+// minimally, the IsAuthority callback should be set.
+type CertChecker struct {
+ // SupportedCriticalOptions lists the CriticalOptions that the
+ // server application layer understands. These are only used
+ // for user certificates.
+ SupportedCriticalOptions []string
+
+ // IsUserAuthority should return true if the key is recognized as an
+ // authority for the given user certificate. This allows for
+ // certificates to be signed by other certificates. This must be set
+ // if this CertChecker will be checking user certificates.
+ IsUserAuthority func(auth PublicKey) bool
+
+ // IsHostAuthority should report whether the key is recognized as
+ // an authority for this host. This allows for certificates to be
+ // signed by other keys, and for those other keys to only be valid
+ // signers for particular hostnames. This must be set if this
+ // CertChecker will be checking host certificates.
+ IsHostAuthority func(auth PublicKey, address string) bool
+
+ // Clock is used for verifying time stamps. If nil, time.Now
+ // is used.
+ Clock func() time.Time
+
+ // UserKeyFallback is called when CertChecker.Authenticate encounters a
+ // public key that is not a certificate. It must implement validation
+ // of user keys or else, if nil, all such keys are rejected.
+ UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
+
+ // HostKeyFallback is called when CertChecker.CheckHostKey encounters a
+ // public key that is not a certificate. It must implement host key
+ // validation or else, if nil, all such keys are rejected.
+ HostKeyFallback HostKeyCallback
+
+ // IsRevoked is called for each certificate so that revocation checking
+ // can be implemented. It should return true if the given certificate
+ // is revoked and false otherwise. If nil, no certificates are
+ // considered to have been revoked.
+ IsRevoked func(cert *Certificate) bool
+}
+
+// CheckHostKey checks a host key certificate. This method can be
+// plugged into ClientConfig.HostKeyCallback.
+func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error {
+ cert, ok := key.(*Certificate)
+ if !ok {
+ if c.HostKeyFallback != nil {
+ return c.HostKeyFallback(addr, remote, key)
+ }
+ return errors.New("ssh: non-certificate host key")
+ }
+ if cert.CertType != HostCert {
+ return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType)
+ }
+ if !c.IsHostAuthority(cert.SignatureKey, addr) {
+ return fmt.Errorf("ssh: no authorities for hostname: %v", addr)
+ }
+
+ hostname, _, err := net.SplitHostPort(addr)
+ if err != nil {
+ return err
+ }
+
+ // Pass hostname only as principal for host certificates (consistent with OpenSSH)
+ return c.CheckCert(hostname, cert)
+}
+
+// Authenticate checks a user certificate. Authenticate can be used as
+// a value for ServerConfig.PublicKeyCallback.
+func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) {
+ cert, ok := pubKey.(*Certificate)
+ if !ok {
+ if c.UserKeyFallback != nil {
+ return c.UserKeyFallback(conn, pubKey)
+ }
+ return nil, errors.New("ssh: normal key pairs not accepted")
+ }
+
+ if cert.CertType != UserCert {
+ return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType)
+ }
+ if !c.IsUserAuthority(cert.SignatureKey) {
+ return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority")
+ }
+
+ if err := c.CheckCert(conn.User(), cert); err != nil {
+ return nil, err
+ }
+
+ return &cert.Permissions, nil
+}
+
+// CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and
+// the signature of the certificate.
+func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
+ if c.IsRevoked != nil && c.IsRevoked(cert) {
+ return fmt.Errorf("ssh: certicate serial %d revoked", cert.Serial)
+ }
+
+ for opt, _ := range cert.CriticalOptions {
+ // sourceAddressCriticalOption will be enforced by
+ // serverAuthenticate
+ if opt == sourceAddressCriticalOption {
+ continue
+ }
+
+ found := false
+ for _, supp := range c.SupportedCriticalOptions {
+ if supp == opt {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt)
+ }
+ }
+
+ if len(cert.ValidPrincipals) > 0 {
+ // By default, certs are valid for all users/hosts.
+ found := false
+ for _, p := range cert.ValidPrincipals {
+ if p == principal {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return fmt.Errorf("ssh: principal %q not in the set of valid principals for given certificate: %q", principal, cert.ValidPrincipals)
+ }
+ }
+
+ clock := c.Clock
+ if clock == nil {
+ clock = time.Now
+ }
+
+ unixNow := clock().Unix()
+ if after := int64(cert.ValidAfter); after < 0 || unixNow < int64(cert.ValidAfter) {
+ return fmt.Errorf("ssh: cert is not yet valid")
+ }
+ if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) {
+ return fmt.Errorf("ssh: cert has expired")
+ }
+ if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil {
+ return fmt.Errorf("ssh: certificate signature does not verify")
+ }
+
+ return nil
+}
+
+// SignCert sets c.SignatureKey to the authority's public key and stores a
+// Signature, by authority, in the certificate.
+func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
+ c.Nonce = make([]byte, 32)
+ if _, err := io.ReadFull(rand, c.Nonce); err != nil {
+ return err
+ }
+ c.SignatureKey = authority.PublicKey()
+
+ sig, err := authority.Sign(rand, c.bytesForSigning())
+ if err != nil {
+ return err
+ }
+ c.Signature = sig
+ return nil
+}
+
+var certAlgoNames = map[string]string{
+ KeyAlgoRSA: CertAlgoRSAv01,
+ KeyAlgoDSA: CertAlgoDSAv01,
+ KeyAlgoECDSA256: CertAlgoECDSA256v01,
+ KeyAlgoECDSA384: CertAlgoECDSA384v01,
+ KeyAlgoECDSA521: CertAlgoECDSA521v01,
+ KeyAlgoED25519: CertAlgoED25519v01,
+}
+
+// certToPrivAlgo returns the underlying algorithm for a certificate algorithm.
+// Panics if a non-certificate algorithm is passed.
+func certToPrivAlgo(algo string) string {
+ for privAlgo, pubAlgo := range certAlgoNames {
+ if pubAlgo == algo {
+ return privAlgo
+ }
+ }
+ panic("unknown cert algorithm")
+}
+
+func (cert *Certificate) bytesForSigning() []byte {
+ c2 := *cert
+ c2.Signature = nil
+ out := c2.Marshal()
+ // Drop trailing signature length.
+ return out[:len(out)-4]
+}
+
+// Marshal serializes c into OpenSSH's wire format. It is part of the
+// PublicKey interface.
+func (c *Certificate) Marshal() []byte {
+ generic := genericCertData{
+ Serial: c.Serial,
+ CertType: c.CertType,
+ KeyId: c.KeyId,
+ ValidPrincipals: marshalStringList(c.ValidPrincipals),
+ ValidAfter: uint64(c.ValidAfter),
+ ValidBefore: uint64(c.ValidBefore),
+ CriticalOptions: marshalTuples(c.CriticalOptions),
+ Extensions: marshalTuples(c.Extensions),
+ Reserved: c.Reserved,
+ SignatureKey: c.SignatureKey.Marshal(),
+ }
+ if c.Signature != nil {
+ generic.Signature = Marshal(c.Signature)
+ }
+ genericBytes := Marshal(&generic)
+ keyBytes := c.Key.Marshal()
+ _, keyBytes, _ = parseString(keyBytes)
+ prefix := Marshal(&struct {
+ Name string
+ Nonce []byte
+ Key []byte `ssh:"rest"`
+ }{c.Type(), c.Nonce, keyBytes})
+
+ result := make([]byte, 0, len(prefix)+len(genericBytes))
+ result = append(result, prefix...)
+ result = append(result, genericBytes...)
+ return result
+}
+
+// Type returns the key name. It is part of the PublicKey interface.
+func (c *Certificate) Type() string {
+ algo, ok := certAlgoNames[c.Key.Type()]
+ if !ok {
+ panic("unknown cert key type " + c.Key.Type())
+ }
+ return algo
+}
+
+// Verify verifies a signature against the certificate's public
+// key. It is part of the PublicKey interface.
+func (c *Certificate) Verify(data []byte, sig *Signature) error {
+ return c.Key.Verify(data, sig)
+}
+
+func parseSignatureBody(in []byte) (out *Signature, rest []byte, ok bool) {
+ format, in, ok := parseString(in)
+ if !ok {
+ return
+ }
+
+ out = &Signature{
+ Format: string(format),
+ }
+
+ if out.Blob, in, ok = parseString(in); !ok {
+ return
+ }
+
+ return out, in, ok
+}
+
+func parseSignature(in []byte) (out *Signature, rest []byte, ok bool) {
+ sigBytes, rest, ok := parseString(in)
+ if !ok {
+ return
+ }
+
+ out, trailing, ok := parseSignatureBody(sigBytes)
+ if !ok || len(trailing) > 0 {
+ return nil, nil, false
+ }
+ return
+}
diff --git a/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/golang.org/x/crypto/ssh/channel.go
new file mode 100644
index 0000000..195530e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/channel.go
@@ -0,0 +1,633 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "sync"
+)
+
+const (
+ minPacketLength = 9
+ // channelMaxPacket contains the maximum number of bytes that will be
+ // sent in a single packet. As per RFC 4253, section 6.1, 32k is also
+ // the minimum.
+ channelMaxPacket = 1 << 15
+ // We follow OpenSSH here.
+ channelWindowSize = 64 * channelMaxPacket
+)
+
+// NewChannel represents an incoming request to a channel. It must either be
+// accepted for use by calling Accept, or rejected by calling Reject.
+type NewChannel interface {
+ // Accept accepts the channel creation request. It returns the Channel
+ // and a Go channel containing SSH requests. The Go channel must be
+ // serviced otherwise the Channel will hang.
+ Accept() (Channel, <-chan *Request, error)
+
+ // Reject rejects the channel creation request. After calling
+ // this, no other methods on the Channel may be called.
+ Reject(reason RejectionReason, message string) error
+
+ // ChannelType returns the type of the channel, as supplied by the
+ // client.
+ ChannelType() string
+
+ // ExtraData returns the arbitrary payload for this channel, as supplied
+ // by the client. This data is specific to the channel type.
+ ExtraData() []byte
+}
+
+// A Channel is an ordered, reliable, flow-controlled, duplex stream
+// that is multiplexed over an SSH connection.
+type Channel interface {
+ // Read reads up to len(data) bytes from the channel.
+ Read(data []byte) (int, error)
+
+ // Write writes len(data) bytes to the channel.
+ Write(data []byte) (int, error)
+
+ // Close signals end of channel use. No data may be sent after this
+ // call.
+ Close() error
+
+ // CloseWrite signals the end of sending in-band
+ // data. Requests may still be sent, and the other side may
+ // still send data
+ CloseWrite() error
+
+ // SendRequest sends a channel request. If wantReply is true,
+ // it will wait for a reply and return the result as a
+ // boolean, otherwise the return value will be false. Channel
+ // requests are out-of-band messages so they may be sent even
+ // if the data stream is closed or blocked by flow control.
+ // If the channel is closed before a reply is returned, io.EOF
+ // is returned.
+ SendRequest(name string, wantReply bool, payload []byte) (bool, error)
+
+ // Stderr returns an io.ReadWriter that writes to this channel
+ // with the extended data type set to stderr. Stderr may
+ // safely be read and written from a different goroutine than
+ // Read and Write respectively.
+ Stderr() io.ReadWriter
+}
+
+// Request is a request sent outside of the normal stream of
+// data. Requests can either be specific to an SSH channel, or they
+// can be global.
+type Request struct {
+ Type string
+ WantReply bool
+ Payload []byte
+
+ ch *channel
+ mux *mux
+}
+
+// Reply sends a response to a request. It must be called for all requests
+// where WantReply is true and is a no-op otherwise. The payload argument is
+// ignored for replies to channel-specific requests.
+func (r *Request) Reply(ok bool, payload []byte) error {
+ if !r.WantReply {
+ return nil
+ }
+
+ if r.ch == nil {
+ return r.mux.ackRequest(ok, payload)
+ }
+
+ return r.ch.ackRequest(ok)
+}
+
+// RejectionReason is an enumeration used when rejecting channel creation
+// requests. See RFC 4254, section 5.1.
+type RejectionReason uint32
+
+const (
+ Prohibited RejectionReason = iota + 1
+ ConnectionFailed
+ UnknownChannelType
+ ResourceShortage
+)
+
+// String converts the rejection reason to human readable form.
+func (r RejectionReason) String() string {
+ switch r {
+ case Prohibited:
+ return "administratively prohibited"
+ case ConnectionFailed:
+ return "connect failed"
+ case UnknownChannelType:
+ return "unknown channel type"
+ case ResourceShortage:
+ return "resource shortage"
+ }
+ return fmt.Sprintf("unknown reason %d", int(r))
+}
+
+func min(a uint32, b int) uint32 {
+ if a < uint32(b) {
+ return a
+ }
+ return uint32(b)
+}
+
+type channelDirection uint8
+
+const (
+ channelInbound channelDirection = iota
+ channelOutbound
+)
+
+// channel is an implementation of the Channel interface that works
+// with the mux class.
+type channel struct {
+ // R/O after creation
+ chanType string
+ extraData []byte
+ localId, remoteId uint32
+
+ // maxIncomingPayload and maxRemotePayload are the maximum
+ // payload sizes of normal and extended data packets for
+ // receiving and sending, respectively. The wire packet will
+ // be 9 or 13 bytes larger (excluding encryption overhead).
+ maxIncomingPayload uint32
+ maxRemotePayload uint32
+
+ mux *mux
+
+ // decided is set to true if an accept or reject message has been sent
+ // (for outbound channels) or received (for inbound channels).
+ decided bool
+
+ // direction contains either channelOutbound, for channels created
+ // locally, or channelInbound, for channels created by the peer.
+ direction channelDirection
+
+ // Pending internal channel messages.
+ msg chan interface{}
+
+ // Since requests have no ID, there can be only one request
+ // with WantReply=true outstanding. This lock is held by a
+ // goroutine that has such an outgoing request pending.
+ sentRequestMu sync.Mutex
+
+ incomingRequests chan *Request
+
+ sentEOF bool
+
+ // thread-safe data
+ remoteWin window
+ pending *buffer
+ extPending *buffer
+
+ // windowMu protects myWindow, the flow-control window.
+ windowMu sync.Mutex
+ myWindow uint32
+
+ // writeMu serializes calls to mux.conn.writePacket() and
+ // protects sentClose and packetPool. This mutex must be
+ // different from windowMu, as writePacket can block if there
+ // is a key exchange pending.
+ writeMu sync.Mutex
+ sentClose bool
+
+ // packetPool has a buffer for each extended channel ID to
+ // save allocations during writes.
+ packetPool map[uint32][]byte
+}
+
+// writePacket sends a packet. If the packet is a channel close, it updates
+// sentClose. This method takes the lock c.writeMu.
+func (c *channel) writePacket(packet []byte) error {
+ c.writeMu.Lock()
+ if c.sentClose {
+ c.writeMu.Unlock()
+ return io.EOF
+ }
+ c.sentClose = (packet[0] == msgChannelClose)
+ err := c.mux.conn.writePacket(packet)
+ c.writeMu.Unlock()
+ return err
+}
+
+func (c *channel) sendMessage(msg interface{}) error {
+ if debugMux {
+ log.Printf("send(%d): %#v", c.mux.chanList.offset, msg)
+ }
+
+ p := Marshal(msg)
+ binary.BigEndian.PutUint32(p[1:], c.remoteId)
+ return c.writePacket(p)
+}
+
+// WriteExtended writes data to a specific extended stream. These streams are
+// used, for example, for stderr.
+func (c *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) {
+ if c.sentEOF {
+ return 0, io.EOF
+ }
+ // 1 byte message type, 4 bytes remoteId, 4 bytes data length
+ opCode := byte(msgChannelData)
+ headerLength := uint32(9)
+ if extendedCode > 0 {
+ headerLength += 4
+ opCode = msgChannelExtendedData
+ }
+
+ c.writeMu.Lock()
+ packet := c.packetPool[extendedCode]
+ // We don't remove the buffer from packetPool, so
+ // WriteExtended calls from different goroutines will be
+ // flagged as errors by the race detector.
+ c.writeMu.Unlock()
+
+ for len(data) > 0 {
+ space := min(c.maxRemotePayload, len(data))
+ if space, err = c.remoteWin.reserve(space); err != nil {
+ return n, err
+ }
+ if want := headerLength + space; uint32(cap(packet)) < want {
+ packet = make([]byte, want)
+ } else {
+ packet = packet[:want]
+ }
+
+ todo := data[:space]
+
+ packet[0] = opCode
+ binary.BigEndian.PutUint32(packet[1:], c.remoteId)
+ if extendedCode > 0 {
+ binary.BigEndian.PutUint32(packet[5:], uint32(extendedCode))
+ }
+ binary.BigEndian.PutUint32(packet[headerLength-4:], uint32(len(todo)))
+ copy(packet[headerLength:], todo)
+ if err = c.writePacket(packet); err != nil {
+ return n, err
+ }
+
+ n += len(todo)
+ data = data[len(todo):]
+ }
+
+ c.writeMu.Lock()
+ c.packetPool[extendedCode] = packet
+ c.writeMu.Unlock()
+
+ return n, err
+}
+
+func (c *channel) handleData(packet []byte) error {
+ headerLen := 9
+ isExtendedData := packet[0] == msgChannelExtendedData
+ if isExtendedData {
+ headerLen = 13
+ }
+ if len(packet) < headerLen {
+ // malformed data packet
+ return parseError(packet[0])
+ }
+
+ var extended uint32
+ if isExtendedData {
+ extended = binary.BigEndian.Uint32(packet[5:])
+ }
+
+ length := binary.BigEndian.Uint32(packet[headerLen-4 : headerLen])
+ if length == 0 {
+ return nil
+ }
+ if length > c.maxIncomingPayload {
+ // TODO(hanwen): should send Disconnect?
+ return errors.New("ssh: incoming packet exceeds maximum payload size")
+ }
+
+ data := packet[headerLen:]
+ if length != uint32(len(data)) {
+ return errors.New("ssh: wrong packet length")
+ }
+
+ c.windowMu.Lock()
+ if c.myWindow < length {
+ c.windowMu.Unlock()
+ // TODO(hanwen): should send Disconnect with reason?
+ return errors.New("ssh: remote side wrote too much")
+ }
+ c.myWindow -= length
+ c.windowMu.Unlock()
+
+ if extended == 1 {
+ c.extPending.write(data)
+ } else if extended > 0 {
+ // discard other extended data.
+ } else {
+ c.pending.write(data)
+ }
+ return nil
+}
+
+func (c *channel) adjustWindow(n uint32) error {
+ c.windowMu.Lock()
+ // Since myWindow is managed on our side, and can never exceed
+ // the initial window setting, we don't worry about overflow.
+ c.myWindow += uint32(n)
+ c.windowMu.Unlock()
+ return c.sendMessage(windowAdjustMsg{
+ AdditionalBytes: uint32(n),
+ })
+}
+
+func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error) {
+ switch extended {
+ case 1:
+ n, err = c.extPending.Read(data)
+ case 0:
+ n, err = c.pending.Read(data)
+ default:
+ return 0, fmt.Errorf("ssh: extended code %d unimplemented", extended)
+ }
+
+ if n > 0 {
+ err = c.adjustWindow(uint32(n))
+ // sendWindowAdjust can return io.EOF if the remote
+ // peer has closed the connection, however we want to
+ // defer forwarding io.EOF to the caller of Read until
+ // the buffer has been drained.
+ if n > 0 && err == io.EOF {
+ err = nil
+ }
+ }
+
+ return n, err
+}
+
+func (c *channel) close() {
+ c.pending.eof()
+ c.extPending.eof()
+ close(c.msg)
+ close(c.incomingRequests)
+ c.writeMu.Lock()
+ // This is not necessary for a normal channel teardown, but if
+ // there was another error, it is.
+ c.sentClose = true
+ c.writeMu.Unlock()
+ // Unblock writers.
+ c.remoteWin.close()
+}
+
+// responseMessageReceived is called when a success or failure message is
+// received on a channel to check that such a message is reasonable for the
+// given channel.
+func (c *channel) responseMessageReceived() error {
+ if c.direction == channelInbound {
+ return errors.New("ssh: channel response message received on inbound channel")
+ }
+ if c.decided {
+ return errors.New("ssh: duplicate response received for channel")
+ }
+ c.decided = true
+ return nil
+}
+
+func (c *channel) handlePacket(packet []byte) error {
+ switch packet[0] {
+ case msgChannelData, msgChannelExtendedData:
+ return c.handleData(packet)
+ case msgChannelClose:
+ c.sendMessage(channelCloseMsg{PeersId: c.remoteId})
+ c.mux.chanList.remove(c.localId)
+ c.close()
+ return nil
+ case msgChannelEOF:
+ // RFC 4254 is mute on how EOF affects dataExt messages but
+ // it is logical to signal EOF at the same time.
+ c.extPending.eof()
+ c.pending.eof()
+ return nil
+ }
+
+ decoded, err := decode(packet)
+ if err != nil {
+ return err
+ }
+
+ switch msg := decoded.(type) {
+ case *channelOpenFailureMsg:
+ if err := c.responseMessageReceived(); err != nil {
+ return err
+ }
+ c.mux.chanList.remove(msg.PeersId)
+ c.msg <- msg
+ case *channelOpenConfirmMsg:
+ if err := c.responseMessageReceived(); err != nil {
+ return err
+ }
+ if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {
+ return fmt.Errorf("ssh: invalid MaxPacketSize %d from peer", msg.MaxPacketSize)
+ }
+ c.remoteId = msg.MyId
+ c.maxRemotePayload = msg.MaxPacketSize
+ c.remoteWin.add(msg.MyWindow)
+ c.msg <- msg
+ case *windowAdjustMsg:
+ if !c.remoteWin.add(msg.AdditionalBytes) {
+ return fmt.Errorf("ssh: invalid window update for %d bytes", msg.AdditionalBytes)
+ }
+ case *channelRequestMsg:
+ req := Request{
+ Type: msg.Request,
+ WantReply: msg.WantReply,
+ Payload: msg.RequestSpecificData,
+ ch: c,
+ }
+
+ c.incomingRequests <- &req
+ default:
+ c.msg <- msg
+ }
+ return nil
+}
+
+func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel {
+ ch := &channel{
+ remoteWin: window{Cond: newCond()},
+ myWindow: channelWindowSize,
+ pending: newBuffer(),
+ extPending: newBuffer(),
+ direction: direction,
+ incomingRequests: make(chan *Request, chanSize),
+ msg: make(chan interface{}, chanSize),
+ chanType: chanType,
+ extraData: extraData,
+ mux: m,
+ packetPool: make(map[uint32][]byte),
+ }
+ ch.localId = m.chanList.add(ch)
+ return ch
+}
+
+var errUndecided = errors.New("ssh: must Accept or Reject channel")
+var errDecidedAlready = errors.New("ssh: can call Accept or Reject only once")
+
+type extChannel struct {
+ code uint32
+ ch *channel
+}
+
+func (e *extChannel) Write(data []byte) (n int, err error) {
+ return e.ch.WriteExtended(data, e.code)
+}
+
+func (e *extChannel) Read(data []byte) (n int, err error) {
+ return e.ch.ReadExtended(data, e.code)
+}
+
+func (c *channel) Accept() (Channel, <-chan *Request, error) {
+ if c.decided {
+ return nil, nil, errDecidedAlready
+ }
+ c.maxIncomingPayload = channelMaxPacket
+ confirm := channelOpenConfirmMsg{
+ PeersId: c.remoteId,
+ MyId: c.localId,
+ MyWindow: c.myWindow,
+ MaxPacketSize: c.maxIncomingPayload,
+ }
+ c.decided = true
+ if err := c.sendMessage(confirm); err != nil {
+ return nil, nil, err
+ }
+
+ return c, c.incomingRequests, nil
+}
+
+func (ch *channel) Reject(reason RejectionReason, message string) error {
+ if ch.decided {
+ return errDecidedAlready
+ }
+ reject := channelOpenFailureMsg{
+ PeersId: ch.remoteId,
+ Reason: reason,
+ Message: message,
+ Language: "en",
+ }
+ ch.decided = true
+ return ch.sendMessage(reject)
+}
+
+func (ch *channel) Read(data []byte) (int, error) {
+ if !ch.decided {
+ return 0, errUndecided
+ }
+ return ch.ReadExtended(data, 0)
+}
+
+func (ch *channel) Write(data []byte) (int, error) {
+ if !ch.decided {
+ return 0, errUndecided
+ }
+ return ch.WriteExtended(data, 0)
+}
+
+func (ch *channel) CloseWrite() error {
+ if !ch.decided {
+ return errUndecided
+ }
+ ch.sentEOF = true
+ return ch.sendMessage(channelEOFMsg{
+ PeersId: ch.remoteId})
+}
+
+func (ch *channel) Close() error {
+ if !ch.decided {
+ return errUndecided
+ }
+
+ return ch.sendMessage(channelCloseMsg{
+ PeersId: ch.remoteId})
+}
+
+// Extended returns an io.ReadWriter that sends and receives data on the given,
+// SSH extended stream. Such streams are used, for example, for stderr.
+func (ch *channel) Extended(code uint32) io.ReadWriter {
+ if !ch.decided {
+ return nil
+ }
+ return &extChannel{code, ch}
+}
+
+func (ch *channel) Stderr() io.ReadWriter {
+ return ch.Extended(1)
+}
+
+func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (bool, error) {
+ if !ch.decided {
+ return false, errUndecided
+ }
+
+ if wantReply {
+ ch.sentRequestMu.Lock()
+ defer ch.sentRequestMu.Unlock()
+ }
+
+ msg := channelRequestMsg{
+ PeersId: ch.remoteId,
+ Request: name,
+ WantReply: wantReply,
+ RequestSpecificData: payload,
+ }
+
+ if err := ch.sendMessage(msg); err != nil {
+ return false, err
+ }
+
+ if wantReply {
+ m, ok := (<-ch.msg)
+ if !ok {
+ return false, io.EOF
+ }
+ switch m.(type) {
+ case *channelRequestFailureMsg:
+ return false, nil
+ case *channelRequestSuccessMsg:
+ return true, nil
+ default:
+ return false, fmt.Errorf("ssh: unexpected response to channel request: %#v", m)
+ }
+ }
+
+ return false, nil
+}
+
+// ackRequest either sends an ack or nack to the channel request.
+func (ch *channel) ackRequest(ok bool) error {
+ if !ch.decided {
+ return errUndecided
+ }
+
+ var msg interface{}
+ if !ok {
+ msg = channelRequestFailureMsg{
+ PeersId: ch.remoteId,
+ }
+ } else {
+ msg = channelRequestSuccessMsg{
+ PeersId: ch.remoteId,
+ }
+ }
+ return ch.sendMessage(msg)
+}
+
+func (ch *channel) ChannelType() string {
+ return ch.chanType
+}
+
+func (ch *channel) ExtraData() []byte {
+ return ch.extraData
+}
diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go
new file mode 100644
index 0000000..22bb30c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/cipher.go
@@ -0,0 +1,629 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/des"
+ "crypto/rc4"
+ "crypto/subtle"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "hash"
+ "io"
+ "io/ioutil"
+)
+
+const (
+ packetSizeMultiple = 16 // TODO(huin) this should be determined by the cipher.
+
+ // RFC 4253 section 6.1 defines a minimum packet size of 32768 that implementations
+ // MUST be able to process (plus a few more kilobytes for padding and mac). The RFC
+ // indicates implementations SHOULD be able to handle larger packet sizes, but then
+ // waffles on about reasonable limits.
+ //
+ // OpenSSH caps their maxPacket at 256kB so we choose to do
+ // the same. maxPacket is also used to ensure that uint32
+ // length fields do not overflow, so it should remain well
+ // below 4G.
+ maxPacket = 256 * 1024
+)
+
+// noneCipher implements cipher.Stream and provides no encryption. It is used
+// by the transport before the first key-exchange.
+type noneCipher struct{}
+
+func (c noneCipher) XORKeyStream(dst, src []byte) {
+ copy(dst, src)
+}
+
+func newAESCTR(key, iv []byte) (cipher.Stream, error) {
+ c, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+ return cipher.NewCTR(c, iv), nil
+}
+
+func newRC4(key, iv []byte) (cipher.Stream, error) {
+ return rc4.NewCipher(key)
+}
+
+type streamCipherMode struct {
+ keySize int
+ ivSize int
+ skip int
+ createFunc func(key, iv []byte) (cipher.Stream, error)
+}
+
+func (c *streamCipherMode) createStream(key, iv []byte) (cipher.Stream, error) {
+ if len(key) < c.keySize {
+ panic("ssh: key length too small for cipher")
+ }
+ if len(iv) < c.ivSize {
+ panic("ssh: iv too small for cipher")
+ }
+
+ stream, err := c.createFunc(key[:c.keySize], iv[:c.ivSize])
+ if err != nil {
+ return nil, err
+ }
+
+ var streamDump []byte
+ if c.skip > 0 {
+ streamDump = make([]byte, 512)
+ }
+
+ for remainingToDump := c.skip; remainingToDump > 0; {
+ dumpThisTime := remainingToDump
+ if dumpThisTime > len(streamDump) {
+ dumpThisTime = len(streamDump)
+ }
+ stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime])
+ remainingToDump -= dumpThisTime
+ }
+
+ return stream, nil
+}
+
+// cipherModes documents properties of supported ciphers. Ciphers not included
+// are not supported and will not be negotiated, even if explicitly requested in
+// ClientConfig.Crypto.Ciphers.
+var cipherModes = map[string]*streamCipherMode{
+ // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
+ // are defined in the order specified in the RFC.
+ "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR},
+ "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR},
+ "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR},
+
+ // Ciphers from RFC4345, which introduces security-improved arcfour ciphers.
+ // They are defined in the order specified in the RFC.
+ "arcfour128": {16, 0, 1536, newRC4},
+ "arcfour256": {32, 0, 1536, newRC4},
+
+ // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol.
+ // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and
+ // RC4) has problems with weak keys, and should be used with caution."
+ // RFC4345 introduces improved versions of Arcfour.
+ "arcfour": {16, 0, 0, newRC4},
+
+ // AES-GCM is not a stream cipher, so it is constructed with a
+ // special case. If we add any more non-stream ciphers, we
+ // should invest a cleaner way to do this.
+ gcmCipherID: {16, 12, 0, nil},
+
+ // CBC mode is insecure and so is not included in the default config.
+ // (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely
+ // needed, it's possible to specify a custom Config to enable it.
+ // You should expect that an active attacker can recover plaintext if
+ // you do.
+ aes128cbcID: {16, aes.BlockSize, 0, nil},
+
+ // 3des-cbc is insecure and is disabled by default.
+ tripledescbcID: {24, des.BlockSize, 0, nil},
+}
+
+// prefixLen is the length of the packet prefix that contains the packet length
+// and number of padding bytes.
+const prefixLen = 5
+
+// streamPacketCipher is a packetCipher using a stream cipher.
+type streamPacketCipher struct {
+ mac hash.Hash
+ cipher cipher.Stream
+ etm bool
+
+ // The following members are to avoid per-packet allocations.
+ prefix [prefixLen]byte
+ seqNumBytes [4]byte
+ padding [2 * packetSizeMultiple]byte
+ packetData []byte
+ macResult []byte
+}
+
+// readPacket reads and decrypt a single packet from the reader argument.
+func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
+ if _, err := io.ReadFull(r, s.prefix[:]); err != nil {
+ return nil, err
+ }
+
+ var encryptedPaddingLength [1]byte
+ if s.mac != nil && s.etm {
+ copy(encryptedPaddingLength[:], s.prefix[4:5])
+ s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
+ } else {
+ s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+ }
+
+ length := binary.BigEndian.Uint32(s.prefix[0:4])
+ paddingLength := uint32(s.prefix[4])
+
+ var macSize uint32
+ if s.mac != nil {
+ s.mac.Reset()
+ binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
+ s.mac.Write(s.seqNumBytes[:])
+ if s.etm {
+ s.mac.Write(s.prefix[:4])
+ s.mac.Write(encryptedPaddingLength[:])
+ } else {
+ s.mac.Write(s.prefix[:])
+ }
+ macSize = uint32(s.mac.Size())
+ }
+
+ if length <= paddingLength+1 {
+ return nil, errors.New("ssh: invalid packet length, packet too small")
+ }
+
+ if length > maxPacket {
+ return nil, errors.New("ssh: invalid packet length, packet too large")
+ }
+
+ // the maxPacket check above ensures that length-1+macSize
+ // does not overflow.
+ if uint32(cap(s.packetData)) < length-1+macSize {
+ s.packetData = make([]byte, length-1+macSize)
+ } else {
+ s.packetData = s.packetData[:length-1+macSize]
+ }
+
+ if _, err := io.ReadFull(r, s.packetData); err != nil {
+ return nil, err
+ }
+ mac := s.packetData[length-1:]
+ data := s.packetData[:length-1]
+
+ if s.mac != nil && s.etm {
+ s.mac.Write(data)
+ }
+
+ s.cipher.XORKeyStream(data, data)
+
+ if s.mac != nil {
+ if !s.etm {
+ s.mac.Write(data)
+ }
+ s.macResult = s.mac.Sum(s.macResult[:0])
+ if subtle.ConstantTimeCompare(s.macResult, mac) != 1 {
+ return nil, errors.New("ssh: MAC failure")
+ }
+ }
+
+ return s.packetData[:length-paddingLength-1], nil
+}
+
+// writePacket encrypts and sends a packet of data to the writer argument
+func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
+ if len(packet) > maxPacket {
+ return errors.New("ssh: packet too large")
+ }
+
+ aadlen := 0
+ if s.mac != nil && s.etm {
+ // packet length is not encrypted for EtM modes
+ aadlen = 4
+ }
+
+ paddingLength := packetSizeMultiple - (prefixLen+len(packet)-aadlen)%packetSizeMultiple
+ if paddingLength < 4 {
+ paddingLength += packetSizeMultiple
+ }
+
+ length := len(packet) + 1 + paddingLength
+ binary.BigEndian.PutUint32(s.prefix[:], uint32(length))
+ s.prefix[4] = byte(paddingLength)
+ padding := s.padding[:paddingLength]
+ if _, err := io.ReadFull(rand, padding); err != nil {
+ return err
+ }
+
+ if s.mac != nil {
+ s.mac.Reset()
+ binary.BigEndian.PutUint32(s.seqNumBytes[:], seqNum)
+ s.mac.Write(s.seqNumBytes[:])
+
+ if s.etm {
+ // For EtM algorithms, the packet length must stay unencrypted,
+ // but the following data (padding length) must be encrypted
+ s.cipher.XORKeyStream(s.prefix[4:5], s.prefix[4:5])
+ }
+
+ s.mac.Write(s.prefix[:])
+
+ if !s.etm {
+ // For non-EtM algorithms, the algorithm is applied on unencrypted data
+ s.mac.Write(packet)
+ s.mac.Write(padding)
+ }
+ }
+
+ if !(s.mac != nil && s.etm) {
+ // For EtM algorithms, the padding length has already been encrypted
+ // and the packet length must remain unencrypted
+ s.cipher.XORKeyStream(s.prefix[:], s.prefix[:])
+ }
+
+ s.cipher.XORKeyStream(packet, packet)
+ s.cipher.XORKeyStream(padding, padding)
+
+ if s.mac != nil && s.etm {
+ // For EtM algorithms, packet and padding must be encrypted
+ s.mac.Write(packet)
+ s.mac.Write(padding)
+ }
+
+ if _, err := w.Write(s.prefix[:]); err != nil {
+ return err
+ }
+ if _, err := w.Write(packet); err != nil {
+ return err
+ }
+ if _, err := w.Write(padding); err != nil {
+ return err
+ }
+
+ if s.mac != nil {
+ s.macResult = s.mac.Sum(s.macResult[:0])
+ if _, err := w.Write(s.macResult); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+type gcmCipher struct {
+ aead cipher.AEAD
+ prefix [4]byte
+ iv []byte
+ buf []byte
+}
+
+func newGCMCipher(iv, key, macKey []byte) (packetCipher, error) {
+ c, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ aead, err := cipher.NewGCM(c)
+ if err != nil {
+ return nil, err
+ }
+
+ return &gcmCipher{
+ aead: aead,
+ iv: iv,
+ }, nil
+}
+
+const gcmTagSize = 16
+
+func (c *gcmCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
+ // Pad out to multiple of 16 bytes. This is different from the
+ // stream cipher because that encrypts the length too.
+ padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple)
+ if padding < 4 {
+ padding += packetSizeMultiple
+ }
+
+ length := uint32(len(packet) + int(padding) + 1)
+ binary.BigEndian.PutUint32(c.prefix[:], length)
+ if _, err := w.Write(c.prefix[:]); err != nil {
+ return err
+ }
+
+ if cap(c.buf) < int(length) {
+ c.buf = make([]byte, length)
+ } else {
+ c.buf = c.buf[:length]
+ }
+
+ c.buf[0] = padding
+ copy(c.buf[1:], packet)
+ if _, err := io.ReadFull(rand, c.buf[1+len(packet):]); err != nil {
+ return err
+ }
+ c.buf = c.aead.Seal(c.buf[:0], c.iv, c.buf, c.prefix[:])
+ if _, err := w.Write(c.buf); err != nil {
+ return err
+ }
+ c.incIV()
+
+ return nil
+}
+
+func (c *gcmCipher) incIV() {
+ for i := 4 + 7; i >= 4; i-- {
+ c.iv[i]++
+ if c.iv[i] != 0 {
+ break
+ }
+ }
+}
+
+func (c *gcmCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
+ if _, err := io.ReadFull(r, c.prefix[:]); err != nil {
+ return nil, err
+ }
+ length := binary.BigEndian.Uint32(c.prefix[:])
+ if length > maxPacket {
+ return nil, errors.New("ssh: max packet length exceeded.")
+ }
+
+ if cap(c.buf) < int(length+gcmTagSize) {
+ c.buf = make([]byte, length+gcmTagSize)
+ } else {
+ c.buf = c.buf[:length+gcmTagSize]
+ }
+
+ if _, err := io.ReadFull(r, c.buf); err != nil {
+ return nil, err
+ }
+
+ plain, err := c.aead.Open(c.buf[:0], c.iv, c.buf, c.prefix[:])
+ if err != nil {
+ return nil, err
+ }
+ c.incIV()
+
+ padding := plain[0]
+ if padding < 4 {
+ // padding is a byte, so it automatically satisfies
+ // the maximum size, which is 255.
+ return nil, fmt.Errorf("ssh: illegal padding %d", padding)
+ }
+
+ if int(padding+1) >= len(plain) {
+ return nil, fmt.Errorf("ssh: padding %d too large", padding)
+ }
+ plain = plain[1 : length-uint32(padding)]
+ return plain, nil
+}
+
+// cbcCipher implements aes128-cbc cipher defined in RFC 4253 section 6.1
+type cbcCipher struct {
+ mac hash.Hash
+ macSize uint32
+ decrypter cipher.BlockMode
+ encrypter cipher.BlockMode
+
+ // The following members are to avoid per-packet allocations.
+ seqNumBytes [4]byte
+ packetData []byte
+ macResult []byte
+
+ // Amount of data we should still read to hide which
+ // verification error triggered.
+ oracleCamouflage uint32
+}
+
+func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+ cbc := &cbcCipher{
+ mac: macModes[algs.MAC].new(macKey),
+ decrypter: cipher.NewCBCDecrypter(c, iv),
+ encrypter: cipher.NewCBCEncrypter(c, iv),
+ packetData: make([]byte, 1024),
+ }
+ if cbc.mac != nil {
+ cbc.macSize = uint32(cbc.mac.Size())
+ }
+
+ return cbc, nil
+}
+
+func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+ c, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ cbc, err := newCBCCipher(c, iv, key, macKey, algs)
+ if err != nil {
+ return nil, err
+ }
+
+ return cbc, nil
+}
+
+func newTripleDESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
+ c, err := des.NewTripleDESCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ cbc, err := newCBCCipher(c, iv, key, macKey, algs)
+ if err != nil {
+ return nil, err
+ }
+
+ return cbc, nil
+}
+
+func maxUInt32(a, b int) uint32 {
+ if a > b {
+ return uint32(a)
+ }
+ return uint32(b)
+}
+
+const (
+ cbcMinPacketSizeMultiple = 8
+ cbcMinPacketSize = 16
+ cbcMinPaddingSize = 4
+)
+
+// cbcError represents a verification error that may leak information.
+type cbcError string
+
+func (e cbcError) Error() string { return string(e) }
+
+func (c *cbcCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
+ p, err := c.readPacketLeaky(seqNum, r)
+ if err != nil {
+ if _, ok := err.(cbcError); ok {
+ // Verification error: read a fixed amount of
+ // data, to make distinguishing between
+ // failing MAC and failing length check more
+ // difficult.
+ io.CopyN(ioutil.Discard, r, int64(c.oracleCamouflage))
+ }
+ }
+ return p, err
+}
+
+func (c *cbcCipher) readPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) {
+ blockSize := c.decrypter.BlockSize()
+
+ // Read the header, which will include some of the subsequent data in the
+ // case of block ciphers - this is copied back to the payload later.
+ // How many bytes of payload/padding will be read with this first read.
+ firstBlockLength := uint32((prefixLen + blockSize - 1) / blockSize * blockSize)
+ firstBlock := c.packetData[:firstBlockLength]
+ if _, err := io.ReadFull(r, firstBlock); err != nil {
+ return nil, err
+ }
+
+ c.oracleCamouflage = maxPacket + 4 + c.macSize - firstBlockLength
+
+ c.decrypter.CryptBlocks(firstBlock, firstBlock)
+ length := binary.BigEndian.Uint32(firstBlock[:4])
+ if length > maxPacket {
+ return nil, cbcError("ssh: packet too large")
+ }
+ if length+4 < maxUInt32(cbcMinPacketSize, blockSize) {
+ // The minimum size of a packet is 16 (or the cipher block size, whichever
+ // is larger) bytes.
+ return nil, cbcError("ssh: packet too small")
+ }
+ // The length of the packet (including the length field but not the MAC) must
+ // be a multiple of the block size or 8, whichever is larger.
+ if (length+4)%maxUInt32(cbcMinPacketSizeMultiple, blockSize) != 0 {
+ return nil, cbcError("ssh: invalid packet length multiple")
+ }
+
+ paddingLength := uint32(firstBlock[4])
+ if paddingLength < cbcMinPaddingSize || length <= paddingLength+1 {
+ return nil, cbcError("ssh: invalid packet length")
+ }
+
+ // Positions within the c.packetData buffer:
+ macStart := 4 + length
+ paddingStart := macStart - paddingLength
+
+ // Entire packet size, starting before length, ending at end of mac.
+ entirePacketSize := macStart + c.macSize
+
+ // Ensure c.packetData is large enough for the entire packet data.
+ if uint32(cap(c.packetData)) < entirePacketSize {
+ // Still need to upsize and copy, but this should be rare at runtime, only
+ // on upsizing the packetData buffer.
+ c.packetData = make([]byte, entirePacketSize)
+ copy(c.packetData, firstBlock)
+ } else {
+ c.packetData = c.packetData[:entirePacketSize]
+ }
+
+ if n, err := io.ReadFull(r, c.packetData[firstBlockLength:]); err != nil {
+ return nil, err
+ } else {
+ c.oracleCamouflage -= uint32(n)
+ }
+
+ remainingCrypted := c.packetData[firstBlockLength:macStart]
+ c.decrypter.CryptBlocks(remainingCrypted, remainingCrypted)
+
+ mac := c.packetData[macStart:]
+ if c.mac != nil {
+ c.mac.Reset()
+ binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum)
+ c.mac.Write(c.seqNumBytes[:])
+ c.mac.Write(c.packetData[:macStart])
+ c.macResult = c.mac.Sum(c.macResult[:0])
+ if subtle.ConstantTimeCompare(c.macResult, mac) != 1 {
+ return nil, cbcError("ssh: MAC failure")
+ }
+ }
+
+ return c.packetData[prefixLen:paddingStart], nil
+}
+
+func (c *cbcCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
+ effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize())
+
+ // Length of encrypted portion of the packet (header, payload, padding).
+ // Enforce minimum padding and packet size.
+ encLength := maxUInt32(prefixLen+len(packet)+cbcMinPaddingSize, cbcMinPaddingSize)
+ // Enforce block size.
+ encLength = (encLength + effectiveBlockSize - 1) / effectiveBlockSize * effectiveBlockSize
+
+ length := encLength - 4
+ paddingLength := int(length) - (1 + len(packet))
+
+ // Overall buffer contains: header, payload, padding, mac.
+ // Space for the MAC is reserved in the capacity but not the slice length.
+ bufferSize := encLength + c.macSize
+ if uint32(cap(c.packetData)) < bufferSize {
+ c.packetData = make([]byte, encLength, bufferSize)
+ } else {
+ c.packetData = c.packetData[:encLength]
+ }
+
+ p := c.packetData
+
+ // Packet header.
+ binary.BigEndian.PutUint32(p, length)
+ p = p[4:]
+ p[0] = byte(paddingLength)
+
+ // Payload.
+ p = p[1:]
+ copy(p, packet)
+
+ // Padding.
+ p = p[len(packet):]
+ if _, err := io.ReadFull(rand, p); err != nil {
+ return err
+ }
+
+ if c.mac != nil {
+ c.mac.Reset()
+ binary.BigEndian.PutUint32(c.seqNumBytes[:], seqNum)
+ c.mac.Write(c.seqNumBytes[:])
+ c.mac.Write(c.packetData)
+ // The MAC is now appended into the capacity reserved for it earlier.
+ c.packetData = c.mac.Sum(c.packetData)
+ }
+
+ c.encrypter.CryptBlocks(c.packetData[:encLength], c.packetData[:encLength])
+
+ if _, err := w.Write(c.packetData); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/client.go b/vendor/golang.org/x/crypto/ssh/client.go
new file mode 100644
index 0000000..a7e3263
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/client.go
@@ -0,0 +1,257 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "net"
+ "sync"
+ "time"
+)
+
+// Client implements a traditional SSH client that supports shells,
+// subprocesses, TCP port/streamlocal forwarding and tunneled dialing.
+type Client struct {
+ Conn
+
+ forwards forwardList // forwarded tcpip connections from the remote side
+ mu sync.Mutex
+ channelHandlers map[string]chan NewChannel
+}
+
+// HandleChannelOpen returns a channel on which NewChannel requests
+// for the given type are sent. If the type already is being handled,
+// nil is returned. The channel is closed when the connection is closed.
+func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if c.channelHandlers == nil {
+ // The SSH channel has been closed.
+ c := make(chan NewChannel)
+ close(c)
+ return c
+ }
+
+ ch := c.channelHandlers[channelType]
+ if ch != nil {
+ return nil
+ }
+
+ ch = make(chan NewChannel, chanSize)
+ c.channelHandlers[channelType] = ch
+ return ch
+}
+
+// NewClient creates a Client on top of the given connection.
+func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
+ conn := &Client{
+ Conn: c,
+ channelHandlers: make(map[string]chan NewChannel, 1),
+ }
+
+ go conn.handleGlobalRequests(reqs)
+ go conn.handleChannelOpens(chans)
+ go func() {
+ conn.Wait()
+ conn.forwards.closeAll()
+ }()
+ go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip"))
+ go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-streamlocal@openssh.com"))
+ return conn
+}
+
+// NewClientConn establishes an authenticated SSH connection using c
+// as the underlying transport. The Request and NewChannel channels
+// must be serviced or the connection will hang.
+func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) {
+ fullConf := *config
+ fullConf.SetDefaults()
+ if fullConf.HostKeyCallback == nil {
+ c.Close()
+ return nil, nil, nil, errors.New("ssh: must specify HostKeyCallback")
+ }
+
+ conn := &connection{
+ sshConn: sshConn{conn: c},
+ }
+
+ if err := conn.clientHandshake(addr, &fullConf); err != nil {
+ c.Close()
+ return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err)
+ }
+ conn.mux = newMux(conn.transport)
+ return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
+}
+
+// clientHandshake performs the client side key exchange. See RFC 4253 Section
+// 7.
+func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) error {
+ if config.ClientVersion != "" {
+ c.clientVersion = []byte(config.ClientVersion)
+ } else {
+ c.clientVersion = []byte(packageVersion)
+ }
+ var err error
+ c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion)
+ if err != nil {
+ return err
+ }
+
+ c.transport = newClientTransport(
+ newTransport(c.sshConn.conn, config.Rand, true /* is client */),
+ c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr())
+ if err := c.transport.waitSession(); err != nil {
+ return err
+ }
+
+ c.sessionID = c.transport.getSessionID()
+ return c.clientAuthenticate(config)
+}
+
+// verifyHostKeySignature verifies the host key obtained in the key
+// exchange.
+func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error {
+ sig, rest, ok := parseSignatureBody(result.Signature)
+ if len(rest) > 0 || !ok {
+ return errors.New("ssh: signature parse error")
+ }
+
+ return hostKey.Verify(result.H, sig)
+}
+
+// NewSession opens a new Session for this client. (A session is a remote
+// execution of a program.)
+func (c *Client) NewSession() (*Session, error) {
+ ch, in, err := c.OpenChannel("session", nil)
+ if err != nil {
+ return nil, err
+ }
+ return newSession(ch, in)
+}
+
+func (c *Client) handleGlobalRequests(incoming <-chan *Request) {
+ for r := range incoming {
+ // This handles keepalive messages and matches
+ // the behaviour of OpenSSH.
+ r.Reply(false, nil)
+ }
+}
+
+// handleChannelOpens channel open messages from the remote side.
+func (c *Client) handleChannelOpens(in <-chan NewChannel) {
+ for ch := range in {
+ c.mu.Lock()
+ handler := c.channelHandlers[ch.ChannelType()]
+ c.mu.Unlock()
+
+ if handler != nil {
+ handler <- ch
+ } else {
+ ch.Reject(UnknownChannelType, fmt.Sprintf("unknown channel type: %v", ch.ChannelType()))
+ }
+ }
+
+ c.mu.Lock()
+ for _, ch := range c.channelHandlers {
+ close(ch)
+ }
+ c.channelHandlers = nil
+ c.mu.Unlock()
+}
+
+// Dial starts a client connection to the given SSH server. It is a
+// convenience function that connects to the given network address,
+// initiates the SSH handshake, and then sets up a Client. For access
+// to incoming channels and requests, use net.Dial with NewClientConn
+// instead.
+func Dial(network, addr string, config *ClientConfig) (*Client, error) {
+ conn, err := net.DialTimeout(network, addr, config.Timeout)
+ if err != nil {
+ return nil, err
+ }
+ c, chans, reqs, err := NewClientConn(conn, addr, config)
+ if err != nil {
+ return nil, err
+ }
+ return NewClient(c, chans, reqs), nil
+}
+
+// HostKeyCallback is the function type used for verifying server
+// keys. A HostKeyCallback must return nil if the host key is OK, or
+// an error to reject it. It receives the hostname as passed to Dial
+// or NewClientConn. The remote address is the RemoteAddr of the
+// net.Conn underlying the the SSH connection.
+type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
+
+// A ClientConfig structure is used to configure a Client. It must not be
+// modified after having been passed to an SSH function.
+type ClientConfig struct {
+ // Config contains configuration that is shared between clients and
+ // servers.
+ Config
+
+ // User contains the username to authenticate as.
+ User string
+
+ // Auth contains possible authentication methods to use with the
+ // server. Only the first instance of a particular RFC 4252 method will
+ // be used during authentication.
+ Auth []AuthMethod
+
+ // HostKeyCallback is called during the cryptographic
+ // handshake to validate the server's host key. The client
+ // configuration must supply this callback for the connection
+ // to succeed. The functions InsecureIgnoreHostKey or
+ // FixedHostKey can be used for simplistic host key checks.
+ HostKeyCallback HostKeyCallback
+
+ // ClientVersion contains the version identification string that will
+ // be used for the connection. If empty, a reasonable default is used.
+ ClientVersion string
+
+ // HostKeyAlgorithms lists the key types that the client will
+ // accept from the server as host key, in order of
+ // preference. If empty, a reasonable default is used. Any
+ // string returned from PublicKey.Type method may be used, or
+ // any of the CertAlgoXxxx and KeyAlgoXxxx constants.
+ HostKeyAlgorithms []string
+
+ // Timeout is the maximum amount of time for the TCP connection to establish.
+ //
+ // A Timeout of zero means no timeout.
+ Timeout time.Duration
+}
+
+// InsecureIgnoreHostKey returns a function that can be used for
+// ClientConfig.HostKeyCallback to accept any host key. It should
+// not be used for production code.
+func InsecureIgnoreHostKey() HostKeyCallback {
+ return func(hostname string, remote net.Addr, key PublicKey) error {
+ return nil
+ }
+}
+
+type fixedHostKey struct {
+ key PublicKey
+}
+
+func (f *fixedHostKey) check(hostname string, remote net.Addr, key PublicKey) error {
+ if f.key == nil {
+ return fmt.Errorf("ssh: required host key was nil")
+ }
+ if !bytes.Equal(key.Marshal(), f.key.Marshal()) {
+ return fmt.Errorf("ssh: host key mismatch")
+ }
+ return nil
+}
+
+// FixedHostKey returns a function for use in
+// ClientConfig.HostKeyCallback to accept only a specific host key.
+func FixedHostKey(key PublicKey) HostKeyCallback {
+ hk := &fixedHostKey{key}
+ return hk.check
+}
diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go
new file mode 100644
index 0000000..b882da0
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/client_auth.go
@@ -0,0 +1,486 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+)
+
+// clientAuthenticate authenticates with the remote server. See RFC 4252.
+func (c *connection) clientAuthenticate(config *ClientConfig) error {
+ // initiate user auth session
+ if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil {
+ return err
+ }
+ packet, err := c.transport.readPacket()
+ if err != nil {
+ return err
+ }
+ var serviceAccept serviceAcceptMsg
+ if err := Unmarshal(packet, &serviceAccept); err != nil {
+ return err
+ }
+
+ // during the authentication phase the client first attempts the "none" method
+ // then any untried methods suggested by the server.
+ tried := make(map[string]bool)
+ var lastMethods []string
+
+ sessionID := c.transport.getSessionID()
+ for auth := AuthMethod(new(noneAuth)); auth != nil; {
+ ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand)
+ if err != nil {
+ return err
+ }
+ if ok {
+ // success
+ return nil
+ }
+ tried[auth.method()] = true
+ if methods == nil {
+ methods = lastMethods
+ }
+ lastMethods = methods
+
+ auth = nil
+
+ findNext:
+ for _, a := range config.Auth {
+ candidateMethod := a.method()
+ if tried[candidateMethod] {
+ continue
+ }
+ for _, meth := range methods {
+ if meth == candidateMethod {
+ auth = a
+ break findNext
+ }
+ }
+ }
+ }
+ return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried))
+}
+
+func keys(m map[string]bool) []string {
+ s := make([]string, 0, len(m))
+
+ for key := range m {
+ s = append(s, key)
+ }
+ return s
+}
+
+// An AuthMethod represents an instance of an RFC 4252 authentication method.
+type AuthMethod interface {
+ // auth authenticates user over transport t.
+ // Returns true if authentication is successful.
+ // If authentication is not successful, a []string of alternative
+ // method names is returned. If the slice is nil, it will be ignored
+ // and the previous set of possible methods will be reused.
+ auth(session []byte, user string, p packetConn, rand io.Reader) (bool, []string, error)
+
+ // method returns the RFC 4252 method name.
+ method() string
+}
+
+// "none" authentication, RFC 4252 section 5.2.
+type noneAuth int
+
+func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+ if err := c.writePacket(Marshal(&userAuthRequestMsg{
+ User: user,
+ Service: serviceSSH,
+ Method: "none",
+ })); err != nil {
+ return false, nil, err
+ }
+
+ return handleAuthResponse(c)
+}
+
+func (n *noneAuth) method() string {
+ return "none"
+}
+
+// passwordCallback is an AuthMethod that fetches the password through
+// a function call, e.g. by prompting the user.
+type passwordCallback func() (password string, err error)
+
+func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+ type passwordAuthMsg struct {
+ User string `sshtype:"50"`
+ Service string
+ Method string
+ Reply bool
+ Password string
+ }
+
+ pw, err := cb()
+ // REVIEW NOTE: is there a need to support skipping a password attempt?
+ // The program may only find out that the user doesn't have a password
+ // when prompting.
+ if err != nil {
+ return false, nil, err
+ }
+
+ if err := c.writePacket(Marshal(&passwordAuthMsg{
+ User: user,
+ Service: serviceSSH,
+ Method: cb.method(),
+ Reply: false,
+ Password: pw,
+ })); err != nil {
+ return false, nil, err
+ }
+
+ return handleAuthResponse(c)
+}
+
+func (cb passwordCallback) method() string {
+ return "password"
+}
+
+// Password returns an AuthMethod using the given password.
+func Password(secret string) AuthMethod {
+ return passwordCallback(func() (string, error) { return secret, nil })
+}
+
+// PasswordCallback returns an AuthMethod that uses a callback for
+// fetching a password.
+func PasswordCallback(prompt func() (secret string, err error)) AuthMethod {
+ return passwordCallback(prompt)
+}
+
+type publickeyAuthMsg struct {
+ User string `sshtype:"50"`
+ Service string
+ Method string
+ // HasSig indicates to the receiver packet that the auth request is signed and
+ // should be used for authentication of the request.
+ HasSig bool
+ Algoname string
+ PubKey []byte
+ // Sig is tagged with "rest" so Marshal will exclude it during
+ // validateKey
+ Sig []byte `ssh:"rest"`
+}
+
+// publicKeyCallback is an AuthMethod that uses a set of key
+// pairs for authentication.
+type publicKeyCallback func() ([]Signer, error)
+
+func (cb publicKeyCallback) method() string {
+ return "publickey"
+}
+
+func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+ // Authentication is performed by sending an enquiry to test if a key is
+ // acceptable to the remote. If the key is acceptable, the client will
+ // attempt to authenticate with the valid key. If not the client will repeat
+ // the process with the remaining keys.
+
+ signers, err := cb()
+ if err != nil {
+ return false, nil, err
+ }
+ var methods []string
+ for _, signer := range signers {
+ ok, err := validateKey(signer.PublicKey(), user, c)
+ if err != nil {
+ return false, nil, err
+ }
+ if !ok {
+ continue
+ }
+
+ pub := signer.PublicKey()
+ pubKey := pub.Marshal()
+ sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
+ User: user,
+ Service: serviceSSH,
+ Method: cb.method(),
+ }, []byte(pub.Type()), pubKey))
+ if err != nil {
+ return false, nil, err
+ }
+
+ // manually wrap the serialized signature in a string
+ s := Marshal(sign)
+ sig := make([]byte, stringLength(len(s)))
+ marshalString(sig, s)
+ msg := publickeyAuthMsg{
+ User: user,
+ Service: serviceSSH,
+ Method: cb.method(),
+ HasSig: true,
+ Algoname: pub.Type(),
+ PubKey: pubKey,
+ Sig: sig,
+ }
+ p := Marshal(&msg)
+ if err := c.writePacket(p); err != nil {
+ return false, nil, err
+ }
+ var success bool
+ success, methods, err = handleAuthResponse(c)
+ if err != nil {
+ return false, nil, err
+ }
+
+ // If authentication succeeds or the list of available methods does not
+ // contain the "publickey" method, do not attempt to authenticate with any
+ // other keys. According to RFC 4252 Section 7, the latter can occur when
+ // additional authentication methods are required.
+ if success || !containsMethod(methods, cb.method()) {
+ return success, methods, err
+ }
+ }
+
+ return false, methods, nil
+}
+
+func containsMethod(methods []string, method string) bool {
+ for _, m := range methods {
+ if m == method {
+ return true
+ }
+ }
+
+ return false
+}
+
+// validateKey validates the key provided is acceptable to the server.
+func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
+ pubKey := key.Marshal()
+ msg := publickeyAuthMsg{
+ User: user,
+ Service: serviceSSH,
+ Method: "publickey",
+ HasSig: false,
+ Algoname: key.Type(),
+ PubKey: pubKey,
+ }
+ if err := c.writePacket(Marshal(&msg)); err != nil {
+ return false, err
+ }
+
+ return confirmKeyAck(key, c)
+}
+
+func confirmKeyAck(key PublicKey, c packetConn) (bool, error) {
+ pubKey := key.Marshal()
+ algoname := key.Type()
+
+ for {
+ packet, err := c.readPacket()
+ if err != nil {
+ return false, err
+ }
+ switch packet[0] {
+ case msgUserAuthBanner:
+ // TODO(gpaul): add callback to present the banner to the user
+ case msgUserAuthPubKeyOk:
+ var msg userAuthPubKeyOkMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return false, err
+ }
+ if msg.Algo != algoname || !bytes.Equal(msg.PubKey, pubKey) {
+ return false, nil
+ }
+ return true, nil
+ case msgUserAuthFailure:
+ return false, nil
+ default:
+ return false, unexpectedMessageError(msgUserAuthSuccess, packet[0])
+ }
+ }
+}
+
+// PublicKeys returns an AuthMethod that uses the given key
+// pairs.
+func PublicKeys(signers ...Signer) AuthMethod {
+ return publicKeyCallback(func() ([]Signer, error) { return signers, nil })
+}
+
+// PublicKeysCallback returns an AuthMethod that runs the given
+// function to obtain a list of key pairs.
+func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod {
+ return publicKeyCallback(getSigners)
+}
+
+// handleAuthResponse returns whether the preceding authentication request succeeded
+// along with a list of remaining authentication methods to try next and
+// an error if an unexpected response was received.
+func handleAuthResponse(c packetConn) (bool, []string, error) {
+ for {
+ packet, err := c.readPacket()
+ if err != nil {
+ return false, nil, err
+ }
+
+ switch packet[0] {
+ case msgUserAuthBanner:
+ // TODO: add callback to present the banner to the user
+ case msgUserAuthFailure:
+ var msg userAuthFailureMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return false, nil, err
+ }
+ return false, msg.Methods, nil
+ case msgUserAuthSuccess:
+ return true, nil, nil
+ default:
+ return false, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
+ }
+ }
+}
+
+// KeyboardInteractiveChallenge should print questions, optionally
+// disabling echoing (e.g. for passwords), and return all the answers.
+// Challenge may be called multiple times in a single session. After
+// successful authentication, the server may send a challenge with no
+// questions, for which the user and instruction messages should be
+// printed. RFC 4256 section 3.3 details how the UI should behave for
+// both CLI and GUI environments.
+type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error)
+
+// KeyboardInteractive returns a AuthMethod using a prompt/response
+// sequence controlled by the server.
+func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod {
+ return challenge
+}
+
+func (cb KeyboardInteractiveChallenge) method() string {
+ return "keyboard-interactive"
+}
+
+func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) {
+ type initiateMsg struct {
+ User string `sshtype:"50"`
+ Service string
+ Method string
+ Language string
+ Submethods string
+ }
+
+ if err := c.writePacket(Marshal(&initiateMsg{
+ User: user,
+ Service: serviceSSH,
+ Method: "keyboard-interactive",
+ })); err != nil {
+ return false, nil, err
+ }
+
+ for {
+ packet, err := c.readPacket()
+ if err != nil {
+ return false, nil, err
+ }
+
+ // like handleAuthResponse, but with less options.
+ switch packet[0] {
+ case msgUserAuthBanner:
+ // TODO: Print banners during userauth.
+ continue
+ case msgUserAuthInfoRequest:
+ // OK
+ case msgUserAuthFailure:
+ var msg userAuthFailureMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return false, nil, err
+ }
+ return false, msg.Methods, nil
+ case msgUserAuthSuccess:
+ return true, nil, nil
+ default:
+ return false, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
+ }
+
+ var msg userAuthInfoRequestMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return false, nil, err
+ }
+
+ // Manually unpack the prompt/echo pairs.
+ rest := msg.Prompts
+ var prompts []string
+ var echos []bool
+ for i := 0; i < int(msg.NumPrompts); i++ {
+ prompt, r, ok := parseString(rest)
+ if !ok || len(r) == 0 {
+ return false, nil, errors.New("ssh: prompt format error")
+ }
+ prompts = append(prompts, string(prompt))
+ echos = append(echos, r[0] != 0)
+ rest = r[1:]
+ }
+
+ if len(rest) != 0 {
+ return false, nil, errors.New("ssh: extra data following keyboard-interactive pairs")
+ }
+
+ answers, err := cb(msg.User, msg.Instruction, prompts, echos)
+ if err != nil {
+ return false, nil, err
+ }
+
+ if len(answers) != len(prompts) {
+ return false, nil, errors.New("ssh: not enough answers from keyboard-interactive callback")
+ }
+ responseLength := 1 + 4
+ for _, a := range answers {
+ responseLength += stringLength(len(a))
+ }
+ serialized := make([]byte, responseLength)
+ p := serialized
+ p[0] = msgUserAuthInfoResponse
+ p = p[1:]
+ p = marshalUint32(p, uint32(len(answers)))
+ for _, a := range answers {
+ p = marshalString(p, []byte(a))
+ }
+
+ if err := c.writePacket(serialized); err != nil {
+ return false, nil, err
+ }
+ }
+}
+
+type retryableAuthMethod struct {
+ authMethod AuthMethod
+ maxTries int
+}
+
+func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok bool, methods []string, err error) {
+ for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ {
+ ok, methods, err = r.authMethod.auth(session, user, c, rand)
+ if ok || err != nil { // either success or error terminate
+ return ok, methods, err
+ }
+ }
+ return ok, methods, err
+}
+
+func (r *retryableAuthMethod) method() string {
+ return r.authMethod.method()
+}
+
+// RetryableAuthMethod is a decorator for other auth methods enabling them to
+// be retried up to maxTries before considering that AuthMethod itself failed.
+// If maxTries is <= 0, will retry indefinitely
+//
+// This is useful for interactive clients using challenge/response type
+// authentication (e.g. Keyboard-Interactive, Password, etc) where the user
+// could mistype their response resulting in the server issuing a
+// SSH_MSG_USERAUTH_FAILURE (rfc4252 #8 [password] and rfc4256 #3.4
+// [keyboard-interactive]); Without this decorator, the non-retryable
+// AuthMethod would be removed from future consideration, and never tried again
+// (and so the user would never be able to retry their entry).
+func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod {
+ return &retryableAuthMethod{authMethod: auth, maxTries: maxTries}
+}
diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go
new file mode 100644
index 0000000..dc39e4d
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/common.go
@@ -0,0 +1,373 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "crypto"
+ "crypto/rand"
+ "fmt"
+ "io"
+ "math"
+ "sync"
+
+ _ "crypto/sha1"
+ _ "crypto/sha256"
+ _ "crypto/sha512"
+)
+
+// These are string constants in the SSH protocol.
+const (
+ compressionNone = "none"
+ serviceUserAuth = "ssh-userauth"
+ serviceSSH = "ssh-connection"
+)
+
+// supportedCiphers specifies the supported ciphers in preference order.
+var supportedCiphers = []string{
+ "aes128-ctr", "aes192-ctr", "aes256-ctr",
+ "aes128-gcm@openssh.com",
+ "arcfour256", "arcfour128",
+}
+
+// supportedKexAlgos specifies the supported key-exchange algorithms in
+// preference order.
+var supportedKexAlgos = []string{
+ kexAlgoCurve25519SHA256,
+ // P384 and P521 are not constant-time yet, but since we don't
+ // reuse ephemeral keys, using them for ECDH should be OK.
+ kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
+ kexAlgoDH14SHA1, kexAlgoDH1SHA1,
+}
+
+// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
+// of authenticating servers) in preference order.
+var supportedHostKeyAlgos = []string{
+ CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
+ CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01,
+
+ KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
+ KeyAlgoRSA, KeyAlgoDSA,
+
+ KeyAlgoED25519,
+}
+
+// supportedMACs specifies a default set of MAC algorithms in preference order.
+// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
+// because they have reached the end of their useful life.
+var supportedMACs = []string{
+ "hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
+}
+
+var supportedCompressions = []string{compressionNone}
+
+// hashFuncs keeps the mapping of supported algorithms to their respective
+// hashes needed for signature verification.
+var hashFuncs = map[string]crypto.Hash{
+ KeyAlgoRSA: crypto.SHA1,
+ KeyAlgoDSA: crypto.SHA1,
+ KeyAlgoECDSA256: crypto.SHA256,
+ KeyAlgoECDSA384: crypto.SHA384,
+ KeyAlgoECDSA521: crypto.SHA512,
+ CertAlgoRSAv01: crypto.SHA1,
+ CertAlgoDSAv01: crypto.SHA1,
+ CertAlgoECDSA256v01: crypto.SHA256,
+ CertAlgoECDSA384v01: crypto.SHA384,
+ CertAlgoECDSA521v01: crypto.SHA512,
+}
+
+// unexpectedMessageError results when the SSH message that we received didn't
+// match what we wanted.
+func unexpectedMessageError(expected, got uint8) error {
+ return fmt.Errorf("ssh: unexpected message type %d (expected %d)", got, expected)
+}
+
+// parseError results from a malformed SSH message.
+func parseError(tag uint8) error {
+ return fmt.Errorf("ssh: parse error in message type %d", tag)
+}
+
+func findCommon(what string, client []string, server []string) (common string, err error) {
+ for _, c := range client {
+ for _, s := range server {
+ if c == s {
+ return c, nil
+ }
+ }
+ }
+ return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server)
+}
+
+type directionAlgorithms struct {
+ Cipher string
+ MAC string
+ Compression string
+}
+
+// rekeyBytes returns a rekeying intervals in bytes.
+func (a *directionAlgorithms) rekeyBytes() int64 {
+ // According to RFC4344 block ciphers should rekey after
+ // 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is
+ // 128.
+ switch a.Cipher {
+ case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcmCipherID, aes128cbcID:
+ return 16 * (1 << 32)
+
+ }
+
+ // For others, stick with RFC4253 recommendation to rekey after 1 Gb of data.
+ return 1 << 30
+}
+
+type algorithms struct {
+ kex string
+ hostKey string
+ w directionAlgorithms
+ r directionAlgorithms
+}
+
+func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) {
+ result := &algorithms{}
+
+ result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos)
+ if err != nil {
+ return
+ }
+
+ result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos)
+ if err != nil {
+ return
+ }
+
+ result.w.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer)
+ if err != nil {
+ return
+ }
+
+ result.r.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient)
+ if err != nil {
+ return
+ }
+
+ result.w.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
+ if err != nil {
+ return
+ }
+
+ result.r.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
+ if err != nil {
+ return
+ }
+
+ result.w.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
+ if err != nil {
+ return
+ }
+
+ result.r.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
+ if err != nil {
+ return
+ }
+
+ return result, nil
+}
+
+// If rekeythreshold is too small, we can't make any progress sending
+// stuff.
+const minRekeyThreshold uint64 = 256
+
+// Config contains configuration data common to both ServerConfig and
+// ClientConfig.
+type Config struct {
+ // Rand provides the source of entropy for cryptographic
+ // primitives. If Rand is nil, the cryptographic random reader
+ // in package crypto/rand will be used.
+ Rand io.Reader
+
+ // The maximum number of bytes sent or received after which a
+ // new key is negotiated. It must be at least 256. If
+ // unspecified, a size suitable for the chosen cipher is used.
+ RekeyThreshold uint64
+
+ // The allowed key exchanges algorithms. If unspecified then a
+ // default set of algorithms is used.
+ KeyExchanges []string
+
+ // The allowed cipher algorithms. If unspecified then a sensible
+ // default is used.
+ Ciphers []string
+
+ // The allowed MAC algorithms. If unspecified then a sensible default
+ // is used.
+ MACs []string
+}
+
+// SetDefaults sets sensible values for unset fields in config. This is
+// exported for testing: Configs passed to SSH functions are copied and have
+// default values set automatically.
+func (c *Config) SetDefaults() {
+ if c.Rand == nil {
+ c.Rand = rand.Reader
+ }
+ if c.Ciphers == nil {
+ c.Ciphers = supportedCiphers
+ }
+ var ciphers []string
+ for _, c := range c.Ciphers {
+ if cipherModes[c] != nil {
+ // reject the cipher if we have no cipherModes definition
+ ciphers = append(ciphers, c)
+ }
+ }
+ c.Ciphers = ciphers
+
+ if c.KeyExchanges == nil {
+ c.KeyExchanges = supportedKexAlgos
+ }
+
+ if c.MACs == nil {
+ c.MACs = supportedMACs
+ }
+
+ if c.RekeyThreshold == 0 {
+ // cipher specific default
+ } else if c.RekeyThreshold < minRekeyThreshold {
+ c.RekeyThreshold = minRekeyThreshold
+ } else if c.RekeyThreshold >= math.MaxInt64 {
+ // Avoid weirdness if somebody uses -1 as a threshold.
+ c.RekeyThreshold = math.MaxInt64
+ }
+}
+
+// buildDataSignedForAuth returns the data that is signed in order to prove
+// possession of a private key. See RFC 4252, section 7.
+func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {
+ data := struct {
+ Session []byte
+ Type byte
+ User string
+ Service string
+ Method string
+ Sign bool
+ Algo []byte
+ PubKey []byte
+ }{
+ sessionId,
+ msgUserAuthRequest,
+ req.User,
+ req.Service,
+ req.Method,
+ true,
+ algo,
+ pubKey,
+ }
+ return Marshal(data)
+}
+
+func appendU16(buf []byte, n uint16) []byte {
+ return append(buf, byte(n>>8), byte(n))
+}
+
+func appendU32(buf []byte, n uint32) []byte {
+ return append(buf, byte(n>>24), byte(n>>16), byte(n>>8), byte(n))
+}
+
+func appendU64(buf []byte, n uint64) []byte {
+ return append(buf,
+ byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32),
+ byte(n>>24), byte(n>>16), byte(n>>8), byte(n))
+}
+
+func appendInt(buf []byte, n int) []byte {
+ return appendU32(buf, uint32(n))
+}
+
+func appendString(buf []byte, s string) []byte {
+ buf = appendU32(buf, uint32(len(s)))
+ buf = append(buf, s...)
+ return buf
+}
+
+func appendBool(buf []byte, b bool) []byte {
+ if b {
+ return append(buf, 1)
+ }
+ return append(buf, 0)
+}
+
+// newCond is a helper to hide the fact that there is no usable zero
+// value for sync.Cond.
+func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) }
+
+// window represents the buffer available to clients
+// wishing to write to a channel.
+type window struct {
+ *sync.Cond
+ win uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1
+ writeWaiters int
+ closed bool
+}
+
+// add adds win to the amount of window available
+// for consumers.
+func (w *window) add(win uint32) bool {
+ // a zero sized window adjust is a noop.
+ if win == 0 {
+ return true
+ }
+ w.L.Lock()
+ if w.win+win < win {
+ w.L.Unlock()
+ return false
+ }
+ w.win += win
+ // It is unusual that multiple goroutines would be attempting to reserve
+ // window space, but not guaranteed. Use broadcast to notify all waiters
+ // that additional window is available.
+ w.Broadcast()
+ w.L.Unlock()
+ return true
+}
+
+// close sets the window to closed, so all reservations fail
+// immediately.
+func (w *window) close() {
+ w.L.Lock()
+ w.closed = true
+ w.Broadcast()
+ w.L.Unlock()
+}
+
+// reserve reserves win from the available window capacity.
+// If no capacity remains, reserve will block. reserve may
+// return less than requested.
+func (w *window) reserve(win uint32) (uint32, error) {
+ var err error
+ w.L.Lock()
+ w.writeWaiters++
+ w.Broadcast()
+ for w.win == 0 && !w.closed {
+ w.Wait()
+ }
+ w.writeWaiters--
+ if w.win < win {
+ win = w.win
+ }
+ w.win -= win
+ if w.closed {
+ err = io.EOF
+ }
+ w.L.Unlock()
+ return win, err
+}
+
+// waitWriterBlocked waits until some goroutine is blocked for further
+// writes. It is used in tests only.
+func (w *window) waitWriterBlocked() {
+ w.Cond.L.Lock()
+ for w.writeWaiters == 0 {
+ w.Cond.Wait()
+ }
+ w.Cond.L.Unlock()
+}
diff --git a/vendor/golang.org/x/crypto/ssh/connection.go b/vendor/golang.org/x/crypto/ssh/connection.go
new file mode 100644
index 0000000..fd6b068
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/connection.go
@@ -0,0 +1,143 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "fmt"
+ "net"
+)
+
+// OpenChannelError is returned if the other side rejects an
+// OpenChannel request.
+type OpenChannelError struct {
+ Reason RejectionReason
+ Message string
+}
+
+func (e *OpenChannelError) Error() string {
+ return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message)
+}
+
+// ConnMetadata holds metadata for the connection.
+type ConnMetadata interface {
+ // User returns the user ID for this connection.
+ User() string
+
+ // SessionID returns the session hash, also denoted by H.
+ SessionID() []byte
+
+ // ClientVersion returns the client's version string as hashed
+ // into the session ID.
+ ClientVersion() []byte
+
+ // ServerVersion returns the server's version string as hashed
+ // into the session ID.
+ ServerVersion() []byte
+
+ // RemoteAddr returns the remote address for this connection.
+ RemoteAddr() net.Addr
+
+ // LocalAddr returns the local address for this connection.
+ LocalAddr() net.Addr
+}
+
+// Conn represents an SSH connection for both server and client roles.
+// Conn is the basis for implementing an application layer, such
+// as ClientConn, which implements the traditional shell access for
+// clients.
+type Conn interface {
+ ConnMetadata
+
+ // SendRequest sends a global request, and returns the
+ // reply. If wantReply is true, it returns the response status
+ // and payload. See also RFC4254, section 4.
+ SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error)
+
+ // OpenChannel tries to open an channel. If the request is
+ // rejected, it returns *OpenChannelError. On success it returns
+ // the SSH Channel and a Go channel for incoming, out-of-band
+ // requests. The Go channel must be serviced, or the
+ // connection will hang.
+ OpenChannel(name string, data []byte) (Channel, <-chan *Request, error)
+
+ // Close closes the underlying network connection
+ Close() error
+
+ // Wait blocks until the connection has shut down, and returns the
+ // error causing the shutdown.
+ Wait() error
+
+ // TODO(hanwen): consider exposing:
+ // RequestKeyChange
+ // Disconnect
+}
+
+// DiscardRequests consumes and rejects all requests from the
+// passed-in channel.
+func DiscardRequests(in <-chan *Request) {
+ for req := range in {
+ if req.WantReply {
+ req.Reply(false, nil)
+ }
+ }
+}
+
+// A connection represents an incoming connection.
+type connection struct {
+ transport *handshakeTransport
+ sshConn
+
+ // The connection protocol.
+ *mux
+}
+
+func (c *connection) Close() error {
+ return c.sshConn.conn.Close()
+}
+
+// sshconn provides net.Conn metadata, but disallows direct reads and
+// writes.
+type sshConn struct {
+ conn net.Conn
+
+ user string
+ sessionID []byte
+ clientVersion []byte
+ serverVersion []byte
+}
+
+func dup(src []byte) []byte {
+ dst := make([]byte, len(src))
+ copy(dst, src)
+ return dst
+}
+
+func (c *sshConn) User() string {
+ return c.user
+}
+
+func (c *sshConn) RemoteAddr() net.Addr {
+ return c.conn.RemoteAddr()
+}
+
+func (c *sshConn) Close() error {
+ return c.conn.Close()
+}
+
+func (c *sshConn) LocalAddr() net.Addr {
+ return c.conn.LocalAddr()
+}
+
+func (c *sshConn) SessionID() []byte {
+ return dup(c.sessionID)
+}
+
+func (c *sshConn) ClientVersion() []byte {
+ return dup(c.clientVersion)
+}
+
+func (c *sshConn) ServerVersion() []byte {
+ return dup(c.serverVersion)
+}
diff --git a/vendor/golang.org/x/crypto/ssh/doc.go b/vendor/golang.org/x/crypto/ssh/doc.go
new file mode 100644
index 0000000..67b7322
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/doc.go
@@ -0,0 +1,21 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package ssh implements an SSH client and server.
+
+SSH is a transport security protocol, an authentication protocol and a
+family of application protocols. The most typical application level
+protocol is a remote shell and this is specifically implemented. However,
+the multiplexed nature of SSH is exposed to users that wish to support
+others.
+
+References:
+ [PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
+ [SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
+
+This package does not fall under the stability promise of the Go language itself,
+so its API may be changed when pressing needs arise.
+*/
+package ssh // import "golang.org/x/crypto/ssh"
diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
new file mode 100644
index 0000000..932ce83
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
@@ -0,0 +1,640 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "crypto/rand"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "net"
+ "sync"
+)
+
+// debugHandshake, if set, prints messages sent and received. Key
+// exchange messages are printed as if DH were used, so the debug
+// messages are wrong when using ECDH.
+const debugHandshake = false
+
+// chanSize sets the amount of buffering SSH connections. This is
+// primarily for testing: setting chanSize=0 uncovers deadlocks more
+// quickly.
+const chanSize = 16
+
+// keyingTransport is a packet based transport that supports key
+// changes. It need not be thread-safe. It should pass through
+// msgNewKeys in both directions.
+type keyingTransport interface {
+ packetConn
+
+ // prepareKeyChange sets up a key change. The key change for a
+ // direction will be effected if a msgNewKeys message is sent
+ // or received.
+ prepareKeyChange(*algorithms, *kexResult) error
+}
+
+// handshakeTransport implements rekeying on top of a keyingTransport
+// and offers a thread-safe writePacket() interface.
+type handshakeTransport struct {
+ conn keyingTransport
+ config *Config
+
+ serverVersion []byte
+ clientVersion []byte
+
+ // hostKeys is non-empty if we are the server. In that case,
+ // it contains all host keys that can be used to sign the
+ // connection.
+ hostKeys []Signer
+
+ // hostKeyAlgorithms is non-empty if we are the client. In that case,
+ // we accept these key types from the server as host key.
+ hostKeyAlgorithms []string
+
+ // On read error, incoming is closed, and readError is set.
+ incoming chan []byte
+ readError error
+
+ mu sync.Mutex
+ writeError error
+ sentInitPacket []byte
+ sentInitMsg *kexInitMsg
+ pendingPackets [][]byte // Used when a key exchange is in progress.
+
+ // If the read loop wants to schedule a kex, it pings this
+ // channel, and the write loop will send out a kex
+ // message.
+ requestKex chan struct{}
+
+ // If the other side requests or confirms a kex, its kexInit
+ // packet is sent here for the write loop to find it.
+ startKex chan *pendingKex
+
+ // data for host key checking
+ hostKeyCallback HostKeyCallback
+ dialAddress string
+ remoteAddr net.Addr
+
+ // Algorithms agreed in the last key exchange.
+ algorithms *algorithms
+
+ readPacketsLeft uint32
+ readBytesLeft int64
+
+ writePacketsLeft uint32
+ writeBytesLeft int64
+
+ // The session ID or nil if first kex did not complete yet.
+ sessionID []byte
+}
+
+type pendingKex struct {
+ otherInit []byte
+ done chan error
+}
+
+func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport {
+ t := &handshakeTransport{
+ conn: conn,
+ serverVersion: serverVersion,
+ clientVersion: clientVersion,
+ incoming: make(chan []byte, chanSize),
+ requestKex: make(chan struct{}, 1),
+ startKex: make(chan *pendingKex, 1),
+
+ config: config,
+ }
+ t.resetReadThresholds()
+ t.resetWriteThresholds()
+
+ // We always start with a mandatory key exchange.
+ t.requestKex <- struct{}{}
+ return t
+}
+
+func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ClientConfig, dialAddr string, addr net.Addr) *handshakeTransport {
+ t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
+ t.dialAddress = dialAddr
+ t.remoteAddr = addr
+ t.hostKeyCallback = config.HostKeyCallback
+ if config.HostKeyAlgorithms != nil {
+ t.hostKeyAlgorithms = config.HostKeyAlgorithms
+ } else {
+ t.hostKeyAlgorithms = supportedHostKeyAlgos
+ }
+ go t.readLoop()
+ go t.kexLoop()
+ return t
+}
+
+func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ServerConfig) *handshakeTransport {
+ t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
+ t.hostKeys = config.hostKeys
+ go t.readLoop()
+ go t.kexLoop()
+ return t
+}
+
+func (t *handshakeTransport) getSessionID() []byte {
+ return t.sessionID
+}
+
+// waitSession waits for the session to be established. This should be
+// the first thing to call after instantiating handshakeTransport.
+func (t *handshakeTransport) waitSession() error {
+ p, err := t.readPacket()
+ if err != nil {
+ return err
+ }
+ if p[0] != msgNewKeys {
+ return fmt.Errorf("ssh: first packet should be msgNewKeys")
+ }
+
+ return nil
+}
+
+func (t *handshakeTransport) id() string {
+ if len(t.hostKeys) > 0 {
+ return "server"
+ }
+ return "client"
+}
+
+func (t *handshakeTransport) printPacket(p []byte, write bool) {
+ action := "got"
+ if write {
+ action = "sent"
+ }
+
+ if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
+ log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p))
+ } else {
+ msg, err := decode(p)
+ log.Printf("%s %s %T %v (%v)", t.id(), action, msg, msg, err)
+ }
+}
+
+func (t *handshakeTransport) readPacket() ([]byte, error) {
+ p, ok := <-t.incoming
+ if !ok {
+ return nil, t.readError
+ }
+ return p, nil
+}
+
+func (t *handshakeTransport) readLoop() {
+ first := true
+ for {
+ p, err := t.readOnePacket(first)
+ first = false
+ if err != nil {
+ t.readError = err
+ close(t.incoming)
+ break
+ }
+ if p[0] == msgIgnore || p[0] == msgDebug {
+ continue
+ }
+ t.incoming <- p
+ }
+
+ // Stop writers too.
+ t.recordWriteError(t.readError)
+
+ // Unblock the writer should it wait for this.
+ close(t.startKex)
+
+ // Don't close t.requestKex; it's also written to from writePacket.
+}
+
+func (t *handshakeTransport) pushPacket(p []byte) error {
+ if debugHandshake {
+ t.printPacket(p, true)
+ }
+ return t.conn.writePacket(p)
+}
+
+func (t *handshakeTransport) getWriteError() error {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ return t.writeError
+}
+
+func (t *handshakeTransport) recordWriteError(err error) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.writeError == nil && err != nil {
+ t.writeError = err
+ }
+}
+
+func (t *handshakeTransport) requestKeyExchange() {
+ select {
+ case t.requestKex <- struct{}{}:
+ default:
+ // something already requested a kex, so do nothing.
+ }
+}
+
+func (t *handshakeTransport) resetWriteThresholds() {
+ t.writePacketsLeft = packetRekeyThreshold
+ if t.config.RekeyThreshold > 0 {
+ t.writeBytesLeft = int64(t.config.RekeyThreshold)
+ } else if t.algorithms != nil {
+ t.writeBytesLeft = t.algorithms.w.rekeyBytes()
+ } else {
+ t.writeBytesLeft = 1 << 30
+ }
+}
+
+func (t *handshakeTransport) kexLoop() {
+
+write:
+ for t.getWriteError() == nil {
+ var request *pendingKex
+ var sent bool
+
+ for request == nil || !sent {
+ var ok bool
+ select {
+ case request, ok = <-t.startKex:
+ if !ok {
+ break write
+ }
+ case <-t.requestKex:
+ break
+ }
+
+ if !sent {
+ if err := t.sendKexInit(); err != nil {
+ t.recordWriteError(err)
+ break
+ }
+ sent = true
+ }
+ }
+
+ if err := t.getWriteError(); err != nil {
+ if request != nil {
+ request.done <- err
+ }
+ break
+ }
+
+ // We're not servicing t.requestKex, but that is OK:
+ // we never block on sending to t.requestKex.
+
+ // We're not servicing t.startKex, but the remote end
+ // has just sent us a kexInitMsg, so it can't send
+ // another key change request, until we close the done
+ // channel on the pendingKex request.
+
+ err := t.enterKeyExchange(request.otherInit)
+
+ t.mu.Lock()
+ t.writeError = err
+ t.sentInitPacket = nil
+ t.sentInitMsg = nil
+
+ t.resetWriteThresholds()
+
+ // we have completed the key exchange. Since the
+ // reader is still blocked, it is safe to clear out
+ // the requestKex channel. This avoids the situation
+ // where: 1) we consumed our own request for the
+ // initial kex, and 2) the kex from the remote side
+ // caused another send on the requestKex channel,
+ clear:
+ for {
+ select {
+ case <-t.requestKex:
+ //
+ default:
+ break clear
+ }
+ }
+
+ request.done <- t.writeError
+
+ // kex finished. Push packets that we received while
+ // the kex was in progress. Don't look at t.startKex
+ // and don't increment writtenSinceKex: if we trigger
+ // another kex while we are still busy with the last
+ // one, things will become very confusing.
+ for _, p := range t.pendingPackets {
+ t.writeError = t.pushPacket(p)
+ if t.writeError != nil {
+ break
+ }
+ }
+ t.pendingPackets = t.pendingPackets[:0]
+ t.mu.Unlock()
+ }
+
+ // drain startKex channel. We don't service t.requestKex
+ // because nobody does blocking sends there.
+ go func() {
+ for init := range t.startKex {
+ init.done <- t.writeError
+ }
+ }()
+
+ // Unblock reader.
+ t.conn.Close()
+}
+
+// The protocol uses uint32 for packet counters, so we can't let them
+// reach 1<<32. We will actually read and write more packets than
+// this, though: the other side may send more packets, and after we
+// hit this limit on writing we will send a few more packets for the
+// key exchange itself.
+const packetRekeyThreshold = (1 << 31)
+
+func (t *handshakeTransport) resetReadThresholds() {
+ t.readPacketsLeft = packetRekeyThreshold
+ if t.config.RekeyThreshold > 0 {
+ t.readBytesLeft = int64(t.config.RekeyThreshold)
+ } else if t.algorithms != nil {
+ t.readBytesLeft = t.algorithms.r.rekeyBytes()
+ } else {
+ t.readBytesLeft = 1 << 30
+ }
+}
+
+func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
+ p, err := t.conn.readPacket()
+ if err != nil {
+ return nil, err
+ }
+
+ if t.readPacketsLeft > 0 {
+ t.readPacketsLeft--
+ } else {
+ t.requestKeyExchange()
+ }
+
+ if t.readBytesLeft > 0 {
+ t.readBytesLeft -= int64(len(p))
+ } else {
+ t.requestKeyExchange()
+ }
+
+ if debugHandshake {
+ t.printPacket(p, false)
+ }
+
+ if first && p[0] != msgKexInit {
+ return nil, fmt.Errorf("ssh: first packet should be msgKexInit")
+ }
+
+ if p[0] != msgKexInit {
+ return p, nil
+ }
+
+ firstKex := t.sessionID == nil
+
+ kex := pendingKex{
+ done: make(chan error, 1),
+ otherInit: p,
+ }
+ t.startKex <- &kex
+ err = <-kex.done
+
+ if debugHandshake {
+ log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ t.resetReadThresholds()
+
+ // By default, a key exchange is hidden from higher layers by
+ // translating it into msgIgnore.
+ successPacket := []byte{msgIgnore}
+ if firstKex {
+ // sendKexInit() for the first kex waits for
+ // msgNewKeys so the authentication process is
+ // guaranteed to happen over an encrypted transport.
+ successPacket = []byte{msgNewKeys}
+ }
+
+ return successPacket, nil
+}
+
+// sendKexInit sends a key change message.
+func (t *handshakeTransport) sendKexInit() error {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.sentInitMsg != nil {
+ // kexInits may be sent either in response to the other side,
+ // or because our side wants to initiate a key change, so we
+ // may have already sent a kexInit. In that case, don't send a
+ // second kexInit.
+ return nil
+ }
+
+ msg := &kexInitMsg{
+ KexAlgos: t.config.KeyExchanges,
+ CiphersClientServer: t.config.Ciphers,
+ CiphersServerClient: t.config.Ciphers,
+ MACsClientServer: t.config.MACs,
+ MACsServerClient: t.config.MACs,
+ CompressionClientServer: supportedCompressions,
+ CompressionServerClient: supportedCompressions,
+ }
+ io.ReadFull(rand.Reader, msg.Cookie[:])
+
+ if len(t.hostKeys) > 0 {
+ for _, k := range t.hostKeys {
+ msg.ServerHostKeyAlgos = append(
+ msg.ServerHostKeyAlgos, k.PublicKey().Type())
+ }
+ } else {
+ msg.ServerHostKeyAlgos = t.hostKeyAlgorithms
+ }
+ packet := Marshal(msg)
+
+ // writePacket destroys the contents, so save a copy.
+ packetCopy := make([]byte, len(packet))
+ copy(packetCopy, packet)
+
+ if err := t.pushPacket(packetCopy); err != nil {
+ return err
+ }
+
+ t.sentInitMsg = msg
+ t.sentInitPacket = packet
+
+ return nil
+}
+
+func (t *handshakeTransport) writePacket(p []byte) error {
+ switch p[0] {
+ case msgKexInit:
+ return errors.New("ssh: only handshakeTransport can send kexInit")
+ case msgNewKeys:
+ return errors.New("ssh: only handshakeTransport can send newKeys")
+ }
+
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.writeError != nil {
+ return t.writeError
+ }
+
+ if t.sentInitMsg != nil {
+ // Copy the packet so the writer can reuse the buffer.
+ cp := make([]byte, len(p))
+ copy(cp, p)
+ t.pendingPackets = append(t.pendingPackets, cp)
+ return nil
+ }
+
+ if t.writeBytesLeft > 0 {
+ t.writeBytesLeft -= int64(len(p))
+ } else {
+ t.requestKeyExchange()
+ }
+
+ if t.writePacketsLeft > 0 {
+ t.writePacketsLeft--
+ } else {
+ t.requestKeyExchange()
+ }
+
+ if err := t.pushPacket(p); err != nil {
+ t.writeError = err
+ }
+
+ return nil
+}
+
+func (t *handshakeTransport) Close() error {
+ return t.conn.Close()
+}
+
+func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
+ if debugHandshake {
+ log.Printf("%s entered key exchange", t.id())
+ }
+
+ otherInit := &kexInitMsg{}
+ if err := Unmarshal(otherInitPacket, otherInit); err != nil {
+ return err
+ }
+
+ magics := handshakeMagics{
+ clientVersion: t.clientVersion,
+ serverVersion: t.serverVersion,
+ clientKexInit: otherInitPacket,
+ serverKexInit: t.sentInitPacket,
+ }
+
+ clientInit := otherInit
+ serverInit := t.sentInitMsg
+ if len(t.hostKeys) == 0 {
+ clientInit, serverInit = serverInit, clientInit
+
+ magics.clientKexInit = t.sentInitPacket
+ magics.serverKexInit = otherInitPacket
+ }
+
+ var err error
+ t.algorithms, err = findAgreedAlgorithms(clientInit, serverInit)
+ if err != nil {
+ return err
+ }
+
+ // We don't send FirstKexFollows, but we handle receiving it.
+ //
+ // RFC 4253 section 7 defines the kex and the agreement method for
+ // first_kex_packet_follows. It states that the guessed packet
+ // should be ignored if the "kex algorithm and/or the host
+ // key algorithm is guessed wrong (server and client have
+ // different preferred algorithm), or if any of the other
+ // algorithms cannot be agreed upon". The other algorithms have
+ // already been checked above so the kex algorithm and host key
+ // algorithm are checked here.
+ if otherInit.FirstKexFollows && (clientInit.KexAlgos[0] != serverInit.KexAlgos[0] || clientInit.ServerHostKeyAlgos[0] != serverInit.ServerHostKeyAlgos[0]) {
+ // other side sent a kex message for the wrong algorithm,
+ // which we have to ignore.
+ if _, err := t.conn.readPacket(); err != nil {
+ return err
+ }
+ }
+
+ kex, ok := kexAlgoMap[t.algorithms.kex]
+ if !ok {
+ return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex)
+ }
+
+ var result *kexResult
+ if len(t.hostKeys) > 0 {
+ result, err = t.server(kex, t.algorithms, &magics)
+ } else {
+ result, err = t.client(kex, t.algorithms, &magics)
+ }
+
+ if err != nil {
+ return err
+ }
+
+ if t.sessionID == nil {
+ t.sessionID = result.H
+ }
+ result.SessionID = t.sessionID
+
+ if err := t.conn.prepareKeyChange(t.algorithms, result); err != nil {
+ return err
+ }
+ if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
+ return err
+ }
+ if packet, err := t.conn.readPacket(); err != nil {
+ return err
+ } else if packet[0] != msgNewKeys {
+ return unexpectedMessageError(msgNewKeys, packet[0])
+ }
+
+ return nil
+}
+
+func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) {
+ var hostKey Signer
+ for _, k := range t.hostKeys {
+ if algs.hostKey == k.PublicKey().Type() {
+ hostKey = k
+ }
+ }
+
+ r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey)
+ return r, err
+}
+
+func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) {
+ result, err := kex.Client(t.conn, t.config.Rand, magics)
+ if err != nil {
+ return nil, err
+ }
+
+ hostKey, err := ParsePublicKey(result.HostKey)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := verifyHostKeySignature(hostKey, result); err != nil {
+ return nil, err
+ }
+
+ err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go
new file mode 100644
index 0000000..f91c277
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/kex.go
@@ -0,0 +1,540 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/subtle"
+ "errors"
+ "io"
+ "math/big"
+
+ "golang.org/x/crypto/curve25519"
+)
+
+const (
+ kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1"
+ kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
+ kexAlgoECDH256 = "ecdh-sha2-nistp256"
+ kexAlgoECDH384 = "ecdh-sha2-nistp384"
+ kexAlgoECDH521 = "ecdh-sha2-nistp521"
+ kexAlgoCurve25519SHA256 = "curve25519-sha256@libssh.org"
+)
+
+// kexResult captures the outcome of a key exchange.
+type kexResult struct {
+ // Session hash. See also RFC 4253, section 8.
+ H []byte
+
+ // Shared secret. See also RFC 4253, section 8.
+ K []byte
+
+ // Host key as hashed into H.
+ HostKey []byte
+
+ // Signature of H.
+ Signature []byte
+
+ // A cryptographic hash function that matches the security
+ // level of the key exchange algorithm. It is used for
+ // calculating H, and for deriving keys from H and K.
+ Hash crypto.Hash
+
+ // The session ID, which is the first H computed. This is used
+ // to derive key material inside the transport.
+ SessionID []byte
+}
+
+// handshakeMagics contains data that is always included in the
+// session hash.
+type handshakeMagics struct {
+ clientVersion, serverVersion []byte
+ clientKexInit, serverKexInit []byte
+}
+
+func (m *handshakeMagics) write(w io.Writer) {
+ writeString(w, m.clientVersion)
+ writeString(w, m.serverVersion)
+ writeString(w, m.clientKexInit)
+ writeString(w, m.serverKexInit)
+}
+
+// kexAlgorithm abstracts different key exchange algorithms.
+type kexAlgorithm interface {
+ // Server runs server-side key agreement, signing the result
+ // with a hostkey.
+ Server(p packetConn, rand io.Reader, magics *handshakeMagics, s Signer) (*kexResult, error)
+
+ // Client runs the client-side key agreement. Caller is
+ // responsible for verifying the host key signature.
+ Client(p packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error)
+}
+
+// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
+type dhGroup struct {
+ g, p, pMinus1 *big.Int
+}
+
+func (group *dhGroup) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, error) {
+ if theirPublic.Cmp(bigOne) <= 0 || theirPublic.Cmp(group.pMinus1) >= 0 {
+ return nil, errors.New("ssh: DH parameter out of bounds")
+ }
+ return new(big.Int).Exp(theirPublic, myPrivate, group.p), nil
+}
+
+func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
+ hashFunc := crypto.SHA1
+
+ var x *big.Int
+ for {
+ var err error
+ if x, err = rand.Int(randSource, group.pMinus1); err != nil {
+ return nil, err
+ }
+ if x.Sign() > 0 {
+ break
+ }
+ }
+
+ X := new(big.Int).Exp(group.g, x, group.p)
+ kexDHInit := kexDHInitMsg{
+ X: X,
+ }
+ if err := c.writePacket(Marshal(&kexDHInit)); err != nil {
+ return nil, err
+ }
+
+ packet, err := c.readPacket()
+ if err != nil {
+ return nil, err
+ }
+
+ var kexDHReply kexDHReplyMsg
+ if err = Unmarshal(packet, &kexDHReply); err != nil {
+ return nil, err
+ }
+
+ kInt, err := group.diffieHellman(kexDHReply.Y, x)
+ if err != nil {
+ return nil, err
+ }
+
+ h := hashFunc.New()
+ magics.write(h)
+ writeString(h, kexDHReply.HostKey)
+ writeInt(h, X)
+ writeInt(h, kexDHReply.Y)
+ K := make([]byte, intLength(kInt))
+ marshalInt(K, kInt)
+ h.Write(K)
+
+ return &kexResult{
+ H: h.Sum(nil),
+ K: K,
+ HostKey: kexDHReply.HostKey,
+ Signature: kexDHReply.Signature,
+ Hash: crypto.SHA1,
+ }, nil
+}
+
+func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+ hashFunc := crypto.SHA1
+ packet, err := c.readPacket()
+ if err != nil {
+ return
+ }
+ var kexDHInit kexDHInitMsg
+ if err = Unmarshal(packet, &kexDHInit); err != nil {
+ return
+ }
+
+ var y *big.Int
+ for {
+ if y, err = rand.Int(randSource, group.pMinus1); err != nil {
+ return
+ }
+ if y.Sign() > 0 {
+ break
+ }
+ }
+
+ Y := new(big.Int).Exp(group.g, y, group.p)
+ kInt, err := group.diffieHellman(kexDHInit.X, y)
+ if err != nil {
+ return nil, err
+ }
+
+ hostKeyBytes := priv.PublicKey().Marshal()
+
+ h := hashFunc.New()
+ magics.write(h)
+ writeString(h, hostKeyBytes)
+ writeInt(h, kexDHInit.X)
+ writeInt(h, Y)
+
+ K := make([]byte, intLength(kInt))
+ marshalInt(K, kInt)
+ h.Write(K)
+
+ H := h.Sum(nil)
+
+ // H is already a hash, but the hostkey signing will apply its
+ // own key-specific hash algorithm.
+ sig, err := signAndMarshal(priv, randSource, H)
+ if err != nil {
+ return nil, err
+ }
+
+ kexDHReply := kexDHReplyMsg{
+ HostKey: hostKeyBytes,
+ Y: Y,
+ Signature: sig,
+ }
+ packet = Marshal(&kexDHReply)
+
+ err = c.writePacket(packet)
+ return &kexResult{
+ H: H,
+ K: K,
+ HostKey: hostKeyBytes,
+ Signature: sig,
+ Hash: crypto.SHA1,
+ }, nil
+}
+
+// ecdh performs Elliptic Curve Diffie-Hellman key exchange as
+// described in RFC 5656, section 4.
+type ecdh struct {
+ curve elliptic.Curve
+}
+
+func (kex *ecdh) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
+ ephKey, err := ecdsa.GenerateKey(kex.curve, rand)
+ if err != nil {
+ return nil, err
+ }
+
+ kexInit := kexECDHInitMsg{
+ ClientPubKey: elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y),
+ }
+
+ serialized := Marshal(&kexInit)
+ if err := c.writePacket(serialized); err != nil {
+ return nil, err
+ }
+
+ packet, err := c.readPacket()
+ if err != nil {
+ return nil, err
+ }
+
+ var reply kexECDHReplyMsg
+ if err = Unmarshal(packet, &reply); err != nil {
+ return nil, err
+ }
+
+ x, y, err := unmarshalECKey(kex.curve, reply.EphemeralPubKey)
+ if err != nil {
+ return nil, err
+ }
+
+ // generate shared secret
+ secret, _ := kex.curve.ScalarMult(x, y, ephKey.D.Bytes())
+
+ h := ecHash(kex.curve).New()
+ magics.write(h)
+ writeString(h, reply.HostKey)
+ writeString(h, kexInit.ClientPubKey)
+ writeString(h, reply.EphemeralPubKey)
+ K := make([]byte, intLength(secret))
+ marshalInt(K, secret)
+ h.Write(K)
+
+ return &kexResult{
+ H: h.Sum(nil),
+ K: K,
+ HostKey: reply.HostKey,
+ Signature: reply.Signature,
+ Hash: ecHash(kex.curve),
+ }, nil
+}
+
+// unmarshalECKey parses and checks an EC key.
+func unmarshalECKey(curve elliptic.Curve, pubkey []byte) (x, y *big.Int, err error) {
+ x, y = elliptic.Unmarshal(curve, pubkey)
+ if x == nil {
+ return nil, nil, errors.New("ssh: elliptic.Unmarshal failure")
+ }
+ if !validateECPublicKey(curve, x, y) {
+ return nil, nil, errors.New("ssh: public key not on curve")
+ }
+ return x, y, nil
+}
+
+// validateECPublicKey checks that the point is a valid public key for
+// the given curve. See [SEC1], 3.2.2
+func validateECPublicKey(curve elliptic.Curve, x, y *big.Int) bool {
+ if x.Sign() == 0 && y.Sign() == 0 {
+ return false
+ }
+
+ if x.Cmp(curve.Params().P) >= 0 {
+ return false
+ }
+
+ if y.Cmp(curve.Params().P) >= 0 {
+ return false
+ }
+
+ if !curve.IsOnCurve(x, y) {
+ return false
+ }
+
+ // We don't check if N * PubKey == 0, since
+ //
+ // - the NIST curves have cofactor = 1, so this is implicit.
+ // (We don't foresee an implementation that supports non NIST
+ // curves)
+ //
+ // - for ephemeral keys, we don't need to worry about small
+ // subgroup attacks.
+ return true
+}
+
+func (kex *ecdh) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+ packet, err := c.readPacket()
+ if err != nil {
+ return nil, err
+ }
+
+ var kexECDHInit kexECDHInitMsg
+ if err = Unmarshal(packet, &kexECDHInit); err != nil {
+ return nil, err
+ }
+
+ clientX, clientY, err := unmarshalECKey(kex.curve, kexECDHInit.ClientPubKey)
+ if err != nil {
+ return nil, err
+ }
+
+ // We could cache this key across multiple users/multiple
+ // connection attempts, but the benefit is small. OpenSSH
+ // generates a new key for each incoming connection.
+ ephKey, err := ecdsa.GenerateKey(kex.curve, rand)
+ if err != nil {
+ return nil, err
+ }
+
+ hostKeyBytes := priv.PublicKey().Marshal()
+
+ serializedEphKey := elliptic.Marshal(kex.curve, ephKey.PublicKey.X, ephKey.PublicKey.Y)
+
+ // generate shared secret
+ secret, _ := kex.curve.ScalarMult(clientX, clientY, ephKey.D.Bytes())
+
+ h := ecHash(kex.curve).New()
+ magics.write(h)
+ writeString(h, hostKeyBytes)
+ writeString(h, kexECDHInit.ClientPubKey)
+ writeString(h, serializedEphKey)
+
+ K := make([]byte, intLength(secret))
+ marshalInt(K, secret)
+ h.Write(K)
+
+ H := h.Sum(nil)
+
+ // H is already a hash, but the hostkey signing will apply its
+ // own key-specific hash algorithm.
+ sig, err := signAndMarshal(priv, rand, H)
+ if err != nil {
+ return nil, err
+ }
+
+ reply := kexECDHReplyMsg{
+ EphemeralPubKey: serializedEphKey,
+ HostKey: hostKeyBytes,
+ Signature: sig,
+ }
+
+ serialized := Marshal(&reply)
+ if err := c.writePacket(serialized); err != nil {
+ return nil, err
+ }
+
+ return &kexResult{
+ H: H,
+ K: K,
+ HostKey: reply.HostKey,
+ Signature: sig,
+ Hash: ecHash(kex.curve),
+ }, nil
+}
+
+var kexAlgoMap = map[string]kexAlgorithm{}
+
+func init() {
+ // This is the group called diffie-hellman-group1-sha1 in RFC
+ // 4253 and Oakley Group 2 in RFC 2409.
+ p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
+ kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
+ g: new(big.Int).SetInt64(2),
+ p: p,
+ pMinus1: new(big.Int).Sub(p, bigOne),
+ }
+
+ // This is the group called diffie-hellman-group14-sha1 in RFC
+ // 4253 and Oakley Group 14 in RFC 3526.
+ p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
+
+ kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
+ g: new(big.Int).SetInt64(2),
+ p: p,
+ pMinus1: new(big.Int).Sub(p, bigOne),
+ }
+
+ kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
+ kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
+ kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
+ kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
+}
+
+// curve25519sha256 implements the curve25519-sha256@libssh.org key
+// agreement protocol, as described in
+// https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt
+type curve25519sha256 struct{}
+
+type curve25519KeyPair struct {
+ priv [32]byte
+ pub [32]byte
+}
+
+func (kp *curve25519KeyPair) generate(rand io.Reader) error {
+ if _, err := io.ReadFull(rand, kp.priv[:]); err != nil {
+ return err
+ }
+ curve25519.ScalarBaseMult(&kp.pub, &kp.priv)
+ return nil
+}
+
+// curve25519Zeros is just an array of 32 zero bytes so that we have something
+// convenient to compare against in order to reject curve25519 points with the
+// wrong order.
+var curve25519Zeros [32]byte
+
+func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handshakeMagics) (*kexResult, error) {
+ var kp curve25519KeyPair
+ if err := kp.generate(rand); err != nil {
+ return nil, err
+ }
+ if err := c.writePacket(Marshal(&kexECDHInitMsg{kp.pub[:]})); err != nil {
+ return nil, err
+ }
+
+ packet, err := c.readPacket()
+ if err != nil {
+ return nil, err
+ }
+
+ var reply kexECDHReplyMsg
+ if err = Unmarshal(packet, &reply); err != nil {
+ return nil, err
+ }
+ if len(reply.EphemeralPubKey) != 32 {
+ return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
+ }
+
+ var servPub, secret [32]byte
+ copy(servPub[:], reply.EphemeralPubKey)
+ curve25519.ScalarMult(&secret, &kp.priv, &servPub)
+ if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
+ return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
+ }
+
+ h := crypto.SHA256.New()
+ magics.write(h)
+ writeString(h, reply.HostKey)
+ writeString(h, kp.pub[:])
+ writeString(h, reply.EphemeralPubKey)
+
+ kInt := new(big.Int).SetBytes(secret[:])
+ K := make([]byte, intLength(kInt))
+ marshalInt(K, kInt)
+ h.Write(K)
+
+ return &kexResult{
+ H: h.Sum(nil),
+ K: K,
+ HostKey: reply.HostKey,
+ Signature: reply.Signature,
+ Hash: crypto.SHA256,
+ }, nil
+}
+
+func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
+ packet, err := c.readPacket()
+ if err != nil {
+ return
+ }
+ var kexInit kexECDHInitMsg
+ if err = Unmarshal(packet, &kexInit); err != nil {
+ return
+ }
+
+ if len(kexInit.ClientPubKey) != 32 {
+ return nil, errors.New("ssh: peer's curve25519 public value has wrong length")
+ }
+
+ var kp curve25519KeyPair
+ if err := kp.generate(rand); err != nil {
+ return nil, err
+ }
+
+ var clientPub, secret [32]byte
+ copy(clientPub[:], kexInit.ClientPubKey)
+ curve25519.ScalarMult(&secret, &kp.priv, &clientPub)
+ if subtle.ConstantTimeCompare(secret[:], curve25519Zeros[:]) == 1 {
+ return nil, errors.New("ssh: peer's curve25519 public value has wrong order")
+ }
+
+ hostKeyBytes := priv.PublicKey().Marshal()
+
+ h := crypto.SHA256.New()
+ magics.write(h)
+ writeString(h, hostKeyBytes)
+ writeString(h, kexInit.ClientPubKey)
+ writeString(h, kp.pub[:])
+
+ kInt := new(big.Int).SetBytes(secret[:])
+ K := make([]byte, intLength(kInt))
+ marshalInt(K, kInt)
+ h.Write(K)
+
+ H := h.Sum(nil)
+
+ sig, err := signAndMarshal(priv, rand, H)
+ if err != nil {
+ return nil, err
+ }
+
+ reply := kexECDHReplyMsg{
+ EphemeralPubKey: kp.pub[:],
+ HostKey: hostKeyBytes,
+ Signature: sig,
+ }
+ if err := c.writePacket(Marshal(&reply)); err != nil {
+ return nil, err
+ }
+ return &kexResult{
+ H: H,
+ K: K,
+ HostKey: hostKeyBytes,
+ Signature: sig,
+ Hash: crypto.SHA256,
+ }, nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go
new file mode 100644
index 0000000..7a8756a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/keys.go
@@ -0,0 +1,1006 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/dsa"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/md5"
+ "crypto/rsa"
+ "crypto/sha256"
+ "crypto/x509"
+ "encoding/asn1"
+ "encoding/base64"
+ "encoding/hex"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io"
+ "math/big"
+ "strings"
+
+ "golang.org/x/crypto/ed25519"
+)
+
+// These constants represent the algorithm names for key types supported by this
+// package.
+const (
+ KeyAlgoRSA = "ssh-rsa"
+ KeyAlgoDSA = "ssh-dss"
+ KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
+ KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
+ KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
+ KeyAlgoED25519 = "ssh-ed25519"
+)
+
+// parsePubKey parses a public key of the given algorithm.
+// Use ParsePublicKey for keys with prepended algorithm.
+func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) {
+ switch algo {
+ case KeyAlgoRSA:
+ return parseRSA(in)
+ case KeyAlgoDSA:
+ return parseDSA(in)
+ case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
+ return parseECDSA(in)
+ case KeyAlgoED25519:
+ return parseED25519(in)
+ case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01:
+ cert, err := parseCert(in, certToPrivAlgo(algo))
+ if err != nil {
+ return nil, nil, err
+ }
+ return cert, nil, nil
+ }
+ return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", algo)
+}
+
+// parseAuthorizedKey parses a public key in OpenSSH authorized_keys format
+// (see sshd(8) manual page) once the options and key type fields have been
+// removed.
+func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) {
+ in = bytes.TrimSpace(in)
+
+ i := bytes.IndexAny(in, " \t")
+ if i == -1 {
+ i = len(in)
+ }
+ base64Key := in[:i]
+
+ key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key)))
+ n, err := base64.StdEncoding.Decode(key, base64Key)
+ if err != nil {
+ return nil, "", err
+ }
+ key = key[:n]
+ out, err = ParsePublicKey(key)
+ if err != nil {
+ return nil, "", err
+ }
+ comment = string(bytes.TrimSpace(in[i:]))
+ return out, comment, nil
+}
+
+// ParseKnownHosts parses an entry in the format of the known_hosts file.
+//
+// The known_hosts format is documented in the sshd(8) manual page. This
+// function will parse a single entry from in. On successful return, marker
+// will contain the optional marker value (i.e. "cert-authority" or "revoked")
+// or else be empty, hosts will contain the hosts that this entry matches,
+// pubKey will contain the public key and comment will contain any trailing
+// comment at the end of the line. See the sshd(8) manual page for the various
+// forms that a host string can take.
+//
+// The unparsed remainder of the input will be returned in rest. This function
+// can be called repeatedly to parse multiple entries.
+//
+// If no entries were found in the input then err will be io.EOF. Otherwise a
+// non-nil err value indicates a parse error.
+func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, err error) {
+ for len(in) > 0 {
+ end := bytes.IndexByte(in, '\n')
+ if end != -1 {
+ rest = in[end+1:]
+ in = in[:end]
+ } else {
+ rest = nil
+ }
+
+ end = bytes.IndexByte(in, '\r')
+ if end != -1 {
+ in = in[:end]
+ }
+
+ in = bytes.TrimSpace(in)
+ if len(in) == 0 || in[0] == '#' {
+ in = rest
+ continue
+ }
+
+ i := bytes.IndexAny(in, " \t")
+ if i == -1 {
+ in = rest
+ continue
+ }
+
+ // Strip out the beginning of the known_host key.
+ // This is either an optional marker or a (set of) hostname(s).
+ keyFields := bytes.Fields(in)
+ if len(keyFields) < 3 || len(keyFields) > 5 {
+ return "", nil, nil, "", nil, errors.New("ssh: invalid entry in known_hosts data")
+ }
+
+ // keyFields[0] is either "@cert-authority", "@revoked" or a comma separated
+ // list of hosts
+ marker := ""
+ if keyFields[0][0] == '@' {
+ marker = string(keyFields[0][1:])
+ keyFields = keyFields[1:]
+ }
+
+ hosts := string(keyFields[0])
+ // keyFields[1] contains the key type (e.g. “ssh-rsa”).
+ // However, that information is duplicated inside the
+ // base64-encoded key and so is ignored here.
+
+ key := bytes.Join(keyFields[2:], []byte(" "))
+ if pubKey, comment, err = parseAuthorizedKey(key); err != nil {
+ return "", nil, nil, "", nil, err
+ }
+
+ return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil
+ }
+
+ return "", nil, nil, "", nil, io.EOF
+}
+
+// ParseAuthorizedKeys parses a public key from an authorized_keys
+// file used in OpenSSH according to the sshd(8) manual page.
+func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
+ for len(in) > 0 {
+ end := bytes.IndexByte(in, '\n')
+ if end != -1 {
+ rest = in[end+1:]
+ in = in[:end]
+ } else {
+ rest = nil
+ }
+
+ end = bytes.IndexByte(in, '\r')
+ if end != -1 {
+ in = in[:end]
+ }
+
+ in = bytes.TrimSpace(in)
+ if len(in) == 0 || in[0] == '#' {
+ in = rest
+ continue
+ }
+
+ i := bytes.IndexAny(in, " \t")
+ if i == -1 {
+ in = rest
+ continue
+ }
+
+ if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
+ return out, comment, options, rest, nil
+ }
+
+ // No key type recognised. Maybe there's an options field at
+ // the beginning.
+ var b byte
+ inQuote := false
+ var candidateOptions []string
+ optionStart := 0
+ for i, b = range in {
+ isEnd := !inQuote && (b == ' ' || b == '\t')
+ if (b == ',' && !inQuote) || isEnd {
+ if i-optionStart > 0 {
+ candidateOptions = append(candidateOptions, string(in[optionStart:i]))
+ }
+ optionStart = i + 1
+ }
+ if isEnd {
+ break
+ }
+ if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) {
+ inQuote = !inQuote
+ }
+ }
+ for i < len(in) && (in[i] == ' ' || in[i] == '\t') {
+ i++
+ }
+ if i == len(in) {
+ // Invalid line: unmatched quote
+ in = rest
+ continue
+ }
+
+ in = in[i:]
+ i = bytes.IndexAny(in, " \t")
+ if i == -1 {
+ in = rest
+ continue
+ }
+
+ if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
+ options = candidateOptions
+ return out, comment, options, rest, nil
+ }
+
+ in = rest
+ continue
+ }
+
+ return nil, "", nil, nil, errors.New("ssh: no key found")
+}
+
+// ParsePublicKey parses an SSH public key formatted for use in
+// the SSH wire protocol according to RFC 4253, section 6.6.
+func ParsePublicKey(in []byte) (out PublicKey, err error) {
+ algo, in, ok := parseString(in)
+ if !ok {
+ return nil, errShortRead
+ }
+ var rest []byte
+ out, rest, err = parsePubKey(in, string(algo))
+ if len(rest) > 0 {
+ return nil, errors.New("ssh: trailing junk in public key")
+ }
+
+ return out, err
+}
+
+// MarshalAuthorizedKey serializes key for inclusion in an OpenSSH
+// authorized_keys file. The return value ends with newline.
+func MarshalAuthorizedKey(key PublicKey) []byte {
+ b := &bytes.Buffer{}
+ b.WriteString(key.Type())
+ b.WriteByte(' ')
+ e := base64.NewEncoder(base64.StdEncoding, b)
+ e.Write(key.Marshal())
+ e.Close()
+ b.WriteByte('\n')
+ return b.Bytes()
+}
+
+// PublicKey is an abstraction of different types of public keys.
+type PublicKey interface {
+ // Type returns the key's type, e.g. "ssh-rsa".
+ Type() string
+
+ // Marshal returns the serialized key data in SSH wire format,
+ // with the name prefix.
+ Marshal() []byte
+
+ // Verify that sig is a signature on the given data using this
+ // key. This function will hash the data appropriately first.
+ Verify(data []byte, sig *Signature) error
+}
+
+// CryptoPublicKey, if implemented by a PublicKey,
+// returns the underlying crypto.PublicKey form of the key.
+type CryptoPublicKey interface {
+ CryptoPublicKey() crypto.PublicKey
+}
+
+// A Signer can create signatures that verify against a public key.
+type Signer interface {
+ // PublicKey returns an associated PublicKey instance.
+ PublicKey() PublicKey
+
+ // Sign returns raw signature for the given data. This method
+ // will apply the hash specified for the keytype to the data.
+ Sign(rand io.Reader, data []byte) (*Signature, error)
+}
+
+type rsaPublicKey rsa.PublicKey
+
+func (r *rsaPublicKey) Type() string {
+ return "ssh-rsa"
+}
+
+// parseRSA parses an RSA key according to RFC 4253, section 6.6.
+func parseRSA(in []byte) (out PublicKey, rest []byte, err error) {
+ var w struct {
+ E *big.Int
+ N *big.Int
+ Rest []byte `ssh:"rest"`
+ }
+ if err := Unmarshal(in, &w); err != nil {
+ return nil, nil, err
+ }
+
+ if w.E.BitLen() > 24 {
+ return nil, nil, errors.New("ssh: exponent too large")
+ }
+ e := w.E.Int64()
+ if e < 3 || e&1 == 0 {
+ return nil, nil, errors.New("ssh: incorrect exponent")
+ }
+
+ var key rsa.PublicKey
+ key.E = int(e)
+ key.N = w.N
+ return (*rsaPublicKey)(&key), w.Rest, nil
+}
+
+func (r *rsaPublicKey) Marshal() []byte {
+ e := new(big.Int).SetInt64(int64(r.E))
+ // RSA publickey struct layout should match the struct used by
+ // parseRSACert in the x/crypto/ssh/agent package.
+ wirekey := struct {
+ Name string
+ E *big.Int
+ N *big.Int
+ }{
+ KeyAlgoRSA,
+ e,
+ r.N,
+ }
+ return Marshal(&wirekey)
+}
+
+func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
+ if sig.Format != r.Type() {
+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type())
+ }
+ h := crypto.SHA1.New()
+ h.Write(data)
+ digest := h.Sum(nil)
+ return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), crypto.SHA1, digest, sig.Blob)
+}
+
+func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey {
+ return (*rsa.PublicKey)(r)
+}
+
+type dsaPublicKey dsa.PublicKey
+
+func (r *dsaPublicKey) Type() string {
+ return "ssh-dss"
+}
+
+// parseDSA parses an DSA key according to RFC 4253, section 6.6.
+func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
+ var w struct {
+ P, Q, G, Y *big.Int
+ Rest []byte `ssh:"rest"`
+ }
+ if err := Unmarshal(in, &w); err != nil {
+ return nil, nil, err
+ }
+
+ key := &dsaPublicKey{
+ Parameters: dsa.Parameters{
+ P: w.P,
+ Q: w.Q,
+ G: w.G,
+ },
+ Y: w.Y,
+ }
+ return key, w.Rest, nil
+}
+
+func (k *dsaPublicKey) Marshal() []byte {
+ // DSA publickey struct layout should match the struct used by
+ // parseDSACert in the x/crypto/ssh/agent package.
+ w := struct {
+ Name string
+ P, Q, G, Y *big.Int
+ }{
+ k.Type(),
+ k.P,
+ k.Q,
+ k.G,
+ k.Y,
+ }
+
+ return Marshal(&w)
+}
+
+func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
+ if sig.Format != k.Type() {
+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
+ }
+ h := crypto.SHA1.New()
+ h.Write(data)
+ digest := h.Sum(nil)
+
+ // Per RFC 4253, section 6.6,
+ // The value for 'dss_signature_blob' is encoded as a string containing
+ // r, followed by s (which are 160-bit integers, without lengths or
+ // padding, unsigned, and in network byte order).
+ // For DSS purposes, sig.Blob should be exactly 40 bytes in length.
+ if len(sig.Blob) != 40 {
+ return errors.New("ssh: DSA signature parse error")
+ }
+ r := new(big.Int).SetBytes(sig.Blob[:20])
+ s := new(big.Int).SetBytes(sig.Blob[20:])
+ if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) {
+ return nil
+ }
+ return errors.New("ssh: signature did not verify")
+}
+
+func (k *dsaPublicKey) CryptoPublicKey() crypto.PublicKey {
+ return (*dsa.PublicKey)(k)
+}
+
+type dsaPrivateKey struct {
+ *dsa.PrivateKey
+}
+
+func (k *dsaPrivateKey) PublicKey() PublicKey {
+ return (*dsaPublicKey)(&k.PrivateKey.PublicKey)
+}
+
+func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
+ h := crypto.SHA1.New()
+ h.Write(data)
+ digest := h.Sum(nil)
+ r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
+ if err != nil {
+ return nil, err
+ }
+
+ sig := make([]byte, 40)
+ rb := r.Bytes()
+ sb := s.Bytes()
+
+ copy(sig[20-len(rb):20], rb)
+ copy(sig[40-len(sb):], sb)
+
+ return &Signature{
+ Format: k.PublicKey().Type(),
+ Blob: sig,
+ }, nil
+}
+
+type ecdsaPublicKey ecdsa.PublicKey
+
+func (key *ecdsaPublicKey) Type() string {
+ return "ecdsa-sha2-" + key.nistID()
+}
+
+func (key *ecdsaPublicKey) nistID() string {
+ switch key.Params().BitSize {
+ case 256:
+ return "nistp256"
+ case 384:
+ return "nistp384"
+ case 521:
+ return "nistp521"
+ }
+ panic("ssh: unsupported ecdsa key size")
+}
+
+type ed25519PublicKey ed25519.PublicKey
+
+func (key ed25519PublicKey) Type() string {
+ return KeyAlgoED25519
+}
+
+func parseED25519(in []byte) (out PublicKey, rest []byte, err error) {
+ var w struct {
+ KeyBytes []byte
+ Rest []byte `ssh:"rest"`
+ }
+
+ if err := Unmarshal(in, &w); err != nil {
+ return nil, nil, err
+ }
+
+ key := ed25519.PublicKey(w.KeyBytes)
+
+ return (ed25519PublicKey)(key), w.Rest, nil
+}
+
+func (key ed25519PublicKey) Marshal() []byte {
+ w := struct {
+ Name string
+ KeyBytes []byte
+ }{
+ KeyAlgoED25519,
+ []byte(key),
+ }
+ return Marshal(&w)
+}
+
+func (key ed25519PublicKey) Verify(b []byte, sig *Signature) error {
+ if sig.Format != key.Type() {
+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
+ }
+
+ edKey := (ed25519.PublicKey)(key)
+ if ok := ed25519.Verify(edKey, b, sig.Blob); !ok {
+ return errors.New("ssh: signature did not verify")
+ }
+
+ return nil
+}
+
+func (k ed25519PublicKey) CryptoPublicKey() crypto.PublicKey {
+ return ed25519.PublicKey(k)
+}
+
+func supportedEllipticCurve(curve elliptic.Curve) bool {
+ return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
+}
+
+// ecHash returns the hash to match the given elliptic curve, see RFC
+// 5656, section 6.2.1
+func ecHash(curve elliptic.Curve) crypto.Hash {
+ bitSize := curve.Params().BitSize
+ switch {
+ case bitSize <= 256:
+ return crypto.SHA256
+ case bitSize <= 384:
+ return crypto.SHA384
+ }
+ return crypto.SHA512
+}
+
+// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
+func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
+ var w struct {
+ Curve string
+ KeyBytes []byte
+ Rest []byte `ssh:"rest"`
+ }
+
+ if err := Unmarshal(in, &w); err != nil {
+ return nil, nil, err
+ }
+
+ key := new(ecdsa.PublicKey)
+
+ switch w.Curve {
+ case "nistp256":
+ key.Curve = elliptic.P256()
+ case "nistp384":
+ key.Curve = elliptic.P384()
+ case "nistp521":
+ key.Curve = elliptic.P521()
+ default:
+ return nil, nil, errors.New("ssh: unsupported curve")
+ }
+
+ key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes)
+ if key.X == nil || key.Y == nil {
+ return nil, nil, errors.New("ssh: invalid curve point")
+ }
+ return (*ecdsaPublicKey)(key), w.Rest, nil
+}
+
+func (key *ecdsaPublicKey) Marshal() []byte {
+ // See RFC 5656, section 3.1.
+ keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y)
+ // ECDSA publickey struct layout should match the struct used by
+ // parseECDSACert in the x/crypto/ssh/agent package.
+ w := struct {
+ Name string
+ ID string
+ Key []byte
+ }{
+ key.Type(),
+ key.nistID(),
+ keyBytes,
+ }
+
+ return Marshal(&w)
+}
+
+func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
+ if sig.Format != key.Type() {
+ return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
+ }
+
+ h := ecHash(key.Curve).New()
+ h.Write(data)
+ digest := h.Sum(nil)
+
+ // Per RFC 5656, section 3.1.2,
+ // The ecdsa_signature_blob value has the following specific encoding:
+ // mpint r
+ // mpint s
+ var ecSig struct {
+ R *big.Int
+ S *big.Int
+ }
+
+ if err := Unmarshal(sig.Blob, &ecSig); err != nil {
+ return err
+ }
+
+ if ecdsa.Verify((*ecdsa.PublicKey)(key), digest, ecSig.R, ecSig.S) {
+ return nil
+ }
+ return errors.New("ssh: signature did not verify")
+}
+
+func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey {
+ return (*ecdsa.PublicKey)(k)
+}
+
+// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
+// *ecdsa.PrivateKey or any other crypto.Signer and returns a corresponding
+// Signer instance. ECDSA keys must use P-256, P-384 or P-521.
+func NewSignerFromKey(key interface{}) (Signer, error) {
+ switch key := key.(type) {
+ case crypto.Signer:
+ return NewSignerFromSigner(key)
+ case *dsa.PrivateKey:
+ return &dsaPrivateKey{key}, nil
+ default:
+ return nil, fmt.Errorf("ssh: unsupported key type %T", key)
+ }
+}
+
+type wrappedSigner struct {
+ signer crypto.Signer
+ pubKey PublicKey
+}
+
+// NewSignerFromSigner takes any crypto.Signer implementation and
+// returns a corresponding Signer interface. This can be used, for
+// example, with keys kept in hardware modules.
+func NewSignerFromSigner(signer crypto.Signer) (Signer, error) {
+ pubKey, err := NewPublicKey(signer.Public())
+ if err != nil {
+ return nil, err
+ }
+
+ return &wrappedSigner{signer, pubKey}, nil
+}
+
+func (s *wrappedSigner) PublicKey() PublicKey {
+ return s.pubKey
+}
+
+func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
+ var hashFunc crypto.Hash
+
+ switch key := s.pubKey.(type) {
+ case *rsaPublicKey, *dsaPublicKey:
+ hashFunc = crypto.SHA1
+ case *ecdsaPublicKey:
+ hashFunc = ecHash(key.Curve)
+ case ed25519PublicKey:
+ default:
+ return nil, fmt.Errorf("ssh: unsupported key type %T", key)
+ }
+
+ var digest []byte
+ if hashFunc != 0 {
+ h := hashFunc.New()
+ h.Write(data)
+ digest = h.Sum(nil)
+ } else {
+ digest = data
+ }
+
+ signature, err := s.signer.Sign(rand, digest, hashFunc)
+ if err != nil {
+ return nil, err
+ }
+
+ // crypto.Signer.Sign is expected to return an ASN.1-encoded signature
+ // for ECDSA and DSA, but that's not the encoding expected by SSH, so
+ // re-encode.
+ switch s.pubKey.(type) {
+ case *ecdsaPublicKey, *dsaPublicKey:
+ type asn1Signature struct {
+ R, S *big.Int
+ }
+ asn1Sig := new(asn1Signature)
+ _, err := asn1.Unmarshal(signature, asn1Sig)
+ if err != nil {
+ return nil, err
+ }
+
+ switch s.pubKey.(type) {
+ case *ecdsaPublicKey:
+ signature = Marshal(asn1Sig)
+
+ case *dsaPublicKey:
+ signature = make([]byte, 40)
+ r := asn1Sig.R.Bytes()
+ s := asn1Sig.S.Bytes()
+ copy(signature[20-len(r):20], r)
+ copy(signature[40-len(s):40], s)
+ }
+ }
+
+ return &Signature{
+ Format: s.pubKey.Type(),
+ Blob: signature,
+ }, nil
+}
+
+// NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey,
+// or ed25519.PublicKey returns a corresponding PublicKey instance.
+// ECDSA keys must use P-256, P-384 or P-521.
+func NewPublicKey(key interface{}) (PublicKey, error) {
+ switch key := key.(type) {
+ case *rsa.PublicKey:
+ return (*rsaPublicKey)(key), nil
+ case *ecdsa.PublicKey:
+ if !supportedEllipticCurve(key.Curve) {
+ return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported.")
+ }
+ return (*ecdsaPublicKey)(key), nil
+ case *dsa.PublicKey:
+ return (*dsaPublicKey)(key), nil
+ case ed25519.PublicKey:
+ return (ed25519PublicKey)(key), nil
+ default:
+ return nil, fmt.Errorf("ssh: unsupported key type %T", key)
+ }
+}
+
+// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports
+// the same keys as ParseRawPrivateKey.
+func ParsePrivateKey(pemBytes []byte) (Signer, error) {
+ key, err := ParseRawPrivateKey(pemBytes)
+ if err != nil {
+ return nil, err
+ }
+
+ return NewSignerFromKey(key)
+}
+
+// ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private
+// key and passphrase. It supports the same keys as
+// ParseRawPrivateKeyWithPassphrase.
+func ParsePrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (Signer, error) {
+ key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase)
+ if err != nil {
+ return nil, err
+ }
+
+ return NewSignerFromKey(key)
+}
+
+// encryptedBlock tells whether a private key is
+// encrypted by examining its Proc-Type header
+// for a mention of ENCRYPTED
+// according to RFC 1421 Section 4.6.1.1.
+func encryptedBlock(block *pem.Block) bool {
+ return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED")
+}
+
+// ParseRawPrivateKey returns a private key from a PEM encoded private key. It
+// supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys.
+func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
+ block, _ := pem.Decode(pemBytes)
+ if block == nil {
+ return nil, errors.New("ssh: no key found")
+ }
+
+ if encryptedBlock(block) {
+ return nil, errors.New("ssh: cannot decode encrypted private keys")
+ }
+
+ switch block.Type {
+ case "RSA PRIVATE KEY":
+ return x509.ParsePKCS1PrivateKey(block.Bytes)
+ case "EC PRIVATE KEY":
+ return x509.ParseECPrivateKey(block.Bytes)
+ case "DSA PRIVATE KEY":
+ return ParseDSAPrivateKey(block.Bytes)
+ case "OPENSSH PRIVATE KEY":
+ return parseOpenSSHPrivateKey(block.Bytes)
+ default:
+ return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
+ }
+}
+
+// ParseRawPrivateKeyWithPassphrase returns a private key decrypted with
+// passphrase from a PEM encoded private key. If wrong passphrase, return
+// x509.IncorrectPasswordError.
+func ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (interface{}, error) {
+ block, _ := pem.Decode(pemBytes)
+ if block == nil {
+ return nil, errors.New("ssh: no key found")
+ }
+ buf := block.Bytes
+
+ if encryptedBlock(block) {
+ if x509.IsEncryptedPEMBlock(block) {
+ var err error
+ buf, err = x509.DecryptPEMBlock(block, passPhrase)
+ if err != nil {
+ if err == x509.IncorrectPasswordError {
+ return nil, err
+ }
+ return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err)
+ }
+ }
+ }
+
+ switch block.Type {
+ case "RSA PRIVATE KEY":
+ return x509.ParsePKCS1PrivateKey(buf)
+ case "EC PRIVATE KEY":
+ return x509.ParseECPrivateKey(buf)
+ case "DSA PRIVATE KEY":
+ return ParseDSAPrivateKey(buf)
+ case "OPENSSH PRIVATE KEY":
+ return parseOpenSSHPrivateKey(buf)
+ default:
+ return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
+ }
+}
+
+// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as
+// specified by the OpenSSL DSA man page.
+func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
+ var k struct {
+ Version int
+ P *big.Int
+ Q *big.Int
+ G *big.Int
+ Pub *big.Int
+ Priv *big.Int
+ }
+ rest, err := asn1.Unmarshal(der, &k)
+ if err != nil {
+ return nil, errors.New("ssh: failed to parse DSA key: " + err.Error())
+ }
+ if len(rest) > 0 {
+ return nil, errors.New("ssh: garbage after DSA key")
+ }
+
+ return &dsa.PrivateKey{
+ PublicKey: dsa.PublicKey{
+ Parameters: dsa.Parameters{
+ P: k.P,
+ Q: k.Q,
+ G: k.G,
+ },
+ Y: k.Pub,
+ },
+ X: k.Priv,
+ }, nil
+}
+
+// Implemented based on the documentation at
+// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
+func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) {
+ magic := append([]byte("openssh-key-v1"), 0)
+ if !bytes.Equal(magic, key[0:len(magic)]) {
+ return nil, errors.New("ssh: invalid openssh private key format")
+ }
+ remaining := key[len(magic):]
+
+ var w struct {
+ CipherName string
+ KdfName string
+ KdfOpts string
+ NumKeys uint32
+ PubKey []byte
+ PrivKeyBlock []byte
+ }
+
+ if err := Unmarshal(remaining, &w); err != nil {
+ return nil, err
+ }
+
+ if w.KdfName != "none" || w.CipherName != "none" {
+ return nil, errors.New("ssh: cannot decode encrypted private keys")
+ }
+
+ pk1 := struct {
+ Check1 uint32
+ Check2 uint32
+ Keytype string
+ Rest []byte `ssh:"rest"`
+ }{}
+
+ if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil {
+ return nil, err
+ }
+
+ if pk1.Check1 != pk1.Check2 {
+ return nil, errors.New("ssh: checkint mismatch")
+ }
+
+ // we only handle ed25519 and rsa keys currently
+ switch pk1.Keytype {
+ case KeyAlgoRSA:
+ // https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773
+ key := struct {
+ N *big.Int
+ E *big.Int
+ D *big.Int
+ Iqmp *big.Int
+ P *big.Int
+ Q *big.Int
+ Comment string
+ Pad []byte `ssh:"rest"`
+ }{}
+
+ if err := Unmarshal(pk1.Rest, &key); err != nil {
+ return nil, err
+ }
+
+ for i, b := range key.Pad {
+ if int(b) != i+1 {
+ return nil, errors.New("ssh: padding not as expected")
+ }
+ }
+
+ pk := &rsa.PrivateKey{
+ PublicKey: rsa.PublicKey{
+ N: key.N,
+ E: int(key.E.Int64()),
+ },
+ D: key.D,
+ Primes: []*big.Int{key.P, key.Q},
+ }
+
+ if err := pk.Validate(); err != nil {
+ return nil, err
+ }
+
+ pk.Precompute()
+
+ return pk, nil
+ case KeyAlgoED25519:
+ key := struct {
+ Pub []byte
+ Priv []byte
+ Comment string
+ Pad []byte `ssh:"rest"`
+ }{}
+
+ if err := Unmarshal(pk1.Rest, &key); err != nil {
+ return nil, err
+ }
+
+ if len(key.Priv) != ed25519.PrivateKeySize {
+ return nil, errors.New("ssh: private key unexpected length")
+ }
+
+ for i, b := range key.Pad {
+ if int(b) != i+1 {
+ return nil, errors.New("ssh: padding not as expected")
+ }
+ }
+
+ pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
+ copy(pk, key.Priv)
+ return &pk, nil
+ default:
+ return nil, errors.New("ssh: unhandled key type")
+ }
+}
+
+// FingerprintLegacyMD5 returns the user presentation of the key's
+// fingerprint as described by RFC 4716 section 4.
+func FingerprintLegacyMD5(pubKey PublicKey) string {
+ md5sum := md5.Sum(pubKey.Marshal())
+ hexarray := make([]string, len(md5sum))
+ for i, c := range md5sum {
+ hexarray[i] = hex.EncodeToString([]byte{c})
+ }
+ return strings.Join(hexarray, ":")
+}
+
+// FingerprintSHA256 returns the user presentation of the key's
+// fingerprint as unpadded base64 encoded sha256 hash.
+// This format was introduced from OpenSSH 6.8.
+// https://www.openssh.com/txt/release-6.8
+// https://tools.ietf.org/html/rfc4648#section-3.2 (unpadded base64 encoding)
+func FingerprintSHA256(pubKey PublicKey) string {
+ sha256sum := sha256.Sum256(pubKey.Marshal())
+ hash := base64.RawStdEncoding.EncodeToString(sha256sum[:])
+ return "SHA256:" + hash
+}
diff --git a/vendor/golang.org/x/crypto/ssh/mac.go b/vendor/golang.org/x/crypto/ssh/mac.go
new file mode 100644
index 0000000..c07a062
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/mac.go
@@ -0,0 +1,61 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+// Message authentication support
+
+import (
+ "crypto/hmac"
+ "crypto/sha1"
+ "crypto/sha256"
+ "hash"
+)
+
+type macMode struct {
+ keySize int
+ etm bool
+ new func(key []byte) hash.Hash
+}
+
+// truncatingMAC wraps around a hash.Hash and truncates the output digest to
+// a given size.
+type truncatingMAC struct {
+ length int
+ hmac hash.Hash
+}
+
+func (t truncatingMAC) Write(data []byte) (int, error) {
+ return t.hmac.Write(data)
+}
+
+func (t truncatingMAC) Sum(in []byte) []byte {
+ out := t.hmac.Sum(in)
+ return out[:len(in)+t.length]
+}
+
+func (t truncatingMAC) Reset() {
+ t.hmac.Reset()
+}
+
+func (t truncatingMAC) Size() int {
+ return t.length
+}
+
+func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
+
+var macModes = map[string]*macMode{
+ "hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash {
+ return hmac.New(sha256.New, key)
+ }},
+ "hmac-sha2-256": {32, false, func(key []byte) hash.Hash {
+ return hmac.New(sha256.New, key)
+ }},
+ "hmac-sha1": {20, false, func(key []byte) hash.Hash {
+ return hmac.New(sha1.New, key)
+ }},
+ "hmac-sha1-96": {20, false, func(key []byte) hash.Hash {
+ return truncatingMAC{12, hmac.New(sha1.New, key)}
+ }},
+}
diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go
new file mode 100644
index 0000000..e6ecd3a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/messages.go
@@ -0,0 +1,758 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "math/big"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+// These are SSH message type numbers. They are scattered around several
+// documents but many were taken from [SSH-PARAMETERS].
+const (
+ msgIgnore = 2
+ msgUnimplemented = 3
+ msgDebug = 4
+ msgNewKeys = 21
+
+ // Standard authentication messages
+ msgUserAuthSuccess = 52
+ msgUserAuthBanner = 53
+)
+
+// SSH messages:
+//
+// These structures mirror the wire format of the corresponding SSH messages.
+// They are marshaled using reflection with the marshal and unmarshal functions
+// in this file. The only wrinkle is that a final member of type []byte with a
+// ssh tag of "rest" receives the remainder of a packet when unmarshaling.
+
+// See RFC 4253, section 11.1.
+const msgDisconnect = 1
+
+// disconnectMsg is the message that signals a disconnect. It is also
+// the error type returned from mux.Wait()
+type disconnectMsg struct {
+ Reason uint32 `sshtype:"1"`
+ Message string
+ Language string
+}
+
+func (d *disconnectMsg) Error() string {
+ return fmt.Sprintf("ssh: disconnect, reason %d: %s", d.Reason, d.Message)
+}
+
+// See RFC 4253, section 7.1.
+const msgKexInit = 20
+
+type kexInitMsg struct {
+ Cookie [16]byte `sshtype:"20"`
+ KexAlgos []string
+ ServerHostKeyAlgos []string
+ CiphersClientServer []string
+ CiphersServerClient []string
+ MACsClientServer []string
+ MACsServerClient []string
+ CompressionClientServer []string
+ CompressionServerClient []string
+ LanguagesClientServer []string
+ LanguagesServerClient []string
+ FirstKexFollows bool
+ Reserved uint32
+}
+
+// See RFC 4253, section 8.
+
+// Diffie-Helman
+const msgKexDHInit = 30
+
+type kexDHInitMsg struct {
+ X *big.Int `sshtype:"30"`
+}
+
+const msgKexECDHInit = 30
+
+type kexECDHInitMsg struct {
+ ClientPubKey []byte `sshtype:"30"`
+}
+
+const msgKexECDHReply = 31
+
+type kexECDHReplyMsg struct {
+ HostKey []byte `sshtype:"31"`
+ EphemeralPubKey []byte
+ Signature []byte
+}
+
+const msgKexDHReply = 31
+
+type kexDHReplyMsg struct {
+ HostKey []byte `sshtype:"31"`
+ Y *big.Int
+ Signature []byte
+}
+
+// See RFC 4253, section 10.
+const msgServiceRequest = 5
+
+type serviceRequestMsg struct {
+ Service string `sshtype:"5"`
+}
+
+// See RFC 4253, section 10.
+const msgServiceAccept = 6
+
+type serviceAcceptMsg struct {
+ Service string `sshtype:"6"`
+}
+
+// See RFC 4252, section 5.
+const msgUserAuthRequest = 50
+
+type userAuthRequestMsg struct {
+ User string `sshtype:"50"`
+ Service string
+ Method string
+ Payload []byte `ssh:"rest"`
+}
+
+// Used for debug printouts of packets.
+type userAuthSuccessMsg struct {
+}
+
+// See RFC 4252, section 5.1
+const msgUserAuthFailure = 51
+
+type userAuthFailureMsg struct {
+ Methods []string `sshtype:"51"`
+ PartialSuccess bool
+}
+
+// See RFC 4256, section 3.2
+const msgUserAuthInfoRequest = 60
+const msgUserAuthInfoResponse = 61
+
+type userAuthInfoRequestMsg struct {
+ User string `sshtype:"60"`
+ Instruction string
+ DeprecatedLanguage string
+ NumPrompts uint32
+ Prompts []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.1.
+const msgChannelOpen = 90
+
+type channelOpenMsg struct {
+ ChanType string `sshtype:"90"`
+ PeersId uint32
+ PeersWindow uint32
+ MaxPacketSize uint32
+ TypeSpecificData []byte `ssh:"rest"`
+}
+
+const msgChannelExtendedData = 95
+const msgChannelData = 94
+
+// Used for debug print outs of packets.
+type channelDataMsg struct {
+ PeersId uint32 `sshtype:"94"`
+ Length uint32
+ Rest []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.1.
+const msgChannelOpenConfirm = 91
+
+type channelOpenConfirmMsg struct {
+ PeersId uint32 `sshtype:"91"`
+ MyId uint32
+ MyWindow uint32
+ MaxPacketSize uint32
+ TypeSpecificData []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.1.
+const msgChannelOpenFailure = 92
+
+type channelOpenFailureMsg struct {
+ PeersId uint32 `sshtype:"92"`
+ Reason RejectionReason
+ Message string
+ Language string
+}
+
+const msgChannelRequest = 98
+
+type channelRequestMsg struct {
+ PeersId uint32 `sshtype:"98"`
+ Request string
+ WantReply bool
+ RequestSpecificData []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.4.
+const msgChannelSuccess = 99
+
+type channelRequestSuccessMsg struct {
+ PeersId uint32 `sshtype:"99"`
+}
+
+// See RFC 4254, section 5.4.
+const msgChannelFailure = 100
+
+type channelRequestFailureMsg struct {
+ PeersId uint32 `sshtype:"100"`
+}
+
+// See RFC 4254, section 5.3
+const msgChannelClose = 97
+
+type channelCloseMsg struct {
+ PeersId uint32 `sshtype:"97"`
+}
+
+// See RFC 4254, section 5.3
+const msgChannelEOF = 96
+
+type channelEOFMsg struct {
+ PeersId uint32 `sshtype:"96"`
+}
+
+// See RFC 4254, section 4
+const msgGlobalRequest = 80
+
+type globalRequestMsg struct {
+ Type string `sshtype:"80"`
+ WantReply bool
+ Data []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 4
+const msgRequestSuccess = 81
+
+type globalRequestSuccessMsg struct {
+ Data []byte `ssh:"rest" sshtype:"81"`
+}
+
+// See RFC 4254, section 4
+const msgRequestFailure = 82
+
+type globalRequestFailureMsg struct {
+ Data []byte `ssh:"rest" sshtype:"82"`
+}
+
+// See RFC 4254, section 5.2
+const msgChannelWindowAdjust = 93
+
+type windowAdjustMsg struct {
+ PeersId uint32 `sshtype:"93"`
+ AdditionalBytes uint32
+}
+
+// See RFC 4252, section 7
+const msgUserAuthPubKeyOk = 60
+
+type userAuthPubKeyOkMsg struct {
+ Algo string `sshtype:"60"`
+ PubKey []byte
+}
+
+// typeTags returns the possible type bytes for the given reflect.Type, which
+// should be a struct. The possible values are separated by a '|' character.
+func typeTags(structType reflect.Type) (tags []byte) {
+ tagStr := structType.Field(0).Tag.Get("sshtype")
+
+ for _, tag := range strings.Split(tagStr, "|") {
+ i, err := strconv.Atoi(tag)
+ if err == nil {
+ tags = append(tags, byte(i))
+ }
+ }
+
+ return tags
+}
+
+func fieldError(t reflect.Type, field int, problem string) error {
+ if problem != "" {
+ problem = ": " + problem
+ }
+ return fmt.Errorf("ssh: unmarshal error for field %s of type %s%s", t.Field(field).Name, t.Name(), problem)
+}
+
+var errShortRead = errors.New("ssh: short read")
+
+// Unmarshal parses data in SSH wire format into a structure. The out
+// argument should be a pointer to struct. If the first member of the
+// struct has the "sshtype" tag set to a '|'-separated set of numbers
+// in decimal, the packet must start with one of those numbers. In
+// case of error, Unmarshal returns a ParseError or
+// UnexpectedMessageError.
+func Unmarshal(data []byte, out interface{}) error {
+ v := reflect.ValueOf(out).Elem()
+ structType := v.Type()
+ expectedTypes := typeTags(structType)
+
+ var expectedType byte
+ if len(expectedTypes) > 0 {
+ expectedType = expectedTypes[0]
+ }
+
+ if len(data) == 0 {
+ return parseError(expectedType)
+ }
+
+ if len(expectedTypes) > 0 {
+ goodType := false
+ for _, e := range expectedTypes {
+ if e > 0 && data[0] == e {
+ goodType = true
+ break
+ }
+ }
+ if !goodType {
+ return fmt.Errorf("ssh: unexpected message type %d (expected one of %v)", data[0], expectedTypes)
+ }
+ data = data[1:]
+ }
+
+ var ok bool
+ for i := 0; i < v.NumField(); i++ {
+ field := v.Field(i)
+ t := field.Type()
+ switch t.Kind() {
+ case reflect.Bool:
+ if len(data) < 1 {
+ return errShortRead
+ }
+ field.SetBool(data[0] != 0)
+ data = data[1:]
+ case reflect.Array:
+ if t.Elem().Kind() != reflect.Uint8 {
+ return fieldError(structType, i, "array of unsupported type")
+ }
+ if len(data) < t.Len() {
+ return errShortRead
+ }
+ for j, n := 0, t.Len(); j < n; j++ {
+ field.Index(j).Set(reflect.ValueOf(data[j]))
+ }
+ data = data[t.Len():]
+ case reflect.Uint64:
+ var u64 uint64
+ if u64, data, ok = parseUint64(data); !ok {
+ return errShortRead
+ }
+ field.SetUint(u64)
+ case reflect.Uint32:
+ var u32 uint32
+ if u32, data, ok = parseUint32(data); !ok {
+ return errShortRead
+ }
+ field.SetUint(uint64(u32))
+ case reflect.Uint8:
+ if len(data) < 1 {
+ return errShortRead
+ }
+ field.SetUint(uint64(data[0]))
+ data = data[1:]
+ case reflect.String:
+ var s []byte
+ if s, data, ok = parseString(data); !ok {
+ return fieldError(structType, i, "")
+ }
+ field.SetString(string(s))
+ case reflect.Slice:
+ switch t.Elem().Kind() {
+ case reflect.Uint8:
+ if structType.Field(i).Tag.Get("ssh") == "rest" {
+ field.Set(reflect.ValueOf(data))
+ data = nil
+ } else {
+ var s []byte
+ if s, data, ok = parseString(data); !ok {
+ return errShortRead
+ }
+ field.Set(reflect.ValueOf(s))
+ }
+ case reflect.String:
+ var nl []string
+ if nl, data, ok = parseNameList(data); !ok {
+ return errShortRead
+ }
+ field.Set(reflect.ValueOf(nl))
+ default:
+ return fieldError(structType, i, "slice of unsupported type")
+ }
+ case reflect.Ptr:
+ if t == bigIntType {
+ var n *big.Int
+ if n, data, ok = parseInt(data); !ok {
+ return errShortRead
+ }
+ field.Set(reflect.ValueOf(n))
+ } else {
+ return fieldError(structType, i, "pointer to unsupported type")
+ }
+ default:
+ return fieldError(structType, i, fmt.Sprintf("unsupported type: %v", t))
+ }
+ }
+
+ if len(data) != 0 {
+ return parseError(expectedType)
+ }
+
+ return nil
+}
+
+// Marshal serializes the message in msg to SSH wire format. The msg
+// argument should be a struct or pointer to struct. If the first
+// member has the "sshtype" tag set to a number in decimal, that
+// number is prepended to the result. If the last of member has the
+// "ssh" tag set to "rest", its contents are appended to the output.
+func Marshal(msg interface{}) []byte {
+ out := make([]byte, 0, 64)
+ return marshalStruct(out, msg)
+}
+
+func marshalStruct(out []byte, msg interface{}) []byte {
+ v := reflect.Indirect(reflect.ValueOf(msg))
+ msgTypes := typeTags(v.Type())
+ if len(msgTypes) > 0 {
+ out = append(out, msgTypes[0])
+ }
+
+ for i, n := 0, v.NumField(); i < n; i++ {
+ field := v.Field(i)
+ switch t := field.Type(); t.Kind() {
+ case reflect.Bool:
+ var v uint8
+ if field.Bool() {
+ v = 1
+ }
+ out = append(out, v)
+ case reflect.Array:
+ if t.Elem().Kind() != reflect.Uint8 {
+ panic(fmt.Sprintf("array of non-uint8 in field %d: %T", i, field.Interface()))
+ }
+ for j, l := 0, t.Len(); j < l; j++ {
+ out = append(out, uint8(field.Index(j).Uint()))
+ }
+ case reflect.Uint32:
+ out = appendU32(out, uint32(field.Uint()))
+ case reflect.Uint64:
+ out = appendU64(out, uint64(field.Uint()))
+ case reflect.Uint8:
+ out = append(out, uint8(field.Uint()))
+ case reflect.String:
+ s := field.String()
+ out = appendInt(out, len(s))
+ out = append(out, s...)
+ case reflect.Slice:
+ switch t.Elem().Kind() {
+ case reflect.Uint8:
+ if v.Type().Field(i).Tag.Get("ssh") != "rest" {
+ out = appendInt(out, field.Len())
+ }
+ out = append(out, field.Bytes()...)
+ case reflect.String:
+ offset := len(out)
+ out = appendU32(out, 0)
+ if n := field.Len(); n > 0 {
+ for j := 0; j < n; j++ {
+ f := field.Index(j)
+ if j != 0 {
+ out = append(out, ',')
+ }
+ out = append(out, f.String()...)
+ }
+ // overwrite length value
+ binary.BigEndian.PutUint32(out[offset:], uint32(len(out)-offset-4))
+ }
+ default:
+ panic(fmt.Sprintf("slice of unknown type in field %d: %T", i, field.Interface()))
+ }
+ case reflect.Ptr:
+ if t == bigIntType {
+ var n *big.Int
+ nValue := reflect.ValueOf(&n)
+ nValue.Elem().Set(field)
+ needed := intLength(n)
+ oldLength := len(out)
+
+ if cap(out)-len(out) < needed {
+ newOut := make([]byte, len(out), 2*(len(out)+needed))
+ copy(newOut, out)
+ out = newOut
+ }
+ out = out[:oldLength+needed]
+ marshalInt(out[oldLength:], n)
+ } else {
+ panic(fmt.Sprintf("pointer to unknown type in field %d: %T", i, field.Interface()))
+ }
+ }
+ }
+
+ return out
+}
+
+var bigOne = big.NewInt(1)
+
+func parseString(in []byte) (out, rest []byte, ok bool) {
+ if len(in) < 4 {
+ return
+ }
+ length := binary.BigEndian.Uint32(in)
+ in = in[4:]
+ if uint32(len(in)) < length {
+ return
+ }
+ out = in[:length]
+ rest = in[length:]
+ ok = true
+ return
+}
+
+var (
+ comma = []byte{','}
+ emptyNameList = []string{}
+)
+
+func parseNameList(in []byte) (out []string, rest []byte, ok bool) {
+ contents, rest, ok := parseString(in)
+ if !ok {
+ return
+ }
+ if len(contents) == 0 {
+ out = emptyNameList
+ return
+ }
+ parts := bytes.Split(contents, comma)
+ out = make([]string, len(parts))
+ for i, part := range parts {
+ out[i] = string(part)
+ }
+ return
+}
+
+func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) {
+ contents, rest, ok := parseString(in)
+ if !ok {
+ return
+ }
+ out = new(big.Int)
+
+ if len(contents) > 0 && contents[0]&0x80 == 0x80 {
+ // This is a negative number
+ notBytes := make([]byte, len(contents))
+ for i := range notBytes {
+ notBytes[i] = ^contents[i]
+ }
+ out.SetBytes(notBytes)
+ out.Add(out, bigOne)
+ out.Neg(out)
+ } else {
+ // Positive number
+ out.SetBytes(contents)
+ }
+ ok = true
+ return
+}
+
+func parseUint32(in []byte) (uint32, []byte, bool) {
+ if len(in) < 4 {
+ return 0, nil, false
+ }
+ return binary.BigEndian.Uint32(in), in[4:], true
+}
+
+func parseUint64(in []byte) (uint64, []byte, bool) {
+ if len(in) < 8 {
+ return 0, nil, false
+ }
+ return binary.BigEndian.Uint64(in), in[8:], true
+}
+
+func intLength(n *big.Int) int {
+ length := 4 /* length bytes */
+ if n.Sign() < 0 {
+ nMinus1 := new(big.Int).Neg(n)
+ nMinus1.Sub(nMinus1, bigOne)
+ bitLen := nMinus1.BitLen()
+ if bitLen%8 == 0 {
+ // The number will need 0xff padding
+ length++
+ }
+ length += (bitLen + 7) / 8
+ } else if n.Sign() == 0 {
+ // A zero is the zero length string
+ } else {
+ bitLen := n.BitLen()
+ if bitLen%8 == 0 {
+ // The number will need 0x00 padding
+ length++
+ }
+ length += (bitLen + 7) / 8
+ }
+
+ return length
+}
+
+func marshalUint32(to []byte, n uint32) []byte {
+ binary.BigEndian.PutUint32(to, n)
+ return to[4:]
+}
+
+func marshalUint64(to []byte, n uint64) []byte {
+ binary.BigEndian.PutUint64(to, n)
+ return to[8:]
+}
+
+func marshalInt(to []byte, n *big.Int) []byte {
+ lengthBytes := to
+ to = to[4:]
+ length := 0
+
+ if n.Sign() < 0 {
+ // A negative number has to be converted to two's-complement
+ // form. So we'll subtract 1 and invert. If the
+ // most-significant-bit isn't set then we'll need to pad the
+ // beginning with 0xff in order to keep the number negative.
+ nMinus1 := new(big.Int).Neg(n)
+ nMinus1.Sub(nMinus1, bigOne)
+ bytes := nMinus1.Bytes()
+ for i := range bytes {
+ bytes[i] ^= 0xff
+ }
+ if len(bytes) == 0 || bytes[0]&0x80 == 0 {
+ to[0] = 0xff
+ to = to[1:]
+ length++
+ }
+ nBytes := copy(to, bytes)
+ to = to[nBytes:]
+ length += nBytes
+ } else if n.Sign() == 0 {
+ // A zero is the zero length string
+ } else {
+ bytes := n.Bytes()
+ if len(bytes) > 0 && bytes[0]&0x80 != 0 {
+ // We'll have to pad this with a 0x00 in order to
+ // stop it looking like a negative number.
+ to[0] = 0
+ to = to[1:]
+ length++
+ }
+ nBytes := copy(to, bytes)
+ to = to[nBytes:]
+ length += nBytes
+ }
+
+ lengthBytes[0] = byte(length >> 24)
+ lengthBytes[1] = byte(length >> 16)
+ lengthBytes[2] = byte(length >> 8)
+ lengthBytes[3] = byte(length)
+ return to
+}
+
+func writeInt(w io.Writer, n *big.Int) {
+ length := intLength(n)
+ buf := make([]byte, length)
+ marshalInt(buf, n)
+ w.Write(buf)
+}
+
+func writeString(w io.Writer, s []byte) {
+ var lengthBytes [4]byte
+ lengthBytes[0] = byte(len(s) >> 24)
+ lengthBytes[1] = byte(len(s) >> 16)
+ lengthBytes[2] = byte(len(s) >> 8)
+ lengthBytes[3] = byte(len(s))
+ w.Write(lengthBytes[:])
+ w.Write(s)
+}
+
+func stringLength(n int) int {
+ return 4 + n
+}
+
+func marshalString(to []byte, s []byte) []byte {
+ to[0] = byte(len(s) >> 24)
+ to[1] = byte(len(s) >> 16)
+ to[2] = byte(len(s) >> 8)
+ to[3] = byte(len(s))
+ to = to[4:]
+ copy(to, s)
+ return to[len(s):]
+}
+
+var bigIntType = reflect.TypeOf((*big.Int)(nil))
+
+// Decode a packet into its corresponding message.
+func decode(packet []byte) (interface{}, error) {
+ var msg interface{}
+ switch packet[0] {
+ case msgDisconnect:
+ msg = new(disconnectMsg)
+ case msgServiceRequest:
+ msg = new(serviceRequestMsg)
+ case msgServiceAccept:
+ msg = new(serviceAcceptMsg)
+ case msgKexInit:
+ msg = new(kexInitMsg)
+ case msgKexDHInit:
+ msg = new(kexDHInitMsg)
+ case msgKexDHReply:
+ msg = new(kexDHReplyMsg)
+ case msgUserAuthRequest:
+ msg = new(userAuthRequestMsg)
+ case msgUserAuthSuccess:
+ return new(userAuthSuccessMsg), nil
+ case msgUserAuthFailure:
+ msg = new(userAuthFailureMsg)
+ case msgUserAuthPubKeyOk:
+ msg = new(userAuthPubKeyOkMsg)
+ case msgGlobalRequest:
+ msg = new(globalRequestMsg)
+ case msgRequestSuccess:
+ msg = new(globalRequestSuccessMsg)
+ case msgRequestFailure:
+ msg = new(globalRequestFailureMsg)
+ case msgChannelOpen:
+ msg = new(channelOpenMsg)
+ case msgChannelData:
+ msg = new(channelDataMsg)
+ case msgChannelOpenConfirm:
+ msg = new(channelOpenConfirmMsg)
+ case msgChannelOpenFailure:
+ msg = new(channelOpenFailureMsg)
+ case msgChannelWindowAdjust:
+ msg = new(windowAdjustMsg)
+ case msgChannelEOF:
+ msg = new(channelEOFMsg)
+ case msgChannelClose:
+ msg = new(channelCloseMsg)
+ case msgChannelRequest:
+ msg = new(channelRequestMsg)
+ case msgChannelSuccess:
+ msg = new(channelRequestSuccessMsg)
+ case msgChannelFailure:
+ msg = new(channelRequestFailureMsg)
+ default:
+ return nil, unexpectedMessageError(0, packet[0])
+ }
+ if err := Unmarshal(packet, msg); err != nil {
+ return nil, err
+ }
+ return msg, nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/mux.go b/vendor/golang.org/x/crypto/ssh/mux.go
new file mode 100644
index 0000000..27a527c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/mux.go
@@ -0,0 +1,330 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "encoding/binary"
+ "fmt"
+ "io"
+ "log"
+ "sync"
+ "sync/atomic"
+)
+
+// debugMux, if set, causes messages in the connection protocol to be
+// logged.
+const debugMux = false
+
+// chanList is a thread safe channel list.
+type chanList struct {
+ // protects concurrent access to chans
+ sync.Mutex
+
+ // chans are indexed by the local id of the channel, which the
+ // other side should send in the PeersId field.
+ chans []*channel
+
+ // This is a debugging aid: it offsets all IDs by this
+ // amount. This helps distinguish otherwise identical
+ // server/client muxes
+ offset uint32
+}
+
+// Assigns a channel ID to the given channel.
+func (c *chanList) add(ch *channel) uint32 {
+ c.Lock()
+ defer c.Unlock()
+ for i := range c.chans {
+ if c.chans[i] == nil {
+ c.chans[i] = ch
+ return uint32(i) + c.offset
+ }
+ }
+ c.chans = append(c.chans, ch)
+ return uint32(len(c.chans)-1) + c.offset
+}
+
+// getChan returns the channel for the given ID.
+func (c *chanList) getChan(id uint32) *channel {
+ id -= c.offset
+
+ c.Lock()
+ defer c.Unlock()
+ if id < uint32(len(c.chans)) {
+ return c.chans[id]
+ }
+ return nil
+}
+
+func (c *chanList) remove(id uint32) {
+ id -= c.offset
+ c.Lock()
+ if id < uint32(len(c.chans)) {
+ c.chans[id] = nil
+ }
+ c.Unlock()
+}
+
+// dropAll forgets all channels it knows, returning them in a slice.
+func (c *chanList) dropAll() []*channel {
+ c.Lock()
+ defer c.Unlock()
+ var r []*channel
+
+ for _, ch := range c.chans {
+ if ch == nil {
+ continue
+ }
+ r = append(r, ch)
+ }
+ c.chans = nil
+ return r
+}
+
+// mux represents the state for the SSH connection protocol, which
+// multiplexes many channels onto a single packet transport.
+type mux struct {
+ conn packetConn
+ chanList chanList
+
+ incomingChannels chan NewChannel
+
+ globalSentMu sync.Mutex
+ globalResponses chan interface{}
+ incomingRequests chan *Request
+
+ errCond *sync.Cond
+ err error
+}
+
+// When debugging, each new chanList instantiation has a different
+// offset.
+var globalOff uint32
+
+func (m *mux) Wait() error {
+ m.errCond.L.Lock()
+ defer m.errCond.L.Unlock()
+ for m.err == nil {
+ m.errCond.Wait()
+ }
+ return m.err
+}
+
+// newMux returns a mux that runs over the given connection.
+func newMux(p packetConn) *mux {
+ m := &mux{
+ conn: p,
+ incomingChannels: make(chan NewChannel, chanSize),
+ globalResponses: make(chan interface{}, 1),
+ incomingRequests: make(chan *Request, chanSize),
+ errCond: newCond(),
+ }
+ if debugMux {
+ m.chanList.offset = atomic.AddUint32(&globalOff, 1)
+ }
+
+ go m.loop()
+ return m
+}
+
+func (m *mux) sendMessage(msg interface{}) error {
+ p := Marshal(msg)
+ if debugMux {
+ log.Printf("send global(%d): %#v", m.chanList.offset, msg)
+ }
+ return m.conn.writePacket(p)
+}
+
+func (m *mux) SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) {
+ if wantReply {
+ m.globalSentMu.Lock()
+ defer m.globalSentMu.Unlock()
+ }
+
+ if err := m.sendMessage(globalRequestMsg{
+ Type: name,
+ WantReply: wantReply,
+ Data: payload,
+ }); err != nil {
+ return false, nil, err
+ }
+
+ if !wantReply {
+ return false, nil, nil
+ }
+
+ msg, ok := <-m.globalResponses
+ if !ok {
+ return false, nil, io.EOF
+ }
+ switch msg := msg.(type) {
+ case *globalRequestFailureMsg:
+ return false, msg.Data, nil
+ case *globalRequestSuccessMsg:
+ return true, msg.Data, nil
+ default:
+ return false, nil, fmt.Errorf("ssh: unexpected response to request: %#v", msg)
+ }
+}
+
+// ackRequest must be called after processing a global request that
+// has WantReply set.
+func (m *mux) ackRequest(ok bool, data []byte) error {
+ if ok {
+ return m.sendMessage(globalRequestSuccessMsg{Data: data})
+ }
+ return m.sendMessage(globalRequestFailureMsg{Data: data})
+}
+
+func (m *mux) Close() error {
+ return m.conn.Close()
+}
+
+// loop runs the connection machine. It will process packets until an
+// error is encountered. To synchronize on loop exit, use mux.Wait.
+func (m *mux) loop() {
+ var err error
+ for err == nil {
+ err = m.onePacket()
+ }
+
+ for _, ch := range m.chanList.dropAll() {
+ ch.close()
+ }
+
+ close(m.incomingChannels)
+ close(m.incomingRequests)
+ close(m.globalResponses)
+
+ m.conn.Close()
+
+ m.errCond.L.Lock()
+ m.err = err
+ m.errCond.Broadcast()
+ m.errCond.L.Unlock()
+
+ if debugMux {
+ log.Println("loop exit", err)
+ }
+}
+
+// onePacket reads and processes one packet.
+func (m *mux) onePacket() error {
+ packet, err := m.conn.readPacket()
+ if err != nil {
+ return err
+ }
+
+ if debugMux {
+ if packet[0] == msgChannelData || packet[0] == msgChannelExtendedData {
+ log.Printf("decoding(%d): data packet - %d bytes", m.chanList.offset, len(packet))
+ } else {
+ p, _ := decode(packet)
+ log.Printf("decoding(%d): %d %#v - %d bytes", m.chanList.offset, packet[0], p, len(packet))
+ }
+ }
+
+ switch packet[0] {
+ case msgChannelOpen:
+ return m.handleChannelOpen(packet)
+ case msgGlobalRequest, msgRequestSuccess, msgRequestFailure:
+ return m.handleGlobalPacket(packet)
+ }
+
+ // assume a channel packet.
+ if len(packet) < 5 {
+ return parseError(packet[0])
+ }
+ id := binary.BigEndian.Uint32(packet[1:])
+ ch := m.chanList.getChan(id)
+ if ch == nil {
+ return fmt.Errorf("ssh: invalid channel %d", id)
+ }
+
+ return ch.handlePacket(packet)
+}
+
+func (m *mux) handleGlobalPacket(packet []byte) error {
+ msg, err := decode(packet)
+ if err != nil {
+ return err
+ }
+
+ switch msg := msg.(type) {
+ case *globalRequestMsg:
+ m.incomingRequests <- &Request{
+ Type: msg.Type,
+ WantReply: msg.WantReply,
+ Payload: msg.Data,
+ mux: m,
+ }
+ case *globalRequestSuccessMsg, *globalRequestFailureMsg:
+ m.globalResponses <- msg
+ default:
+ panic(fmt.Sprintf("not a global message %#v", msg))
+ }
+
+ return nil
+}
+
+// handleChannelOpen schedules a channel to be Accept()ed.
+func (m *mux) handleChannelOpen(packet []byte) error {
+ var msg channelOpenMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return err
+ }
+
+ if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {
+ failMsg := channelOpenFailureMsg{
+ PeersId: msg.PeersId,
+ Reason: ConnectionFailed,
+ Message: "invalid request",
+ Language: "en_US.UTF-8",
+ }
+ return m.sendMessage(failMsg)
+ }
+
+ c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData)
+ c.remoteId = msg.PeersId
+ c.maxRemotePayload = msg.MaxPacketSize
+ c.remoteWin.add(msg.PeersWindow)
+ m.incomingChannels <- c
+ return nil
+}
+
+func (m *mux) OpenChannel(chanType string, extra []byte) (Channel, <-chan *Request, error) {
+ ch, err := m.openChannel(chanType, extra)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return ch, ch.incomingRequests, nil
+}
+
+func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) {
+ ch := m.newChannel(chanType, channelOutbound, extra)
+
+ ch.maxIncomingPayload = channelMaxPacket
+
+ open := channelOpenMsg{
+ ChanType: chanType,
+ PeersWindow: ch.myWindow,
+ MaxPacketSize: ch.maxIncomingPayload,
+ TypeSpecificData: extra,
+ PeersId: ch.localId,
+ }
+ if err := m.sendMessage(open); err != nil {
+ return nil, err
+ }
+
+ switch msg := (<-ch.msg).(type) {
+ case *channelOpenConfirmMsg:
+ return ch, nil
+ case *channelOpenFailureMsg:
+ return nil, &OpenChannelError{msg.Reason, msg.Message}
+ default:
+ return nil, fmt.Errorf("ssh: unexpected packet in response to channel open: %T", msg)
+ }
+}
diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go
new file mode 100644
index 0000000..b6f4cc8
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/server.go
@@ -0,0 +1,563 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "strings"
+)
+
+// The Permissions type holds fine-grained permissions that are
+// specific to a user or a specific authentication method for a user.
+// The Permissions value for a successful authentication attempt is
+// available in ServerConn, so it can be used to pass information from
+// the user-authentication phase to the application layer.
+type Permissions struct {
+ // CriticalOptions indicate restrictions to the default
+ // permissions, and are typically used in conjunction with
+ // user certificates. The standard for SSH certificates
+ // defines "force-command" (only allow the given command to
+ // execute) and "source-address" (only allow connections from
+ // the given address). The SSH package currently only enforces
+ // the "source-address" critical option. It is up to server
+ // implementations to enforce other critical options, such as
+ // "force-command", by checking them after the SSH handshake
+ // is successful. In general, SSH servers should reject
+ // connections that specify critical options that are unknown
+ // or not supported.
+ CriticalOptions map[string]string
+
+ // Extensions are extra functionality that the server may
+ // offer on authenticated connections. Lack of support for an
+ // extension does not preclude authenticating a user. Common
+ // extensions are "permit-agent-forwarding",
+ // "permit-X11-forwarding". The Go SSH library currently does
+ // not act on any extension, and it is up to server
+ // implementations to honor them. Extensions can be used to
+ // pass data from the authentication callbacks to the server
+ // application layer.
+ Extensions map[string]string
+}
+
+// ServerConfig holds server specific configuration data.
+type ServerConfig struct {
+ // Config contains configuration shared between client and server.
+ Config
+
+ hostKeys []Signer
+
+ // NoClientAuth is true if clients are allowed to connect without
+ // authenticating.
+ NoClientAuth bool
+
+ // MaxAuthTries specifies the maximum number of authentication attempts
+ // permitted per connection. If set to a negative number, the number of
+ // attempts are unlimited. If set to zero, the number of attempts are limited
+ // to 6.
+ MaxAuthTries int
+
+ // PasswordCallback, if non-nil, is called when a user
+ // attempts to authenticate using a password.
+ PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
+
+ // PublicKeyCallback, if non-nil, is called when a client
+ // offers a public key for authentication. It must return true
+ // if the given public key can be used to authenticate the
+ // given user. For example, see CertChecker.Authenticate. A
+ // call to this function does not guarantee that the key
+ // offered is in fact used to authenticate. To record any data
+ // depending on the public key, store it inside a
+ // Permissions.Extensions entry.
+ PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
+
+ // KeyboardInteractiveCallback, if non-nil, is called when
+ // keyboard-interactive authentication is selected (RFC
+ // 4256). The client object's Challenge function should be
+ // used to query the user. The callback may offer multiple
+ // Challenge rounds. To avoid information leaks, the client
+ // should be presented a challenge even if the user is
+ // unknown.
+ KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error)
+
+ // AuthLogCallback, if non-nil, is called to log all authentication
+ // attempts.
+ AuthLogCallback func(conn ConnMetadata, method string, err error)
+
+ // ServerVersion is the version identification string to announce in
+ // the public handshake.
+ // If empty, a reasonable default is used.
+ // Note that RFC 4253 section 4.2 requires that this string start with
+ // "SSH-2.0-".
+ ServerVersion string
+}
+
+// AddHostKey adds a private key as a host key. If an existing host
+// key exists with the same algorithm, it is overwritten. Each server
+// config must have at least one host key.
+func (s *ServerConfig) AddHostKey(key Signer) {
+ for i, k := range s.hostKeys {
+ if k.PublicKey().Type() == key.PublicKey().Type() {
+ s.hostKeys[i] = key
+ return
+ }
+ }
+
+ s.hostKeys = append(s.hostKeys, key)
+}
+
+// cachedPubKey contains the results of querying whether a public key is
+// acceptable for a user.
+type cachedPubKey struct {
+ user string
+ pubKeyData []byte
+ result error
+ perms *Permissions
+}
+
+const maxCachedPubKeys = 16
+
+// pubKeyCache caches tests for public keys. Since SSH clients
+// will query whether a public key is acceptable before attempting to
+// authenticate with it, we end up with duplicate queries for public
+// key validity. The cache only applies to a single ServerConn.
+type pubKeyCache struct {
+ keys []cachedPubKey
+}
+
+// get returns the result for a given user/algo/key tuple.
+func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) {
+ for _, k := range c.keys {
+ if k.user == user && bytes.Equal(k.pubKeyData, pubKeyData) {
+ return k, true
+ }
+ }
+ return cachedPubKey{}, false
+}
+
+// add adds the given tuple to the cache.
+func (c *pubKeyCache) add(candidate cachedPubKey) {
+ if len(c.keys) < maxCachedPubKeys {
+ c.keys = append(c.keys, candidate)
+ }
+}
+
+// ServerConn is an authenticated SSH connection, as seen from the
+// server
+type ServerConn struct {
+ Conn
+
+ // If the succeeding authentication callback returned a
+ // non-nil Permissions pointer, it is stored here.
+ Permissions *Permissions
+}
+
+// NewServerConn starts a new SSH server with c as the underlying
+// transport. It starts with a handshake and, if the handshake is
+// unsuccessful, it closes the connection and returns an error. The
+// Request and NewChannel channels must be serviced, or the connection
+// will hang.
+func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
+ fullConf := *config
+ fullConf.SetDefaults()
+ if fullConf.MaxAuthTries == 0 {
+ fullConf.MaxAuthTries = 6
+ }
+
+ s := &connection{
+ sshConn: sshConn{conn: c},
+ }
+ perms, err := s.serverHandshake(&fullConf)
+ if err != nil {
+ c.Close()
+ return nil, nil, nil, err
+ }
+ return &ServerConn{s, perms}, s.mux.incomingChannels, s.mux.incomingRequests, nil
+}
+
+// signAndMarshal signs the data with the appropriate algorithm,
+// and serializes the result in SSH wire format.
+func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) {
+ sig, err := k.Sign(rand, data)
+ if err != nil {
+ return nil, err
+ }
+
+ return Marshal(sig), nil
+}
+
+// handshake performs key exchange and user authentication.
+func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) {
+ if len(config.hostKeys) == 0 {
+ return nil, errors.New("ssh: server has no host keys")
+ }
+
+ if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil && config.KeyboardInteractiveCallback == nil {
+ return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
+ }
+
+ if config.ServerVersion != "" {
+ s.serverVersion = []byte(config.ServerVersion)
+ } else {
+ s.serverVersion = []byte(packageVersion)
+ }
+ var err error
+ s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion)
+ if err != nil {
+ return nil, err
+ }
+
+ tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */)
+ s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config)
+
+ if err := s.transport.waitSession(); err != nil {
+ return nil, err
+ }
+
+ // We just did the key change, so the session ID is established.
+ s.sessionID = s.transport.getSessionID()
+
+ var packet []byte
+ if packet, err = s.transport.readPacket(); err != nil {
+ return nil, err
+ }
+
+ var serviceRequest serviceRequestMsg
+ if err = Unmarshal(packet, &serviceRequest); err != nil {
+ return nil, err
+ }
+ if serviceRequest.Service != serviceUserAuth {
+ return nil, errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating")
+ }
+ serviceAccept := serviceAcceptMsg{
+ Service: serviceUserAuth,
+ }
+ if err := s.transport.writePacket(Marshal(&serviceAccept)); err != nil {
+ return nil, err
+ }
+
+ perms, err := s.serverAuthenticate(config)
+ if err != nil {
+ return nil, err
+ }
+ s.mux = newMux(s.transport)
+ return perms, err
+}
+
+func isAcceptableAlgo(algo string) bool {
+ switch algo {
+ case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoED25519,
+ CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01:
+ return true
+ }
+ return false
+}
+
+func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
+ if addr == nil {
+ return errors.New("ssh: no address known for client, but source-address match required")
+ }
+
+ tcpAddr, ok := addr.(*net.TCPAddr)
+ if !ok {
+ return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr)
+ }
+
+ for _, sourceAddr := range strings.Split(sourceAddrs, ",") {
+ if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
+ if allowedIP.Equal(tcpAddr.IP) {
+ return nil
+ }
+ } else {
+ _, ipNet, err := net.ParseCIDR(sourceAddr)
+ if err != nil {
+ return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
+ }
+
+ if ipNet.Contains(tcpAddr.IP) {
+ return nil
+ }
+ }
+ }
+
+ return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr)
+}
+
+// ServerAuthError implements the error interface. It appends any authentication
+// errors that may occur, and is returned if all of the authentication methods
+// provided by the user failed to authenticate.
+type ServerAuthError struct {
+ // Errors contains authentication errors returned by the authentication
+ // callback methods.
+ Errors []error
+}
+
+func (l ServerAuthError) Error() string {
+ var errs []string
+ for _, err := range l.Errors {
+ errs = append(errs, err.Error())
+ }
+ return "[" + strings.Join(errs, ", ") + "]"
+}
+
+func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
+ sessionID := s.transport.getSessionID()
+ var cache pubKeyCache
+ var perms *Permissions
+
+ authFailures := 0
+ var authErrs []error
+
+userAuthLoop:
+ for {
+ if authFailures >= config.MaxAuthTries && config.MaxAuthTries > 0 {
+ discMsg := &disconnectMsg{
+ Reason: 2,
+ Message: "too many authentication failures",
+ }
+
+ if err := s.transport.writePacket(Marshal(discMsg)); err != nil {
+ return nil, err
+ }
+
+ return nil, discMsg
+ }
+
+ var userAuthReq userAuthRequestMsg
+ if packet, err := s.transport.readPacket(); err != nil {
+ if err == io.EOF {
+ return nil, &ServerAuthError{Errors: authErrs}
+ }
+ return nil, err
+ } else if err = Unmarshal(packet, &userAuthReq); err != nil {
+ return nil, err
+ }
+
+ if userAuthReq.Service != serviceSSH {
+ return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service)
+ }
+
+ s.user = userAuthReq.User
+ perms = nil
+ authErr := errors.New("no auth passed yet")
+
+ switch userAuthReq.Method {
+ case "none":
+ if config.NoClientAuth {
+ authErr = nil
+ }
+
+ // allow initial attempt of 'none' without penalty
+ if authFailures == 0 {
+ authFailures--
+ }
+ case "password":
+ if config.PasswordCallback == nil {
+ authErr = errors.New("ssh: password auth not configured")
+ break
+ }
+ payload := userAuthReq.Payload
+ if len(payload) < 1 || payload[0] != 0 {
+ return nil, parseError(msgUserAuthRequest)
+ }
+ payload = payload[1:]
+ password, payload, ok := parseString(payload)
+ if !ok || len(payload) > 0 {
+ return nil, parseError(msgUserAuthRequest)
+ }
+
+ perms, authErr = config.PasswordCallback(s, password)
+ case "keyboard-interactive":
+ if config.KeyboardInteractiveCallback == nil {
+ authErr = errors.New("ssh: keyboard-interactive auth not configubred")
+ break
+ }
+
+ prompter := &sshClientKeyboardInteractive{s}
+ perms, authErr = config.KeyboardInteractiveCallback(s, prompter.Challenge)
+ case "publickey":
+ if config.PublicKeyCallback == nil {
+ authErr = errors.New("ssh: publickey auth not configured")
+ break
+ }
+ payload := userAuthReq.Payload
+ if len(payload) < 1 {
+ return nil, parseError(msgUserAuthRequest)
+ }
+ isQuery := payload[0] == 0
+ payload = payload[1:]
+ algoBytes, payload, ok := parseString(payload)
+ if !ok {
+ return nil, parseError(msgUserAuthRequest)
+ }
+ algo := string(algoBytes)
+ if !isAcceptableAlgo(algo) {
+ authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo)
+ break
+ }
+
+ pubKeyData, payload, ok := parseString(payload)
+ if !ok {
+ return nil, parseError(msgUserAuthRequest)
+ }
+
+ pubKey, err := ParsePublicKey(pubKeyData)
+ if err != nil {
+ return nil, err
+ }
+
+ candidate, ok := cache.get(s.user, pubKeyData)
+ if !ok {
+ candidate.user = s.user
+ candidate.pubKeyData = pubKeyData
+ candidate.perms, candidate.result = config.PublicKeyCallback(s, pubKey)
+ if candidate.result == nil && candidate.perms != nil && candidate.perms.CriticalOptions != nil && candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" {
+ candidate.result = checkSourceAddress(
+ s.RemoteAddr(),
+ candidate.perms.CriticalOptions[sourceAddressCriticalOption])
+ }
+ cache.add(candidate)
+ }
+
+ if isQuery {
+ // The client can query if the given public key
+ // would be okay.
+
+ if len(payload) > 0 {
+ return nil, parseError(msgUserAuthRequest)
+ }
+
+ if candidate.result == nil {
+ okMsg := userAuthPubKeyOkMsg{
+ Algo: algo,
+ PubKey: pubKeyData,
+ }
+ if err = s.transport.writePacket(Marshal(&okMsg)); err != nil {
+ return nil, err
+ }
+ continue userAuthLoop
+ }
+ authErr = candidate.result
+ } else {
+ sig, payload, ok := parseSignature(payload)
+ if !ok || len(payload) > 0 {
+ return nil, parseError(msgUserAuthRequest)
+ }
+ // Ensure the public key algo and signature algo
+ // are supported. Compare the private key
+ // algorithm name that corresponds to algo with
+ // sig.Format. This is usually the same, but
+ // for certs, the names differ.
+ if !isAcceptableAlgo(sig.Format) {
+ break
+ }
+ signedData := buildDataSignedForAuth(sessionID, userAuthReq, algoBytes, pubKeyData)
+
+ if err := pubKey.Verify(signedData, sig); err != nil {
+ return nil, err
+ }
+
+ authErr = candidate.result
+ perms = candidate.perms
+ }
+ default:
+ authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method)
+ }
+
+ authErrs = append(authErrs, authErr)
+
+ if config.AuthLogCallback != nil {
+ config.AuthLogCallback(s, userAuthReq.Method, authErr)
+ }
+
+ if authErr == nil {
+ break userAuthLoop
+ }
+
+ authFailures++
+
+ var failureMsg userAuthFailureMsg
+ if config.PasswordCallback != nil {
+ failureMsg.Methods = append(failureMsg.Methods, "password")
+ }
+ if config.PublicKeyCallback != nil {
+ failureMsg.Methods = append(failureMsg.Methods, "publickey")
+ }
+ if config.KeyboardInteractiveCallback != nil {
+ failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive")
+ }
+
+ if len(failureMsg.Methods) == 0 {
+ return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
+ }
+
+ if err := s.transport.writePacket(Marshal(&failureMsg)); err != nil {
+ return nil, err
+ }
+ }
+
+ if err := s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil {
+ return nil, err
+ }
+ return perms, nil
+}
+
+// sshClientKeyboardInteractive implements a ClientKeyboardInteractive by
+// asking the client on the other side of a ServerConn.
+type sshClientKeyboardInteractive struct {
+ *connection
+}
+
+func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
+ if len(questions) != len(echos) {
+ return nil, errors.New("ssh: echos and questions must have equal length")
+ }
+
+ var prompts []byte
+ for i := range questions {
+ prompts = appendString(prompts, questions[i])
+ prompts = appendBool(prompts, echos[i])
+ }
+
+ if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{
+ Instruction: instruction,
+ NumPrompts: uint32(len(questions)),
+ Prompts: prompts,
+ })); err != nil {
+ return nil, err
+ }
+
+ packet, err := c.transport.readPacket()
+ if err != nil {
+ return nil, err
+ }
+ if packet[0] != msgUserAuthInfoResponse {
+ return nil, unexpectedMessageError(msgUserAuthInfoResponse, packet[0])
+ }
+ packet = packet[1:]
+
+ n, packet, ok := parseUint32(packet)
+ if !ok || int(n) != len(questions) {
+ return nil, parseError(msgUserAuthInfoResponse)
+ }
+
+ for i := uint32(0); i < n; i++ {
+ ans, rest, ok := parseString(packet)
+ if !ok {
+ return nil, parseError(msgUserAuthInfoResponse)
+ }
+
+ answers = append(answers, string(ans))
+ packet = rest
+ }
+ if len(packet) != 0 {
+ return nil, errors.New("ssh: junk at end of message")
+ }
+
+ return answers, nil
+}
diff --git a/vendor/golang.org/x/crypto/ssh/session.go b/vendor/golang.org/x/crypto/ssh/session.go
new file mode 100644
index 0000000..cc06e03
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/session.go
@@ -0,0 +1,647 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+// Session implements an interactive session described in
+// "RFC 4254, section 6".
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "sync"
+)
+
+type Signal string
+
+// POSIX signals as listed in RFC 4254 Section 6.10.
+const (
+ SIGABRT Signal = "ABRT"
+ SIGALRM Signal = "ALRM"
+ SIGFPE Signal = "FPE"
+ SIGHUP Signal = "HUP"
+ SIGILL Signal = "ILL"
+ SIGINT Signal = "INT"
+ SIGKILL Signal = "KILL"
+ SIGPIPE Signal = "PIPE"
+ SIGQUIT Signal = "QUIT"
+ SIGSEGV Signal = "SEGV"
+ SIGTERM Signal = "TERM"
+ SIGUSR1 Signal = "USR1"
+ SIGUSR2 Signal = "USR2"
+)
+
+var signals = map[Signal]int{
+ SIGABRT: 6,
+ SIGALRM: 14,
+ SIGFPE: 8,
+ SIGHUP: 1,
+ SIGILL: 4,
+ SIGINT: 2,
+ SIGKILL: 9,
+ SIGPIPE: 13,
+ SIGQUIT: 3,
+ SIGSEGV: 11,
+ SIGTERM: 15,
+}
+
+type TerminalModes map[uint8]uint32
+
+// POSIX terminal mode flags as listed in RFC 4254 Section 8.
+const (
+ tty_OP_END = 0
+ VINTR = 1
+ VQUIT = 2
+ VERASE = 3
+ VKILL = 4
+ VEOF = 5
+ VEOL = 6
+ VEOL2 = 7
+ VSTART = 8
+ VSTOP = 9
+ VSUSP = 10
+ VDSUSP = 11
+ VREPRINT = 12
+ VWERASE = 13
+ VLNEXT = 14
+ VFLUSH = 15
+ VSWTCH = 16
+ VSTATUS = 17
+ VDISCARD = 18
+ IGNPAR = 30
+ PARMRK = 31
+ INPCK = 32
+ ISTRIP = 33
+ INLCR = 34
+ IGNCR = 35
+ ICRNL = 36
+ IUCLC = 37
+ IXON = 38
+ IXANY = 39
+ IXOFF = 40
+ IMAXBEL = 41
+ ISIG = 50
+ ICANON = 51
+ XCASE = 52
+ ECHO = 53
+ ECHOE = 54
+ ECHOK = 55
+ ECHONL = 56
+ NOFLSH = 57
+ TOSTOP = 58
+ IEXTEN = 59
+ ECHOCTL = 60
+ ECHOKE = 61
+ PENDIN = 62
+ OPOST = 70
+ OLCUC = 71
+ ONLCR = 72
+ OCRNL = 73
+ ONOCR = 74
+ ONLRET = 75
+ CS7 = 90
+ CS8 = 91
+ PARENB = 92
+ PARODD = 93
+ TTY_OP_ISPEED = 128
+ TTY_OP_OSPEED = 129
+)
+
+// A Session represents a connection to a remote command or shell.
+type Session struct {
+ // Stdin specifies the remote process's standard input.
+ // If Stdin is nil, the remote process reads from an empty
+ // bytes.Buffer.
+ Stdin io.Reader
+
+ // Stdout and Stderr specify the remote process's standard
+ // output and error.
+ //
+ // If either is nil, Run connects the corresponding file
+ // descriptor to an instance of ioutil.Discard. There is a
+ // fixed amount of buffering that is shared for the two streams.
+ // If either blocks it may eventually cause the remote
+ // command to block.
+ Stdout io.Writer
+ Stderr io.Writer
+
+ ch Channel // the channel backing this session
+ started bool // true once Start, Run or Shell is invoked.
+ copyFuncs []func() error
+ errors chan error // one send per copyFunc
+
+ // true if pipe method is active
+ stdinpipe, stdoutpipe, stderrpipe bool
+
+ // stdinPipeWriter is non-nil if StdinPipe has not been called
+ // and Stdin was specified by the user; it is the write end of
+ // a pipe connecting Session.Stdin to the stdin channel.
+ stdinPipeWriter io.WriteCloser
+
+ exitStatus chan error
+}
+
+// SendRequest sends an out-of-band channel request on the SSH channel
+// underlying the session.
+func (s *Session) SendRequest(name string, wantReply bool, payload []byte) (bool, error) {
+ return s.ch.SendRequest(name, wantReply, payload)
+}
+
+func (s *Session) Close() error {
+ return s.ch.Close()
+}
+
+// RFC 4254 Section 6.4.
+type setenvRequest struct {
+ Name string
+ Value string
+}
+
+// Setenv sets an environment variable that will be applied to any
+// command executed by Shell or Run.
+func (s *Session) Setenv(name, value string) error {
+ msg := setenvRequest{
+ Name: name,
+ Value: value,
+ }
+ ok, err := s.ch.SendRequest("env", true, Marshal(&msg))
+ if err == nil && !ok {
+ err = errors.New("ssh: setenv failed")
+ }
+ return err
+}
+
+// RFC 4254 Section 6.2.
+type ptyRequestMsg struct {
+ Term string
+ Columns uint32
+ Rows uint32
+ Width uint32
+ Height uint32
+ Modelist string
+}
+
+// RequestPty requests the association of a pty with the session on the remote host.
+func (s *Session) RequestPty(term string, h, w int, termmodes TerminalModes) error {
+ var tm []byte
+ for k, v := range termmodes {
+ kv := struct {
+ Key byte
+ Val uint32
+ }{k, v}
+
+ tm = append(tm, Marshal(&kv)...)
+ }
+ tm = append(tm, tty_OP_END)
+ req := ptyRequestMsg{
+ Term: term,
+ Columns: uint32(w),
+ Rows: uint32(h),
+ Width: uint32(w * 8),
+ Height: uint32(h * 8),
+ Modelist: string(tm),
+ }
+ ok, err := s.ch.SendRequest("pty-req", true, Marshal(&req))
+ if err == nil && !ok {
+ err = errors.New("ssh: pty-req failed")
+ }
+ return err
+}
+
+// RFC 4254 Section 6.5.
+type subsystemRequestMsg struct {
+ Subsystem string
+}
+
+// RequestSubsystem requests the association of a subsystem with the session on the remote host.
+// A subsystem is a predefined command that runs in the background when the ssh session is initiated
+func (s *Session) RequestSubsystem(subsystem string) error {
+ msg := subsystemRequestMsg{
+ Subsystem: subsystem,
+ }
+ ok, err := s.ch.SendRequest("subsystem", true, Marshal(&msg))
+ if err == nil && !ok {
+ err = errors.New("ssh: subsystem request failed")
+ }
+ return err
+}
+
+// RFC 4254 Section 6.7.
+type ptyWindowChangeMsg struct {
+ Columns uint32
+ Rows uint32
+ Width uint32
+ Height uint32
+}
+
+// WindowChange informs the remote host about a terminal window dimension change to h rows and w columns.
+func (s *Session) WindowChange(h, w int) error {
+ req := ptyWindowChangeMsg{
+ Columns: uint32(w),
+ Rows: uint32(h),
+ Width: uint32(w * 8),
+ Height: uint32(h * 8),
+ }
+ _, err := s.ch.SendRequest("window-change", false, Marshal(&req))
+ return err
+}
+
+// RFC 4254 Section 6.9.
+type signalMsg struct {
+ Signal string
+}
+
+// Signal sends the given signal to the remote process.
+// sig is one of the SIG* constants.
+func (s *Session) Signal(sig Signal) error {
+ msg := signalMsg{
+ Signal: string(sig),
+ }
+
+ _, err := s.ch.SendRequest("signal", false, Marshal(&msg))
+ return err
+}
+
+// RFC 4254 Section 6.5.
+type execMsg struct {
+ Command string
+}
+
+// Start runs cmd on the remote host. Typically, the remote
+// server passes cmd to the shell for interpretation.
+// A Session only accepts one call to Run, Start or Shell.
+func (s *Session) Start(cmd string) error {
+ if s.started {
+ return errors.New("ssh: session already started")
+ }
+ req := execMsg{
+ Command: cmd,
+ }
+
+ ok, err := s.ch.SendRequest("exec", true, Marshal(&req))
+ if err == nil && !ok {
+ err = fmt.Errorf("ssh: command %v failed", cmd)
+ }
+ if err != nil {
+ return err
+ }
+ return s.start()
+}
+
+// Run runs cmd on the remote host. Typically, the remote
+// server passes cmd to the shell for interpretation.
+// A Session only accepts one call to Run, Start, Shell, Output,
+// or CombinedOutput.
+//
+// The returned error is nil if the command runs, has no problems
+// copying stdin, stdout, and stderr, and exits with a zero exit
+// status.
+//
+// If the remote server does not send an exit status, an error of type
+// *ExitMissingError is returned. If the command completes
+// unsuccessfully or is interrupted by a signal, the error is of type
+// *ExitError. Other error types may be returned for I/O problems.
+func (s *Session) Run(cmd string) error {
+ err := s.Start(cmd)
+ if err != nil {
+ return err
+ }
+ return s.Wait()
+}
+
+// Output runs cmd on the remote host and returns its standard output.
+func (s *Session) Output(cmd string) ([]byte, error) {
+ if s.Stdout != nil {
+ return nil, errors.New("ssh: Stdout already set")
+ }
+ var b bytes.Buffer
+ s.Stdout = &b
+ err := s.Run(cmd)
+ return b.Bytes(), err
+}
+
+type singleWriter struct {
+ b bytes.Buffer
+ mu sync.Mutex
+}
+
+func (w *singleWriter) Write(p []byte) (int, error) {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ return w.b.Write(p)
+}
+
+// CombinedOutput runs cmd on the remote host and returns its combined
+// standard output and standard error.
+func (s *Session) CombinedOutput(cmd string) ([]byte, error) {
+ if s.Stdout != nil {
+ return nil, errors.New("ssh: Stdout already set")
+ }
+ if s.Stderr != nil {
+ return nil, errors.New("ssh: Stderr already set")
+ }
+ var b singleWriter
+ s.Stdout = &b
+ s.Stderr = &b
+ err := s.Run(cmd)
+ return b.b.Bytes(), err
+}
+
+// Shell starts a login shell on the remote host. A Session only
+// accepts one call to Run, Start, Shell, Output, or CombinedOutput.
+func (s *Session) Shell() error {
+ if s.started {
+ return errors.New("ssh: session already started")
+ }
+
+ ok, err := s.ch.SendRequest("shell", true, nil)
+ if err == nil && !ok {
+ return errors.New("ssh: could not start shell")
+ }
+ if err != nil {
+ return err
+ }
+ return s.start()
+}
+
+func (s *Session) start() error {
+ s.started = true
+
+ type F func(*Session)
+ for _, setupFd := range []F{(*Session).stdin, (*Session).stdout, (*Session).stderr} {
+ setupFd(s)
+ }
+
+ s.errors = make(chan error, len(s.copyFuncs))
+ for _, fn := range s.copyFuncs {
+ go func(fn func() error) {
+ s.errors <- fn()
+ }(fn)
+ }
+ return nil
+}
+
+// Wait waits for the remote command to exit.
+//
+// The returned error is nil if the command runs, has no problems
+// copying stdin, stdout, and stderr, and exits with a zero exit
+// status.
+//
+// If the remote server does not send an exit status, an error of type
+// *ExitMissingError is returned. If the command completes
+// unsuccessfully or is interrupted by a signal, the error is of type
+// *ExitError. Other error types may be returned for I/O problems.
+func (s *Session) Wait() error {
+ if !s.started {
+ return errors.New("ssh: session not started")
+ }
+ waitErr := <-s.exitStatus
+
+ if s.stdinPipeWriter != nil {
+ s.stdinPipeWriter.Close()
+ }
+ var copyError error
+ for _ = range s.copyFuncs {
+ if err := <-s.errors; err != nil && copyError == nil {
+ copyError = err
+ }
+ }
+ if waitErr != nil {
+ return waitErr
+ }
+ return copyError
+}
+
+func (s *Session) wait(reqs <-chan *Request) error {
+ wm := Waitmsg{status: -1}
+ // Wait for msg channel to be closed before returning.
+ for msg := range reqs {
+ switch msg.Type {
+ case "exit-status":
+ wm.status = int(binary.BigEndian.Uint32(msg.Payload))
+ case "exit-signal":
+ var sigval struct {
+ Signal string
+ CoreDumped bool
+ Error string
+ Lang string
+ }
+ if err := Unmarshal(msg.Payload, &sigval); err != nil {
+ return err
+ }
+
+ // Must sanitize strings?
+ wm.signal = sigval.Signal
+ wm.msg = sigval.Error
+ wm.lang = sigval.Lang
+ default:
+ // This handles keepalives and matches
+ // OpenSSH's behaviour.
+ if msg.WantReply {
+ msg.Reply(false, nil)
+ }
+ }
+ }
+ if wm.status == 0 {
+ return nil
+ }
+ if wm.status == -1 {
+ // exit-status was never sent from server
+ if wm.signal == "" {
+ // signal was not sent either. RFC 4254
+ // section 6.10 recommends against this
+ // behavior, but it is allowed, so we let
+ // clients handle it.
+ return &ExitMissingError{}
+ }
+ wm.status = 128
+ if _, ok := signals[Signal(wm.signal)]; ok {
+ wm.status += signals[Signal(wm.signal)]
+ }
+ }
+
+ return &ExitError{wm}
+}
+
+// ExitMissingError is returned if a session is torn down cleanly, but
+// the server sends no confirmation of the exit status.
+type ExitMissingError struct{}
+
+func (e *ExitMissingError) Error() string {
+ return "wait: remote command exited without exit status or exit signal"
+}
+
+func (s *Session) stdin() {
+ if s.stdinpipe {
+ return
+ }
+ var stdin io.Reader
+ if s.Stdin == nil {
+ stdin = new(bytes.Buffer)
+ } else {
+ r, w := io.Pipe()
+ go func() {
+ _, err := io.Copy(w, s.Stdin)
+ w.CloseWithError(err)
+ }()
+ stdin, s.stdinPipeWriter = r, w
+ }
+ s.copyFuncs = append(s.copyFuncs, func() error {
+ _, err := io.Copy(s.ch, stdin)
+ if err1 := s.ch.CloseWrite(); err == nil && err1 != io.EOF {
+ err = err1
+ }
+ return err
+ })
+}
+
+func (s *Session) stdout() {
+ if s.stdoutpipe {
+ return
+ }
+ if s.Stdout == nil {
+ s.Stdout = ioutil.Discard
+ }
+ s.copyFuncs = append(s.copyFuncs, func() error {
+ _, err := io.Copy(s.Stdout, s.ch)
+ return err
+ })
+}
+
+func (s *Session) stderr() {
+ if s.stderrpipe {
+ return
+ }
+ if s.Stderr == nil {
+ s.Stderr = ioutil.Discard
+ }
+ s.copyFuncs = append(s.copyFuncs, func() error {
+ _, err := io.Copy(s.Stderr, s.ch.Stderr())
+ return err
+ })
+}
+
+// sessionStdin reroutes Close to CloseWrite.
+type sessionStdin struct {
+ io.Writer
+ ch Channel
+}
+
+func (s *sessionStdin) Close() error {
+ return s.ch.CloseWrite()
+}
+
+// StdinPipe returns a pipe that will be connected to the
+// remote command's standard input when the command starts.
+func (s *Session) StdinPipe() (io.WriteCloser, error) {
+ if s.Stdin != nil {
+ return nil, errors.New("ssh: Stdin already set")
+ }
+ if s.started {
+ return nil, errors.New("ssh: StdinPipe after process started")
+ }
+ s.stdinpipe = true
+ return &sessionStdin{s.ch, s.ch}, nil
+}
+
+// StdoutPipe returns a pipe that will be connected to the
+// remote command's standard output when the command starts.
+// There is a fixed amount of buffering that is shared between
+// stdout and stderr streams. If the StdoutPipe reader is
+// not serviced fast enough it may eventually cause the
+// remote command to block.
+func (s *Session) StdoutPipe() (io.Reader, error) {
+ if s.Stdout != nil {
+ return nil, errors.New("ssh: Stdout already set")
+ }
+ if s.started {
+ return nil, errors.New("ssh: StdoutPipe after process started")
+ }
+ s.stdoutpipe = true
+ return s.ch, nil
+}
+
+// StderrPipe returns a pipe that will be connected to the
+// remote command's standard error when the command starts.
+// There is a fixed amount of buffering that is shared between
+// stdout and stderr streams. If the StderrPipe reader is
+// not serviced fast enough it may eventually cause the
+// remote command to block.
+func (s *Session) StderrPipe() (io.Reader, error) {
+ if s.Stderr != nil {
+ return nil, errors.New("ssh: Stderr already set")
+ }
+ if s.started {
+ return nil, errors.New("ssh: StderrPipe after process started")
+ }
+ s.stderrpipe = true
+ return s.ch.Stderr(), nil
+}
+
+// newSession returns a new interactive session on the remote host.
+func newSession(ch Channel, reqs <-chan *Request) (*Session, error) {
+ s := &Session{
+ ch: ch,
+ }
+ s.exitStatus = make(chan error, 1)
+ go func() {
+ s.exitStatus <- s.wait(reqs)
+ }()
+
+ return s, nil
+}
+
+// An ExitError reports unsuccessful completion of a remote command.
+type ExitError struct {
+ Waitmsg
+}
+
+func (e *ExitError) Error() string {
+ return e.Waitmsg.String()
+}
+
+// Waitmsg stores the information about an exited remote command
+// as reported by Wait.
+type Waitmsg struct {
+ status int
+ signal string
+ msg string
+ lang string
+}
+
+// ExitStatus returns the exit status of the remote command.
+func (w Waitmsg) ExitStatus() int {
+ return w.status
+}
+
+// Signal returns the exit signal of the remote command if
+// it was terminated violently.
+func (w Waitmsg) Signal() string {
+ return w.signal
+}
+
+// Msg returns the exit message given by the remote command
+func (w Waitmsg) Msg() string {
+ return w.msg
+}
+
+// Lang returns the language tag. See RFC 3066
+func (w Waitmsg) Lang() string {
+ return w.lang
+}
+
+func (w Waitmsg) String() string {
+ str := fmt.Sprintf("Process exited with status %v", w.status)
+ if w.signal != "" {
+ str += fmt.Sprintf(" from signal %v", w.signal)
+ }
+ if w.msg != "" {
+ str += fmt.Sprintf(". Reason was: %v", w.msg)
+ }
+ return str
+}
diff --git a/vendor/golang.org/x/crypto/ssh/streamlocal.go b/vendor/golang.org/x/crypto/ssh/streamlocal.go
new file mode 100644
index 0000000..a2dccc6
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/streamlocal.go
@@ -0,0 +1,115 @@
+package ssh
+
+import (
+ "errors"
+ "io"
+ "net"
+)
+
+// streamLocalChannelOpenDirectMsg is a struct used for SSH_MSG_CHANNEL_OPEN message
+// with "direct-streamlocal@openssh.com" string.
+//
+// See openssh-portable/PROTOCOL, section 2.4. connection: Unix domain socket forwarding
+// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL#L235
+type streamLocalChannelOpenDirectMsg struct {
+ socketPath string
+ reserved0 string
+ reserved1 uint32
+}
+
+// forwardedStreamLocalPayload is a struct used for SSH_MSG_CHANNEL_OPEN message
+// with "forwarded-streamlocal@openssh.com" string.
+type forwardedStreamLocalPayload struct {
+ SocketPath string
+ Reserved0 string
+}
+
+// streamLocalChannelForwardMsg is a struct used for SSH2_MSG_GLOBAL_REQUEST message
+// with "streamlocal-forward@openssh.com"/"cancel-streamlocal-forward@openssh.com" string.
+type streamLocalChannelForwardMsg struct {
+ socketPath string
+}
+
+// ListenUnix is similar to ListenTCP but uses a Unix domain socket.
+func (c *Client) ListenUnix(socketPath string) (net.Listener, error) {
+ m := streamLocalChannelForwardMsg{
+ socketPath,
+ }
+ // send message
+ ok, _, err := c.SendRequest("streamlocal-forward@openssh.com", true, Marshal(&m))
+ if err != nil {
+ return nil, err
+ }
+ if !ok {
+ return nil, errors.New("ssh: streamlocal-forward@openssh.com request denied by peer")
+ }
+ ch := c.forwards.add(&net.UnixAddr{Name: socketPath, Net: "unix"})
+
+ return &unixListener{socketPath, c, ch}, nil
+}
+
+func (c *Client) dialStreamLocal(socketPath string) (Channel, error) {
+ msg := streamLocalChannelOpenDirectMsg{
+ socketPath: socketPath,
+ }
+ ch, in, err := c.OpenChannel("direct-streamlocal@openssh.com", Marshal(&msg))
+ if err != nil {
+ return nil, err
+ }
+ go DiscardRequests(in)
+ return ch, err
+}
+
+type unixListener struct {
+ socketPath string
+
+ conn *Client
+ in <-chan forward
+}
+
+// Accept waits for and returns the next connection to the listener.
+func (l *unixListener) Accept() (net.Conn, error) {
+ s, ok := <-l.in
+ if !ok {
+ return nil, io.EOF
+ }
+ ch, incoming, err := s.newCh.Accept()
+ if err != nil {
+ return nil, err
+ }
+ go DiscardRequests(incoming)
+
+ return &chanConn{
+ Channel: ch,
+ laddr: &net.UnixAddr{
+ Name: l.socketPath,
+ Net: "unix",
+ },
+ raddr: &net.UnixAddr{
+ Name: "@",
+ Net: "unix",
+ },
+ }, nil
+}
+
+// Close closes the listener.
+func (l *unixListener) Close() error {
+ // this also closes the listener.
+ l.conn.forwards.remove(&net.UnixAddr{Name: l.socketPath, Net: "unix"})
+ m := streamLocalChannelForwardMsg{
+ l.socketPath,
+ }
+ ok, _, err := l.conn.SendRequest("cancel-streamlocal-forward@openssh.com", true, Marshal(&m))
+ if err == nil && !ok {
+ err = errors.New("ssh: cancel-streamlocal-forward@openssh.com failed")
+ }
+ return err
+}
+
+// Addr returns the listener's network address.
+func (l *unixListener) Addr() net.Addr {
+ return &net.UnixAddr{
+ Name: l.socketPath,
+ Net: "unix",
+ }
+}
diff --git a/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/golang.org/x/crypto/ssh/tcpip.go
new file mode 100644
index 0000000..acf1717
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/tcpip.go
@@ -0,0 +1,465 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "math/rand"
+ "net"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+)
+
+// Listen requests the remote peer open a listening socket on
+// addr. Incoming connections will be available by calling Accept on
+// the returned net.Listener. The listener must be serviced, or the
+// SSH connection may hang.
+// N must be "tcp", "tcp4", "tcp6", or "unix".
+func (c *Client) Listen(n, addr string) (net.Listener, error) {
+ switch n {
+ case "tcp", "tcp4", "tcp6":
+ laddr, err := net.ResolveTCPAddr(n, addr)
+ if err != nil {
+ return nil, err
+ }
+ return c.ListenTCP(laddr)
+ case "unix":
+ return c.ListenUnix(addr)
+ default:
+ return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
+ }
+}
+
+// Automatic port allocation is broken with OpenSSH before 6.0. See
+// also https://bugzilla.mindrot.org/show_bug.cgi?id=2017. In
+// particular, OpenSSH 5.9 sends a channelOpenMsg with port number 0,
+// rather than the actual port number. This means you can never open
+// two different listeners with auto allocated ports. We work around
+// this by trying explicit ports until we succeed.
+
+const openSSHPrefix = "OpenSSH_"
+
+var portRandomizer = rand.New(rand.NewSource(time.Now().UnixNano()))
+
+// isBrokenOpenSSHVersion returns true if the given version string
+// specifies a version of OpenSSH that is known to have a bug in port
+// forwarding.
+func isBrokenOpenSSHVersion(versionStr string) bool {
+ i := strings.Index(versionStr, openSSHPrefix)
+ if i < 0 {
+ return false
+ }
+ i += len(openSSHPrefix)
+ j := i
+ for ; j < len(versionStr); j++ {
+ if versionStr[j] < '0' || versionStr[j] > '9' {
+ break
+ }
+ }
+ version, _ := strconv.Atoi(versionStr[i:j])
+ return version < 6
+}
+
+// autoPortListenWorkaround simulates automatic port allocation by
+// trying random ports repeatedly.
+func (c *Client) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Listener, error) {
+ var sshListener net.Listener
+ var err error
+ const tries = 10
+ for i := 0; i < tries; i++ {
+ addr := *laddr
+ addr.Port = 1024 + portRandomizer.Intn(60000)
+ sshListener, err = c.ListenTCP(&addr)
+ if err == nil {
+ laddr.Port = addr.Port
+ return sshListener, err
+ }
+ }
+ return nil, fmt.Errorf("ssh: listen on random port failed after %d tries: %v", tries, err)
+}
+
+// RFC 4254 7.1
+type channelForwardMsg struct {
+ addr string
+ rport uint32
+}
+
+// ListenTCP requests the remote peer open a listening socket
+// on laddr. Incoming connections will be available by calling
+// Accept on the returned net.Listener.
+func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
+ if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) {
+ return c.autoPortListenWorkaround(laddr)
+ }
+
+ m := channelForwardMsg{
+ laddr.IP.String(),
+ uint32(laddr.Port),
+ }
+ // send message
+ ok, resp, err := c.SendRequest("tcpip-forward", true, Marshal(&m))
+ if err != nil {
+ return nil, err
+ }
+ if !ok {
+ return nil, errors.New("ssh: tcpip-forward request denied by peer")
+ }
+
+ // If the original port was 0, then the remote side will
+ // supply a real port number in the response.
+ if laddr.Port == 0 {
+ var p struct {
+ Port uint32
+ }
+ if err := Unmarshal(resp, &p); err != nil {
+ return nil, err
+ }
+ laddr.Port = int(p.Port)
+ }
+
+ // Register this forward, using the port number we obtained.
+ ch := c.forwards.add(laddr)
+
+ return &tcpListener{laddr, c, ch}, nil
+}
+
+// forwardList stores a mapping between remote
+// forward requests and the tcpListeners.
+type forwardList struct {
+ sync.Mutex
+ entries []forwardEntry
+}
+
+// forwardEntry represents an established mapping of a laddr on a
+// remote ssh server to a channel connected to a tcpListener.
+type forwardEntry struct {
+ laddr net.Addr
+ c chan forward
+}
+
+// forward represents an incoming forwarded tcpip connection. The
+// arguments to add/remove/lookup should be address as specified in
+// the original forward-request.
+type forward struct {
+ newCh NewChannel // the ssh client channel underlying this forward
+ raddr net.Addr // the raddr of the incoming connection
+}
+
+func (l *forwardList) add(addr net.Addr) chan forward {
+ l.Lock()
+ defer l.Unlock()
+ f := forwardEntry{
+ laddr: addr,
+ c: make(chan forward, 1),
+ }
+ l.entries = append(l.entries, f)
+ return f.c
+}
+
+// See RFC 4254, section 7.2
+type forwardedTCPPayload struct {
+ Addr string
+ Port uint32
+ OriginAddr string
+ OriginPort uint32
+}
+
+// parseTCPAddr parses the originating address from the remote into a *net.TCPAddr.
+func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) {
+ if port == 0 || port > 65535 {
+ return nil, fmt.Errorf("ssh: port number out of range: %d", port)
+ }
+ ip := net.ParseIP(string(addr))
+ if ip == nil {
+ return nil, fmt.Errorf("ssh: cannot parse IP address %q", addr)
+ }
+ return &net.TCPAddr{IP: ip, Port: int(port)}, nil
+}
+
+func (l *forwardList) handleChannels(in <-chan NewChannel) {
+ for ch := range in {
+ var (
+ laddr net.Addr
+ raddr net.Addr
+ err error
+ )
+ switch channelType := ch.ChannelType(); channelType {
+ case "forwarded-tcpip":
+ var payload forwardedTCPPayload
+ if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
+ ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
+ continue
+ }
+
+ // RFC 4254 section 7.2 specifies that incoming
+ // addresses should list the address, in string
+ // format. It is implied that this should be an IP
+ // address, as it would be impossible to connect to it
+ // otherwise.
+ laddr, err = parseTCPAddr(payload.Addr, payload.Port)
+ if err != nil {
+ ch.Reject(ConnectionFailed, err.Error())
+ continue
+ }
+ raddr, err = parseTCPAddr(payload.OriginAddr, payload.OriginPort)
+ if err != nil {
+ ch.Reject(ConnectionFailed, err.Error())
+ continue
+ }
+
+ case "forwarded-streamlocal@openssh.com":
+ var payload forwardedStreamLocalPayload
+ if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
+ ch.Reject(ConnectionFailed, "could not parse forwarded-streamlocal@openssh.com payload: "+err.Error())
+ continue
+ }
+ laddr = &net.UnixAddr{
+ Name: payload.SocketPath,
+ Net: "unix",
+ }
+ raddr = &net.UnixAddr{
+ Name: "@",
+ Net: "unix",
+ }
+ default:
+ panic(fmt.Errorf("ssh: unknown channel type %s", channelType))
+ }
+ if ok := l.forward(laddr, raddr, ch); !ok {
+ // Section 7.2, implementations MUST reject spurious incoming
+ // connections.
+ ch.Reject(Prohibited, "no forward for address")
+ continue
+ }
+
+ }
+}
+
+// remove removes the forward entry, and the channel feeding its
+// listener.
+func (l *forwardList) remove(addr net.Addr) {
+ l.Lock()
+ defer l.Unlock()
+ for i, f := range l.entries {
+ if addr.Network() == f.laddr.Network() && addr.String() == f.laddr.String() {
+ l.entries = append(l.entries[:i], l.entries[i+1:]...)
+ close(f.c)
+ return
+ }
+ }
+}
+
+// closeAll closes and clears all forwards.
+func (l *forwardList) closeAll() {
+ l.Lock()
+ defer l.Unlock()
+ for _, f := range l.entries {
+ close(f.c)
+ }
+ l.entries = nil
+}
+
+func (l *forwardList) forward(laddr, raddr net.Addr, ch NewChannel) bool {
+ l.Lock()
+ defer l.Unlock()
+ for _, f := range l.entries {
+ if laddr.Network() == f.laddr.Network() && laddr.String() == f.laddr.String() {
+ f.c <- forward{newCh: ch, raddr: raddr}
+ return true
+ }
+ }
+ return false
+}
+
+type tcpListener struct {
+ laddr *net.TCPAddr
+
+ conn *Client
+ in <-chan forward
+}
+
+// Accept waits for and returns the next connection to the listener.
+func (l *tcpListener) Accept() (net.Conn, error) {
+ s, ok := <-l.in
+ if !ok {
+ return nil, io.EOF
+ }
+ ch, incoming, err := s.newCh.Accept()
+ if err != nil {
+ return nil, err
+ }
+ go DiscardRequests(incoming)
+
+ return &chanConn{
+ Channel: ch,
+ laddr: l.laddr,
+ raddr: s.raddr,
+ }, nil
+}
+
+// Close closes the listener.
+func (l *tcpListener) Close() error {
+ m := channelForwardMsg{
+ l.laddr.IP.String(),
+ uint32(l.laddr.Port),
+ }
+
+ // this also closes the listener.
+ l.conn.forwards.remove(l.laddr)
+ ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m))
+ if err == nil && !ok {
+ err = errors.New("ssh: cancel-tcpip-forward failed")
+ }
+ return err
+}
+
+// Addr returns the listener's network address.
+func (l *tcpListener) Addr() net.Addr {
+ return l.laddr
+}
+
+// Dial initiates a connection to the addr from the remote host.
+// The resulting connection has a zero LocalAddr() and RemoteAddr().
+func (c *Client) Dial(n, addr string) (net.Conn, error) {
+ var ch Channel
+ switch n {
+ case "tcp", "tcp4", "tcp6":
+ // Parse the address into host and numeric port.
+ host, portString, err := net.SplitHostPort(addr)
+ if err != nil {
+ return nil, err
+ }
+ port, err := strconv.ParseUint(portString, 10, 16)
+ if err != nil {
+ return nil, err
+ }
+ ch, err = c.dial(net.IPv4zero.String(), 0, host, int(port))
+ if err != nil {
+ return nil, err
+ }
+ // Use a zero address for local and remote address.
+ zeroAddr := &net.TCPAddr{
+ IP: net.IPv4zero,
+ Port: 0,
+ }
+ return &chanConn{
+ Channel: ch,
+ laddr: zeroAddr,
+ raddr: zeroAddr,
+ }, nil
+ case "unix":
+ var err error
+ ch, err = c.dialStreamLocal(addr)
+ if err != nil {
+ return nil, err
+ }
+ return &chanConn{
+ Channel: ch,
+ laddr: &net.UnixAddr{
+ Name: "@",
+ Net: "unix",
+ },
+ raddr: &net.UnixAddr{
+ Name: addr,
+ Net: "unix",
+ },
+ }, nil
+ default:
+ return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
+ }
+}
+
+// DialTCP connects to the remote address raddr on the network net,
+// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used
+// as the local address for the connection.
+func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) {
+ if laddr == nil {
+ laddr = &net.TCPAddr{
+ IP: net.IPv4zero,
+ Port: 0,
+ }
+ }
+ ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port)
+ if err != nil {
+ return nil, err
+ }
+ return &chanConn{
+ Channel: ch,
+ laddr: laddr,
+ raddr: raddr,
+ }, nil
+}
+
+// RFC 4254 7.2
+type channelOpenDirectMsg struct {
+ raddr string
+ rport uint32
+ laddr string
+ lport uint32
+}
+
+func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel, error) {
+ msg := channelOpenDirectMsg{
+ raddr: raddr,
+ rport: uint32(rport),
+ laddr: laddr,
+ lport: uint32(lport),
+ }
+ ch, in, err := c.OpenChannel("direct-tcpip", Marshal(&msg))
+ if err != nil {
+ return nil, err
+ }
+ go DiscardRequests(in)
+ return ch, err
+}
+
+type tcpChan struct {
+ Channel // the backing channel
+}
+
+// chanConn fulfills the net.Conn interface without
+// the tcpChan having to hold laddr or raddr directly.
+type chanConn struct {
+ Channel
+ laddr, raddr net.Addr
+}
+
+// LocalAddr returns the local network address.
+func (t *chanConn) LocalAddr() net.Addr {
+ return t.laddr
+}
+
+// RemoteAddr returns the remote network address.
+func (t *chanConn) RemoteAddr() net.Addr {
+ return t.raddr
+}
+
+// SetDeadline sets the read and write deadlines associated
+// with the connection.
+func (t *chanConn) SetDeadline(deadline time.Time) error {
+ if err := t.SetReadDeadline(deadline); err != nil {
+ return err
+ }
+ return t.SetWriteDeadline(deadline)
+}
+
+// SetReadDeadline sets the read deadline.
+// A zero value for t means Read will not time out.
+// After the deadline, the error from Read will implement net.Error
+// with Timeout() == true.
+func (t *chanConn) SetReadDeadline(deadline time.Time) error {
+ // for compatibility with previous version,
+ // the error message contains "tcpChan"
+ return errors.New("ssh: tcpChan: deadline not supported")
+}
+
+// SetWriteDeadline exists to satisfy the net.Conn interface
+// but is not implemented by this type. It always returns an error.
+func (t *chanConn) SetWriteDeadline(deadline time.Time) error {
+ return errors.New("ssh: tcpChan: deadline not supported")
+}
diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go
new file mode 100644
index 0000000..f9780e0
--- /dev/null
+++ b/vendor/golang.org/x/crypto/ssh/transport.go
@@ -0,0 +1,375 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "bufio"
+ "errors"
+ "io"
+ "log"
+)
+
+// debugTransport if set, will print packet types as they go over the
+// wire. No message decoding is done, to minimize the impact on timing.
+const debugTransport = false
+
+const (
+ gcmCipherID = "aes128-gcm@openssh.com"
+ aes128cbcID = "aes128-cbc"
+ tripledescbcID = "3des-cbc"
+)
+
+// packetConn represents a transport that implements packet based
+// operations.
+type packetConn interface {
+ // Encrypt and send a packet of data to the remote peer.
+ writePacket(packet []byte) error
+
+ // Read a packet from the connection. The read is blocking,
+ // i.e. if error is nil, then the returned byte slice is
+ // always non-empty.
+ readPacket() ([]byte, error)
+
+ // Close closes the write-side of the connection.
+ Close() error
+}
+
+// transport is the keyingTransport that implements the SSH packet
+// protocol.
+type transport struct {
+ reader connectionState
+ writer connectionState
+
+ bufReader *bufio.Reader
+ bufWriter *bufio.Writer
+ rand io.Reader
+ isClient bool
+ io.Closer
+}
+
+// packetCipher represents a combination of SSH encryption/MAC
+// protocol. A single instance should be used for one direction only.
+type packetCipher interface {
+ // writePacket encrypts the packet and writes it to w. The
+ // contents of the packet are generally scrambled.
+ writePacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error
+
+ // readPacket reads and decrypts a packet of data. The
+ // returned packet may be overwritten by future calls of
+ // readPacket.
+ readPacket(seqnum uint32, r io.Reader) ([]byte, error)
+}
+
+// connectionState represents one side (read or write) of the
+// connection. This is necessary because each direction has its own
+// keys, and can even have its own algorithms
+type connectionState struct {
+ packetCipher
+ seqNum uint32
+ dir direction
+ pendingKeyChange chan packetCipher
+}
+
+// prepareKeyChange sets up key material for a keychange. The key changes in
+// both directions are triggered by reading and writing a msgNewKey packet
+// respectively.
+func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error {
+ if ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult); err != nil {
+ return err
+ } else {
+ t.reader.pendingKeyChange <- ciph
+ }
+
+ if ciph, err := newPacketCipher(t.writer.dir, algs.w, kexResult); err != nil {
+ return err
+ } else {
+ t.writer.pendingKeyChange <- ciph
+ }
+
+ return nil
+}
+
+func (t *transport) printPacket(p []byte, write bool) {
+ if len(p) == 0 {
+ return
+ }
+ who := "server"
+ if t.isClient {
+ who = "client"
+ }
+ what := "read"
+ if write {
+ what = "write"
+ }
+
+ log.Println(what, who, p[0])
+}
+
+// Read and decrypt next packet.
+func (t *transport) readPacket() (p []byte, err error) {
+ for {
+ p, err = t.reader.readPacket(t.bufReader)
+ if err != nil {
+ break
+ }
+ if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) {
+ break
+ }
+ }
+ if debugTransport {
+ t.printPacket(p, false)
+ }
+
+ return p, err
+}
+
+func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
+ packet, err := s.packetCipher.readPacket(s.seqNum, r)
+ s.seqNum++
+ if err == nil && len(packet) == 0 {
+ err = errors.New("ssh: zero length packet")
+ }
+
+ if len(packet) > 0 {
+ switch packet[0] {
+ case msgNewKeys:
+ select {
+ case cipher := <-s.pendingKeyChange:
+ s.packetCipher = cipher
+ default:
+ return nil, errors.New("ssh: got bogus newkeys message.")
+ }
+
+ case msgDisconnect:
+ // Transform a disconnect message into an
+ // error. Since this is lowest level at which
+ // we interpret message types, doing it here
+ // ensures that we don't have to handle it
+ // elsewhere.
+ var msg disconnectMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return nil, err
+ }
+ return nil, &msg
+ }
+ }
+
+ // The packet may point to an internal buffer, so copy the
+ // packet out here.
+ fresh := make([]byte, len(packet))
+ copy(fresh, packet)
+
+ return fresh, err
+}
+
+func (t *transport) writePacket(packet []byte) error {
+ if debugTransport {
+ t.printPacket(packet, true)
+ }
+ return t.writer.writePacket(t.bufWriter, t.rand, packet)
+}
+
+func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error {
+ changeKeys := len(packet) > 0 && packet[0] == msgNewKeys
+
+ err := s.packetCipher.writePacket(s.seqNum, w, rand, packet)
+ if err != nil {
+ return err
+ }
+ if err = w.Flush(); err != nil {
+ return err
+ }
+ s.seqNum++
+ if changeKeys {
+ select {
+ case cipher := <-s.pendingKeyChange:
+ s.packetCipher = cipher
+ default:
+ panic("ssh: no key material for msgNewKeys")
+ }
+ }
+ return err
+}
+
+func newTransport(rwc io.ReadWriteCloser, rand io.Reader, isClient bool) *transport {
+ t := &transport{
+ bufReader: bufio.NewReader(rwc),
+ bufWriter: bufio.NewWriter(rwc),
+ rand: rand,
+ reader: connectionState{
+ packetCipher: &streamPacketCipher{cipher: noneCipher{}},
+ pendingKeyChange: make(chan packetCipher, 1),
+ },
+ writer: connectionState{
+ packetCipher: &streamPacketCipher{cipher: noneCipher{}},
+ pendingKeyChange: make(chan packetCipher, 1),
+ },
+ Closer: rwc,
+ }
+ t.isClient = isClient
+
+ if isClient {
+ t.reader.dir = serverKeys
+ t.writer.dir = clientKeys
+ } else {
+ t.reader.dir = clientKeys
+ t.writer.dir = serverKeys
+ }
+
+ return t
+}
+
+type direction struct {
+ ivTag []byte
+ keyTag []byte
+ macKeyTag []byte
+}
+
+var (
+ serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}}
+ clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}}
+)
+
+// generateKeys generates key material for IV, MAC and encryption.
+func generateKeys(d direction, algs directionAlgorithms, kex *kexResult) (iv, key, macKey []byte) {
+ cipherMode := cipherModes[algs.Cipher]
+ macMode := macModes[algs.MAC]
+
+ iv = make([]byte, cipherMode.ivSize)
+ key = make([]byte, cipherMode.keySize)
+ macKey = make([]byte, macMode.keySize)
+
+ generateKeyMaterial(iv, d.ivTag, kex)
+ generateKeyMaterial(key, d.keyTag, kex)
+ generateKeyMaterial(macKey, d.macKeyTag, kex)
+ return
+}
+
+// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as
+// described in RFC 4253, section 6.4. direction should either be serverKeys
+// (to setup server->client keys) or clientKeys (for client->server keys).
+func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
+ iv, key, macKey := generateKeys(d, algs, kex)
+
+ if algs.Cipher == gcmCipherID {
+ return newGCMCipher(iv, key, macKey)
+ }
+
+ if algs.Cipher == aes128cbcID {
+ return newAESCBCCipher(iv, key, macKey, algs)
+ }
+
+ if algs.Cipher == tripledescbcID {
+ return newTripleDESCBCCipher(iv, key, macKey, algs)
+ }
+
+ c := &streamPacketCipher{
+ mac: macModes[algs.MAC].new(macKey),
+ etm: macModes[algs.MAC].etm,
+ }
+ c.macResult = make([]byte, c.mac.Size())
+
+ var err error
+ c.cipher, err = cipherModes[algs.Cipher].createStream(key, iv)
+ if err != nil {
+ return nil, err
+ }
+
+ return c, nil
+}
+
+// generateKeyMaterial fills out with key material generated from tag, K, H
+// and sessionId, as specified in RFC 4253, section 7.2.
+func generateKeyMaterial(out, tag []byte, r *kexResult) {
+ var digestsSoFar []byte
+
+ h := r.Hash.New()
+ for len(out) > 0 {
+ h.Reset()
+ h.Write(r.K)
+ h.Write(r.H)
+
+ if len(digestsSoFar) == 0 {
+ h.Write(tag)
+ h.Write(r.SessionID)
+ } else {
+ h.Write(digestsSoFar)
+ }
+
+ digest := h.Sum(nil)
+ n := copy(out, digest)
+ out = out[n:]
+ if len(out) > 0 {
+ digestsSoFar = append(digestsSoFar, digest...)
+ }
+ }
+}
+
+const packageVersion = "SSH-2.0-Go"
+
+// Sends and receives a version line. The versionLine string should
+// be US ASCII, start with "SSH-2.0-", and should not include a
+// newline. exchangeVersions returns the other side's version line.
+func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte, err error) {
+ // Contrary to the RFC, we do not ignore lines that don't
+ // start with "SSH-2.0-" to make the library usable with
+ // nonconforming servers.
+ for _, c := range versionLine {
+ // The spec disallows non US-ASCII chars, and
+ // specifically forbids null chars.
+ if c < 32 {
+ return nil, errors.New("ssh: junk character in version line")
+ }
+ }
+ if _, err = rw.Write(append(versionLine, '\r', '\n')); err != nil {
+ return
+ }
+
+ them, err = readVersion(rw)
+ return them, err
+}
+
+// maxVersionStringBytes is the maximum number of bytes that we'll
+// accept as a version string. RFC 4253 section 4.2 limits this at 255
+// chars
+const maxVersionStringBytes = 255
+
+// Read version string as specified by RFC 4253, section 4.2.
+func readVersion(r io.Reader) ([]byte, error) {
+ versionString := make([]byte, 0, 64)
+ var ok bool
+ var buf [1]byte
+
+ for len(versionString) < maxVersionStringBytes {
+ _, err := io.ReadFull(r, buf[:])
+ if err != nil {
+ return nil, err
+ }
+ // The RFC says that the version should be terminated with \r\n
+ // but several SSH servers actually only send a \n.
+ if buf[0] == '\n' {
+ ok = true
+ break
+ }
+
+ // non ASCII chars are disallowed, but we are lenient,
+ // since Go doesn't use null-terminated strings.
+
+ // The RFC allows a comment after a space, however,
+ // all of it (version and comments) goes into the
+ // session hash.
+ versionString = append(versionString, buf[0])
+ }
+
+ if !ok {
+ return nil, errors.New("ssh: overflow reading version string")
+ }
+
+ // There might be a '\r' on the end which we should remove.
+ if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' {
+ versionString = versionString[:len(versionString)-1]
+ }
+ return versionString, nil
+}
diff --git a/cmd/gost/vendor/golang.org/x/crypto/tea/cipher.go b/vendor/golang.org/x/crypto/tea/cipher.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/crypto/tea/cipher.go
rename to vendor/golang.org/x/crypto/tea/cipher.go
diff --git a/cmd/gost/vendor/golang.org/x/crypto/twofish/twofish.go b/vendor/golang.org/x/crypto/twofish/twofish.go
similarity index 99%
rename from cmd/gost/vendor/golang.org/x/crypto/twofish/twofish.go
rename to vendor/golang.org/x/crypto/twofish/twofish.go
index 376fa0e..6db01fc 100644
--- a/cmd/gost/vendor/golang.org/x/crypto/twofish/twofish.go
+++ b/vendor/golang.org/x/crypto/twofish/twofish.go
@@ -5,7 +5,7 @@
// Package twofish implements Bruce Schneier's Twofish encryption algorithm.
package twofish // import "golang.org/x/crypto/twofish"
-// Twofish is defined in http://www.schneier.com/paper-twofish-paper.pdf [TWOFISH]
+// Twofish is defined in https://www.schneier.com/paper-twofish-paper.pdf [TWOFISH]
// This code is a port of the LibTom C implementation.
// See http://libtom.org/?page=features&newsitems=5&whatfile=crypt.
diff --git a/cmd/gost/vendor/golang.org/x/crypto/xtea/block.go b/vendor/golang.org/x/crypto/xtea/block.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/crypto/xtea/block.go
rename to vendor/golang.org/x/crypto/xtea/block.go
diff --git a/cmd/gost/vendor/golang.org/x/crypto/xtea/cipher.go b/vendor/golang.org/x/crypto/xtea/cipher.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/crypto/xtea/cipher.go
rename to vendor/golang.org/x/crypto/xtea/cipher.go
diff --git a/cmd/gost/vendor/golang.org/x/net/LICENSE b/vendor/golang.org/x/net/LICENSE
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/LICENSE
rename to vendor/golang.org/x/net/LICENSE
diff --git a/cmd/gost/vendor/golang.org/x/net/PATENTS b/vendor/golang.org/x/net/PATENTS
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/PATENTS
rename to vendor/golang.org/x/net/PATENTS
diff --git a/cmd/gost/vendor/golang.org/x/net/bpf/asm.go b/vendor/golang.org/x/net/bpf/asm.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/bpf/asm.go
rename to vendor/golang.org/x/net/bpf/asm.go
diff --git a/cmd/gost/vendor/golang.org/x/net/bpf/constants.go b/vendor/golang.org/x/net/bpf/constants.go
similarity index 97%
rename from cmd/gost/vendor/golang.org/x/net/bpf/constants.go
rename to vendor/golang.org/x/net/bpf/constants.go
index 2c8bbab..ccf6ada 100644
--- a/cmd/gost/vendor/golang.org/x/net/bpf/constants.go
+++ b/vendor/golang.org/x/net/bpf/constants.go
@@ -70,6 +70,9 @@ type Extension int
// Extension functions available in the Linux kernel.
const (
+ // extOffset is the negative maximum number of instructions used
+ // to load instructions by overloading the K argument.
+ extOffset = -0x1000
// ExtLen returns the length of the packet.
ExtLen Extension = 1
// ExtProto returns the packet's L3 protocol type.
diff --git a/cmd/gost/vendor/golang.org/x/net/bpf/doc.go b/vendor/golang.org/x/net/bpf/doc.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/bpf/doc.go
rename to vendor/golang.org/x/net/bpf/doc.go
diff --git a/cmd/gost/vendor/golang.org/x/net/bpf/instructions.go b/vendor/golang.org/x/net/bpf/instructions.go
similarity index 59%
rename from cmd/gost/vendor/golang.org/x/net/bpf/instructions.go
rename to vendor/golang.org/x/net/bpf/instructions.go
index 68ae6f5..3b4fd08 100644
--- a/cmd/gost/vendor/golang.org/x/net/bpf/instructions.go
+++ b/vendor/golang.org/x/net/bpf/instructions.go
@@ -57,6 +57,9 @@ func (ri RawInstruction) Disassemble() Instruction {
}
return LoadScratch{Dst: reg, N: int(ri.K)}
case opAddrModeAbsolute:
+ if ri.K > extOffset+0xffffffff {
+ return LoadExtension{Num: Extension(-extOffset + ri.K)}
+ }
return LoadAbsolute{Size: sz, Off: ri.K}
case opAddrModeIndirect:
return LoadIndirect{Size: sz, Off: ri.K}
@@ -104,6 +107,14 @@ func (ri RawInstruction) Disassemble() Instruction {
case opJumpAlways:
return Jump{Skip: ri.K}
case opJumpEqual:
+ if ri.Jt == 0 {
+ return JumpIf{
+ Cond: JumpNotEqual,
+ Val: ri.K,
+ SkipTrue: ri.Jf,
+ SkipFalse: 0,
+ }
+ }
return JumpIf{
Cond: JumpEqual,
Val: ri.K,
@@ -111,6 +122,14 @@ func (ri RawInstruction) Disassemble() Instruction {
SkipFalse: ri.Jf,
}
case opJumpGT:
+ if ri.Jt == 0 {
+ return JumpIf{
+ Cond: JumpLessOrEqual,
+ Val: ri.K,
+ SkipTrue: ri.Jf,
+ SkipFalse: 0,
+ }
+ }
return JumpIf{
Cond: JumpGreaterThan,
Val: ri.K,
@@ -118,6 +137,14 @@ func (ri RawInstruction) Disassemble() Instruction {
SkipFalse: ri.Jf,
}
case opJumpGE:
+ if ri.Jt == 0 {
+ return JumpIf{
+ Cond: JumpLessThan,
+ Val: ri.K,
+ SkipTrue: ri.Jf,
+ SkipFalse: 0,
+ }
+ }
return JumpIf{
Cond: JumpGreaterOrEqual,
Val: ri.K,
@@ -171,6 +198,18 @@ func (a LoadConstant) Assemble() (RawInstruction, error) {
return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val)
}
+// String returns the the instruction in assembler notation.
+func (a LoadConstant) String() string {
+ switch a.Dst {
+ case RegA:
+ return fmt.Sprintf("ld #%d", a.Val)
+ case RegX:
+ return fmt.Sprintf("ldx #%d", a.Val)
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
// LoadScratch loads scratch[N] into register Dst.
type LoadScratch struct {
Dst Register
@@ -185,6 +224,18 @@ func (a LoadScratch) Assemble() (RawInstruction, error) {
return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
}
+// String returns the the instruction in assembler notation.
+func (a LoadScratch) String() string {
+ switch a.Dst {
+ case RegA:
+ return fmt.Sprintf("ld M[%d]", a.N)
+ case RegX:
+ return fmt.Sprintf("ldx M[%d]", a.N)
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
// LoadAbsolute loads packet[Off:Off+Size] as an integer value into
// register A.
type LoadAbsolute struct {
@@ -197,6 +248,23 @@ func (a LoadAbsolute) Assemble() (RawInstruction, error) {
return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
}
+// String returns the the instruction in assembler notation.
+func (a LoadAbsolute) String() string {
+ switch a.Size {
+ case 1: // byte
+ return fmt.Sprintf("ldb [%d]", a.Off)
+ case 2: // half word
+ return fmt.Sprintf("ldh [%d]", a.Off)
+ case 4: // word
+ if a.Off > extOffset+0xffffffff {
+ return LoadExtension{Num: Extension(a.Off + 0x1000)}.String()
+ }
+ return fmt.Sprintf("ld [%d]", a.Off)
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
// LoadIndirect loads packet[X+Off:X+Off+Size] as an integer value
// into register A.
type LoadIndirect struct {
@@ -209,6 +277,20 @@ func (a LoadIndirect) Assemble() (RawInstruction, error) {
return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
}
+// String returns the the instruction in assembler notation.
+func (a LoadIndirect) String() string {
+ switch a.Size {
+ case 1: // byte
+ return fmt.Sprintf("ldb [x + %d]", a.Off)
+ case 2: // half word
+ return fmt.Sprintf("ldh [x + %d]", a.Off)
+ case 4: // word
+ return fmt.Sprintf("ld [x + %d]", a.Off)
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
// LoadMemShift multiplies the first 4 bits of the byte at packet[Off]
// by 4 and stores the result in register X.
//
@@ -224,6 +306,11 @@ func (a LoadMemShift) Assemble() (RawInstruction, error) {
return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
}
+// String returns the the instruction in assembler notation.
+func (a LoadMemShift) String() string {
+ return fmt.Sprintf("ldx 4*([%d]&0xf)", a.Off)
+}
+
// LoadExtension invokes a linux-specific extension and stores the
// result in register A.
type LoadExtension struct {
@@ -235,7 +322,47 @@ func (a LoadExtension) Assemble() (RawInstruction, error) {
if a.Num == ExtLen {
return assembleLoad(RegA, 4, opAddrModePacketLen, 0)
}
- return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(-0x1000+a.Num))
+ return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(extOffset+a.Num))
+}
+
+// String returns the the instruction in assembler notation.
+func (a LoadExtension) String() string {
+ switch a.Num {
+ case ExtLen:
+ return "ld #len"
+ case ExtProto:
+ return "ld #proto"
+ case ExtType:
+ return "ld #type"
+ case ExtPayloadOffset:
+ return "ld #poff"
+ case ExtInterfaceIndex:
+ return "ld #ifidx"
+ case ExtNetlinkAttr:
+ return "ld #nla"
+ case ExtNetlinkAttrNested:
+ return "ld #nlan"
+ case ExtMark:
+ return "ld #mark"
+ case ExtQueue:
+ return "ld #queue"
+ case ExtLinkLayerType:
+ return "ld #hatype"
+ case ExtRXHash:
+ return "ld #rxhash"
+ case ExtCPUID:
+ return "ld #cpu"
+ case ExtVLANTag:
+ return "ld #vlan_tci"
+ case ExtVLANTagPresent:
+ return "ld #vlan_avail"
+ case ExtVLANProto:
+ return "ld #vlan_tpid"
+ case ExtRand:
+ return "ld #rand"
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
}
// StoreScratch stores register Src into scratch[N].
@@ -265,6 +392,18 @@ func (a StoreScratch) Assemble() (RawInstruction, error) {
}, nil
}
+// String returns the the instruction in assembler notation.
+func (a StoreScratch) String() string {
+ switch a.Src {
+ case RegA:
+ return fmt.Sprintf("st M[%d]", a.N)
+ case RegX:
+ return fmt.Sprintf("stx M[%d]", a.N)
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
// ALUOpConstant executes A = A Val.
type ALUOpConstant struct {
Op ALUOp
@@ -279,6 +418,34 @@ func (a ALUOpConstant) Assemble() (RawInstruction, error) {
}, nil
}
+// String returns the the instruction in assembler notation.
+func (a ALUOpConstant) String() string {
+ switch a.Op {
+ case ALUOpAdd:
+ return fmt.Sprintf("add #%d", a.Val)
+ case ALUOpSub:
+ return fmt.Sprintf("sub #%d", a.Val)
+ case ALUOpMul:
+ return fmt.Sprintf("mul #%d", a.Val)
+ case ALUOpDiv:
+ return fmt.Sprintf("div #%d", a.Val)
+ case ALUOpMod:
+ return fmt.Sprintf("mod #%d", a.Val)
+ case ALUOpAnd:
+ return fmt.Sprintf("and #%d", a.Val)
+ case ALUOpOr:
+ return fmt.Sprintf("or #%d", a.Val)
+ case ALUOpXor:
+ return fmt.Sprintf("xor #%d", a.Val)
+ case ALUOpShiftLeft:
+ return fmt.Sprintf("lsh #%d", a.Val)
+ case ALUOpShiftRight:
+ return fmt.Sprintf("rsh #%d", a.Val)
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
// ALUOpX executes A = A X
type ALUOpX struct {
Op ALUOp
@@ -291,6 +458,34 @@ func (a ALUOpX) Assemble() (RawInstruction, error) {
}, nil
}
+// String returns the the instruction in assembler notation.
+func (a ALUOpX) String() string {
+ switch a.Op {
+ case ALUOpAdd:
+ return "add x"
+ case ALUOpSub:
+ return "sub x"
+ case ALUOpMul:
+ return "mul x"
+ case ALUOpDiv:
+ return "div x"
+ case ALUOpMod:
+ return "mod x"
+ case ALUOpAnd:
+ return "and x"
+ case ALUOpOr:
+ return "or x"
+ case ALUOpXor:
+ return "xor x"
+ case ALUOpShiftLeft:
+ return "lsh x"
+ case ALUOpShiftRight:
+ return "rsh x"
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
// NegateA executes A = -A.
type NegateA struct{}
@@ -301,6 +496,11 @@ func (a NegateA) Assemble() (RawInstruction, error) {
}, nil
}
+// String returns the the instruction in assembler notation.
+func (a NegateA) String() string {
+ return fmt.Sprintf("neg")
+}
+
// Jump skips the following Skip instructions in the program.
type Jump struct {
Skip uint32
@@ -314,6 +514,11 @@ func (a Jump) Assemble() (RawInstruction, error) {
}, nil
}
+// String returns the the instruction in assembler notation.
+func (a Jump) String() string {
+ return fmt.Sprintf("ja %d", a.Skip)
+}
+
// JumpIf skips the following Skip instructions in the program if A
// Val is true.
type JumpIf struct {
@@ -361,6 +566,51 @@ func (a JumpIf) Assemble() (RawInstruction, error) {
}, nil
}
+// String returns the the instruction in assembler notation.
+func (a JumpIf) String() string {
+ switch a.Cond {
+ // K == A
+ case JumpEqual:
+ return conditionalJump(a, "jeq", "jneq")
+ // K != A
+ case JumpNotEqual:
+ return fmt.Sprintf("jneq #%d,%d", a.Val, a.SkipTrue)
+ // K > A
+ case JumpGreaterThan:
+ return conditionalJump(a, "jgt", "jle")
+ // K < A
+ case JumpLessThan:
+ return fmt.Sprintf("jlt #%d,%d", a.Val, a.SkipTrue)
+ // K >= A
+ case JumpGreaterOrEqual:
+ return conditionalJump(a, "jge", "jlt")
+ // K <= A
+ case JumpLessOrEqual:
+ return fmt.Sprintf("jle #%d,%d", a.Val, a.SkipTrue)
+ // K & A != 0
+ case JumpBitsSet:
+ if a.SkipFalse > 0 {
+ return fmt.Sprintf("jset #%d,%d,%d", a.Val, a.SkipTrue, a.SkipFalse)
+ }
+ return fmt.Sprintf("jset #%d,%d", a.Val, a.SkipTrue)
+ // K & A == 0, there is no assembler instruction for JumpBitNotSet, use JumpBitSet and invert skips
+ case JumpBitsNotSet:
+ return JumpIf{Cond: JumpBitsSet, SkipTrue: a.SkipFalse, SkipFalse: a.SkipTrue, Val: a.Val}.String()
+ default:
+ return fmt.Sprintf("unknown instruction: %#v", a)
+ }
+}
+
+func conditionalJump(inst JumpIf, positiveJump, negativeJump string) string {
+ if inst.SkipTrue > 0 {
+ if inst.SkipFalse > 0 {
+ return fmt.Sprintf("%s #%d,%d,%d", positiveJump, inst.Val, inst.SkipTrue, inst.SkipFalse)
+ }
+ return fmt.Sprintf("%s #%d,%d", positiveJump, inst.Val, inst.SkipTrue)
+ }
+ return fmt.Sprintf("%s #%d,%d", negativeJump, inst.Val, inst.SkipFalse)
+}
+
// RetA exits the BPF program, returning the value of register A.
type RetA struct{}
@@ -371,6 +621,11 @@ func (a RetA) Assemble() (RawInstruction, error) {
}, nil
}
+// String returns the the instruction in assembler notation.
+func (a RetA) String() string {
+ return fmt.Sprintf("ret a")
+}
+
// RetConstant exits the BPF program, returning a constant value.
type RetConstant struct {
Val uint32
@@ -384,6 +639,11 @@ func (a RetConstant) Assemble() (RawInstruction, error) {
}, nil
}
+// String returns the the instruction in assembler notation.
+func (a RetConstant) String() string {
+ return fmt.Sprintf("ret #%d", a.Val)
+}
+
// TXA copies the value of register X to register A.
type TXA struct{}
@@ -394,6 +654,11 @@ func (a TXA) Assemble() (RawInstruction, error) {
}, nil
}
+// String returns the the instruction in assembler notation.
+func (a TXA) String() string {
+ return fmt.Sprintf("txa")
+}
+
// TAX copies the value of register A to register X.
type TAX struct{}
@@ -404,6 +669,11 @@ func (a TAX) Assemble() (RawInstruction, error) {
}, nil
}
+// String returns the the instruction in assembler notation.
+func (a TAX) String() string {
+ return fmt.Sprintf("tax")
+}
+
func assembleLoad(dst Register, loadSize int, mode uint16, k uint32) (RawInstruction, error) {
var (
cls uint16
diff --git a/cmd/gost/vendor/golang.org/x/net/bpf/vm.go b/vendor/golang.org/x/net/bpf/vm.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/bpf/vm.go
rename to vendor/golang.org/x/net/bpf/vm.go
diff --git a/cmd/gost/vendor/golang.org/x/net/bpf/vm_instructions.go b/vendor/golang.org/x/net/bpf/vm_instructions.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/bpf/vm_instructions.go
rename to vendor/golang.org/x/net/bpf/vm_instructions.go
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/Dockerfile b/vendor/golang.org/x/net/http2/Dockerfile
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/Dockerfile
rename to vendor/golang.org/x/net/http2/Dockerfile
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/Makefile b/vendor/golang.org/x/net/http2/Makefile
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/Makefile
rename to vendor/golang.org/x/net/http2/Makefile
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/README b/vendor/golang.org/x/net/http2/README
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/README
rename to vendor/golang.org/x/net/http2/README
diff --git a/vendor/golang.org/x/net/http2/ciphers.go b/vendor/golang.org/x/net/http2/ciphers.go
new file mode 100644
index 0000000..698860b
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/ciphers.go
@@ -0,0 +1,641 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+// A list of the possible cipher suite ids. Taken from
+// http://www.iana.org/assignments/tls-parameters/tls-parameters.txt
+
+const (
+ cipher_TLS_NULL_WITH_NULL_NULL uint16 = 0x0000
+ cipher_TLS_RSA_WITH_NULL_MD5 uint16 = 0x0001
+ cipher_TLS_RSA_WITH_NULL_SHA uint16 = 0x0002
+ cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0003
+ cipher_TLS_RSA_WITH_RC4_128_MD5 uint16 = 0x0004
+ cipher_TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
+ cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x0006
+ cipher_TLS_RSA_WITH_IDEA_CBC_SHA uint16 = 0x0007
+ cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0008
+ cipher_TLS_RSA_WITH_DES_CBC_SHA uint16 = 0x0009
+ cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000A
+ cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000B
+ cipher_TLS_DH_DSS_WITH_DES_CBC_SHA uint16 = 0x000C
+ cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x000D
+ cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000E
+ cipher_TLS_DH_RSA_WITH_DES_CBC_SHA uint16 = 0x000F
+ cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0010
+ cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0011
+ cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA uint16 = 0x0012
+ cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x0013
+ cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0014
+ cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA uint16 = 0x0015
+ cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0016
+ cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0017
+ cipher_TLS_DH_anon_WITH_RC4_128_MD5 uint16 = 0x0018
+ cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0019
+ cipher_TLS_DH_anon_WITH_DES_CBC_SHA uint16 = 0x001A
+ cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0x001B
+ // Reserved uint16 = 0x001C-1D
+ cipher_TLS_KRB5_WITH_DES_CBC_SHA uint16 = 0x001E
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA uint16 = 0x001F
+ cipher_TLS_KRB5_WITH_RC4_128_SHA uint16 = 0x0020
+ cipher_TLS_KRB5_WITH_IDEA_CBC_SHA uint16 = 0x0021
+ cipher_TLS_KRB5_WITH_DES_CBC_MD5 uint16 = 0x0022
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5 uint16 = 0x0023
+ cipher_TLS_KRB5_WITH_RC4_128_MD5 uint16 = 0x0024
+ cipher_TLS_KRB5_WITH_IDEA_CBC_MD5 uint16 = 0x0025
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA uint16 = 0x0026
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA uint16 = 0x0027
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA uint16 = 0x0028
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 uint16 = 0x0029
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x002A
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5 uint16 = 0x002B
+ cipher_TLS_PSK_WITH_NULL_SHA uint16 = 0x002C
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA uint16 = 0x002D
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA uint16 = 0x002E
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002F
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0030
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0031
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0032
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0033
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA uint16 = 0x0034
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0036
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0037
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0038
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0039
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA uint16 = 0x003A
+ cipher_TLS_RSA_WITH_NULL_SHA256 uint16 = 0x003B
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003C
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003D
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x003E
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003F
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x0040
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0041
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0042
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0043
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0044
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0045
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0046
+ // Reserved uint16 = 0x0047-4F
+ // Reserved uint16 = 0x0050-58
+ // Reserved uint16 = 0x0059-5C
+ // Unassigned uint16 = 0x005D-5F
+ // Reserved uint16 = 0x0060-66
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x0068
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x0069
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x006A
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006B
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256 uint16 = 0x006C
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256 uint16 = 0x006D
+ // Unassigned uint16 = 0x006E-83
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0084
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0085
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0086
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0087
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0088
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0089
+ cipher_TLS_PSK_WITH_RC4_128_SHA uint16 = 0x008A
+ cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008B
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA uint16 = 0x008C
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA uint16 = 0x008D
+ cipher_TLS_DHE_PSK_WITH_RC4_128_SHA uint16 = 0x008E
+ cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008F
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0090
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0091
+ cipher_TLS_RSA_PSK_WITH_RC4_128_SHA uint16 = 0x0092
+ cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x0093
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0094
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0095
+ cipher_TLS_RSA_WITH_SEED_CBC_SHA uint16 = 0x0096
+ cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA uint16 = 0x0097
+ cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA uint16 = 0x0098
+ cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA uint16 = 0x0099
+ cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA uint16 = 0x009A
+ cipher_TLS_DH_anon_WITH_SEED_CBC_SHA uint16 = 0x009B
+ cipher_TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009C
+ cipher_TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009D
+ cipher_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009E
+ cipher_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009F
+ cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x00A0
+ cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x00A1
+ cipher_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A2
+ cipher_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A3
+ cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A4
+ cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A5
+ cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256 uint16 = 0x00A6
+ cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384 uint16 = 0x00A7
+ cipher_TLS_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00A8
+ cipher_TLS_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00A9
+ cipher_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AA
+ cipher_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AB
+ cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AC
+ cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AD
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00AE
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00AF
+ cipher_TLS_PSK_WITH_NULL_SHA256 uint16 = 0x00B0
+ cipher_TLS_PSK_WITH_NULL_SHA384 uint16 = 0x00B1
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B2
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B3
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA256 uint16 = 0x00B4
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA384 uint16 = 0x00B5
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B6
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B7
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA256 uint16 = 0x00B8
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA384 uint16 = 0x00B9
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BA
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BB
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BC
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BD
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BE
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BF
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C0
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C1
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C2
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C3
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C4
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C5
+ // Unassigned uint16 = 0x00C6-FE
+ cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV uint16 = 0x00FF
+ // Unassigned uint16 = 0x01-55,*
+ cipher_TLS_FALLBACK_SCSV uint16 = 0x5600
+ // Unassigned uint16 = 0x5601 - 0xC000
+ cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA uint16 = 0xC001
+ cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA uint16 = 0xC002
+ cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC003
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC004
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC005
+ cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA uint16 = 0xC006
+ cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xC007
+ cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC008
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC009
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC00A
+ cipher_TLS_ECDH_RSA_WITH_NULL_SHA uint16 = 0xC00B
+ cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA uint16 = 0xC00C
+ cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC00D
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC00E
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC00F
+ cipher_TLS_ECDHE_RSA_WITH_NULL_SHA uint16 = 0xC010
+ cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xC011
+ cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC012
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC013
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC014
+ cipher_TLS_ECDH_anon_WITH_NULL_SHA uint16 = 0xC015
+ cipher_TLS_ECDH_anon_WITH_RC4_128_SHA uint16 = 0xC016
+ cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0xC017
+ cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA uint16 = 0xC018
+ cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA uint16 = 0xC019
+ cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01A
+ cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01B
+ cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01C
+ cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA uint16 = 0xC01D
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC01E
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA uint16 = 0xC01F
+ cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA uint16 = 0xC020
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC021
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA uint16 = 0xC022
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC023
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC024
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC025
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC026
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC027
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC028
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC029
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC02A
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02B
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02C
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02D
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02E
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02F
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC030
+ cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC031
+ cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC032
+ cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA uint16 = 0xC033
+ cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0xC034
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0xC035
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0xC036
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0xC037
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0xC038
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA uint16 = 0xC039
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256 uint16 = 0xC03A
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384 uint16 = 0xC03B
+ cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03C
+ cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03D
+ cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03E
+ cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03F
+ cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC040
+ cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC041
+ cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC042
+ cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC043
+ cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC044
+ cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC045
+ cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC046
+ cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC047
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC048
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC049
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04A
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04B
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04C
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04D
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04E
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04F
+ cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC050
+ cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC051
+ cipher_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC052
+ cipher_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC053
+ cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC054
+ cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC055
+ cipher_TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC056
+ cipher_TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC057
+ cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC058
+ cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC059
+ cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05A
+ cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05B
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05C
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05D
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05E
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05F
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC060
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC061
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC062
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC063
+ cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC064
+ cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC065
+ cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC066
+ cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC067
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC068
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC069
+ cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06A
+ cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06B
+ cipher_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06C
+ cipher_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06D
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06E
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06F
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC070
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC071
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC072
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC073
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC074
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC075
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC076
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC077
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC078
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC079
+ cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07A
+ cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07B
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07C
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07D
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07E
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07F
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC080
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC081
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC082
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC083
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC084
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC085
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC086
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC087
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC088
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC089
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08A
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08B
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08C
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08D
+ cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08E
+ cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08F
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC090
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC091
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC092
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC093
+ cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC094
+ cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC095
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC096
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC097
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC098
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC099
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC09A
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC09B
+ cipher_TLS_RSA_WITH_AES_128_CCM uint16 = 0xC09C
+ cipher_TLS_RSA_WITH_AES_256_CCM uint16 = 0xC09D
+ cipher_TLS_DHE_RSA_WITH_AES_128_CCM uint16 = 0xC09E
+ cipher_TLS_DHE_RSA_WITH_AES_256_CCM uint16 = 0xC09F
+ cipher_TLS_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A0
+ cipher_TLS_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A1
+ cipher_TLS_DHE_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A2
+ cipher_TLS_DHE_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A3
+ cipher_TLS_PSK_WITH_AES_128_CCM uint16 = 0xC0A4
+ cipher_TLS_PSK_WITH_AES_256_CCM uint16 = 0xC0A5
+ cipher_TLS_DHE_PSK_WITH_AES_128_CCM uint16 = 0xC0A6
+ cipher_TLS_DHE_PSK_WITH_AES_256_CCM uint16 = 0xC0A7
+ cipher_TLS_PSK_WITH_AES_128_CCM_8 uint16 = 0xC0A8
+ cipher_TLS_PSK_WITH_AES_256_CCM_8 uint16 = 0xC0A9
+ cipher_TLS_PSK_DHE_WITH_AES_128_CCM_8 uint16 = 0xC0AA
+ cipher_TLS_PSK_DHE_WITH_AES_256_CCM_8 uint16 = 0xC0AB
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM uint16 = 0xC0AC
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM uint16 = 0xC0AD
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 uint16 = 0xC0AE
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 uint16 = 0xC0AF
+ // Unassigned uint16 = 0xC0B0-FF
+ // Unassigned uint16 = 0xC1-CB,*
+ // Unassigned uint16 = 0xCC00-A7
+ cipher_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA8
+ cipher_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA9
+ cipher_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAA
+ cipher_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAB
+ cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAC
+ cipher_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAD
+ cipher_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAE
+)
+
+// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
+// References:
+// https://tools.ietf.org/html/rfc7540#appendix-A
+// Reject cipher suites from Appendix A.
+// "This list includes those cipher suites that do not
+// offer an ephemeral key exchange and those that are
+// based on the TLS null, stream or block cipher type"
+func isBadCipher(cipher uint16) bool {
+ switch cipher {
+ case cipher_TLS_NULL_WITH_NULL_NULL,
+ cipher_TLS_RSA_WITH_NULL_MD5,
+ cipher_TLS_RSA_WITH_NULL_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_RSA_WITH_RC4_128_MD5,
+ cipher_TLS_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
+ cipher_TLS_RSA_WITH_IDEA_CBC_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_DH_anon_WITH_RC4_128_MD5,
+ cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_KRB5_WITH_DES_CBC_SHA,
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_KRB5_WITH_RC4_128_SHA,
+ cipher_TLS_KRB5_WITH_IDEA_CBC_SHA,
+ cipher_TLS_KRB5_WITH_DES_CBC_MD5,
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5,
+ cipher_TLS_KRB5_WITH_RC4_128_MD5,
+ cipher_TLS_KRB5_WITH_IDEA_CBC_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_PSK_WITH_NULL_SHA,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA,
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA,
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_WITH_NULL_SHA256,
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_SEED_CBC_SHA,
+ cipher_TLS_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_PSK_WITH_NULL_SHA256,
+ cipher_TLS_PSK_WITH_NULL_SHA384,
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA256,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA256,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
+ cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_NULL_SHA,
+ cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_NULL_SHA,
+ cipher_TLS_ECDH_anon_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_AES_128_CCM,
+ cipher_TLS_RSA_WITH_AES_256_CCM,
+ cipher_TLS_RSA_WITH_AES_128_CCM_8,
+ cipher_TLS_RSA_WITH_AES_256_CCM_8,
+ cipher_TLS_PSK_WITH_AES_128_CCM,
+ cipher_TLS_PSK_WITH_AES_256_CCM,
+ cipher_TLS_PSK_WITH_AES_128_CCM_8,
+ cipher_TLS_PSK_WITH_AES_256_CCM_8:
+ return true
+ default:
+ return false
+ }
+}
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/client_conn_pool.go b/vendor/golang.org/x/net/http2/client_conn_pool.go
similarity index 98%
rename from cmd/gost/vendor/golang.org/x/net/http2/client_conn_pool.go
rename to vendor/golang.org/x/net/http2/client_conn_pool.go
index b139412..bdf5652 100644
--- a/cmd/gost/vendor/golang.org/x/net/http2/client_conn_pool.go
+++ b/vendor/golang.org/x/net/http2/client_conn_pool.go
@@ -247,7 +247,7 @@ func filterOutClientConn(in []*ClientConn, exclude *ClientConn) []*ClientConn {
}
// noDialClientConnPool is an implementation of http2.ClientConnPool
-// which never dials. We let the HTTP/1.1 client dial and use its TLS
+// which never dials. We let the HTTP/1.1 client dial and use its TLS
// connection instead.
type noDialClientConnPool struct{ *clientConnPool }
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/configure_transport.go b/vendor/golang.org/x/net/http2/configure_transport.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/configure_transport.go
rename to vendor/golang.org/x/net/http2/configure_transport.go
diff --git a/vendor/golang.org/x/net/http2/databuffer.go b/vendor/golang.org/x/net/http2/databuffer.go
new file mode 100644
index 0000000..a3067f8
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/databuffer.go
@@ -0,0 +1,146 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+)
+
+// Buffer chunks are allocated from a pool to reduce pressure on GC.
+// The maximum wasted space per dataBuffer is 2x the largest size class,
+// which happens when the dataBuffer has multiple chunks and there is
+// one unread byte in both the first and last chunks. We use a few size
+// classes to minimize overheads for servers that typically receive very
+// small request bodies.
+//
+// TODO: Benchmark to determine if the pools are necessary. The GC may have
+// improved enough that we can instead allocate chunks like this:
+// make([]byte, max(16<<10, expectedBytesRemaining))
+var (
+ dataChunkSizeClasses = []int{
+ 1 << 10,
+ 2 << 10,
+ 4 << 10,
+ 8 << 10,
+ 16 << 10,
+ }
+ dataChunkPools = [...]sync.Pool{
+ {New: func() interface{} { return make([]byte, 1<<10) }},
+ {New: func() interface{} { return make([]byte, 2<<10) }},
+ {New: func() interface{} { return make([]byte, 4<<10) }},
+ {New: func() interface{} { return make([]byte, 8<<10) }},
+ {New: func() interface{} { return make([]byte, 16<<10) }},
+ }
+)
+
+func getDataBufferChunk(size int64) []byte {
+ i := 0
+ for ; i < len(dataChunkSizeClasses)-1; i++ {
+ if size <= int64(dataChunkSizeClasses[i]) {
+ break
+ }
+ }
+ return dataChunkPools[i].Get().([]byte)
+}
+
+func putDataBufferChunk(p []byte) {
+ for i, n := range dataChunkSizeClasses {
+ if len(p) == n {
+ dataChunkPools[i].Put(p)
+ return
+ }
+ }
+ panic(fmt.Sprintf("unexpected buffer len=%v", len(p)))
+}
+
+// dataBuffer is an io.ReadWriter backed by a list of data chunks.
+// Each dataBuffer is used to read DATA frames on a single stream.
+// The buffer is divided into chunks so the server can limit the
+// total memory used by a single connection without limiting the
+// request body size on any single stream.
+type dataBuffer struct {
+ chunks [][]byte
+ r int // next byte to read is chunks[0][r]
+ w int // next byte to write is chunks[len(chunks)-1][w]
+ size int // total buffered bytes
+ expected int64 // we expect at least this many bytes in future Write calls (ignored if <= 0)
+}
+
+var errReadEmpty = errors.New("read from empty dataBuffer")
+
+// Read copies bytes from the buffer into p.
+// It is an error to read when no data is available.
+func (b *dataBuffer) Read(p []byte) (int, error) {
+ if b.size == 0 {
+ return 0, errReadEmpty
+ }
+ var ntotal int
+ for len(p) > 0 && b.size > 0 {
+ readFrom := b.bytesFromFirstChunk()
+ n := copy(p, readFrom)
+ p = p[n:]
+ ntotal += n
+ b.r += n
+ b.size -= n
+ // If the first chunk has been consumed, advance to the next chunk.
+ if b.r == len(b.chunks[0]) {
+ putDataBufferChunk(b.chunks[0])
+ end := len(b.chunks) - 1
+ copy(b.chunks[:end], b.chunks[1:])
+ b.chunks[end] = nil
+ b.chunks = b.chunks[:end]
+ b.r = 0
+ }
+ }
+ return ntotal, nil
+}
+
+func (b *dataBuffer) bytesFromFirstChunk() []byte {
+ if len(b.chunks) == 1 {
+ return b.chunks[0][b.r:b.w]
+ }
+ return b.chunks[0][b.r:]
+}
+
+// Len returns the number of bytes of the unread portion of the buffer.
+func (b *dataBuffer) Len() int {
+ return b.size
+}
+
+// Write appends p to the buffer.
+func (b *dataBuffer) Write(p []byte) (int, error) {
+ ntotal := len(p)
+ for len(p) > 0 {
+ // If the last chunk is empty, allocate a new chunk. Try to allocate
+ // enough to fully copy p plus any additional bytes we expect to
+ // receive. However, this may allocate less than len(p).
+ want := int64(len(p))
+ if b.expected > want {
+ want = b.expected
+ }
+ chunk := b.lastChunkOrAlloc(want)
+ n := copy(chunk[b.w:], p)
+ p = p[n:]
+ b.w += n
+ b.size += n
+ b.expected -= int64(n)
+ }
+ return ntotal, nil
+}
+
+func (b *dataBuffer) lastChunkOrAlloc(want int64) []byte {
+ if len(b.chunks) != 0 {
+ last := b.chunks[len(b.chunks)-1]
+ if b.w < len(last) {
+ return last
+ }
+ }
+ chunk := getDataBufferChunk(want)
+ b.chunks = append(b.chunks, chunk)
+ b.w = 0
+ return chunk
+}
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/errors.go b/vendor/golang.org/x/net/http2/errors.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/errors.go
rename to vendor/golang.org/x/net/http2/errors.go
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/flow.go b/vendor/golang.org/x/net/http2/flow.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/flow.go
rename to vendor/golang.org/x/net/http2/flow.go
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/frame.go b/vendor/golang.org/x/net/http2/frame.go
similarity index 94%
rename from cmd/gost/vendor/golang.org/x/net/http2/frame.go
rename to vendor/golang.org/x/net/http2/frame.go
index 358833f..3b14890 100644
--- a/cmd/gost/vendor/golang.org/x/net/http2/frame.go
+++ b/vendor/golang.org/x/net/http2/frame.go
@@ -122,7 +122,7 @@ var flagName = map[FrameType]map[Flags]string{
// a frameParser parses a frame given its FrameHeader and payload
// bytes. The length of payload will always equal fh.Length (which
// might be 0).
-type frameParser func(fh FrameHeader, payload []byte) (Frame, error)
+type frameParser func(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error)
var frameParsers = map[FrameType]frameParser{
FrameData: parseDataFrame,
@@ -312,7 +312,7 @@ type Framer struct {
MaxHeaderListSize uint32
// TODO: track which type of frame & with which flags was sent
- // last. Then return an error (unless AllowIllegalWrites) if
+ // last. Then return an error (unless AllowIllegalWrites) if
// we're in the middle of a header block and a
// non-Continuation or Continuation on a different stream is
// attempted to be written.
@@ -323,6 +323,8 @@ type Framer struct {
debugFramerBuf *bytes.Buffer
debugReadLoggerf func(string, ...interface{})
debugWriteLoggerf func(string, ...interface{})
+
+ frameCache *frameCache // nil if frames aren't reused (default)
}
func (fr *Framer) maxHeaderListSize() uint32 {
@@ -398,6 +400,27 @@ const (
maxFrameSize = 1<<24 - 1
)
+// SetReuseFrames allows the Framer to reuse Frames.
+// If called on a Framer, Frames returned by calls to ReadFrame are only
+// valid until the next call to ReadFrame.
+func (fr *Framer) SetReuseFrames() {
+ if fr.frameCache != nil {
+ return
+ }
+ fr.frameCache = &frameCache{}
+}
+
+type frameCache struct {
+ dataFrame DataFrame
+}
+
+func (fc *frameCache) getDataFrame() *DataFrame {
+ if fc == nil {
+ return &DataFrame{}
+ }
+ return &fc.dataFrame
+}
+
// NewFramer returns a Framer that writes frames to w and reads them from r.
func NewFramer(w io.Writer, r io.Reader) *Framer {
fr := &Framer{
@@ -477,7 +500,7 @@ func (fr *Framer) ReadFrame() (Frame, error) {
if _, err := io.ReadFull(fr.r, payload); err != nil {
return nil, err
}
- f, err := typeFrameParser(fh.Type)(fh, payload)
+ f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, payload)
if err != nil {
if ce, ok := err.(connError); ok {
return nil, fr.connError(ce.Code, ce.Reason)
@@ -565,7 +588,7 @@ func (f *DataFrame) Data() []byte {
return f.data
}
-func parseDataFrame(fh FrameHeader, payload []byte) (Frame, error) {
+func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
if fh.StreamID == 0 {
// DATA frames MUST be associated with a stream. If a
// DATA frame is received whose stream identifier
@@ -574,9 +597,9 @@ func parseDataFrame(fh FrameHeader, payload []byte) (Frame, error) {
// PROTOCOL_ERROR.
return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
}
- f := &DataFrame{
- FrameHeader: fh,
- }
+ f := fc.getDataFrame()
+ f.FrameHeader = fh
+
var padSize byte
if fh.Flags.Has(FlagDataPadded) {
var err error
@@ -600,6 +623,7 @@ var (
errStreamID = errors.New("invalid stream ID")
errDepStreamID = errors.New("invalid dependent stream ID")
errPadLength = errors.New("pad length too large")
+ errPadBytes = errors.New("padding bytes must all be zeros unless AllowIllegalWrites is enabled")
)
func validStreamIDOrZero(streamID uint32) bool {
@@ -623,6 +647,7 @@ func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
//
// If pad is nil, the padding bit is not sent.
// The length of pad must not exceed 255 bytes.
+// The bytes of pad must all be zero, unless f.AllowIllegalWrites is set.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility not to violate the maximum frame size
@@ -631,8 +656,18 @@ func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []by
if !validStreamID(streamID) && !f.AllowIllegalWrites {
return errStreamID
}
- if len(pad) > 255 {
- return errPadLength
+ if len(pad) > 0 {
+ if len(pad) > 255 {
+ return errPadLength
+ }
+ if !f.AllowIllegalWrites {
+ for _, b := range pad {
+ if b != 0 {
+ // "Padding octets MUST be set to zero when sending."
+ return errPadBytes
+ }
+ }
+ }
}
var flags Flags
if endStream {
@@ -660,10 +695,10 @@ type SettingsFrame struct {
p []byte
}
-func parseSettingsFrame(fh FrameHeader, p []byte) (Frame, error) {
+func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
// When this (ACK 0x1) bit is set, the payload of the
- // SETTINGS frame MUST be empty. Receipt of a
+ // SETTINGS frame MUST be empty. Receipt of a
// SETTINGS frame with the ACK flag set and a length
// field value other than 0 MUST be treated as a
// connection error (Section 5.4.1) of type
@@ -672,7 +707,7 @@ func parseSettingsFrame(fh FrameHeader, p []byte) (Frame, error) {
}
if fh.StreamID != 0 {
// SETTINGS frames always apply to a connection,
- // never a single stream. The stream identifier for a
+ // never a single stream. The stream identifier for a
// SETTINGS frame MUST be zero (0x0). If an endpoint
// receives a SETTINGS frame whose stream identifier
// field is anything other than 0x0, the endpoint MUST
@@ -762,7 +797,7 @@ type PingFrame struct {
func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) }
-func parsePingFrame(fh FrameHeader, payload []byte) (Frame, error) {
+func parsePingFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
if len(payload) != 8 {
return nil, ConnectionError(ErrCodeFrameSize)
}
@@ -802,7 +837,7 @@ func (f *GoAwayFrame) DebugData() []byte {
return f.debugData
}
-func parseGoAwayFrame(fh FrameHeader, p []byte) (Frame, error) {
+func parseGoAwayFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
if fh.StreamID != 0 {
return nil, ConnectionError(ErrCodeProtocol)
}
@@ -842,7 +877,7 @@ func (f *UnknownFrame) Payload() []byte {
return f.p
}
-func parseUnknownFrame(fh FrameHeader, p []byte) (Frame, error) {
+func parseUnknownFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
return &UnknownFrame{fh, p}, nil
}
@@ -853,7 +888,7 @@ type WindowUpdateFrame struct {
Increment uint32 // never read with high bit set
}
-func parseWindowUpdateFrame(fh FrameHeader, p []byte) (Frame, error) {
+func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
if len(p) != 4 {
return nil, ConnectionError(ErrCodeFrameSize)
}
@@ -918,12 +953,12 @@ func (f *HeadersFrame) HasPriority() bool {
return f.FrameHeader.Flags.Has(FlagHeadersPriority)
}
-func parseHeadersFrame(fh FrameHeader, p []byte) (_ Frame, err error) {
+func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
hf := &HeadersFrame{
FrameHeader: fh,
}
if fh.StreamID == 0 {
- // HEADERS frames MUST be associated with a stream. If a HEADERS frame
+ // HEADERS frames MUST be associated with a stream. If a HEADERS frame
// is received whose stream identifier field is 0x0, the recipient MUST
// respond with a connection error (Section 5.4.1) of type
// PROTOCOL_ERROR.
@@ -1045,7 +1080,7 @@ type PriorityParam struct {
Exclusive bool
// Weight is the stream's zero-indexed weight. It should be
- // set together with StreamDep, or neither should be set. Per
+ // set together with StreamDep, or neither should be set. Per
// the spec, "Add one to the value to obtain a weight between
// 1 and 256."
Weight uint8
@@ -1055,7 +1090,7 @@ func (p PriorityParam) IsZero() bool {
return p == PriorityParam{}
}
-func parsePriorityFrame(fh FrameHeader, payload []byte) (Frame, error) {
+func parsePriorityFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
if fh.StreamID == 0 {
return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
}
@@ -1102,7 +1137,7 @@ type RSTStreamFrame struct {
ErrCode ErrCode
}
-func parseRSTStreamFrame(fh FrameHeader, p []byte) (Frame, error) {
+func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
if len(p) != 4 {
return nil, ConnectionError(ErrCodeFrameSize)
}
@@ -1132,7 +1167,7 @@ type ContinuationFrame struct {
headerFragBuf []byte
}
-func parseContinuationFrame(fh FrameHeader, p []byte) (Frame, error) {
+func parseContinuationFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
if fh.StreamID == 0 {
return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
}
@@ -1182,7 +1217,7 @@ func (f *PushPromiseFrame) HeadersEnded() bool {
return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders)
}
-func parsePushPromise(fh FrameHeader, p []byte) (_ Frame, err error) {
+func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
pp := &PushPromiseFrame{
FrameHeader: fh,
}
diff --git a/vendor/golang.org/x/net/http2/go16.go b/vendor/golang.org/x/net/http2/go16.go
new file mode 100644
index 0000000..00b2e9e
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/go16.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.6
+
+package http2
+
+import (
+ "net/http"
+ "time"
+)
+
+func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
+ return t1.ExpectContinueTimeout
+}
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/go17.go b/vendor/golang.org/x/net/http2/go17.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/go17.go
rename to vendor/golang.org/x/net/http2/go17.go
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/go17_not18.go b/vendor/golang.org/x/net/http2/go17_not18.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/go17_not18.go
rename to vendor/golang.org/x/net/http2/go17_not18.go
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/go18.go b/vendor/golang.org/x/net/http2/go18.go
similarity index 87%
rename from cmd/gost/vendor/golang.org/x/net/http2/go18.go
rename to vendor/golang.org/x/net/http2/go18.go
index 633202c..73cc238 100644
--- a/cmd/gost/vendor/golang.org/x/net/http2/go18.go
+++ b/vendor/golang.org/x/net/http2/go18.go
@@ -12,7 +12,11 @@ import (
"net/http"
)
-func cloneTLSConfig(c *tls.Config) *tls.Config { return c.Clone() }
+func cloneTLSConfig(c *tls.Config) *tls.Config {
+ c2 := c.Clone()
+ c2.GetClientCertificate = c.GetClientCertificate // golang.org/issue/19264
+ return c2
+}
var _ http.Pusher = (*responseWriter)(nil)
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/gotrack.go b/vendor/golang.org/x/net/http2/gotrack.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/gotrack.go
rename to vendor/golang.org/x/net/http2/gotrack.go
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/headermap.go b/vendor/golang.org/x/net/http2/headermap.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/headermap.go
rename to vendor/golang.org/x/net/http2/headermap.go
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/hpack/encode.go b/vendor/golang.org/x/net/http2/hpack/encode.go
similarity index 93%
rename from cmd/gost/vendor/golang.org/x/net/http2/hpack/encode.go
rename to vendor/golang.org/x/net/http2/hpack/encode.go
index f9bb033..54726c2 100644
--- a/cmd/gost/vendor/golang.org/x/net/http2/hpack/encode.go
+++ b/vendor/golang.org/x/net/http2/hpack/encode.go
@@ -39,13 +39,14 @@ func NewEncoder(w io.Writer) *Encoder {
tableSizeUpdate: false,
w: w,
}
+ e.dynTab.table.init()
e.dynTab.setMaxSize(initialHeaderTableSize)
return e
}
// WriteField encodes f into a single Write to e's underlying Writer.
// This function may also produce bytes for "Header Table Size Update"
-// if necessary. If produced, it is done before encoding f.
+// if necessary. If produced, it is done before encoding f.
func (e *Encoder) WriteField(f HeaderField) error {
e.buf = e.buf[:0]
@@ -88,29 +89,17 @@ func (e *Encoder) WriteField(f HeaderField) error {
// only name matches, i points to that index and nameValueMatch
// becomes false.
func (e *Encoder) searchTable(f HeaderField) (i uint64, nameValueMatch bool) {
- for idx, hf := range staticTable {
- if !constantTimeStringCompare(hf.Name, f.Name) {
- continue
- }
- if i == 0 {
- i = uint64(idx + 1)
- }
- if f.Sensitive {
- continue
- }
- if !constantTimeStringCompare(hf.Value, f.Value) {
- continue
- }
- i = uint64(idx + 1)
- nameValueMatch = true
- return
+ i, nameValueMatch = staticTable.search(f)
+ if nameValueMatch {
+ return i, true
}
- j, nameValueMatch := e.dynTab.search(f)
+ j, nameValueMatch := e.dynTab.table.search(f)
if nameValueMatch || (i == 0 && j != 0) {
- i = j + uint64(len(staticTable))
+ return j + uint64(staticTable.len()), nameValueMatch
}
- return
+
+ return i, false
}
// SetMaxDynamicTableSize changes the dynamic header table size to v.
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/hpack/hpack.go b/vendor/golang.org/x/net/http2/hpack/hpack.go
similarity index 85%
rename from cmd/gost/vendor/golang.org/x/net/http2/hpack/hpack.go
rename to vendor/golang.org/x/net/http2/hpack/hpack.go
index 135b9f6..176644a 100644
--- a/cmd/gost/vendor/golang.org/x/net/http2/hpack/hpack.go
+++ b/vendor/golang.org/x/net/http2/hpack/hpack.go
@@ -61,7 +61,7 @@ func (hf HeaderField) String() string {
func (hf HeaderField) Size() uint32 {
// http://http2.github.io/http2-spec/compression.html#rfc.section.4.1
// "The size of the dynamic table is the sum of the size of
- // its entries. The size of an entry is the sum of its name's
+ // its entries. The size of an entry is the sum of its name's
// length in octets (as defined in Section 5.2), its value's
// length in octets (see Section 5.2), plus 32. The size of
// an entry is calculated using the length of the name and
@@ -102,6 +102,7 @@ func NewDecoder(maxDynamicTableSize uint32, emitFunc func(f HeaderField)) *Decod
emit: emitFunc,
emitEnabled: true,
}
+ d.dynTab.table.init()
d.dynTab.allowedMaxSize = maxDynamicTableSize
d.dynTab.setMaxSize(maxDynamicTableSize)
return d
@@ -154,12 +155,9 @@ func (d *Decoder) SetAllowedMaxDynamicTableSize(v uint32) {
}
type dynamicTable struct {
- // ents is the FIFO described at
// http://http2.github.io/http2-spec/compression.html#rfc.section.2.3.2
- // The newest (low index) is append at the end, and items are
- // evicted from the front.
- ents []HeaderField
- size uint32
+ table headerFieldTable
+ size uint32 // in bytes
maxSize uint32 // current maxSize
allowedMaxSize uint32 // maxSize may go up to this, inclusive
}
@@ -169,95 +167,45 @@ func (dt *dynamicTable) setMaxSize(v uint32) {
dt.evict()
}
-// TODO: change dynamicTable to be a struct with a slice and a size int field,
-// per http://http2.github.io/http2-spec/compression.html#rfc.section.4.1:
-//
-//
-// Then make add increment the size. maybe the max size should move from Decoder to
-// dynamicTable and add should return an ok bool if there was enough space.
-//
-// Later we'll need a remove operation on dynamicTable.
-
func (dt *dynamicTable) add(f HeaderField) {
- dt.ents = append(dt.ents, f)
+ dt.table.addEntry(f)
dt.size += f.Size()
dt.evict()
}
-// If we're too big, evict old stuff (front of the slice)
+// If we're too big, evict old stuff.
func (dt *dynamicTable) evict() {
- base := dt.ents // keep base pointer of slice
- for dt.size > dt.maxSize {
- dt.size -= dt.ents[0].Size()
- dt.ents = dt.ents[1:]
+ var n int
+ for dt.size > dt.maxSize && n < dt.table.len() {
+ dt.size -= dt.table.ents[n].Size()
+ n++
}
-
- // Shift slice contents down if we evicted things.
- if len(dt.ents) != len(base) {
- copy(base, dt.ents)
- dt.ents = base[:len(dt.ents)]
- }
-}
-
-// constantTimeStringCompare compares string a and b in a constant
-// time manner.
-func constantTimeStringCompare(a, b string) bool {
- if len(a) != len(b) {
- return false
- }
-
- c := byte(0)
-
- for i := 0; i < len(a); i++ {
- c |= a[i] ^ b[i]
- }
-
- return c == 0
-}
-
-// Search searches f in the table. The return value i is 0 if there is
-// no name match. If there is name match or name/value match, i is the
-// index of that entry (1-based). If both name and value match,
-// nameValueMatch becomes true.
-func (dt *dynamicTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
- l := len(dt.ents)
- for j := l - 1; j >= 0; j-- {
- ent := dt.ents[j]
- if !constantTimeStringCompare(ent.Name, f.Name) {
- continue
- }
- if i == 0 {
- i = uint64(l - j)
- }
- if f.Sensitive {
- continue
- }
- if !constantTimeStringCompare(ent.Value, f.Value) {
- continue
- }
- i = uint64(l - j)
- nameValueMatch = true
- return
- }
- return
+ dt.table.evictOldest(n)
}
func (d *Decoder) maxTableIndex() int {
- return len(d.dynTab.ents) + len(staticTable)
+ // This should never overflow. RFC 7540 Section 6.5.2 limits the size of
+ // the dynamic table to 2^32 bytes, where each entry will occupy more than
+ // one byte. Further, the staticTable has a fixed, small length.
+ return d.dynTab.table.len() + staticTable.len()
}
func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {
- if i < 1 {
+ // See Section 2.3.3.
+ if i == 0 {
return
}
+ if i <= uint64(staticTable.len()) {
+ return staticTable.ents[i-1], true
+ }
if i > uint64(d.maxTableIndex()) {
return
}
- if i <= uint64(len(staticTable)) {
- return staticTable[i-1], true
- }
- dents := d.dynTab.ents
- return dents[len(dents)-(int(i)-len(staticTable))], true
+ // In the dynamic table, newer entries have lower indices.
+ // However, dt.ents[0] is the oldest entry. Hence, dt.ents is
+ // the reversed dynamic table.
+ dt := d.dynTab.table
+ return dt.ents[dt.len()-(int(i)-staticTable.len())], true
}
// Decode decodes an entire block.
@@ -307,7 +255,7 @@ func (d *Decoder) Write(p []byte) (n int, err error) {
err = d.parseHeaderFieldRepr()
if err == errNeedMore {
// Extra paranoia, making sure saveBuf won't
- // get too large. All the varint and string
+ // get too large. All the varint and string
// reading code earlier should already catch
// overlong things and return ErrStringLength,
// but keep this as a last resort.
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/hpack/huffman.go b/vendor/golang.org/x/net/http2/hpack/huffman.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/hpack/huffman.go
rename to vendor/golang.org/x/net/http2/hpack/huffman.go
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/hpack/tables.go b/vendor/golang.org/x/net/http2/hpack/tables.go
similarity index 56%
rename from cmd/gost/vendor/golang.org/x/net/http2/hpack/tables.go
rename to vendor/golang.org/x/net/http2/hpack/tables.go
index b9283a0..5d7f635 100644
--- a/cmd/gost/vendor/golang.org/x/net/http2/hpack/tables.go
+++ b/vendor/golang.org/x/net/http2/hpack/tables.go
@@ -4,13 +4,135 @@
package hpack
+import (
+ "fmt"
+)
+
+// headerFieldTable implements a list of HeaderFields.
+// This is used to implement the static and dynamic tables.
+type headerFieldTable struct {
+ // For static tables, entries are never evicted.
+ //
+ // For dynamic tables, entries are evicted from ents[0] and added to the end.
+ // Each entry has a unique id that starts at one and increments for each
+ // entry that is added. This unique id is stable across evictions, meaning
+ // it can be used as a pointer to a specific entry. As in hpack, unique ids
+ // are 1-based. The unique id for ents[k] is k + evictCount + 1.
+ //
+ // Zero is not a valid unique id.
+ //
+ // evictCount should not overflow in any remotely practical situation. In
+ // practice, we will have one dynamic table per HTTP/2 connection. If we
+ // assume a very powerful server that handles 1M QPS per connection and each
+ // request adds (then evicts) 100 entries from the table, it would still take
+ // 2M years for evictCount to overflow.
+ ents []HeaderField
+ evictCount uint64
+
+ // byName maps a HeaderField name to the unique id of the newest entry with
+ // the same name. See above for a definition of "unique id".
+ byName map[string]uint64
+
+ // byNameValue maps a HeaderField name/value pair to the unique id of the newest
+ // entry with the same name and value. See above for a definition of "unique id".
+ byNameValue map[pairNameValue]uint64
+}
+
+type pairNameValue struct {
+ name, value string
+}
+
+func (t *headerFieldTable) init() {
+ t.byName = make(map[string]uint64)
+ t.byNameValue = make(map[pairNameValue]uint64)
+}
+
+// len reports the number of entries in the table.
+func (t *headerFieldTable) len() int {
+ return len(t.ents)
+}
+
+// addEntry adds a new entry.
+func (t *headerFieldTable) addEntry(f HeaderField) {
+ id := uint64(t.len()) + t.evictCount + 1
+ t.byName[f.Name] = id
+ t.byNameValue[pairNameValue{f.Name, f.Value}] = id
+ t.ents = append(t.ents, f)
+}
+
+// evictOldest evicts the n oldest entries in the table.
+func (t *headerFieldTable) evictOldest(n int) {
+ if n > t.len() {
+ panic(fmt.Sprintf("evictOldest(%v) on table with %v entries", n, t.len()))
+ }
+ for k := 0; k < n; k++ {
+ f := t.ents[k]
+ id := t.evictCount + uint64(k) + 1
+ if t.byName[f.Name] == id {
+ delete(t.byName, f.Name)
+ }
+ if p := (pairNameValue{f.Name, f.Value}); t.byNameValue[p] == id {
+ delete(t.byNameValue, p)
+ }
+ }
+ copy(t.ents, t.ents[n:])
+ for k := t.len() - n; k < t.len(); k++ {
+ t.ents[k] = HeaderField{} // so strings can be garbage collected
+ }
+ t.ents = t.ents[:t.len()-n]
+ if t.evictCount+uint64(n) < t.evictCount {
+ panic("evictCount overflow")
+ }
+ t.evictCount += uint64(n)
+}
+
+// search finds f in the table. If there is no match, i is 0.
+// If both name and value match, i is the matched index and nameValueMatch
+// becomes true. If only name matches, i points to that index and
+// nameValueMatch becomes false.
+//
+// The returned index is a 1-based HPACK index. For dynamic tables, HPACK says
+// that index 1 should be the newest entry, but t.ents[0] is the oldest entry,
+// meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic
+// table, the return value i actually refers to the entry t.ents[t.len()-i].
+//
+// All tables are assumed to be a dynamic tables except for the global
+// staticTable pointer.
+//
+// See Section 2.3.3.
+func (t *headerFieldTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
+ if !f.Sensitive {
+ if id := t.byNameValue[pairNameValue{f.Name, f.Value}]; id != 0 {
+ return t.idToIndex(id), true
+ }
+ }
+ if id := t.byName[f.Name]; id != 0 {
+ return t.idToIndex(id), false
+ }
+ return 0, false
+}
+
+// idToIndex converts a unique id to an HPACK index.
+// See Section 2.3.3.
+func (t *headerFieldTable) idToIndex(id uint64) uint64 {
+ if id <= t.evictCount {
+ panic(fmt.Sprintf("id (%v) <= evictCount (%v)", id, t.evictCount))
+ }
+ k := id - t.evictCount - 1 // convert id to an index t.ents[k]
+ if t != staticTable {
+ return uint64(t.len()) - k // dynamic table
+ }
+ return k + 1
+}
+
func pair(name, value string) HeaderField {
return HeaderField{Name: name, Value: value}
}
// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
-var staticTable = [...]HeaderField{
- pair(":authority", ""), // index 1 (1-based)
+var staticTable = newStaticTable()
+var staticTableEntries = [...]HeaderField{
+ pair(":authority", ""),
pair(":method", "GET"),
pair(":method", "POST"),
pair(":path", "/"),
@@ -73,6 +195,15 @@ var staticTable = [...]HeaderField{
pair("www-authenticate", ""),
}
+func newStaticTable() *headerFieldTable {
+ t := &headerFieldTable{}
+ t.init()
+ for _, e := range staticTableEntries[:] {
+ t.addEntry(e)
+ }
+ return t
+}
+
var huffmanCodes = [256]uint32{
0x1ff8,
0x7fffd8,
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/http2.go b/vendor/golang.org/x/net/http2/http2.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/http2.go
rename to vendor/golang.org/x/net/http2/http2.go
diff --git a/vendor/golang.org/x/net/http2/not_go16.go b/vendor/golang.org/x/net/http2/not_go16.go
new file mode 100644
index 0000000..508cebc
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/not_go16.go
@@ -0,0 +1,21 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.6
+
+package http2
+
+import (
+ "net/http"
+ "time"
+)
+
+func configureTransport(t1 *http.Transport) (*Transport, error) {
+ return nil, errTransportVersion
+}
+
+func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
+ return 0
+
+}
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/not_go17.go b/vendor/golang.org/x/net/http2/not_go17.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/not_go17.go
rename to vendor/golang.org/x/net/http2/not_go17.go
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/not_go18.go b/vendor/golang.org/x/net/http2/not_go18.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/not_go18.go
rename to vendor/golang.org/x/net/http2/not_go18.go
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/pipe.go b/vendor/golang.org/x/net/http2/pipe.go
similarity index 98%
rename from cmd/gost/vendor/golang.org/x/net/http2/pipe.go
rename to vendor/golang.org/x/net/http2/pipe.go
index 53b7a1d..914aaf8 100644
--- a/cmd/gost/vendor/golang.org/x/net/http2/pipe.go
+++ b/vendor/golang.org/x/net/http2/pipe.go
@@ -10,7 +10,7 @@ import (
"sync"
)
-// pipe is a goroutine-safe io.Reader/io.Writer pair. It's like
+// pipe is a goroutine-safe io.Reader/io.Writer pair. It's like
// io.Pipe except there are no PipeReader/PipeWriter halves, and the
// underlying buffer is an interface. (io.Pipe is always unbuffered)
type pipe struct {
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go
similarity index 92%
rename from cmd/gost/vendor/golang.org/x/net/http2/server.go
rename to vendor/golang.org/x/net/http2/server.go
index 3c6b90c..2aba2be 100644
--- a/cmd/gost/vendor/golang.org/x/net/http2/server.go
+++ b/vendor/golang.org/x/net/http2/server.go
@@ -110,11 +110,38 @@ type Server struct {
// activity for the purposes of IdleTimeout.
IdleTimeout time.Duration
+ // MaxUploadBufferPerConnection is the size of the initial flow
+ // control window for each connections. The HTTP/2 spec does not
+ // allow this to be smaller than 65535 or larger than 2^32-1.
+ // If the value is outside this range, a default value will be
+ // used instead.
+ MaxUploadBufferPerConnection int32
+
+ // MaxUploadBufferPerStream is the size of the initial flow control
+ // window for each stream. The HTTP/2 spec does not allow this to
+ // be larger than 2^32-1. If the value is zero or larger than the
+ // maximum, a default value will be used instead.
+ MaxUploadBufferPerStream int32
+
// NewWriteScheduler constructs a write scheduler for a connection.
// If nil, a default scheduler is chosen.
NewWriteScheduler func() WriteScheduler
}
+func (s *Server) initialConnRecvWindowSize() int32 {
+ if s.MaxUploadBufferPerConnection > initialWindowSize {
+ return s.MaxUploadBufferPerConnection
+ }
+ return 1 << 20
+}
+
+func (s *Server) initialStreamRecvWindowSize() int32 {
+ if s.MaxUploadBufferPerStream > 0 {
+ return s.MaxUploadBufferPerStream
+ }
+ return 1 << 20
+}
+
func (s *Server) maxReadFrameSize() uint32 {
if v := s.MaxReadFrameSize; v >= minMaxFrameSize && v <= maxFrameSize {
return v
@@ -255,35 +282,34 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
defer cancel()
sc := &serverConn{
- srv: s,
- hs: opts.baseConfig(),
- conn: c,
- baseCtx: baseCtx,
- remoteAddrStr: c.RemoteAddr().String(),
- bw: newBufferedWriter(c),
- handler: opts.handler(),
- streams: make(map[uint32]*stream),
- readFrameCh: make(chan readFrameResult),
- wantWriteFrameCh: make(chan FrameWriteRequest, 8),
- wantStartPushCh: make(chan startPushRequest, 8),
- wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync
- bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
- doneServing: make(chan struct{}),
- clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"
- advMaxStreams: s.maxConcurrentStreams(),
- initialWindowSize: initialWindowSize,
- maxFrameSize: initialMaxFrameSize,
- headerTableSize: initialHeaderTableSize,
- serveG: newGoroutineLock(),
- pushEnabled: true,
+ srv: s,
+ hs: opts.baseConfig(),
+ conn: c,
+ baseCtx: baseCtx,
+ remoteAddrStr: c.RemoteAddr().String(),
+ bw: newBufferedWriter(c),
+ handler: opts.handler(),
+ streams: make(map[uint32]*stream),
+ readFrameCh: make(chan readFrameResult),
+ wantWriteFrameCh: make(chan FrameWriteRequest, 8),
+ wantStartPushCh: make(chan startPushRequest, 8),
+ wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync
+ bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
+ doneServing: make(chan struct{}),
+ clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"
+ advMaxStreams: s.maxConcurrentStreams(),
+ initialStreamSendWindowSize: initialWindowSize,
+ maxFrameSize: initialMaxFrameSize,
+ headerTableSize: initialHeaderTableSize,
+ serveG: newGoroutineLock(),
+ pushEnabled: true,
}
// The net/http package sets the write deadline from the
// http.Server.WriteTimeout during the TLS handshake, but then
- // passes the connection off to us with the deadline already
- // set. Disarm it here so that it is not applied to additional
- // streams opened on this connection.
- // TODO: implement WriteTimeout fully. See Issue 18437.
+ // passes the connection off to us with the deadline already set.
+ // Write deadlines are set per stream in serverConn.newStream.
+ // Disarm the net.Conn write deadline here.
if sc.hs.WriteTimeout != 0 {
sc.conn.SetWriteDeadline(time.Time{})
}
@@ -294,6 +320,9 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
sc.writeSched = NewRandomWriteScheduler()
}
+ // These start at the RFC-specified defaults. If there is a higher
+ // configured value for inflow, that will be updated when we send a
+ // WINDOW_UPDATE shortly after sending SETTINGS.
sc.flow.add(initialWindowSize)
sc.inflow.add(initialWindowSize)
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
@@ -387,34 +416,34 @@ type serverConn struct {
writeSched WriteScheduler
// Everything following is owned by the serve loop; use serveG.check():
- serveG goroutineLock // used to verify funcs are on serve()
- pushEnabled bool
- sawFirstSettings bool // got the initial SETTINGS frame after the preface
- needToSendSettingsAck bool
- unackedSettings int // how many SETTINGS have we sent without ACKs?
- clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
- advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
- curClientStreams uint32 // number of open streams initiated by the client
- curPushedStreams uint32 // number of open streams initiated by server push
- maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
- maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
- streams map[uint32]*stream
- initialWindowSize int32
- maxFrameSize int32
- headerTableSize uint32
- peerMaxHeaderListSize uint32 // zero means unknown (default)
- canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
- writingFrame bool // started writing a frame (on serve goroutine or separate)
- writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
- needsFrameFlush bool // last frame write wasn't a flush
- inGoAway bool // we've started to or sent GOAWAY
- inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
- needToSendGoAway bool // we need to schedule a GOAWAY frame write
- goAwayCode ErrCode
- shutdownTimerCh <-chan time.Time // nil until used
- shutdownTimer *time.Timer // nil until used
- idleTimer *time.Timer // nil if unused
- idleTimerCh <-chan time.Time // nil if unused
+ serveG goroutineLock // used to verify funcs are on serve()
+ pushEnabled bool
+ sawFirstSettings bool // got the initial SETTINGS frame after the preface
+ needToSendSettingsAck bool
+ unackedSettings int // how many SETTINGS have we sent without ACKs?
+ clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
+ advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
+ curClientStreams uint32 // number of open streams initiated by the client
+ curPushedStreams uint32 // number of open streams initiated by server push
+ maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
+ maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
+ streams map[uint32]*stream
+ initialStreamSendWindowSize int32
+ maxFrameSize int32
+ headerTableSize uint32
+ peerMaxHeaderListSize uint32 // zero means unknown (default)
+ canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
+ writingFrame bool // started writing a frame (on serve goroutine or separate)
+ writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
+ needsFrameFlush bool // last frame write wasn't a flush
+ inGoAway bool // we've started to or sent GOAWAY
+ inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
+ needToSendGoAway bool // we need to schedule a GOAWAY frame write
+ goAwayCode ErrCode
+ shutdownTimerCh <-chan time.Time // nil until used
+ shutdownTimer *time.Timer // nil until used
+ idleTimer *time.Timer // nil if unused
+ idleTimerCh <-chan time.Time // nil if unused
// Owned by the writeFrameAsync goroutine:
headerWriteBuf bytes.Buffer
@@ -463,10 +492,10 @@ type stream struct {
numTrailerValues int64
weight uint8
state streamState
- resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
- gotTrailerHeader bool // HEADER frame for trailers was seen
- wroteHeaders bool // whether we wrote headers (not status 100)
- reqBuf []byte // if non-nil, body pipe buffer to return later at EOF
+ resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
+ gotTrailerHeader bool // HEADER frame for trailers was seen
+ wroteHeaders bool // whether we wrote headers (not status 100)
+ writeDeadline *time.Timer // nil if unused
trailer http.Header // accumulated trailers
reqTrailer http.Header // handler's Request.Trailer
@@ -696,21 +725,23 @@ func (sc *serverConn) serve() {
{SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
{SettingMaxConcurrentStreams, sc.advMaxStreams},
{SettingMaxHeaderListSize, sc.maxHeaderListSize()},
-
- // TODO: more actual settings, notably
- // SettingInitialWindowSize, but then we also
- // want to bump up the conn window size the
- // same amount here right after the settings
+ {SettingInitialWindowSize, uint32(sc.srv.initialStreamRecvWindowSize())},
},
})
sc.unackedSettings++
+ // Each connection starts with intialWindowSize inflow tokens.
+ // If a higher value is configured, we add more tokens.
+ if diff := sc.srv.initialConnRecvWindowSize() - initialWindowSize; diff > 0 {
+ sc.sendWindowUpdate(nil, int(diff))
+ }
+
if err := sc.readPreface(); err != nil {
sc.condlogf(err, "http2: server: error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)
return
}
// Now that we've got the preface, get us out of the
- // "StateNew" state. We can't go directly to idle, though.
+ // "StateNew" state. We can't go directly to idle, though.
// Active means we read some data and anticipate a request. We'll
// do another Active when we get a HEADERS frame.
sc.setConnState(http.StateActive)
@@ -722,9 +753,13 @@ func (sc *serverConn) serve() {
sc.idleTimerCh = sc.idleTimer.C
}
- var gracefulShutdownCh <-chan struct{}
+ var gracefulShutdownCh chan struct{}
if sc.hs != nil {
- gracefulShutdownCh = h1ServerShutdownChan(sc.hs)
+ ch := h1ServerShutdownChan(sc.hs)
+ if ch != nil {
+ gracefulShutdownCh = make(chan struct{})
+ go sc.awaitGracefulShutdown(ch, gracefulShutdownCh)
+ }
}
go sc.readFrames() // closed by defer sc.conn.Close above
@@ -735,6 +770,10 @@ func (sc *serverConn) serve() {
loopNum++
select {
case wr := <-sc.wantWriteFrameCh:
+ if se, ok := wr.write.(StreamError); ok {
+ sc.resetStream(se)
+ break
+ }
sc.writeFrame(wr)
case spr := <-sc.wantStartPushCh:
sc.startPush(spr)
@@ -773,6 +812,14 @@ func (sc *serverConn) serve() {
}
}
+func (sc *serverConn) awaitGracefulShutdown(sharedCh <-chan struct{}, privateCh chan struct{}) {
+ select {
+ case <-sc.doneServing:
+ case <-sharedCh:
+ close(privateCh)
+ }
+}
+
// readPreface reads the ClientPreface greeting from the peer
// or returns an error on timeout or an invalid greeting.
func (sc *serverConn) readPreface() error {
@@ -1014,7 +1061,11 @@ func (sc *serverConn) wroteFrame(res frameWriteResult) {
// stateClosed after the RST_STREAM frame is
// written.
st.state = stateHalfClosedLocal
- sc.resetStream(streamError(st.id, ErrCodeCancel))
+ // Section 8.1: a server MAY request that the client abort
+ // transmission of a request without error by sending a
+ // RST_STREAM with an error code of NO_ERROR after sending
+ // a complete response.
+ sc.resetStream(streamError(st.id, ErrCodeNo))
case stateHalfClosedRemote:
sc.closeStream(st, errHandlerComplete)
}
@@ -1305,6 +1356,9 @@ func (sc *serverConn) closeStream(st *stream, err error) {
panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))
}
st.state = stateClosed
+ if st.writeDeadline != nil {
+ st.writeDeadline.Stop()
+ }
if st.isPushed() {
sc.curPushedStreams--
} else {
@@ -1395,9 +1449,9 @@ func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
// adjust the size of all stream flow control windows that it
// maintains by the difference between the new value and the
// old value."
- old := sc.initialWindowSize
- sc.initialWindowSize = int32(val)
- growth := sc.initialWindowSize - old // may be negative
+ old := sc.initialStreamSendWindowSize
+ sc.initialStreamSendWindowSize = int32(val)
+ growth := int32(val) - old // may be negative
for _, st := range sc.streams {
if !st.flow.add(growth) {
// 6.9.2 Initial Flow Control Window Size
@@ -1543,6 +1597,12 @@ func (st *stream) copyTrailersToHandlerRequest() {
}
}
+// onWriteTimeout is run on its own goroutine (from time.AfterFunc)
+// when the stream's WriteTimeout has fired.
+func (st *stream) onWriteTimeout() {
+ st.sc.writeFrameFromHandler(FrameWriteRequest{write: streamError(st.id, ErrCodeInternal)})
+}
+
func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
sc.serveG.check()
id := f.StreamID
@@ -1719,9 +1779,12 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
}
st.cw.Init()
st.flow.conn = &sc.flow // link to conn-level counter
- st.flow.add(sc.initialWindowSize)
- st.inflow.conn = &sc.inflow // link to conn-level counter
- st.inflow.add(initialWindowSize) // TODO: update this when we send a higher initial window size in the initial settings
+ st.flow.add(sc.initialStreamSendWindowSize)
+ st.inflow.conn = &sc.inflow // link to conn-level counter
+ st.inflow.add(sc.srv.initialStreamRecvWindowSize())
+ if sc.hs.WriteTimeout != 0 {
+ st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
+ }
sc.streams[id] = st
sc.writeSched.OpenStream(st.id, OpenStreamOptions{PusherID: pusherID})
@@ -1785,16 +1848,14 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
return nil, nil, err
}
if bodyOpen {
- st.reqBuf = getRequestBodyBuf()
- req.Body.(*requestBody).pipe = &pipe{
- b: &fixedBuffer{buf: st.reqBuf},
- }
-
if vv, ok := rp.header["Content-Length"]; ok {
req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
} else {
req.ContentLength = -1
}
+ req.Body.(*requestBody).pipe = &pipe{
+ b: &dataBuffer{expected: req.ContentLength},
+ }
}
return rw, req, nil
}
@@ -1890,24 +1951,6 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
return rw, req, nil
}
-var reqBodyCache = make(chan []byte, 8)
-
-func getRequestBodyBuf() []byte {
- select {
- case b := <-reqBodyCache:
- return b
- default:
- return make([]byte, initialWindowSize)
- }
-}
-
-func putRequestBodyBuf(b []byte) {
- select {
- case reqBodyCache <- b:
- default:
- }
-}
-
// Run on its own goroutine.
func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
didPanic := true
@@ -2003,12 +2046,6 @@ func (sc *serverConn) noteBodyReadFromHandler(st *stream, n int, err error) {
case <-sc.doneServing:
}
}
- if err == io.EOF {
- if buf := st.reqBuf; buf != nil {
- st.reqBuf = nil // shouldn't matter; field unused by other
- putRequestBodyBuf(buf)
- }
- }
}
func (sc *serverConn) noteBodyRead(st *stream, n int) {
@@ -2103,8 +2140,8 @@ func (b *requestBody) Read(p []byte) (n int, err error) {
return
}
-// responseWriter is the http.ResponseWriter implementation. It's
-// intentionally small (1 pointer wide) to minimize garbage. The
+// responseWriter is the http.ResponseWriter implementation. It's
+// intentionally small (1 pointer wide) to minimize garbage. The
// responseWriterState pointer inside is zeroed at the end of a
// request (in handlerDone) and calls on the responseWriter thereafter
// simply crash (caller's mistake), but the much larger responseWriterState
@@ -2278,7 +2315,7 @@ const TrailerPrefix = "Trailer:"
// says you SHOULD (but not must) predeclare any trailers in the
// header, the official ResponseWriter rules said trailers in Go must
// be predeclared, and then we reuse the same ResponseWriter.Header()
-// map to mean both Headers and Trailers. When it's time to write the
+// map to mean both Headers and Trailers. When it's time to write the
// Trailers, we pick out the fields of Headers that were declared as
// trailers. That worked for a while, until we found the first major
// user of Trailers in the wild: gRPC (using them only over http2),
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go
similarity index 99%
rename from cmd/gost/vendor/golang.org/x/net/http2/transport.go
rename to vendor/golang.org/x/net/http2/transport.go
index 0c7e859..84d042d 100644
--- a/cmd/gost/vendor/golang.org/x/net/http2/transport.go
+++ b/vendor/golang.org/x/net/http2/transport.go
@@ -575,7 +575,7 @@ func (cc *ClientConn) canTakeNewRequestLocked() bool {
cc.nextStreamID < math.MaxInt32
}
-// onIdleTimeout is called from a time.AfterFunc goroutine. It will
+// onIdleTimeout is called from a time.AfterFunc goroutine. It will
// only be called when we're idle, but because we're coming from a new
// goroutine, there could be a new request coming in at the same time,
// so this simply calls the synchronized closeIfIdle to shut down this
@@ -809,8 +809,8 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
// 2xx, however, then assume the server DOES potentially
// want our body (e.g. full-duplex streaming:
// golang.org/issue/13444). If it turns out the server
- // doesn't, they'll RST_STREAM us soon enough. This is a
- // heuristic to avoid adding knobs to Transport. Hopefully
+ // doesn't, they'll RST_STREAM us soon enough. This is a
+ // heuristic to avoid adding knobs to Transport. Hopefully
// we can keep it.
bodyWriter.cancel()
cs.abortRequestBodyWrite(errStopReqBodyWrite)
@@ -1528,8 +1528,7 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
return res, nil
}
- buf := new(bytes.Buffer) // TODO(bradfitz): recycle this garbage
- cs.bufPipe = pipe{b: buf}
+ cs.bufPipe = pipe{b: &dataBuffer{expected: res.ContentLength}}
cs.bytesRemain = res.ContentLength
res.Body = transportResponseBody{cs}
go cs.awaitRequestCancel(cs.req)
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/write.go b/vendor/golang.org/x/net/http2/write.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/write.go
rename to vendor/golang.org/x/net/http2/write.go
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/writesched.go b/vendor/golang.org/x/net/http2/writesched.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/writesched.go
rename to vendor/golang.org/x/net/http2/writesched.go
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/writesched_priority.go b/vendor/golang.org/x/net/http2/writesched_priority.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/writesched_priority.go
rename to vendor/golang.org/x/net/http2/writesched_priority.go
diff --git a/cmd/gost/vendor/golang.org/x/net/http2/writesched_random.go b/vendor/golang.org/x/net/http2/writesched_random.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/http2/writesched_random.go
rename to vendor/golang.org/x/net/http2/writesched_random.go
diff --git a/vendor/golang.org/x/net/idna/idna.go b/vendor/golang.org/x/net/idna/idna.go
new file mode 100644
index 0000000..ee2dbda
--- /dev/null
+++ b/vendor/golang.org/x/net/idna/idna.go
@@ -0,0 +1,668 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package idna implements IDNA2008 using the compatibility processing
+// defined by UTS (Unicode Technical Standard) #46, which defines a standard to
+// deal with the transition from IDNA2003.
+//
+// IDNA2008 (Internationalized Domain Names for Applications), is defined in RFC
+// 5890, RFC 5891, RFC 5892, RFC 5893 and RFC 5894.
+// UTS #46 is defined in http://www.unicode.org/reports/tr46.
+// See http://unicode.org/cldr/utility/idna.jsp for a visualization of the
+// differences between these two standards.
+package idna // import "golang.org/x/net/idna"
+
+import (
+ "fmt"
+ "strings"
+ "unicode/utf8"
+
+ "golang.org/x/text/secure/bidirule"
+ "golang.org/x/text/unicode/norm"
+)
+
+// NOTE: Unlike common practice in Go APIs, the functions will return a
+// sanitized domain name in case of errors. Browsers sometimes use a partially
+// evaluated string as lookup.
+// TODO: the current error handling is, in my opinion, the least opinionated.
+// Other strategies are also viable, though:
+// Option 1) Return an empty string in case of error, but allow the user to
+// specify explicitly which errors to ignore.
+// Option 2) Return the partially evaluated string if it is itself a valid
+// string, otherwise return the empty string in case of error.
+// Option 3) Option 1 and 2.
+// Option 4) Always return an empty string for now and implement Option 1 as
+// needed, and document that the return string may not be empty in case of
+// error in the future.
+// I think Option 1 is best, but it is quite opinionated.
+
+// ToASCII is a wrapper for Punycode.ToASCII.
+func ToASCII(s string) (string, error) {
+ return Punycode.process(s, true)
+}
+
+// ToUnicode is a wrapper for Punycode.ToUnicode.
+func ToUnicode(s string) (string, error) {
+ return Punycode.process(s, false)
+}
+
+// An Option configures a Profile at creation time.
+type Option func(*options)
+
+// Transitional sets a Profile to use the Transitional mapping as defined in UTS
+// #46. This will cause, for example, "ß" to be mapped to "ss". Using the
+// transitional mapping provides a compromise between IDNA2003 and IDNA2008
+// compatibility. It is used by most browsers when resolving domain names. This
+// option is only meaningful if combined with MapForLookup.
+func Transitional(transitional bool) Option {
+ return func(o *options) { o.transitional = true }
+}
+
+// VerifyDNSLength sets whether a Profile should fail if any of the IDN parts
+// are longer than allowed by the RFC.
+func VerifyDNSLength(verify bool) Option {
+ return func(o *options) { o.verifyDNSLength = verify }
+}
+
+// ValidateLabels sets whether to check the mandatory label validation criteria
+// as defined in Section 5.4 of RFC 5891. This includes testing for correct use
+// of hyphens ('-'), normalization, validity of runes, and the context rules.
+func ValidateLabels(enable bool) Option {
+ return func(o *options) {
+ // Don't override existing mappings, but set one that at least checks
+ // normalization if it is not set.
+ if o.mapping == nil && enable {
+ o.mapping = normalize
+ }
+ o.trie = trie
+ o.validateLabels = enable
+ o.fromPuny = validateFromPunycode
+ }
+}
+
+// StrictDomainName limits the set of permissable ASCII characters to those
+// allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the
+// hyphen). This is set by default for MapForLookup and ValidateForRegistration.
+//
+// This option is useful, for instance, for browsers that allow characters
+// outside this range, for example a '_' (U+005F LOW LINE). See
+// http://www.rfc-editor.org/std/std3.txt for more details This option
+// corresponds to the UseSTD3ASCIIRules option in UTS #46.
+func StrictDomainName(use bool) Option {
+ return func(o *options) {
+ o.trie = trie
+ o.useSTD3Rules = use
+ o.fromPuny = validateFromPunycode
+ }
+}
+
+// NOTE: the following options pull in tables. The tables should not be linked
+// in as long as the options are not used.
+
+// BidiRule enables the Bidi rule as defined in RFC 5893. Any application
+// that relies on proper validation of labels should include this rule.
+func BidiRule() Option {
+ return func(o *options) { o.bidirule = bidirule.ValidString }
+}
+
+// ValidateForRegistration sets validation options to verify that a given IDN is
+// properly formatted for registration as defined by Section 4 of RFC 5891.
+func ValidateForRegistration() Option {
+ return func(o *options) {
+ o.mapping = validateRegistration
+ StrictDomainName(true)(o)
+ ValidateLabels(true)(o)
+ VerifyDNSLength(true)(o)
+ BidiRule()(o)
+ }
+}
+
+// MapForLookup sets validation and mapping options such that a given IDN is
+// transformed for domain name lookup according to the requirements set out in
+// Section 5 of RFC 5891. The mappings follow the recommendations of RFC 5894,
+// RFC 5895 and UTS 46. It does not add the Bidi Rule. Use the BidiRule option
+// to add this check.
+//
+// The mappings include normalization and mapping case, width and other
+// compatibility mappings.
+func MapForLookup() Option {
+ return func(o *options) {
+ o.mapping = validateAndMap
+ StrictDomainName(true)(o)
+ ValidateLabels(true)(o)
+ }
+}
+
+type options struct {
+ transitional bool
+ useSTD3Rules bool
+ validateLabels bool
+ verifyDNSLength bool
+
+ trie *idnaTrie
+
+ // fromPuny calls validation rules when converting A-labels to U-labels.
+ fromPuny func(p *Profile, s string) error
+
+ // mapping implements a validation and mapping step as defined in RFC 5895
+ // or UTS 46, tailored to, for example, domain registration or lookup.
+ mapping func(p *Profile, s string) (string, error)
+
+ // bidirule, if specified, checks whether s conforms to the Bidi Rule
+ // defined in RFC 5893.
+ bidirule func(s string) bool
+}
+
+// A Profile defines the configuration of a IDNA mapper.
+type Profile struct {
+ options
+}
+
+func apply(o *options, opts []Option) {
+ for _, f := range opts {
+ f(o)
+ }
+}
+
+// New creates a new Profile.
+//
+// With no options, the returned Profile is the most permissive and equals the
+// Punycode Profile. Options can be passed to further restrict the Profile. The
+// MapForLookup and ValidateForRegistration options set a collection of options,
+// for lookup and registration purposes respectively, which can be tailored by
+// adding more fine-grained options, where later options override earlier
+// options.
+func New(o ...Option) *Profile {
+ p := &Profile{}
+ apply(&p.options, o)
+ return p
+}
+
+// ToASCII converts a domain or domain label to its ASCII form. For example,
+// ToASCII("bücher.example.com") is "xn--bcher-kva.example.com", and
+// ToASCII("golang") is "golang". If an error is encountered it will return
+// an error and a (partially) processed result.
+func (p *Profile) ToASCII(s string) (string, error) {
+ return p.process(s, true)
+}
+
+// ToUnicode converts a domain or domain label to its Unicode form. For example,
+// ToUnicode("xn--bcher-kva.example.com") is "bücher.example.com", and
+// ToUnicode("golang") is "golang". If an error is encountered it will return
+// an error and a (partially) processed result.
+func (p *Profile) ToUnicode(s string) (string, error) {
+ pp := *p
+ pp.transitional = false
+ return pp.process(s, false)
+}
+
+// String reports a string with a description of the profile for debugging
+// purposes. The string format may change with different versions.
+func (p *Profile) String() string {
+ s := ""
+ if p.transitional {
+ s = "Transitional"
+ } else {
+ s = "NonTransitional"
+ }
+ if p.useSTD3Rules {
+ s += ":UseSTD3Rules"
+ }
+ if p.validateLabels {
+ s += ":ValidateLabels"
+ }
+ if p.verifyDNSLength {
+ s += ":VerifyDNSLength"
+ }
+ return s
+}
+
+var (
+ // Punycode is a Profile that does raw punycode processing with a minimum
+ // of validation.
+ Punycode *Profile = punycode
+
+ // Lookup is the recommended profile for looking up domain names, according
+ // to Section 5 of RFC 5891. The exact configuration of this profile may
+ // change over time.
+ Lookup *Profile = lookup
+
+ // Display is the recommended profile for displaying domain names.
+ // The configuration of this profile may change over time.
+ Display *Profile = display
+
+ // Registration is the recommended profile for checking whether a given
+ // IDN is valid for registration, according to Section 4 of RFC 5891.
+ Registration *Profile = registration
+
+ punycode = &Profile{}
+ lookup = &Profile{options{
+ transitional: true,
+ useSTD3Rules: true,
+ validateLabels: true,
+ trie: trie,
+ fromPuny: validateFromPunycode,
+ mapping: validateAndMap,
+ bidirule: bidirule.ValidString,
+ }}
+ display = &Profile{options{
+ useSTD3Rules: true,
+ validateLabels: true,
+ trie: trie,
+ fromPuny: validateFromPunycode,
+ mapping: validateAndMap,
+ bidirule: bidirule.ValidString,
+ }}
+ registration = &Profile{options{
+ useSTD3Rules: true,
+ validateLabels: true,
+ verifyDNSLength: true,
+ trie: trie,
+ fromPuny: validateFromPunycode,
+ mapping: validateRegistration,
+ bidirule: bidirule.ValidString,
+ }}
+
+ // TODO: profiles
+ // Register: recommended for approving domain names: don't do any mappings
+ // but rather reject on invalid input. Bundle or block deviation characters.
+)
+
+type labelError struct{ label, code_ string }
+
+func (e labelError) code() string { return e.code_ }
+func (e labelError) Error() string {
+ return fmt.Sprintf("idna: invalid label %q", e.label)
+}
+
+type runeError rune
+
+func (e runeError) code() string { return "P1" }
+func (e runeError) Error() string {
+ return fmt.Sprintf("idna: disallowed rune %U", e)
+}
+
+// process implements the algorithm described in section 4 of UTS #46,
+// see http://www.unicode.org/reports/tr46.
+func (p *Profile) process(s string, toASCII bool) (string, error) {
+ var err error
+ if p.mapping != nil {
+ s, err = p.mapping(p, s)
+ }
+ // Remove leading empty labels.
+ for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
+ }
+ // It seems like we should only create this error on ToASCII, but the
+ // UTS 46 conformance tests suggests we should always check this.
+ if err == nil && p.verifyDNSLength && s == "" {
+ err = &labelError{s, "A4"}
+ }
+ labels := labelIter{orig: s}
+ for ; !labels.done(); labels.next() {
+ label := labels.label()
+ if label == "" {
+ // Empty labels are not okay. The label iterator skips the last
+ // label if it is empty.
+ if err == nil && p.verifyDNSLength {
+ err = &labelError{s, "A4"}
+ }
+ continue
+ }
+ if strings.HasPrefix(label, acePrefix) {
+ u, err2 := decode(label[len(acePrefix):])
+ if err2 != nil {
+ if err == nil {
+ err = err2
+ }
+ // Spec says keep the old label.
+ continue
+ }
+ labels.set(u)
+ if err == nil && p.validateLabels {
+ err = p.fromPuny(p, u)
+ }
+ if err == nil {
+ // This should be called on NonTransitional, according to the
+ // spec, but that currently does not have any effect. Use the
+ // original profile to preserve options.
+ err = p.validateLabel(u)
+ }
+ } else if err == nil {
+ err = p.validateLabel(label)
+ }
+ }
+ if toASCII {
+ for labels.reset(); !labels.done(); labels.next() {
+ label := labels.label()
+ if !ascii(label) {
+ a, err2 := encode(acePrefix, label)
+ if err == nil {
+ err = err2
+ }
+ label = a
+ labels.set(a)
+ }
+ n := len(label)
+ if p.verifyDNSLength && err == nil && (n == 0 || n > 63) {
+ err = &labelError{label, "A4"}
+ }
+ }
+ }
+ s = labels.result()
+ if toASCII && p.verifyDNSLength && err == nil {
+ // Compute the length of the domain name minus the root label and its dot.
+ n := len(s)
+ if n > 0 && s[n-1] == '.' {
+ n--
+ }
+ if len(s) < 1 || n > 253 {
+ err = &labelError{s, "A4"}
+ }
+ }
+ return s, err
+}
+
+func normalize(p *Profile, s string) (string, error) {
+ return norm.NFC.String(s), nil
+}
+
+func validateRegistration(p *Profile, s string) (string, error) {
+ if !norm.NFC.IsNormalString(s) {
+ return s, &labelError{s, "V1"}
+ }
+ var err error
+ for i := 0; i < len(s); {
+ v, sz := trie.lookupString(s[i:])
+ i += sz
+ // Copy bytes not copied so far.
+ switch p.simplify(info(v).category()) {
+ // TODO: handle the NV8 defined in the Unicode idna data set to allow
+ // for strict conformance to IDNA2008.
+ case valid, deviation:
+ case disallowed, mapped, unknown, ignored:
+ if err == nil {
+ r, _ := utf8.DecodeRuneInString(s[i:])
+ err = runeError(r)
+ }
+ }
+ }
+ return s, err
+}
+
+func validateAndMap(p *Profile, s string) (string, error) {
+ var (
+ err error
+ b []byte
+ k int
+ )
+ for i := 0; i < len(s); {
+ v, sz := trie.lookupString(s[i:])
+ start := i
+ i += sz
+ // Copy bytes not copied so far.
+ switch p.simplify(info(v).category()) {
+ case valid:
+ continue
+ case disallowed:
+ if err == nil {
+ r, _ := utf8.DecodeRuneInString(s[i:])
+ err = runeError(r)
+ }
+ continue
+ case mapped, deviation:
+ b = append(b, s[k:start]...)
+ b = info(v).appendMapping(b, s[start:i])
+ case ignored:
+ b = append(b, s[k:start]...)
+ // drop the rune
+ case unknown:
+ b = append(b, s[k:start]...)
+ b = append(b, "\ufffd"...)
+ }
+ k = i
+ }
+ if k == 0 {
+ // No changes so far.
+ s = norm.NFC.String(s)
+ } else {
+ b = append(b, s[k:]...)
+ if norm.NFC.QuickSpan(b) != len(b) {
+ b = norm.NFC.Bytes(b)
+ }
+ // TODO: the punycode converters require strings as input.
+ s = string(b)
+ }
+ return s, err
+}
+
+// A labelIter allows iterating over domain name labels.
+type labelIter struct {
+ orig string
+ slice []string
+ curStart int
+ curEnd int
+ i int
+}
+
+func (l *labelIter) reset() {
+ l.curStart = 0
+ l.curEnd = 0
+ l.i = 0
+}
+
+func (l *labelIter) done() bool {
+ return l.curStart >= len(l.orig)
+}
+
+func (l *labelIter) result() string {
+ if l.slice != nil {
+ return strings.Join(l.slice, ".")
+ }
+ return l.orig
+}
+
+func (l *labelIter) label() string {
+ if l.slice != nil {
+ return l.slice[l.i]
+ }
+ p := strings.IndexByte(l.orig[l.curStart:], '.')
+ l.curEnd = l.curStart + p
+ if p == -1 {
+ l.curEnd = len(l.orig)
+ }
+ return l.orig[l.curStart:l.curEnd]
+}
+
+// next sets the value to the next label. It skips the last label if it is empty.
+func (l *labelIter) next() {
+ l.i++
+ if l.slice != nil {
+ if l.i >= len(l.slice) || l.i == len(l.slice)-1 && l.slice[l.i] == "" {
+ l.curStart = len(l.orig)
+ }
+ } else {
+ l.curStart = l.curEnd + 1
+ if l.curStart == len(l.orig)-1 && l.orig[l.curStart] == '.' {
+ l.curStart = len(l.orig)
+ }
+ }
+}
+
+func (l *labelIter) set(s string) {
+ if l.slice == nil {
+ l.slice = strings.Split(l.orig, ".")
+ }
+ l.slice[l.i] = s
+}
+
+// acePrefix is the ASCII Compatible Encoding prefix.
+const acePrefix = "xn--"
+
+func (p *Profile) simplify(cat category) category {
+ switch cat {
+ case disallowedSTD3Mapped:
+ if p.useSTD3Rules {
+ cat = disallowed
+ } else {
+ cat = mapped
+ }
+ case disallowedSTD3Valid:
+ if p.useSTD3Rules {
+ cat = disallowed
+ } else {
+ cat = valid
+ }
+ case deviation:
+ if !p.transitional {
+ cat = valid
+ }
+ case validNV8, validXV8:
+ // TODO: handle V2008
+ cat = valid
+ }
+ return cat
+}
+
+func validateFromPunycode(p *Profile, s string) error {
+ if !norm.NFC.IsNormalString(s) {
+ return &labelError{s, "V1"}
+ }
+ for i := 0; i < len(s); {
+ v, sz := trie.lookupString(s[i:])
+ if c := p.simplify(info(v).category()); c != valid && c != deviation {
+ return &labelError{s, "V6"}
+ }
+ i += sz
+ }
+ return nil
+}
+
+const (
+ zwnj = "\u200c"
+ zwj = "\u200d"
+)
+
+type joinState int8
+
+const (
+ stateStart joinState = iota
+ stateVirama
+ stateBefore
+ stateBeforeVirama
+ stateAfter
+ stateFAIL
+)
+
+var joinStates = [][numJoinTypes]joinState{
+ stateStart: {
+ joiningL: stateBefore,
+ joiningD: stateBefore,
+ joinZWNJ: stateFAIL,
+ joinZWJ: stateFAIL,
+ joinVirama: stateVirama,
+ },
+ stateVirama: {
+ joiningL: stateBefore,
+ joiningD: stateBefore,
+ },
+ stateBefore: {
+ joiningL: stateBefore,
+ joiningD: stateBefore,
+ joiningT: stateBefore,
+ joinZWNJ: stateAfter,
+ joinZWJ: stateFAIL,
+ joinVirama: stateBeforeVirama,
+ },
+ stateBeforeVirama: {
+ joiningL: stateBefore,
+ joiningD: stateBefore,
+ joiningT: stateBefore,
+ },
+ stateAfter: {
+ joiningL: stateFAIL,
+ joiningD: stateBefore,
+ joiningT: stateAfter,
+ joiningR: stateStart,
+ joinZWNJ: stateFAIL,
+ joinZWJ: stateFAIL,
+ joinVirama: stateAfter, // no-op as we can't accept joiners here
+ },
+ stateFAIL: {
+ 0: stateFAIL,
+ joiningL: stateFAIL,
+ joiningD: stateFAIL,
+ joiningT: stateFAIL,
+ joiningR: stateFAIL,
+ joinZWNJ: stateFAIL,
+ joinZWJ: stateFAIL,
+ joinVirama: stateFAIL,
+ },
+}
+
+// validateLabel validates the criteria from Section 4.1. Item 1, 4, and 6 are
+// already implicitly satisfied by the overall implementation.
+func (p *Profile) validateLabel(s string) error {
+ if s == "" {
+ if p.verifyDNSLength {
+ return &labelError{s, "A4"}
+ }
+ return nil
+ }
+ if p.bidirule != nil && !p.bidirule(s) {
+ return &labelError{s, "B"}
+ }
+ if !p.validateLabels {
+ return nil
+ }
+ trie := p.trie // p.validateLabels is only set if trie is set.
+ if len(s) > 4 && s[2] == '-' && s[3] == '-' {
+ return &labelError{s, "V2"}
+ }
+ if s[0] == '-' || s[len(s)-1] == '-' {
+ return &labelError{s, "V3"}
+ }
+ // TODO: merge the use of this in the trie.
+ v, sz := trie.lookupString(s)
+ x := info(v)
+ if x.isModifier() {
+ return &labelError{s, "V5"}
+ }
+ // Quickly return in the absence of zero-width (non) joiners.
+ if strings.Index(s, zwj) == -1 && strings.Index(s, zwnj) == -1 {
+ return nil
+ }
+ st := stateStart
+ for i := 0; ; {
+ jt := x.joinType()
+ if s[i:i+sz] == zwj {
+ jt = joinZWJ
+ } else if s[i:i+sz] == zwnj {
+ jt = joinZWNJ
+ }
+ st = joinStates[st][jt]
+ if x.isViramaModifier() {
+ st = joinStates[st][joinVirama]
+ }
+ if i += sz; i == len(s) {
+ break
+ }
+ v, sz = trie.lookupString(s[i:])
+ x = info(v)
+ }
+ if st == stateFAIL || st == stateAfter {
+ return &labelError{s, "C"}
+ }
+ return nil
+}
+
+func ascii(s string) bool {
+ for i := 0; i < len(s); i++ {
+ if s[i] >= utf8.RuneSelf {
+ return false
+ }
+ }
+ return true
+}
diff --git a/cmd/gost/vendor/golang.org/x/net/idna/punycode.go b/vendor/golang.org/x/net/idna/punycode.go
similarity index 87%
rename from cmd/gost/vendor/golang.org/x/net/idna/punycode.go
rename to vendor/golang.org/x/net/idna/punycode.go
index 92e733f..02c7d59 100644
--- a/cmd/gost/vendor/golang.org/x/net/idna/punycode.go
+++ b/vendor/golang.org/x/net/idna/punycode.go
@@ -1,4 +1,6 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -7,7 +9,6 @@ package idna
// This file implements the Punycode algorithm from RFC 3492.
import (
- "fmt"
"math"
"strings"
"unicode/utf8"
@@ -27,6 +28,8 @@ const (
tmin int32 = 1
)
+func punyError(s string) error { return &labelError{s, "A3"} }
+
// decode decodes a string as specified in section 6.2.
func decode(encoded string) (string, error) {
if encoded == "" {
@@ -34,7 +37,7 @@ func decode(encoded string) (string, error) {
}
pos := 1 + strings.LastIndex(encoded, "-")
if pos == 1 {
- return "", fmt.Errorf("idna: invalid label %q", encoded)
+ return "", punyError(encoded)
}
if pos == len(encoded) {
return encoded[:len(encoded)-1], nil
@@ -50,16 +53,16 @@ func decode(encoded string) (string, error) {
oldI, w := i, int32(1)
for k := base; ; k += base {
if pos == len(encoded) {
- return "", fmt.Errorf("idna: invalid label %q", encoded)
+ return "", punyError(encoded)
}
digit, ok := decodeDigit(encoded[pos])
if !ok {
- return "", fmt.Errorf("idna: invalid label %q", encoded)
+ return "", punyError(encoded)
}
pos++
i += digit * w
if i < 0 {
- return "", fmt.Errorf("idna: invalid label %q", encoded)
+ return "", punyError(encoded)
}
t := k - bias
if t < tmin {
@@ -72,7 +75,7 @@ func decode(encoded string) (string, error) {
}
w *= base - t
if w >= math.MaxInt32/base {
- return "", fmt.Errorf("idna: invalid label %q", encoded)
+ return "", punyError(encoded)
}
}
x := int32(len(output) + 1)
@@ -80,7 +83,7 @@ func decode(encoded string) (string, error) {
n += i / x
i %= x
if n > utf8.MaxRune || len(output) >= 1024 {
- return "", fmt.Errorf("idna: invalid label %q", encoded)
+ return "", punyError(encoded)
}
output = append(output, 0)
copy(output[i+1:], output[i:])
@@ -121,14 +124,14 @@ func encode(prefix, s string) (string, error) {
}
delta += (m - n) * (h + 1)
if delta < 0 {
- return "", fmt.Errorf("idna: invalid label %q", s)
+ return "", punyError(s)
}
n = m
for _, r := range s {
if r < n {
delta++
if delta < 0 {
- return "", fmt.Errorf("idna: invalid label %q", s)
+ return "", punyError(s)
}
continue
}
diff --git a/vendor/golang.org/x/net/idna/tables.go b/vendor/golang.org/x/net/idna/tables.go
new file mode 100644
index 0000000..d281934
--- /dev/null
+++ b/vendor/golang.org/x/net/idna/tables.go
@@ -0,0 +1,4477 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package idna
+
+// UnicodeVersion is the Unicode version from which the tables in this package are derived.
+const UnicodeVersion = "9.0.0"
+
+var mappings string = "" + // Size: 8176 bytes
+ "\x00\x01 \x03 ̈\x01a\x03 ̄\x012\x013\x03 ́\x03 ̧\x011\x01o\x051⁄4\x051⁄2" +
+ "\x053⁄4\x03i̇\x03l·\x03ʼn\x01s\x03dž\x03ⱥ\x03ⱦ\x01h\x01j\x01r\x01w\x01y" +
+ "\x03 ̆\x03 ̇\x03 ̊\x03 ̨\x03 ̃\x03 ̋\x01l\x01x\x04̈́\x03 ι\x01;\x05 ̈́" +
+ "\x04եւ\x04اٴ\x04وٴ\x04ۇٴ\x04يٴ\x06क़\x06ख़\x06ग़\x06ज़\x06ड़\x06ढ़\x06फ़" +
+ "\x06य़\x06ড়\x06ঢ়\x06য়\x06ਲ਼\x06ਸ਼\x06ਖ਼\x06ਗ਼\x06ਜ਼\x06ਫ਼\x06ଡ଼\x06ଢ଼" +
+ "\x06ํา\x06ໍາ\x06ຫນ\x06ຫມ\x06གྷ\x06ཌྷ\x06དྷ\x06བྷ\x06ཛྷ\x06ཀྵ\x06ཱི\x06ཱུ" +
+ "\x06ྲྀ\x09ྲཱྀ\x06ླྀ\x09ླཱྀ\x06ཱྀ\x06ྒྷ\x06ྜྷ\x06ྡྷ\x06ྦྷ\x06ྫྷ\x06ྐྵ\x02" +
+ "в\x02д\x02о\x02с\x02т\x02ъ\x02ѣ\x02æ\x01b\x01d\x01e\x02ǝ\x01g\x01i\x01k" +
+ "\x01m\x01n\x02ȣ\x01p\x01t\x01u\x02ɐ\x02ɑ\x02ə\x02ɛ\x02ɜ\x02ŋ\x02ɔ\x02ɯ" +
+ "\x01v\x02β\x02γ\x02δ\x02φ\x02χ\x02ρ\x02н\x02ɒ\x01c\x02ɕ\x02ð\x01f\x02ɟ" +
+ "\x02ɡ\x02ɥ\x02ɨ\x02ɩ\x02ɪ\x02ʝ\x02ɭ\x02ʟ\x02ɱ\x02ɰ\x02ɲ\x02ɳ\x02ɴ\x02ɵ" +
+ "\x02ɸ\x02ʂ\x02ʃ\x02ƫ\x02ʉ\x02ʊ\x02ʋ\x02ʌ\x01z\x02ʐ\x02ʑ\x02ʒ\x02θ\x02ss" +
+ "\x02ά\x02έ\x02ή\x02ί\x02ό\x02ύ\x02ώ\x05ἀι\x05ἁι\x05ἂι\x05ἃι\x05ἄι\x05ἅι" +
+ "\x05ἆι\x05ἇι\x05ἠι\x05ἡι\x05ἢι\x05ἣι\x05ἤι\x05ἥι\x05ἦι\x05ἧι\x05ὠι\x05ὡι" +
+ "\x05ὢι\x05ὣι\x05ὤι\x05ὥι\x05ὦι\x05ὧι\x05ὰι\x04αι\x04άι\x05ᾶι\x02ι\x05 ̈͂" +
+ "\x05ὴι\x04ηι\x04ήι\x05ῆι\x05 ̓̀\x05 ̓́\x05 ̓͂\x02ΐ\x05 ̔̀\x05 ̔́\x05 ̔͂" +
+ "\x02ΰ\x05 ̈̀\x01`\x05ὼι\x04ωι\x04ώι\x05ῶι\x06′′\x09′′′\x06‵‵\x09‵‵‵\x02!" +
+ "!\x02??\x02?!\x02!?\x0c′′′′\x010\x014\x015\x016\x017\x018\x019\x01+\x01=" +
+ "\x01(\x01)\x02rs\x02ħ\x02no\x01q\x02sm\x02tm\x02ω\x02å\x02א\x02ב\x02ג" +
+ "\x02ד\x02π\x051⁄7\x051⁄9\x061⁄10\x051⁄3\x052⁄3\x051⁄5\x052⁄5\x053⁄5\x054" +
+ "⁄5\x051⁄6\x055⁄6\x051⁄8\x053⁄8\x055⁄8\x057⁄8\x041⁄\x02ii\x02iv\x02vi" +
+ "\x04viii\x02ix\x02xi\x050⁄3\x06∫∫\x09∫∫∫\x06∮∮\x09∮∮∮\x0210\x0211\x0212" +
+ "\x0213\x0214\x0215\x0216\x0217\x0218\x0219\x0220\x04(10)\x04(11)\x04(12)" +
+ "\x04(13)\x04(14)\x04(15)\x04(16)\x04(17)\x04(18)\x04(19)\x04(20)\x0c∫∫∫∫" +
+ "\x02==\x05⫝̸\x02ɫ\x02ɽ\x02ȿ\x02ɀ\x01.\x04 ゙\x04 ゚\x06より\x06コト\x05(ᄀ)\x05" +
+ "(ᄂ)\x05(ᄃ)\x05(ᄅ)\x05(ᄆ)\x05(ᄇ)\x05(ᄉ)\x05(ᄋ)\x05(ᄌ)\x05(ᄎ)\x05(ᄏ)\x05(ᄐ" +
+ ")\x05(ᄑ)\x05(ᄒ)\x05(가)\x05(나)\x05(다)\x05(라)\x05(마)\x05(바)\x05(사)\x05(아)" +
+ "\x05(자)\x05(차)\x05(카)\x05(타)\x05(파)\x05(하)\x05(주)\x08(오전)\x08(오후)\x05(一)" +
+ "\x05(二)\x05(三)\x05(四)\x05(五)\x05(六)\x05(七)\x05(八)\x05(九)\x05(十)\x05(月)" +
+ "\x05(火)\x05(水)\x05(木)\x05(金)\x05(土)\x05(日)\x05(株)\x05(有)\x05(社)\x05(名)" +
+ "\x05(特)\x05(財)\x05(祝)\x05(労)\x05(代)\x05(呼)\x05(学)\x05(監)\x05(企)\x05(資)" +
+ "\x05(協)\x05(祭)\x05(休)\x05(自)\x05(至)\x0221\x0222\x0223\x0224\x0225\x0226" +
+ "\x0227\x0228\x0229\x0230\x0231\x0232\x0233\x0234\x0235\x06참고\x06주의\x0236" +
+ "\x0237\x0238\x0239\x0240\x0241\x0242\x0243\x0244\x0245\x0246\x0247\x0248" +
+ "\x0249\x0250\x041月\x042月\x043月\x044月\x045月\x046月\x047月\x048月\x049月\x0510" +
+ "月\x0511月\x0512月\x02hg\x02ev\x0cアパート\x0cアルファ\x0cアンペア\x09アール\x0cイニング\x09" +
+ "インチ\x09ウォン\x0fエスクード\x0cエーカー\x09オンス\x09オーム\x09カイリ\x0cカラット\x0cカロリー\x09ガロ" +
+ "ン\x09ガンマ\x06ギガ\x09ギニー\x0cキュリー\x0cギルダー\x06キロ\x0fキログラム\x12キロメートル\x0fキロワッ" +
+ "ト\x09グラム\x0fグラムトン\x0fクルゼイロ\x0cクローネ\x09ケース\x09コルナ\x09コーポ\x0cサイクル\x0fサンチ" +
+ "ーム\x0cシリング\x09センチ\x09セント\x09ダース\x06デシ\x06ドル\x06トン\x06ナノ\x09ノット\x09ハイツ" +
+ "\x0fパーセント\x09パーツ\x0cバーレル\x0fピアストル\x09ピクル\x06ピコ\x06ビル\x0fファラッド\x0cフィート" +
+ "\x0fブッシェル\x09フラン\x0fヘクタール\x06ペソ\x09ペニヒ\x09ヘルツ\x09ペンス\x09ページ\x09ベータ\x0cポイ" +
+ "ント\x09ボルト\x06ホン\x09ポンド\x09ホール\x09ホーン\x0cマイクロ\x09マイル\x09マッハ\x09マルク\x0fマ" +
+ "ンション\x0cミクロン\x06ミリ\x0fミリバール\x06メガ\x0cメガトン\x0cメートル\x09ヤード\x09ヤール\x09ユアン" +
+ "\x0cリットル\x06リラ\x09ルピー\x0cルーブル\x06レム\x0fレントゲン\x09ワット\x040点\x041点\x042点" +
+ "\x043点\x044点\x045点\x046点\x047点\x048点\x049点\x0510点\x0511点\x0512点\x0513点" +
+ "\x0514点\x0515点\x0516点\x0517点\x0518点\x0519点\x0520点\x0521点\x0522点\x0523点" +
+ "\x0524点\x02da\x02au\x02ov\x02pc\x02dm\x02iu\x06平成\x06昭和\x06大正\x06明治\x0c株" +
+ "式会社\x02pa\x02na\x02ma\x02ka\x02kb\x02mb\x02gb\x04kcal\x02pf\x02nf\x02m" +
+ "g\x02kg\x02hz\x02ml\x02dl\x02kl\x02fm\x02nm\x02mm\x02cm\x02km\x02m2\x02m" +
+ "3\x05m∕s\x06m∕s2\x07rad∕s\x08rad∕s2\x02ps\x02ns\x02ms\x02pv\x02nv\x02mv" +
+ "\x02kv\x02pw\x02nw\x02mw\x02kw\x02bq\x02cc\x02cd\x06c∕kg\x02db\x02gy\x02" +
+ "ha\x02hp\x02in\x02kk\x02kt\x02lm\x02ln\x02lx\x02ph\x02pr\x02sr\x02sv\x02" +
+ "wb\x05v∕m\x05a∕m\x041日\x042日\x043日\x044日\x045日\x046日\x047日\x048日\x049日" +
+ "\x0510日\x0511日\x0512日\x0513日\x0514日\x0515日\x0516日\x0517日\x0518日\x0519日" +
+ "\x0520日\x0521日\x0522日\x0523日\x0524日\x0525日\x0526日\x0527日\x0528日\x0529日" +
+ "\x0530日\x0531日\x02ь\x02ɦ\x02ɬ\x02ʞ\x02ʇ\x02œ\x04𤋮\x04𢡊\x04𢡄\x04𣏕\x04𥉉" +
+ "\x04𥳐\x04𧻓\x02ff\x02fi\x02fl\x02st\x04մն\x04մե\x04մի\x04վն\x04մխ\x04יִ" +
+ "\x04ײַ\x02ע\x02ה\x02כ\x02ל\x02ם\x02ר\x02ת\x04שׁ\x04שׂ\x06שּׁ\x06שּׂ\x04א" +
+ "ַ\x04אָ\x04אּ\x04בּ\x04גּ\x04דּ\x04הּ\x04וּ\x04זּ\x04טּ\x04יּ\x04ךּ\x04" +
+ "כּ\x04לּ\x04מּ\x04נּ\x04סּ\x04ףּ\x04פּ\x04צּ\x04קּ\x04רּ\x04שּ\x04תּ" +
+ "\x04וֹ\x04בֿ\x04כֿ\x04פֿ\x04אל\x02ٱ\x02ٻ\x02پ\x02ڀ\x02ٺ\x02ٿ\x02ٹ\x02ڤ" +
+ "\x02ڦ\x02ڄ\x02ڃ\x02چ\x02ڇ\x02ڍ\x02ڌ\x02ڎ\x02ڈ\x02ژ\x02ڑ\x02ک\x02گ\x02ڳ" +
+ "\x02ڱ\x02ں\x02ڻ\x02ۀ\x02ہ\x02ھ\x02ے\x02ۓ\x02ڭ\x02ۇ\x02ۆ\x02ۈ\x02ۋ\x02ۅ" +
+ "\x02ۉ\x02ې\x02ى\x04ئا\x04ئە\x04ئو\x04ئۇ\x04ئۆ\x04ئۈ\x04ئې\x04ئى\x02ی\x04" +
+ "ئج\x04ئح\x04ئم\x04ئي\x04بج\x04بح\x04بخ\x04بم\x04بى\x04بي\x04تج\x04تح" +
+ "\x04تخ\x04تم\x04تى\x04تي\x04ثج\x04ثم\x04ثى\x04ثي\x04جح\x04جم\x04حج\x04حم" +
+ "\x04خج\x04خح\x04خم\x04سج\x04سح\x04سخ\x04سم\x04صح\x04صم\x04ضج\x04ضح\x04ضخ" +
+ "\x04ضم\x04طح\x04طم\x04ظم\x04عج\x04عم\x04غج\x04غم\x04فج\x04فح\x04فخ\x04فم" +
+ "\x04فى\x04في\x04قح\x04قم\x04قى\x04قي\x04كا\x04كج\x04كح\x04كخ\x04كل\x04كم" +
+ "\x04كى\x04كي\x04لج\x04لح\x04لخ\x04لم\x04لى\x04لي\x04مج\x04مح\x04مخ\x04مم" +
+ "\x04مى\x04مي\x04نج\x04نح\x04نخ\x04نم\x04نى\x04ني\x04هج\x04هم\x04هى\x04هي" +
+ "\x04يج\x04يح\x04يخ\x04يم\x04يى\x04يي\x04ذٰ\x04رٰ\x04ىٰ\x05 ٌّ\x05 ٍّ\x05" +
+ " َّ\x05 ُّ\x05 ِّ\x05 ّٰ\x04ئر\x04ئز\x04ئن\x04بر\x04بز\x04بن\x04تر\x04تز" +
+ "\x04تن\x04ثر\x04ثز\x04ثن\x04ما\x04نر\x04نز\x04نن\x04ير\x04يز\x04ين\x04ئخ" +
+ "\x04ئه\x04به\x04ته\x04صخ\x04له\x04نه\x04هٰ\x04يه\x04ثه\x04سه\x04شم\x04شه" +
+ "\x06ـَّ\x06ـُّ\x06ـِّ\x04طى\x04طي\x04عى\x04عي\x04غى\x04غي\x04سى\x04سي" +
+ "\x04شى\x04شي\x04حى\x04حي\x04جى\x04جي\x04خى\x04خي\x04صى\x04صي\x04ضى\x04ضي" +
+ "\x04شج\x04شح\x04شخ\x04شر\x04سر\x04صر\x04ضر\x04اً\x06تجم\x06تحج\x06تحم" +
+ "\x06تخم\x06تمج\x06تمح\x06تمخ\x06جمح\x06حمي\x06حمى\x06سحج\x06سجح\x06سجى" +
+ "\x06سمح\x06سمج\x06سمم\x06صحح\x06صمم\x06شحم\x06شجي\x06شمخ\x06شمم\x06ضحى" +
+ "\x06ضخم\x06طمح\x06طمم\x06طمي\x06عجم\x06عمم\x06عمى\x06غمم\x06غمي\x06غمى" +
+ "\x06فخم\x06قمح\x06قمم\x06لحم\x06لحي\x06لحى\x06لجج\x06لخم\x06لمح\x06محج" +
+ "\x06محم\x06محي\x06مجح\x06مجم\x06مخج\x06مخم\x06مجخ\x06همج\x06همم\x06نحم" +
+ "\x06نحى\x06نجم\x06نجى\x06نمي\x06نمى\x06يمم\x06بخي\x06تجي\x06تجى\x06تخي" +
+ "\x06تخى\x06تمي\x06تمى\x06جمي\x06جحى\x06جمى\x06سخى\x06صحي\x06شحي\x06ضحي" +
+ "\x06لجي\x06لمي\x06يحي\x06يجي\x06يمي\x06ممي\x06قمي\x06نحي\x06عمي\x06كمي" +
+ "\x06نجح\x06مخي\x06لجم\x06كمم\x06جحي\x06حجي\x06مجي\x06فمي\x06بحي\x06سخي" +
+ "\x06نجي\x06صلے\x06قلے\x08الله\x08اكبر\x08محمد\x08صلعم\x08رسول\x08عليه" +
+ "\x08وسلم\x06صلى!صلى الله عليه وسلم\x0fجل جلاله\x08ریال\x01,\x01:\x01!" +
+ "\x01?\x01_\x01{\x01}\x01[\x01]\x01#\x01&\x01*\x01-\x01<\x01>\x01\\\x01$" +
+ "\x01%\x01@\x04ـً\x04ـَ\x04ـُ\x04ـِ\x04ـّ\x04ـْ\x02ء\x02آ\x02أ\x02ؤ\x02إ" +
+ "\x02ئ\x02ا\x02ب\x02ة\x02ت\x02ث\x02ج\x02ح\x02خ\x02د\x02ذ\x02ر\x02ز\x02س" +
+ "\x02ش\x02ص\x02ض\x02ط\x02ظ\x02ع\x02غ\x02ف\x02ق\x02ك\x02ل\x02م\x02ن\x02ه" +
+ "\x02و\x02ي\x04لآ\x04لأ\x04لإ\x04لا\x01\x22\x01'\x01/\x01^\x01|\x01~\x02¢" +
+ "\x02£\x02¬\x02¦\x02¥\x08𝅗𝅥\x08𝅘𝅥\x0c𝅘𝅥𝅮\x0c𝅘𝅥𝅯\x0c𝅘𝅥𝅰\x0c𝅘𝅥𝅱\x0c𝅘𝅥𝅲\x08𝆹" +
+ "𝅥\x08𝆺𝅥\x0c𝆹𝅥𝅮\x0c𝆺𝅥𝅮\x0c𝆹𝅥𝅯\x0c𝆺𝅥𝅯\x02ı\x02ȷ\x02α\x02ε\x02ζ\x02η\x02" +
+ "κ\x02λ\x02μ\x02ν\x02ξ\x02ο\x02σ\x02τ\x02υ\x02ψ\x03∇\x03∂\x02ϝ\x02ٮ\x02ڡ" +
+ "\x02ٯ\x020,\x021,\x022,\x023,\x024,\x025,\x026,\x027,\x028,\x029,\x03(a)" +
+ "\x03(b)\x03(c)\x03(d)\x03(e)\x03(f)\x03(g)\x03(h)\x03(i)\x03(j)\x03(k)" +
+ "\x03(l)\x03(m)\x03(n)\x03(o)\x03(p)\x03(q)\x03(r)\x03(s)\x03(t)\x03(u)" +
+ "\x03(v)\x03(w)\x03(x)\x03(y)\x03(z)\x07〔s〕\x02wz\x02hv\x02sd\x03ppv\x02w" +
+ "c\x02mc\x02md\x02dj\x06ほか\x06ココ\x03サ\x03手\x03字\x03双\x03デ\x03二\x03多\x03解" +
+ "\x03天\x03交\x03映\x03無\x03料\x03前\x03後\x03再\x03新\x03初\x03終\x03生\x03販\x03声" +
+ "\x03吹\x03演\x03投\x03捕\x03一\x03三\x03遊\x03左\x03中\x03右\x03指\x03走\x03打\x03禁" +
+ "\x03空\x03合\x03満\x03有\x03月\x03申\x03割\x03営\x03配\x09〔本〕\x09〔三〕\x09〔二〕\x09〔安" +
+ "〕\x09〔点〕\x09〔打〕\x09〔盗〕\x09〔勝〕\x09〔敗〕\x03得\x03可\x03丽\x03丸\x03乁\x03你\x03" +
+ "侮\x03侻\x03倂\x03偺\x03備\x03僧\x03像\x03㒞\x03免\x03兔\x03兤\x03具\x03㒹\x03內\x03" +
+ "冗\x03冤\x03仌\x03冬\x03况\x03凵\x03刃\x03㓟\x03刻\x03剆\x03剷\x03㔕\x03勇\x03勉\x03" +
+ "勤\x03勺\x03包\x03匆\x03北\x03卉\x03卑\x03博\x03即\x03卽\x03卿\x03灰\x03及\x03叟\x03" +
+ "叫\x03叱\x03吆\x03咞\x03吸\x03呈\x03周\x03咢\x03哶\x03唐\x03啓\x03啣\x03善\x03喙\x03" +
+ "喫\x03喳\x03嗂\x03圖\x03嘆\x03圗\x03噑\x03噴\x03切\x03壮\x03城\x03埴\x03堍\x03型\x03" +
+ "堲\x03報\x03墬\x03売\x03壷\x03夆\x03夢\x03奢\x03姬\x03娛\x03娧\x03姘\x03婦\x03㛮\x03" +
+ "嬈\x03嬾\x03寃\x03寘\x03寧\x03寳\x03寿\x03将\x03尢\x03㞁\x03屠\x03屮\x03峀\x03岍\x03" +
+ "嵃\x03嵮\x03嵫\x03嵼\x03巡\x03巢\x03㠯\x03巽\x03帨\x03帽\x03幩\x03㡢\x03㡼\x03庰\x03" +
+ "庳\x03庶\x03廊\x03廾\x03舁\x03弢\x03㣇\x03形\x03彫\x03㣣\x03徚\x03忍\x03志\x03忹\x03" +
+ "悁\x03㤺\x03㤜\x03悔\x03惇\x03慈\x03慌\x03慎\x03慺\x03憎\x03憲\x03憤\x03憯\x03懞\x03" +
+ "懲\x03懶\x03成\x03戛\x03扝\x03抱\x03拔\x03捐\x03挽\x03拼\x03捨\x03掃\x03揤\x03搢\x03" +
+ "揅\x03掩\x03㨮\x03摩\x03摾\x03撝\x03摷\x03㩬\x03敏\x03敬\x03旣\x03書\x03晉\x03㬙\x03" +
+ "暑\x03㬈\x03㫤\x03冒\x03冕\x03最\x03暜\x03肭\x03䏙\x03朗\x03望\x03朡\x03杞\x03杓\x03" +
+ "㭉\x03柺\x03枅\x03桒\x03梅\x03梎\x03栟\x03椔\x03㮝\x03楂\x03榣\x03槪\x03檨\x03櫛\x03" +
+ "㰘\x03次\x03歔\x03㱎\x03歲\x03殟\x03殺\x03殻\x03汎\x03沿\x03泍\x03汧\x03洖\x03派\x03" +
+ "海\x03流\x03浩\x03浸\x03涅\x03洴\x03港\x03湮\x03㴳\x03滋\x03滇\x03淹\x03潮\x03濆\x03" +
+ "瀹\x03瀞\x03瀛\x03㶖\x03灊\x03災\x03灷\x03炭\x03煅\x03熜\x03爨\x03爵\x03牐\x03犀\x03" +
+ "犕\x03獺\x03王\x03㺬\x03玥\x03㺸\x03瑇\x03瑜\x03瑱\x03璅\x03瓊\x03㼛\x03甤\x03甾\x03" +
+ "異\x03瘐\x03㿼\x03䀈\x03直\x03眞\x03真\x03睊\x03䀹\x03瞋\x03䁆\x03䂖\x03硎\x03碌\x03" +
+ "磌\x03䃣\x03祖\x03福\x03秫\x03䄯\x03穀\x03穊\x03穏\x03䈂\x03篆\x03築\x03䈧\x03糒\x03" +
+ "䊠\x03糨\x03糣\x03紀\x03絣\x03䌁\x03緇\x03縂\x03繅\x03䌴\x03䍙\x03罺\x03羕\x03翺\x03" +
+ "者\x03聠\x03聰\x03䏕\x03育\x03脃\x03䐋\x03脾\x03媵\x03舄\x03辞\x03䑫\x03芑\x03芋\x03" +
+ "芝\x03劳\x03花\x03芳\x03芽\x03苦\x03若\x03茝\x03荣\x03莭\x03茣\x03莽\x03菧\x03著\x03" +
+ "荓\x03菊\x03菌\x03菜\x03䔫\x03蓱\x03蓳\x03蔖\x03蕤\x03䕝\x03䕡\x03䕫\x03虐\x03虜\x03" +
+ "虧\x03虩\x03蚩\x03蚈\x03蜎\x03蛢\x03蝹\x03蜨\x03蝫\x03螆\x03蟡\x03蠁\x03䗹\x03衠\x03" +
+ "衣\x03裗\x03裞\x03䘵\x03裺\x03㒻\x03䚾\x03䛇\x03誠\x03諭\x03變\x03豕\x03貫\x03賁\x03" +
+ "贛\x03起\x03跋\x03趼\x03跰\x03軔\x03輸\x03邔\x03郱\x03鄑\x03鄛\x03鈸\x03鋗\x03鋘\x03" +
+ "鉼\x03鏹\x03鐕\x03開\x03䦕\x03閷\x03䧦\x03雃\x03嶲\x03霣\x03䩮\x03䩶\x03韠\x03䪲\x03" +
+ "頋\x03頩\x03飢\x03䬳\x03餩\x03馧\x03駂\x03駾\x03䯎\x03鬒\x03鱀\x03鳽\x03䳎\x03䳭\x03" +
+ "鵧\x03䳸\x03麻\x03䵖\x03黹\x03黾\x03鼅\x03鼏\x03鼖\x03鼻"
+
+var xorData string = "" + // Size: 4855 bytes
+ "\x02\x0c\x09\x02\xb0\xec\x02\xad\xd8\x02\xad\xd9\x02\x06\x07\x02\x0f\x12" +
+ "\x02\x0f\x1f\x02\x0f\x1d\x02\x01\x13\x02\x0f\x16\x02\x0f\x0b\x02\x0f3" +
+ "\x02\x0f7\x02\x0f?\x02\x0f/\x02\x0f*\x02\x0c&\x02\x0c*\x02\x0c;\x02\x0c9" +
+ "\x02\x0c%\x02\xab\xed\x02\xab\xe2\x02\xab\xe3\x02\xa9\xe0\x02\xa9\xe1" +
+ "\x02\xa9\xe6\x02\xa3\xcb\x02\xa3\xc8\x02\xa3\xc9\x02\x01#\x02\x01\x08" +
+ "\x02\x0e>\x02\x0e'\x02\x0f\x03\x02\x03\x0d\x02\x03\x09\x02\x03\x17\x02" +
+ "\x03\x0e\x02\x02\x03\x02\x011\x02\x01\x00\x02\x01\x10\x02\x03<\x02\x07" +
+ "\x0d\x02\x02\x0c\x02\x0c0\x02\x01\x03\x02\x01\x01\x02\x01 \x02\x01\x22" +
+ "\x02\x01)\x02\x01\x0a\x02\x01\x0c\x02\x02\x06\x02\x02\x02\x02\x03\x10" +
+ "\x03\x037 \x03\x0b+\x03\x02\x01\x04\x02\x01\x02\x02\x019\x02\x03\x1c\x02" +
+ "\x02$\x03\x80p$\x02\x03:\x02\x03\x0a\x03\xc1r.\x03\xc1r,\x03\xc1r\x02" +
+ "\x02\x02:\x02\x02>\x02\x02,\x02\x02\x10\x02\x02\x00\x03\xc1s<\x03\xc1s*" +
+ "\x03\xc2L$\x03\xc2L;\x02\x09)\x02\x0a\x19\x03\x83\xab\xe3\x03\x83\xab" +
+ "\xf2\x03 4\xe0\x03\x81\xab\xea\x03\x81\xab\xf3\x03 4\xef\x03\x96\xe1\xcd" +
+ "\x03\x84\xe5\xc3\x02\x0d\x11\x03\x8b\xec\xcb\x03\x94\xec\xcf\x03\x9a\xec" +
+ "\xc2\x03\x8b\xec\xdb\x03\x94\xec\xdf\x03\x9a\xec\xd2\x03\x01\x0c!\x03" +
+ "\x01\x0c#\x03ʠ\x9d\x03ʣ\x9c\x03ʢ\x9f\x03ʥ\x9e\x03ʤ\x91\x03ʧ\x90\x03ʦ\x93" +
+ "\x03ʩ\x92\x03ʨ\x95\x03\xca\xf3\xb5\x03\xca\xf0\xb4\x03\xca\xf1\xb7\x03" +
+ "\xca\xf6\xb6\x03\xca\xf7\x89\x03\xca\xf4\x88\x03\xca\xf5\x8b\x03\xca\xfa" +
+ "\x8a\x03\xca\xfb\x8d\x03\xca\xf8\x8c\x03\xca\xf9\x8f\x03\xca\xfe\x8e\x03" +
+ "\xca\xff\x81\x03\xca\xfc\x80\x03\xca\xfd\x83\x03\xca\xe2\x82\x03\xca\xe3" +
+ "\x85\x03\xca\xe0\x84\x03\xca\xe1\x87\x03\xca\xe6\x86\x03\xca\xe7\x99\x03" +
+ "\xca\xe4\x98\x03\xca\xe5\x9b\x03\xca\xea\x9a\x03\xca\xeb\x9d\x03\xca\xe8" +
+ "\x9c\x03ؓ\x89\x03ߔ\x8b\x02\x010\x03\x03\x04\x1e\x03\x04\x15\x12\x03\x0b" +
+ "\x05,\x03\x06\x04\x00\x03\x06\x04)\x03\x06\x044\x03\x06\x04<\x03\x06\x05" +
+ "\x1d\x03\x06\x06\x00\x03\x06\x06\x0a\x03\x06\x06'\x03\x06\x062\x03\x0786" +
+ "\x03\x079/\x03\x079 \x03\x07:\x0e\x03\x07:\x1b\x03\x07:%\x03\x07;/\x03" +
+ "\x07;%\x03\x074\x11\x03\x076\x09\x03\x077*\x03\x070\x01\x03\x070\x0f\x03" +
+ "\x070.\x03\x071\x16\x03\x071\x04\x03\x0710\x03\x072\x18\x03\x072-\x03" +
+ "\x073\x14\x03\x073>\x03\x07'\x09\x03\x07 \x00\x03\x07\x1f\x0b\x03\x07" +
+ "\x18#\x03\x07\x18(\x03\x07\x186\x03\x07\x18\x03\x03\x07\x19\x16\x03\x07" +
+ "\x116\x03\x07\x12'\x03\x07\x13\x10\x03\x07\x0c&\x03\x07\x0c\x08\x03\x07" +
+ "\x0c\x13\x03\x07\x0d\x02\x03\x07\x0d\x1c\x03\x07\x0b5\x03\x07\x0b\x0a" +
+ "\x03\x07\x0b\x01\x03\x07\x0b\x0f\x03\x07\x05\x00\x03\x07\x05\x09\x03\x07" +
+ "\x05\x0b\x03\x07\x07\x01\x03\x07\x07\x08\x03\x07\x00<\x03\x07\x00+\x03" +
+ "\x07\x01)\x03\x07\x01\x1b\x03\x07\x01\x08\x03\x07\x03?\x03\x0445\x03\x04" +
+ "4\x08\x03\x0454\x03\x04)/\x03\x04)5\x03\x04+\x05\x03\x04+\x14\x03\x04+ " +
+ "\x03\x04+<\x03\x04*&\x03\x04*\x22\x03\x04&8\x03\x04!\x01\x03\x04!\x22" +
+ "\x03\x04\x11+\x03\x04\x10.\x03\x04\x104\x03\x04\x13=\x03\x04\x12\x04\x03" +
+ "\x04\x12\x0a\x03\x04\x0d\x1d\x03\x04\x0d\x07\x03\x04\x0d \x03\x05<>\x03" +
+ "\x055<\x03\x055!\x03\x055#\x03\x055&\x03\x054\x1d\x03\x054\x02\x03\x054" +
+ "\x07\x03\x0571\x03\x053\x1a\x03\x053\x16\x03\x05.<\x03\x05.\x07\x03\x05)" +
+ ":\x03\x05)<\x03\x05)\x0c\x03\x05)\x15\x03\x05+-\x03\x05+5\x03\x05$\x1e" +
+ "\x03\x05$\x14\x03\x05'\x04\x03\x05'\x14\x03\x05&\x02\x03\x05\x226\x03" +
+ "\x05\x22\x0c\x03\x05\x22\x1c\x03\x05\x19\x0a\x03\x05\x1b\x09\x03\x05\x1b" +
+ "\x0c\x03\x05\x14\x07\x03\x05\x16?\x03\x05\x16\x0c\x03\x05\x0c\x05\x03" +
+ "\x05\x0e\x0f\x03\x05\x01\x0e\x03\x05\x00(\x03\x05\x030\x03\x05\x03\x06" +
+ "\x03\x0a==\x03\x0a=1\x03\x0a=,\x03\x0a=\x0c\x03\x0a??\x03\x0a<\x08\x03" +
+ "\x0a9!\x03\x0a9)\x03\x0a97\x03\x0a99\x03\x0a6\x0a\x03\x0a6\x1c\x03\x0a6" +
+ "\x17\x03\x0a7'\x03\x0a78\x03\x0a73\x03\x0a'\x01\x03\x0a'&\x03\x0a\x1f" +
+ "\x0e\x03\x0a\x1f\x03\x03\x0a\x1f3\x03\x0a\x1b/\x03\x0a\x18\x19\x03\x0a" +
+ "\x19\x01\x03\x0a\x16\x14\x03\x0a\x0e\x22\x03\x0a\x0f\x10\x03\x0a\x0f\x02" +
+ "\x03\x0a\x0f \x03\x0a\x0c\x04\x03\x0a\x0b>\x03\x0a\x0b+\x03\x0a\x08/\x03" +
+ "\x0a\x046\x03\x0a\x05\x14\x03\x0a\x00\x04\x03\x0a\x00\x10\x03\x0a\x00" +
+ "\x14\x03\x0b<3\x03\x0b;*\x03\x0b9\x22\x03\x0b9)\x03\x0b97\x03\x0b+\x10" +
+ "\x03\x0b((\x03\x0b&5\x03\x0b$\x1c\x03\x0b$\x12\x03\x0b%\x04\x03\x0b#<" +
+ "\x03\x0b#0\x03\x0b#\x0d\x03\x0b#\x19\x03\x0b!:\x03\x0b!\x1f\x03\x0b!\x00" +
+ "\x03\x0b\x1e5\x03\x0b\x1c\x1d\x03\x0b\x1d-\x03\x0b\x1d(\x03\x0b\x18.\x03" +
+ "\x0b\x18 \x03\x0b\x18\x16\x03\x0b\x14\x13\x03\x0b\x15$\x03\x0b\x15\x22" +
+ "\x03\x0b\x12\x1b\x03\x0b\x12\x10\x03\x0b\x132\x03\x0b\x13=\x03\x0b\x12" +
+ "\x18\x03\x0b\x0c&\x03\x0b\x061\x03\x0b\x06:\x03\x0b\x05#\x03\x0b\x05<" +
+ "\x03\x0b\x04\x0b\x03\x0b\x04\x04\x03\x0b\x04\x1b\x03\x0b\x042\x03\x0b" +
+ "\x041\x03\x0b\x03\x03\x03\x0b\x03\x1d\x03\x0b\x03/\x03\x0b\x03+\x03\x0b" +
+ "\x02\x1b\x03\x0b\x02\x00\x03\x0b\x01\x1e\x03\x0b\x01\x08\x03\x0b\x015" +
+ "\x03\x06\x0d9\x03\x06\x0d=\x03\x06\x0d?\x03\x02\x001\x03\x02\x003\x03" +
+ "\x02\x02\x19\x03\x02\x006\x03\x02\x02\x1b\x03\x02\x004\x03\x02\x00<\x03" +
+ "\x02\x02\x0a\x03\x02\x02\x0e\x03\x02\x01\x1a\x03\x02\x01\x07\x03\x02\x01" +
+ "\x05\x03\x02\x01\x0b\x03\x02\x01%\x03\x02\x01\x0c\x03\x02\x01\x04\x03" +
+ "\x02\x01\x1c\x03\x02\x00.\x03\x02\x002\x03\x02\x00>\x03\x02\x00\x12\x03" +
+ "\x02\x00\x16\x03\x02\x011\x03\x02\x013\x03\x02\x02 \x03\x02\x02%\x03\x02" +
+ "\x02$\x03\x02\x028\x03\x02\x02;\x03\x02\x024\x03\x02\x012\x03\x02\x022" +
+ "\x03\x02\x02/\x03\x02\x01,\x03\x02\x01\x13\x03\x02\x01\x16\x03\x02\x01" +
+ "\x11\x03\x02\x01\x1e\x03\x02\x01\x15\x03\x02\x01\x17\x03\x02\x01\x0f\x03" +
+ "\x02\x01\x08\x03\x02\x00?\x03\x02\x03\x07\x03\x02\x03\x0d\x03\x02\x03" +
+ "\x13\x03\x02\x03\x1d\x03\x02\x03\x1f\x03\x02\x00\x03\x03\x02\x00\x0d\x03" +
+ "\x02\x00\x01\x03\x02\x00\x1b\x03\x02\x00\x19\x03\x02\x00\x18\x03\x02\x00" +
+ "\x13\x03\x02\x00/\x03\x07>\x12\x03\x07<\x1f\x03\x07>\x1d\x03\x06\x1d\x0e" +
+ "\x03\x07>\x1c\x03\x07>:\x03\x07>\x13\x03\x04\x12+\x03\x07?\x03\x03\x07>" +
+ "\x02\x03\x06\x224\x03\x06\x1a.\x03\x07<%\x03\x06\x1c\x0b\x03\x0609\x03" +
+ "\x05\x1f\x01\x03\x04'\x08\x03\x93\xfd\xf5\x03\x02\x0d \x03\x02\x0d#\x03" +
+ "\x02\x0d!\x03\x02\x0d&\x03\x02\x0d\x22\x03\x02\x0d/\x03\x02\x0d,\x03\x02" +
+ "\x0d$\x03\x02\x0d'\x03\x02\x0d%\x03\x02\x0d;\x03\x02\x0d=\x03\x02\x0d?" +
+ "\x03\x099.\x03\x08\x0b7\x03\x08\x02\x14\x03\x08\x14\x0d\x03\x08.:\x03" +
+ "\x089'\x03\x0f\x0b\x18\x03\x0f\x1c1\x03\x0f\x17&\x03\x0f9\x1f\x03\x0f0" +
+ "\x0c\x03\x0e\x0a9\x03\x0e\x056\x03\x0e\x1c#\x03\x0f\x13\x0e\x03\x072\x00" +
+ "\x03\x070\x0d\x03\x072\x0b\x03\x06\x11\x18\x03\x070\x10\x03\x06\x0f(\x03" +
+ "\x072\x05\x03\x06\x0f,\x03\x073\x15\x03\x06\x07\x08\x03\x05\x16\x02\x03" +
+ "\x04\x0b \x03\x05:8\x03\x05\x16%\x03\x0a\x0d\x1f\x03\x06\x16\x10\x03\x05" +
+ "\x1d5\x03\x05*;\x03\x05\x16\x1b\x03\x04.-\x03\x06\x1a\x19\x03\x04\x03," +
+ "\x03\x0b87\x03\x04/\x0a\x03\x06\x00,\x03\x04-\x01\x03\x04\x1e-\x03\x06/(" +
+ "\x03\x0a\x0b5\x03\x06\x0e7\x03\x06\x07.\x03\x0597\x03\x0a*%\x03\x0760" +
+ "\x03\x06\x0c;\x03\x05'\x00\x03\x072.\x03\x072\x08\x03\x06=\x01\x03\x06" +
+ "\x05\x1b\x03\x06\x06\x12\x03\x06$=\x03\x06'\x0d\x03\x04\x11\x0f\x03\x076" +
+ ",\x03\x06\x07;\x03\x06.,\x03\x86\xf9\xea\x03\x8f\xff\xeb\x02\x092\x02" +
+ "\x095\x02\x094\x02\x09;\x02\x09>\x02\x098\x02\x09*\x02\x09/\x02\x09,\x02" +
+ "\x09%\x02\x09&\x02\x09#\x02\x09 \x02\x08!\x02\x08%\x02\x08$\x02\x08+\x02" +
+ "\x08.\x02\x08*\x02\x08&\x02\x088\x02\x08>\x02\x084\x02\x086\x02\x080\x02" +
+ "\x08\x10\x02\x08\x17\x02\x08\x12\x02\x08\x1d\x02\x08\x1f\x02\x08\x13\x02" +
+ "\x08\x15\x02\x08\x14\x02\x08\x0c\x03\x8b\xfd\xd0\x03\x81\xec\xc6\x03\x87" +
+ "\xe0\x8a\x03-2\xe3\x03\x80\xef\xe4\x03-2\xea\x03\x88\xe6\xeb\x03\x8e\xe6" +
+ "\xe8\x03\x84\xe6\xe9\x03\x97\xe6\xee\x03-2\xf9\x03-2\xf6\x03\x8e\xe3\xad" +
+ "\x03\x80\xe3\x92\x03\x88\xe3\x90\x03\x8e\xe3\x90\x03\x80\xe3\x97\x03\x88" +
+ "\xe3\x95\x03\x88\xfe\xcb\x03\x8e\xfe\xca\x03\x84\xfe\xcd\x03\x91\xef\xc9" +
+ "\x03-2\xc1\x03-2\xc0\x03-2\xcb\x03\x88@\x09\x03\x8e@\x08\x03\x8f\xe0\xf5" +
+ "\x03\x8e\xe6\xf9\x03\x8e\xe0\xfa\x03\x93\xff\xf4\x03\x84\xee\xd3\x03\x0b" +
+ "(\x04\x023 \x021;\x02\x01*\x03\x0b#\x10\x03\x0b 0\x03\x0b!\x10\x03\x0b!0" +
+ "\x03\x07\x15\x08\x03\x09?5\x03\x07\x1f\x08\x03\x07\x17\x0b\x03\x09\x1f" +
+ "\x15\x03\x0b\x1c7\x03\x0a+#\x03\x06\x1a\x1b\x03\x06\x1a\x14\x03\x0a\x01" +
+ "\x18\x03\x06#\x1b\x03\x0a2\x0c\x03\x0a\x01\x04\x03\x09#;\x03\x08='\x03" +
+ "\x08\x1a\x0a\x03\x07\x03\x07:+\x03\x07\x07*\x03\x06&\x1c\x03\x09\x0c" +
+ "\x16\x03\x09\x10\x0e\x03\x08'\x0f\x03\x08+\x09\x03\x074%\x03\x06!3\x03" +
+ "\x06\x03+\x03\x0b\x1e\x19\x03\x0a))\x03\x09\x08\x19\x03\x08,\x05\x03\x07" +
+ "<2\x03\x06\x1c>\x03\x0a\x111\x03\x09\x1b\x09\x03\x073.\x03\x07\x01\x00" +
+ "\x03\x09/,\x03\x07#>\x03\x07\x048\x03\x0a\x1f\x22\x03\x098>\x03\x09\x11" +
+ "\x00\x03\x08/\x17\x03\x06'\x22\x03\x0b\x1a+\x03\x0a\x22\x19\x03\x0a/1" +
+ "\x03\x0974\x03\x09\x0f\x22\x03\x08,\x22\x03\x08?\x14\x03\x07$5\x03\x07<3" +
+ "\x03\x07=*\x03\x07\x13\x18\x03\x068\x0a\x03\x06\x09\x16\x03\x06\x13\x00" +
+ "\x03\x08\x067\x03\x08\x01\x03\x03\x08\x12\x1d\x03\x07+7\x03\x06(;\x03" +
+ "\x06\x1c?\x03\x07\x0e\x17\x03\x0a\x06\x1d\x03\x0a\x19\x07\x03\x08\x14$" +
+ "\x03\x07$;\x03\x08,$\x03\x08\x06\x0d\x03\x07\x16\x0a\x03\x06>>\x03\x0a" +
+ "\x06\x12\x03\x0a\x14)\x03\x09\x0d\x1f\x03\x09\x12\x17\x03\x09\x19\x01" +
+ "\x03\x08\x11 \x03\x08\x1d'\x03\x06<\x1a\x03\x0a.\x00\x03\x07'\x18\x03" +
+ "\x0a\x22\x08\x03\x08\x0d\x0a\x03\x08\x13)\x03\x07*)\x03\x06<,\x03\x07" +
+ "\x0b\x1a\x03\x09.\x14\x03\x09\x0d\x1e\x03\x07\x0e#\x03\x0b\x1d'\x03\x0a" +
+ "\x0a8\x03\x09%2\x03\x08+&\x03\x080\x12\x03\x0a)4\x03\x08\x06\x1f\x03\x0b" +
+ "\x1b\x1a\x03\x0a\x1b\x0f\x03\x0b\x1d*\x03\x09\x16$\x03\x090\x11\x03\x08" +
+ "\x11\x08\x03\x0a*(\x03\x0a\x042\x03\x089,\x03\x074'\x03\x07\x0f\x05\x03" +
+ "\x09\x0b\x0a\x03\x07\x1b\x01\x03\x09\x17:\x03\x09.\x0d\x03\x07.\x11\x03" +
+ "\x09+\x15\x03\x080\x13\x03\x0b\x1f\x19\x03\x0a \x11\x03\x0a\x220\x03\x09" +
+ "\x07;\x03\x08\x16\x1c\x03\x07,\x13\x03\x07\x0e/\x03\x06\x221\x03\x0a." +
+ "\x0a\x03\x0a7\x02\x03\x0a\x032\x03\x0a\x1d.\x03\x091\x06\x03\x09\x19:" +
+ "\x03\x08\x02/\x03\x060+\x03\x06\x0f-\x03\x06\x1c\x1f\x03\x06\x1d\x07\x03" +
+ "\x0a,\x11\x03\x09=\x0d\x03\x09\x0b;\x03\x07\x1b/\x03\x0a\x1f:\x03\x09 " +
+ "\x1f\x03\x09.\x10\x03\x094\x0b\x03\x09\x1a1\x03\x08#\x1a\x03\x084\x1d" +
+ "\x03\x08\x01\x1f\x03\x08\x11\x22\x03\x07'8\x03\x07\x1a>\x03\x0757\x03" +
+ "\x06&9\x03\x06+\x11\x03\x0a.\x0b\x03\x0a,>\x03\x0a4#\x03\x08%\x17\x03" +
+ "\x07\x05\x22\x03\x07\x0c\x0b\x03\x0a\x1d+\x03\x0a\x19\x16\x03\x09+\x1f" +
+ "\x03\x09\x08\x0b\x03\x08\x16\x18\x03\x08+\x12\x03\x0b\x1d\x0c\x03\x0a=" +
+ "\x10\x03\x0a\x09\x0d\x03\x0a\x10\x11\x03\x09&0\x03\x08(\x1f\x03\x087\x07" +
+ "\x03\x08\x185\x03\x07'6\x03\x06.\x05\x03\x06=\x04\x03\x06;;\x03\x06\x06," +
+ "\x03\x0b\x18>\x03\x08\x00\x18\x03\x06 \x03\x03\x06<\x00\x03\x09%\x18\x03" +
+ "\x0b\x1c<\x03\x0a%!\x03\x0a\x09\x12\x03\x0a\x16\x02\x03\x090'\x03\x09" +
+ "\x0e=\x03\x08 \x0e\x03\x08>\x03\x03\x074>\x03\x06&?\x03\x06\x19\x09\x03" +
+ "\x06?(\x03\x0a-\x0e\x03\x09:3\x03\x098:\x03\x09\x12\x0b\x03\x09\x1d\x17" +
+ "\x03\x087\x05\x03\x082\x14\x03\x08\x06%\x03\x08\x13\x1f\x03\x06\x06\x0e" +
+ "\x03\x0a\x22<\x03\x09/<\x03\x06>+\x03\x0a'?\x03\x0a\x13\x0c\x03\x09\x10<" +
+ "\x03\x07\x1b=\x03\x0a\x19\x13\x03\x09\x22\x1d\x03\x09\x07\x0d\x03\x08)" +
+ "\x1c\x03\x06=\x1a\x03\x0a/4\x03\x0a7\x11\x03\x0a\x16:\x03\x09?3\x03\x09:" +
+ "/\x03\x09\x05\x0a\x03\x09\x14\x06\x03\x087\x22\x03\x080\x07\x03\x08\x1a" +
+ "\x1f\x03\x07\x04(\x03\x07\x04\x09\x03\x06 %\x03\x06<\x08\x03\x0a+\x14" +
+ "\x03\x09\x1d\x16\x03\x0a70\x03\x08 >\x03\x0857\x03\x070\x0a\x03\x06=\x12" +
+ "\x03\x06\x16%\x03\x06\x1d,\x03\x099#\x03\x09\x10>\x03\x07 \x1e\x03\x08" +
+ "\x0c<\x03\x08\x0b\x18\x03\x08\x15+\x03\x08,:\x03\x08%\x22\x03\x07\x0a$" +
+ "\x03\x0b\x1c=\x03\x07+\x08\x03\x0a/\x05\x03\x0a \x07\x03\x0a\x12'\x03" +
+ "\x09#\x11\x03\x08\x1b\x15\x03\x0a\x06\x01\x03\x09\x1c\x1b\x03\x0922\x03" +
+ "\x07\x14<\x03\x07\x09\x04\x03\x061\x04\x03\x07\x0e\x01\x03\x0a\x13\x18" +
+ "\x03\x0a-\x0c\x03\x0a?\x0d\x03\x0a\x09\x0a\x03\x091&\x03\x0a/\x0b\x03" +
+ "\x08$<\x03\x083\x1d\x03\x08\x0c$\x03\x08\x0d\x07\x03\x08\x0d?\x03\x08" +
+ "\x0e\x14\x03\x065\x0a\x03\x08\x1a#\x03\x08\x16#\x03\x0702\x03\x07\x03" +
+ "\x1a\x03\x06(\x1d\x03\x06+\x1b\x03\x06\x0b\x05\x03\x06\x0b\x17\x03\x06" +
+ "\x0c\x04\x03\x06\x1e\x19\x03\x06+0\x03\x062\x18\x03\x0b\x16\x1e\x03\x0a+" +
+ "\x16\x03\x0a-?\x03\x0a#:\x03\x0a#\x10\x03\x0a%$\x03\x0a>+\x03\x0a01\x03" +
+ "\x0a1\x10\x03\x0a\x099\x03\x0a\x0a\x12\x03\x0a\x19\x1f\x03\x0a\x19\x12" +
+ "\x03\x09*)\x03\x09-\x16\x03\x09.1\x03\x09.2\x03\x09<\x0e\x03\x09> \x03" +
+ "\x093\x12\x03\x09\x0b\x01\x03\x09\x1c2\x03\x09\x11\x1c\x03\x09\x15%\x03" +
+ "\x08,&\x03\x08!\x22\x03\x089(\x03\x08\x0b\x1a\x03\x08\x0d2\x03\x08\x0c" +
+ "\x04\x03\x08\x0c\x06\x03\x08\x0c\x1f\x03\x08\x0c\x0c\x03\x08\x0f\x1f\x03" +
+ "\x08\x0f\x1d\x03\x08\x00\x14\x03\x08\x03\x14\x03\x08\x06\x16\x03\x08\x1e" +
+ "#\x03\x08\x11\x11\x03\x08\x10\x18\x03\x08\x14(\x03\x07)\x1e\x03\x07.1" +
+ "\x03\x07 $\x03\x07 '\x03\x078\x08\x03\x07\x0d0\x03\x07\x0f7\x03\x07\x05#" +
+ "\x03\x07\x05\x1a\x03\x07\x1a7\x03\x07\x1d-\x03\x07\x17\x10\x03\x06)\x1f" +
+ "\x03\x062\x0b\x03\x066\x16\x03\x06\x09\x11\x03\x09(\x1e\x03\x07!5\x03" +
+ "\x0b\x11\x16\x03\x0a/\x04\x03\x0a,\x1a\x03\x0b\x173\x03\x0a,1\x03\x0a/5" +
+ "\x03\x0a\x221\x03\x0a\x22\x0d\x03\x0a?%\x03\x0a<,\x03\x0a?#\x03\x0a>\x19" +
+ "\x03\x0a\x08&\x03\x0a\x0b\x0e\x03\x0a\x0c:\x03\x0a\x0c+\x03\x0a\x03\x22" +
+ "\x03\x0a\x06)\x03\x0a\x11\x10\x03\x0a\x11\x1a\x03\x0a\x17-\x03\x0a\x14(" +
+ "\x03\x09)\x1e\x03\x09/\x09\x03\x09.\x00\x03\x09,\x07\x03\x09/*\x03\x09-9" +
+ "\x03\x09\x228\x03\x09%\x09\x03\x09:\x12\x03\x09;\x1d\x03\x09?\x06\x03" +
+ "\x093%\x03\x096\x05\x03\x096\x08\x03\x097\x02\x03\x09\x07,\x03\x09\x04," +
+ "\x03\x09\x1f\x16\x03\x09\x11\x03\x03\x09\x11\x12\x03\x09\x168\x03\x08*" +
+ "\x05\x03\x08/2\x03\x084:\x03\x08\x22+\x03\x08 0\x03\x08&\x0a\x03\x08;" +
+ "\x10\x03\x08>$\x03\x08>\x18\x03\x0829\x03\x082:\x03\x081,\x03\x081<\x03" +
+ "\x081\x1c\x03\x087#\x03\x087*\x03\x08\x09'\x03\x08\x00\x1d\x03\x08\x05-" +
+ "\x03\x08\x1f4\x03\x08\x1d\x04\x03\x08\x16\x0f\x03\x07*7\x03\x07'!\x03" +
+ "\x07%\x1b\x03\x077\x0c\x03\x07\x0c1\x03\x07\x0c.\x03\x07\x00\x06\x03\x07" +
+ "\x01\x02\x03\x07\x010\x03\x07\x06=\x03\x07\x01\x03\x03\x07\x01\x13\x03" +
+ "\x07\x06\x06\x03\x07\x05\x0a\x03\x07\x1f\x09\x03\x07\x17:\x03\x06*1\x03" +
+ "\x06-\x1d\x03\x06\x223\x03\x062:\x03\x060$\x03\x066\x1e\x03\x064\x12\x03" +
+ "\x0645\x03\x06\x0b\x00\x03\x06\x0b7\x03\x06\x07\x1f\x03\x06\x15\x12\x03" +
+ "\x0c\x05\x0f\x03\x0b+\x0b\x03\x0b+-\x03\x06\x16\x1b\x03\x06\x15\x17\x03" +
+ "\x89\xca\xea\x03\x89\xca\xe8\x03\x0c8\x10\x03\x0c8\x01\x03\x0c8\x0f\x03" +
+ "\x0d8%\x03\x0d8!\x03\x0c8-\x03\x0c8/\x03\x0c8+\x03\x0c87\x03\x0c85\x03" +
+ "\x0c9\x09\x03\x0c9\x0d\x03\x0c9\x0f\x03\x0c9\x0b\x03\xcfu\x0c\x03\xcfu" +
+ "\x0f\x03\xcfu\x0e\x03\xcfu\x09\x03\x0c9\x10\x03\x0d9\x0c\x03\xcf`;\x03" +
+ "\xcf`>\x03\xcf`9\x03\xcf`8\x03\xcf`7\x03\xcf`*\x03\xcf`-\x03\xcf`,\x03" +
+ "\x0d\x1b\x1a\x03\x0d\x1b&\x03\x0c=.\x03\x0c=%\x03\x0c>\x1e\x03\x0c>\x14" +
+ "\x03\x0c?\x06\x03\x0c?\x0b\x03\x0c?\x0c\x03\x0c?\x0d\x03\x0c?\x02\x03" +
+ "\x0c>\x0f\x03\x0c>\x08\x03\x0c>\x09\x03\x0c>,\x03\x0c>\x0c\x03\x0c?\x13" +
+ "\x03\x0c?\x16\x03\x0c?\x15\x03\x0c?\x1c\x03\x0c?\x1f\x03\x0c?\x1d\x03" +
+ "\x0c?\x1a\x03\x0c?\x17\x03\x0c?\x08\x03\x0c?\x09\x03\x0c?\x0e\x03\x0c?" +
+ "\x04\x03\x0c?\x05\x03\x0c\x03\x0c=\x00\x03\x0c=\x06\x03\x0c=\x05\x03" +
+ "\x0c=\x0c\x03\x0c=\x0f\x03\x0c=\x0d\x03\x0c=\x0b\x03\x0c=\x07\x03\x0c=" +
+ "\x19\x03\x0c=\x15\x03\x0c=\x11\x03\x0c=1\x03\x0c=3\x03\x0c=0\x03\x0c=>" +
+ "\x03\x0c=2\x03\x0c=6\x03\x0c<\x07\x03\x0c<\x05\x03\x0e:!\x03\x0e:#\x03" +
+ "\x0e8\x09\x03\x0e:&\x03\x0e8\x0b\x03\x0e:$\x03\x0e:,\x03\x0e8\x1a\x03" +
+ "\x0e8\x1e\x03\x0e:*\x03\x0e:7\x03\x0e:5\x03\x0e:;\x03\x0e:\x15\x03\x0e:<" +
+ "\x03\x0e:4\x03\x0e:'\x03\x0e:-\x03\x0e:%\x03\x0e:?\x03\x0e:=\x03\x0e:)" +
+ "\x03\x0e:/\x03\xcfs'\x03\x0d=\x0f\x03\x0d+*\x03\x0d99\x03\x0d9;\x03\x0d9" +
+ "?\x03\x0d)\x0d\x03\x0d(%\x02\x01\x18\x02\x01(\x02\x01\x1e\x03\x0f$!\x03" +
+ "\x0f87\x03\x0f4\x0e\x03\x0f5\x1d\x03\x06'\x03\x03\x0f\x08\x18\x03\x0f" +
+ "\x0d\x1b\x03\x0e2=\x03\x0e;\x08\x03\x0e:\x0b\x03\x0e\x06$\x03\x0e\x0d)" +
+ "\x03\x0e\x16\x1f\x03\x0e\x16\x1b\x03\x0d$\x0a\x03\x05,\x1d\x03\x0d. \x03" +
+ "\x0d.#\x03\x0c(/\x03\x09%\x02\x03\x0d90\x03\x0d\x0e4\x03\x0d\x0d\x0f\x03" +
+ "\x0c#\x00\x03\x0c,\x1e\x03\x0c2\x0e\x03\x0c\x01\x17\x03\x0c\x09:\x03\x0e" +
+ "\x173\x03\x0c\x08\x03\x03\x0c\x11\x07\x03\x0c\x10\x18\x03\x0c\x1f\x1c" +
+ "\x03\x0c\x19\x0e\x03\x0c\x1a\x1f\x03\x0f0>\x03\x0b->\x03\x0b<+\x03\x0b8" +
+ "\x13\x03\x0b\x043\x03\x0b\x14\x03\x03\x0b\x16%\x03\x0d\x22&\x03\x0b\x1a" +
+ "\x1a\x03\x0b\x1a\x04\x03\x0a%9\x03\x0a&2\x03\x0a&0\x03\x0a!\x1a\x03\x0a!" +
+ "7\x03\x0a5\x10\x03\x0a=4\x03\x0a?\x0e\x03\x0a>\x10\x03\x0a\x00 \x03\x0a" +
+ "\x0f:\x03\x0a\x0f9\x03\x0a\x0b\x0a\x03\x0a\x17%\x03\x0a\x1b-\x03\x09-" +
+ "\x1a\x03\x09,4\x03\x09.,\x03\x09)\x09\x03\x096!\x03\x091\x1f\x03\x093" +
+ "\x16\x03\x0c+\x1f\x03\x098 \x03\x098=\x03\x0c(\x1a\x03\x0c(\x16\x03\x09" +
+ "\x0a+\x03\x09\x16\x12\x03\x09\x13\x0e\x03\x09\x153\x03\x08)!\x03\x09\x1a" +
+ "\x01\x03\x09\x18\x01\x03\x08%#\x03\x08>\x22\x03\x08\x05%\x03\x08\x02*" +
+ "\x03\x08\x15;\x03\x08\x1b7\x03\x0f\x07\x1d\x03\x0f\x04\x03\x03\x070\x0c" +
+ "\x03\x07;\x0b\x03\x07\x08\x17\x03\x07\x12\x06\x03\x06/-\x03\x0671\x03" +
+ "\x065+\x03\x06>7\x03\x06\x049\x03\x05+\x1e\x03\x05,\x17\x03\x05 \x1d\x03" +
+ "\x05\x22\x05\x03\x050\x1d"
+
+// lookup returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *idnaTrie) lookup(s []byte) (v uint16, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return idnaValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := idnaIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := idnaIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = idnaIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := idnaIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = idnaIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = idnaIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *idnaTrie) lookupUnsafe(s []byte) uint16 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return idnaValues[c0]
+ }
+ i := idnaIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = idnaIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = idnaIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// lookupString returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *idnaTrie) lookupString(s string) (v uint16, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return idnaValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := idnaIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := idnaIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = idnaIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := idnaIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = idnaIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = idnaIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *idnaTrie) lookupStringUnsafe(s string) uint16 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return idnaValues[c0]
+ }
+ i := idnaIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = idnaIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = idnaIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// idnaTrie. Total size: 28496 bytes (27.83 KiB). Checksum: 43288b883596640e.
+type idnaTrie struct{}
+
+func newIdnaTrie(i int) *idnaTrie {
+ return &idnaTrie{}
+}
+
+// lookupValue determines the type of block n and looks up the value for b.
+func (t *idnaTrie) lookupValue(n uint32, b byte) uint16 {
+ switch {
+ case n < 123:
+ return uint16(idnaValues[n<<6+uint32(b)])
+ default:
+ n -= 123
+ return uint16(idnaSparse.lookup(n, b))
+ }
+}
+
+// idnaValues: 125 blocks, 8000 entries, 16000 bytes
+// The third block is the zero block.
+var idnaValues = [8000]uint16{
+ // Block 0x0, offset 0x0
+ 0x00: 0x0080, 0x01: 0x0080, 0x02: 0x0080, 0x03: 0x0080, 0x04: 0x0080, 0x05: 0x0080,
+ 0x06: 0x0080, 0x07: 0x0080, 0x08: 0x0080, 0x09: 0x0080, 0x0a: 0x0080, 0x0b: 0x0080,
+ 0x0c: 0x0080, 0x0d: 0x0080, 0x0e: 0x0080, 0x0f: 0x0080, 0x10: 0x0080, 0x11: 0x0080,
+ 0x12: 0x0080, 0x13: 0x0080, 0x14: 0x0080, 0x15: 0x0080, 0x16: 0x0080, 0x17: 0x0080,
+ 0x18: 0x0080, 0x19: 0x0080, 0x1a: 0x0080, 0x1b: 0x0080, 0x1c: 0x0080, 0x1d: 0x0080,
+ 0x1e: 0x0080, 0x1f: 0x0080, 0x20: 0x0080, 0x21: 0x0080, 0x22: 0x0080, 0x23: 0x0080,
+ 0x24: 0x0080, 0x25: 0x0080, 0x26: 0x0080, 0x27: 0x0080, 0x28: 0x0080, 0x29: 0x0080,
+ 0x2a: 0x0080, 0x2b: 0x0080, 0x2c: 0x0080, 0x2d: 0x0008, 0x2e: 0x0008, 0x2f: 0x0080,
+ 0x30: 0x0008, 0x31: 0x0008, 0x32: 0x0008, 0x33: 0x0008, 0x34: 0x0008, 0x35: 0x0008,
+ 0x36: 0x0008, 0x37: 0x0008, 0x38: 0x0008, 0x39: 0x0008, 0x3a: 0x0080, 0x3b: 0x0080,
+ 0x3c: 0x0080, 0x3d: 0x0080, 0x3e: 0x0080, 0x3f: 0x0080,
+ // Block 0x1, offset 0x40
+ 0x40: 0x0080, 0x41: 0xe105, 0x42: 0xe105, 0x43: 0xe105, 0x44: 0xe105, 0x45: 0xe105,
+ 0x46: 0xe105, 0x47: 0xe105, 0x48: 0xe105, 0x49: 0xe105, 0x4a: 0xe105, 0x4b: 0xe105,
+ 0x4c: 0xe105, 0x4d: 0xe105, 0x4e: 0xe105, 0x4f: 0xe105, 0x50: 0xe105, 0x51: 0xe105,
+ 0x52: 0xe105, 0x53: 0xe105, 0x54: 0xe105, 0x55: 0xe105, 0x56: 0xe105, 0x57: 0xe105,
+ 0x58: 0xe105, 0x59: 0xe105, 0x5a: 0xe105, 0x5b: 0x0080, 0x5c: 0x0080, 0x5d: 0x0080,
+ 0x5e: 0x0080, 0x5f: 0x0080, 0x60: 0x0080, 0x61: 0x0008, 0x62: 0x0008, 0x63: 0x0008,
+ 0x64: 0x0008, 0x65: 0x0008, 0x66: 0x0008, 0x67: 0x0008, 0x68: 0x0008, 0x69: 0x0008,
+ 0x6a: 0x0008, 0x6b: 0x0008, 0x6c: 0x0008, 0x6d: 0x0008, 0x6e: 0x0008, 0x6f: 0x0008,
+ 0x70: 0x0008, 0x71: 0x0008, 0x72: 0x0008, 0x73: 0x0008, 0x74: 0x0008, 0x75: 0x0008,
+ 0x76: 0x0008, 0x77: 0x0008, 0x78: 0x0008, 0x79: 0x0008, 0x7a: 0x0008, 0x7b: 0x0080,
+ 0x7c: 0x0080, 0x7d: 0x0080, 0x7e: 0x0080, 0x7f: 0x0080,
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc0: 0x0040, 0xc1: 0x0040, 0xc2: 0x0040, 0xc3: 0x0040, 0xc4: 0x0040, 0xc5: 0x0040,
+ 0xc6: 0x0040, 0xc7: 0x0040, 0xc8: 0x0040, 0xc9: 0x0040, 0xca: 0x0040, 0xcb: 0x0040,
+ 0xcc: 0x0040, 0xcd: 0x0040, 0xce: 0x0040, 0xcf: 0x0040, 0xd0: 0x0040, 0xd1: 0x0040,
+ 0xd2: 0x0040, 0xd3: 0x0040, 0xd4: 0x0040, 0xd5: 0x0040, 0xd6: 0x0040, 0xd7: 0x0040,
+ 0xd8: 0x0040, 0xd9: 0x0040, 0xda: 0x0040, 0xdb: 0x0040, 0xdc: 0x0040, 0xdd: 0x0040,
+ 0xde: 0x0040, 0xdf: 0x0040, 0xe0: 0x000a, 0xe1: 0x0018, 0xe2: 0x0018, 0xe3: 0x0018,
+ 0xe4: 0x0018, 0xe5: 0x0018, 0xe6: 0x0018, 0xe7: 0x0018, 0xe8: 0x001a, 0xe9: 0x0018,
+ 0xea: 0x0039, 0xeb: 0x0018, 0xec: 0x0018, 0xed: 0x03c0, 0xee: 0x0018, 0xef: 0x004a,
+ 0xf0: 0x0018, 0xf1: 0x0018, 0xf2: 0x0069, 0xf3: 0x0079, 0xf4: 0x008a, 0xf5: 0x0005,
+ 0xf6: 0x0018, 0xf7: 0x0008, 0xf8: 0x00aa, 0xf9: 0x00c9, 0xfa: 0x00d9, 0xfb: 0x0018,
+ 0xfc: 0x00e9, 0xfd: 0x0119, 0xfe: 0x0149, 0xff: 0x0018,
+ // Block 0x4, offset 0x100
+ 0x100: 0xe00d, 0x101: 0x0008, 0x102: 0xe00d, 0x103: 0x0008, 0x104: 0xe00d, 0x105: 0x0008,
+ 0x106: 0xe00d, 0x107: 0x0008, 0x108: 0xe00d, 0x109: 0x0008, 0x10a: 0xe00d, 0x10b: 0x0008,
+ 0x10c: 0xe00d, 0x10d: 0x0008, 0x10e: 0xe00d, 0x10f: 0x0008, 0x110: 0xe00d, 0x111: 0x0008,
+ 0x112: 0xe00d, 0x113: 0x0008, 0x114: 0xe00d, 0x115: 0x0008, 0x116: 0xe00d, 0x117: 0x0008,
+ 0x118: 0xe00d, 0x119: 0x0008, 0x11a: 0xe00d, 0x11b: 0x0008, 0x11c: 0xe00d, 0x11d: 0x0008,
+ 0x11e: 0xe00d, 0x11f: 0x0008, 0x120: 0xe00d, 0x121: 0x0008, 0x122: 0xe00d, 0x123: 0x0008,
+ 0x124: 0xe00d, 0x125: 0x0008, 0x126: 0xe00d, 0x127: 0x0008, 0x128: 0xe00d, 0x129: 0x0008,
+ 0x12a: 0xe00d, 0x12b: 0x0008, 0x12c: 0xe00d, 0x12d: 0x0008, 0x12e: 0xe00d, 0x12f: 0x0008,
+ 0x130: 0x0179, 0x131: 0x0008, 0x132: 0x0035, 0x133: 0x004d, 0x134: 0xe00d, 0x135: 0x0008,
+ 0x136: 0xe00d, 0x137: 0x0008, 0x138: 0x0008, 0x139: 0xe01d, 0x13a: 0x0008, 0x13b: 0xe03d,
+ 0x13c: 0x0008, 0x13d: 0xe01d, 0x13e: 0x0008, 0x13f: 0x0199,
+ // Block 0x5, offset 0x140
+ 0x140: 0x0199, 0x141: 0xe01d, 0x142: 0x0008, 0x143: 0xe03d, 0x144: 0x0008, 0x145: 0xe01d,
+ 0x146: 0x0008, 0x147: 0xe07d, 0x148: 0x0008, 0x149: 0x01b9, 0x14a: 0xe00d, 0x14b: 0x0008,
+ 0x14c: 0xe00d, 0x14d: 0x0008, 0x14e: 0xe00d, 0x14f: 0x0008, 0x150: 0xe00d, 0x151: 0x0008,
+ 0x152: 0xe00d, 0x153: 0x0008, 0x154: 0xe00d, 0x155: 0x0008, 0x156: 0xe00d, 0x157: 0x0008,
+ 0x158: 0xe00d, 0x159: 0x0008, 0x15a: 0xe00d, 0x15b: 0x0008, 0x15c: 0xe00d, 0x15d: 0x0008,
+ 0x15e: 0xe00d, 0x15f: 0x0008, 0x160: 0xe00d, 0x161: 0x0008, 0x162: 0xe00d, 0x163: 0x0008,
+ 0x164: 0xe00d, 0x165: 0x0008, 0x166: 0xe00d, 0x167: 0x0008, 0x168: 0xe00d, 0x169: 0x0008,
+ 0x16a: 0xe00d, 0x16b: 0x0008, 0x16c: 0xe00d, 0x16d: 0x0008, 0x16e: 0xe00d, 0x16f: 0x0008,
+ 0x170: 0xe00d, 0x171: 0x0008, 0x172: 0xe00d, 0x173: 0x0008, 0x174: 0xe00d, 0x175: 0x0008,
+ 0x176: 0xe00d, 0x177: 0x0008, 0x178: 0x0065, 0x179: 0xe01d, 0x17a: 0x0008, 0x17b: 0xe03d,
+ 0x17c: 0x0008, 0x17d: 0xe01d, 0x17e: 0x0008, 0x17f: 0x01d9,
+ // Block 0x6, offset 0x180
+ 0x180: 0x0008, 0x181: 0x007d, 0x182: 0xe00d, 0x183: 0x0008, 0x184: 0xe00d, 0x185: 0x0008,
+ 0x186: 0x007d, 0x187: 0xe07d, 0x188: 0x0008, 0x189: 0x0095, 0x18a: 0x00ad, 0x18b: 0xe03d,
+ 0x18c: 0x0008, 0x18d: 0x0008, 0x18e: 0x00c5, 0x18f: 0x00dd, 0x190: 0x00f5, 0x191: 0xe01d,
+ 0x192: 0x0008, 0x193: 0x010d, 0x194: 0x0125, 0x195: 0x0008, 0x196: 0x013d, 0x197: 0x013d,
+ 0x198: 0xe00d, 0x199: 0x0008, 0x19a: 0x0008, 0x19b: 0x0008, 0x19c: 0x010d, 0x19d: 0x0155,
+ 0x19e: 0x0008, 0x19f: 0x016d, 0x1a0: 0xe00d, 0x1a1: 0x0008, 0x1a2: 0xe00d, 0x1a3: 0x0008,
+ 0x1a4: 0xe00d, 0x1a5: 0x0008, 0x1a6: 0x0185, 0x1a7: 0xe07d, 0x1a8: 0x0008, 0x1a9: 0x019d,
+ 0x1aa: 0x0008, 0x1ab: 0x0008, 0x1ac: 0xe00d, 0x1ad: 0x0008, 0x1ae: 0x0185, 0x1af: 0xe0fd,
+ 0x1b0: 0x0008, 0x1b1: 0x01b5, 0x1b2: 0x01cd, 0x1b3: 0xe03d, 0x1b4: 0x0008, 0x1b5: 0xe01d,
+ 0x1b6: 0x0008, 0x1b7: 0x01e5, 0x1b8: 0xe00d, 0x1b9: 0x0008, 0x1ba: 0x0008, 0x1bb: 0x0008,
+ 0x1bc: 0xe00d, 0x1bd: 0x0008, 0x1be: 0x0008, 0x1bf: 0x0008,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x0008, 0x1c1: 0x0008, 0x1c2: 0x0008, 0x1c3: 0x0008, 0x1c4: 0x01e9, 0x1c5: 0x01e9,
+ 0x1c6: 0x01e9, 0x1c7: 0x01fd, 0x1c8: 0x0215, 0x1c9: 0x022d, 0x1ca: 0x0245, 0x1cb: 0x025d,
+ 0x1cc: 0x0275, 0x1cd: 0xe01d, 0x1ce: 0x0008, 0x1cf: 0xe0fd, 0x1d0: 0x0008, 0x1d1: 0xe01d,
+ 0x1d2: 0x0008, 0x1d3: 0xe03d, 0x1d4: 0x0008, 0x1d5: 0xe01d, 0x1d6: 0x0008, 0x1d7: 0xe07d,
+ 0x1d8: 0x0008, 0x1d9: 0xe01d, 0x1da: 0x0008, 0x1db: 0xe03d, 0x1dc: 0x0008, 0x1dd: 0x0008,
+ 0x1de: 0xe00d, 0x1df: 0x0008, 0x1e0: 0xe00d, 0x1e1: 0x0008, 0x1e2: 0xe00d, 0x1e3: 0x0008,
+ 0x1e4: 0xe00d, 0x1e5: 0x0008, 0x1e6: 0xe00d, 0x1e7: 0x0008, 0x1e8: 0xe00d, 0x1e9: 0x0008,
+ 0x1ea: 0xe00d, 0x1eb: 0x0008, 0x1ec: 0xe00d, 0x1ed: 0x0008, 0x1ee: 0xe00d, 0x1ef: 0x0008,
+ 0x1f0: 0x0008, 0x1f1: 0x028d, 0x1f2: 0x02a5, 0x1f3: 0x02bd, 0x1f4: 0xe00d, 0x1f5: 0x0008,
+ 0x1f6: 0x02d5, 0x1f7: 0x02ed, 0x1f8: 0xe00d, 0x1f9: 0x0008, 0x1fa: 0xe00d, 0x1fb: 0x0008,
+ 0x1fc: 0xe00d, 0x1fd: 0x0008, 0x1fe: 0xe00d, 0x1ff: 0x0008,
+ // Block 0x8, offset 0x200
+ 0x200: 0xe00d, 0x201: 0x0008, 0x202: 0xe00d, 0x203: 0x0008, 0x204: 0xe00d, 0x205: 0x0008,
+ 0x206: 0xe00d, 0x207: 0x0008, 0x208: 0xe00d, 0x209: 0x0008, 0x20a: 0xe00d, 0x20b: 0x0008,
+ 0x20c: 0xe00d, 0x20d: 0x0008, 0x20e: 0xe00d, 0x20f: 0x0008, 0x210: 0xe00d, 0x211: 0x0008,
+ 0x212: 0xe00d, 0x213: 0x0008, 0x214: 0xe00d, 0x215: 0x0008, 0x216: 0xe00d, 0x217: 0x0008,
+ 0x218: 0xe00d, 0x219: 0x0008, 0x21a: 0xe00d, 0x21b: 0x0008, 0x21c: 0xe00d, 0x21d: 0x0008,
+ 0x21e: 0xe00d, 0x21f: 0x0008, 0x220: 0x0305, 0x221: 0x0008, 0x222: 0xe00d, 0x223: 0x0008,
+ 0x224: 0xe00d, 0x225: 0x0008, 0x226: 0xe00d, 0x227: 0x0008, 0x228: 0xe00d, 0x229: 0x0008,
+ 0x22a: 0xe00d, 0x22b: 0x0008, 0x22c: 0xe00d, 0x22d: 0x0008, 0x22e: 0xe00d, 0x22f: 0x0008,
+ 0x230: 0xe00d, 0x231: 0x0008, 0x232: 0xe00d, 0x233: 0x0008, 0x234: 0x0008, 0x235: 0x0008,
+ 0x236: 0x0008, 0x237: 0x0008, 0x238: 0x0008, 0x239: 0x0008, 0x23a: 0x0209, 0x23b: 0xe03d,
+ 0x23c: 0x0008, 0x23d: 0x031d, 0x23e: 0x0229, 0x23f: 0x0008,
+ // Block 0x9, offset 0x240
+ 0x240: 0x0008, 0x241: 0x0008, 0x242: 0x0018, 0x243: 0x0018, 0x244: 0x0018, 0x245: 0x0018,
+ 0x246: 0x0008, 0x247: 0x0008, 0x248: 0x0008, 0x249: 0x0008, 0x24a: 0x0008, 0x24b: 0x0008,
+ 0x24c: 0x0008, 0x24d: 0x0008, 0x24e: 0x0008, 0x24f: 0x0008, 0x250: 0x0008, 0x251: 0x0008,
+ 0x252: 0x0018, 0x253: 0x0018, 0x254: 0x0018, 0x255: 0x0018, 0x256: 0x0018, 0x257: 0x0018,
+ 0x258: 0x029a, 0x259: 0x02ba, 0x25a: 0x02da, 0x25b: 0x02fa, 0x25c: 0x031a, 0x25d: 0x033a,
+ 0x25e: 0x0018, 0x25f: 0x0018, 0x260: 0x03ad, 0x261: 0x0359, 0x262: 0x01d9, 0x263: 0x0369,
+ 0x264: 0x03c5, 0x265: 0x0018, 0x266: 0x0018, 0x267: 0x0018, 0x268: 0x0018, 0x269: 0x0018,
+ 0x26a: 0x0018, 0x26b: 0x0018, 0x26c: 0x0008, 0x26d: 0x0018, 0x26e: 0x0008, 0x26f: 0x0018,
+ 0x270: 0x0018, 0x271: 0x0018, 0x272: 0x0018, 0x273: 0x0018, 0x274: 0x0018, 0x275: 0x0018,
+ 0x276: 0x0018, 0x277: 0x0018, 0x278: 0x0018, 0x279: 0x0018, 0x27a: 0x0018, 0x27b: 0x0018,
+ 0x27c: 0x0018, 0x27d: 0x0018, 0x27e: 0x0018, 0x27f: 0x0018,
+ // Block 0xa, offset 0x280
+ 0x280: 0x03dd, 0x281: 0x03dd, 0x282: 0x1308, 0x283: 0x03f5, 0x284: 0x0379, 0x285: 0x040d,
+ 0x286: 0x1308, 0x287: 0x1308, 0x288: 0x1308, 0x289: 0x1308, 0x28a: 0x1308, 0x28b: 0x1308,
+ 0x28c: 0x1308, 0x28d: 0x1308, 0x28e: 0x1308, 0x28f: 0x13c0, 0x290: 0x1308, 0x291: 0x1308,
+ 0x292: 0x1308, 0x293: 0x1308, 0x294: 0x1308, 0x295: 0x1308, 0x296: 0x1308, 0x297: 0x1308,
+ 0x298: 0x1308, 0x299: 0x1308, 0x29a: 0x1308, 0x29b: 0x1308, 0x29c: 0x1308, 0x29d: 0x1308,
+ 0x29e: 0x1308, 0x29f: 0x1308, 0x2a0: 0x1308, 0x2a1: 0x1308, 0x2a2: 0x1308, 0x2a3: 0x1308,
+ 0x2a4: 0x1308, 0x2a5: 0x1308, 0x2a6: 0x1308, 0x2a7: 0x1308, 0x2a8: 0x1308, 0x2a9: 0x1308,
+ 0x2aa: 0x1308, 0x2ab: 0x1308, 0x2ac: 0x1308, 0x2ad: 0x1308, 0x2ae: 0x1308, 0x2af: 0x1308,
+ 0x2b0: 0xe00d, 0x2b1: 0x0008, 0x2b2: 0xe00d, 0x2b3: 0x0008, 0x2b4: 0x0425, 0x2b5: 0x0008,
+ 0x2b6: 0xe00d, 0x2b7: 0x0008, 0x2b8: 0x0040, 0x2b9: 0x0040, 0x2ba: 0x03a2, 0x2bb: 0x0008,
+ 0x2bc: 0x0008, 0x2bd: 0x0008, 0x2be: 0x03c2, 0x2bf: 0x043d,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0x0040, 0x2c1: 0x0040, 0x2c2: 0x0040, 0x2c3: 0x0040, 0x2c4: 0x008a, 0x2c5: 0x03d2,
+ 0x2c6: 0xe155, 0x2c7: 0x0455, 0x2c8: 0xe12d, 0x2c9: 0xe13d, 0x2ca: 0xe12d, 0x2cb: 0x0040,
+ 0x2cc: 0x03dd, 0x2cd: 0x0040, 0x2ce: 0x046d, 0x2cf: 0x0485, 0x2d0: 0x0008, 0x2d1: 0xe105,
+ 0x2d2: 0xe105, 0x2d3: 0xe105, 0x2d4: 0xe105, 0x2d5: 0xe105, 0x2d6: 0xe105, 0x2d7: 0xe105,
+ 0x2d8: 0xe105, 0x2d9: 0xe105, 0x2da: 0xe105, 0x2db: 0xe105, 0x2dc: 0xe105, 0x2dd: 0xe105,
+ 0x2de: 0xe105, 0x2df: 0xe105, 0x2e0: 0x049d, 0x2e1: 0x049d, 0x2e2: 0x0040, 0x2e3: 0x049d,
+ 0x2e4: 0x049d, 0x2e5: 0x049d, 0x2e6: 0x049d, 0x2e7: 0x049d, 0x2e8: 0x049d, 0x2e9: 0x049d,
+ 0x2ea: 0x049d, 0x2eb: 0x049d, 0x2ec: 0x0008, 0x2ed: 0x0008, 0x2ee: 0x0008, 0x2ef: 0x0008,
+ 0x2f0: 0x0008, 0x2f1: 0x0008, 0x2f2: 0x0008, 0x2f3: 0x0008, 0x2f4: 0x0008, 0x2f5: 0x0008,
+ 0x2f6: 0x0008, 0x2f7: 0x0008, 0x2f8: 0x0008, 0x2f9: 0x0008, 0x2fa: 0x0008, 0x2fb: 0x0008,
+ 0x2fc: 0x0008, 0x2fd: 0x0008, 0x2fe: 0x0008, 0x2ff: 0x0008,
+ // Block 0xc, offset 0x300
+ 0x300: 0x0008, 0x301: 0x0008, 0x302: 0xe00f, 0x303: 0x0008, 0x304: 0x0008, 0x305: 0x0008,
+ 0x306: 0x0008, 0x307: 0x0008, 0x308: 0x0008, 0x309: 0x0008, 0x30a: 0x0008, 0x30b: 0x0008,
+ 0x30c: 0x0008, 0x30d: 0x0008, 0x30e: 0x0008, 0x30f: 0xe0c5, 0x310: 0x04b5, 0x311: 0x04cd,
+ 0x312: 0xe0bd, 0x313: 0xe0f5, 0x314: 0xe0fd, 0x315: 0xe09d, 0x316: 0xe0b5, 0x317: 0x0008,
+ 0x318: 0xe00d, 0x319: 0x0008, 0x31a: 0xe00d, 0x31b: 0x0008, 0x31c: 0xe00d, 0x31d: 0x0008,
+ 0x31e: 0xe00d, 0x31f: 0x0008, 0x320: 0xe00d, 0x321: 0x0008, 0x322: 0xe00d, 0x323: 0x0008,
+ 0x324: 0xe00d, 0x325: 0x0008, 0x326: 0xe00d, 0x327: 0x0008, 0x328: 0xe00d, 0x329: 0x0008,
+ 0x32a: 0xe00d, 0x32b: 0x0008, 0x32c: 0xe00d, 0x32d: 0x0008, 0x32e: 0xe00d, 0x32f: 0x0008,
+ 0x330: 0x04e5, 0x331: 0xe185, 0x332: 0xe18d, 0x333: 0x0008, 0x334: 0x04fd, 0x335: 0x03dd,
+ 0x336: 0x0018, 0x337: 0xe07d, 0x338: 0x0008, 0x339: 0xe1d5, 0x33a: 0xe00d, 0x33b: 0x0008,
+ 0x33c: 0x0008, 0x33d: 0x0515, 0x33e: 0x052d, 0x33f: 0x052d,
+ // Block 0xd, offset 0x340
+ 0x340: 0x0008, 0x341: 0x0008, 0x342: 0x0008, 0x343: 0x0008, 0x344: 0x0008, 0x345: 0x0008,
+ 0x346: 0x0008, 0x347: 0x0008, 0x348: 0x0008, 0x349: 0x0008, 0x34a: 0x0008, 0x34b: 0x0008,
+ 0x34c: 0x0008, 0x34d: 0x0008, 0x34e: 0x0008, 0x34f: 0x0008, 0x350: 0x0008, 0x351: 0x0008,
+ 0x352: 0x0008, 0x353: 0x0008, 0x354: 0x0008, 0x355: 0x0008, 0x356: 0x0008, 0x357: 0x0008,
+ 0x358: 0x0008, 0x359: 0x0008, 0x35a: 0x0008, 0x35b: 0x0008, 0x35c: 0x0008, 0x35d: 0x0008,
+ 0x35e: 0x0008, 0x35f: 0x0008, 0x360: 0xe00d, 0x361: 0x0008, 0x362: 0xe00d, 0x363: 0x0008,
+ 0x364: 0xe00d, 0x365: 0x0008, 0x366: 0xe00d, 0x367: 0x0008, 0x368: 0xe00d, 0x369: 0x0008,
+ 0x36a: 0xe00d, 0x36b: 0x0008, 0x36c: 0xe00d, 0x36d: 0x0008, 0x36e: 0xe00d, 0x36f: 0x0008,
+ 0x370: 0xe00d, 0x371: 0x0008, 0x372: 0xe00d, 0x373: 0x0008, 0x374: 0xe00d, 0x375: 0x0008,
+ 0x376: 0xe00d, 0x377: 0x0008, 0x378: 0xe00d, 0x379: 0x0008, 0x37a: 0xe00d, 0x37b: 0x0008,
+ 0x37c: 0xe00d, 0x37d: 0x0008, 0x37e: 0xe00d, 0x37f: 0x0008,
+ // Block 0xe, offset 0x380
+ 0x380: 0xe00d, 0x381: 0x0008, 0x382: 0x0018, 0x383: 0x1308, 0x384: 0x1308, 0x385: 0x1308,
+ 0x386: 0x1308, 0x387: 0x1308, 0x388: 0x1318, 0x389: 0x1318, 0x38a: 0xe00d, 0x38b: 0x0008,
+ 0x38c: 0xe00d, 0x38d: 0x0008, 0x38e: 0xe00d, 0x38f: 0x0008, 0x390: 0xe00d, 0x391: 0x0008,
+ 0x392: 0xe00d, 0x393: 0x0008, 0x394: 0xe00d, 0x395: 0x0008, 0x396: 0xe00d, 0x397: 0x0008,
+ 0x398: 0xe00d, 0x399: 0x0008, 0x39a: 0xe00d, 0x39b: 0x0008, 0x39c: 0xe00d, 0x39d: 0x0008,
+ 0x39e: 0xe00d, 0x39f: 0x0008, 0x3a0: 0xe00d, 0x3a1: 0x0008, 0x3a2: 0xe00d, 0x3a3: 0x0008,
+ 0x3a4: 0xe00d, 0x3a5: 0x0008, 0x3a6: 0xe00d, 0x3a7: 0x0008, 0x3a8: 0xe00d, 0x3a9: 0x0008,
+ 0x3aa: 0xe00d, 0x3ab: 0x0008, 0x3ac: 0xe00d, 0x3ad: 0x0008, 0x3ae: 0xe00d, 0x3af: 0x0008,
+ 0x3b0: 0xe00d, 0x3b1: 0x0008, 0x3b2: 0xe00d, 0x3b3: 0x0008, 0x3b4: 0xe00d, 0x3b5: 0x0008,
+ 0x3b6: 0xe00d, 0x3b7: 0x0008, 0x3b8: 0xe00d, 0x3b9: 0x0008, 0x3ba: 0xe00d, 0x3bb: 0x0008,
+ 0x3bc: 0xe00d, 0x3bd: 0x0008, 0x3be: 0xe00d, 0x3bf: 0x0008,
+ // Block 0xf, offset 0x3c0
+ 0x3c0: 0x0040, 0x3c1: 0xe01d, 0x3c2: 0x0008, 0x3c3: 0xe03d, 0x3c4: 0x0008, 0x3c5: 0xe01d,
+ 0x3c6: 0x0008, 0x3c7: 0xe07d, 0x3c8: 0x0008, 0x3c9: 0xe01d, 0x3ca: 0x0008, 0x3cb: 0xe03d,
+ 0x3cc: 0x0008, 0x3cd: 0xe01d, 0x3ce: 0x0008, 0x3cf: 0x0008, 0x3d0: 0xe00d, 0x3d1: 0x0008,
+ 0x3d2: 0xe00d, 0x3d3: 0x0008, 0x3d4: 0xe00d, 0x3d5: 0x0008, 0x3d6: 0xe00d, 0x3d7: 0x0008,
+ 0x3d8: 0xe00d, 0x3d9: 0x0008, 0x3da: 0xe00d, 0x3db: 0x0008, 0x3dc: 0xe00d, 0x3dd: 0x0008,
+ 0x3de: 0xe00d, 0x3df: 0x0008, 0x3e0: 0xe00d, 0x3e1: 0x0008, 0x3e2: 0xe00d, 0x3e3: 0x0008,
+ 0x3e4: 0xe00d, 0x3e5: 0x0008, 0x3e6: 0xe00d, 0x3e7: 0x0008, 0x3e8: 0xe00d, 0x3e9: 0x0008,
+ 0x3ea: 0xe00d, 0x3eb: 0x0008, 0x3ec: 0xe00d, 0x3ed: 0x0008, 0x3ee: 0xe00d, 0x3ef: 0x0008,
+ 0x3f0: 0xe00d, 0x3f1: 0x0008, 0x3f2: 0xe00d, 0x3f3: 0x0008, 0x3f4: 0xe00d, 0x3f5: 0x0008,
+ 0x3f6: 0xe00d, 0x3f7: 0x0008, 0x3f8: 0xe00d, 0x3f9: 0x0008, 0x3fa: 0xe00d, 0x3fb: 0x0008,
+ 0x3fc: 0xe00d, 0x3fd: 0x0008, 0x3fe: 0xe00d, 0x3ff: 0x0008,
+ // Block 0x10, offset 0x400
+ 0x400: 0xe00d, 0x401: 0x0008, 0x402: 0xe00d, 0x403: 0x0008, 0x404: 0xe00d, 0x405: 0x0008,
+ 0x406: 0xe00d, 0x407: 0x0008, 0x408: 0xe00d, 0x409: 0x0008, 0x40a: 0xe00d, 0x40b: 0x0008,
+ 0x40c: 0xe00d, 0x40d: 0x0008, 0x40e: 0xe00d, 0x40f: 0x0008, 0x410: 0xe00d, 0x411: 0x0008,
+ 0x412: 0xe00d, 0x413: 0x0008, 0x414: 0xe00d, 0x415: 0x0008, 0x416: 0xe00d, 0x417: 0x0008,
+ 0x418: 0xe00d, 0x419: 0x0008, 0x41a: 0xe00d, 0x41b: 0x0008, 0x41c: 0xe00d, 0x41d: 0x0008,
+ 0x41e: 0xe00d, 0x41f: 0x0008, 0x420: 0xe00d, 0x421: 0x0008, 0x422: 0xe00d, 0x423: 0x0008,
+ 0x424: 0xe00d, 0x425: 0x0008, 0x426: 0xe00d, 0x427: 0x0008, 0x428: 0xe00d, 0x429: 0x0008,
+ 0x42a: 0xe00d, 0x42b: 0x0008, 0x42c: 0xe00d, 0x42d: 0x0008, 0x42e: 0xe00d, 0x42f: 0x0008,
+ 0x430: 0x0040, 0x431: 0x03f5, 0x432: 0x03f5, 0x433: 0x03f5, 0x434: 0x03f5, 0x435: 0x03f5,
+ 0x436: 0x03f5, 0x437: 0x03f5, 0x438: 0x03f5, 0x439: 0x03f5, 0x43a: 0x03f5, 0x43b: 0x03f5,
+ 0x43c: 0x03f5, 0x43d: 0x03f5, 0x43e: 0x03f5, 0x43f: 0x03f5,
+ // Block 0x11, offset 0x440
+ 0x440: 0x0040, 0x441: 0x0040, 0x442: 0x0040, 0x443: 0x0040, 0x444: 0x0040, 0x445: 0x0040,
+ 0x446: 0x0018, 0x447: 0x0018, 0x448: 0x0018, 0x449: 0x0018, 0x44a: 0x0018, 0x44b: 0x0018,
+ 0x44c: 0x0018, 0x44d: 0x0018, 0x44e: 0x0018, 0x44f: 0x0018, 0x450: 0x1308, 0x451: 0x1308,
+ 0x452: 0x1308, 0x453: 0x1308, 0x454: 0x1308, 0x455: 0x1308, 0x456: 0x1308, 0x457: 0x1308,
+ 0x458: 0x1308, 0x459: 0x1308, 0x45a: 0x1308, 0x45b: 0x0018, 0x45c: 0x0340, 0x45d: 0x0040,
+ 0x45e: 0x0018, 0x45f: 0x0018, 0x460: 0x0208, 0x461: 0x0008, 0x462: 0x0408, 0x463: 0x0408,
+ 0x464: 0x0408, 0x465: 0x0408, 0x466: 0x0208, 0x467: 0x0408, 0x468: 0x0208, 0x469: 0x0408,
+ 0x46a: 0x0208, 0x46b: 0x0208, 0x46c: 0x0208, 0x46d: 0x0208, 0x46e: 0x0208, 0x46f: 0x0408,
+ 0x470: 0x0408, 0x471: 0x0408, 0x472: 0x0408, 0x473: 0x0208, 0x474: 0x0208, 0x475: 0x0208,
+ 0x476: 0x0208, 0x477: 0x0208, 0x478: 0x0208, 0x479: 0x0208, 0x47a: 0x0208, 0x47b: 0x0208,
+ 0x47c: 0x0208, 0x47d: 0x0208, 0x47e: 0x0208, 0x47f: 0x0208,
+ // Block 0x12, offset 0x480
+ 0x480: 0x0408, 0x481: 0x0208, 0x482: 0x0208, 0x483: 0x0408, 0x484: 0x0408, 0x485: 0x0408,
+ 0x486: 0x0408, 0x487: 0x0408, 0x488: 0x0408, 0x489: 0x0408, 0x48a: 0x0408, 0x48b: 0x0408,
+ 0x48c: 0x0208, 0x48d: 0x0408, 0x48e: 0x0208, 0x48f: 0x0408, 0x490: 0x0208, 0x491: 0x0208,
+ 0x492: 0x0408, 0x493: 0x0408, 0x494: 0x0018, 0x495: 0x0408, 0x496: 0x1308, 0x497: 0x1308,
+ 0x498: 0x1308, 0x499: 0x1308, 0x49a: 0x1308, 0x49b: 0x1308, 0x49c: 0x1308, 0x49d: 0x0040,
+ 0x49e: 0x0018, 0x49f: 0x1308, 0x4a0: 0x1308, 0x4a1: 0x1308, 0x4a2: 0x1308, 0x4a3: 0x1308,
+ 0x4a4: 0x1308, 0x4a5: 0x0008, 0x4a6: 0x0008, 0x4a7: 0x1308, 0x4a8: 0x1308, 0x4a9: 0x0018,
+ 0x4aa: 0x1308, 0x4ab: 0x1308, 0x4ac: 0x1308, 0x4ad: 0x1308, 0x4ae: 0x0408, 0x4af: 0x0408,
+ 0x4b0: 0x0008, 0x4b1: 0x0008, 0x4b2: 0x0008, 0x4b3: 0x0008, 0x4b4: 0x0008, 0x4b5: 0x0008,
+ 0x4b6: 0x0008, 0x4b7: 0x0008, 0x4b8: 0x0008, 0x4b9: 0x0008, 0x4ba: 0x0208, 0x4bb: 0x0208,
+ 0x4bc: 0x0208, 0x4bd: 0x0008, 0x4be: 0x0008, 0x4bf: 0x0208,
+ // Block 0x13, offset 0x4c0
+ 0x4c0: 0x0018, 0x4c1: 0x0018, 0x4c2: 0x0018, 0x4c3: 0x0018, 0x4c4: 0x0018, 0x4c5: 0x0018,
+ 0x4c6: 0x0018, 0x4c7: 0x0018, 0x4c8: 0x0018, 0x4c9: 0x0018, 0x4ca: 0x0018, 0x4cb: 0x0018,
+ 0x4cc: 0x0018, 0x4cd: 0x0018, 0x4ce: 0x0040, 0x4cf: 0x0340, 0x4d0: 0x0408, 0x4d1: 0x1308,
+ 0x4d2: 0x0208, 0x4d3: 0x0208, 0x4d4: 0x0208, 0x4d5: 0x0408, 0x4d6: 0x0408, 0x4d7: 0x0408,
+ 0x4d8: 0x0408, 0x4d9: 0x0408, 0x4da: 0x0208, 0x4db: 0x0208, 0x4dc: 0x0208, 0x4dd: 0x0208,
+ 0x4de: 0x0408, 0x4df: 0x0208, 0x4e0: 0x0208, 0x4e1: 0x0208, 0x4e2: 0x0208, 0x4e3: 0x0208,
+ 0x4e4: 0x0208, 0x4e5: 0x0208, 0x4e6: 0x0208, 0x4e7: 0x0208, 0x4e8: 0x0408, 0x4e9: 0x0208,
+ 0x4ea: 0x0408, 0x4eb: 0x0208, 0x4ec: 0x0408, 0x4ed: 0x0208, 0x4ee: 0x0208, 0x4ef: 0x0408,
+ 0x4f0: 0x1308, 0x4f1: 0x1308, 0x4f2: 0x1308, 0x4f3: 0x1308, 0x4f4: 0x1308, 0x4f5: 0x1308,
+ 0x4f6: 0x1308, 0x4f7: 0x1308, 0x4f8: 0x1308, 0x4f9: 0x1308, 0x4fa: 0x1308, 0x4fb: 0x1308,
+ 0x4fc: 0x1308, 0x4fd: 0x1308, 0x4fe: 0x1308, 0x4ff: 0x1308,
+ // Block 0x14, offset 0x500
+ 0x500: 0x1008, 0x501: 0x1308, 0x502: 0x1308, 0x503: 0x1308, 0x504: 0x1308, 0x505: 0x1308,
+ 0x506: 0x1308, 0x507: 0x1308, 0x508: 0x1308, 0x509: 0x1008, 0x50a: 0x1008, 0x50b: 0x1008,
+ 0x50c: 0x1008, 0x50d: 0x1b08, 0x50e: 0x1008, 0x50f: 0x1008, 0x510: 0x0008, 0x511: 0x1308,
+ 0x512: 0x1308, 0x513: 0x1308, 0x514: 0x1308, 0x515: 0x1308, 0x516: 0x1308, 0x517: 0x1308,
+ 0x518: 0x04c9, 0x519: 0x0501, 0x51a: 0x0539, 0x51b: 0x0571, 0x51c: 0x05a9, 0x51d: 0x05e1,
+ 0x51e: 0x0619, 0x51f: 0x0651, 0x520: 0x0008, 0x521: 0x0008, 0x522: 0x1308, 0x523: 0x1308,
+ 0x524: 0x0018, 0x525: 0x0018, 0x526: 0x0008, 0x527: 0x0008, 0x528: 0x0008, 0x529: 0x0008,
+ 0x52a: 0x0008, 0x52b: 0x0008, 0x52c: 0x0008, 0x52d: 0x0008, 0x52e: 0x0008, 0x52f: 0x0008,
+ 0x530: 0x0018, 0x531: 0x0008, 0x532: 0x0008, 0x533: 0x0008, 0x534: 0x0008, 0x535: 0x0008,
+ 0x536: 0x0008, 0x537: 0x0008, 0x538: 0x0008, 0x539: 0x0008, 0x53a: 0x0008, 0x53b: 0x0008,
+ 0x53c: 0x0008, 0x53d: 0x0008, 0x53e: 0x0008, 0x53f: 0x0008,
+ // Block 0x15, offset 0x540
+ 0x540: 0x0008, 0x541: 0x1308, 0x542: 0x1008, 0x543: 0x1008, 0x544: 0x0040, 0x545: 0x0008,
+ 0x546: 0x0008, 0x547: 0x0008, 0x548: 0x0008, 0x549: 0x0008, 0x54a: 0x0008, 0x54b: 0x0008,
+ 0x54c: 0x0008, 0x54d: 0x0040, 0x54e: 0x0040, 0x54f: 0x0008, 0x550: 0x0008, 0x551: 0x0040,
+ 0x552: 0x0040, 0x553: 0x0008, 0x554: 0x0008, 0x555: 0x0008, 0x556: 0x0008, 0x557: 0x0008,
+ 0x558: 0x0008, 0x559: 0x0008, 0x55a: 0x0008, 0x55b: 0x0008, 0x55c: 0x0008, 0x55d: 0x0008,
+ 0x55e: 0x0008, 0x55f: 0x0008, 0x560: 0x0008, 0x561: 0x0008, 0x562: 0x0008, 0x563: 0x0008,
+ 0x564: 0x0008, 0x565: 0x0008, 0x566: 0x0008, 0x567: 0x0008, 0x568: 0x0008, 0x569: 0x0040,
+ 0x56a: 0x0008, 0x56b: 0x0008, 0x56c: 0x0008, 0x56d: 0x0008, 0x56e: 0x0008, 0x56f: 0x0008,
+ 0x570: 0x0008, 0x571: 0x0040, 0x572: 0x0008, 0x573: 0x0040, 0x574: 0x0040, 0x575: 0x0040,
+ 0x576: 0x0008, 0x577: 0x0008, 0x578: 0x0008, 0x579: 0x0008, 0x57a: 0x0040, 0x57b: 0x0040,
+ 0x57c: 0x1308, 0x57d: 0x0008, 0x57e: 0x1008, 0x57f: 0x1008,
+ // Block 0x16, offset 0x580
+ 0x580: 0x1008, 0x581: 0x1308, 0x582: 0x1308, 0x583: 0x1308, 0x584: 0x1308, 0x585: 0x0040,
+ 0x586: 0x0040, 0x587: 0x1008, 0x588: 0x1008, 0x589: 0x0040, 0x58a: 0x0040, 0x58b: 0x1008,
+ 0x58c: 0x1008, 0x58d: 0x1b08, 0x58e: 0x0008, 0x58f: 0x0040, 0x590: 0x0040, 0x591: 0x0040,
+ 0x592: 0x0040, 0x593: 0x0040, 0x594: 0x0040, 0x595: 0x0040, 0x596: 0x0040, 0x597: 0x1008,
+ 0x598: 0x0040, 0x599: 0x0040, 0x59a: 0x0040, 0x59b: 0x0040, 0x59c: 0x0689, 0x59d: 0x06c1,
+ 0x59e: 0x0040, 0x59f: 0x06f9, 0x5a0: 0x0008, 0x5a1: 0x0008, 0x5a2: 0x1308, 0x5a3: 0x1308,
+ 0x5a4: 0x0040, 0x5a5: 0x0040, 0x5a6: 0x0008, 0x5a7: 0x0008, 0x5a8: 0x0008, 0x5a9: 0x0008,
+ 0x5aa: 0x0008, 0x5ab: 0x0008, 0x5ac: 0x0008, 0x5ad: 0x0008, 0x5ae: 0x0008, 0x5af: 0x0008,
+ 0x5b0: 0x0008, 0x5b1: 0x0008, 0x5b2: 0x0018, 0x5b3: 0x0018, 0x5b4: 0x0018, 0x5b5: 0x0018,
+ 0x5b6: 0x0018, 0x5b7: 0x0018, 0x5b8: 0x0018, 0x5b9: 0x0018, 0x5ba: 0x0018, 0x5bb: 0x0018,
+ 0x5bc: 0x0040, 0x5bd: 0x0040, 0x5be: 0x0040, 0x5bf: 0x0040,
+ // Block 0x17, offset 0x5c0
+ 0x5c0: 0x0040, 0x5c1: 0x1308, 0x5c2: 0x1308, 0x5c3: 0x1008, 0x5c4: 0x0040, 0x5c5: 0x0008,
+ 0x5c6: 0x0008, 0x5c7: 0x0008, 0x5c8: 0x0008, 0x5c9: 0x0008, 0x5ca: 0x0008, 0x5cb: 0x0040,
+ 0x5cc: 0x0040, 0x5cd: 0x0040, 0x5ce: 0x0040, 0x5cf: 0x0008, 0x5d0: 0x0008, 0x5d1: 0x0040,
+ 0x5d2: 0x0040, 0x5d3: 0x0008, 0x5d4: 0x0008, 0x5d5: 0x0008, 0x5d6: 0x0008, 0x5d7: 0x0008,
+ 0x5d8: 0x0008, 0x5d9: 0x0008, 0x5da: 0x0008, 0x5db: 0x0008, 0x5dc: 0x0008, 0x5dd: 0x0008,
+ 0x5de: 0x0008, 0x5df: 0x0008, 0x5e0: 0x0008, 0x5e1: 0x0008, 0x5e2: 0x0008, 0x5e3: 0x0008,
+ 0x5e4: 0x0008, 0x5e5: 0x0008, 0x5e6: 0x0008, 0x5e7: 0x0008, 0x5e8: 0x0008, 0x5e9: 0x0040,
+ 0x5ea: 0x0008, 0x5eb: 0x0008, 0x5ec: 0x0008, 0x5ed: 0x0008, 0x5ee: 0x0008, 0x5ef: 0x0008,
+ 0x5f0: 0x0008, 0x5f1: 0x0040, 0x5f2: 0x0008, 0x5f3: 0x0731, 0x5f4: 0x0040, 0x5f5: 0x0008,
+ 0x5f6: 0x0769, 0x5f7: 0x0040, 0x5f8: 0x0008, 0x5f9: 0x0008, 0x5fa: 0x0040, 0x5fb: 0x0040,
+ 0x5fc: 0x1308, 0x5fd: 0x0040, 0x5fe: 0x1008, 0x5ff: 0x1008,
+ // Block 0x18, offset 0x600
+ 0x600: 0x1008, 0x601: 0x1308, 0x602: 0x1308, 0x603: 0x0040, 0x604: 0x0040, 0x605: 0x0040,
+ 0x606: 0x0040, 0x607: 0x1308, 0x608: 0x1308, 0x609: 0x0040, 0x60a: 0x0040, 0x60b: 0x1308,
+ 0x60c: 0x1308, 0x60d: 0x1b08, 0x60e: 0x0040, 0x60f: 0x0040, 0x610: 0x0040, 0x611: 0x1308,
+ 0x612: 0x0040, 0x613: 0x0040, 0x614: 0x0040, 0x615: 0x0040, 0x616: 0x0040, 0x617: 0x0040,
+ 0x618: 0x0040, 0x619: 0x07a1, 0x61a: 0x07d9, 0x61b: 0x0811, 0x61c: 0x0008, 0x61d: 0x0040,
+ 0x61e: 0x0849, 0x61f: 0x0040, 0x620: 0x0040, 0x621: 0x0040, 0x622: 0x0040, 0x623: 0x0040,
+ 0x624: 0x0040, 0x625: 0x0040, 0x626: 0x0008, 0x627: 0x0008, 0x628: 0x0008, 0x629: 0x0008,
+ 0x62a: 0x0008, 0x62b: 0x0008, 0x62c: 0x0008, 0x62d: 0x0008, 0x62e: 0x0008, 0x62f: 0x0008,
+ 0x630: 0x1308, 0x631: 0x1308, 0x632: 0x0008, 0x633: 0x0008, 0x634: 0x0008, 0x635: 0x1308,
+ 0x636: 0x0040, 0x637: 0x0040, 0x638: 0x0040, 0x639: 0x0040, 0x63a: 0x0040, 0x63b: 0x0040,
+ 0x63c: 0x0040, 0x63d: 0x0040, 0x63e: 0x0040, 0x63f: 0x0040,
+ // Block 0x19, offset 0x640
+ 0x640: 0x0040, 0x641: 0x1308, 0x642: 0x1308, 0x643: 0x1008, 0x644: 0x0040, 0x645: 0x0008,
+ 0x646: 0x0008, 0x647: 0x0008, 0x648: 0x0008, 0x649: 0x0008, 0x64a: 0x0008, 0x64b: 0x0008,
+ 0x64c: 0x0008, 0x64d: 0x0008, 0x64e: 0x0040, 0x64f: 0x0008, 0x650: 0x0008, 0x651: 0x0008,
+ 0x652: 0x0040, 0x653: 0x0008, 0x654: 0x0008, 0x655: 0x0008, 0x656: 0x0008, 0x657: 0x0008,
+ 0x658: 0x0008, 0x659: 0x0008, 0x65a: 0x0008, 0x65b: 0x0008, 0x65c: 0x0008, 0x65d: 0x0008,
+ 0x65e: 0x0008, 0x65f: 0x0008, 0x660: 0x0008, 0x661: 0x0008, 0x662: 0x0008, 0x663: 0x0008,
+ 0x664: 0x0008, 0x665: 0x0008, 0x666: 0x0008, 0x667: 0x0008, 0x668: 0x0008, 0x669: 0x0040,
+ 0x66a: 0x0008, 0x66b: 0x0008, 0x66c: 0x0008, 0x66d: 0x0008, 0x66e: 0x0008, 0x66f: 0x0008,
+ 0x670: 0x0008, 0x671: 0x0040, 0x672: 0x0008, 0x673: 0x0008, 0x674: 0x0040, 0x675: 0x0008,
+ 0x676: 0x0008, 0x677: 0x0008, 0x678: 0x0008, 0x679: 0x0008, 0x67a: 0x0040, 0x67b: 0x0040,
+ 0x67c: 0x1308, 0x67d: 0x0008, 0x67e: 0x1008, 0x67f: 0x1008,
+ // Block 0x1a, offset 0x680
+ 0x680: 0x1008, 0x681: 0x1308, 0x682: 0x1308, 0x683: 0x1308, 0x684: 0x1308, 0x685: 0x1308,
+ 0x686: 0x0040, 0x687: 0x1308, 0x688: 0x1308, 0x689: 0x1008, 0x68a: 0x0040, 0x68b: 0x1008,
+ 0x68c: 0x1008, 0x68d: 0x1b08, 0x68e: 0x0040, 0x68f: 0x0040, 0x690: 0x0008, 0x691: 0x0040,
+ 0x692: 0x0040, 0x693: 0x0040, 0x694: 0x0040, 0x695: 0x0040, 0x696: 0x0040, 0x697: 0x0040,
+ 0x698: 0x0040, 0x699: 0x0040, 0x69a: 0x0040, 0x69b: 0x0040, 0x69c: 0x0040, 0x69d: 0x0040,
+ 0x69e: 0x0040, 0x69f: 0x0040, 0x6a0: 0x0008, 0x6a1: 0x0008, 0x6a2: 0x1308, 0x6a3: 0x1308,
+ 0x6a4: 0x0040, 0x6a5: 0x0040, 0x6a6: 0x0008, 0x6a7: 0x0008, 0x6a8: 0x0008, 0x6a9: 0x0008,
+ 0x6aa: 0x0008, 0x6ab: 0x0008, 0x6ac: 0x0008, 0x6ad: 0x0008, 0x6ae: 0x0008, 0x6af: 0x0008,
+ 0x6b0: 0x0018, 0x6b1: 0x0018, 0x6b2: 0x0040, 0x6b3: 0x0040, 0x6b4: 0x0040, 0x6b5: 0x0040,
+ 0x6b6: 0x0040, 0x6b7: 0x0040, 0x6b8: 0x0040, 0x6b9: 0x0008, 0x6ba: 0x0040, 0x6bb: 0x0040,
+ 0x6bc: 0x0040, 0x6bd: 0x0040, 0x6be: 0x0040, 0x6bf: 0x0040,
+ // Block 0x1b, offset 0x6c0
+ 0x6c0: 0x0040, 0x6c1: 0x1308, 0x6c2: 0x1008, 0x6c3: 0x1008, 0x6c4: 0x0040, 0x6c5: 0x0008,
+ 0x6c6: 0x0008, 0x6c7: 0x0008, 0x6c8: 0x0008, 0x6c9: 0x0008, 0x6ca: 0x0008, 0x6cb: 0x0008,
+ 0x6cc: 0x0008, 0x6cd: 0x0040, 0x6ce: 0x0040, 0x6cf: 0x0008, 0x6d0: 0x0008, 0x6d1: 0x0040,
+ 0x6d2: 0x0040, 0x6d3: 0x0008, 0x6d4: 0x0008, 0x6d5: 0x0008, 0x6d6: 0x0008, 0x6d7: 0x0008,
+ 0x6d8: 0x0008, 0x6d9: 0x0008, 0x6da: 0x0008, 0x6db: 0x0008, 0x6dc: 0x0008, 0x6dd: 0x0008,
+ 0x6de: 0x0008, 0x6df: 0x0008, 0x6e0: 0x0008, 0x6e1: 0x0008, 0x6e2: 0x0008, 0x6e3: 0x0008,
+ 0x6e4: 0x0008, 0x6e5: 0x0008, 0x6e6: 0x0008, 0x6e7: 0x0008, 0x6e8: 0x0008, 0x6e9: 0x0040,
+ 0x6ea: 0x0008, 0x6eb: 0x0008, 0x6ec: 0x0008, 0x6ed: 0x0008, 0x6ee: 0x0008, 0x6ef: 0x0008,
+ 0x6f0: 0x0008, 0x6f1: 0x0040, 0x6f2: 0x0008, 0x6f3: 0x0008, 0x6f4: 0x0040, 0x6f5: 0x0008,
+ 0x6f6: 0x0008, 0x6f7: 0x0008, 0x6f8: 0x0008, 0x6f9: 0x0008, 0x6fa: 0x0040, 0x6fb: 0x0040,
+ 0x6fc: 0x1308, 0x6fd: 0x0008, 0x6fe: 0x1008, 0x6ff: 0x1308,
+ // Block 0x1c, offset 0x700
+ 0x700: 0x1008, 0x701: 0x1308, 0x702: 0x1308, 0x703: 0x1308, 0x704: 0x1308, 0x705: 0x0040,
+ 0x706: 0x0040, 0x707: 0x1008, 0x708: 0x1008, 0x709: 0x0040, 0x70a: 0x0040, 0x70b: 0x1008,
+ 0x70c: 0x1008, 0x70d: 0x1b08, 0x70e: 0x0040, 0x70f: 0x0040, 0x710: 0x0040, 0x711: 0x0040,
+ 0x712: 0x0040, 0x713: 0x0040, 0x714: 0x0040, 0x715: 0x0040, 0x716: 0x1308, 0x717: 0x1008,
+ 0x718: 0x0040, 0x719: 0x0040, 0x71a: 0x0040, 0x71b: 0x0040, 0x71c: 0x0881, 0x71d: 0x08b9,
+ 0x71e: 0x0040, 0x71f: 0x0008, 0x720: 0x0008, 0x721: 0x0008, 0x722: 0x1308, 0x723: 0x1308,
+ 0x724: 0x0040, 0x725: 0x0040, 0x726: 0x0008, 0x727: 0x0008, 0x728: 0x0008, 0x729: 0x0008,
+ 0x72a: 0x0008, 0x72b: 0x0008, 0x72c: 0x0008, 0x72d: 0x0008, 0x72e: 0x0008, 0x72f: 0x0008,
+ 0x730: 0x0018, 0x731: 0x0008, 0x732: 0x0018, 0x733: 0x0018, 0x734: 0x0018, 0x735: 0x0018,
+ 0x736: 0x0018, 0x737: 0x0018, 0x738: 0x0040, 0x739: 0x0040, 0x73a: 0x0040, 0x73b: 0x0040,
+ 0x73c: 0x0040, 0x73d: 0x0040, 0x73e: 0x0040, 0x73f: 0x0040,
+ // Block 0x1d, offset 0x740
+ 0x740: 0x0040, 0x741: 0x0040, 0x742: 0x1308, 0x743: 0x0008, 0x744: 0x0040, 0x745: 0x0008,
+ 0x746: 0x0008, 0x747: 0x0008, 0x748: 0x0008, 0x749: 0x0008, 0x74a: 0x0008, 0x74b: 0x0040,
+ 0x74c: 0x0040, 0x74d: 0x0040, 0x74e: 0x0008, 0x74f: 0x0008, 0x750: 0x0008, 0x751: 0x0040,
+ 0x752: 0x0008, 0x753: 0x0008, 0x754: 0x0008, 0x755: 0x0008, 0x756: 0x0040, 0x757: 0x0040,
+ 0x758: 0x0040, 0x759: 0x0008, 0x75a: 0x0008, 0x75b: 0x0040, 0x75c: 0x0008, 0x75d: 0x0040,
+ 0x75e: 0x0008, 0x75f: 0x0008, 0x760: 0x0040, 0x761: 0x0040, 0x762: 0x0040, 0x763: 0x0008,
+ 0x764: 0x0008, 0x765: 0x0040, 0x766: 0x0040, 0x767: 0x0040, 0x768: 0x0008, 0x769: 0x0008,
+ 0x76a: 0x0008, 0x76b: 0x0040, 0x76c: 0x0040, 0x76d: 0x0040, 0x76e: 0x0008, 0x76f: 0x0008,
+ 0x770: 0x0008, 0x771: 0x0008, 0x772: 0x0008, 0x773: 0x0008, 0x774: 0x0008, 0x775: 0x0008,
+ 0x776: 0x0008, 0x777: 0x0008, 0x778: 0x0008, 0x779: 0x0008, 0x77a: 0x0040, 0x77b: 0x0040,
+ 0x77c: 0x0040, 0x77d: 0x0040, 0x77e: 0x1008, 0x77f: 0x1008,
+ // Block 0x1e, offset 0x780
+ 0x780: 0x1308, 0x781: 0x1008, 0x782: 0x1008, 0x783: 0x1008, 0x784: 0x1008, 0x785: 0x0040,
+ 0x786: 0x1308, 0x787: 0x1308, 0x788: 0x1308, 0x789: 0x0040, 0x78a: 0x1308, 0x78b: 0x1308,
+ 0x78c: 0x1308, 0x78d: 0x1b08, 0x78e: 0x0040, 0x78f: 0x0040, 0x790: 0x0040, 0x791: 0x0040,
+ 0x792: 0x0040, 0x793: 0x0040, 0x794: 0x0040, 0x795: 0x1308, 0x796: 0x1308, 0x797: 0x0040,
+ 0x798: 0x0008, 0x799: 0x0008, 0x79a: 0x0008, 0x79b: 0x0040, 0x79c: 0x0040, 0x79d: 0x0040,
+ 0x79e: 0x0040, 0x79f: 0x0040, 0x7a0: 0x0008, 0x7a1: 0x0008, 0x7a2: 0x1308, 0x7a3: 0x1308,
+ 0x7a4: 0x0040, 0x7a5: 0x0040, 0x7a6: 0x0008, 0x7a7: 0x0008, 0x7a8: 0x0008, 0x7a9: 0x0008,
+ 0x7aa: 0x0008, 0x7ab: 0x0008, 0x7ac: 0x0008, 0x7ad: 0x0008, 0x7ae: 0x0008, 0x7af: 0x0008,
+ 0x7b0: 0x0040, 0x7b1: 0x0040, 0x7b2: 0x0040, 0x7b3: 0x0040, 0x7b4: 0x0040, 0x7b5: 0x0040,
+ 0x7b6: 0x0040, 0x7b7: 0x0040, 0x7b8: 0x0018, 0x7b9: 0x0018, 0x7ba: 0x0018, 0x7bb: 0x0018,
+ 0x7bc: 0x0018, 0x7bd: 0x0018, 0x7be: 0x0018, 0x7bf: 0x0018,
+ // Block 0x1f, offset 0x7c0
+ 0x7c0: 0x0008, 0x7c1: 0x1308, 0x7c2: 0x1008, 0x7c3: 0x1008, 0x7c4: 0x0040, 0x7c5: 0x0008,
+ 0x7c6: 0x0008, 0x7c7: 0x0008, 0x7c8: 0x0008, 0x7c9: 0x0008, 0x7ca: 0x0008, 0x7cb: 0x0008,
+ 0x7cc: 0x0008, 0x7cd: 0x0040, 0x7ce: 0x0008, 0x7cf: 0x0008, 0x7d0: 0x0008, 0x7d1: 0x0040,
+ 0x7d2: 0x0008, 0x7d3: 0x0008, 0x7d4: 0x0008, 0x7d5: 0x0008, 0x7d6: 0x0008, 0x7d7: 0x0008,
+ 0x7d8: 0x0008, 0x7d9: 0x0008, 0x7da: 0x0008, 0x7db: 0x0008, 0x7dc: 0x0008, 0x7dd: 0x0008,
+ 0x7de: 0x0008, 0x7df: 0x0008, 0x7e0: 0x0008, 0x7e1: 0x0008, 0x7e2: 0x0008, 0x7e3: 0x0008,
+ 0x7e4: 0x0008, 0x7e5: 0x0008, 0x7e6: 0x0008, 0x7e7: 0x0008, 0x7e8: 0x0008, 0x7e9: 0x0040,
+ 0x7ea: 0x0008, 0x7eb: 0x0008, 0x7ec: 0x0008, 0x7ed: 0x0008, 0x7ee: 0x0008, 0x7ef: 0x0008,
+ 0x7f0: 0x0008, 0x7f1: 0x0008, 0x7f2: 0x0008, 0x7f3: 0x0008, 0x7f4: 0x0040, 0x7f5: 0x0008,
+ 0x7f6: 0x0008, 0x7f7: 0x0008, 0x7f8: 0x0008, 0x7f9: 0x0008, 0x7fa: 0x0040, 0x7fb: 0x0040,
+ 0x7fc: 0x1308, 0x7fd: 0x0008, 0x7fe: 0x1008, 0x7ff: 0x1308,
+ // Block 0x20, offset 0x800
+ 0x800: 0x1008, 0x801: 0x1008, 0x802: 0x1008, 0x803: 0x1008, 0x804: 0x1008, 0x805: 0x0040,
+ 0x806: 0x1308, 0x807: 0x1008, 0x808: 0x1008, 0x809: 0x0040, 0x80a: 0x1008, 0x80b: 0x1008,
+ 0x80c: 0x1308, 0x80d: 0x1b08, 0x80e: 0x0040, 0x80f: 0x0040, 0x810: 0x0040, 0x811: 0x0040,
+ 0x812: 0x0040, 0x813: 0x0040, 0x814: 0x0040, 0x815: 0x1008, 0x816: 0x1008, 0x817: 0x0040,
+ 0x818: 0x0040, 0x819: 0x0040, 0x81a: 0x0040, 0x81b: 0x0040, 0x81c: 0x0040, 0x81d: 0x0040,
+ 0x81e: 0x0008, 0x81f: 0x0040, 0x820: 0x0008, 0x821: 0x0008, 0x822: 0x1308, 0x823: 0x1308,
+ 0x824: 0x0040, 0x825: 0x0040, 0x826: 0x0008, 0x827: 0x0008, 0x828: 0x0008, 0x829: 0x0008,
+ 0x82a: 0x0008, 0x82b: 0x0008, 0x82c: 0x0008, 0x82d: 0x0008, 0x82e: 0x0008, 0x82f: 0x0008,
+ 0x830: 0x0040, 0x831: 0x0008, 0x832: 0x0008, 0x833: 0x0040, 0x834: 0x0040, 0x835: 0x0040,
+ 0x836: 0x0040, 0x837: 0x0040, 0x838: 0x0040, 0x839: 0x0040, 0x83a: 0x0040, 0x83b: 0x0040,
+ 0x83c: 0x0040, 0x83d: 0x0040, 0x83e: 0x0040, 0x83f: 0x0040,
+ // Block 0x21, offset 0x840
+ 0x840: 0x1008, 0x841: 0x1308, 0x842: 0x1308, 0x843: 0x1308, 0x844: 0x1308, 0x845: 0x0040,
+ 0x846: 0x1008, 0x847: 0x1008, 0x848: 0x1008, 0x849: 0x0040, 0x84a: 0x1008, 0x84b: 0x1008,
+ 0x84c: 0x1008, 0x84d: 0x1b08, 0x84e: 0x0008, 0x84f: 0x0018, 0x850: 0x0040, 0x851: 0x0040,
+ 0x852: 0x0040, 0x853: 0x0040, 0x854: 0x0008, 0x855: 0x0008, 0x856: 0x0008, 0x857: 0x1008,
+ 0x858: 0x0018, 0x859: 0x0018, 0x85a: 0x0018, 0x85b: 0x0018, 0x85c: 0x0018, 0x85d: 0x0018,
+ 0x85e: 0x0018, 0x85f: 0x0008, 0x860: 0x0008, 0x861: 0x0008, 0x862: 0x1308, 0x863: 0x1308,
+ 0x864: 0x0040, 0x865: 0x0040, 0x866: 0x0008, 0x867: 0x0008, 0x868: 0x0008, 0x869: 0x0008,
+ 0x86a: 0x0008, 0x86b: 0x0008, 0x86c: 0x0008, 0x86d: 0x0008, 0x86e: 0x0008, 0x86f: 0x0008,
+ 0x870: 0x0018, 0x871: 0x0018, 0x872: 0x0018, 0x873: 0x0018, 0x874: 0x0018, 0x875: 0x0018,
+ 0x876: 0x0018, 0x877: 0x0018, 0x878: 0x0018, 0x879: 0x0018, 0x87a: 0x0008, 0x87b: 0x0008,
+ 0x87c: 0x0008, 0x87d: 0x0008, 0x87e: 0x0008, 0x87f: 0x0008,
+ // Block 0x22, offset 0x880
+ 0x880: 0x0040, 0x881: 0x0008, 0x882: 0x0008, 0x883: 0x0040, 0x884: 0x0008, 0x885: 0x0040,
+ 0x886: 0x0040, 0x887: 0x0008, 0x888: 0x0008, 0x889: 0x0040, 0x88a: 0x0008, 0x88b: 0x0040,
+ 0x88c: 0x0040, 0x88d: 0x0008, 0x88e: 0x0040, 0x88f: 0x0040, 0x890: 0x0040, 0x891: 0x0040,
+ 0x892: 0x0040, 0x893: 0x0040, 0x894: 0x0008, 0x895: 0x0008, 0x896: 0x0008, 0x897: 0x0008,
+ 0x898: 0x0040, 0x899: 0x0008, 0x89a: 0x0008, 0x89b: 0x0008, 0x89c: 0x0008, 0x89d: 0x0008,
+ 0x89e: 0x0008, 0x89f: 0x0008, 0x8a0: 0x0040, 0x8a1: 0x0008, 0x8a2: 0x0008, 0x8a3: 0x0008,
+ 0x8a4: 0x0040, 0x8a5: 0x0008, 0x8a6: 0x0040, 0x8a7: 0x0008, 0x8a8: 0x0040, 0x8a9: 0x0040,
+ 0x8aa: 0x0008, 0x8ab: 0x0008, 0x8ac: 0x0040, 0x8ad: 0x0008, 0x8ae: 0x0008, 0x8af: 0x0008,
+ 0x8b0: 0x0008, 0x8b1: 0x1308, 0x8b2: 0x0008, 0x8b3: 0x0929, 0x8b4: 0x1308, 0x8b5: 0x1308,
+ 0x8b6: 0x1308, 0x8b7: 0x1308, 0x8b8: 0x1308, 0x8b9: 0x1308, 0x8ba: 0x0040, 0x8bb: 0x1308,
+ 0x8bc: 0x1308, 0x8bd: 0x0008, 0x8be: 0x0040, 0x8bf: 0x0040,
+ // Block 0x23, offset 0x8c0
+ 0x8c0: 0x0008, 0x8c1: 0x0008, 0x8c2: 0x0008, 0x8c3: 0x09d1, 0x8c4: 0x0008, 0x8c5: 0x0008,
+ 0x8c6: 0x0008, 0x8c7: 0x0008, 0x8c8: 0x0040, 0x8c9: 0x0008, 0x8ca: 0x0008, 0x8cb: 0x0008,
+ 0x8cc: 0x0008, 0x8cd: 0x0a09, 0x8ce: 0x0008, 0x8cf: 0x0008, 0x8d0: 0x0008, 0x8d1: 0x0008,
+ 0x8d2: 0x0a41, 0x8d3: 0x0008, 0x8d4: 0x0008, 0x8d5: 0x0008, 0x8d6: 0x0008, 0x8d7: 0x0a79,
+ 0x8d8: 0x0008, 0x8d9: 0x0008, 0x8da: 0x0008, 0x8db: 0x0008, 0x8dc: 0x0ab1, 0x8dd: 0x0008,
+ 0x8de: 0x0008, 0x8df: 0x0008, 0x8e0: 0x0008, 0x8e1: 0x0008, 0x8e2: 0x0008, 0x8e3: 0x0008,
+ 0x8e4: 0x0008, 0x8e5: 0x0008, 0x8e6: 0x0008, 0x8e7: 0x0008, 0x8e8: 0x0008, 0x8e9: 0x0ae9,
+ 0x8ea: 0x0008, 0x8eb: 0x0008, 0x8ec: 0x0008, 0x8ed: 0x0040, 0x8ee: 0x0040, 0x8ef: 0x0040,
+ 0x8f0: 0x0040, 0x8f1: 0x1308, 0x8f2: 0x1308, 0x8f3: 0x0b21, 0x8f4: 0x1308, 0x8f5: 0x0b59,
+ 0x8f6: 0x0b91, 0x8f7: 0x0bc9, 0x8f8: 0x0c19, 0x8f9: 0x0c51, 0x8fa: 0x1308, 0x8fb: 0x1308,
+ 0x8fc: 0x1308, 0x8fd: 0x1308, 0x8fe: 0x1308, 0x8ff: 0x1008,
+ // Block 0x24, offset 0x900
+ 0x900: 0x1308, 0x901: 0x0ca1, 0x902: 0x1308, 0x903: 0x1308, 0x904: 0x1b08, 0x905: 0x0018,
+ 0x906: 0x1308, 0x907: 0x1308, 0x908: 0x0008, 0x909: 0x0008, 0x90a: 0x0008, 0x90b: 0x0008,
+ 0x90c: 0x0008, 0x90d: 0x1308, 0x90e: 0x1308, 0x90f: 0x1308, 0x910: 0x1308, 0x911: 0x1308,
+ 0x912: 0x1308, 0x913: 0x0cd9, 0x914: 0x1308, 0x915: 0x1308, 0x916: 0x1308, 0x917: 0x1308,
+ 0x918: 0x0040, 0x919: 0x1308, 0x91a: 0x1308, 0x91b: 0x1308, 0x91c: 0x1308, 0x91d: 0x0d11,
+ 0x91e: 0x1308, 0x91f: 0x1308, 0x920: 0x1308, 0x921: 0x1308, 0x922: 0x0d49, 0x923: 0x1308,
+ 0x924: 0x1308, 0x925: 0x1308, 0x926: 0x1308, 0x927: 0x0d81, 0x928: 0x1308, 0x929: 0x1308,
+ 0x92a: 0x1308, 0x92b: 0x1308, 0x92c: 0x0db9, 0x92d: 0x1308, 0x92e: 0x1308, 0x92f: 0x1308,
+ 0x930: 0x1308, 0x931: 0x1308, 0x932: 0x1308, 0x933: 0x1308, 0x934: 0x1308, 0x935: 0x1308,
+ 0x936: 0x1308, 0x937: 0x1308, 0x938: 0x1308, 0x939: 0x0df1, 0x93a: 0x1308, 0x93b: 0x1308,
+ 0x93c: 0x1308, 0x93d: 0x0040, 0x93e: 0x0018, 0x93f: 0x0018,
+ // Block 0x25, offset 0x940
+ 0x940: 0x0008, 0x941: 0x0008, 0x942: 0x0008, 0x943: 0x0008, 0x944: 0x0008, 0x945: 0x0008,
+ 0x946: 0x0008, 0x947: 0x0008, 0x948: 0x0008, 0x949: 0x0008, 0x94a: 0x0008, 0x94b: 0x0008,
+ 0x94c: 0x0008, 0x94d: 0x0008, 0x94e: 0x0008, 0x94f: 0x0008, 0x950: 0x0008, 0x951: 0x0008,
+ 0x952: 0x0008, 0x953: 0x0008, 0x954: 0x0008, 0x955: 0x0008, 0x956: 0x0008, 0x957: 0x0008,
+ 0x958: 0x0008, 0x959: 0x0008, 0x95a: 0x0008, 0x95b: 0x0008, 0x95c: 0x0008, 0x95d: 0x0008,
+ 0x95e: 0x0008, 0x95f: 0x0008, 0x960: 0x0008, 0x961: 0x0008, 0x962: 0x0008, 0x963: 0x0008,
+ 0x964: 0x0008, 0x965: 0x0008, 0x966: 0x0008, 0x967: 0x0008, 0x968: 0x0008, 0x969: 0x0008,
+ 0x96a: 0x0008, 0x96b: 0x0008, 0x96c: 0x0039, 0x96d: 0x0ed1, 0x96e: 0x0ee9, 0x96f: 0x0008,
+ 0x970: 0x0ef9, 0x971: 0x0f09, 0x972: 0x0f19, 0x973: 0x0f31, 0x974: 0x0249, 0x975: 0x0f41,
+ 0x976: 0x0259, 0x977: 0x0f51, 0x978: 0x0359, 0x979: 0x0f61, 0x97a: 0x0f71, 0x97b: 0x0008,
+ 0x97c: 0x00d9, 0x97d: 0x0f81, 0x97e: 0x0f99, 0x97f: 0x0269,
+ // Block 0x26, offset 0x980
+ 0x980: 0x0fa9, 0x981: 0x0fb9, 0x982: 0x0279, 0x983: 0x0039, 0x984: 0x0fc9, 0x985: 0x0fe1,
+ 0x986: 0x059d, 0x987: 0x0ee9, 0x988: 0x0ef9, 0x989: 0x0f09, 0x98a: 0x0ff9, 0x98b: 0x1011,
+ 0x98c: 0x1029, 0x98d: 0x0f31, 0x98e: 0x0008, 0x98f: 0x0f51, 0x990: 0x0f61, 0x991: 0x1041,
+ 0x992: 0x00d9, 0x993: 0x1059, 0x994: 0x05b5, 0x995: 0x05b5, 0x996: 0x0f99, 0x997: 0x0fa9,
+ 0x998: 0x0fb9, 0x999: 0x059d, 0x99a: 0x1071, 0x99b: 0x1089, 0x99c: 0x05cd, 0x99d: 0x1099,
+ 0x99e: 0x10b1, 0x99f: 0x10c9, 0x9a0: 0x10e1, 0x9a1: 0x10f9, 0x9a2: 0x0f41, 0x9a3: 0x0269,
+ 0x9a4: 0x0fb9, 0x9a5: 0x1089, 0x9a6: 0x1099, 0x9a7: 0x10b1, 0x9a8: 0x1111, 0x9a9: 0x10e1,
+ 0x9aa: 0x10f9, 0x9ab: 0x0008, 0x9ac: 0x0008, 0x9ad: 0x0008, 0x9ae: 0x0008, 0x9af: 0x0008,
+ 0x9b0: 0x0008, 0x9b1: 0x0008, 0x9b2: 0x0008, 0x9b3: 0x0008, 0x9b4: 0x0008, 0x9b5: 0x0008,
+ 0x9b6: 0x0008, 0x9b7: 0x0008, 0x9b8: 0x1129, 0x9b9: 0x0008, 0x9ba: 0x0008, 0x9bb: 0x0008,
+ 0x9bc: 0x0008, 0x9bd: 0x0008, 0x9be: 0x0008, 0x9bf: 0x0008,
+ // Block 0x27, offset 0x9c0
+ 0x9c0: 0x0008, 0x9c1: 0x0008, 0x9c2: 0x0008, 0x9c3: 0x0008, 0x9c4: 0x0008, 0x9c5: 0x0008,
+ 0x9c6: 0x0008, 0x9c7: 0x0008, 0x9c8: 0x0008, 0x9c9: 0x0008, 0x9ca: 0x0008, 0x9cb: 0x0008,
+ 0x9cc: 0x0008, 0x9cd: 0x0008, 0x9ce: 0x0008, 0x9cf: 0x0008, 0x9d0: 0x0008, 0x9d1: 0x0008,
+ 0x9d2: 0x0008, 0x9d3: 0x0008, 0x9d4: 0x0008, 0x9d5: 0x0008, 0x9d6: 0x0008, 0x9d7: 0x0008,
+ 0x9d8: 0x0008, 0x9d9: 0x0008, 0x9da: 0x0008, 0x9db: 0x1141, 0x9dc: 0x1159, 0x9dd: 0x1169,
+ 0x9de: 0x1181, 0x9df: 0x1029, 0x9e0: 0x1199, 0x9e1: 0x11a9, 0x9e2: 0x11c1, 0x9e3: 0x11d9,
+ 0x9e4: 0x11f1, 0x9e5: 0x1209, 0x9e6: 0x1221, 0x9e7: 0x05e5, 0x9e8: 0x1239, 0x9e9: 0x1251,
+ 0x9ea: 0xe17d, 0x9eb: 0x1269, 0x9ec: 0x1281, 0x9ed: 0x1299, 0x9ee: 0x12b1, 0x9ef: 0x12c9,
+ 0x9f0: 0x12e1, 0x9f1: 0x12f9, 0x9f2: 0x1311, 0x9f3: 0x1329, 0x9f4: 0x1341, 0x9f5: 0x1359,
+ 0x9f6: 0x1371, 0x9f7: 0x1389, 0x9f8: 0x05fd, 0x9f9: 0x13a1, 0x9fa: 0x13b9, 0x9fb: 0x13d1,
+ 0x9fc: 0x13e1, 0x9fd: 0x13f9, 0x9fe: 0x1411, 0x9ff: 0x1429,
+ // Block 0x28, offset 0xa00
+ 0xa00: 0xe00d, 0xa01: 0x0008, 0xa02: 0xe00d, 0xa03: 0x0008, 0xa04: 0xe00d, 0xa05: 0x0008,
+ 0xa06: 0xe00d, 0xa07: 0x0008, 0xa08: 0xe00d, 0xa09: 0x0008, 0xa0a: 0xe00d, 0xa0b: 0x0008,
+ 0xa0c: 0xe00d, 0xa0d: 0x0008, 0xa0e: 0xe00d, 0xa0f: 0x0008, 0xa10: 0xe00d, 0xa11: 0x0008,
+ 0xa12: 0xe00d, 0xa13: 0x0008, 0xa14: 0xe00d, 0xa15: 0x0008, 0xa16: 0xe00d, 0xa17: 0x0008,
+ 0xa18: 0xe00d, 0xa19: 0x0008, 0xa1a: 0xe00d, 0xa1b: 0x0008, 0xa1c: 0xe00d, 0xa1d: 0x0008,
+ 0xa1e: 0xe00d, 0xa1f: 0x0008, 0xa20: 0xe00d, 0xa21: 0x0008, 0xa22: 0xe00d, 0xa23: 0x0008,
+ 0xa24: 0xe00d, 0xa25: 0x0008, 0xa26: 0xe00d, 0xa27: 0x0008, 0xa28: 0xe00d, 0xa29: 0x0008,
+ 0xa2a: 0xe00d, 0xa2b: 0x0008, 0xa2c: 0xe00d, 0xa2d: 0x0008, 0xa2e: 0xe00d, 0xa2f: 0x0008,
+ 0xa30: 0xe00d, 0xa31: 0x0008, 0xa32: 0xe00d, 0xa33: 0x0008, 0xa34: 0xe00d, 0xa35: 0x0008,
+ 0xa36: 0xe00d, 0xa37: 0x0008, 0xa38: 0xe00d, 0xa39: 0x0008, 0xa3a: 0xe00d, 0xa3b: 0x0008,
+ 0xa3c: 0xe00d, 0xa3d: 0x0008, 0xa3e: 0xe00d, 0xa3f: 0x0008,
+ // Block 0x29, offset 0xa40
+ 0xa40: 0xe00d, 0xa41: 0x0008, 0xa42: 0xe00d, 0xa43: 0x0008, 0xa44: 0xe00d, 0xa45: 0x0008,
+ 0xa46: 0xe00d, 0xa47: 0x0008, 0xa48: 0xe00d, 0xa49: 0x0008, 0xa4a: 0xe00d, 0xa4b: 0x0008,
+ 0xa4c: 0xe00d, 0xa4d: 0x0008, 0xa4e: 0xe00d, 0xa4f: 0x0008, 0xa50: 0xe00d, 0xa51: 0x0008,
+ 0xa52: 0xe00d, 0xa53: 0x0008, 0xa54: 0xe00d, 0xa55: 0x0008, 0xa56: 0x0008, 0xa57: 0x0008,
+ 0xa58: 0x0008, 0xa59: 0x0008, 0xa5a: 0x0615, 0xa5b: 0x0635, 0xa5c: 0x0008, 0xa5d: 0x0008,
+ 0xa5e: 0x1441, 0xa5f: 0x0008, 0xa60: 0xe00d, 0xa61: 0x0008, 0xa62: 0xe00d, 0xa63: 0x0008,
+ 0xa64: 0xe00d, 0xa65: 0x0008, 0xa66: 0xe00d, 0xa67: 0x0008, 0xa68: 0xe00d, 0xa69: 0x0008,
+ 0xa6a: 0xe00d, 0xa6b: 0x0008, 0xa6c: 0xe00d, 0xa6d: 0x0008, 0xa6e: 0xe00d, 0xa6f: 0x0008,
+ 0xa70: 0xe00d, 0xa71: 0x0008, 0xa72: 0xe00d, 0xa73: 0x0008, 0xa74: 0xe00d, 0xa75: 0x0008,
+ 0xa76: 0xe00d, 0xa77: 0x0008, 0xa78: 0xe00d, 0xa79: 0x0008, 0xa7a: 0xe00d, 0xa7b: 0x0008,
+ 0xa7c: 0xe00d, 0xa7d: 0x0008, 0xa7e: 0xe00d, 0xa7f: 0x0008,
+ // Block 0x2a, offset 0xa80
+ 0xa80: 0x0008, 0xa81: 0x0008, 0xa82: 0x0008, 0xa83: 0x0008, 0xa84: 0x0008, 0xa85: 0x0008,
+ 0xa86: 0x0040, 0xa87: 0x0040, 0xa88: 0xe045, 0xa89: 0xe045, 0xa8a: 0xe045, 0xa8b: 0xe045,
+ 0xa8c: 0xe045, 0xa8d: 0xe045, 0xa8e: 0x0040, 0xa8f: 0x0040, 0xa90: 0x0008, 0xa91: 0x0008,
+ 0xa92: 0x0008, 0xa93: 0x0008, 0xa94: 0x0008, 0xa95: 0x0008, 0xa96: 0x0008, 0xa97: 0x0008,
+ 0xa98: 0x0040, 0xa99: 0xe045, 0xa9a: 0x0040, 0xa9b: 0xe045, 0xa9c: 0x0040, 0xa9d: 0xe045,
+ 0xa9e: 0x0040, 0xa9f: 0xe045, 0xaa0: 0x0008, 0xaa1: 0x0008, 0xaa2: 0x0008, 0xaa3: 0x0008,
+ 0xaa4: 0x0008, 0xaa5: 0x0008, 0xaa6: 0x0008, 0xaa7: 0x0008, 0xaa8: 0xe045, 0xaa9: 0xe045,
+ 0xaaa: 0xe045, 0xaab: 0xe045, 0xaac: 0xe045, 0xaad: 0xe045, 0xaae: 0xe045, 0xaaf: 0xe045,
+ 0xab0: 0x0008, 0xab1: 0x1459, 0xab2: 0x0008, 0xab3: 0x1471, 0xab4: 0x0008, 0xab5: 0x1489,
+ 0xab6: 0x0008, 0xab7: 0x14a1, 0xab8: 0x0008, 0xab9: 0x14b9, 0xaba: 0x0008, 0xabb: 0x14d1,
+ 0xabc: 0x0008, 0xabd: 0x14e9, 0xabe: 0x0040, 0xabf: 0x0040,
+ // Block 0x2b, offset 0xac0
+ 0xac0: 0x1501, 0xac1: 0x1531, 0xac2: 0x1561, 0xac3: 0x1591, 0xac4: 0x15c1, 0xac5: 0x15f1,
+ 0xac6: 0x1621, 0xac7: 0x1651, 0xac8: 0x1501, 0xac9: 0x1531, 0xaca: 0x1561, 0xacb: 0x1591,
+ 0xacc: 0x15c1, 0xacd: 0x15f1, 0xace: 0x1621, 0xacf: 0x1651, 0xad0: 0x1681, 0xad1: 0x16b1,
+ 0xad2: 0x16e1, 0xad3: 0x1711, 0xad4: 0x1741, 0xad5: 0x1771, 0xad6: 0x17a1, 0xad7: 0x17d1,
+ 0xad8: 0x1681, 0xad9: 0x16b1, 0xada: 0x16e1, 0xadb: 0x1711, 0xadc: 0x1741, 0xadd: 0x1771,
+ 0xade: 0x17a1, 0xadf: 0x17d1, 0xae0: 0x1801, 0xae1: 0x1831, 0xae2: 0x1861, 0xae3: 0x1891,
+ 0xae4: 0x18c1, 0xae5: 0x18f1, 0xae6: 0x1921, 0xae7: 0x1951, 0xae8: 0x1801, 0xae9: 0x1831,
+ 0xaea: 0x1861, 0xaeb: 0x1891, 0xaec: 0x18c1, 0xaed: 0x18f1, 0xaee: 0x1921, 0xaef: 0x1951,
+ 0xaf0: 0x0008, 0xaf1: 0x0008, 0xaf2: 0x1981, 0xaf3: 0x19b1, 0xaf4: 0x19d9, 0xaf5: 0x0040,
+ 0xaf6: 0x0008, 0xaf7: 0x1a01, 0xaf8: 0xe045, 0xaf9: 0xe045, 0xafa: 0x064d, 0xafb: 0x1459,
+ 0xafc: 0x19b1, 0xafd: 0x0666, 0xafe: 0x1a31, 0xaff: 0x0686,
+ // Block 0x2c, offset 0xb00
+ 0xb00: 0x06a6, 0xb01: 0x1a4a, 0xb02: 0x1a79, 0xb03: 0x1aa9, 0xb04: 0x1ad1, 0xb05: 0x0040,
+ 0xb06: 0x0008, 0xb07: 0x1af9, 0xb08: 0x06c5, 0xb09: 0x1471, 0xb0a: 0x06dd, 0xb0b: 0x1489,
+ 0xb0c: 0x1aa9, 0xb0d: 0x1b2a, 0xb0e: 0x1b5a, 0xb0f: 0x1b8a, 0xb10: 0x0008, 0xb11: 0x0008,
+ 0xb12: 0x0008, 0xb13: 0x1bb9, 0xb14: 0x0040, 0xb15: 0x0040, 0xb16: 0x0008, 0xb17: 0x0008,
+ 0xb18: 0xe045, 0xb19: 0xe045, 0xb1a: 0x06f5, 0xb1b: 0x14a1, 0xb1c: 0x0040, 0xb1d: 0x1bd2,
+ 0xb1e: 0x1c02, 0xb1f: 0x1c32, 0xb20: 0x0008, 0xb21: 0x0008, 0xb22: 0x0008, 0xb23: 0x1c61,
+ 0xb24: 0x0008, 0xb25: 0x0008, 0xb26: 0x0008, 0xb27: 0x0008, 0xb28: 0xe045, 0xb29: 0xe045,
+ 0xb2a: 0x070d, 0xb2b: 0x14d1, 0xb2c: 0xe04d, 0xb2d: 0x1c7a, 0xb2e: 0x03d2, 0xb2f: 0x1caa,
+ 0xb30: 0x0040, 0xb31: 0x0040, 0xb32: 0x1cb9, 0xb33: 0x1ce9, 0xb34: 0x1d11, 0xb35: 0x0040,
+ 0xb36: 0x0008, 0xb37: 0x1d39, 0xb38: 0x0725, 0xb39: 0x14b9, 0xb3a: 0x0515, 0xb3b: 0x14e9,
+ 0xb3c: 0x1ce9, 0xb3d: 0x073e, 0xb3e: 0x075e, 0xb3f: 0x0040,
+ // Block 0x2d, offset 0xb40
+ 0xb40: 0x000a, 0xb41: 0x000a, 0xb42: 0x000a, 0xb43: 0x000a, 0xb44: 0x000a, 0xb45: 0x000a,
+ 0xb46: 0x000a, 0xb47: 0x000a, 0xb48: 0x000a, 0xb49: 0x000a, 0xb4a: 0x000a, 0xb4b: 0x03c0,
+ 0xb4c: 0x0003, 0xb4d: 0x0003, 0xb4e: 0x0340, 0xb4f: 0x0340, 0xb50: 0x0018, 0xb51: 0xe00d,
+ 0xb52: 0x0018, 0xb53: 0x0018, 0xb54: 0x0018, 0xb55: 0x0018, 0xb56: 0x0018, 0xb57: 0x077e,
+ 0xb58: 0x0018, 0xb59: 0x0018, 0xb5a: 0x0018, 0xb5b: 0x0018, 0xb5c: 0x0018, 0xb5d: 0x0018,
+ 0xb5e: 0x0018, 0xb5f: 0x0018, 0xb60: 0x0018, 0xb61: 0x0018, 0xb62: 0x0018, 0xb63: 0x0018,
+ 0xb64: 0x0040, 0xb65: 0x0040, 0xb66: 0x0040, 0xb67: 0x0018, 0xb68: 0x0040, 0xb69: 0x0040,
+ 0xb6a: 0x0340, 0xb6b: 0x0340, 0xb6c: 0x0340, 0xb6d: 0x0340, 0xb6e: 0x0340, 0xb6f: 0x000a,
+ 0xb70: 0x0018, 0xb71: 0x0018, 0xb72: 0x0018, 0xb73: 0x1d69, 0xb74: 0x1da1, 0xb75: 0x0018,
+ 0xb76: 0x1df1, 0xb77: 0x1e29, 0xb78: 0x0018, 0xb79: 0x0018, 0xb7a: 0x0018, 0xb7b: 0x0018,
+ 0xb7c: 0x1e7a, 0xb7d: 0x0018, 0xb7e: 0x079e, 0xb7f: 0x0018,
+ // Block 0x2e, offset 0xb80
+ 0xb80: 0x0018, 0xb81: 0x0018, 0xb82: 0x0018, 0xb83: 0x0018, 0xb84: 0x0018, 0xb85: 0x0018,
+ 0xb86: 0x0018, 0xb87: 0x1e92, 0xb88: 0x1eaa, 0xb89: 0x1ec2, 0xb8a: 0x0018, 0xb8b: 0x0018,
+ 0xb8c: 0x0018, 0xb8d: 0x0018, 0xb8e: 0x0018, 0xb8f: 0x0018, 0xb90: 0x0018, 0xb91: 0x0018,
+ 0xb92: 0x0018, 0xb93: 0x0018, 0xb94: 0x0018, 0xb95: 0x0018, 0xb96: 0x0018, 0xb97: 0x1ed9,
+ 0xb98: 0x0018, 0xb99: 0x0018, 0xb9a: 0x0018, 0xb9b: 0x0018, 0xb9c: 0x0018, 0xb9d: 0x0018,
+ 0xb9e: 0x0018, 0xb9f: 0x000a, 0xba0: 0x03c0, 0xba1: 0x0340, 0xba2: 0x0340, 0xba3: 0x0340,
+ 0xba4: 0x03c0, 0xba5: 0x0040, 0xba6: 0x0040, 0xba7: 0x0040, 0xba8: 0x0040, 0xba9: 0x0040,
+ 0xbaa: 0x0340, 0xbab: 0x0340, 0xbac: 0x0340, 0xbad: 0x0340, 0xbae: 0x0340, 0xbaf: 0x0340,
+ 0xbb0: 0x1f41, 0xbb1: 0x0f41, 0xbb2: 0x0040, 0xbb3: 0x0040, 0xbb4: 0x1f51, 0xbb5: 0x1f61,
+ 0xbb6: 0x1f71, 0xbb7: 0x1f81, 0xbb8: 0x1f91, 0xbb9: 0x1fa1, 0xbba: 0x1fb2, 0xbbb: 0x07bd,
+ 0xbbc: 0x1fc2, 0xbbd: 0x1fd2, 0xbbe: 0x1fe2, 0xbbf: 0x0f71,
+ // Block 0x2f, offset 0xbc0
+ 0xbc0: 0x1f41, 0xbc1: 0x00c9, 0xbc2: 0x0069, 0xbc3: 0x0079, 0xbc4: 0x1f51, 0xbc5: 0x1f61,
+ 0xbc6: 0x1f71, 0xbc7: 0x1f81, 0xbc8: 0x1f91, 0xbc9: 0x1fa1, 0xbca: 0x1fb2, 0xbcb: 0x07d5,
+ 0xbcc: 0x1fc2, 0xbcd: 0x1fd2, 0xbce: 0x1fe2, 0xbcf: 0x0040, 0xbd0: 0x0039, 0xbd1: 0x0f09,
+ 0xbd2: 0x00d9, 0xbd3: 0x0369, 0xbd4: 0x0ff9, 0xbd5: 0x0249, 0xbd6: 0x0f51, 0xbd7: 0x0359,
+ 0xbd8: 0x0f61, 0xbd9: 0x0f71, 0xbda: 0x0f99, 0xbdb: 0x01d9, 0xbdc: 0x0fa9, 0xbdd: 0x0040,
+ 0xbde: 0x0040, 0xbdf: 0x0040, 0xbe0: 0x0018, 0xbe1: 0x0018, 0xbe2: 0x0018, 0xbe3: 0x0018,
+ 0xbe4: 0x0018, 0xbe5: 0x0018, 0xbe6: 0x0018, 0xbe7: 0x0018, 0xbe8: 0x1ff1, 0xbe9: 0x0018,
+ 0xbea: 0x0018, 0xbeb: 0x0018, 0xbec: 0x0018, 0xbed: 0x0018, 0xbee: 0x0018, 0xbef: 0x0018,
+ 0xbf0: 0x0018, 0xbf1: 0x0018, 0xbf2: 0x0018, 0xbf3: 0x0018, 0xbf4: 0x0018, 0xbf5: 0x0018,
+ 0xbf6: 0x0018, 0xbf7: 0x0018, 0xbf8: 0x0018, 0xbf9: 0x0018, 0xbfa: 0x0018, 0xbfb: 0x0018,
+ 0xbfc: 0x0018, 0xbfd: 0x0018, 0xbfe: 0x0018, 0xbff: 0x0040,
+ // Block 0x30, offset 0xc00
+ 0xc00: 0x07ee, 0xc01: 0x080e, 0xc02: 0x1159, 0xc03: 0x082d, 0xc04: 0x0018, 0xc05: 0x084e,
+ 0xc06: 0x086e, 0xc07: 0x1011, 0xc08: 0x0018, 0xc09: 0x088d, 0xc0a: 0x0f31, 0xc0b: 0x0249,
+ 0xc0c: 0x0249, 0xc0d: 0x0249, 0xc0e: 0x0249, 0xc0f: 0x2009, 0xc10: 0x0f41, 0xc11: 0x0f41,
+ 0xc12: 0x0359, 0xc13: 0x0359, 0xc14: 0x0018, 0xc15: 0x0f71, 0xc16: 0x2021, 0xc17: 0x0018,
+ 0xc18: 0x0018, 0xc19: 0x0f99, 0xc1a: 0x2039, 0xc1b: 0x0269, 0xc1c: 0x0269, 0xc1d: 0x0269,
+ 0xc1e: 0x0018, 0xc1f: 0x0018, 0xc20: 0x2049, 0xc21: 0x08ad, 0xc22: 0x2061, 0xc23: 0x0018,
+ 0xc24: 0x13d1, 0xc25: 0x0018, 0xc26: 0x2079, 0xc27: 0x0018, 0xc28: 0x13d1, 0xc29: 0x0018,
+ 0xc2a: 0x0f51, 0xc2b: 0x2091, 0xc2c: 0x0ee9, 0xc2d: 0x1159, 0xc2e: 0x0018, 0xc2f: 0x0f09,
+ 0xc30: 0x0f09, 0xc31: 0x1199, 0xc32: 0x0040, 0xc33: 0x0f61, 0xc34: 0x00d9, 0xc35: 0x20a9,
+ 0xc36: 0x20c1, 0xc37: 0x20d9, 0xc38: 0x20f1, 0xc39: 0x0f41, 0xc3a: 0x0018, 0xc3b: 0x08cd,
+ 0xc3c: 0x2109, 0xc3d: 0x10b1, 0xc3e: 0x10b1, 0xc3f: 0x2109,
+ // Block 0x31, offset 0xc40
+ 0xc40: 0x08ed, 0xc41: 0x0018, 0xc42: 0x0018, 0xc43: 0x0018, 0xc44: 0x0018, 0xc45: 0x0ef9,
+ 0xc46: 0x0ef9, 0xc47: 0x0f09, 0xc48: 0x0f41, 0xc49: 0x0259, 0xc4a: 0x0018, 0xc4b: 0x0018,
+ 0xc4c: 0x0018, 0xc4d: 0x0018, 0xc4e: 0x0008, 0xc4f: 0x0018, 0xc50: 0x2121, 0xc51: 0x2151,
+ 0xc52: 0x2181, 0xc53: 0x21b9, 0xc54: 0x21e9, 0xc55: 0x2219, 0xc56: 0x2249, 0xc57: 0x2279,
+ 0xc58: 0x22a9, 0xc59: 0x22d9, 0xc5a: 0x2309, 0xc5b: 0x2339, 0xc5c: 0x2369, 0xc5d: 0x2399,
+ 0xc5e: 0x23c9, 0xc5f: 0x23f9, 0xc60: 0x0f41, 0xc61: 0x2421, 0xc62: 0x0905, 0xc63: 0x2439,
+ 0xc64: 0x1089, 0xc65: 0x2451, 0xc66: 0x0925, 0xc67: 0x2469, 0xc68: 0x2491, 0xc69: 0x0369,
+ 0xc6a: 0x24a9, 0xc6b: 0x0945, 0xc6c: 0x0359, 0xc6d: 0x1159, 0xc6e: 0x0ef9, 0xc6f: 0x0f61,
+ 0xc70: 0x0f41, 0xc71: 0x2421, 0xc72: 0x0965, 0xc73: 0x2439, 0xc74: 0x1089, 0xc75: 0x2451,
+ 0xc76: 0x0985, 0xc77: 0x2469, 0xc78: 0x2491, 0xc79: 0x0369, 0xc7a: 0x24a9, 0xc7b: 0x09a5,
+ 0xc7c: 0x0359, 0xc7d: 0x1159, 0xc7e: 0x0ef9, 0xc7f: 0x0f61,
+ // Block 0x32, offset 0xc80
+ 0xc80: 0x0018, 0xc81: 0x0018, 0xc82: 0x0018, 0xc83: 0x0018, 0xc84: 0x0018, 0xc85: 0x0018,
+ 0xc86: 0x0018, 0xc87: 0x0018, 0xc88: 0x0018, 0xc89: 0x0018, 0xc8a: 0x0018, 0xc8b: 0x0040,
+ 0xc8c: 0x0040, 0xc8d: 0x0040, 0xc8e: 0x0040, 0xc8f: 0x0040, 0xc90: 0x0040, 0xc91: 0x0040,
+ 0xc92: 0x0040, 0xc93: 0x0040, 0xc94: 0x0040, 0xc95: 0x0040, 0xc96: 0x0040, 0xc97: 0x0040,
+ 0xc98: 0x0040, 0xc99: 0x0040, 0xc9a: 0x0040, 0xc9b: 0x0040, 0xc9c: 0x0040, 0xc9d: 0x0040,
+ 0xc9e: 0x0040, 0xc9f: 0x0040, 0xca0: 0x00c9, 0xca1: 0x0069, 0xca2: 0x0079, 0xca3: 0x1f51,
+ 0xca4: 0x1f61, 0xca5: 0x1f71, 0xca6: 0x1f81, 0xca7: 0x1f91, 0xca8: 0x1fa1, 0xca9: 0x2601,
+ 0xcaa: 0x2619, 0xcab: 0x2631, 0xcac: 0x2649, 0xcad: 0x2661, 0xcae: 0x2679, 0xcaf: 0x2691,
+ 0xcb0: 0x26a9, 0xcb1: 0x26c1, 0xcb2: 0x26d9, 0xcb3: 0x26f1, 0xcb4: 0x0a06, 0xcb5: 0x0a26,
+ 0xcb6: 0x0a46, 0xcb7: 0x0a66, 0xcb8: 0x0a86, 0xcb9: 0x0aa6, 0xcba: 0x0ac6, 0xcbb: 0x0ae6,
+ 0xcbc: 0x0b06, 0xcbd: 0x270a, 0xcbe: 0x2732, 0xcbf: 0x275a,
+ // Block 0x33, offset 0xcc0
+ 0xcc0: 0x2782, 0xcc1: 0x27aa, 0xcc2: 0x27d2, 0xcc3: 0x27fa, 0xcc4: 0x2822, 0xcc5: 0x284a,
+ 0xcc6: 0x2872, 0xcc7: 0x289a, 0xcc8: 0x0040, 0xcc9: 0x0040, 0xcca: 0x0040, 0xccb: 0x0040,
+ 0xccc: 0x0040, 0xccd: 0x0040, 0xcce: 0x0040, 0xccf: 0x0040, 0xcd0: 0x0040, 0xcd1: 0x0040,
+ 0xcd2: 0x0040, 0xcd3: 0x0040, 0xcd4: 0x0040, 0xcd5: 0x0040, 0xcd6: 0x0040, 0xcd7: 0x0040,
+ 0xcd8: 0x0040, 0xcd9: 0x0040, 0xcda: 0x0040, 0xcdb: 0x0040, 0xcdc: 0x0b26, 0xcdd: 0x0b46,
+ 0xcde: 0x0b66, 0xcdf: 0x0b86, 0xce0: 0x0ba6, 0xce1: 0x0bc6, 0xce2: 0x0be6, 0xce3: 0x0c06,
+ 0xce4: 0x0c26, 0xce5: 0x0c46, 0xce6: 0x0c66, 0xce7: 0x0c86, 0xce8: 0x0ca6, 0xce9: 0x0cc6,
+ 0xcea: 0x0ce6, 0xceb: 0x0d06, 0xcec: 0x0d26, 0xced: 0x0d46, 0xcee: 0x0d66, 0xcef: 0x0d86,
+ 0xcf0: 0x0da6, 0xcf1: 0x0dc6, 0xcf2: 0x0de6, 0xcf3: 0x0e06, 0xcf4: 0x0e26, 0xcf5: 0x0e46,
+ 0xcf6: 0x0039, 0xcf7: 0x0ee9, 0xcf8: 0x1159, 0xcf9: 0x0ef9, 0xcfa: 0x0f09, 0xcfb: 0x1199,
+ 0xcfc: 0x0f31, 0xcfd: 0x0249, 0xcfe: 0x0f41, 0xcff: 0x0259,
+ // Block 0x34, offset 0xd00
+ 0xd00: 0x0f51, 0xd01: 0x0359, 0xd02: 0x0f61, 0xd03: 0x0f71, 0xd04: 0x00d9, 0xd05: 0x0f99,
+ 0xd06: 0x2039, 0xd07: 0x0269, 0xd08: 0x01d9, 0xd09: 0x0fa9, 0xd0a: 0x0fb9, 0xd0b: 0x1089,
+ 0xd0c: 0x0279, 0xd0d: 0x0369, 0xd0e: 0x0289, 0xd0f: 0x13d1, 0xd10: 0x0039, 0xd11: 0x0ee9,
+ 0xd12: 0x1159, 0xd13: 0x0ef9, 0xd14: 0x0f09, 0xd15: 0x1199, 0xd16: 0x0f31, 0xd17: 0x0249,
+ 0xd18: 0x0f41, 0xd19: 0x0259, 0xd1a: 0x0f51, 0xd1b: 0x0359, 0xd1c: 0x0f61, 0xd1d: 0x0f71,
+ 0xd1e: 0x00d9, 0xd1f: 0x0f99, 0xd20: 0x2039, 0xd21: 0x0269, 0xd22: 0x01d9, 0xd23: 0x0fa9,
+ 0xd24: 0x0fb9, 0xd25: 0x1089, 0xd26: 0x0279, 0xd27: 0x0369, 0xd28: 0x0289, 0xd29: 0x13d1,
+ 0xd2a: 0x1f41, 0xd2b: 0x0018, 0xd2c: 0x0018, 0xd2d: 0x0018, 0xd2e: 0x0018, 0xd2f: 0x0018,
+ 0xd30: 0x0018, 0xd31: 0x0018, 0xd32: 0x0018, 0xd33: 0x0018, 0xd34: 0x0018, 0xd35: 0x0018,
+ 0xd36: 0x0018, 0xd37: 0x0018, 0xd38: 0x0018, 0xd39: 0x0018, 0xd3a: 0x0018, 0xd3b: 0x0018,
+ 0xd3c: 0x0018, 0xd3d: 0x0018, 0xd3e: 0x0018, 0xd3f: 0x0018,
+ // Block 0x35, offset 0xd40
+ 0xd40: 0x0008, 0xd41: 0x0008, 0xd42: 0x0008, 0xd43: 0x0008, 0xd44: 0x0008, 0xd45: 0x0008,
+ 0xd46: 0x0008, 0xd47: 0x0008, 0xd48: 0x0008, 0xd49: 0x0008, 0xd4a: 0x0008, 0xd4b: 0x0008,
+ 0xd4c: 0x0008, 0xd4d: 0x0008, 0xd4e: 0x0008, 0xd4f: 0x0008, 0xd50: 0x0008, 0xd51: 0x0008,
+ 0xd52: 0x0008, 0xd53: 0x0008, 0xd54: 0x0008, 0xd55: 0x0008, 0xd56: 0x0008, 0xd57: 0x0008,
+ 0xd58: 0x0008, 0xd59: 0x0008, 0xd5a: 0x0008, 0xd5b: 0x0008, 0xd5c: 0x0008, 0xd5d: 0x0008,
+ 0xd5e: 0x0008, 0xd5f: 0x0040, 0xd60: 0xe00d, 0xd61: 0x0008, 0xd62: 0x2971, 0xd63: 0x0ebd,
+ 0xd64: 0x2989, 0xd65: 0x0008, 0xd66: 0x0008, 0xd67: 0xe07d, 0xd68: 0x0008, 0xd69: 0xe01d,
+ 0xd6a: 0x0008, 0xd6b: 0xe03d, 0xd6c: 0x0008, 0xd6d: 0x0fe1, 0xd6e: 0x1281, 0xd6f: 0x0fc9,
+ 0xd70: 0x1141, 0xd71: 0x0008, 0xd72: 0xe00d, 0xd73: 0x0008, 0xd74: 0x0008, 0xd75: 0xe01d,
+ 0xd76: 0x0008, 0xd77: 0x0008, 0xd78: 0x0008, 0xd79: 0x0008, 0xd7a: 0x0008, 0xd7b: 0x0008,
+ 0xd7c: 0x0259, 0xd7d: 0x1089, 0xd7e: 0x29a1, 0xd7f: 0x29b9,
+ // Block 0x36, offset 0xd80
+ 0xd80: 0xe00d, 0xd81: 0x0008, 0xd82: 0xe00d, 0xd83: 0x0008, 0xd84: 0xe00d, 0xd85: 0x0008,
+ 0xd86: 0xe00d, 0xd87: 0x0008, 0xd88: 0xe00d, 0xd89: 0x0008, 0xd8a: 0xe00d, 0xd8b: 0x0008,
+ 0xd8c: 0xe00d, 0xd8d: 0x0008, 0xd8e: 0xe00d, 0xd8f: 0x0008, 0xd90: 0xe00d, 0xd91: 0x0008,
+ 0xd92: 0xe00d, 0xd93: 0x0008, 0xd94: 0xe00d, 0xd95: 0x0008, 0xd96: 0xe00d, 0xd97: 0x0008,
+ 0xd98: 0xe00d, 0xd99: 0x0008, 0xd9a: 0xe00d, 0xd9b: 0x0008, 0xd9c: 0xe00d, 0xd9d: 0x0008,
+ 0xd9e: 0xe00d, 0xd9f: 0x0008, 0xda0: 0xe00d, 0xda1: 0x0008, 0xda2: 0xe00d, 0xda3: 0x0008,
+ 0xda4: 0x0008, 0xda5: 0x0018, 0xda6: 0x0018, 0xda7: 0x0018, 0xda8: 0x0018, 0xda9: 0x0018,
+ 0xdaa: 0x0018, 0xdab: 0xe03d, 0xdac: 0x0008, 0xdad: 0xe01d, 0xdae: 0x0008, 0xdaf: 0x1308,
+ 0xdb0: 0x1308, 0xdb1: 0x1308, 0xdb2: 0xe00d, 0xdb3: 0x0008, 0xdb4: 0x0040, 0xdb5: 0x0040,
+ 0xdb6: 0x0040, 0xdb7: 0x0040, 0xdb8: 0x0040, 0xdb9: 0x0018, 0xdba: 0x0018, 0xdbb: 0x0018,
+ 0xdbc: 0x0018, 0xdbd: 0x0018, 0xdbe: 0x0018, 0xdbf: 0x0018,
+ // Block 0x37, offset 0xdc0
+ 0xdc0: 0x26fd, 0xdc1: 0x271d, 0xdc2: 0x273d, 0xdc3: 0x275d, 0xdc4: 0x277d, 0xdc5: 0x279d,
+ 0xdc6: 0x27bd, 0xdc7: 0x27dd, 0xdc8: 0x27fd, 0xdc9: 0x281d, 0xdca: 0x283d, 0xdcb: 0x285d,
+ 0xdcc: 0x287d, 0xdcd: 0x289d, 0xdce: 0x28bd, 0xdcf: 0x28dd, 0xdd0: 0x28fd, 0xdd1: 0x291d,
+ 0xdd2: 0x293d, 0xdd3: 0x295d, 0xdd4: 0x297d, 0xdd5: 0x299d, 0xdd6: 0x0040, 0xdd7: 0x0040,
+ 0xdd8: 0x0040, 0xdd9: 0x0040, 0xdda: 0x0040, 0xddb: 0x0040, 0xddc: 0x0040, 0xddd: 0x0040,
+ 0xdde: 0x0040, 0xddf: 0x0040, 0xde0: 0x0040, 0xde1: 0x0040, 0xde2: 0x0040, 0xde3: 0x0040,
+ 0xde4: 0x0040, 0xde5: 0x0040, 0xde6: 0x0040, 0xde7: 0x0040, 0xde8: 0x0040, 0xde9: 0x0040,
+ 0xdea: 0x0040, 0xdeb: 0x0040, 0xdec: 0x0040, 0xded: 0x0040, 0xdee: 0x0040, 0xdef: 0x0040,
+ 0xdf0: 0x0040, 0xdf1: 0x0040, 0xdf2: 0x0040, 0xdf3: 0x0040, 0xdf4: 0x0040, 0xdf5: 0x0040,
+ 0xdf6: 0x0040, 0xdf7: 0x0040, 0xdf8: 0x0040, 0xdf9: 0x0040, 0xdfa: 0x0040, 0xdfb: 0x0040,
+ 0xdfc: 0x0040, 0xdfd: 0x0040, 0xdfe: 0x0040, 0xdff: 0x0040,
+ // Block 0x38, offset 0xe00
+ 0xe00: 0x000a, 0xe01: 0x0018, 0xe02: 0x29d1, 0xe03: 0x0018, 0xe04: 0x0018, 0xe05: 0x0008,
+ 0xe06: 0x0008, 0xe07: 0x0008, 0xe08: 0x0018, 0xe09: 0x0018, 0xe0a: 0x0018, 0xe0b: 0x0018,
+ 0xe0c: 0x0018, 0xe0d: 0x0018, 0xe0e: 0x0018, 0xe0f: 0x0018, 0xe10: 0x0018, 0xe11: 0x0018,
+ 0xe12: 0x0018, 0xe13: 0x0018, 0xe14: 0x0018, 0xe15: 0x0018, 0xe16: 0x0018, 0xe17: 0x0018,
+ 0xe18: 0x0018, 0xe19: 0x0018, 0xe1a: 0x0018, 0xe1b: 0x0018, 0xe1c: 0x0018, 0xe1d: 0x0018,
+ 0xe1e: 0x0018, 0xe1f: 0x0018, 0xe20: 0x0018, 0xe21: 0x0018, 0xe22: 0x0018, 0xe23: 0x0018,
+ 0xe24: 0x0018, 0xe25: 0x0018, 0xe26: 0x0018, 0xe27: 0x0018, 0xe28: 0x0018, 0xe29: 0x0018,
+ 0xe2a: 0x1308, 0xe2b: 0x1308, 0xe2c: 0x1308, 0xe2d: 0x1308, 0xe2e: 0x1018, 0xe2f: 0x1018,
+ 0xe30: 0x0018, 0xe31: 0x0018, 0xe32: 0x0018, 0xe33: 0x0018, 0xe34: 0x0018, 0xe35: 0x0018,
+ 0xe36: 0xe125, 0xe37: 0x0018, 0xe38: 0x29bd, 0xe39: 0x29dd, 0xe3a: 0x29fd, 0xe3b: 0x0018,
+ 0xe3c: 0x0008, 0xe3d: 0x0018, 0xe3e: 0x0018, 0xe3f: 0x0018,
+ // Block 0x39, offset 0xe40
+ 0xe40: 0x2b3d, 0xe41: 0x2b5d, 0xe42: 0x2b7d, 0xe43: 0x2b9d, 0xe44: 0x2bbd, 0xe45: 0x2bdd,
+ 0xe46: 0x2bdd, 0xe47: 0x2bdd, 0xe48: 0x2bfd, 0xe49: 0x2bfd, 0xe4a: 0x2bfd, 0xe4b: 0x2bfd,
+ 0xe4c: 0x2c1d, 0xe4d: 0x2c1d, 0xe4e: 0x2c1d, 0xe4f: 0x2c3d, 0xe50: 0x2c5d, 0xe51: 0x2c5d,
+ 0xe52: 0x2a7d, 0xe53: 0x2a7d, 0xe54: 0x2c5d, 0xe55: 0x2c5d, 0xe56: 0x2c7d, 0xe57: 0x2c7d,
+ 0xe58: 0x2c5d, 0xe59: 0x2c5d, 0xe5a: 0x2a7d, 0xe5b: 0x2a7d, 0xe5c: 0x2c5d, 0xe5d: 0x2c5d,
+ 0xe5e: 0x2c3d, 0xe5f: 0x2c3d, 0xe60: 0x2c9d, 0xe61: 0x2c9d, 0xe62: 0x2cbd, 0xe63: 0x2cbd,
+ 0xe64: 0x0040, 0xe65: 0x2cdd, 0xe66: 0x2cfd, 0xe67: 0x2d1d, 0xe68: 0x2d1d, 0xe69: 0x2d3d,
+ 0xe6a: 0x2d5d, 0xe6b: 0x2d7d, 0xe6c: 0x2d9d, 0xe6d: 0x2dbd, 0xe6e: 0x2ddd, 0xe6f: 0x2dfd,
+ 0xe70: 0x2e1d, 0xe71: 0x2e3d, 0xe72: 0x2e3d, 0xe73: 0x2e5d, 0xe74: 0x2e7d, 0xe75: 0x2e7d,
+ 0xe76: 0x2e9d, 0xe77: 0x2ebd, 0xe78: 0x2e5d, 0xe79: 0x2edd, 0xe7a: 0x2efd, 0xe7b: 0x2edd,
+ 0xe7c: 0x2e5d, 0xe7d: 0x2f1d, 0xe7e: 0x2f3d, 0xe7f: 0x2f5d,
+ // Block 0x3a, offset 0xe80
+ 0xe80: 0x2f7d, 0xe81: 0x2f9d, 0xe82: 0x2cfd, 0xe83: 0x2cdd, 0xe84: 0x2fbd, 0xe85: 0x2fdd,
+ 0xe86: 0x2ffd, 0xe87: 0x301d, 0xe88: 0x303d, 0xe89: 0x305d, 0xe8a: 0x307d, 0xe8b: 0x309d,
+ 0xe8c: 0x30bd, 0xe8d: 0x30dd, 0xe8e: 0x30fd, 0xe8f: 0x0040, 0xe90: 0x0018, 0xe91: 0x0018,
+ 0xe92: 0x311d, 0xe93: 0x313d, 0xe94: 0x315d, 0xe95: 0x317d, 0xe96: 0x319d, 0xe97: 0x31bd,
+ 0xe98: 0x31dd, 0xe99: 0x31fd, 0xe9a: 0x321d, 0xe9b: 0x323d, 0xe9c: 0x315d, 0xe9d: 0x325d,
+ 0xe9e: 0x327d, 0xe9f: 0x329d, 0xea0: 0x0008, 0xea1: 0x0008, 0xea2: 0x0008, 0xea3: 0x0008,
+ 0xea4: 0x0008, 0xea5: 0x0008, 0xea6: 0x0008, 0xea7: 0x0008, 0xea8: 0x0008, 0xea9: 0x0008,
+ 0xeaa: 0x0008, 0xeab: 0x0008, 0xeac: 0x0008, 0xead: 0x0008, 0xeae: 0x0008, 0xeaf: 0x0008,
+ 0xeb0: 0x0008, 0xeb1: 0x0008, 0xeb2: 0x0008, 0xeb3: 0x0008, 0xeb4: 0x0008, 0xeb5: 0x0008,
+ 0xeb6: 0x0008, 0xeb7: 0x0008, 0xeb8: 0x0008, 0xeb9: 0x0008, 0xeba: 0x0008, 0xebb: 0x0040,
+ 0xebc: 0x0040, 0xebd: 0x0040, 0xebe: 0x0040, 0xebf: 0x0040,
+ // Block 0x3b, offset 0xec0
+ 0xec0: 0x36a2, 0xec1: 0x36d2, 0xec2: 0x3702, 0xec3: 0x3732, 0xec4: 0x32bd, 0xec5: 0x32dd,
+ 0xec6: 0x32fd, 0xec7: 0x331d, 0xec8: 0x0018, 0xec9: 0x0018, 0xeca: 0x0018, 0xecb: 0x0018,
+ 0xecc: 0x0018, 0xecd: 0x0018, 0xece: 0x0018, 0xecf: 0x0018, 0xed0: 0x333d, 0xed1: 0x3761,
+ 0xed2: 0x3779, 0xed3: 0x3791, 0xed4: 0x37a9, 0xed5: 0x37c1, 0xed6: 0x37d9, 0xed7: 0x37f1,
+ 0xed8: 0x3809, 0xed9: 0x3821, 0xeda: 0x3839, 0xedb: 0x3851, 0xedc: 0x3869, 0xedd: 0x3881,
+ 0xede: 0x3899, 0xedf: 0x38b1, 0xee0: 0x335d, 0xee1: 0x337d, 0xee2: 0x339d, 0xee3: 0x33bd,
+ 0xee4: 0x33dd, 0xee5: 0x33dd, 0xee6: 0x33fd, 0xee7: 0x341d, 0xee8: 0x343d, 0xee9: 0x345d,
+ 0xeea: 0x347d, 0xeeb: 0x349d, 0xeec: 0x34bd, 0xeed: 0x34dd, 0xeee: 0x34fd, 0xeef: 0x351d,
+ 0xef0: 0x353d, 0xef1: 0x355d, 0xef2: 0x357d, 0xef3: 0x359d, 0xef4: 0x35bd, 0xef5: 0x35dd,
+ 0xef6: 0x35fd, 0xef7: 0x361d, 0xef8: 0x363d, 0xef9: 0x365d, 0xefa: 0x367d, 0xefb: 0x369d,
+ 0xefc: 0x38c9, 0xefd: 0x3901, 0xefe: 0x36bd, 0xeff: 0x0018,
+ // Block 0x3c, offset 0xf00
+ 0xf00: 0x36dd, 0xf01: 0x36fd, 0xf02: 0x371d, 0xf03: 0x373d, 0xf04: 0x375d, 0xf05: 0x377d,
+ 0xf06: 0x379d, 0xf07: 0x37bd, 0xf08: 0x37dd, 0xf09: 0x37fd, 0xf0a: 0x381d, 0xf0b: 0x383d,
+ 0xf0c: 0x385d, 0xf0d: 0x387d, 0xf0e: 0x389d, 0xf0f: 0x38bd, 0xf10: 0x38dd, 0xf11: 0x38fd,
+ 0xf12: 0x391d, 0xf13: 0x393d, 0xf14: 0x395d, 0xf15: 0x397d, 0xf16: 0x399d, 0xf17: 0x39bd,
+ 0xf18: 0x39dd, 0xf19: 0x39fd, 0xf1a: 0x3a1d, 0xf1b: 0x3a3d, 0xf1c: 0x3a5d, 0xf1d: 0x3a7d,
+ 0xf1e: 0x3a9d, 0xf1f: 0x3abd, 0xf20: 0x3add, 0xf21: 0x3afd, 0xf22: 0x3b1d, 0xf23: 0x3b3d,
+ 0xf24: 0x3b5d, 0xf25: 0x3b7d, 0xf26: 0x127d, 0xf27: 0x3b9d, 0xf28: 0x3bbd, 0xf29: 0x3bdd,
+ 0xf2a: 0x3bfd, 0xf2b: 0x3c1d, 0xf2c: 0x3c3d, 0xf2d: 0x3c5d, 0xf2e: 0x239d, 0xf2f: 0x3c7d,
+ 0xf30: 0x3c9d, 0xf31: 0x3939, 0xf32: 0x3951, 0xf33: 0x3969, 0xf34: 0x3981, 0xf35: 0x3999,
+ 0xf36: 0x39b1, 0xf37: 0x39c9, 0xf38: 0x39e1, 0xf39: 0x39f9, 0xf3a: 0x3a11, 0xf3b: 0x3a29,
+ 0xf3c: 0x3a41, 0xf3d: 0x3a59, 0xf3e: 0x3a71, 0xf3f: 0x3a89,
+ // Block 0x3d, offset 0xf40
+ 0xf40: 0x3aa1, 0xf41: 0x3ac9, 0xf42: 0x3af1, 0xf43: 0x3b19, 0xf44: 0x3b41, 0xf45: 0x3b69,
+ 0xf46: 0x3b91, 0xf47: 0x3bb9, 0xf48: 0x3be1, 0xf49: 0x3c09, 0xf4a: 0x3c39, 0xf4b: 0x3c69,
+ 0xf4c: 0x3c99, 0xf4d: 0x3cbd, 0xf4e: 0x3cb1, 0xf4f: 0x3cdd, 0xf50: 0x3cfd, 0xf51: 0x3d15,
+ 0xf52: 0x3d2d, 0xf53: 0x3d45, 0xf54: 0x3d5d, 0xf55: 0x3d5d, 0xf56: 0x3d45, 0xf57: 0x3d75,
+ 0xf58: 0x07bd, 0xf59: 0x3d8d, 0xf5a: 0x3da5, 0xf5b: 0x3dbd, 0xf5c: 0x3dd5, 0xf5d: 0x3ded,
+ 0xf5e: 0x3e05, 0xf5f: 0x3e1d, 0xf60: 0x3e35, 0xf61: 0x3e4d, 0xf62: 0x3e65, 0xf63: 0x3e7d,
+ 0xf64: 0x3e95, 0xf65: 0x3e95, 0xf66: 0x3ead, 0xf67: 0x3ead, 0xf68: 0x3ec5, 0xf69: 0x3ec5,
+ 0xf6a: 0x3edd, 0xf6b: 0x3ef5, 0xf6c: 0x3f0d, 0xf6d: 0x3f25, 0xf6e: 0x3f3d, 0xf6f: 0x3f3d,
+ 0xf70: 0x3f55, 0xf71: 0x3f55, 0xf72: 0x3f55, 0xf73: 0x3f6d, 0xf74: 0x3f85, 0xf75: 0x3f9d,
+ 0xf76: 0x3fb5, 0xf77: 0x3f9d, 0xf78: 0x3fcd, 0xf79: 0x3fe5, 0xf7a: 0x3f6d, 0xf7b: 0x3ffd,
+ 0xf7c: 0x4015, 0xf7d: 0x4015, 0xf7e: 0x4015, 0xf7f: 0x0040,
+ // Block 0x3e, offset 0xf80
+ 0xf80: 0x3cc9, 0xf81: 0x3d31, 0xf82: 0x3d99, 0xf83: 0x3e01, 0xf84: 0x3e51, 0xf85: 0x3eb9,
+ 0xf86: 0x3f09, 0xf87: 0x3f59, 0xf88: 0x3fd9, 0xf89: 0x4041, 0xf8a: 0x4091, 0xf8b: 0x40e1,
+ 0xf8c: 0x4131, 0xf8d: 0x4199, 0xf8e: 0x4201, 0xf8f: 0x4251, 0xf90: 0x42a1, 0xf91: 0x42d9,
+ 0xf92: 0x4329, 0xf93: 0x4391, 0xf94: 0x43f9, 0xf95: 0x4431, 0xf96: 0x44b1, 0xf97: 0x4549,
+ 0xf98: 0x45c9, 0xf99: 0x4619, 0xf9a: 0x4699, 0xf9b: 0x4719, 0xf9c: 0x4781, 0xf9d: 0x47d1,
+ 0xf9e: 0x4821, 0xf9f: 0x4871, 0xfa0: 0x48d9, 0xfa1: 0x4959, 0xfa2: 0x49c1, 0xfa3: 0x4a11,
+ 0xfa4: 0x4a61, 0xfa5: 0x4ab1, 0xfa6: 0x4ae9, 0xfa7: 0x4b21, 0xfa8: 0x4b59, 0xfa9: 0x4b91,
+ 0xfaa: 0x4be1, 0xfab: 0x4c31, 0xfac: 0x4cb1, 0xfad: 0x4d01, 0xfae: 0x4d69, 0xfaf: 0x4de9,
+ 0xfb0: 0x4e39, 0xfb1: 0x4e71, 0xfb2: 0x4ea9, 0xfb3: 0x4f29, 0xfb4: 0x4f91, 0xfb5: 0x5011,
+ 0xfb6: 0x5061, 0xfb7: 0x50e1, 0xfb8: 0x5119, 0xfb9: 0x5169, 0xfba: 0x51b9, 0xfbb: 0x5209,
+ 0xfbc: 0x5259, 0xfbd: 0x52a9, 0xfbe: 0x5311, 0xfbf: 0x5361,
+ // Block 0x3f, offset 0xfc0
+ 0xfc0: 0x5399, 0xfc1: 0x53e9, 0xfc2: 0x5439, 0xfc3: 0x5489, 0xfc4: 0x54f1, 0xfc5: 0x5541,
+ 0xfc6: 0x5591, 0xfc7: 0x55e1, 0xfc8: 0x5661, 0xfc9: 0x56c9, 0xfca: 0x5701, 0xfcb: 0x5781,
+ 0xfcc: 0x57b9, 0xfcd: 0x5821, 0xfce: 0x5889, 0xfcf: 0x58d9, 0xfd0: 0x5929, 0xfd1: 0x5979,
+ 0xfd2: 0x59e1, 0xfd3: 0x5a19, 0xfd4: 0x5a69, 0xfd5: 0x5ad1, 0xfd6: 0x5b09, 0xfd7: 0x5b89,
+ 0xfd8: 0x5bd9, 0xfd9: 0x5c01, 0xfda: 0x5c29, 0xfdb: 0x5c51, 0xfdc: 0x5c79, 0xfdd: 0x5ca1,
+ 0xfde: 0x5cc9, 0xfdf: 0x5cf1, 0xfe0: 0x5d19, 0xfe1: 0x5d41, 0xfe2: 0x5d69, 0xfe3: 0x5d99,
+ 0xfe4: 0x5dc9, 0xfe5: 0x5df9, 0xfe6: 0x5e29, 0xfe7: 0x5e59, 0xfe8: 0x5e89, 0xfe9: 0x5eb9,
+ 0xfea: 0x5ee9, 0xfeb: 0x5f19, 0xfec: 0x5f49, 0xfed: 0x5f79, 0xfee: 0x5fa9, 0xfef: 0x5fd9,
+ 0xff0: 0x6009, 0xff1: 0x402d, 0xff2: 0x6039, 0xff3: 0x6051, 0xff4: 0x404d, 0xff5: 0x6069,
+ 0xff6: 0x6081, 0xff7: 0x6099, 0xff8: 0x406d, 0xff9: 0x406d, 0xffa: 0x60b1, 0xffb: 0x60c9,
+ 0xffc: 0x6101, 0xffd: 0x6139, 0xffe: 0x6171, 0xfff: 0x61a9,
+ // Block 0x40, offset 0x1000
+ 0x1000: 0x6211, 0x1001: 0x6229, 0x1002: 0x408d, 0x1003: 0x6241, 0x1004: 0x6259, 0x1005: 0x6271,
+ 0x1006: 0x6289, 0x1007: 0x62a1, 0x1008: 0x40ad, 0x1009: 0x62b9, 0x100a: 0x62e1, 0x100b: 0x62f9,
+ 0x100c: 0x40cd, 0x100d: 0x40cd, 0x100e: 0x6311, 0x100f: 0x6329, 0x1010: 0x6341, 0x1011: 0x40ed,
+ 0x1012: 0x410d, 0x1013: 0x412d, 0x1014: 0x414d, 0x1015: 0x416d, 0x1016: 0x6359, 0x1017: 0x6371,
+ 0x1018: 0x6389, 0x1019: 0x63a1, 0x101a: 0x63b9, 0x101b: 0x418d, 0x101c: 0x63d1, 0x101d: 0x63e9,
+ 0x101e: 0x6401, 0x101f: 0x41ad, 0x1020: 0x41cd, 0x1021: 0x6419, 0x1022: 0x41ed, 0x1023: 0x420d,
+ 0x1024: 0x422d, 0x1025: 0x6431, 0x1026: 0x424d, 0x1027: 0x6449, 0x1028: 0x6479, 0x1029: 0x6211,
+ 0x102a: 0x426d, 0x102b: 0x428d, 0x102c: 0x42ad, 0x102d: 0x42cd, 0x102e: 0x64b1, 0x102f: 0x64f1,
+ 0x1030: 0x6539, 0x1031: 0x6551, 0x1032: 0x42ed, 0x1033: 0x6569, 0x1034: 0x6581, 0x1035: 0x6599,
+ 0x1036: 0x430d, 0x1037: 0x65b1, 0x1038: 0x65c9, 0x1039: 0x65b1, 0x103a: 0x65e1, 0x103b: 0x65f9,
+ 0x103c: 0x432d, 0x103d: 0x6611, 0x103e: 0x6629, 0x103f: 0x6611,
+ // Block 0x41, offset 0x1040
+ 0x1040: 0x434d, 0x1041: 0x436d, 0x1042: 0x0040, 0x1043: 0x6641, 0x1044: 0x6659, 0x1045: 0x6671,
+ 0x1046: 0x6689, 0x1047: 0x0040, 0x1048: 0x66c1, 0x1049: 0x66d9, 0x104a: 0x66f1, 0x104b: 0x6709,
+ 0x104c: 0x6721, 0x104d: 0x6739, 0x104e: 0x6401, 0x104f: 0x6751, 0x1050: 0x6769, 0x1051: 0x6781,
+ 0x1052: 0x438d, 0x1053: 0x6799, 0x1054: 0x6289, 0x1055: 0x43ad, 0x1056: 0x43cd, 0x1057: 0x67b1,
+ 0x1058: 0x0040, 0x1059: 0x43ed, 0x105a: 0x67c9, 0x105b: 0x67e1, 0x105c: 0x67f9, 0x105d: 0x6811,
+ 0x105e: 0x6829, 0x105f: 0x6859, 0x1060: 0x6889, 0x1061: 0x68b1, 0x1062: 0x68d9, 0x1063: 0x6901,
+ 0x1064: 0x6929, 0x1065: 0x6951, 0x1066: 0x6979, 0x1067: 0x69a1, 0x1068: 0x69c9, 0x1069: 0x69f1,
+ 0x106a: 0x6a21, 0x106b: 0x6a51, 0x106c: 0x6a81, 0x106d: 0x6ab1, 0x106e: 0x6ae1, 0x106f: 0x6b11,
+ 0x1070: 0x6b41, 0x1071: 0x6b71, 0x1072: 0x6ba1, 0x1073: 0x6bd1, 0x1074: 0x6c01, 0x1075: 0x6c31,
+ 0x1076: 0x6c61, 0x1077: 0x6c91, 0x1078: 0x6cc1, 0x1079: 0x6cf1, 0x107a: 0x6d21, 0x107b: 0x6d51,
+ 0x107c: 0x6d81, 0x107d: 0x6db1, 0x107e: 0x6de1, 0x107f: 0x440d,
+ // Block 0x42, offset 0x1080
+ 0x1080: 0xe00d, 0x1081: 0x0008, 0x1082: 0xe00d, 0x1083: 0x0008, 0x1084: 0xe00d, 0x1085: 0x0008,
+ 0x1086: 0xe00d, 0x1087: 0x0008, 0x1088: 0xe00d, 0x1089: 0x0008, 0x108a: 0xe00d, 0x108b: 0x0008,
+ 0x108c: 0xe00d, 0x108d: 0x0008, 0x108e: 0xe00d, 0x108f: 0x0008, 0x1090: 0xe00d, 0x1091: 0x0008,
+ 0x1092: 0xe00d, 0x1093: 0x0008, 0x1094: 0xe00d, 0x1095: 0x0008, 0x1096: 0xe00d, 0x1097: 0x0008,
+ 0x1098: 0xe00d, 0x1099: 0x0008, 0x109a: 0xe00d, 0x109b: 0x0008, 0x109c: 0xe00d, 0x109d: 0x0008,
+ 0x109e: 0xe00d, 0x109f: 0x0008, 0x10a0: 0xe00d, 0x10a1: 0x0008, 0x10a2: 0xe00d, 0x10a3: 0x0008,
+ 0x10a4: 0xe00d, 0x10a5: 0x0008, 0x10a6: 0xe00d, 0x10a7: 0x0008, 0x10a8: 0xe00d, 0x10a9: 0x0008,
+ 0x10aa: 0xe00d, 0x10ab: 0x0008, 0x10ac: 0xe00d, 0x10ad: 0x0008, 0x10ae: 0x0008, 0x10af: 0x1308,
+ 0x10b0: 0x1318, 0x10b1: 0x1318, 0x10b2: 0x1318, 0x10b3: 0x0018, 0x10b4: 0x1308, 0x10b5: 0x1308,
+ 0x10b6: 0x1308, 0x10b7: 0x1308, 0x10b8: 0x1308, 0x10b9: 0x1308, 0x10ba: 0x1308, 0x10bb: 0x1308,
+ 0x10bc: 0x1308, 0x10bd: 0x1308, 0x10be: 0x0018, 0x10bf: 0x0008,
+ // Block 0x43, offset 0x10c0
+ 0x10c0: 0xe00d, 0x10c1: 0x0008, 0x10c2: 0xe00d, 0x10c3: 0x0008, 0x10c4: 0xe00d, 0x10c5: 0x0008,
+ 0x10c6: 0xe00d, 0x10c7: 0x0008, 0x10c8: 0xe00d, 0x10c9: 0x0008, 0x10ca: 0xe00d, 0x10cb: 0x0008,
+ 0x10cc: 0xe00d, 0x10cd: 0x0008, 0x10ce: 0xe00d, 0x10cf: 0x0008, 0x10d0: 0xe00d, 0x10d1: 0x0008,
+ 0x10d2: 0xe00d, 0x10d3: 0x0008, 0x10d4: 0xe00d, 0x10d5: 0x0008, 0x10d6: 0xe00d, 0x10d7: 0x0008,
+ 0x10d8: 0xe00d, 0x10d9: 0x0008, 0x10da: 0xe00d, 0x10db: 0x0008, 0x10dc: 0x0ea1, 0x10dd: 0x6e11,
+ 0x10de: 0x1308, 0x10df: 0x1308, 0x10e0: 0x0008, 0x10e1: 0x0008, 0x10e2: 0x0008, 0x10e3: 0x0008,
+ 0x10e4: 0x0008, 0x10e5: 0x0008, 0x10e6: 0x0008, 0x10e7: 0x0008, 0x10e8: 0x0008, 0x10e9: 0x0008,
+ 0x10ea: 0x0008, 0x10eb: 0x0008, 0x10ec: 0x0008, 0x10ed: 0x0008, 0x10ee: 0x0008, 0x10ef: 0x0008,
+ 0x10f0: 0x0008, 0x10f1: 0x0008, 0x10f2: 0x0008, 0x10f3: 0x0008, 0x10f4: 0x0008, 0x10f5: 0x0008,
+ 0x10f6: 0x0008, 0x10f7: 0x0008, 0x10f8: 0x0008, 0x10f9: 0x0008, 0x10fa: 0x0008, 0x10fb: 0x0008,
+ 0x10fc: 0x0008, 0x10fd: 0x0008, 0x10fe: 0x0008, 0x10ff: 0x0008,
+ // Block 0x44, offset 0x1100
+ 0x1100: 0x0018, 0x1101: 0x0018, 0x1102: 0x0018, 0x1103: 0x0018, 0x1104: 0x0018, 0x1105: 0x0018,
+ 0x1106: 0x0018, 0x1107: 0x0018, 0x1108: 0x0018, 0x1109: 0x0018, 0x110a: 0x0018, 0x110b: 0x0018,
+ 0x110c: 0x0018, 0x110d: 0x0018, 0x110e: 0x0018, 0x110f: 0x0018, 0x1110: 0x0018, 0x1111: 0x0018,
+ 0x1112: 0x0018, 0x1113: 0x0018, 0x1114: 0x0018, 0x1115: 0x0018, 0x1116: 0x0018, 0x1117: 0x0008,
+ 0x1118: 0x0008, 0x1119: 0x0008, 0x111a: 0x0008, 0x111b: 0x0008, 0x111c: 0x0008, 0x111d: 0x0008,
+ 0x111e: 0x0008, 0x111f: 0x0008, 0x1120: 0x0018, 0x1121: 0x0018, 0x1122: 0xe00d, 0x1123: 0x0008,
+ 0x1124: 0xe00d, 0x1125: 0x0008, 0x1126: 0xe00d, 0x1127: 0x0008, 0x1128: 0xe00d, 0x1129: 0x0008,
+ 0x112a: 0xe00d, 0x112b: 0x0008, 0x112c: 0xe00d, 0x112d: 0x0008, 0x112e: 0xe00d, 0x112f: 0x0008,
+ 0x1130: 0x0008, 0x1131: 0x0008, 0x1132: 0xe00d, 0x1133: 0x0008, 0x1134: 0xe00d, 0x1135: 0x0008,
+ 0x1136: 0xe00d, 0x1137: 0x0008, 0x1138: 0xe00d, 0x1139: 0x0008, 0x113a: 0xe00d, 0x113b: 0x0008,
+ 0x113c: 0xe00d, 0x113d: 0x0008, 0x113e: 0xe00d, 0x113f: 0x0008,
+ // Block 0x45, offset 0x1140
+ 0x1140: 0xe00d, 0x1141: 0x0008, 0x1142: 0xe00d, 0x1143: 0x0008, 0x1144: 0xe00d, 0x1145: 0x0008,
+ 0x1146: 0xe00d, 0x1147: 0x0008, 0x1148: 0xe00d, 0x1149: 0x0008, 0x114a: 0xe00d, 0x114b: 0x0008,
+ 0x114c: 0xe00d, 0x114d: 0x0008, 0x114e: 0xe00d, 0x114f: 0x0008, 0x1150: 0xe00d, 0x1151: 0x0008,
+ 0x1152: 0xe00d, 0x1153: 0x0008, 0x1154: 0xe00d, 0x1155: 0x0008, 0x1156: 0xe00d, 0x1157: 0x0008,
+ 0x1158: 0xe00d, 0x1159: 0x0008, 0x115a: 0xe00d, 0x115b: 0x0008, 0x115c: 0xe00d, 0x115d: 0x0008,
+ 0x115e: 0xe00d, 0x115f: 0x0008, 0x1160: 0xe00d, 0x1161: 0x0008, 0x1162: 0xe00d, 0x1163: 0x0008,
+ 0x1164: 0xe00d, 0x1165: 0x0008, 0x1166: 0xe00d, 0x1167: 0x0008, 0x1168: 0xe00d, 0x1169: 0x0008,
+ 0x116a: 0xe00d, 0x116b: 0x0008, 0x116c: 0xe00d, 0x116d: 0x0008, 0x116e: 0xe00d, 0x116f: 0x0008,
+ 0x1170: 0xe0fd, 0x1171: 0x0008, 0x1172: 0x0008, 0x1173: 0x0008, 0x1174: 0x0008, 0x1175: 0x0008,
+ 0x1176: 0x0008, 0x1177: 0x0008, 0x1178: 0x0008, 0x1179: 0xe01d, 0x117a: 0x0008, 0x117b: 0xe03d,
+ 0x117c: 0x0008, 0x117d: 0x442d, 0x117e: 0xe00d, 0x117f: 0x0008,
+ // Block 0x46, offset 0x1180
+ 0x1180: 0xe00d, 0x1181: 0x0008, 0x1182: 0xe00d, 0x1183: 0x0008, 0x1184: 0xe00d, 0x1185: 0x0008,
+ 0x1186: 0xe00d, 0x1187: 0x0008, 0x1188: 0x0008, 0x1189: 0x0018, 0x118a: 0x0018, 0x118b: 0xe03d,
+ 0x118c: 0x0008, 0x118d: 0x11d9, 0x118e: 0x0008, 0x118f: 0x0008, 0x1190: 0xe00d, 0x1191: 0x0008,
+ 0x1192: 0xe00d, 0x1193: 0x0008, 0x1194: 0x0008, 0x1195: 0x0008, 0x1196: 0xe00d, 0x1197: 0x0008,
+ 0x1198: 0xe00d, 0x1199: 0x0008, 0x119a: 0xe00d, 0x119b: 0x0008, 0x119c: 0xe00d, 0x119d: 0x0008,
+ 0x119e: 0xe00d, 0x119f: 0x0008, 0x11a0: 0xe00d, 0x11a1: 0x0008, 0x11a2: 0xe00d, 0x11a3: 0x0008,
+ 0x11a4: 0xe00d, 0x11a5: 0x0008, 0x11a6: 0xe00d, 0x11a7: 0x0008, 0x11a8: 0xe00d, 0x11a9: 0x0008,
+ 0x11aa: 0x6e29, 0x11ab: 0x1029, 0x11ac: 0x11c1, 0x11ad: 0x6e41, 0x11ae: 0x1221, 0x11af: 0x0040,
+ 0x11b0: 0x6e59, 0x11b1: 0x6e71, 0x11b2: 0x1239, 0x11b3: 0x444d, 0x11b4: 0xe00d, 0x11b5: 0x0008,
+ 0x11b6: 0xe00d, 0x11b7: 0x0008, 0x11b8: 0x0040, 0x11b9: 0x0040, 0x11ba: 0x0040, 0x11bb: 0x0040,
+ 0x11bc: 0x0040, 0x11bd: 0x0040, 0x11be: 0x0040, 0x11bf: 0x0040,
+ // Block 0x47, offset 0x11c0
+ 0x11c0: 0x64d5, 0x11c1: 0x64f5, 0x11c2: 0x6515, 0x11c3: 0x6535, 0x11c4: 0x6555, 0x11c5: 0x6575,
+ 0x11c6: 0x6595, 0x11c7: 0x65b5, 0x11c8: 0x65d5, 0x11c9: 0x65f5, 0x11ca: 0x6615, 0x11cb: 0x6635,
+ 0x11cc: 0x6655, 0x11cd: 0x6675, 0x11ce: 0x0008, 0x11cf: 0x0008, 0x11d0: 0x6695, 0x11d1: 0x0008,
+ 0x11d2: 0x66b5, 0x11d3: 0x0008, 0x11d4: 0x0008, 0x11d5: 0x66d5, 0x11d6: 0x66f5, 0x11d7: 0x6715,
+ 0x11d8: 0x6735, 0x11d9: 0x6755, 0x11da: 0x6775, 0x11db: 0x6795, 0x11dc: 0x67b5, 0x11dd: 0x67d5,
+ 0x11de: 0x67f5, 0x11df: 0x0008, 0x11e0: 0x6815, 0x11e1: 0x0008, 0x11e2: 0x6835, 0x11e3: 0x0008,
+ 0x11e4: 0x0008, 0x11e5: 0x6855, 0x11e6: 0x6875, 0x11e7: 0x0008, 0x11e8: 0x0008, 0x11e9: 0x0008,
+ 0x11ea: 0x6895, 0x11eb: 0x68b5, 0x11ec: 0x68d5, 0x11ed: 0x68f5, 0x11ee: 0x6915, 0x11ef: 0x6935,
+ 0x11f0: 0x6955, 0x11f1: 0x6975, 0x11f2: 0x6995, 0x11f3: 0x69b5, 0x11f4: 0x69d5, 0x11f5: 0x69f5,
+ 0x11f6: 0x6a15, 0x11f7: 0x6a35, 0x11f8: 0x6a55, 0x11f9: 0x6a75, 0x11fa: 0x6a95, 0x11fb: 0x6ab5,
+ 0x11fc: 0x6ad5, 0x11fd: 0x6af5, 0x11fe: 0x6b15, 0x11ff: 0x6b35,
+ // Block 0x48, offset 0x1200
+ 0x1200: 0x7a95, 0x1201: 0x7ab5, 0x1202: 0x7ad5, 0x1203: 0x7af5, 0x1204: 0x7b15, 0x1205: 0x7b35,
+ 0x1206: 0x7b55, 0x1207: 0x7b75, 0x1208: 0x7b95, 0x1209: 0x7bb5, 0x120a: 0x7bd5, 0x120b: 0x7bf5,
+ 0x120c: 0x7c15, 0x120d: 0x7c35, 0x120e: 0x7c55, 0x120f: 0x6ec9, 0x1210: 0x6ef1, 0x1211: 0x6f19,
+ 0x1212: 0x7c75, 0x1213: 0x7c95, 0x1214: 0x7cb5, 0x1215: 0x6f41, 0x1216: 0x6f69, 0x1217: 0x6f91,
+ 0x1218: 0x7cd5, 0x1219: 0x7cf5, 0x121a: 0x0040, 0x121b: 0x0040, 0x121c: 0x0040, 0x121d: 0x0040,
+ 0x121e: 0x0040, 0x121f: 0x0040, 0x1220: 0x0040, 0x1221: 0x0040, 0x1222: 0x0040, 0x1223: 0x0040,
+ 0x1224: 0x0040, 0x1225: 0x0040, 0x1226: 0x0040, 0x1227: 0x0040, 0x1228: 0x0040, 0x1229: 0x0040,
+ 0x122a: 0x0040, 0x122b: 0x0040, 0x122c: 0x0040, 0x122d: 0x0040, 0x122e: 0x0040, 0x122f: 0x0040,
+ 0x1230: 0x0040, 0x1231: 0x0040, 0x1232: 0x0040, 0x1233: 0x0040, 0x1234: 0x0040, 0x1235: 0x0040,
+ 0x1236: 0x0040, 0x1237: 0x0040, 0x1238: 0x0040, 0x1239: 0x0040, 0x123a: 0x0040, 0x123b: 0x0040,
+ 0x123c: 0x0040, 0x123d: 0x0040, 0x123e: 0x0040, 0x123f: 0x0040,
+ // Block 0x49, offset 0x1240
+ 0x1240: 0x6fb9, 0x1241: 0x6fd1, 0x1242: 0x6fe9, 0x1243: 0x7d15, 0x1244: 0x7d35, 0x1245: 0x7001,
+ 0x1246: 0x7001, 0x1247: 0x0040, 0x1248: 0x0040, 0x1249: 0x0040, 0x124a: 0x0040, 0x124b: 0x0040,
+ 0x124c: 0x0040, 0x124d: 0x0040, 0x124e: 0x0040, 0x124f: 0x0040, 0x1250: 0x0040, 0x1251: 0x0040,
+ 0x1252: 0x0040, 0x1253: 0x7019, 0x1254: 0x7041, 0x1255: 0x7069, 0x1256: 0x7091, 0x1257: 0x70b9,
+ 0x1258: 0x0040, 0x1259: 0x0040, 0x125a: 0x0040, 0x125b: 0x0040, 0x125c: 0x0040, 0x125d: 0x70e1,
+ 0x125e: 0x1308, 0x125f: 0x7109, 0x1260: 0x7131, 0x1261: 0x20a9, 0x1262: 0x20f1, 0x1263: 0x7149,
+ 0x1264: 0x7161, 0x1265: 0x7179, 0x1266: 0x7191, 0x1267: 0x71a9, 0x1268: 0x71c1, 0x1269: 0x1fb2,
+ 0x126a: 0x71d9, 0x126b: 0x7201, 0x126c: 0x7229, 0x126d: 0x7261, 0x126e: 0x7299, 0x126f: 0x72c1,
+ 0x1270: 0x72e9, 0x1271: 0x7311, 0x1272: 0x7339, 0x1273: 0x7361, 0x1274: 0x7389, 0x1275: 0x73b1,
+ 0x1276: 0x73d9, 0x1277: 0x0040, 0x1278: 0x7401, 0x1279: 0x7429, 0x127a: 0x7451, 0x127b: 0x7479,
+ 0x127c: 0x74a1, 0x127d: 0x0040, 0x127e: 0x74c9, 0x127f: 0x0040,
+ // Block 0x4a, offset 0x1280
+ 0x1280: 0x74f1, 0x1281: 0x7519, 0x1282: 0x0040, 0x1283: 0x7541, 0x1284: 0x7569, 0x1285: 0x0040,
+ 0x1286: 0x7591, 0x1287: 0x75b9, 0x1288: 0x75e1, 0x1289: 0x7609, 0x128a: 0x7631, 0x128b: 0x7659,
+ 0x128c: 0x7681, 0x128d: 0x76a9, 0x128e: 0x76d1, 0x128f: 0x76f9, 0x1290: 0x7721, 0x1291: 0x7721,
+ 0x1292: 0x7739, 0x1293: 0x7739, 0x1294: 0x7739, 0x1295: 0x7739, 0x1296: 0x7751, 0x1297: 0x7751,
+ 0x1298: 0x7751, 0x1299: 0x7751, 0x129a: 0x7769, 0x129b: 0x7769, 0x129c: 0x7769, 0x129d: 0x7769,
+ 0x129e: 0x7781, 0x129f: 0x7781, 0x12a0: 0x7781, 0x12a1: 0x7781, 0x12a2: 0x7799, 0x12a3: 0x7799,
+ 0x12a4: 0x7799, 0x12a5: 0x7799, 0x12a6: 0x77b1, 0x12a7: 0x77b1, 0x12a8: 0x77b1, 0x12a9: 0x77b1,
+ 0x12aa: 0x77c9, 0x12ab: 0x77c9, 0x12ac: 0x77c9, 0x12ad: 0x77c9, 0x12ae: 0x77e1, 0x12af: 0x77e1,
+ 0x12b0: 0x77e1, 0x12b1: 0x77e1, 0x12b2: 0x77f9, 0x12b3: 0x77f9, 0x12b4: 0x77f9, 0x12b5: 0x77f9,
+ 0x12b6: 0x7811, 0x12b7: 0x7811, 0x12b8: 0x7811, 0x12b9: 0x7811, 0x12ba: 0x7829, 0x12bb: 0x7829,
+ 0x12bc: 0x7829, 0x12bd: 0x7829, 0x12be: 0x7841, 0x12bf: 0x7841,
+ // Block 0x4b, offset 0x12c0
+ 0x12c0: 0x7841, 0x12c1: 0x7841, 0x12c2: 0x7859, 0x12c3: 0x7859, 0x12c4: 0x7871, 0x12c5: 0x7871,
+ 0x12c6: 0x7889, 0x12c7: 0x7889, 0x12c8: 0x78a1, 0x12c9: 0x78a1, 0x12ca: 0x78b9, 0x12cb: 0x78b9,
+ 0x12cc: 0x78d1, 0x12cd: 0x78d1, 0x12ce: 0x78e9, 0x12cf: 0x78e9, 0x12d0: 0x78e9, 0x12d1: 0x78e9,
+ 0x12d2: 0x7901, 0x12d3: 0x7901, 0x12d4: 0x7901, 0x12d5: 0x7901, 0x12d6: 0x7919, 0x12d7: 0x7919,
+ 0x12d8: 0x7919, 0x12d9: 0x7919, 0x12da: 0x7931, 0x12db: 0x7931, 0x12dc: 0x7931, 0x12dd: 0x7931,
+ 0x12de: 0x7949, 0x12df: 0x7949, 0x12e0: 0x7961, 0x12e1: 0x7961, 0x12e2: 0x7961, 0x12e3: 0x7961,
+ 0x12e4: 0x7979, 0x12e5: 0x7979, 0x12e6: 0x7991, 0x12e7: 0x7991, 0x12e8: 0x7991, 0x12e9: 0x7991,
+ 0x12ea: 0x79a9, 0x12eb: 0x79a9, 0x12ec: 0x79a9, 0x12ed: 0x79a9, 0x12ee: 0x79c1, 0x12ef: 0x79c1,
+ 0x12f0: 0x79d9, 0x12f1: 0x79d9, 0x12f2: 0x0018, 0x12f3: 0x0018, 0x12f4: 0x0018, 0x12f5: 0x0018,
+ 0x12f6: 0x0018, 0x12f7: 0x0018, 0x12f8: 0x0018, 0x12f9: 0x0018, 0x12fa: 0x0018, 0x12fb: 0x0018,
+ 0x12fc: 0x0018, 0x12fd: 0x0018, 0x12fe: 0x0018, 0x12ff: 0x0018,
+ // Block 0x4c, offset 0x1300
+ 0x1300: 0x0018, 0x1301: 0x0018, 0x1302: 0x0040, 0x1303: 0x0040, 0x1304: 0x0040, 0x1305: 0x0040,
+ 0x1306: 0x0040, 0x1307: 0x0040, 0x1308: 0x0040, 0x1309: 0x0040, 0x130a: 0x0040, 0x130b: 0x0040,
+ 0x130c: 0x0040, 0x130d: 0x0040, 0x130e: 0x0040, 0x130f: 0x0040, 0x1310: 0x0040, 0x1311: 0x0040,
+ 0x1312: 0x0040, 0x1313: 0x79f1, 0x1314: 0x79f1, 0x1315: 0x79f1, 0x1316: 0x79f1, 0x1317: 0x7a09,
+ 0x1318: 0x7a09, 0x1319: 0x7a21, 0x131a: 0x7a21, 0x131b: 0x7a39, 0x131c: 0x7a39, 0x131d: 0x0479,
+ 0x131e: 0x7a51, 0x131f: 0x7a51, 0x1320: 0x7a69, 0x1321: 0x7a69, 0x1322: 0x7a81, 0x1323: 0x7a81,
+ 0x1324: 0x7a99, 0x1325: 0x7a99, 0x1326: 0x7a99, 0x1327: 0x7a99, 0x1328: 0x7ab1, 0x1329: 0x7ab1,
+ 0x132a: 0x7ac9, 0x132b: 0x7ac9, 0x132c: 0x7af1, 0x132d: 0x7af1, 0x132e: 0x7b19, 0x132f: 0x7b19,
+ 0x1330: 0x7b41, 0x1331: 0x7b41, 0x1332: 0x7b69, 0x1333: 0x7b69, 0x1334: 0x7b91, 0x1335: 0x7b91,
+ 0x1336: 0x7bb9, 0x1337: 0x7bb9, 0x1338: 0x7bb9, 0x1339: 0x7be1, 0x133a: 0x7be1, 0x133b: 0x7be1,
+ 0x133c: 0x7c09, 0x133d: 0x7c09, 0x133e: 0x7c09, 0x133f: 0x7c09,
+ // Block 0x4d, offset 0x1340
+ 0x1340: 0x85f9, 0x1341: 0x8621, 0x1342: 0x8649, 0x1343: 0x8671, 0x1344: 0x8699, 0x1345: 0x86c1,
+ 0x1346: 0x86e9, 0x1347: 0x8711, 0x1348: 0x8739, 0x1349: 0x8761, 0x134a: 0x8789, 0x134b: 0x87b1,
+ 0x134c: 0x87d9, 0x134d: 0x8801, 0x134e: 0x8829, 0x134f: 0x8851, 0x1350: 0x8879, 0x1351: 0x88a1,
+ 0x1352: 0x88c9, 0x1353: 0x88f1, 0x1354: 0x8919, 0x1355: 0x8941, 0x1356: 0x8969, 0x1357: 0x8991,
+ 0x1358: 0x89b9, 0x1359: 0x89e1, 0x135a: 0x8a09, 0x135b: 0x8a31, 0x135c: 0x8a59, 0x135d: 0x8a81,
+ 0x135e: 0x8aaa, 0x135f: 0x8ada, 0x1360: 0x8b0a, 0x1361: 0x8b3a, 0x1362: 0x8b6a, 0x1363: 0x8b9a,
+ 0x1364: 0x8bc9, 0x1365: 0x8bf1, 0x1366: 0x7c71, 0x1367: 0x8c19, 0x1368: 0x7be1, 0x1369: 0x7c99,
+ 0x136a: 0x8c41, 0x136b: 0x8c69, 0x136c: 0x7d39, 0x136d: 0x8c91, 0x136e: 0x7d61, 0x136f: 0x7d89,
+ 0x1370: 0x8cb9, 0x1371: 0x8ce1, 0x1372: 0x7e29, 0x1373: 0x8d09, 0x1374: 0x7e51, 0x1375: 0x7e79,
+ 0x1376: 0x8d31, 0x1377: 0x8d59, 0x1378: 0x7ec9, 0x1379: 0x8d81, 0x137a: 0x7ef1, 0x137b: 0x7f19,
+ 0x137c: 0x83a1, 0x137d: 0x83c9, 0x137e: 0x8441, 0x137f: 0x8469,
+ // Block 0x4e, offset 0x1380
+ 0x1380: 0x8491, 0x1381: 0x8531, 0x1382: 0x8559, 0x1383: 0x8581, 0x1384: 0x85a9, 0x1385: 0x8649,
+ 0x1386: 0x8671, 0x1387: 0x8699, 0x1388: 0x8da9, 0x1389: 0x8739, 0x138a: 0x8dd1, 0x138b: 0x8df9,
+ 0x138c: 0x8829, 0x138d: 0x8e21, 0x138e: 0x8851, 0x138f: 0x8879, 0x1390: 0x8a81, 0x1391: 0x8e49,
+ 0x1392: 0x8e71, 0x1393: 0x89b9, 0x1394: 0x8e99, 0x1395: 0x89e1, 0x1396: 0x8a09, 0x1397: 0x7c21,
+ 0x1398: 0x7c49, 0x1399: 0x8ec1, 0x139a: 0x7c71, 0x139b: 0x8ee9, 0x139c: 0x7cc1, 0x139d: 0x7ce9,
+ 0x139e: 0x7d11, 0x139f: 0x7d39, 0x13a0: 0x8f11, 0x13a1: 0x7db1, 0x13a2: 0x7dd9, 0x13a3: 0x7e01,
+ 0x13a4: 0x7e29, 0x13a5: 0x8f39, 0x13a6: 0x7ec9, 0x13a7: 0x7f41, 0x13a8: 0x7f69, 0x13a9: 0x7f91,
+ 0x13aa: 0x7fb9, 0x13ab: 0x7fe1, 0x13ac: 0x8031, 0x13ad: 0x8059, 0x13ae: 0x8081, 0x13af: 0x80a9,
+ 0x13b0: 0x80d1, 0x13b1: 0x80f9, 0x13b2: 0x8f61, 0x13b3: 0x8121, 0x13b4: 0x8149, 0x13b5: 0x8171,
+ 0x13b6: 0x8199, 0x13b7: 0x81c1, 0x13b8: 0x81e9, 0x13b9: 0x8239, 0x13ba: 0x8261, 0x13bb: 0x8289,
+ 0x13bc: 0x82b1, 0x13bd: 0x82d9, 0x13be: 0x8301, 0x13bf: 0x8329,
+ // Block 0x4f, offset 0x13c0
+ 0x13c0: 0x8351, 0x13c1: 0x8379, 0x13c2: 0x83f1, 0x13c3: 0x8419, 0x13c4: 0x84b9, 0x13c5: 0x84e1,
+ 0x13c6: 0x8509, 0x13c7: 0x8531, 0x13c8: 0x8559, 0x13c9: 0x85d1, 0x13ca: 0x85f9, 0x13cb: 0x8621,
+ 0x13cc: 0x8649, 0x13cd: 0x8f89, 0x13ce: 0x86c1, 0x13cf: 0x86e9, 0x13d0: 0x8711, 0x13d1: 0x8739,
+ 0x13d2: 0x87b1, 0x13d3: 0x87d9, 0x13d4: 0x8801, 0x13d5: 0x8829, 0x13d6: 0x8fb1, 0x13d7: 0x88a1,
+ 0x13d8: 0x88c9, 0x13d9: 0x8fd9, 0x13da: 0x8941, 0x13db: 0x8969, 0x13dc: 0x8991, 0x13dd: 0x89b9,
+ 0x13de: 0x9001, 0x13df: 0x7c71, 0x13e0: 0x8ee9, 0x13e1: 0x7d39, 0x13e2: 0x8f11, 0x13e3: 0x7e29,
+ 0x13e4: 0x8f39, 0x13e5: 0x7ec9, 0x13e6: 0x9029, 0x13e7: 0x80d1, 0x13e8: 0x9051, 0x13e9: 0x9079,
+ 0x13ea: 0x90a1, 0x13eb: 0x8531, 0x13ec: 0x8559, 0x13ed: 0x8649, 0x13ee: 0x8829, 0x13ef: 0x8fb1,
+ 0x13f0: 0x89b9, 0x13f1: 0x9001, 0x13f2: 0x90c9, 0x13f3: 0x9101, 0x13f4: 0x9139, 0x13f5: 0x9171,
+ 0x13f6: 0x9199, 0x13f7: 0x91c1, 0x13f8: 0x91e9, 0x13f9: 0x9211, 0x13fa: 0x9239, 0x13fb: 0x9261,
+ 0x13fc: 0x9289, 0x13fd: 0x92b1, 0x13fe: 0x92d9, 0x13ff: 0x9301,
+ // Block 0x50, offset 0x1400
+ 0x1400: 0x9329, 0x1401: 0x9351, 0x1402: 0x9379, 0x1403: 0x93a1, 0x1404: 0x93c9, 0x1405: 0x93f1,
+ 0x1406: 0x9419, 0x1407: 0x9441, 0x1408: 0x9469, 0x1409: 0x9491, 0x140a: 0x94b9, 0x140b: 0x94e1,
+ 0x140c: 0x9079, 0x140d: 0x9509, 0x140e: 0x9531, 0x140f: 0x9559, 0x1410: 0x9581, 0x1411: 0x9171,
+ 0x1412: 0x9199, 0x1413: 0x91c1, 0x1414: 0x91e9, 0x1415: 0x9211, 0x1416: 0x9239, 0x1417: 0x9261,
+ 0x1418: 0x9289, 0x1419: 0x92b1, 0x141a: 0x92d9, 0x141b: 0x9301, 0x141c: 0x9329, 0x141d: 0x9351,
+ 0x141e: 0x9379, 0x141f: 0x93a1, 0x1420: 0x93c9, 0x1421: 0x93f1, 0x1422: 0x9419, 0x1423: 0x9441,
+ 0x1424: 0x9469, 0x1425: 0x9491, 0x1426: 0x94b9, 0x1427: 0x94e1, 0x1428: 0x9079, 0x1429: 0x9509,
+ 0x142a: 0x9531, 0x142b: 0x9559, 0x142c: 0x9581, 0x142d: 0x9491, 0x142e: 0x94b9, 0x142f: 0x94e1,
+ 0x1430: 0x9079, 0x1431: 0x9051, 0x1432: 0x90a1, 0x1433: 0x8211, 0x1434: 0x8059, 0x1435: 0x8081,
+ 0x1436: 0x80a9, 0x1437: 0x9491, 0x1438: 0x94b9, 0x1439: 0x94e1, 0x143a: 0x8211, 0x143b: 0x8239,
+ 0x143c: 0x95a9, 0x143d: 0x95a9, 0x143e: 0x0018, 0x143f: 0x0018,
+ // Block 0x51, offset 0x1440
+ 0x1440: 0x0040, 0x1441: 0x0040, 0x1442: 0x0040, 0x1443: 0x0040, 0x1444: 0x0040, 0x1445: 0x0040,
+ 0x1446: 0x0040, 0x1447: 0x0040, 0x1448: 0x0040, 0x1449: 0x0040, 0x144a: 0x0040, 0x144b: 0x0040,
+ 0x144c: 0x0040, 0x144d: 0x0040, 0x144e: 0x0040, 0x144f: 0x0040, 0x1450: 0x95d1, 0x1451: 0x9609,
+ 0x1452: 0x9609, 0x1453: 0x9641, 0x1454: 0x9679, 0x1455: 0x96b1, 0x1456: 0x96e9, 0x1457: 0x9721,
+ 0x1458: 0x9759, 0x1459: 0x9759, 0x145a: 0x9791, 0x145b: 0x97c9, 0x145c: 0x9801, 0x145d: 0x9839,
+ 0x145e: 0x9871, 0x145f: 0x98a9, 0x1460: 0x98a9, 0x1461: 0x98e1, 0x1462: 0x9919, 0x1463: 0x9919,
+ 0x1464: 0x9951, 0x1465: 0x9951, 0x1466: 0x9989, 0x1467: 0x99c1, 0x1468: 0x99c1, 0x1469: 0x99f9,
+ 0x146a: 0x9a31, 0x146b: 0x9a31, 0x146c: 0x9a69, 0x146d: 0x9a69, 0x146e: 0x9aa1, 0x146f: 0x9ad9,
+ 0x1470: 0x9ad9, 0x1471: 0x9b11, 0x1472: 0x9b11, 0x1473: 0x9b49, 0x1474: 0x9b81, 0x1475: 0x9bb9,
+ 0x1476: 0x9bf1, 0x1477: 0x9bf1, 0x1478: 0x9c29, 0x1479: 0x9c61, 0x147a: 0x9c99, 0x147b: 0x9cd1,
+ 0x147c: 0x9d09, 0x147d: 0x9d09, 0x147e: 0x9d41, 0x147f: 0x9d79,
+ // Block 0x52, offset 0x1480
+ 0x1480: 0xa949, 0x1481: 0xa981, 0x1482: 0xa9b9, 0x1483: 0xa8a1, 0x1484: 0x9bb9, 0x1485: 0x9989,
+ 0x1486: 0xa9f1, 0x1487: 0xaa29, 0x1488: 0x0040, 0x1489: 0x0040, 0x148a: 0x0040, 0x148b: 0x0040,
+ 0x148c: 0x0040, 0x148d: 0x0040, 0x148e: 0x0040, 0x148f: 0x0040, 0x1490: 0x0040, 0x1491: 0x0040,
+ 0x1492: 0x0040, 0x1493: 0x0040, 0x1494: 0x0040, 0x1495: 0x0040, 0x1496: 0x0040, 0x1497: 0x0040,
+ 0x1498: 0x0040, 0x1499: 0x0040, 0x149a: 0x0040, 0x149b: 0x0040, 0x149c: 0x0040, 0x149d: 0x0040,
+ 0x149e: 0x0040, 0x149f: 0x0040, 0x14a0: 0x0040, 0x14a1: 0x0040, 0x14a2: 0x0040, 0x14a3: 0x0040,
+ 0x14a4: 0x0040, 0x14a5: 0x0040, 0x14a6: 0x0040, 0x14a7: 0x0040, 0x14a8: 0x0040, 0x14a9: 0x0040,
+ 0x14aa: 0x0040, 0x14ab: 0x0040, 0x14ac: 0x0040, 0x14ad: 0x0040, 0x14ae: 0x0040, 0x14af: 0x0040,
+ 0x14b0: 0xaa61, 0x14b1: 0xaa99, 0x14b2: 0xaad1, 0x14b3: 0xab19, 0x14b4: 0xab61, 0x14b5: 0xaba9,
+ 0x14b6: 0xabf1, 0x14b7: 0xac39, 0x14b8: 0xac81, 0x14b9: 0xacc9, 0x14ba: 0xad02, 0x14bb: 0xae12,
+ 0x14bc: 0xae91, 0x14bd: 0x0018, 0x14be: 0x0040, 0x14bf: 0x0040,
+ // Block 0x53, offset 0x14c0
+ 0x14c0: 0x13c0, 0x14c1: 0x13c0, 0x14c2: 0x13c0, 0x14c3: 0x13c0, 0x14c4: 0x13c0, 0x14c5: 0x13c0,
+ 0x14c6: 0x13c0, 0x14c7: 0x13c0, 0x14c8: 0x13c0, 0x14c9: 0x13c0, 0x14ca: 0x13c0, 0x14cb: 0x13c0,
+ 0x14cc: 0x13c0, 0x14cd: 0x13c0, 0x14ce: 0x13c0, 0x14cf: 0x13c0, 0x14d0: 0xaeda, 0x14d1: 0x7d55,
+ 0x14d2: 0x0040, 0x14d3: 0xaeea, 0x14d4: 0x03c2, 0x14d5: 0xaefa, 0x14d6: 0xaf0a, 0x14d7: 0x7d75,
+ 0x14d8: 0x7d95, 0x14d9: 0x0040, 0x14da: 0x0040, 0x14db: 0x0040, 0x14dc: 0x0040, 0x14dd: 0x0040,
+ 0x14de: 0x0040, 0x14df: 0x0040, 0x14e0: 0x1308, 0x14e1: 0x1308, 0x14e2: 0x1308, 0x14e3: 0x1308,
+ 0x14e4: 0x1308, 0x14e5: 0x1308, 0x14e6: 0x1308, 0x14e7: 0x1308, 0x14e8: 0x1308, 0x14e9: 0x1308,
+ 0x14ea: 0x1308, 0x14eb: 0x1308, 0x14ec: 0x1308, 0x14ed: 0x1308, 0x14ee: 0x1308, 0x14ef: 0x1308,
+ 0x14f0: 0x0040, 0x14f1: 0x7db5, 0x14f2: 0x7dd5, 0x14f3: 0xaf1a, 0x14f4: 0xaf1a, 0x14f5: 0x1fd2,
+ 0x14f6: 0x1fe2, 0x14f7: 0xaf2a, 0x14f8: 0xaf3a, 0x14f9: 0x7df5, 0x14fa: 0x7e15, 0x14fb: 0x7e35,
+ 0x14fc: 0x7df5, 0x14fd: 0x7e55, 0x14fe: 0x7e75, 0x14ff: 0x7e55,
+ // Block 0x54, offset 0x1500
+ 0x1500: 0x7e95, 0x1501: 0x7eb5, 0x1502: 0x7ed5, 0x1503: 0x7eb5, 0x1504: 0x7ef5, 0x1505: 0x0018,
+ 0x1506: 0x0018, 0x1507: 0xaf4a, 0x1508: 0xaf5a, 0x1509: 0x7f16, 0x150a: 0x7f36, 0x150b: 0x7f56,
+ 0x150c: 0x7f76, 0x150d: 0xaf1a, 0x150e: 0xaf1a, 0x150f: 0xaf1a, 0x1510: 0xaeda, 0x1511: 0x7f95,
+ 0x1512: 0x0040, 0x1513: 0x0040, 0x1514: 0x03c2, 0x1515: 0xaeea, 0x1516: 0xaf0a, 0x1517: 0xaefa,
+ 0x1518: 0x7fb5, 0x1519: 0x1fd2, 0x151a: 0x1fe2, 0x151b: 0xaf2a, 0x151c: 0xaf3a, 0x151d: 0x7e95,
+ 0x151e: 0x7ef5, 0x151f: 0xaf6a, 0x1520: 0xaf7a, 0x1521: 0xaf8a, 0x1522: 0x1fb2, 0x1523: 0xaf99,
+ 0x1524: 0xafaa, 0x1525: 0xafba, 0x1526: 0x1fc2, 0x1527: 0x0040, 0x1528: 0xafca, 0x1529: 0xafda,
+ 0x152a: 0xafea, 0x152b: 0xaffa, 0x152c: 0x0040, 0x152d: 0x0040, 0x152e: 0x0040, 0x152f: 0x0040,
+ 0x1530: 0x7fd6, 0x1531: 0xb009, 0x1532: 0x7ff6, 0x1533: 0x0008, 0x1534: 0x8016, 0x1535: 0x0040,
+ 0x1536: 0x8036, 0x1537: 0xb031, 0x1538: 0x8056, 0x1539: 0xb059, 0x153a: 0x8076, 0x153b: 0xb081,
+ 0x153c: 0x8096, 0x153d: 0xb0a9, 0x153e: 0x80b6, 0x153f: 0xb0d1,
+ // Block 0x55, offset 0x1540
+ 0x1540: 0xb0f9, 0x1541: 0xb111, 0x1542: 0xb111, 0x1543: 0xb129, 0x1544: 0xb129, 0x1545: 0xb141,
+ 0x1546: 0xb141, 0x1547: 0xb159, 0x1548: 0xb159, 0x1549: 0xb171, 0x154a: 0xb171, 0x154b: 0xb171,
+ 0x154c: 0xb171, 0x154d: 0xb189, 0x154e: 0xb189, 0x154f: 0xb1a1, 0x1550: 0xb1a1, 0x1551: 0xb1a1,
+ 0x1552: 0xb1a1, 0x1553: 0xb1b9, 0x1554: 0xb1b9, 0x1555: 0xb1d1, 0x1556: 0xb1d1, 0x1557: 0xb1d1,
+ 0x1558: 0xb1d1, 0x1559: 0xb1e9, 0x155a: 0xb1e9, 0x155b: 0xb1e9, 0x155c: 0xb1e9, 0x155d: 0xb201,
+ 0x155e: 0xb201, 0x155f: 0xb201, 0x1560: 0xb201, 0x1561: 0xb219, 0x1562: 0xb219, 0x1563: 0xb219,
+ 0x1564: 0xb219, 0x1565: 0xb231, 0x1566: 0xb231, 0x1567: 0xb231, 0x1568: 0xb231, 0x1569: 0xb249,
+ 0x156a: 0xb249, 0x156b: 0xb261, 0x156c: 0xb261, 0x156d: 0xb279, 0x156e: 0xb279, 0x156f: 0xb291,
+ 0x1570: 0xb291, 0x1571: 0xb2a9, 0x1572: 0xb2a9, 0x1573: 0xb2a9, 0x1574: 0xb2a9, 0x1575: 0xb2c1,
+ 0x1576: 0xb2c1, 0x1577: 0xb2c1, 0x1578: 0xb2c1, 0x1579: 0xb2d9, 0x157a: 0xb2d9, 0x157b: 0xb2d9,
+ 0x157c: 0xb2d9, 0x157d: 0xb2f1, 0x157e: 0xb2f1, 0x157f: 0xb2f1,
+ // Block 0x56, offset 0x1580
+ 0x1580: 0xb2f1, 0x1581: 0xb309, 0x1582: 0xb309, 0x1583: 0xb309, 0x1584: 0xb309, 0x1585: 0xb321,
+ 0x1586: 0xb321, 0x1587: 0xb321, 0x1588: 0xb321, 0x1589: 0xb339, 0x158a: 0xb339, 0x158b: 0xb339,
+ 0x158c: 0xb339, 0x158d: 0xb351, 0x158e: 0xb351, 0x158f: 0xb351, 0x1590: 0xb351, 0x1591: 0xb369,
+ 0x1592: 0xb369, 0x1593: 0xb369, 0x1594: 0xb369, 0x1595: 0xb381, 0x1596: 0xb381, 0x1597: 0xb381,
+ 0x1598: 0xb381, 0x1599: 0xb399, 0x159a: 0xb399, 0x159b: 0xb399, 0x159c: 0xb399, 0x159d: 0xb3b1,
+ 0x159e: 0xb3b1, 0x159f: 0xb3b1, 0x15a0: 0xb3b1, 0x15a1: 0xb3c9, 0x15a2: 0xb3c9, 0x15a3: 0xb3c9,
+ 0x15a4: 0xb3c9, 0x15a5: 0xb3e1, 0x15a6: 0xb3e1, 0x15a7: 0xb3e1, 0x15a8: 0xb3e1, 0x15a9: 0xb3f9,
+ 0x15aa: 0xb3f9, 0x15ab: 0xb3f9, 0x15ac: 0xb3f9, 0x15ad: 0xb411, 0x15ae: 0xb411, 0x15af: 0x7ab1,
+ 0x15b0: 0x7ab1, 0x15b1: 0xb429, 0x15b2: 0xb429, 0x15b3: 0xb429, 0x15b4: 0xb429, 0x15b5: 0xb441,
+ 0x15b6: 0xb441, 0x15b7: 0xb469, 0x15b8: 0xb469, 0x15b9: 0xb491, 0x15ba: 0xb491, 0x15bb: 0xb4b9,
+ 0x15bc: 0xb4b9, 0x15bd: 0x0040, 0x15be: 0x0040, 0x15bf: 0x03c0,
+ // Block 0x57, offset 0x15c0
+ 0x15c0: 0x0040, 0x15c1: 0xaefa, 0x15c2: 0xb4e2, 0x15c3: 0xaf6a, 0x15c4: 0xafda, 0x15c5: 0xafea,
+ 0x15c6: 0xaf7a, 0x15c7: 0xb4f2, 0x15c8: 0x1fd2, 0x15c9: 0x1fe2, 0x15ca: 0xaf8a, 0x15cb: 0x1fb2,
+ 0x15cc: 0xaeda, 0x15cd: 0xaf99, 0x15ce: 0x29d1, 0x15cf: 0xb502, 0x15d0: 0x1f41, 0x15d1: 0x00c9,
+ 0x15d2: 0x0069, 0x15d3: 0x0079, 0x15d4: 0x1f51, 0x15d5: 0x1f61, 0x15d6: 0x1f71, 0x15d7: 0x1f81,
+ 0x15d8: 0x1f91, 0x15d9: 0x1fa1, 0x15da: 0xaeea, 0x15db: 0x03c2, 0x15dc: 0xafaa, 0x15dd: 0x1fc2,
+ 0x15de: 0xafba, 0x15df: 0xaf0a, 0x15e0: 0xaffa, 0x15e1: 0x0039, 0x15e2: 0x0ee9, 0x15e3: 0x1159,
+ 0x15e4: 0x0ef9, 0x15e5: 0x0f09, 0x15e6: 0x1199, 0x15e7: 0x0f31, 0x15e8: 0x0249, 0x15e9: 0x0f41,
+ 0x15ea: 0x0259, 0x15eb: 0x0f51, 0x15ec: 0x0359, 0x15ed: 0x0f61, 0x15ee: 0x0f71, 0x15ef: 0x00d9,
+ 0x15f0: 0x0f99, 0x15f1: 0x2039, 0x15f2: 0x0269, 0x15f3: 0x01d9, 0x15f4: 0x0fa9, 0x15f5: 0x0fb9,
+ 0x15f6: 0x1089, 0x15f7: 0x0279, 0x15f8: 0x0369, 0x15f9: 0x0289, 0x15fa: 0x13d1, 0x15fb: 0xaf4a,
+ 0x15fc: 0xafca, 0x15fd: 0xaf5a, 0x15fe: 0xb512, 0x15ff: 0xaf1a,
+ // Block 0x58, offset 0x1600
+ 0x1600: 0x1caa, 0x1601: 0x0039, 0x1602: 0x0ee9, 0x1603: 0x1159, 0x1604: 0x0ef9, 0x1605: 0x0f09,
+ 0x1606: 0x1199, 0x1607: 0x0f31, 0x1608: 0x0249, 0x1609: 0x0f41, 0x160a: 0x0259, 0x160b: 0x0f51,
+ 0x160c: 0x0359, 0x160d: 0x0f61, 0x160e: 0x0f71, 0x160f: 0x00d9, 0x1610: 0x0f99, 0x1611: 0x2039,
+ 0x1612: 0x0269, 0x1613: 0x01d9, 0x1614: 0x0fa9, 0x1615: 0x0fb9, 0x1616: 0x1089, 0x1617: 0x0279,
+ 0x1618: 0x0369, 0x1619: 0x0289, 0x161a: 0x13d1, 0x161b: 0xaf2a, 0x161c: 0xb522, 0x161d: 0xaf3a,
+ 0x161e: 0xb532, 0x161f: 0x80d5, 0x1620: 0x80f5, 0x1621: 0x29d1, 0x1622: 0x8115, 0x1623: 0x8115,
+ 0x1624: 0x8135, 0x1625: 0x8155, 0x1626: 0x8175, 0x1627: 0x8195, 0x1628: 0x81b5, 0x1629: 0x81d5,
+ 0x162a: 0x81f5, 0x162b: 0x8215, 0x162c: 0x8235, 0x162d: 0x8255, 0x162e: 0x8275, 0x162f: 0x8295,
+ 0x1630: 0x82b5, 0x1631: 0x82d5, 0x1632: 0x82f5, 0x1633: 0x8315, 0x1634: 0x8335, 0x1635: 0x8355,
+ 0x1636: 0x8375, 0x1637: 0x8395, 0x1638: 0x83b5, 0x1639: 0x83d5, 0x163a: 0x83f5, 0x163b: 0x8415,
+ 0x163c: 0x81b5, 0x163d: 0x8435, 0x163e: 0x8455, 0x163f: 0x8215,
+ // Block 0x59, offset 0x1640
+ 0x1640: 0x8475, 0x1641: 0x8495, 0x1642: 0x84b5, 0x1643: 0x84d5, 0x1644: 0x84f5, 0x1645: 0x8515,
+ 0x1646: 0x8535, 0x1647: 0x8555, 0x1648: 0x84d5, 0x1649: 0x8575, 0x164a: 0x84d5, 0x164b: 0x8595,
+ 0x164c: 0x8595, 0x164d: 0x85b5, 0x164e: 0x85b5, 0x164f: 0x85d5, 0x1650: 0x8515, 0x1651: 0x85f5,
+ 0x1652: 0x8615, 0x1653: 0x85f5, 0x1654: 0x8635, 0x1655: 0x8615, 0x1656: 0x8655, 0x1657: 0x8655,
+ 0x1658: 0x8675, 0x1659: 0x8675, 0x165a: 0x8695, 0x165b: 0x8695, 0x165c: 0x8615, 0x165d: 0x8115,
+ 0x165e: 0x86b5, 0x165f: 0x86d5, 0x1660: 0x0040, 0x1661: 0x86f5, 0x1662: 0x8715, 0x1663: 0x8735,
+ 0x1664: 0x8755, 0x1665: 0x8735, 0x1666: 0x8775, 0x1667: 0x8795, 0x1668: 0x87b5, 0x1669: 0x87b5,
+ 0x166a: 0x87d5, 0x166b: 0x87d5, 0x166c: 0x87f5, 0x166d: 0x87f5, 0x166e: 0x87d5, 0x166f: 0x87d5,
+ 0x1670: 0x8815, 0x1671: 0x8835, 0x1672: 0x8855, 0x1673: 0x8875, 0x1674: 0x8895, 0x1675: 0x88b5,
+ 0x1676: 0x88b5, 0x1677: 0x88b5, 0x1678: 0x88d5, 0x1679: 0x88d5, 0x167a: 0x88d5, 0x167b: 0x88d5,
+ 0x167c: 0x87b5, 0x167d: 0x87b5, 0x167e: 0x87b5, 0x167f: 0x0040,
+ // Block 0x5a, offset 0x1680
+ 0x1680: 0x0040, 0x1681: 0x0040, 0x1682: 0x8715, 0x1683: 0x86f5, 0x1684: 0x88f5, 0x1685: 0x86f5,
+ 0x1686: 0x8715, 0x1687: 0x86f5, 0x1688: 0x0040, 0x1689: 0x0040, 0x168a: 0x8915, 0x168b: 0x8715,
+ 0x168c: 0x8935, 0x168d: 0x88f5, 0x168e: 0x8935, 0x168f: 0x8715, 0x1690: 0x0040, 0x1691: 0x0040,
+ 0x1692: 0x8955, 0x1693: 0x8975, 0x1694: 0x8875, 0x1695: 0x8935, 0x1696: 0x88f5, 0x1697: 0x8935,
+ 0x1698: 0x0040, 0x1699: 0x0040, 0x169a: 0x8995, 0x169b: 0x89b5, 0x169c: 0x8995, 0x169d: 0x0040,
+ 0x169e: 0x0040, 0x169f: 0x0040, 0x16a0: 0xb541, 0x16a1: 0xb559, 0x16a2: 0xb571, 0x16a3: 0x89d6,
+ 0x16a4: 0xb589, 0x16a5: 0xb5a1, 0x16a6: 0x89f5, 0x16a7: 0x0040, 0x16a8: 0x8a15, 0x16a9: 0x8a35,
+ 0x16aa: 0x8a55, 0x16ab: 0x8a35, 0x16ac: 0x8a75, 0x16ad: 0x8a95, 0x16ae: 0x8ab5, 0x16af: 0x0040,
+ 0x16b0: 0x0040, 0x16b1: 0x0040, 0x16b2: 0x0040, 0x16b3: 0x0040, 0x16b4: 0x0040, 0x16b5: 0x0040,
+ 0x16b6: 0x0040, 0x16b7: 0x0040, 0x16b8: 0x0040, 0x16b9: 0x0340, 0x16ba: 0x0340, 0x16bb: 0x0340,
+ 0x16bc: 0x0040, 0x16bd: 0x0040, 0x16be: 0x0040, 0x16bf: 0x0040,
+ // Block 0x5b, offset 0x16c0
+ 0x16c0: 0x0208, 0x16c1: 0x0208, 0x16c2: 0x0208, 0x16c3: 0x0208, 0x16c4: 0x0208, 0x16c5: 0x0408,
+ 0x16c6: 0x0008, 0x16c7: 0x0408, 0x16c8: 0x0018, 0x16c9: 0x0408, 0x16ca: 0x0408, 0x16cb: 0x0008,
+ 0x16cc: 0x0008, 0x16cd: 0x0108, 0x16ce: 0x0408, 0x16cf: 0x0408, 0x16d0: 0x0408, 0x16d1: 0x0408,
+ 0x16d2: 0x0408, 0x16d3: 0x0208, 0x16d4: 0x0208, 0x16d5: 0x0208, 0x16d6: 0x0208, 0x16d7: 0x0108,
+ 0x16d8: 0x0208, 0x16d9: 0x0208, 0x16da: 0x0208, 0x16db: 0x0208, 0x16dc: 0x0208, 0x16dd: 0x0408,
+ 0x16de: 0x0208, 0x16df: 0x0208, 0x16e0: 0x0208, 0x16e1: 0x0408, 0x16e2: 0x0008, 0x16e3: 0x0008,
+ 0x16e4: 0x0408, 0x16e5: 0x1308, 0x16e6: 0x1308, 0x16e7: 0x0040, 0x16e8: 0x0040, 0x16e9: 0x0040,
+ 0x16ea: 0x0040, 0x16eb: 0x0218, 0x16ec: 0x0218, 0x16ed: 0x0218, 0x16ee: 0x0218, 0x16ef: 0x0418,
+ 0x16f0: 0x0018, 0x16f1: 0x0018, 0x16f2: 0x0018, 0x16f3: 0x0018, 0x16f4: 0x0018, 0x16f5: 0x0018,
+ 0x16f6: 0x0018, 0x16f7: 0x0040, 0x16f8: 0x0040, 0x16f9: 0x0040, 0x16fa: 0x0040, 0x16fb: 0x0040,
+ 0x16fc: 0x0040, 0x16fd: 0x0040, 0x16fe: 0x0040, 0x16ff: 0x0040,
+ // Block 0x5c, offset 0x1700
+ 0x1700: 0x0208, 0x1701: 0x0408, 0x1702: 0x0208, 0x1703: 0x0408, 0x1704: 0x0408, 0x1705: 0x0408,
+ 0x1706: 0x0208, 0x1707: 0x0208, 0x1708: 0x0208, 0x1709: 0x0408, 0x170a: 0x0208, 0x170b: 0x0208,
+ 0x170c: 0x0408, 0x170d: 0x0208, 0x170e: 0x0408, 0x170f: 0x0408, 0x1710: 0x0208, 0x1711: 0x0408,
+ 0x1712: 0x0040, 0x1713: 0x0040, 0x1714: 0x0040, 0x1715: 0x0040, 0x1716: 0x0040, 0x1717: 0x0040,
+ 0x1718: 0x0040, 0x1719: 0x0018, 0x171a: 0x0018, 0x171b: 0x0018, 0x171c: 0x0018, 0x171d: 0x0040,
+ 0x171e: 0x0040, 0x171f: 0x0040, 0x1720: 0x0040, 0x1721: 0x0040, 0x1722: 0x0040, 0x1723: 0x0040,
+ 0x1724: 0x0040, 0x1725: 0x0040, 0x1726: 0x0040, 0x1727: 0x0040, 0x1728: 0x0040, 0x1729: 0x0418,
+ 0x172a: 0x0418, 0x172b: 0x0418, 0x172c: 0x0418, 0x172d: 0x0218, 0x172e: 0x0218, 0x172f: 0x0018,
+ 0x1730: 0x0040, 0x1731: 0x0040, 0x1732: 0x0040, 0x1733: 0x0040, 0x1734: 0x0040, 0x1735: 0x0040,
+ 0x1736: 0x0040, 0x1737: 0x0040, 0x1738: 0x0040, 0x1739: 0x0040, 0x173a: 0x0040, 0x173b: 0x0040,
+ 0x173c: 0x0040, 0x173d: 0x0040, 0x173e: 0x0040, 0x173f: 0x0040,
+ // Block 0x5d, offset 0x1740
+ 0x1740: 0x1308, 0x1741: 0x1308, 0x1742: 0x1008, 0x1743: 0x1008, 0x1744: 0x0040, 0x1745: 0x0008,
+ 0x1746: 0x0008, 0x1747: 0x0008, 0x1748: 0x0008, 0x1749: 0x0008, 0x174a: 0x0008, 0x174b: 0x0008,
+ 0x174c: 0x0008, 0x174d: 0x0040, 0x174e: 0x0040, 0x174f: 0x0008, 0x1750: 0x0008, 0x1751: 0x0040,
+ 0x1752: 0x0040, 0x1753: 0x0008, 0x1754: 0x0008, 0x1755: 0x0008, 0x1756: 0x0008, 0x1757: 0x0008,
+ 0x1758: 0x0008, 0x1759: 0x0008, 0x175a: 0x0008, 0x175b: 0x0008, 0x175c: 0x0008, 0x175d: 0x0008,
+ 0x175e: 0x0008, 0x175f: 0x0008, 0x1760: 0x0008, 0x1761: 0x0008, 0x1762: 0x0008, 0x1763: 0x0008,
+ 0x1764: 0x0008, 0x1765: 0x0008, 0x1766: 0x0008, 0x1767: 0x0008, 0x1768: 0x0008, 0x1769: 0x0040,
+ 0x176a: 0x0008, 0x176b: 0x0008, 0x176c: 0x0008, 0x176d: 0x0008, 0x176e: 0x0008, 0x176f: 0x0008,
+ 0x1770: 0x0008, 0x1771: 0x0040, 0x1772: 0x0008, 0x1773: 0x0008, 0x1774: 0x0040, 0x1775: 0x0008,
+ 0x1776: 0x0008, 0x1777: 0x0008, 0x1778: 0x0008, 0x1779: 0x0008, 0x177a: 0x0040, 0x177b: 0x0040,
+ 0x177c: 0x1308, 0x177d: 0x0008, 0x177e: 0x1008, 0x177f: 0x1008,
+ // Block 0x5e, offset 0x1780
+ 0x1780: 0x1308, 0x1781: 0x1008, 0x1782: 0x1008, 0x1783: 0x1008, 0x1784: 0x1008, 0x1785: 0x0040,
+ 0x1786: 0x0040, 0x1787: 0x1008, 0x1788: 0x1008, 0x1789: 0x0040, 0x178a: 0x0040, 0x178b: 0x1008,
+ 0x178c: 0x1008, 0x178d: 0x1808, 0x178e: 0x0040, 0x178f: 0x0040, 0x1790: 0x0008, 0x1791: 0x0040,
+ 0x1792: 0x0040, 0x1793: 0x0040, 0x1794: 0x0040, 0x1795: 0x0040, 0x1796: 0x0040, 0x1797: 0x1008,
+ 0x1798: 0x0040, 0x1799: 0x0040, 0x179a: 0x0040, 0x179b: 0x0040, 0x179c: 0x0040, 0x179d: 0x0008,
+ 0x179e: 0x0008, 0x179f: 0x0008, 0x17a0: 0x0008, 0x17a1: 0x0008, 0x17a2: 0x1008, 0x17a3: 0x1008,
+ 0x17a4: 0x0040, 0x17a5: 0x0040, 0x17a6: 0x1308, 0x17a7: 0x1308, 0x17a8: 0x1308, 0x17a9: 0x1308,
+ 0x17aa: 0x1308, 0x17ab: 0x1308, 0x17ac: 0x1308, 0x17ad: 0x0040, 0x17ae: 0x0040, 0x17af: 0x0040,
+ 0x17b0: 0x1308, 0x17b1: 0x1308, 0x17b2: 0x1308, 0x17b3: 0x1308, 0x17b4: 0x1308, 0x17b5: 0x0040,
+ 0x17b6: 0x0040, 0x17b7: 0x0040, 0x17b8: 0x0040, 0x17b9: 0x0040, 0x17ba: 0x0040, 0x17bb: 0x0040,
+ 0x17bc: 0x0040, 0x17bd: 0x0040, 0x17be: 0x0040, 0x17bf: 0x0040,
+ // Block 0x5f, offset 0x17c0
+ 0x17c0: 0x0039, 0x17c1: 0x0ee9, 0x17c2: 0x1159, 0x17c3: 0x0ef9, 0x17c4: 0x0f09, 0x17c5: 0x1199,
+ 0x17c6: 0x0f31, 0x17c7: 0x0249, 0x17c8: 0x0f41, 0x17c9: 0x0259, 0x17ca: 0x0f51, 0x17cb: 0x0359,
+ 0x17cc: 0x0f61, 0x17cd: 0x0f71, 0x17ce: 0x00d9, 0x17cf: 0x0f99, 0x17d0: 0x2039, 0x17d1: 0x0269,
+ 0x17d2: 0x01d9, 0x17d3: 0x0fa9, 0x17d4: 0x0fb9, 0x17d5: 0x1089, 0x17d6: 0x0279, 0x17d7: 0x0369,
+ 0x17d8: 0x0289, 0x17d9: 0x13d1, 0x17da: 0x0039, 0x17db: 0x0ee9, 0x17dc: 0x1159, 0x17dd: 0x0ef9,
+ 0x17de: 0x0f09, 0x17df: 0x1199, 0x17e0: 0x0f31, 0x17e1: 0x0249, 0x17e2: 0x0f41, 0x17e3: 0x0259,
+ 0x17e4: 0x0f51, 0x17e5: 0x0359, 0x17e6: 0x0f61, 0x17e7: 0x0f71, 0x17e8: 0x00d9, 0x17e9: 0x0f99,
+ 0x17ea: 0x2039, 0x17eb: 0x0269, 0x17ec: 0x01d9, 0x17ed: 0x0fa9, 0x17ee: 0x0fb9, 0x17ef: 0x1089,
+ 0x17f0: 0x0279, 0x17f1: 0x0369, 0x17f2: 0x0289, 0x17f3: 0x13d1, 0x17f4: 0x0039, 0x17f5: 0x0ee9,
+ 0x17f6: 0x1159, 0x17f7: 0x0ef9, 0x17f8: 0x0f09, 0x17f9: 0x1199, 0x17fa: 0x0f31, 0x17fb: 0x0249,
+ 0x17fc: 0x0f41, 0x17fd: 0x0259, 0x17fe: 0x0f51, 0x17ff: 0x0359,
+ // Block 0x60, offset 0x1800
+ 0x1800: 0x0f61, 0x1801: 0x0f71, 0x1802: 0x00d9, 0x1803: 0x0f99, 0x1804: 0x2039, 0x1805: 0x0269,
+ 0x1806: 0x01d9, 0x1807: 0x0fa9, 0x1808: 0x0fb9, 0x1809: 0x1089, 0x180a: 0x0279, 0x180b: 0x0369,
+ 0x180c: 0x0289, 0x180d: 0x13d1, 0x180e: 0x0039, 0x180f: 0x0ee9, 0x1810: 0x1159, 0x1811: 0x0ef9,
+ 0x1812: 0x0f09, 0x1813: 0x1199, 0x1814: 0x0f31, 0x1815: 0x0040, 0x1816: 0x0f41, 0x1817: 0x0259,
+ 0x1818: 0x0f51, 0x1819: 0x0359, 0x181a: 0x0f61, 0x181b: 0x0f71, 0x181c: 0x00d9, 0x181d: 0x0f99,
+ 0x181e: 0x2039, 0x181f: 0x0269, 0x1820: 0x01d9, 0x1821: 0x0fa9, 0x1822: 0x0fb9, 0x1823: 0x1089,
+ 0x1824: 0x0279, 0x1825: 0x0369, 0x1826: 0x0289, 0x1827: 0x13d1, 0x1828: 0x0039, 0x1829: 0x0ee9,
+ 0x182a: 0x1159, 0x182b: 0x0ef9, 0x182c: 0x0f09, 0x182d: 0x1199, 0x182e: 0x0f31, 0x182f: 0x0249,
+ 0x1830: 0x0f41, 0x1831: 0x0259, 0x1832: 0x0f51, 0x1833: 0x0359, 0x1834: 0x0f61, 0x1835: 0x0f71,
+ 0x1836: 0x00d9, 0x1837: 0x0f99, 0x1838: 0x2039, 0x1839: 0x0269, 0x183a: 0x01d9, 0x183b: 0x0fa9,
+ 0x183c: 0x0fb9, 0x183d: 0x1089, 0x183e: 0x0279, 0x183f: 0x0369,
+ // Block 0x61, offset 0x1840
+ 0x1840: 0x0289, 0x1841: 0x13d1, 0x1842: 0x0039, 0x1843: 0x0ee9, 0x1844: 0x1159, 0x1845: 0x0ef9,
+ 0x1846: 0x0f09, 0x1847: 0x1199, 0x1848: 0x0f31, 0x1849: 0x0249, 0x184a: 0x0f41, 0x184b: 0x0259,
+ 0x184c: 0x0f51, 0x184d: 0x0359, 0x184e: 0x0f61, 0x184f: 0x0f71, 0x1850: 0x00d9, 0x1851: 0x0f99,
+ 0x1852: 0x2039, 0x1853: 0x0269, 0x1854: 0x01d9, 0x1855: 0x0fa9, 0x1856: 0x0fb9, 0x1857: 0x1089,
+ 0x1858: 0x0279, 0x1859: 0x0369, 0x185a: 0x0289, 0x185b: 0x13d1, 0x185c: 0x0039, 0x185d: 0x0040,
+ 0x185e: 0x1159, 0x185f: 0x0ef9, 0x1860: 0x0040, 0x1861: 0x0040, 0x1862: 0x0f31, 0x1863: 0x0040,
+ 0x1864: 0x0040, 0x1865: 0x0259, 0x1866: 0x0f51, 0x1867: 0x0040, 0x1868: 0x0040, 0x1869: 0x0f71,
+ 0x186a: 0x00d9, 0x186b: 0x0f99, 0x186c: 0x2039, 0x186d: 0x0040, 0x186e: 0x01d9, 0x186f: 0x0fa9,
+ 0x1870: 0x0fb9, 0x1871: 0x1089, 0x1872: 0x0279, 0x1873: 0x0369, 0x1874: 0x0289, 0x1875: 0x13d1,
+ 0x1876: 0x0039, 0x1877: 0x0ee9, 0x1878: 0x1159, 0x1879: 0x0ef9, 0x187a: 0x0040, 0x187b: 0x1199,
+ 0x187c: 0x0040, 0x187d: 0x0249, 0x187e: 0x0f41, 0x187f: 0x0259,
+ // Block 0x62, offset 0x1880
+ 0x1880: 0x0f51, 0x1881: 0x0359, 0x1882: 0x0f61, 0x1883: 0x0f71, 0x1884: 0x0040, 0x1885: 0x0f99,
+ 0x1886: 0x2039, 0x1887: 0x0269, 0x1888: 0x01d9, 0x1889: 0x0fa9, 0x188a: 0x0fb9, 0x188b: 0x1089,
+ 0x188c: 0x0279, 0x188d: 0x0369, 0x188e: 0x0289, 0x188f: 0x13d1, 0x1890: 0x0039, 0x1891: 0x0ee9,
+ 0x1892: 0x1159, 0x1893: 0x0ef9, 0x1894: 0x0f09, 0x1895: 0x1199, 0x1896: 0x0f31, 0x1897: 0x0249,
+ 0x1898: 0x0f41, 0x1899: 0x0259, 0x189a: 0x0f51, 0x189b: 0x0359, 0x189c: 0x0f61, 0x189d: 0x0f71,
+ 0x189e: 0x00d9, 0x189f: 0x0f99, 0x18a0: 0x2039, 0x18a1: 0x0269, 0x18a2: 0x01d9, 0x18a3: 0x0fa9,
+ 0x18a4: 0x0fb9, 0x18a5: 0x1089, 0x18a6: 0x0279, 0x18a7: 0x0369, 0x18a8: 0x0289, 0x18a9: 0x13d1,
+ 0x18aa: 0x0039, 0x18ab: 0x0ee9, 0x18ac: 0x1159, 0x18ad: 0x0ef9, 0x18ae: 0x0f09, 0x18af: 0x1199,
+ 0x18b0: 0x0f31, 0x18b1: 0x0249, 0x18b2: 0x0f41, 0x18b3: 0x0259, 0x18b4: 0x0f51, 0x18b5: 0x0359,
+ 0x18b6: 0x0f61, 0x18b7: 0x0f71, 0x18b8: 0x00d9, 0x18b9: 0x0f99, 0x18ba: 0x2039, 0x18bb: 0x0269,
+ 0x18bc: 0x01d9, 0x18bd: 0x0fa9, 0x18be: 0x0fb9, 0x18bf: 0x1089,
+ // Block 0x63, offset 0x18c0
+ 0x18c0: 0x0279, 0x18c1: 0x0369, 0x18c2: 0x0289, 0x18c3: 0x13d1, 0x18c4: 0x0039, 0x18c5: 0x0ee9,
+ 0x18c6: 0x0040, 0x18c7: 0x0ef9, 0x18c8: 0x0f09, 0x18c9: 0x1199, 0x18ca: 0x0f31, 0x18cb: 0x0040,
+ 0x18cc: 0x0040, 0x18cd: 0x0259, 0x18ce: 0x0f51, 0x18cf: 0x0359, 0x18d0: 0x0f61, 0x18d1: 0x0f71,
+ 0x18d2: 0x00d9, 0x18d3: 0x0f99, 0x18d4: 0x2039, 0x18d5: 0x0040, 0x18d6: 0x01d9, 0x18d7: 0x0fa9,
+ 0x18d8: 0x0fb9, 0x18d9: 0x1089, 0x18da: 0x0279, 0x18db: 0x0369, 0x18dc: 0x0289, 0x18dd: 0x0040,
+ 0x18de: 0x0039, 0x18df: 0x0ee9, 0x18e0: 0x1159, 0x18e1: 0x0ef9, 0x18e2: 0x0f09, 0x18e3: 0x1199,
+ 0x18e4: 0x0f31, 0x18e5: 0x0249, 0x18e6: 0x0f41, 0x18e7: 0x0259, 0x18e8: 0x0f51, 0x18e9: 0x0359,
+ 0x18ea: 0x0f61, 0x18eb: 0x0f71, 0x18ec: 0x00d9, 0x18ed: 0x0f99, 0x18ee: 0x2039, 0x18ef: 0x0269,
+ 0x18f0: 0x01d9, 0x18f1: 0x0fa9, 0x18f2: 0x0fb9, 0x18f3: 0x1089, 0x18f4: 0x0279, 0x18f5: 0x0369,
+ 0x18f6: 0x0289, 0x18f7: 0x13d1, 0x18f8: 0x0039, 0x18f9: 0x0ee9, 0x18fa: 0x0040, 0x18fb: 0x0ef9,
+ 0x18fc: 0x0f09, 0x18fd: 0x1199, 0x18fe: 0x0f31, 0x18ff: 0x0040,
+ // Block 0x64, offset 0x1900
+ 0x1900: 0x0f41, 0x1901: 0x0259, 0x1902: 0x0f51, 0x1903: 0x0359, 0x1904: 0x0f61, 0x1905: 0x0040,
+ 0x1906: 0x00d9, 0x1907: 0x0040, 0x1908: 0x0040, 0x1909: 0x0040, 0x190a: 0x01d9, 0x190b: 0x0fa9,
+ 0x190c: 0x0fb9, 0x190d: 0x1089, 0x190e: 0x0279, 0x190f: 0x0369, 0x1910: 0x0289, 0x1911: 0x0040,
+ 0x1912: 0x0039, 0x1913: 0x0ee9, 0x1914: 0x1159, 0x1915: 0x0ef9, 0x1916: 0x0f09, 0x1917: 0x1199,
+ 0x1918: 0x0f31, 0x1919: 0x0249, 0x191a: 0x0f41, 0x191b: 0x0259, 0x191c: 0x0f51, 0x191d: 0x0359,
+ 0x191e: 0x0f61, 0x191f: 0x0f71, 0x1920: 0x00d9, 0x1921: 0x0f99, 0x1922: 0x2039, 0x1923: 0x0269,
+ 0x1924: 0x01d9, 0x1925: 0x0fa9, 0x1926: 0x0fb9, 0x1927: 0x1089, 0x1928: 0x0279, 0x1929: 0x0369,
+ 0x192a: 0x0289, 0x192b: 0x13d1, 0x192c: 0x0039, 0x192d: 0x0ee9, 0x192e: 0x1159, 0x192f: 0x0ef9,
+ 0x1930: 0x0f09, 0x1931: 0x1199, 0x1932: 0x0f31, 0x1933: 0x0249, 0x1934: 0x0f41, 0x1935: 0x0259,
+ 0x1936: 0x0f51, 0x1937: 0x0359, 0x1938: 0x0f61, 0x1939: 0x0f71, 0x193a: 0x00d9, 0x193b: 0x0f99,
+ 0x193c: 0x2039, 0x193d: 0x0269, 0x193e: 0x01d9, 0x193f: 0x0fa9,
+ // Block 0x65, offset 0x1940
+ 0x1940: 0x0fb9, 0x1941: 0x1089, 0x1942: 0x0279, 0x1943: 0x0369, 0x1944: 0x0289, 0x1945: 0x13d1,
+ 0x1946: 0x0039, 0x1947: 0x0ee9, 0x1948: 0x1159, 0x1949: 0x0ef9, 0x194a: 0x0f09, 0x194b: 0x1199,
+ 0x194c: 0x0f31, 0x194d: 0x0249, 0x194e: 0x0f41, 0x194f: 0x0259, 0x1950: 0x0f51, 0x1951: 0x0359,
+ 0x1952: 0x0f61, 0x1953: 0x0f71, 0x1954: 0x00d9, 0x1955: 0x0f99, 0x1956: 0x2039, 0x1957: 0x0269,
+ 0x1958: 0x01d9, 0x1959: 0x0fa9, 0x195a: 0x0fb9, 0x195b: 0x1089, 0x195c: 0x0279, 0x195d: 0x0369,
+ 0x195e: 0x0289, 0x195f: 0x13d1, 0x1960: 0x0039, 0x1961: 0x0ee9, 0x1962: 0x1159, 0x1963: 0x0ef9,
+ 0x1964: 0x0f09, 0x1965: 0x1199, 0x1966: 0x0f31, 0x1967: 0x0249, 0x1968: 0x0f41, 0x1969: 0x0259,
+ 0x196a: 0x0f51, 0x196b: 0x0359, 0x196c: 0x0f61, 0x196d: 0x0f71, 0x196e: 0x00d9, 0x196f: 0x0f99,
+ 0x1970: 0x2039, 0x1971: 0x0269, 0x1972: 0x01d9, 0x1973: 0x0fa9, 0x1974: 0x0fb9, 0x1975: 0x1089,
+ 0x1976: 0x0279, 0x1977: 0x0369, 0x1978: 0x0289, 0x1979: 0x13d1, 0x197a: 0x0039, 0x197b: 0x0ee9,
+ 0x197c: 0x1159, 0x197d: 0x0ef9, 0x197e: 0x0f09, 0x197f: 0x1199,
+ // Block 0x66, offset 0x1980
+ 0x1980: 0x0f31, 0x1981: 0x0249, 0x1982: 0x0f41, 0x1983: 0x0259, 0x1984: 0x0f51, 0x1985: 0x0359,
+ 0x1986: 0x0f61, 0x1987: 0x0f71, 0x1988: 0x00d9, 0x1989: 0x0f99, 0x198a: 0x2039, 0x198b: 0x0269,
+ 0x198c: 0x01d9, 0x198d: 0x0fa9, 0x198e: 0x0fb9, 0x198f: 0x1089, 0x1990: 0x0279, 0x1991: 0x0369,
+ 0x1992: 0x0289, 0x1993: 0x13d1, 0x1994: 0x0039, 0x1995: 0x0ee9, 0x1996: 0x1159, 0x1997: 0x0ef9,
+ 0x1998: 0x0f09, 0x1999: 0x1199, 0x199a: 0x0f31, 0x199b: 0x0249, 0x199c: 0x0f41, 0x199d: 0x0259,
+ 0x199e: 0x0f51, 0x199f: 0x0359, 0x19a0: 0x0f61, 0x19a1: 0x0f71, 0x19a2: 0x00d9, 0x19a3: 0x0f99,
+ 0x19a4: 0x2039, 0x19a5: 0x0269, 0x19a6: 0x01d9, 0x19a7: 0x0fa9, 0x19a8: 0x0fb9, 0x19a9: 0x1089,
+ 0x19aa: 0x0279, 0x19ab: 0x0369, 0x19ac: 0x0289, 0x19ad: 0x13d1, 0x19ae: 0x0039, 0x19af: 0x0ee9,
+ 0x19b0: 0x1159, 0x19b1: 0x0ef9, 0x19b2: 0x0f09, 0x19b3: 0x1199, 0x19b4: 0x0f31, 0x19b5: 0x0249,
+ 0x19b6: 0x0f41, 0x19b7: 0x0259, 0x19b8: 0x0f51, 0x19b9: 0x0359, 0x19ba: 0x0f61, 0x19bb: 0x0f71,
+ 0x19bc: 0x00d9, 0x19bd: 0x0f99, 0x19be: 0x2039, 0x19bf: 0x0269,
+ // Block 0x67, offset 0x19c0
+ 0x19c0: 0x01d9, 0x19c1: 0x0fa9, 0x19c2: 0x0fb9, 0x19c3: 0x1089, 0x19c4: 0x0279, 0x19c5: 0x0369,
+ 0x19c6: 0x0289, 0x19c7: 0x13d1, 0x19c8: 0x0039, 0x19c9: 0x0ee9, 0x19ca: 0x1159, 0x19cb: 0x0ef9,
+ 0x19cc: 0x0f09, 0x19cd: 0x1199, 0x19ce: 0x0f31, 0x19cf: 0x0249, 0x19d0: 0x0f41, 0x19d1: 0x0259,
+ 0x19d2: 0x0f51, 0x19d3: 0x0359, 0x19d4: 0x0f61, 0x19d5: 0x0f71, 0x19d6: 0x00d9, 0x19d7: 0x0f99,
+ 0x19d8: 0x2039, 0x19d9: 0x0269, 0x19da: 0x01d9, 0x19db: 0x0fa9, 0x19dc: 0x0fb9, 0x19dd: 0x1089,
+ 0x19de: 0x0279, 0x19df: 0x0369, 0x19e0: 0x0289, 0x19e1: 0x13d1, 0x19e2: 0x0039, 0x19e3: 0x0ee9,
+ 0x19e4: 0x1159, 0x19e5: 0x0ef9, 0x19e6: 0x0f09, 0x19e7: 0x1199, 0x19e8: 0x0f31, 0x19e9: 0x0249,
+ 0x19ea: 0x0f41, 0x19eb: 0x0259, 0x19ec: 0x0f51, 0x19ed: 0x0359, 0x19ee: 0x0f61, 0x19ef: 0x0f71,
+ 0x19f0: 0x00d9, 0x19f1: 0x0f99, 0x19f2: 0x2039, 0x19f3: 0x0269, 0x19f4: 0x01d9, 0x19f5: 0x0fa9,
+ 0x19f6: 0x0fb9, 0x19f7: 0x1089, 0x19f8: 0x0279, 0x19f9: 0x0369, 0x19fa: 0x0289, 0x19fb: 0x13d1,
+ 0x19fc: 0x0039, 0x19fd: 0x0ee9, 0x19fe: 0x1159, 0x19ff: 0x0ef9,
+ // Block 0x68, offset 0x1a00
+ 0x1a00: 0x0f09, 0x1a01: 0x1199, 0x1a02: 0x0f31, 0x1a03: 0x0249, 0x1a04: 0x0f41, 0x1a05: 0x0259,
+ 0x1a06: 0x0f51, 0x1a07: 0x0359, 0x1a08: 0x0f61, 0x1a09: 0x0f71, 0x1a0a: 0x00d9, 0x1a0b: 0x0f99,
+ 0x1a0c: 0x2039, 0x1a0d: 0x0269, 0x1a0e: 0x01d9, 0x1a0f: 0x0fa9, 0x1a10: 0x0fb9, 0x1a11: 0x1089,
+ 0x1a12: 0x0279, 0x1a13: 0x0369, 0x1a14: 0x0289, 0x1a15: 0x13d1, 0x1a16: 0x0039, 0x1a17: 0x0ee9,
+ 0x1a18: 0x1159, 0x1a19: 0x0ef9, 0x1a1a: 0x0f09, 0x1a1b: 0x1199, 0x1a1c: 0x0f31, 0x1a1d: 0x0249,
+ 0x1a1e: 0x0f41, 0x1a1f: 0x0259, 0x1a20: 0x0f51, 0x1a21: 0x0359, 0x1a22: 0x0f61, 0x1a23: 0x0f71,
+ 0x1a24: 0x00d9, 0x1a25: 0x0f99, 0x1a26: 0x2039, 0x1a27: 0x0269, 0x1a28: 0x01d9, 0x1a29: 0x0fa9,
+ 0x1a2a: 0x0fb9, 0x1a2b: 0x1089, 0x1a2c: 0x0279, 0x1a2d: 0x0369, 0x1a2e: 0x0289, 0x1a2f: 0x13d1,
+ 0x1a30: 0x0039, 0x1a31: 0x0ee9, 0x1a32: 0x1159, 0x1a33: 0x0ef9, 0x1a34: 0x0f09, 0x1a35: 0x1199,
+ 0x1a36: 0x0f31, 0x1a37: 0x0249, 0x1a38: 0x0f41, 0x1a39: 0x0259, 0x1a3a: 0x0f51, 0x1a3b: 0x0359,
+ 0x1a3c: 0x0f61, 0x1a3d: 0x0f71, 0x1a3e: 0x00d9, 0x1a3f: 0x0f99,
+ // Block 0x69, offset 0x1a40
+ 0x1a40: 0x2039, 0x1a41: 0x0269, 0x1a42: 0x01d9, 0x1a43: 0x0fa9, 0x1a44: 0x0fb9, 0x1a45: 0x1089,
+ 0x1a46: 0x0279, 0x1a47: 0x0369, 0x1a48: 0x0289, 0x1a49: 0x13d1, 0x1a4a: 0x0039, 0x1a4b: 0x0ee9,
+ 0x1a4c: 0x1159, 0x1a4d: 0x0ef9, 0x1a4e: 0x0f09, 0x1a4f: 0x1199, 0x1a50: 0x0f31, 0x1a51: 0x0249,
+ 0x1a52: 0x0f41, 0x1a53: 0x0259, 0x1a54: 0x0f51, 0x1a55: 0x0359, 0x1a56: 0x0f61, 0x1a57: 0x0f71,
+ 0x1a58: 0x00d9, 0x1a59: 0x0f99, 0x1a5a: 0x2039, 0x1a5b: 0x0269, 0x1a5c: 0x01d9, 0x1a5d: 0x0fa9,
+ 0x1a5e: 0x0fb9, 0x1a5f: 0x1089, 0x1a60: 0x0279, 0x1a61: 0x0369, 0x1a62: 0x0289, 0x1a63: 0x13d1,
+ 0x1a64: 0xba81, 0x1a65: 0xba99, 0x1a66: 0x0040, 0x1a67: 0x0040, 0x1a68: 0xbab1, 0x1a69: 0x1099,
+ 0x1a6a: 0x10b1, 0x1a6b: 0x10c9, 0x1a6c: 0xbac9, 0x1a6d: 0xbae1, 0x1a6e: 0xbaf9, 0x1a6f: 0x1429,
+ 0x1a70: 0x1a31, 0x1a71: 0xbb11, 0x1a72: 0xbb29, 0x1a73: 0xbb41, 0x1a74: 0xbb59, 0x1a75: 0xbb71,
+ 0x1a76: 0xbb89, 0x1a77: 0x2109, 0x1a78: 0x1111, 0x1a79: 0x1429, 0x1a7a: 0xbba1, 0x1a7b: 0xbbb9,
+ 0x1a7c: 0xbbd1, 0x1a7d: 0x10e1, 0x1a7e: 0x10f9, 0x1a7f: 0xbbe9,
+ // Block 0x6a, offset 0x1a80
+ 0x1a80: 0x2079, 0x1a81: 0xbc01, 0x1a82: 0xbab1, 0x1a83: 0x1099, 0x1a84: 0x10b1, 0x1a85: 0x10c9,
+ 0x1a86: 0xbac9, 0x1a87: 0xbae1, 0x1a88: 0xbaf9, 0x1a89: 0x1429, 0x1a8a: 0x1a31, 0x1a8b: 0xbb11,
+ 0x1a8c: 0xbb29, 0x1a8d: 0xbb41, 0x1a8e: 0xbb59, 0x1a8f: 0xbb71, 0x1a90: 0xbb89, 0x1a91: 0x2109,
+ 0x1a92: 0x1111, 0x1a93: 0xbba1, 0x1a94: 0xbba1, 0x1a95: 0xbbb9, 0x1a96: 0xbbd1, 0x1a97: 0x10e1,
+ 0x1a98: 0x10f9, 0x1a99: 0xbbe9, 0x1a9a: 0x2079, 0x1a9b: 0xbc21, 0x1a9c: 0xbac9, 0x1a9d: 0x1429,
+ 0x1a9e: 0xbb11, 0x1a9f: 0x10e1, 0x1aa0: 0x1111, 0x1aa1: 0x2109, 0x1aa2: 0xbab1, 0x1aa3: 0x1099,
+ 0x1aa4: 0x10b1, 0x1aa5: 0x10c9, 0x1aa6: 0xbac9, 0x1aa7: 0xbae1, 0x1aa8: 0xbaf9, 0x1aa9: 0x1429,
+ 0x1aaa: 0x1a31, 0x1aab: 0xbb11, 0x1aac: 0xbb29, 0x1aad: 0xbb41, 0x1aae: 0xbb59, 0x1aaf: 0xbb71,
+ 0x1ab0: 0xbb89, 0x1ab1: 0x2109, 0x1ab2: 0x1111, 0x1ab3: 0x1429, 0x1ab4: 0xbba1, 0x1ab5: 0xbbb9,
+ 0x1ab6: 0xbbd1, 0x1ab7: 0x10e1, 0x1ab8: 0x10f9, 0x1ab9: 0xbbe9, 0x1aba: 0x2079, 0x1abb: 0xbc01,
+ 0x1abc: 0xbab1, 0x1abd: 0x1099, 0x1abe: 0x10b1, 0x1abf: 0x10c9,
+ // Block 0x6b, offset 0x1ac0
+ 0x1ac0: 0xbac9, 0x1ac1: 0xbae1, 0x1ac2: 0xbaf9, 0x1ac3: 0x1429, 0x1ac4: 0x1a31, 0x1ac5: 0xbb11,
+ 0x1ac6: 0xbb29, 0x1ac7: 0xbb41, 0x1ac8: 0xbb59, 0x1ac9: 0xbb71, 0x1aca: 0xbb89, 0x1acb: 0x2109,
+ 0x1acc: 0x1111, 0x1acd: 0xbba1, 0x1ace: 0xbba1, 0x1acf: 0xbbb9, 0x1ad0: 0xbbd1, 0x1ad1: 0x10e1,
+ 0x1ad2: 0x10f9, 0x1ad3: 0xbbe9, 0x1ad4: 0x2079, 0x1ad5: 0xbc21, 0x1ad6: 0xbac9, 0x1ad7: 0x1429,
+ 0x1ad8: 0xbb11, 0x1ad9: 0x10e1, 0x1ada: 0x1111, 0x1adb: 0x2109, 0x1adc: 0xbab1, 0x1add: 0x1099,
+ 0x1ade: 0x10b1, 0x1adf: 0x10c9, 0x1ae0: 0xbac9, 0x1ae1: 0xbae1, 0x1ae2: 0xbaf9, 0x1ae3: 0x1429,
+ 0x1ae4: 0x1a31, 0x1ae5: 0xbb11, 0x1ae6: 0xbb29, 0x1ae7: 0xbb41, 0x1ae8: 0xbb59, 0x1ae9: 0xbb71,
+ 0x1aea: 0xbb89, 0x1aeb: 0x2109, 0x1aec: 0x1111, 0x1aed: 0x1429, 0x1aee: 0xbba1, 0x1aef: 0xbbb9,
+ 0x1af0: 0xbbd1, 0x1af1: 0x10e1, 0x1af2: 0x10f9, 0x1af3: 0xbbe9, 0x1af4: 0x2079, 0x1af5: 0xbc01,
+ 0x1af6: 0xbab1, 0x1af7: 0x1099, 0x1af8: 0x10b1, 0x1af9: 0x10c9, 0x1afa: 0xbac9, 0x1afb: 0xbae1,
+ 0x1afc: 0xbaf9, 0x1afd: 0x1429, 0x1afe: 0x1a31, 0x1aff: 0xbb11,
+ // Block 0x6c, offset 0x1b00
+ 0x1b00: 0xbb29, 0x1b01: 0xbb41, 0x1b02: 0xbb59, 0x1b03: 0xbb71, 0x1b04: 0xbb89, 0x1b05: 0x2109,
+ 0x1b06: 0x1111, 0x1b07: 0xbba1, 0x1b08: 0xbba1, 0x1b09: 0xbbb9, 0x1b0a: 0xbbd1, 0x1b0b: 0x10e1,
+ 0x1b0c: 0x10f9, 0x1b0d: 0xbbe9, 0x1b0e: 0x2079, 0x1b0f: 0xbc21, 0x1b10: 0xbac9, 0x1b11: 0x1429,
+ 0x1b12: 0xbb11, 0x1b13: 0x10e1, 0x1b14: 0x1111, 0x1b15: 0x2109, 0x1b16: 0xbab1, 0x1b17: 0x1099,
+ 0x1b18: 0x10b1, 0x1b19: 0x10c9, 0x1b1a: 0xbac9, 0x1b1b: 0xbae1, 0x1b1c: 0xbaf9, 0x1b1d: 0x1429,
+ 0x1b1e: 0x1a31, 0x1b1f: 0xbb11, 0x1b20: 0xbb29, 0x1b21: 0xbb41, 0x1b22: 0xbb59, 0x1b23: 0xbb71,
+ 0x1b24: 0xbb89, 0x1b25: 0x2109, 0x1b26: 0x1111, 0x1b27: 0x1429, 0x1b28: 0xbba1, 0x1b29: 0xbbb9,
+ 0x1b2a: 0xbbd1, 0x1b2b: 0x10e1, 0x1b2c: 0x10f9, 0x1b2d: 0xbbe9, 0x1b2e: 0x2079, 0x1b2f: 0xbc01,
+ 0x1b30: 0xbab1, 0x1b31: 0x1099, 0x1b32: 0x10b1, 0x1b33: 0x10c9, 0x1b34: 0xbac9, 0x1b35: 0xbae1,
+ 0x1b36: 0xbaf9, 0x1b37: 0x1429, 0x1b38: 0x1a31, 0x1b39: 0xbb11, 0x1b3a: 0xbb29, 0x1b3b: 0xbb41,
+ 0x1b3c: 0xbb59, 0x1b3d: 0xbb71, 0x1b3e: 0xbb89, 0x1b3f: 0x2109,
+ // Block 0x6d, offset 0x1b40
+ 0x1b40: 0x1111, 0x1b41: 0xbba1, 0x1b42: 0xbba1, 0x1b43: 0xbbb9, 0x1b44: 0xbbd1, 0x1b45: 0x10e1,
+ 0x1b46: 0x10f9, 0x1b47: 0xbbe9, 0x1b48: 0x2079, 0x1b49: 0xbc21, 0x1b4a: 0xbac9, 0x1b4b: 0x1429,
+ 0x1b4c: 0xbb11, 0x1b4d: 0x10e1, 0x1b4e: 0x1111, 0x1b4f: 0x2109, 0x1b50: 0xbab1, 0x1b51: 0x1099,
+ 0x1b52: 0x10b1, 0x1b53: 0x10c9, 0x1b54: 0xbac9, 0x1b55: 0xbae1, 0x1b56: 0xbaf9, 0x1b57: 0x1429,
+ 0x1b58: 0x1a31, 0x1b59: 0xbb11, 0x1b5a: 0xbb29, 0x1b5b: 0xbb41, 0x1b5c: 0xbb59, 0x1b5d: 0xbb71,
+ 0x1b5e: 0xbb89, 0x1b5f: 0x2109, 0x1b60: 0x1111, 0x1b61: 0x1429, 0x1b62: 0xbba1, 0x1b63: 0xbbb9,
+ 0x1b64: 0xbbd1, 0x1b65: 0x10e1, 0x1b66: 0x10f9, 0x1b67: 0xbbe9, 0x1b68: 0x2079, 0x1b69: 0xbc01,
+ 0x1b6a: 0xbab1, 0x1b6b: 0x1099, 0x1b6c: 0x10b1, 0x1b6d: 0x10c9, 0x1b6e: 0xbac9, 0x1b6f: 0xbae1,
+ 0x1b70: 0xbaf9, 0x1b71: 0x1429, 0x1b72: 0x1a31, 0x1b73: 0xbb11, 0x1b74: 0xbb29, 0x1b75: 0xbb41,
+ 0x1b76: 0xbb59, 0x1b77: 0xbb71, 0x1b78: 0xbb89, 0x1b79: 0x2109, 0x1b7a: 0x1111, 0x1b7b: 0xbba1,
+ 0x1b7c: 0xbba1, 0x1b7d: 0xbbb9, 0x1b7e: 0xbbd1, 0x1b7f: 0x10e1,
+ // Block 0x6e, offset 0x1b80
+ 0x1b80: 0x10f9, 0x1b81: 0xbbe9, 0x1b82: 0x2079, 0x1b83: 0xbc21, 0x1b84: 0xbac9, 0x1b85: 0x1429,
+ 0x1b86: 0xbb11, 0x1b87: 0x10e1, 0x1b88: 0x1111, 0x1b89: 0x2109, 0x1b8a: 0xbc41, 0x1b8b: 0xbc41,
+ 0x1b8c: 0x0040, 0x1b8d: 0x0040, 0x1b8e: 0x1f41, 0x1b8f: 0x00c9, 0x1b90: 0x0069, 0x1b91: 0x0079,
+ 0x1b92: 0x1f51, 0x1b93: 0x1f61, 0x1b94: 0x1f71, 0x1b95: 0x1f81, 0x1b96: 0x1f91, 0x1b97: 0x1fa1,
+ 0x1b98: 0x1f41, 0x1b99: 0x00c9, 0x1b9a: 0x0069, 0x1b9b: 0x0079, 0x1b9c: 0x1f51, 0x1b9d: 0x1f61,
+ 0x1b9e: 0x1f71, 0x1b9f: 0x1f81, 0x1ba0: 0x1f91, 0x1ba1: 0x1fa1, 0x1ba2: 0x1f41, 0x1ba3: 0x00c9,
+ 0x1ba4: 0x0069, 0x1ba5: 0x0079, 0x1ba6: 0x1f51, 0x1ba7: 0x1f61, 0x1ba8: 0x1f71, 0x1ba9: 0x1f81,
+ 0x1baa: 0x1f91, 0x1bab: 0x1fa1, 0x1bac: 0x1f41, 0x1bad: 0x00c9, 0x1bae: 0x0069, 0x1baf: 0x0079,
+ 0x1bb0: 0x1f51, 0x1bb1: 0x1f61, 0x1bb2: 0x1f71, 0x1bb3: 0x1f81, 0x1bb4: 0x1f91, 0x1bb5: 0x1fa1,
+ 0x1bb6: 0x1f41, 0x1bb7: 0x00c9, 0x1bb8: 0x0069, 0x1bb9: 0x0079, 0x1bba: 0x1f51, 0x1bbb: 0x1f61,
+ 0x1bbc: 0x1f71, 0x1bbd: 0x1f81, 0x1bbe: 0x1f91, 0x1bbf: 0x1fa1,
+ // Block 0x6f, offset 0x1bc0
+ 0x1bc0: 0xe115, 0x1bc1: 0xe115, 0x1bc2: 0xe135, 0x1bc3: 0xe135, 0x1bc4: 0xe115, 0x1bc5: 0xe115,
+ 0x1bc6: 0xe175, 0x1bc7: 0xe175, 0x1bc8: 0xe115, 0x1bc9: 0xe115, 0x1bca: 0xe135, 0x1bcb: 0xe135,
+ 0x1bcc: 0xe115, 0x1bcd: 0xe115, 0x1bce: 0xe1f5, 0x1bcf: 0xe1f5, 0x1bd0: 0xe115, 0x1bd1: 0xe115,
+ 0x1bd2: 0xe135, 0x1bd3: 0xe135, 0x1bd4: 0xe115, 0x1bd5: 0xe115, 0x1bd6: 0xe175, 0x1bd7: 0xe175,
+ 0x1bd8: 0xe115, 0x1bd9: 0xe115, 0x1bda: 0xe135, 0x1bdb: 0xe135, 0x1bdc: 0xe115, 0x1bdd: 0xe115,
+ 0x1bde: 0x8b05, 0x1bdf: 0x8b05, 0x1be0: 0x04b5, 0x1be1: 0x04b5, 0x1be2: 0x0208, 0x1be3: 0x0208,
+ 0x1be4: 0x0208, 0x1be5: 0x0208, 0x1be6: 0x0208, 0x1be7: 0x0208, 0x1be8: 0x0208, 0x1be9: 0x0208,
+ 0x1bea: 0x0208, 0x1beb: 0x0208, 0x1bec: 0x0208, 0x1bed: 0x0208, 0x1bee: 0x0208, 0x1bef: 0x0208,
+ 0x1bf0: 0x0208, 0x1bf1: 0x0208, 0x1bf2: 0x0208, 0x1bf3: 0x0208, 0x1bf4: 0x0208, 0x1bf5: 0x0208,
+ 0x1bf6: 0x0208, 0x1bf7: 0x0208, 0x1bf8: 0x0208, 0x1bf9: 0x0208, 0x1bfa: 0x0208, 0x1bfb: 0x0208,
+ 0x1bfc: 0x0208, 0x1bfd: 0x0208, 0x1bfe: 0x0208, 0x1bff: 0x0208,
+ // Block 0x70, offset 0x1c00
+ 0x1c00: 0xb189, 0x1c01: 0xb1a1, 0x1c02: 0xb201, 0x1c03: 0xb249, 0x1c04: 0x0040, 0x1c05: 0xb411,
+ 0x1c06: 0xb291, 0x1c07: 0xb219, 0x1c08: 0xb309, 0x1c09: 0xb429, 0x1c0a: 0xb399, 0x1c0b: 0xb3b1,
+ 0x1c0c: 0xb3c9, 0x1c0d: 0xb3e1, 0x1c0e: 0xb2a9, 0x1c0f: 0xb339, 0x1c10: 0xb369, 0x1c11: 0xb2d9,
+ 0x1c12: 0xb381, 0x1c13: 0xb279, 0x1c14: 0xb2c1, 0x1c15: 0xb1d1, 0x1c16: 0xb1e9, 0x1c17: 0xb231,
+ 0x1c18: 0xb261, 0x1c19: 0xb2f1, 0x1c1a: 0xb321, 0x1c1b: 0xb351, 0x1c1c: 0xbc59, 0x1c1d: 0x7949,
+ 0x1c1e: 0xbc71, 0x1c1f: 0xbc89, 0x1c20: 0x0040, 0x1c21: 0xb1a1, 0x1c22: 0xb201, 0x1c23: 0x0040,
+ 0x1c24: 0xb3f9, 0x1c25: 0x0040, 0x1c26: 0x0040, 0x1c27: 0xb219, 0x1c28: 0x0040, 0x1c29: 0xb429,
+ 0x1c2a: 0xb399, 0x1c2b: 0xb3b1, 0x1c2c: 0xb3c9, 0x1c2d: 0xb3e1, 0x1c2e: 0xb2a9, 0x1c2f: 0xb339,
+ 0x1c30: 0xb369, 0x1c31: 0xb2d9, 0x1c32: 0xb381, 0x1c33: 0x0040, 0x1c34: 0xb2c1, 0x1c35: 0xb1d1,
+ 0x1c36: 0xb1e9, 0x1c37: 0xb231, 0x1c38: 0x0040, 0x1c39: 0xb2f1, 0x1c3a: 0x0040, 0x1c3b: 0xb351,
+ 0x1c3c: 0x0040, 0x1c3d: 0x0040, 0x1c3e: 0x0040, 0x1c3f: 0x0040,
+ // Block 0x71, offset 0x1c40
+ 0x1c40: 0x0040, 0x1c41: 0x0040, 0x1c42: 0xb201, 0x1c43: 0x0040, 0x1c44: 0x0040, 0x1c45: 0x0040,
+ 0x1c46: 0x0040, 0x1c47: 0xb219, 0x1c48: 0x0040, 0x1c49: 0xb429, 0x1c4a: 0x0040, 0x1c4b: 0xb3b1,
+ 0x1c4c: 0x0040, 0x1c4d: 0xb3e1, 0x1c4e: 0xb2a9, 0x1c4f: 0xb339, 0x1c50: 0x0040, 0x1c51: 0xb2d9,
+ 0x1c52: 0xb381, 0x1c53: 0x0040, 0x1c54: 0xb2c1, 0x1c55: 0x0040, 0x1c56: 0x0040, 0x1c57: 0xb231,
+ 0x1c58: 0x0040, 0x1c59: 0xb2f1, 0x1c5a: 0x0040, 0x1c5b: 0xb351, 0x1c5c: 0x0040, 0x1c5d: 0x7949,
+ 0x1c5e: 0x0040, 0x1c5f: 0xbc89, 0x1c60: 0x0040, 0x1c61: 0xb1a1, 0x1c62: 0xb201, 0x1c63: 0x0040,
+ 0x1c64: 0xb3f9, 0x1c65: 0x0040, 0x1c66: 0x0040, 0x1c67: 0xb219, 0x1c68: 0xb309, 0x1c69: 0xb429,
+ 0x1c6a: 0xb399, 0x1c6b: 0x0040, 0x1c6c: 0xb3c9, 0x1c6d: 0xb3e1, 0x1c6e: 0xb2a9, 0x1c6f: 0xb339,
+ 0x1c70: 0xb369, 0x1c71: 0xb2d9, 0x1c72: 0xb381, 0x1c73: 0x0040, 0x1c74: 0xb2c1, 0x1c75: 0xb1d1,
+ 0x1c76: 0xb1e9, 0x1c77: 0xb231, 0x1c78: 0x0040, 0x1c79: 0xb2f1, 0x1c7a: 0xb321, 0x1c7b: 0xb351,
+ 0x1c7c: 0xbc59, 0x1c7d: 0x0040, 0x1c7e: 0xbc71, 0x1c7f: 0x0040,
+ // Block 0x72, offset 0x1c80
+ 0x1c80: 0xb189, 0x1c81: 0xb1a1, 0x1c82: 0xb201, 0x1c83: 0xb249, 0x1c84: 0xb3f9, 0x1c85: 0xb411,
+ 0x1c86: 0xb291, 0x1c87: 0xb219, 0x1c88: 0xb309, 0x1c89: 0xb429, 0x1c8a: 0x0040, 0x1c8b: 0xb3b1,
+ 0x1c8c: 0xb3c9, 0x1c8d: 0xb3e1, 0x1c8e: 0xb2a9, 0x1c8f: 0xb339, 0x1c90: 0xb369, 0x1c91: 0xb2d9,
+ 0x1c92: 0xb381, 0x1c93: 0xb279, 0x1c94: 0xb2c1, 0x1c95: 0xb1d1, 0x1c96: 0xb1e9, 0x1c97: 0xb231,
+ 0x1c98: 0xb261, 0x1c99: 0xb2f1, 0x1c9a: 0xb321, 0x1c9b: 0xb351, 0x1c9c: 0x0040, 0x1c9d: 0x0040,
+ 0x1c9e: 0x0040, 0x1c9f: 0x0040, 0x1ca0: 0x0040, 0x1ca1: 0xb1a1, 0x1ca2: 0xb201, 0x1ca3: 0xb249,
+ 0x1ca4: 0x0040, 0x1ca5: 0xb411, 0x1ca6: 0xb291, 0x1ca7: 0xb219, 0x1ca8: 0xb309, 0x1ca9: 0xb429,
+ 0x1caa: 0x0040, 0x1cab: 0xb3b1, 0x1cac: 0xb3c9, 0x1cad: 0xb3e1, 0x1cae: 0xb2a9, 0x1caf: 0xb339,
+ 0x1cb0: 0xb369, 0x1cb1: 0xb2d9, 0x1cb2: 0xb381, 0x1cb3: 0xb279, 0x1cb4: 0xb2c1, 0x1cb5: 0xb1d1,
+ 0x1cb6: 0xb1e9, 0x1cb7: 0xb231, 0x1cb8: 0xb261, 0x1cb9: 0xb2f1, 0x1cba: 0xb321, 0x1cbb: 0xb351,
+ 0x1cbc: 0x0040, 0x1cbd: 0x0040, 0x1cbe: 0x0040, 0x1cbf: 0x0040,
+ // Block 0x73, offset 0x1cc0
+ 0x1cc0: 0x0040, 0x1cc1: 0xbca2, 0x1cc2: 0xbcba, 0x1cc3: 0xbcd2, 0x1cc4: 0xbcea, 0x1cc5: 0xbd02,
+ 0x1cc6: 0xbd1a, 0x1cc7: 0xbd32, 0x1cc8: 0xbd4a, 0x1cc9: 0xbd62, 0x1cca: 0xbd7a, 0x1ccb: 0x0018,
+ 0x1ccc: 0x0018, 0x1ccd: 0x0040, 0x1cce: 0x0040, 0x1ccf: 0x0040, 0x1cd0: 0xbd92, 0x1cd1: 0xbdb2,
+ 0x1cd2: 0xbdd2, 0x1cd3: 0xbdf2, 0x1cd4: 0xbe12, 0x1cd5: 0xbe32, 0x1cd6: 0xbe52, 0x1cd7: 0xbe72,
+ 0x1cd8: 0xbe92, 0x1cd9: 0xbeb2, 0x1cda: 0xbed2, 0x1cdb: 0xbef2, 0x1cdc: 0xbf12, 0x1cdd: 0xbf32,
+ 0x1cde: 0xbf52, 0x1cdf: 0xbf72, 0x1ce0: 0xbf92, 0x1ce1: 0xbfb2, 0x1ce2: 0xbfd2, 0x1ce3: 0xbff2,
+ 0x1ce4: 0xc012, 0x1ce5: 0xc032, 0x1ce6: 0xc052, 0x1ce7: 0xc072, 0x1ce8: 0xc092, 0x1ce9: 0xc0b2,
+ 0x1cea: 0xc0d1, 0x1ceb: 0x1159, 0x1cec: 0x0269, 0x1ced: 0x6671, 0x1cee: 0xc111, 0x1cef: 0x0040,
+ 0x1cf0: 0x0039, 0x1cf1: 0x0ee9, 0x1cf2: 0x1159, 0x1cf3: 0x0ef9, 0x1cf4: 0x0f09, 0x1cf5: 0x1199,
+ 0x1cf6: 0x0f31, 0x1cf7: 0x0249, 0x1cf8: 0x0f41, 0x1cf9: 0x0259, 0x1cfa: 0x0f51, 0x1cfb: 0x0359,
+ 0x1cfc: 0x0f61, 0x1cfd: 0x0f71, 0x1cfe: 0x00d9, 0x1cff: 0x0f99,
+ // Block 0x74, offset 0x1d00
+ 0x1d00: 0x2039, 0x1d01: 0x0269, 0x1d02: 0x01d9, 0x1d03: 0x0fa9, 0x1d04: 0x0fb9, 0x1d05: 0x1089,
+ 0x1d06: 0x0279, 0x1d07: 0x0369, 0x1d08: 0x0289, 0x1d09: 0x13d1, 0x1d0a: 0xc129, 0x1d0b: 0x65b1,
+ 0x1d0c: 0xc141, 0x1d0d: 0x1441, 0x1d0e: 0xc159, 0x1d0f: 0xc179, 0x1d10: 0x0018, 0x1d11: 0x0018,
+ 0x1d12: 0x0018, 0x1d13: 0x0018, 0x1d14: 0x0018, 0x1d15: 0x0018, 0x1d16: 0x0018, 0x1d17: 0x0018,
+ 0x1d18: 0x0018, 0x1d19: 0x0018, 0x1d1a: 0x0018, 0x1d1b: 0x0018, 0x1d1c: 0x0018, 0x1d1d: 0x0018,
+ 0x1d1e: 0x0018, 0x1d1f: 0x0018, 0x1d20: 0x0018, 0x1d21: 0x0018, 0x1d22: 0x0018, 0x1d23: 0x0018,
+ 0x1d24: 0x0018, 0x1d25: 0x0018, 0x1d26: 0x0018, 0x1d27: 0x0018, 0x1d28: 0x0018, 0x1d29: 0x0018,
+ 0x1d2a: 0xc191, 0x1d2b: 0xc1a9, 0x1d2c: 0x0040, 0x1d2d: 0x0040, 0x1d2e: 0x0040, 0x1d2f: 0x0040,
+ 0x1d30: 0x0018, 0x1d31: 0x0018, 0x1d32: 0x0018, 0x1d33: 0x0018, 0x1d34: 0x0018, 0x1d35: 0x0018,
+ 0x1d36: 0x0018, 0x1d37: 0x0018, 0x1d38: 0x0018, 0x1d39: 0x0018, 0x1d3a: 0x0018, 0x1d3b: 0x0018,
+ 0x1d3c: 0x0018, 0x1d3d: 0x0018, 0x1d3e: 0x0018, 0x1d3f: 0x0018,
+ // Block 0x75, offset 0x1d40
+ 0x1d40: 0xc1d9, 0x1d41: 0xc211, 0x1d42: 0xc249, 0x1d43: 0x0040, 0x1d44: 0x0040, 0x1d45: 0x0040,
+ 0x1d46: 0x0040, 0x1d47: 0x0040, 0x1d48: 0x0040, 0x1d49: 0x0040, 0x1d4a: 0x0040, 0x1d4b: 0x0040,
+ 0x1d4c: 0x0040, 0x1d4d: 0x0040, 0x1d4e: 0x0040, 0x1d4f: 0x0040, 0x1d50: 0xc269, 0x1d51: 0xc289,
+ 0x1d52: 0xc2a9, 0x1d53: 0xc2c9, 0x1d54: 0xc2e9, 0x1d55: 0xc309, 0x1d56: 0xc329, 0x1d57: 0xc349,
+ 0x1d58: 0xc369, 0x1d59: 0xc389, 0x1d5a: 0xc3a9, 0x1d5b: 0xc3c9, 0x1d5c: 0xc3e9, 0x1d5d: 0xc409,
+ 0x1d5e: 0xc429, 0x1d5f: 0xc449, 0x1d60: 0xc469, 0x1d61: 0xc489, 0x1d62: 0xc4a9, 0x1d63: 0xc4c9,
+ 0x1d64: 0xc4e9, 0x1d65: 0xc509, 0x1d66: 0xc529, 0x1d67: 0xc549, 0x1d68: 0xc569, 0x1d69: 0xc589,
+ 0x1d6a: 0xc5a9, 0x1d6b: 0xc5c9, 0x1d6c: 0xc5e9, 0x1d6d: 0xc609, 0x1d6e: 0xc629, 0x1d6f: 0xc649,
+ 0x1d70: 0xc669, 0x1d71: 0xc689, 0x1d72: 0xc6a9, 0x1d73: 0xc6c9, 0x1d74: 0xc6e9, 0x1d75: 0xc709,
+ 0x1d76: 0xc729, 0x1d77: 0xc749, 0x1d78: 0xc769, 0x1d79: 0xc789, 0x1d7a: 0xc7a9, 0x1d7b: 0xc7c9,
+ 0x1d7c: 0x0040, 0x1d7d: 0x0040, 0x1d7e: 0x0040, 0x1d7f: 0x0040,
+ // Block 0x76, offset 0x1d80
+ 0x1d80: 0xcaf9, 0x1d81: 0xcb19, 0x1d82: 0xcb39, 0x1d83: 0x8b1d, 0x1d84: 0xcb59, 0x1d85: 0xcb79,
+ 0x1d86: 0xcb99, 0x1d87: 0xcbb9, 0x1d88: 0xcbd9, 0x1d89: 0xcbf9, 0x1d8a: 0xcc19, 0x1d8b: 0xcc39,
+ 0x1d8c: 0xcc59, 0x1d8d: 0x8b3d, 0x1d8e: 0xcc79, 0x1d8f: 0xcc99, 0x1d90: 0xccb9, 0x1d91: 0xccd9,
+ 0x1d92: 0x8b5d, 0x1d93: 0xccf9, 0x1d94: 0xcd19, 0x1d95: 0xc429, 0x1d96: 0x8b7d, 0x1d97: 0xcd39,
+ 0x1d98: 0xcd59, 0x1d99: 0xcd79, 0x1d9a: 0xcd99, 0x1d9b: 0xcdb9, 0x1d9c: 0x8b9d, 0x1d9d: 0xcdd9,
+ 0x1d9e: 0xcdf9, 0x1d9f: 0xce19, 0x1da0: 0xce39, 0x1da1: 0xce59, 0x1da2: 0xc789, 0x1da3: 0xce79,
+ 0x1da4: 0xce99, 0x1da5: 0xceb9, 0x1da6: 0xced9, 0x1da7: 0xcef9, 0x1da8: 0xcf19, 0x1da9: 0xcf39,
+ 0x1daa: 0xcf59, 0x1dab: 0xcf79, 0x1dac: 0xcf99, 0x1dad: 0xcfb9, 0x1dae: 0xcfd9, 0x1daf: 0xcff9,
+ 0x1db0: 0xd019, 0x1db1: 0xd039, 0x1db2: 0xd039, 0x1db3: 0xd039, 0x1db4: 0x8bbd, 0x1db5: 0xd059,
+ 0x1db6: 0xd079, 0x1db7: 0xd099, 0x1db8: 0x8bdd, 0x1db9: 0xd0b9, 0x1dba: 0xd0d9, 0x1dbb: 0xd0f9,
+ 0x1dbc: 0xd119, 0x1dbd: 0xd139, 0x1dbe: 0xd159, 0x1dbf: 0xd179,
+ // Block 0x77, offset 0x1dc0
+ 0x1dc0: 0xd199, 0x1dc1: 0xd1b9, 0x1dc2: 0xd1d9, 0x1dc3: 0xd1f9, 0x1dc4: 0xd219, 0x1dc5: 0xd239,
+ 0x1dc6: 0xd239, 0x1dc7: 0xd259, 0x1dc8: 0xd279, 0x1dc9: 0xd299, 0x1dca: 0xd2b9, 0x1dcb: 0xd2d9,
+ 0x1dcc: 0xd2f9, 0x1dcd: 0xd319, 0x1dce: 0xd339, 0x1dcf: 0xd359, 0x1dd0: 0xd379, 0x1dd1: 0xd399,
+ 0x1dd2: 0xd3b9, 0x1dd3: 0xd3d9, 0x1dd4: 0xd3f9, 0x1dd5: 0xd419, 0x1dd6: 0xd439, 0x1dd7: 0xd459,
+ 0x1dd8: 0xd479, 0x1dd9: 0x8bfd, 0x1dda: 0xd499, 0x1ddb: 0xd4b9, 0x1ddc: 0xd4d9, 0x1ddd: 0xc309,
+ 0x1dde: 0xd4f9, 0x1ddf: 0xd519, 0x1de0: 0x8c1d, 0x1de1: 0x8c3d, 0x1de2: 0xd539, 0x1de3: 0xd559,
+ 0x1de4: 0xd579, 0x1de5: 0xd599, 0x1de6: 0xd5b9, 0x1de7: 0xd5d9, 0x1de8: 0x0040, 0x1de9: 0xd5f9,
+ 0x1dea: 0xd619, 0x1deb: 0xd619, 0x1dec: 0x8c5d, 0x1ded: 0xd639, 0x1dee: 0xd659, 0x1def: 0xd679,
+ 0x1df0: 0xd699, 0x1df1: 0x8c7d, 0x1df2: 0xd6b9, 0x1df3: 0xd6d9, 0x1df4: 0x0040, 0x1df5: 0xd6f9,
+ 0x1df6: 0xd719, 0x1df7: 0xd739, 0x1df8: 0xd759, 0x1df9: 0xd779, 0x1dfa: 0xd799, 0x1dfb: 0x8c9d,
+ 0x1dfc: 0xd7b9, 0x1dfd: 0x8cbd, 0x1dfe: 0xd7d9, 0x1dff: 0xd7f9,
+ // Block 0x78, offset 0x1e00
+ 0x1e00: 0xd819, 0x1e01: 0xd839, 0x1e02: 0xd859, 0x1e03: 0xd879, 0x1e04: 0xd899, 0x1e05: 0xd8b9,
+ 0x1e06: 0xd8d9, 0x1e07: 0xd8f9, 0x1e08: 0xd919, 0x1e09: 0x8cdd, 0x1e0a: 0xd939, 0x1e0b: 0xd959,
+ 0x1e0c: 0xd979, 0x1e0d: 0xd999, 0x1e0e: 0xd9b9, 0x1e0f: 0x8cfd, 0x1e10: 0xd9d9, 0x1e11: 0x8d1d,
+ 0x1e12: 0x8d3d, 0x1e13: 0xd9f9, 0x1e14: 0xda19, 0x1e15: 0xda19, 0x1e16: 0xda39, 0x1e17: 0x8d5d,
+ 0x1e18: 0x8d7d, 0x1e19: 0xda59, 0x1e1a: 0xda79, 0x1e1b: 0xda99, 0x1e1c: 0xdab9, 0x1e1d: 0xdad9,
+ 0x1e1e: 0xdaf9, 0x1e1f: 0xdb19, 0x1e20: 0xdb39, 0x1e21: 0xdb59, 0x1e22: 0xdb79, 0x1e23: 0xdb99,
+ 0x1e24: 0x8d9d, 0x1e25: 0xdbb9, 0x1e26: 0xdbd9, 0x1e27: 0xdbf9, 0x1e28: 0xdc19, 0x1e29: 0xdbf9,
+ 0x1e2a: 0xdc39, 0x1e2b: 0xdc59, 0x1e2c: 0xdc79, 0x1e2d: 0xdc99, 0x1e2e: 0xdcb9, 0x1e2f: 0xdcd9,
+ 0x1e30: 0xdcf9, 0x1e31: 0xdd19, 0x1e32: 0xdd39, 0x1e33: 0xdd59, 0x1e34: 0xdd79, 0x1e35: 0xdd99,
+ 0x1e36: 0xddb9, 0x1e37: 0xddd9, 0x1e38: 0x8dbd, 0x1e39: 0xddf9, 0x1e3a: 0xde19, 0x1e3b: 0xde39,
+ 0x1e3c: 0xde59, 0x1e3d: 0xde79, 0x1e3e: 0x8ddd, 0x1e3f: 0xde99,
+ // Block 0x79, offset 0x1e40
+ 0x1e40: 0xe599, 0x1e41: 0xe5b9, 0x1e42: 0xe5d9, 0x1e43: 0xe5f9, 0x1e44: 0xe619, 0x1e45: 0xe639,
+ 0x1e46: 0x8efd, 0x1e47: 0xe659, 0x1e48: 0xe679, 0x1e49: 0xe699, 0x1e4a: 0xe6b9, 0x1e4b: 0xe6d9,
+ 0x1e4c: 0xe6f9, 0x1e4d: 0x8f1d, 0x1e4e: 0xe719, 0x1e4f: 0xe739, 0x1e50: 0x8f3d, 0x1e51: 0x8f5d,
+ 0x1e52: 0xe759, 0x1e53: 0xe779, 0x1e54: 0xe799, 0x1e55: 0xe7b9, 0x1e56: 0xe7d9, 0x1e57: 0xe7f9,
+ 0x1e58: 0xe819, 0x1e59: 0xe839, 0x1e5a: 0xe859, 0x1e5b: 0x8f7d, 0x1e5c: 0xe879, 0x1e5d: 0x8f9d,
+ 0x1e5e: 0xe899, 0x1e5f: 0x0040, 0x1e60: 0xe8b9, 0x1e61: 0xe8d9, 0x1e62: 0xe8f9, 0x1e63: 0x8fbd,
+ 0x1e64: 0xe919, 0x1e65: 0xe939, 0x1e66: 0x8fdd, 0x1e67: 0x8ffd, 0x1e68: 0xe959, 0x1e69: 0xe979,
+ 0x1e6a: 0xe999, 0x1e6b: 0xe9b9, 0x1e6c: 0xe9d9, 0x1e6d: 0xe9d9, 0x1e6e: 0xe9f9, 0x1e6f: 0xea19,
+ 0x1e70: 0xea39, 0x1e71: 0xea59, 0x1e72: 0xea79, 0x1e73: 0xea99, 0x1e74: 0xeab9, 0x1e75: 0x901d,
+ 0x1e76: 0xead9, 0x1e77: 0x903d, 0x1e78: 0xeaf9, 0x1e79: 0x905d, 0x1e7a: 0xeb19, 0x1e7b: 0x907d,
+ 0x1e7c: 0x909d, 0x1e7d: 0x90bd, 0x1e7e: 0xeb39, 0x1e7f: 0xeb59,
+ // Block 0x7a, offset 0x1e80
+ 0x1e80: 0xeb79, 0x1e81: 0x90dd, 0x1e82: 0x90fd, 0x1e83: 0x911d, 0x1e84: 0x913d, 0x1e85: 0xeb99,
+ 0x1e86: 0xebb9, 0x1e87: 0xebb9, 0x1e88: 0xebd9, 0x1e89: 0xebf9, 0x1e8a: 0xec19, 0x1e8b: 0xec39,
+ 0x1e8c: 0xec59, 0x1e8d: 0x915d, 0x1e8e: 0xec79, 0x1e8f: 0xec99, 0x1e90: 0xecb9, 0x1e91: 0xecd9,
+ 0x1e92: 0x917d, 0x1e93: 0xecf9, 0x1e94: 0x919d, 0x1e95: 0x91bd, 0x1e96: 0xed19, 0x1e97: 0xed39,
+ 0x1e98: 0xed59, 0x1e99: 0xed79, 0x1e9a: 0xed99, 0x1e9b: 0xedb9, 0x1e9c: 0x91dd, 0x1e9d: 0x91fd,
+ 0x1e9e: 0x921d, 0x1e9f: 0x0040, 0x1ea0: 0xedd9, 0x1ea1: 0x923d, 0x1ea2: 0xedf9, 0x1ea3: 0xee19,
+ 0x1ea4: 0xee39, 0x1ea5: 0x925d, 0x1ea6: 0xee59, 0x1ea7: 0xee79, 0x1ea8: 0xee99, 0x1ea9: 0xeeb9,
+ 0x1eaa: 0xeed9, 0x1eab: 0x927d, 0x1eac: 0xeef9, 0x1ead: 0xef19, 0x1eae: 0xef39, 0x1eaf: 0xef59,
+ 0x1eb0: 0xef79, 0x1eb1: 0xef99, 0x1eb2: 0x929d, 0x1eb3: 0x92bd, 0x1eb4: 0xefb9, 0x1eb5: 0x92dd,
+ 0x1eb6: 0xefd9, 0x1eb7: 0x92fd, 0x1eb8: 0xeff9, 0x1eb9: 0xf019, 0x1eba: 0xf039, 0x1ebb: 0x931d,
+ 0x1ebc: 0x933d, 0x1ebd: 0xf059, 0x1ebe: 0x935d, 0x1ebf: 0xf079,
+ // Block 0x7b, offset 0x1ec0
+ 0x1ec0: 0xf6b9, 0x1ec1: 0xf6d9, 0x1ec2: 0xf6f9, 0x1ec3: 0xf719, 0x1ec4: 0xf739, 0x1ec5: 0x951d,
+ 0x1ec6: 0xf759, 0x1ec7: 0xf779, 0x1ec8: 0xf799, 0x1ec9: 0xf7b9, 0x1eca: 0xf7d9, 0x1ecb: 0x953d,
+ 0x1ecc: 0x955d, 0x1ecd: 0xf7f9, 0x1ece: 0xf819, 0x1ecf: 0xf839, 0x1ed0: 0xf859, 0x1ed1: 0xf879,
+ 0x1ed2: 0xf899, 0x1ed3: 0x957d, 0x1ed4: 0xf8b9, 0x1ed5: 0xf8d9, 0x1ed6: 0xf8f9, 0x1ed7: 0xf919,
+ 0x1ed8: 0x959d, 0x1ed9: 0x95bd, 0x1eda: 0xf939, 0x1edb: 0xf959, 0x1edc: 0xf979, 0x1edd: 0x95dd,
+ 0x1ede: 0xf999, 0x1edf: 0xf9b9, 0x1ee0: 0x6815, 0x1ee1: 0x95fd, 0x1ee2: 0xf9d9, 0x1ee3: 0xf9f9,
+ 0x1ee4: 0xfa19, 0x1ee5: 0x961d, 0x1ee6: 0xfa39, 0x1ee7: 0xfa59, 0x1ee8: 0xfa79, 0x1ee9: 0xfa99,
+ 0x1eea: 0xfab9, 0x1eeb: 0xfad9, 0x1eec: 0xfaf9, 0x1eed: 0x963d, 0x1eee: 0xfb19, 0x1eef: 0xfb39,
+ 0x1ef0: 0xfb59, 0x1ef1: 0x965d, 0x1ef2: 0xfb79, 0x1ef3: 0xfb99, 0x1ef4: 0xfbb9, 0x1ef5: 0xfbd9,
+ 0x1ef6: 0x7b35, 0x1ef7: 0x967d, 0x1ef8: 0xfbf9, 0x1ef9: 0xfc19, 0x1efa: 0xfc39, 0x1efb: 0x969d,
+ 0x1efc: 0xfc59, 0x1efd: 0x96bd, 0x1efe: 0xfc79, 0x1eff: 0xfc79,
+ // Block 0x7c, offset 0x1f00
+ 0x1f00: 0xfc99, 0x1f01: 0x96dd, 0x1f02: 0xfcb9, 0x1f03: 0xfcd9, 0x1f04: 0xfcf9, 0x1f05: 0xfd19,
+ 0x1f06: 0xfd39, 0x1f07: 0xfd59, 0x1f08: 0xfd79, 0x1f09: 0x96fd, 0x1f0a: 0xfd99, 0x1f0b: 0xfdb9,
+ 0x1f0c: 0xfdd9, 0x1f0d: 0xfdf9, 0x1f0e: 0xfe19, 0x1f0f: 0xfe39, 0x1f10: 0x971d, 0x1f11: 0xfe59,
+ 0x1f12: 0x973d, 0x1f13: 0x975d, 0x1f14: 0x977d, 0x1f15: 0xfe79, 0x1f16: 0xfe99, 0x1f17: 0xfeb9,
+ 0x1f18: 0xfed9, 0x1f19: 0xfef9, 0x1f1a: 0xff19, 0x1f1b: 0xff39, 0x1f1c: 0xff59, 0x1f1d: 0x979d,
+ 0x1f1e: 0x0040, 0x1f1f: 0x0040, 0x1f20: 0x0040, 0x1f21: 0x0040, 0x1f22: 0x0040, 0x1f23: 0x0040,
+ 0x1f24: 0x0040, 0x1f25: 0x0040, 0x1f26: 0x0040, 0x1f27: 0x0040, 0x1f28: 0x0040, 0x1f29: 0x0040,
+ 0x1f2a: 0x0040, 0x1f2b: 0x0040, 0x1f2c: 0x0040, 0x1f2d: 0x0040, 0x1f2e: 0x0040, 0x1f2f: 0x0040,
+ 0x1f30: 0x0040, 0x1f31: 0x0040, 0x1f32: 0x0040, 0x1f33: 0x0040, 0x1f34: 0x0040, 0x1f35: 0x0040,
+ 0x1f36: 0x0040, 0x1f37: 0x0040, 0x1f38: 0x0040, 0x1f39: 0x0040, 0x1f3a: 0x0040, 0x1f3b: 0x0040,
+ 0x1f3c: 0x0040, 0x1f3d: 0x0040, 0x1f3e: 0x0040, 0x1f3f: 0x0040,
+}
+
+// idnaIndex: 35 blocks, 2240 entries, 4480 bytes
+// Block 0 is the zero block.
+var idnaIndex = [2240]uint16{
+ // Block 0x0, offset 0x0
+ // Block 0x1, offset 0x40
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc2: 0x01, 0xc3: 0x7b, 0xc4: 0x02, 0xc5: 0x03, 0xc6: 0x04, 0xc7: 0x05,
+ 0xc8: 0x06, 0xc9: 0x7c, 0xca: 0x7d, 0xcb: 0x07, 0xcc: 0x7e, 0xcd: 0x08, 0xce: 0x09, 0xcf: 0x0a,
+ 0xd0: 0x7f, 0xd1: 0x0b, 0xd2: 0x0c, 0xd3: 0x0d, 0xd4: 0x0e, 0xd5: 0x80, 0xd6: 0x81, 0xd7: 0x82,
+ 0xd8: 0x0f, 0xd9: 0x83, 0xda: 0x84, 0xdb: 0x10, 0xdc: 0x11, 0xdd: 0x85, 0xde: 0x86, 0xdf: 0x87,
+ 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05, 0xe4: 0x06, 0xe5: 0x07, 0xe6: 0x07, 0xe7: 0x07,
+ 0xe8: 0x07, 0xe9: 0x08, 0xea: 0x09, 0xeb: 0x07, 0xec: 0x07, 0xed: 0x0a, 0xee: 0x0b, 0xef: 0x0c,
+ 0xf0: 0x1c, 0xf1: 0x1d, 0xf2: 0x1d, 0xf3: 0x1f, 0xf4: 0x20,
+ // Block 0x4, offset 0x100
+ 0x120: 0x88, 0x121: 0x89, 0x122: 0x8a, 0x123: 0x8b, 0x124: 0x8c, 0x125: 0x12, 0x126: 0x13, 0x127: 0x14,
+ 0x128: 0x15, 0x129: 0x16, 0x12a: 0x17, 0x12b: 0x18, 0x12c: 0x19, 0x12d: 0x1a, 0x12e: 0x1b, 0x12f: 0x8d,
+ 0x130: 0x8e, 0x131: 0x1c, 0x132: 0x1d, 0x133: 0x1e, 0x134: 0x8f, 0x135: 0x1f, 0x136: 0x90, 0x137: 0x91,
+ 0x138: 0x92, 0x139: 0x93, 0x13a: 0x20, 0x13b: 0x94, 0x13c: 0x95, 0x13d: 0x21, 0x13e: 0x22, 0x13f: 0x96,
+ // Block 0x5, offset 0x140
+ 0x140: 0x97, 0x141: 0x98, 0x142: 0x99, 0x143: 0x9a, 0x144: 0x9b, 0x145: 0x9c, 0x146: 0x9b, 0x147: 0x9b,
+ 0x148: 0x9d, 0x149: 0x9e, 0x14a: 0x9f, 0x14b: 0xa0, 0x14c: 0xa1, 0x14d: 0xa2, 0x14e: 0xa3, 0x14f: 0xa4,
+ 0x150: 0xa5, 0x151: 0x9d, 0x152: 0x9d, 0x153: 0x9d, 0x154: 0x9d, 0x155: 0x9d, 0x156: 0x9d, 0x157: 0x9d,
+ 0x158: 0x9d, 0x159: 0xa6, 0x15a: 0xa7, 0x15b: 0xa8, 0x15c: 0xa9, 0x15d: 0xaa, 0x15e: 0xab, 0x15f: 0xac,
+ 0x160: 0xad, 0x161: 0xae, 0x162: 0xaf, 0x163: 0xb0, 0x164: 0xb1, 0x165: 0xb2, 0x166: 0xb3, 0x167: 0xb4,
+ 0x168: 0xb5, 0x169: 0xb6, 0x16a: 0xb7, 0x16b: 0xb8, 0x16c: 0xb9, 0x16d: 0xba, 0x16e: 0xbb, 0x16f: 0xbc,
+ 0x170: 0xbd, 0x171: 0xbe, 0x172: 0xbf, 0x173: 0xc0, 0x174: 0x23, 0x175: 0x24, 0x176: 0x25, 0x177: 0xc1,
+ 0x178: 0x26, 0x179: 0x26, 0x17a: 0x27, 0x17b: 0x26, 0x17c: 0xc2, 0x17d: 0x28, 0x17e: 0x29, 0x17f: 0x2a,
+ // Block 0x6, offset 0x180
+ 0x180: 0x2b, 0x181: 0x2c, 0x182: 0x2d, 0x183: 0xc3, 0x184: 0x2e, 0x185: 0x2f, 0x186: 0xc4, 0x187: 0x9b,
+ 0x188: 0xc5, 0x189: 0xc6, 0x18a: 0x9b, 0x18b: 0x9b, 0x18c: 0xc7, 0x18d: 0x9b, 0x18e: 0x9b, 0x18f: 0xc8,
+ 0x190: 0xc9, 0x191: 0x30, 0x192: 0x31, 0x193: 0x32, 0x194: 0x9b, 0x195: 0x9b, 0x196: 0x9b, 0x197: 0x9b,
+ 0x198: 0x9b, 0x199: 0x9b, 0x19a: 0x9b, 0x19b: 0x9b, 0x19c: 0x9b, 0x19d: 0x9b, 0x19e: 0x9b, 0x19f: 0x9b,
+ 0x1a0: 0x9b, 0x1a1: 0x9b, 0x1a2: 0x9b, 0x1a3: 0x9b, 0x1a4: 0x9b, 0x1a5: 0x9b, 0x1a6: 0x9b, 0x1a7: 0x9b,
+ 0x1a8: 0xca, 0x1a9: 0xcb, 0x1aa: 0x9b, 0x1ab: 0xcc, 0x1ac: 0x9b, 0x1ad: 0xcd, 0x1ae: 0xce, 0x1af: 0xcf,
+ 0x1b0: 0xd0, 0x1b1: 0x33, 0x1b2: 0x26, 0x1b3: 0x34, 0x1b4: 0xd1, 0x1b5: 0xd2, 0x1b6: 0xd3, 0x1b7: 0xd4,
+ 0x1b8: 0xd5, 0x1b9: 0xd6, 0x1ba: 0xd7, 0x1bb: 0xd8, 0x1bc: 0xd9, 0x1bd: 0xda, 0x1be: 0xdb, 0x1bf: 0x35,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x36, 0x1c1: 0xdc, 0x1c2: 0xdd, 0x1c3: 0xde, 0x1c4: 0xdf, 0x1c5: 0x37, 0x1c6: 0x38, 0x1c7: 0xe0,
+ 0x1c8: 0xe1, 0x1c9: 0x39, 0x1ca: 0x3a, 0x1cb: 0x3b, 0x1cc: 0x3c, 0x1cd: 0x3d, 0x1ce: 0x3e, 0x1cf: 0x3f,
+ 0x1d0: 0x9d, 0x1d1: 0x9d, 0x1d2: 0x9d, 0x1d3: 0x9d, 0x1d4: 0x9d, 0x1d5: 0x9d, 0x1d6: 0x9d, 0x1d7: 0x9d,
+ 0x1d8: 0x9d, 0x1d9: 0x9d, 0x1da: 0x9d, 0x1db: 0x9d, 0x1dc: 0x9d, 0x1dd: 0x9d, 0x1de: 0x9d, 0x1df: 0x9d,
+ 0x1e0: 0x9d, 0x1e1: 0x9d, 0x1e2: 0x9d, 0x1e3: 0x9d, 0x1e4: 0x9d, 0x1e5: 0x9d, 0x1e6: 0x9d, 0x1e7: 0x9d,
+ 0x1e8: 0x9d, 0x1e9: 0x9d, 0x1ea: 0x9d, 0x1eb: 0x9d, 0x1ec: 0x9d, 0x1ed: 0x9d, 0x1ee: 0x9d, 0x1ef: 0x9d,
+ 0x1f0: 0x9d, 0x1f1: 0x9d, 0x1f2: 0x9d, 0x1f3: 0x9d, 0x1f4: 0x9d, 0x1f5: 0x9d, 0x1f6: 0x9d, 0x1f7: 0x9d,
+ 0x1f8: 0x9d, 0x1f9: 0x9d, 0x1fa: 0x9d, 0x1fb: 0x9d, 0x1fc: 0x9d, 0x1fd: 0x9d, 0x1fe: 0x9d, 0x1ff: 0x9d,
+ // Block 0x8, offset 0x200
+ 0x200: 0x9d, 0x201: 0x9d, 0x202: 0x9d, 0x203: 0x9d, 0x204: 0x9d, 0x205: 0x9d, 0x206: 0x9d, 0x207: 0x9d,
+ 0x208: 0x9d, 0x209: 0x9d, 0x20a: 0x9d, 0x20b: 0x9d, 0x20c: 0x9d, 0x20d: 0x9d, 0x20e: 0x9d, 0x20f: 0x9d,
+ 0x210: 0x9d, 0x211: 0x9d, 0x212: 0x9d, 0x213: 0x9d, 0x214: 0x9d, 0x215: 0x9d, 0x216: 0x9d, 0x217: 0x9d,
+ 0x218: 0x9d, 0x219: 0x9d, 0x21a: 0x9d, 0x21b: 0x9d, 0x21c: 0x9d, 0x21d: 0x9d, 0x21e: 0x9d, 0x21f: 0x9d,
+ 0x220: 0x9d, 0x221: 0x9d, 0x222: 0x9d, 0x223: 0x9d, 0x224: 0x9d, 0x225: 0x9d, 0x226: 0x9d, 0x227: 0x9d,
+ 0x228: 0x9d, 0x229: 0x9d, 0x22a: 0x9d, 0x22b: 0x9d, 0x22c: 0x9d, 0x22d: 0x9d, 0x22e: 0x9d, 0x22f: 0x9d,
+ 0x230: 0x9d, 0x231: 0x9d, 0x232: 0x9d, 0x233: 0x9d, 0x234: 0x9d, 0x235: 0x9d, 0x236: 0xb0, 0x237: 0x9b,
+ 0x238: 0x9d, 0x239: 0x9d, 0x23a: 0x9d, 0x23b: 0x9d, 0x23c: 0x9d, 0x23d: 0x9d, 0x23e: 0x9d, 0x23f: 0x9d,
+ // Block 0x9, offset 0x240
+ 0x240: 0x9d, 0x241: 0x9d, 0x242: 0x9d, 0x243: 0x9d, 0x244: 0x9d, 0x245: 0x9d, 0x246: 0x9d, 0x247: 0x9d,
+ 0x248: 0x9d, 0x249: 0x9d, 0x24a: 0x9d, 0x24b: 0x9d, 0x24c: 0x9d, 0x24d: 0x9d, 0x24e: 0x9d, 0x24f: 0x9d,
+ 0x250: 0x9d, 0x251: 0x9d, 0x252: 0x9d, 0x253: 0x9d, 0x254: 0x9d, 0x255: 0x9d, 0x256: 0x9d, 0x257: 0x9d,
+ 0x258: 0x9d, 0x259: 0x9d, 0x25a: 0x9d, 0x25b: 0x9d, 0x25c: 0x9d, 0x25d: 0x9d, 0x25e: 0x9d, 0x25f: 0x9d,
+ 0x260: 0x9d, 0x261: 0x9d, 0x262: 0x9d, 0x263: 0x9d, 0x264: 0x9d, 0x265: 0x9d, 0x266: 0x9d, 0x267: 0x9d,
+ 0x268: 0x9d, 0x269: 0x9d, 0x26a: 0x9d, 0x26b: 0x9d, 0x26c: 0x9d, 0x26d: 0x9d, 0x26e: 0x9d, 0x26f: 0x9d,
+ 0x270: 0x9d, 0x271: 0x9d, 0x272: 0x9d, 0x273: 0x9d, 0x274: 0x9d, 0x275: 0x9d, 0x276: 0x9d, 0x277: 0x9d,
+ 0x278: 0x9d, 0x279: 0x9d, 0x27a: 0x9d, 0x27b: 0x9d, 0x27c: 0x9d, 0x27d: 0x9d, 0x27e: 0x9d, 0x27f: 0x9d,
+ // Block 0xa, offset 0x280
+ 0x280: 0x9d, 0x281: 0x9d, 0x282: 0x9d, 0x283: 0x9d, 0x284: 0x9d, 0x285: 0x9d, 0x286: 0x9d, 0x287: 0x9d,
+ 0x288: 0x9d, 0x289: 0x9d, 0x28a: 0x9d, 0x28b: 0x9d, 0x28c: 0x9d, 0x28d: 0x9d, 0x28e: 0x9d, 0x28f: 0x9d,
+ 0x290: 0x9d, 0x291: 0x9d, 0x292: 0x9d, 0x293: 0x9d, 0x294: 0x9d, 0x295: 0x9d, 0x296: 0x9d, 0x297: 0x9d,
+ 0x298: 0x9d, 0x299: 0x9d, 0x29a: 0x9d, 0x29b: 0x9d, 0x29c: 0x9d, 0x29d: 0x9d, 0x29e: 0x9d, 0x29f: 0x9d,
+ 0x2a0: 0x9d, 0x2a1: 0x9d, 0x2a2: 0x9d, 0x2a3: 0x9d, 0x2a4: 0x9d, 0x2a5: 0x9d, 0x2a6: 0x9d, 0x2a7: 0x9d,
+ 0x2a8: 0x9d, 0x2a9: 0x9d, 0x2aa: 0x9d, 0x2ab: 0x9d, 0x2ac: 0x9d, 0x2ad: 0x9d, 0x2ae: 0x9d, 0x2af: 0x9d,
+ 0x2b0: 0x9d, 0x2b1: 0x9d, 0x2b2: 0x9d, 0x2b3: 0x9d, 0x2b4: 0x9d, 0x2b5: 0x9d, 0x2b6: 0x9d, 0x2b7: 0x9d,
+ 0x2b8: 0x9d, 0x2b9: 0x9d, 0x2ba: 0x9d, 0x2bb: 0x9d, 0x2bc: 0x9d, 0x2bd: 0x9d, 0x2be: 0x9d, 0x2bf: 0xe2,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0x9d, 0x2c1: 0x9d, 0x2c2: 0x9d, 0x2c3: 0x9d, 0x2c4: 0x9d, 0x2c5: 0x9d, 0x2c6: 0x9d, 0x2c7: 0x9d,
+ 0x2c8: 0x9d, 0x2c9: 0x9d, 0x2ca: 0x9d, 0x2cb: 0x9d, 0x2cc: 0x9d, 0x2cd: 0x9d, 0x2ce: 0x9d, 0x2cf: 0x9d,
+ 0x2d0: 0x9d, 0x2d1: 0x9d, 0x2d2: 0xe3, 0x2d3: 0xe4, 0x2d4: 0x9d, 0x2d5: 0x9d, 0x2d6: 0x9d, 0x2d7: 0x9d,
+ 0x2d8: 0xe5, 0x2d9: 0x40, 0x2da: 0x41, 0x2db: 0xe6, 0x2dc: 0x42, 0x2dd: 0x43, 0x2de: 0x44, 0x2df: 0xe7,
+ 0x2e0: 0xe8, 0x2e1: 0xe9, 0x2e2: 0xea, 0x2e3: 0xeb, 0x2e4: 0xec, 0x2e5: 0xed, 0x2e6: 0xee, 0x2e7: 0xef,
+ 0x2e8: 0xf0, 0x2e9: 0xf1, 0x2ea: 0xf2, 0x2eb: 0xf3, 0x2ec: 0xf4, 0x2ed: 0xf5, 0x2ee: 0xf6, 0x2ef: 0xf7,
+ 0x2f0: 0x9d, 0x2f1: 0x9d, 0x2f2: 0x9d, 0x2f3: 0x9d, 0x2f4: 0x9d, 0x2f5: 0x9d, 0x2f6: 0x9d, 0x2f7: 0x9d,
+ 0x2f8: 0x9d, 0x2f9: 0x9d, 0x2fa: 0x9d, 0x2fb: 0x9d, 0x2fc: 0x9d, 0x2fd: 0x9d, 0x2fe: 0x9d, 0x2ff: 0x9d,
+ // Block 0xc, offset 0x300
+ 0x300: 0x9d, 0x301: 0x9d, 0x302: 0x9d, 0x303: 0x9d, 0x304: 0x9d, 0x305: 0x9d, 0x306: 0x9d, 0x307: 0x9d,
+ 0x308: 0x9d, 0x309: 0x9d, 0x30a: 0x9d, 0x30b: 0x9d, 0x30c: 0x9d, 0x30d: 0x9d, 0x30e: 0x9d, 0x30f: 0x9d,
+ 0x310: 0x9d, 0x311: 0x9d, 0x312: 0x9d, 0x313: 0x9d, 0x314: 0x9d, 0x315: 0x9d, 0x316: 0x9d, 0x317: 0x9d,
+ 0x318: 0x9d, 0x319: 0x9d, 0x31a: 0x9d, 0x31b: 0x9d, 0x31c: 0x9d, 0x31d: 0x9d, 0x31e: 0xf8, 0x31f: 0xf9,
+ // Block 0xd, offset 0x340
+ 0x340: 0xb8, 0x341: 0xb8, 0x342: 0xb8, 0x343: 0xb8, 0x344: 0xb8, 0x345: 0xb8, 0x346: 0xb8, 0x347: 0xb8,
+ 0x348: 0xb8, 0x349: 0xb8, 0x34a: 0xb8, 0x34b: 0xb8, 0x34c: 0xb8, 0x34d: 0xb8, 0x34e: 0xb8, 0x34f: 0xb8,
+ 0x350: 0xb8, 0x351: 0xb8, 0x352: 0xb8, 0x353: 0xb8, 0x354: 0xb8, 0x355: 0xb8, 0x356: 0xb8, 0x357: 0xb8,
+ 0x358: 0xb8, 0x359: 0xb8, 0x35a: 0xb8, 0x35b: 0xb8, 0x35c: 0xb8, 0x35d: 0xb8, 0x35e: 0xb8, 0x35f: 0xb8,
+ 0x360: 0xb8, 0x361: 0xb8, 0x362: 0xb8, 0x363: 0xb8, 0x364: 0xb8, 0x365: 0xb8, 0x366: 0xb8, 0x367: 0xb8,
+ 0x368: 0xb8, 0x369: 0xb8, 0x36a: 0xb8, 0x36b: 0xb8, 0x36c: 0xb8, 0x36d: 0xb8, 0x36e: 0xb8, 0x36f: 0xb8,
+ 0x370: 0xb8, 0x371: 0xb8, 0x372: 0xb8, 0x373: 0xb8, 0x374: 0xb8, 0x375: 0xb8, 0x376: 0xb8, 0x377: 0xb8,
+ 0x378: 0xb8, 0x379: 0xb8, 0x37a: 0xb8, 0x37b: 0xb8, 0x37c: 0xb8, 0x37d: 0xb8, 0x37e: 0xb8, 0x37f: 0xb8,
+ // Block 0xe, offset 0x380
+ 0x380: 0xb8, 0x381: 0xb8, 0x382: 0xb8, 0x383: 0xb8, 0x384: 0xb8, 0x385: 0xb8, 0x386: 0xb8, 0x387: 0xb8,
+ 0x388: 0xb8, 0x389: 0xb8, 0x38a: 0xb8, 0x38b: 0xb8, 0x38c: 0xb8, 0x38d: 0xb8, 0x38e: 0xb8, 0x38f: 0xb8,
+ 0x390: 0xb8, 0x391: 0xb8, 0x392: 0xb8, 0x393: 0xb8, 0x394: 0xb8, 0x395: 0xb8, 0x396: 0xb8, 0x397: 0xb8,
+ 0x398: 0xb8, 0x399: 0xb8, 0x39a: 0xb8, 0x39b: 0xb8, 0x39c: 0xb8, 0x39d: 0xb8, 0x39e: 0xb8, 0x39f: 0xb8,
+ 0x3a0: 0xb8, 0x3a1: 0xb8, 0x3a2: 0xb8, 0x3a3: 0xb8, 0x3a4: 0xfa, 0x3a5: 0xfb, 0x3a6: 0xfc, 0x3a7: 0xfd,
+ 0x3a8: 0x45, 0x3a9: 0xfe, 0x3aa: 0xff, 0x3ab: 0x46, 0x3ac: 0x47, 0x3ad: 0x48, 0x3ae: 0x49, 0x3af: 0x4a,
+ 0x3b0: 0x100, 0x3b1: 0x4b, 0x3b2: 0x4c, 0x3b3: 0x4d, 0x3b4: 0x4e, 0x3b5: 0x4f, 0x3b6: 0x101, 0x3b7: 0x50,
+ 0x3b8: 0x51, 0x3b9: 0x52, 0x3ba: 0x53, 0x3bb: 0x54, 0x3bc: 0x55, 0x3bd: 0x56, 0x3be: 0x57, 0x3bf: 0x58,
+ // Block 0xf, offset 0x3c0
+ 0x3c0: 0x102, 0x3c1: 0x103, 0x3c2: 0x9d, 0x3c3: 0x104, 0x3c4: 0x105, 0x3c5: 0x9b, 0x3c6: 0x106, 0x3c7: 0x107,
+ 0x3c8: 0xb8, 0x3c9: 0xb8, 0x3ca: 0x108, 0x3cb: 0x109, 0x3cc: 0x10a, 0x3cd: 0x10b, 0x3ce: 0x10c, 0x3cf: 0x10d,
+ 0x3d0: 0x10e, 0x3d1: 0x9d, 0x3d2: 0x10f, 0x3d3: 0x110, 0x3d4: 0x111, 0x3d5: 0x112, 0x3d6: 0xb8, 0x3d7: 0xb8,
+ 0x3d8: 0x9d, 0x3d9: 0x9d, 0x3da: 0x9d, 0x3db: 0x9d, 0x3dc: 0x113, 0x3dd: 0x114, 0x3de: 0xb8, 0x3df: 0xb8,
+ 0x3e0: 0x115, 0x3e1: 0x116, 0x3e2: 0x117, 0x3e3: 0x118, 0x3e4: 0x119, 0x3e5: 0xb8, 0x3e6: 0x11a, 0x3e7: 0x11b,
+ 0x3e8: 0x11c, 0x3e9: 0x11d, 0x3ea: 0x11e, 0x3eb: 0x59, 0x3ec: 0x11f, 0x3ed: 0x120, 0x3ee: 0x5a, 0x3ef: 0xb8,
+ 0x3f0: 0x9d, 0x3f1: 0x121, 0x3f2: 0x122, 0x3f3: 0x123, 0x3f4: 0xb8, 0x3f5: 0xb8, 0x3f6: 0xb8, 0x3f7: 0xb8,
+ 0x3f8: 0xb8, 0x3f9: 0x124, 0x3fa: 0xb8, 0x3fb: 0xb8, 0x3fc: 0xb8, 0x3fd: 0xb8, 0x3fe: 0xb8, 0x3ff: 0xb8,
+ // Block 0x10, offset 0x400
+ 0x400: 0x125, 0x401: 0x126, 0x402: 0x127, 0x403: 0x128, 0x404: 0x129, 0x405: 0x12a, 0x406: 0x12b, 0x407: 0x12c,
+ 0x408: 0x12d, 0x409: 0xb8, 0x40a: 0x12e, 0x40b: 0x12f, 0x40c: 0x5b, 0x40d: 0x5c, 0x40e: 0xb8, 0x40f: 0xb8,
+ 0x410: 0x130, 0x411: 0x131, 0x412: 0x132, 0x413: 0x133, 0x414: 0xb8, 0x415: 0xb8, 0x416: 0x134, 0x417: 0x135,
+ 0x418: 0x136, 0x419: 0x137, 0x41a: 0x138, 0x41b: 0x139, 0x41c: 0x13a, 0x41d: 0xb8, 0x41e: 0xb8, 0x41f: 0xb8,
+ 0x420: 0xb8, 0x421: 0xb8, 0x422: 0x13b, 0x423: 0x13c, 0x424: 0xb8, 0x425: 0xb8, 0x426: 0xb8, 0x427: 0xb8,
+ 0x428: 0xb8, 0x429: 0xb8, 0x42a: 0xb8, 0x42b: 0x13d, 0x42c: 0xb8, 0x42d: 0xb8, 0x42e: 0xb8, 0x42f: 0xb8,
+ 0x430: 0x13e, 0x431: 0x13f, 0x432: 0x140, 0x433: 0xb8, 0x434: 0xb8, 0x435: 0xb8, 0x436: 0xb8, 0x437: 0xb8,
+ 0x438: 0xb8, 0x439: 0xb8, 0x43a: 0xb8, 0x43b: 0xb8, 0x43c: 0xb8, 0x43d: 0xb8, 0x43e: 0xb8, 0x43f: 0xb8,
+ // Block 0x11, offset 0x440
+ 0x440: 0x9d, 0x441: 0x9d, 0x442: 0x9d, 0x443: 0x9d, 0x444: 0x9d, 0x445: 0x9d, 0x446: 0x9d, 0x447: 0x9d,
+ 0x448: 0x9d, 0x449: 0x9d, 0x44a: 0x9d, 0x44b: 0x9d, 0x44c: 0x9d, 0x44d: 0x9d, 0x44e: 0x141, 0x44f: 0xb8,
+ 0x450: 0x9b, 0x451: 0x142, 0x452: 0x9d, 0x453: 0x9d, 0x454: 0x9d, 0x455: 0x143, 0x456: 0xb8, 0x457: 0xb8,
+ 0x458: 0xb8, 0x459: 0xb8, 0x45a: 0xb8, 0x45b: 0xb8, 0x45c: 0xb8, 0x45d: 0xb8, 0x45e: 0xb8, 0x45f: 0xb8,
+ 0x460: 0xb8, 0x461: 0xb8, 0x462: 0xb8, 0x463: 0xb8, 0x464: 0xb8, 0x465: 0xb8, 0x466: 0xb8, 0x467: 0xb8,
+ 0x468: 0xb8, 0x469: 0xb8, 0x46a: 0xb8, 0x46b: 0xb8, 0x46c: 0xb8, 0x46d: 0xb8, 0x46e: 0xb8, 0x46f: 0xb8,
+ 0x470: 0xb8, 0x471: 0xb8, 0x472: 0xb8, 0x473: 0xb8, 0x474: 0xb8, 0x475: 0xb8, 0x476: 0xb8, 0x477: 0xb8,
+ 0x478: 0xb8, 0x479: 0xb8, 0x47a: 0xb8, 0x47b: 0xb8, 0x47c: 0xb8, 0x47d: 0xb8, 0x47e: 0xb8, 0x47f: 0xb8,
+ // Block 0x12, offset 0x480
+ 0x480: 0x9d, 0x481: 0x9d, 0x482: 0x9d, 0x483: 0x9d, 0x484: 0x9d, 0x485: 0x9d, 0x486: 0x9d, 0x487: 0x9d,
+ 0x488: 0x9d, 0x489: 0x9d, 0x48a: 0x9d, 0x48b: 0x9d, 0x48c: 0x9d, 0x48d: 0x9d, 0x48e: 0x9d, 0x48f: 0x9d,
+ 0x490: 0x144, 0x491: 0xb8, 0x492: 0xb8, 0x493: 0xb8, 0x494: 0xb8, 0x495: 0xb8, 0x496: 0xb8, 0x497: 0xb8,
+ 0x498: 0xb8, 0x499: 0xb8, 0x49a: 0xb8, 0x49b: 0xb8, 0x49c: 0xb8, 0x49d: 0xb8, 0x49e: 0xb8, 0x49f: 0xb8,
+ 0x4a0: 0xb8, 0x4a1: 0xb8, 0x4a2: 0xb8, 0x4a3: 0xb8, 0x4a4: 0xb8, 0x4a5: 0xb8, 0x4a6: 0xb8, 0x4a7: 0xb8,
+ 0x4a8: 0xb8, 0x4a9: 0xb8, 0x4aa: 0xb8, 0x4ab: 0xb8, 0x4ac: 0xb8, 0x4ad: 0xb8, 0x4ae: 0xb8, 0x4af: 0xb8,
+ 0x4b0: 0xb8, 0x4b1: 0xb8, 0x4b2: 0xb8, 0x4b3: 0xb8, 0x4b4: 0xb8, 0x4b5: 0xb8, 0x4b6: 0xb8, 0x4b7: 0xb8,
+ 0x4b8: 0xb8, 0x4b9: 0xb8, 0x4ba: 0xb8, 0x4bb: 0xb8, 0x4bc: 0xb8, 0x4bd: 0xb8, 0x4be: 0xb8, 0x4bf: 0xb8,
+ // Block 0x13, offset 0x4c0
+ 0x4c0: 0xb8, 0x4c1: 0xb8, 0x4c2: 0xb8, 0x4c3: 0xb8, 0x4c4: 0xb8, 0x4c5: 0xb8, 0x4c6: 0xb8, 0x4c7: 0xb8,
+ 0x4c8: 0xb8, 0x4c9: 0xb8, 0x4ca: 0xb8, 0x4cb: 0xb8, 0x4cc: 0xb8, 0x4cd: 0xb8, 0x4ce: 0xb8, 0x4cf: 0xb8,
+ 0x4d0: 0x9d, 0x4d1: 0x9d, 0x4d2: 0x9d, 0x4d3: 0x9d, 0x4d4: 0x9d, 0x4d5: 0x9d, 0x4d6: 0x9d, 0x4d7: 0x9d,
+ 0x4d8: 0x9d, 0x4d9: 0x145, 0x4da: 0xb8, 0x4db: 0xb8, 0x4dc: 0xb8, 0x4dd: 0xb8, 0x4de: 0xb8, 0x4df: 0xb8,
+ 0x4e0: 0xb8, 0x4e1: 0xb8, 0x4e2: 0xb8, 0x4e3: 0xb8, 0x4e4: 0xb8, 0x4e5: 0xb8, 0x4e6: 0xb8, 0x4e7: 0xb8,
+ 0x4e8: 0xb8, 0x4e9: 0xb8, 0x4ea: 0xb8, 0x4eb: 0xb8, 0x4ec: 0xb8, 0x4ed: 0xb8, 0x4ee: 0xb8, 0x4ef: 0xb8,
+ 0x4f0: 0xb8, 0x4f1: 0xb8, 0x4f2: 0xb8, 0x4f3: 0xb8, 0x4f4: 0xb8, 0x4f5: 0xb8, 0x4f6: 0xb8, 0x4f7: 0xb8,
+ 0x4f8: 0xb8, 0x4f9: 0xb8, 0x4fa: 0xb8, 0x4fb: 0xb8, 0x4fc: 0xb8, 0x4fd: 0xb8, 0x4fe: 0xb8, 0x4ff: 0xb8,
+ // Block 0x14, offset 0x500
+ 0x500: 0xb8, 0x501: 0xb8, 0x502: 0xb8, 0x503: 0xb8, 0x504: 0xb8, 0x505: 0xb8, 0x506: 0xb8, 0x507: 0xb8,
+ 0x508: 0xb8, 0x509: 0xb8, 0x50a: 0xb8, 0x50b: 0xb8, 0x50c: 0xb8, 0x50d: 0xb8, 0x50e: 0xb8, 0x50f: 0xb8,
+ 0x510: 0xb8, 0x511: 0xb8, 0x512: 0xb8, 0x513: 0xb8, 0x514: 0xb8, 0x515: 0xb8, 0x516: 0xb8, 0x517: 0xb8,
+ 0x518: 0xb8, 0x519: 0xb8, 0x51a: 0xb8, 0x51b: 0xb8, 0x51c: 0xb8, 0x51d: 0xb8, 0x51e: 0xb8, 0x51f: 0xb8,
+ 0x520: 0x9d, 0x521: 0x9d, 0x522: 0x9d, 0x523: 0x9d, 0x524: 0x9d, 0x525: 0x9d, 0x526: 0x9d, 0x527: 0x9d,
+ 0x528: 0x13d, 0x529: 0x146, 0x52a: 0xb8, 0x52b: 0x147, 0x52c: 0x148, 0x52d: 0x149, 0x52e: 0x14a, 0x52f: 0xb8,
+ 0x530: 0xb8, 0x531: 0xb8, 0x532: 0xb8, 0x533: 0xb8, 0x534: 0xb8, 0x535: 0xb8, 0x536: 0xb8, 0x537: 0xb8,
+ 0x538: 0xb8, 0x539: 0xb8, 0x53a: 0xb8, 0x53b: 0xb8, 0x53c: 0x9d, 0x53d: 0x14b, 0x53e: 0x14c, 0x53f: 0x14d,
+ // Block 0x15, offset 0x540
+ 0x540: 0x9d, 0x541: 0x9d, 0x542: 0x9d, 0x543: 0x9d, 0x544: 0x9d, 0x545: 0x9d, 0x546: 0x9d, 0x547: 0x9d,
+ 0x548: 0x9d, 0x549: 0x9d, 0x54a: 0x9d, 0x54b: 0x9d, 0x54c: 0x9d, 0x54d: 0x9d, 0x54e: 0x9d, 0x54f: 0x9d,
+ 0x550: 0x9d, 0x551: 0x9d, 0x552: 0x9d, 0x553: 0x9d, 0x554: 0x9d, 0x555: 0x9d, 0x556: 0x9d, 0x557: 0x9d,
+ 0x558: 0x9d, 0x559: 0x9d, 0x55a: 0x9d, 0x55b: 0x9d, 0x55c: 0x9d, 0x55d: 0x9d, 0x55e: 0x9d, 0x55f: 0x14e,
+ 0x560: 0x9d, 0x561: 0x9d, 0x562: 0x9d, 0x563: 0x9d, 0x564: 0x9d, 0x565: 0x9d, 0x566: 0x9d, 0x567: 0x9d,
+ 0x568: 0x9d, 0x569: 0x9d, 0x56a: 0x9d, 0x56b: 0x14f, 0x56c: 0xb8, 0x56d: 0xb8, 0x56e: 0xb8, 0x56f: 0xb8,
+ 0x570: 0xb8, 0x571: 0xb8, 0x572: 0xb8, 0x573: 0xb8, 0x574: 0xb8, 0x575: 0xb8, 0x576: 0xb8, 0x577: 0xb8,
+ 0x578: 0xb8, 0x579: 0xb8, 0x57a: 0xb8, 0x57b: 0xb8, 0x57c: 0xb8, 0x57d: 0xb8, 0x57e: 0xb8, 0x57f: 0xb8,
+ // Block 0x16, offset 0x580
+ 0x580: 0x150, 0x581: 0xb8, 0x582: 0xb8, 0x583: 0xb8, 0x584: 0xb8, 0x585: 0xb8, 0x586: 0xb8, 0x587: 0xb8,
+ 0x588: 0xb8, 0x589: 0xb8, 0x58a: 0xb8, 0x58b: 0xb8, 0x58c: 0xb8, 0x58d: 0xb8, 0x58e: 0xb8, 0x58f: 0xb8,
+ 0x590: 0xb8, 0x591: 0xb8, 0x592: 0xb8, 0x593: 0xb8, 0x594: 0xb8, 0x595: 0xb8, 0x596: 0xb8, 0x597: 0xb8,
+ 0x598: 0xb8, 0x599: 0xb8, 0x59a: 0xb8, 0x59b: 0xb8, 0x59c: 0xb8, 0x59d: 0xb8, 0x59e: 0xb8, 0x59f: 0xb8,
+ 0x5a0: 0xb8, 0x5a1: 0xb8, 0x5a2: 0xb8, 0x5a3: 0xb8, 0x5a4: 0xb8, 0x5a5: 0xb8, 0x5a6: 0xb8, 0x5a7: 0xb8,
+ 0x5a8: 0xb8, 0x5a9: 0xb8, 0x5aa: 0xb8, 0x5ab: 0xb8, 0x5ac: 0xb8, 0x5ad: 0xb8, 0x5ae: 0xb8, 0x5af: 0xb8,
+ 0x5b0: 0x9d, 0x5b1: 0x151, 0x5b2: 0x152, 0x5b3: 0xb8, 0x5b4: 0xb8, 0x5b5: 0xb8, 0x5b6: 0xb8, 0x5b7: 0xb8,
+ 0x5b8: 0xb8, 0x5b9: 0xb8, 0x5ba: 0xb8, 0x5bb: 0xb8, 0x5bc: 0xb8, 0x5bd: 0xb8, 0x5be: 0xb8, 0x5bf: 0xb8,
+ // Block 0x17, offset 0x5c0
+ 0x5c0: 0x9b, 0x5c1: 0x9b, 0x5c2: 0x9b, 0x5c3: 0x153, 0x5c4: 0x154, 0x5c5: 0x155, 0x5c6: 0x156, 0x5c7: 0x157,
+ 0x5c8: 0x9b, 0x5c9: 0x158, 0x5ca: 0xb8, 0x5cb: 0xb8, 0x5cc: 0x9b, 0x5cd: 0x159, 0x5ce: 0xb8, 0x5cf: 0xb8,
+ 0x5d0: 0x5d, 0x5d1: 0x5e, 0x5d2: 0x5f, 0x5d3: 0x60, 0x5d4: 0x61, 0x5d5: 0x62, 0x5d6: 0x63, 0x5d7: 0x64,
+ 0x5d8: 0x65, 0x5d9: 0x66, 0x5da: 0x67, 0x5db: 0x68, 0x5dc: 0x69, 0x5dd: 0x6a, 0x5de: 0x6b, 0x5df: 0x6c,
+ 0x5e0: 0x9b, 0x5e1: 0x9b, 0x5e2: 0x9b, 0x5e3: 0x9b, 0x5e4: 0x9b, 0x5e5: 0x9b, 0x5e6: 0x9b, 0x5e7: 0x9b,
+ 0x5e8: 0x15a, 0x5e9: 0x15b, 0x5ea: 0x15c, 0x5eb: 0xb8, 0x5ec: 0xb8, 0x5ed: 0xb8, 0x5ee: 0xb8, 0x5ef: 0xb8,
+ 0x5f0: 0xb8, 0x5f1: 0xb8, 0x5f2: 0xb8, 0x5f3: 0xb8, 0x5f4: 0xb8, 0x5f5: 0xb8, 0x5f6: 0xb8, 0x5f7: 0xb8,
+ 0x5f8: 0xb8, 0x5f9: 0xb8, 0x5fa: 0xb8, 0x5fb: 0xb8, 0x5fc: 0xb8, 0x5fd: 0xb8, 0x5fe: 0xb8, 0x5ff: 0xb8,
+ // Block 0x18, offset 0x600
+ 0x600: 0x15d, 0x601: 0xb8, 0x602: 0xb8, 0x603: 0xb8, 0x604: 0xb8, 0x605: 0xb8, 0x606: 0xb8, 0x607: 0xb8,
+ 0x608: 0xb8, 0x609: 0xb8, 0x60a: 0xb8, 0x60b: 0xb8, 0x60c: 0xb8, 0x60d: 0xb8, 0x60e: 0xb8, 0x60f: 0xb8,
+ 0x610: 0xb8, 0x611: 0xb8, 0x612: 0xb8, 0x613: 0xb8, 0x614: 0xb8, 0x615: 0xb8, 0x616: 0xb8, 0x617: 0xb8,
+ 0x618: 0xb8, 0x619: 0xb8, 0x61a: 0xb8, 0x61b: 0xb8, 0x61c: 0xb8, 0x61d: 0xb8, 0x61e: 0xb8, 0x61f: 0xb8,
+ 0x620: 0x9d, 0x621: 0x9d, 0x622: 0x9d, 0x623: 0x15e, 0x624: 0x6d, 0x625: 0x15f, 0x626: 0xb8, 0x627: 0xb8,
+ 0x628: 0xb8, 0x629: 0xb8, 0x62a: 0xb8, 0x62b: 0xb8, 0x62c: 0xb8, 0x62d: 0xb8, 0x62e: 0xb8, 0x62f: 0xb8,
+ 0x630: 0xb8, 0x631: 0xb8, 0x632: 0xb8, 0x633: 0xb8, 0x634: 0xb8, 0x635: 0xb8, 0x636: 0xb8, 0x637: 0xb8,
+ 0x638: 0x6e, 0x639: 0x6f, 0x63a: 0x70, 0x63b: 0x160, 0x63c: 0xb8, 0x63d: 0xb8, 0x63e: 0xb8, 0x63f: 0xb8,
+ // Block 0x19, offset 0x640
+ 0x640: 0x161, 0x641: 0x9b, 0x642: 0x162, 0x643: 0x163, 0x644: 0x71, 0x645: 0x72, 0x646: 0x164, 0x647: 0x165,
+ 0x648: 0x73, 0x649: 0x166, 0x64a: 0xb8, 0x64b: 0xb8, 0x64c: 0x9b, 0x64d: 0x9b, 0x64e: 0x9b, 0x64f: 0x9b,
+ 0x650: 0x9b, 0x651: 0x9b, 0x652: 0x9b, 0x653: 0x9b, 0x654: 0x9b, 0x655: 0x9b, 0x656: 0x9b, 0x657: 0x9b,
+ 0x658: 0x9b, 0x659: 0x9b, 0x65a: 0x9b, 0x65b: 0x167, 0x65c: 0x9b, 0x65d: 0x168, 0x65e: 0x9b, 0x65f: 0x169,
+ 0x660: 0x16a, 0x661: 0x16b, 0x662: 0x16c, 0x663: 0xb8, 0x664: 0x16d, 0x665: 0x16e, 0x666: 0x16f, 0x667: 0x170,
+ 0x668: 0xb8, 0x669: 0xb8, 0x66a: 0xb8, 0x66b: 0xb8, 0x66c: 0xb8, 0x66d: 0xb8, 0x66e: 0xb8, 0x66f: 0xb8,
+ 0x670: 0xb8, 0x671: 0xb8, 0x672: 0xb8, 0x673: 0xb8, 0x674: 0xb8, 0x675: 0xb8, 0x676: 0xb8, 0x677: 0xb8,
+ 0x678: 0xb8, 0x679: 0xb8, 0x67a: 0xb8, 0x67b: 0xb8, 0x67c: 0xb8, 0x67d: 0xb8, 0x67e: 0xb8, 0x67f: 0xb8,
+ // Block 0x1a, offset 0x680
+ 0x680: 0x9d, 0x681: 0x9d, 0x682: 0x9d, 0x683: 0x9d, 0x684: 0x9d, 0x685: 0x9d, 0x686: 0x9d, 0x687: 0x9d,
+ 0x688: 0x9d, 0x689: 0x9d, 0x68a: 0x9d, 0x68b: 0x9d, 0x68c: 0x9d, 0x68d: 0x9d, 0x68e: 0x9d, 0x68f: 0x9d,
+ 0x690: 0x9d, 0x691: 0x9d, 0x692: 0x9d, 0x693: 0x9d, 0x694: 0x9d, 0x695: 0x9d, 0x696: 0x9d, 0x697: 0x9d,
+ 0x698: 0x9d, 0x699: 0x9d, 0x69a: 0x9d, 0x69b: 0x171, 0x69c: 0x9d, 0x69d: 0x9d, 0x69e: 0x9d, 0x69f: 0x9d,
+ 0x6a0: 0x9d, 0x6a1: 0x9d, 0x6a2: 0x9d, 0x6a3: 0x9d, 0x6a4: 0x9d, 0x6a5: 0x9d, 0x6a6: 0x9d, 0x6a7: 0x9d,
+ 0x6a8: 0x9d, 0x6a9: 0x9d, 0x6aa: 0x9d, 0x6ab: 0x9d, 0x6ac: 0x9d, 0x6ad: 0x9d, 0x6ae: 0x9d, 0x6af: 0x9d,
+ 0x6b0: 0x9d, 0x6b1: 0x9d, 0x6b2: 0x9d, 0x6b3: 0x9d, 0x6b4: 0x9d, 0x6b5: 0x9d, 0x6b6: 0x9d, 0x6b7: 0x9d,
+ 0x6b8: 0x9d, 0x6b9: 0x9d, 0x6ba: 0x9d, 0x6bb: 0x9d, 0x6bc: 0x9d, 0x6bd: 0x9d, 0x6be: 0x9d, 0x6bf: 0x9d,
+ // Block 0x1b, offset 0x6c0
+ 0x6c0: 0x9d, 0x6c1: 0x9d, 0x6c2: 0x9d, 0x6c3: 0x9d, 0x6c4: 0x9d, 0x6c5: 0x9d, 0x6c6: 0x9d, 0x6c7: 0x9d,
+ 0x6c8: 0x9d, 0x6c9: 0x9d, 0x6ca: 0x9d, 0x6cb: 0x9d, 0x6cc: 0x9d, 0x6cd: 0x9d, 0x6ce: 0x9d, 0x6cf: 0x9d,
+ 0x6d0: 0x9d, 0x6d1: 0x9d, 0x6d2: 0x9d, 0x6d3: 0x9d, 0x6d4: 0x9d, 0x6d5: 0x9d, 0x6d6: 0x9d, 0x6d7: 0x9d,
+ 0x6d8: 0x9d, 0x6d9: 0x9d, 0x6da: 0x9d, 0x6db: 0x9d, 0x6dc: 0x172, 0x6dd: 0x9d, 0x6de: 0x9d, 0x6df: 0x9d,
+ 0x6e0: 0x173, 0x6e1: 0x9d, 0x6e2: 0x9d, 0x6e3: 0x9d, 0x6e4: 0x9d, 0x6e5: 0x9d, 0x6e6: 0x9d, 0x6e7: 0x9d,
+ 0x6e8: 0x9d, 0x6e9: 0x9d, 0x6ea: 0x9d, 0x6eb: 0x9d, 0x6ec: 0x9d, 0x6ed: 0x9d, 0x6ee: 0x9d, 0x6ef: 0x9d,
+ 0x6f0: 0x9d, 0x6f1: 0x9d, 0x6f2: 0x9d, 0x6f3: 0x9d, 0x6f4: 0x9d, 0x6f5: 0x9d, 0x6f6: 0x9d, 0x6f7: 0x9d,
+ 0x6f8: 0x9d, 0x6f9: 0x9d, 0x6fa: 0x9d, 0x6fb: 0x9d, 0x6fc: 0x9d, 0x6fd: 0x9d, 0x6fe: 0x9d, 0x6ff: 0x9d,
+ // Block 0x1c, offset 0x700
+ 0x700: 0x9d, 0x701: 0x9d, 0x702: 0x9d, 0x703: 0x9d, 0x704: 0x9d, 0x705: 0x9d, 0x706: 0x9d, 0x707: 0x9d,
+ 0x708: 0x9d, 0x709: 0x9d, 0x70a: 0x9d, 0x70b: 0x9d, 0x70c: 0x9d, 0x70d: 0x9d, 0x70e: 0x9d, 0x70f: 0x9d,
+ 0x710: 0x9d, 0x711: 0x9d, 0x712: 0x9d, 0x713: 0x9d, 0x714: 0x9d, 0x715: 0x9d, 0x716: 0x9d, 0x717: 0x9d,
+ 0x718: 0x9d, 0x719: 0x9d, 0x71a: 0x9d, 0x71b: 0x9d, 0x71c: 0x9d, 0x71d: 0x9d, 0x71e: 0x9d, 0x71f: 0x9d,
+ 0x720: 0x9d, 0x721: 0x9d, 0x722: 0x9d, 0x723: 0x9d, 0x724: 0x9d, 0x725: 0x9d, 0x726: 0x9d, 0x727: 0x9d,
+ 0x728: 0x9d, 0x729: 0x9d, 0x72a: 0x9d, 0x72b: 0x9d, 0x72c: 0x9d, 0x72d: 0x9d, 0x72e: 0x9d, 0x72f: 0x9d,
+ 0x730: 0x9d, 0x731: 0x9d, 0x732: 0x9d, 0x733: 0x9d, 0x734: 0x9d, 0x735: 0x9d, 0x736: 0x9d, 0x737: 0x9d,
+ 0x738: 0x9d, 0x739: 0x9d, 0x73a: 0x174, 0x73b: 0xb8, 0x73c: 0xb8, 0x73d: 0xb8, 0x73e: 0xb8, 0x73f: 0xb8,
+ // Block 0x1d, offset 0x740
+ 0x740: 0xb8, 0x741: 0xb8, 0x742: 0xb8, 0x743: 0xb8, 0x744: 0xb8, 0x745: 0xb8, 0x746: 0xb8, 0x747: 0xb8,
+ 0x748: 0xb8, 0x749: 0xb8, 0x74a: 0xb8, 0x74b: 0xb8, 0x74c: 0xb8, 0x74d: 0xb8, 0x74e: 0xb8, 0x74f: 0xb8,
+ 0x750: 0xb8, 0x751: 0xb8, 0x752: 0xb8, 0x753: 0xb8, 0x754: 0xb8, 0x755: 0xb8, 0x756: 0xb8, 0x757: 0xb8,
+ 0x758: 0xb8, 0x759: 0xb8, 0x75a: 0xb8, 0x75b: 0xb8, 0x75c: 0xb8, 0x75d: 0xb8, 0x75e: 0xb8, 0x75f: 0xb8,
+ 0x760: 0x74, 0x761: 0x75, 0x762: 0x76, 0x763: 0x175, 0x764: 0x77, 0x765: 0x78, 0x766: 0x176, 0x767: 0x79,
+ 0x768: 0x7a, 0x769: 0xb8, 0x76a: 0xb8, 0x76b: 0xb8, 0x76c: 0xb8, 0x76d: 0xb8, 0x76e: 0xb8, 0x76f: 0xb8,
+ 0x770: 0xb8, 0x771: 0xb8, 0x772: 0xb8, 0x773: 0xb8, 0x774: 0xb8, 0x775: 0xb8, 0x776: 0xb8, 0x777: 0xb8,
+ 0x778: 0xb8, 0x779: 0xb8, 0x77a: 0xb8, 0x77b: 0xb8, 0x77c: 0xb8, 0x77d: 0xb8, 0x77e: 0xb8, 0x77f: 0xb8,
+ // Block 0x1e, offset 0x780
+ 0x790: 0x0d, 0x791: 0x0e, 0x792: 0x0f, 0x793: 0x10, 0x794: 0x11, 0x795: 0x0b, 0x796: 0x12, 0x797: 0x07,
+ 0x798: 0x13, 0x799: 0x0b, 0x79a: 0x0b, 0x79b: 0x14, 0x79c: 0x0b, 0x79d: 0x15, 0x79e: 0x16, 0x79f: 0x17,
+ 0x7a0: 0x07, 0x7a1: 0x07, 0x7a2: 0x07, 0x7a3: 0x07, 0x7a4: 0x07, 0x7a5: 0x07, 0x7a6: 0x07, 0x7a7: 0x07,
+ 0x7a8: 0x07, 0x7a9: 0x07, 0x7aa: 0x18, 0x7ab: 0x19, 0x7ac: 0x1a, 0x7ad: 0x0b, 0x7ae: 0x0b, 0x7af: 0x1b,
+ 0x7b0: 0x0b, 0x7b1: 0x0b, 0x7b2: 0x0b, 0x7b3: 0x0b, 0x7b4: 0x0b, 0x7b5: 0x0b, 0x7b6: 0x0b, 0x7b7: 0x0b,
+ 0x7b8: 0x0b, 0x7b9: 0x0b, 0x7ba: 0x0b, 0x7bb: 0x0b, 0x7bc: 0x0b, 0x7bd: 0x0b, 0x7be: 0x0b, 0x7bf: 0x0b,
+ // Block 0x1f, offset 0x7c0
+ 0x7c0: 0x0b, 0x7c1: 0x0b, 0x7c2: 0x0b, 0x7c3: 0x0b, 0x7c4: 0x0b, 0x7c5: 0x0b, 0x7c6: 0x0b, 0x7c7: 0x0b,
+ 0x7c8: 0x0b, 0x7c9: 0x0b, 0x7ca: 0x0b, 0x7cb: 0x0b, 0x7cc: 0x0b, 0x7cd: 0x0b, 0x7ce: 0x0b, 0x7cf: 0x0b,
+ 0x7d0: 0x0b, 0x7d1: 0x0b, 0x7d2: 0x0b, 0x7d3: 0x0b, 0x7d4: 0x0b, 0x7d5: 0x0b, 0x7d6: 0x0b, 0x7d7: 0x0b,
+ 0x7d8: 0x0b, 0x7d9: 0x0b, 0x7da: 0x0b, 0x7db: 0x0b, 0x7dc: 0x0b, 0x7dd: 0x0b, 0x7de: 0x0b, 0x7df: 0x0b,
+ 0x7e0: 0x0b, 0x7e1: 0x0b, 0x7e2: 0x0b, 0x7e3: 0x0b, 0x7e4: 0x0b, 0x7e5: 0x0b, 0x7e6: 0x0b, 0x7e7: 0x0b,
+ 0x7e8: 0x0b, 0x7e9: 0x0b, 0x7ea: 0x0b, 0x7eb: 0x0b, 0x7ec: 0x0b, 0x7ed: 0x0b, 0x7ee: 0x0b, 0x7ef: 0x0b,
+ 0x7f0: 0x0b, 0x7f1: 0x0b, 0x7f2: 0x0b, 0x7f3: 0x0b, 0x7f4: 0x0b, 0x7f5: 0x0b, 0x7f6: 0x0b, 0x7f7: 0x0b,
+ 0x7f8: 0x0b, 0x7f9: 0x0b, 0x7fa: 0x0b, 0x7fb: 0x0b, 0x7fc: 0x0b, 0x7fd: 0x0b, 0x7fe: 0x0b, 0x7ff: 0x0b,
+ // Block 0x20, offset 0x800
+ 0x800: 0x177, 0x801: 0x178, 0x802: 0xb8, 0x803: 0xb8, 0x804: 0x179, 0x805: 0x179, 0x806: 0x179, 0x807: 0x17a,
+ 0x808: 0xb8, 0x809: 0xb8, 0x80a: 0xb8, 0x80b: 0xb8, 0x80c: 0xb8, 0x80d: 0xb8, 0x80e: 0xb8, 0x80f: 0xb8,
+ 0x810: 0xb8, 0x811: 0xb8, 0x812: 0xb8, 0x813: 0xb8, 0x814: 0xb8, 0x815: 0xb8, 0x816: 0xb8, 0x817: 0xb8,
+ 0x818: 0xb8, 0x819: 0xb8, 0x81a: 0xb8, 0x81b: 0xb8, 0x81c: 0xb8, 0x81d: 0xb8, 0x81e: 0xb8, 0x81f: 0xb8,
+ 0x820: 0xb8, 0x821: 0xb8, 0x822: 0xb8, 0x823: 0xb8, 0x824: 0xb8, 0x825: 0xb8, 0x826: 0xb8, 0x827: 0xb8,
+ 0x828: 0xb8, 0x829: 0xb8, 0x82a: 0xb8, 0x82b: 0xb8, 0x82c: 0xb8, 0x82d: 0xb8, 0x82e: 0xb8, 0x82f: 0xb8,
+ 0x830: 0xb8, 0x831: 0xb8, 0x832: 0xb8, 0x833: 0xb8, 0x834: 0xb8, 0x835: 0xb8, 0x836: 0xb8, 0x837: 0xb8,
+ 0x838: 0xb8, 0x839: 0xb8, 0x83a: 0xb8, 0x83b: 0xb8, 0x83c: 0xb8, 0x83d: 0xb8, 0x83e: 0xb8, 0x83f: 0xb8,
+ // Block 0x21, offset 0x840
+ 0x840: 0x0b, 0x841: 0x0b, 0x842: 0x0b, 0x843: 0x0b, 0x844: 0x0b, 0x845: 0x0b, 0x846: 0x0b, 0x847: 0x0b,
+ 0x848: 0x0b, 0x849: 0x0b, 0x84a: 0x0b, 0x84b: 0x0b, 0x84c: 0x0b, 0x84d: 0x0b, 0x84e: 0x0b, 0x84f: 0x0b,
+ 0x850: 0x0b, 0x851: 0x0b, 0x852: 0x0b, 0x853: 0x0b, 0x854: 0x0b, 0x855: 0x0b, 0x856: 0x0b, 0x857: 0x0b,
+ 0x858: 0x0b, 0x859: 0x0b, 0x85a: 0x0b, 0x85b: 0x0b, 0x85c: 0x0b, 0x85d: 0x0b, 0x85e: 0x0b, 0x85f: 0x0b,
+ 0x860: 0x1e, 0x861: 0x0b, 0x862: 0x0b, 0x863: 0x0b, 0x864: 0x0b, 0x865: 0x0b, 0x866: 0x0b, 0x867: 0x0b,
+ 0x868: 0x0b, 0x869: 0x0b, 0x86a: 0x0b, 0x86b: 0x0b, 0x86c: 0x0b, 0x86d: 0x0b, 0x86e: 0x0b, 0x86f: 0x0b,
+ 0x870: 0x0b, 0x871: 0x0b, 0x872: 0x0b, 0x873: 0x0b, 0x874: 0x0b, 0x875: 0x0b, 0x876: 0x0b, 0x877: 0x0b,
+ 0x878: 0x0b, 0x879: 0x0b, 0x87a: 0x0b, 0x87b: 0x0b, 0x87c: 0x0b, 0x87d: 0x0b, 0x87e: 0x0b, 0x87f: 0x0b,
+ // Block 0x22, offset 0x880
+ 0x880: 0x0b, 0x881: 0x0b, 0x882: 0x0b, 0x883: 0x0b, 0x884: 0x0b, 0x885: 0x0b, 0x886: 0x0b, 0x887: 0x0b,
+ 0x888: 0x0b, 0x889: 0x0b, 0x88a: 0x0b, 0x88b: 0x0b, 0x88c: 0x0b, 0x88d: 0x0b, 0x88e: 0x0b, 0x88f: 0x0b,
+}
+
+// idnaSparseOffset: 256 entries, 512 bytes
+var idnaSparseOffset = []uint16{0x0, 0x8, 0x19, 0x25, 0x27, 0x2c, 0x34, 0x3f, 0x4b, 0x5c, 0x60, 0x6f, 0x74, 0x7b, 0x87, 0x95, 0xa3, 0xa8, 0xb1, 0xc1, 0xcf, 0xdc, 0xe8, 0xf9, 0x103, 0x10a, 0x117, 0x128, 0x12f, 0x13a, 0x149, 0x157, 0x161, 0x163, 0x167, 0x169, 0x175, 0x180, 0x188, 0x18e, 0x194, 0x199, 0x19e, 0x1a1, 0x1a5, 0x1ab, 0x1b0, 0x1bc, 0x1c6, 0x1cc, 0x1dd, 0x1e7, 0x1ea, 0x1f2, 0x1f5, 0x202, 0x20a, 0x20e, 0x215, 0x21d, 0x22d, 0x239, 0x23b, 0x245, 0x251, 0x25d, 0x269, 0x271, 0x276, 0x280, 0x291, 0x295, 0x2a0, 0x2a4, 0x2ad, 0x2b5, 0x2bb, 0x2c0, 0x2c3, 0x2c6, 0x2ca, 0x2d0, 0x2d4, 0x2d8, 0x2de, 0x2e5, 0x2eb, 0x2f3, 0x2fa, 0x305, 0x30f, 0x313, 0x316, 0x31c, 0x320, 0x322, 0x325, 0x327, 0x32a, 0x334, 0x337, 0x346, 0x34a, 0x34f, 0x352, 0x356, 0x35b, 0x360, 0x366, 0x36c, 0x37b, 0x381, 0x385, 0x394, 0x399, 0x3a1, 0x3ab, 0x3b6, 0x3be, 0x3cf, 0x3d8, 0x3e8, 0x3f5, 0x3ff, 0x404, 0x411, 0x415, 0x41a, 0x41c, 0x420, 0x422, 0x426, 0x42f, 0x435, 0x439, 0x449, 0x453, 0x458, 0x45b, 0x461, 0x468, 0x46d, 0x471, 0x477, 0x47c, 0x485, 0x48a, 0x490, 0x497, 0x49e, 0x4a5, 0x4a9, 0x4ae, 0x4b1, 0x4b6, 0x4c2, 0x4c8, 0x4cd, 0x4d4, 0x4dc, 0x4e1, 0x4e5, 0x4f5, 0x4fc, 0x500, 0x504, 0x50b, 0x50e, 0x511, 0x515, 0x519, 0x51f, 0x528, 0x534, 0x53b, 0x544, 0x54c, 0x553, 0x561, 0x56e, 0x57b, 0x584, 0x588, 0x596, 0x59e, 0x5a9, 0x5b2, 0x5b8, 0x5c0, 0x5c9, 0x5d3, 0x5d6, 0x5e2, 0x5e5, 0x5ea, 0x5ed, 0x5f7, 0x600, 0x60c, 0x60f, 0x614, 0x617, 0x61a, 0x61d, 0x624, 0x62b, 0x62f, 0x63a, 0x63d, 0x643, 0x648, 0x64c, 0x64f, 0x652, 0x655, 0x65a, 0x664, 0x667, 0x66b, 0x67a, 0x686, 0x68a, 0x68f, 0x694, 0x698, 0x69d, 0x6a6, 0x6b1, 0x6b7, 0x6bf, 0x6c3, 0x6c7, 0x6cd, 0x6d3, 0x6d8, 0x6db, 0x6e9, 0x6f0, 0x6f3, 0x6f6, 0x6fa, 0x700, 0x705, 0x70f, 0x714, 0x717, 0x71a, 0x71d, 0x720, 0x724, 0x727, 0x737, 0x748, 0x74d, 0x74f, 0x751}
+
+// idnaSparseValues: 1876 entries, 7504 bytes
+var idnaSparseValues = [1876]valueRange{
+ // Block 0x0, offset 0x0
+ {value: 0x0000, lo: 0x07},
+ {value: 0xe105, lo: 0x80, hi: 0x96},
+ {value: 0x0018, lo: 0x97, hi: 0x97},
+ {value: 0xe105, lo: 0x98, hi: 0x9e},
+ {value: 0x001f, lo: 0x9f, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xb6},
+ {value: 0x0018, lo: 0xb7, hi: 0xb7},
+ {value: 0x0008, lo: 0xb8, hi: 0xbf},
+ // Block 0x1, offset 0x8
+ {value: 0x0000, lo: 0x10},
+ {value: 0x0008, lo: 0x80, hi: 0x80},
+ {value: 0xe01d, lo: 0x81, hi: 0x81},
+ {value: 0x0008, lo: 0x82, hi: 0x82},
+ {value: 0x0335, lo: 0x83, hi: 0x83},
+ {value: 0x034d, lo: 0x84, hi: 0x84},
+ {value: 0x0365, lo: 0x85, hi: 0x85},
+ {value: 0xe00d, lo: 0x86, hi: 0x86},
+ {value: 0x0008, lo: 0x87, hi: 0x87},
+ {value: 0xe00d, lo: 0x88, hi: 0x88},
+ {value: 0x0008, lo: 0x89, hi: 0x89},
+ {value: 0xe00d, lo: 0x8a, hi: 0x8a},
+ {value: 0x0008, lo: 0x8b, hi: 0x8b},
+ {value: 0xe00d, lo: 0x8c, hi: 0x8c},
+ {value: 0x0008, lo: 0x8d, hi: 0x8d},
+ {value: 0xe00d, lo: 0x8e, hi: 0x8e},
+ {value: 0x0008, lo: 0x8f, hi: 0xbf},
+ // Block 0x2, offset 0x19
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0xaf},
+ {value: 0x0249, lo: 0xb0, hi: 0xb0},
+ {value: 0x037d, lo: 0xb1, hi: 0xb1},
+ {value: 0x0259, lo: 0xb2, hi: 0xb2},
+ {value: 0x0269, lo: 0xb3, hi: 0xb3},
+ {value: 0x034d, lo: 0xb4, hi: 0xb4},
+ {value: 0x0395, lo: 0xb5, hi: 0xb5},
+ {value: 0xe1bd, lo: 0xb6, hi: 0xb6},
+ {value: 0x0279, lo: 0xb7, hi: 0xb7},
+ {value: 0x0289, lo: 0xb8, hi: 0xb8},
+ {value: 0x0008, lo: 0xb9, hi: 0xbf},
+ // Block 0x3, offset 0x25
+ {value: 0x0000, lo: 0x01},
+ {value: 0x1308, lo: 0x80, hi: 0xbf},
+ // Block 0x4, offset 0x27
+ {value: 0x0000, lo: 0x04},
+ {value: 0x03f5, lo: 0x80, hi: 0x8f},
+ {value: 0xe105, lo: 0x90, hi: 0x9f},
+ {value: 0x049d, lo: 0xa0, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x5, offset 0x2c
+ {value: 0x0000, lo: 0x07},
+ {value: 0xe185, lo: 0x80, hi: 0x8f},
+ {value: 0x0545, lo: 0x90, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x98},
+ {value: 0x0008, lo: 0x99, hi: 0x99},
+ {value: 0x0018, lo: 0x9a, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xa0},
+ {value: 0x0008, lo: 0xa1, hi: 0xbf},
+ // Block 0x6, offset 0x34
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x0401, lo: 0x87, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x88},
+ {value: 0x0018, lo: 0x89, hi: 0x8a},
+ {value: 0x0040, lo: 0x8b, hi: 0x8c},
+ {value: 0x0018, lo: 0x8d, hi: 0x8f},
+ {value: 0x0040, lo: 0x90, hi: 0x90},
+ {value: 0x1308, lo: 0x91, hi: 0xbd},
+ {value: 0x0018, lo: 0xbe, hi: 0xbe},
+ {value: 0x1308, lo: 0xbf, hi: 0xbf},
+ // Block 0x7, offset 0x3f
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0018, lo: 0x80, hi: 0x80},
+ {value: 0x1308, lo: 0x81, hi: 0x82},
+ {value: 0x0018, lo: 0x83, hi: 0x83},
+ {value: 0x1308, lo: 0x84, hi: 0x85},
+ {value: 0x0018, lo: 0x86, hi: 0x86},
+ {value: 0x1308, lo: 0x87, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xaa},
+ {value: 0x0040, lo: 0xab, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xbf},
+ // Block 0x8, offset 0x4b
+ {value: 0x0000, lo: 0x10},
+ {value: 0x0018, lo: 0x80, hi: 0x80},
+ {value: 0x0208, lo: 0x81, hi: 0x87},
+ {value: 0x0408, lo: 0x88, hi: 0x88},
+ {value: 0x0208, lo: 0x89, hi: 0x8a},
+ {value: 0x1308, lo: 0x8b, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa9},
+ {value: 0x0018, lo: 0xaa, hi: 0xad},
+ {value: 0x0208, lo: 0xae, hi: 0xaf},
+ {value: 0x1308, lo: 0xb0, hi: 0xb0},
+ {value: 0x0408, lo: 0xb1, hi: 0xb3},
+ {value: 0x0008, lo: 0xb4, hi: 0xb4},
+ {value: 0x0429, lo: 0xb5, hi: 0xb5},
+ {value: 0x0451, lo: 0xb6, hi: 0xb6},
+ {value: 0x0479, lo: 0xb7, hi: 0xb7},
+ {value: 0x04a1, lo: 0xb8, hi: 0xb8},
+ {value: 0x0208, lo: 0xb9, hi: 0xbf},
+ // Block 0x9, offset 0x5c
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0208, lo: 0x80, hi: 0x87},
+ {value: 0x0408, lo: 0x88, hi: 0x99},
+ {value: 0x0208, lo: 0x9a, hi: 0xbf},
+ // Block 0xa, offset 0x60
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x1308, lo: 0x80, hi: 0x8a},
+ {value: 0x0040, lo: 0x8b, hi: 0x8c},
+ {value: 0x0408, lo: 0x8d, hi: 0x8d},
+ {value: 0x0208, lo: 0x8e, hi: 0x98},
+ {value: 0x0408, lo: 0x99, hi: 0x9b},
+ {value: 0x0208, lo: 0x9c, hi: 0xaa},
+ {value: 0x0408, lo: 0xab, hi: 0xac},
+ {value: 0x0208, lo: 0xad, hi: 0xb0},
+ {value: 0x0408, lo: 0xb1, hi: 0xb1},
+ {value: 0x0208, lo: 0xb2, hi: 0xb2},
+ {value: 0x0408, lo: 0xb3, hi: 0xb4},
+ {value: 0x0208, lo: 0xb5, hi: 0xb7},
+ {value: 0x0408, lo: 0xb8, hi: 0xb9},
+ {value: 0x0208, lo: 0xba, hi: 0xbf},
+ // Block 0xb, offset 0x6f
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0xa5},
+ {value: 0x1308, lo: 0xa6, hi: 0xb0},
+ {value: 0x0008, lo: 0xb1, hi: 0xb1},
+ {value: 0x0040, lo: 0xb2, hi: 0xbf},
+ // Block 0xc, offset 0x74
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0008, lo: 0x80, hi: 0x89},
+ {value: 0x0208, lo: 0x8a, hi: 0xaa},
+ {value: 0x1308, lo: 0xab, hi: 0xb3},
+ {value: 0x0008, lo: 0xb4, hi: 0xb5},
+ {value: 0x0018, lo: 0xb6, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbf},
+ // Block 0xd, offset 0x7b
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0x95},
+ {value: 0x1308, lo: 0x96, hi: 0x99},
+ {value: 0x0008, lo: 0x9a, hi: 0x9a},
+ {value: 0x1308, lo: 0x9b, hi: 0xa3},
+ {value: 0x0008, lo: 0xa4, hi: 0xa4},
+ {value: 0x1308, lo: 0xa5, hi: 0xa7},
+ {value: 0x0008, lo: 0xa8, hi: 0xa8},
+ {value: 0x1308, lo: 0xa9, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0xe, offset 0x87
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x0408, lo: 0x80, hi: 0x80},
+ {value: 0x0208, lo: 0x81, hi: 0x85},
+ {value: 0x0408, lo: 0x86, hi: 0x87},
+ {value: 0x0208, lo: 0x88, hi: 0x88},
+ {value: 0x0408, lo: 0x89, hi: 0x89},
+ {value: 0x0208, lo: 0x8a, hi: 0x93},
+ {value: 0x0408, lo: 0x94, hi: 0x94},
+ {value: 0x0208, lo: 0x95, hi: 0x95},
+ {value: 0x0008, lo: 0x96, hi: 0x98},
+ {value: 0x1308, lo: 0x99, hi: 0x9b},
+ {value: 0x0040, lo: 0x9c, hi: 0x9d},
+ {value: 0x0018, lo: 0x9e, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0xbf},
+ // Block 0xf, offset 0x95
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x0040, lo: 0x80, hi: 0x9f},
+ {value: 0x0208, lo: 0xa0, hi: 0xa9},
+ {value: 0x0408, lo: 0xaa, hi: 0xac},
+ {value: 0x0008, lo: 0xad, hi: 0xad},
+ {value: 0x0408, lo: 0xae, hi: 0xae},
+ {value: 0x0208, lo: 0xaf, hi: 0xb0},
+ {value: 0x0408, lo: 0xb1, hi: 0xb2},
+ {value: 0x0208, lo: 0xb3, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xb5},
+ {value: 0x0208, lo: 0xb6, hi: 0xb8},
+ {value: 0x0408, lo: 0xb9, hi: 0xb9},
+ {value: 0x0208, lo: 0xba, hi: 0xbd},
+ {value: 0x0040, lo: 0xbe, hi: 0xbf},
+ // Block 0x10, offset 0xa3
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0040, lo: 0x80, hi: 0x93},
+ {value: 0x1308, lo: 0x94, hi: 0xa1},
+ {value: 0x0040, lo: 0xa2, hi: 0xa2},
+ {value: 0x1308, lo: 0xa3, hi: 0xbf},
+ // Block 0x11, offset 0xa8
+ {value: 0x0000, lo: 0x08},
+ {value: 0x1308, lo: 0x80, hi: 0x82},
+ {value: 0x1008, lo: 0x83, hi: 0x83},
+ {value: 0x0008, lo: 0x84, hi: 0xb9},
+ {value: 0x1308, lo: 0xba, hi: 0xba},
+ {value: 0x1008, lo: 0xbb, hi: 0xbb},
+ {value: 0x1308, lo: 0xbc, hi: 0xbc},
+ {value: 0x0008, lo: 0xbd, hi: 0xbd},
+ {value: 0x1008, lo: 0xbe, hi: 0xbf},
+ // Block 0x12, offset 0xb1
+ {value: 0x0000, lo: 0x0f},
+ {value: 0x1308, lo: 0x80, hi: 0x80},
+ {value: 0x1008, lo: 0x81, hi: 0x82},
+ {value: 0x0040, lo: 0x83, hi: 0x85},
+ {value: 0x1008, lo: 0x86, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x89},
+ {value: 0x1008, lo: 0x8a, hi: 0x8c},
+ {value: 0x1b08, lo: 0x8d, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x90},
+ {value: 0x0040, lo: 0x91, hi: 0x96},
+ {value: 0x1008, lo: 0x97, hi: 0x97},
+ {value: 0x0040, lo: 0x98, hi: 0xa5},
+ {value: 0x0008, lo: 0xa6, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbf},
+ // Block 0x13, offset 0xc1
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x1308, lo: 0x80, hi: 0x80},
+ {value: 0x1008, lo: 0x81, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0x84},
+ {value: 0x0008, lo: 0x85, hi: 0x8c},
+ {value: 0x0040, lo: 0x8d, hi: 0x8d},
+ {value: 0x0008, lo: 0x8e, hi: 0x90},
+ {value: 0x0040, lo: 0x91, hi: 0x91},
+ {value: 0x0008, lo: 0x92, hi: 0xa8},
+ {value: 0x0040, lo: 0xa9, hi: 0xa9},
+ {value: 0x0008, lo: 0xaa, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbc},
+ {value: 0x0008, lo: 0xbd, hi: 0xbd},
+ {value: 0x1308, lo: 0xbe, hi: 0xbf},
+ // Block 0x14, offset 0xcf
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0040, lo: 0x80, hi: 0x80},
+ {value: 0x1308, lo: 0x81, hi: 0x81},
+ {value: 0x1008, lo: 0x82, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0x84},
+ {value: 0x0008, lo: 0x85, hi: 0x8c},
+ {value: 0x0040, lo: 0x8d, hi: 0x8d},
+ {value: 0x0008, lo: 0x8e, hi: 0x90},
+ {value: 0x0040, lo: 0x91, hi: 0x91},
+ {value: 0x0008, lo: 0x92, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbc},
+ {value: 0x0008, lo: 0xbd, hi: 0xbd},
+ {value: 0x1008, lo: 0xbe, hi: 0xbf},
+ // Block 0x15, offset 0xdc
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0040, lo: 0x80, hi: 0x81},
+ {value: 0x1008, lo: 0x82, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0x84},
+ {value: 0x0008, lo: 0x85, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x99},
+ {value: 0x0008, lo: 0x9a, hi: 0xb1},
+ {value: 0x0040, lo: 0xb2, hi: 0xb2},
+ {value: 0x0008, lo: 0xb3, hi: 0xbb},
+ {value: 0x0040, lo: 0xbc, hi: 0xbc},
+ {value: 0x0008, lo: 0xbd, hi: 0xbd},
+ {value: 0x0040, lo: 0xbe, hi: 0xbf},
+ // Block 0x16, offset 0xe8
+ {value: 0x0000, lo: 0x10},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x89},
+ {value: 0x1b08, lo: 0x8a, hi: 0x8a},
+ {value: 0x0040, lo: 0x8b, hi: 0x8e},
+ {value: 0x1008, lo: 0x8f, hi: 0x91},
+ {value: 0x1308, lo: 0x92, hi: 0x94},
+ {value: 0x0040, lo: 0x95, hi: 0x95},
+ {value: 0x1308, lo: 0x96, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x97},
+ {value: 0x1008, lo: 0x98, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xa5},
+ {value: 0x0008, lo: 0xa6, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xb1},
+ {value: 0x1008, lo: 0xb2, hi: 0xb3},
+ {value: 0x0018, lo: 0xb4, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xbf},
+ // Block 0x17, offset 0xf9
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0040, lo: 0x80, hi: 0x80},
+ {value: 0x0008, lo: 0x81, hi: 0xb0},
+ {value: 0x1308, lo: 0xb1, hi: 0xb1},
+ {value: 0x0008, lo: 0xb2, hi: 0xb2},
+ {value: 0x08f1, lo: 0xb3, hi: 0xb3},
+ {value: 0x1308, lo: 0xb4, hi: 0xb9},
+ {value: 0x1b08, lo: 0xba, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbe},
+ {value: 0x0018, lo: 0xbf, hi: 0xbf},
+ // Block 0x18, offset 0x103
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x1308, lo: 0x87, hi: 0x8e},
+ {value: 0x0018, lo: 0x8f, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0018, lo: 0x9a, hi: 0x9b},
+ {value: 0x0040, lo: 0x9c, hi: 0xbf},
+ // Block 0x19, offset 0x10a
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0008, lo: 0x80, hi: 0x84},
+ {value: 0x0040, lo: 0x85, hi: 0x85},
+ {value: 0x0008, lo: 0x86, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x87},
+ {value: 0x1308, lo: 0x88, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9b},
+ {value: 0x0961, lo: 0x9c, hi: 0x9c},
+ {value: 0x0999, lo: 0x9d, hi: 0x9d},
+ {value: 0x0008, lo: 0x9e, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xbf},
+ // Block 0x1a, offset 0x117
+ {value: 0x0000, lo: 0x10},
+ {value: 0x0008, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0x8a},
+ {value: 0x0008, lo: 0x8b, hi: 0x8b},
+ {value: 0xe03d, lo: 0x8c, hi: 0x8c},
+ {value: 0x0018, lo: 0x8d, hi: 0x97},
+ {value: 0x1308, lo: 0x98, hi: 0x99},
+ {value: 0x0018, lo: 0x9a, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa9},
+ {value: 0x0018, lo: 0xaa, hi: 0xb4},
+ {value: 0x1308, lo: 0xb5, hi: 0xb5},
+ {value: 0x0018, lo: 0xb6, hi: 0xb6},
+ {value: 0x1308, lo: 0xb7, hi: 0xb7},
+ {value: 0x0018, lo: 0xb8, hi: 0xb8},
+ {value: 0x1308, lo: 0xb9, hi: 0xb9},
+ {value: 0x0018, lo: 0xba, hi: 0xbd},
+ {value: 0x1008, lo: 0xbe, hi: 0xbf},
+ // Block 0x1b, offset 0x128
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0018, lo: 0x80, hi: 0x85},
+ {value: 0x1308, lo: 0x86, hi: 0x86},
+ {value: 0x0018, lo: 0x87, hi: 0x8c},
+ {value: 0x0040, lo: 0x8d, hi: 0x8d},
+ {value: 0x0018, lo: 0x8e, hi: 0x9a},
+ {value: 0x0040, lo: 0x9b, hi: 0xbf},
+ // Block 0x1c, offset 0x12f
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x0008, lo: 0x80, hi: 0xaa},
+ {value: 0x1008, lo: 0xab, hi: 0xac},
+ {value: 0x1308, lo: 0xad, hi: 0xb0},
+ {value: 0x1008, lo: 0xb1, hi: 0xb1},
+ {value: 0x1308, lo: 0xb2, hi: 0xb7},
+ {value: 0x1008, lo: 0xb8, hi: 0xb8},
+ {value: 0x1b08, lo: 0xb9, hi: 0xba},
+ {value: 0x1008, lo: 0xbb, hi: 0xbc},
+ {value: 0x1308, lo: 0xbd, hi: 0xbe},
+ {value: 0x0008, lo: 0xbf, hi: 0xbf},
+ // Block 0x1d, offset 0x13a
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x0008, lo: 0x80, hi: 0x89},
+ {value: 0x0018, lo: 0x8a, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x95},
+ {value: 0x1008, lo: 0x96, hi: 0x97},
+ {value: 0x1308, lo: 0x98, hi: 0x99},
+ {value: 0x0008, lo: 0x9a, hi: 0x9d},
+ {value: 0x1308, lo: 0x9e, hi: 0xa0},
+ {value: 0x0008, lo: 0xa1, hi: 0xa1},
+ {value: 0x1008, lo: 0xa2, hi: 0xa4},
+ {value: 0x0008, lo: 0xa5, hi: 0xa6},
+ {value: 0x1008, lo: 0xa7, hi: 0xad},
+ {value: 0x0008, lo: 0xae, hi: 0xb0},
+ {value: 0x1308, lo: 0xb1, hi: 0xb4},
+ {value: 0x0008, lo: 0xb5, hi: 0xbf},
+ // Block 0x1e, offset 0x149
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x0008, lo: 0x80, hi: 0x81},
+ {value: 0x1308, lo: 0x82, hi: 0x82},
+ {value: 0x1008, lo: 0x83, hi: 0x84},
+ {value: 0x1308, lo: 0x85, hi: 0x86},
+ {value: 0x1008, lo: 0x87, hi: 0x8c},
+ {value: 0x1308, lo: 0x8d, hi: 0x8d},
+ {value: 0x0008, lo: 0x8e, hi: 0x8e},
+ {value: 0x1008, lo: 0x8f, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x1008, lo: 0x9a, hi: 0x9c},
+ {value: 0x1308, lo: 0x9d, hi: 0x9d},
+ {value: 0x0018, lo: 0x9e, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xbf},
+ // Block 0x1f, offset 0x157
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0040, lo: 0x80, hi: 0x86},
+ {value: 0x055d, lo: 0x87, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8c},
+ {value: 0x055d, lo: 0x8d, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xba},
+ {value: 0x0018, lo: 0xbb, hi: 0xbb},
+ {value: 0xe105, lo: 0xbc, hi: 0xbc},
+ {value: 0x0008, lo: 0xbd, hi: 0xbf},
+ // Block 0x20, offset 0x161
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0018, lo: 0x80, hi: 0xbf},
+ // Block 0x21, offset 0x163
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0xa0},
+ {value: 0x0018, lo: 0xa1, hi: 0xbf},
+ // Block 0x22, offset 0x167
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0008, lo: 0x80, hi: 0xbf},
+ // Block 0x23, offset 0x169
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x89},
+ {value: 0x0008, lo: 0x8a, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x97},
+ {value: 0x0008, lo: 0x98, hi: 0x98},
+ {value: 0x0040, lo: 0x99, hi: 0x99},
+ {value: 0x0008, lo: 0x9a, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbf},
+ // Block 0x24, offset 0x175
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x0008, lo: 0x80, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x89},
+ {value: 0x0008, lo: 0x8a, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xb0},
+ {value: 0x0040, lo: 0xb1, hi: 0xb1},
+ {value: 0x0008, lo: 0xb2, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xb7},
+ {value: 0x0008, lo: 0xb8, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0x25, offset 0x180
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0x80},
+ {value: 0x0040, lo: 0x81, hi: 0x81},
+ {value: 0x0008, lo: 0x82, hi: 0x85},
+ {value: 0x0040, lo: 0x86, hi: 0x87},
+ {value: 0x0008, lo: 0x88, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x97},
+ {value: 0x0008, lo: 0x98, hi: 0xbf},
+ // Block 0x26, offset 0x188
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0x90},
+ {value: 0x0040, lo: 0x91, hi: 0x91},
+ {value: 0x0008, lo: 0x92, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0x97},
+ {value: 0x0008, lo: 0x98, hi: 0xbf},
+ // Block 0x27, offset 0x18e
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0x9a},
+ {value: 0x0040, lo: 0x9b, hi: 0x9c},
+ {value: 0x1308, lo: 0x9d, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xbc},
+ {value: 0x0040, lo: 0xbd, hi: 0xbf},
+ // Block 0x28, offset 0x194
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbf},
+ // Block 0x29, offset 0x199
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xb7},
+ {value: 0xe045, lo: 0xb8, hi: 0xbd},
+ {value: 0x0040, lo: 0xbe, hi: 0xbf},
+ // Block 0x2a, offset 0x19e
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0x80},
+ {value: 0x0008, lo: 0x81, hi: 0xbf},
+ // Block 0x2b, offset 0x1a1
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xac},
+ {value: 0x0018, lo: 0xad, hi: 0xae},
+ {value: 0x0008, lo: 0xaf, hi: 0xbf},
+ // Block 0x2c, offset 0x1a5
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0040, lo: 0x80, hi: 0x80},
+ {value: 0x0008, lo: 0x81, hi: 0x9a},
+ {value: 0x0018, lo: 0x9b, hi: 0x9c},
+ {value: 0x0040, lo: 0x9d, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbf},
+ // Block 0x2d, offset 0x1ab
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0xaa},
+ {value: 0x0018, lo: 0xab, hi: 0xb0},
+ {value: 0x0008, lo: 0xb1, hi: 0xb8},
+ {value: 0x0040, lo: 0xb9, hi: 0xbf},
+ // Block 0x2e, offset 0x1b0
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0x8c},
+ {value: 0x0040, lo: 0x8d, hi: 0x8d},
+ {value: 0x0008, lo: 0x8e, hi: 0x91},
+ {value: 0x1308, lo: 0x92, hi: 0x93},
+ {value: 0x1b08, lo: 0x94, hi: 0x94},
+ {value: 0x0040, lo: 0x95, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xb1},
+ {value: 0x1308, lo: 0xb2, hi: 0xb3},
+ {value: 0x1b08, lo: 0xb4, hi: 0xb4},
+ {value: 0x0018, lo: 0xb5, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xbf},
+ // Block 0x2f, offset 0x1bc
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0x91},
+ {value: 0x1308, lo: 0x92, hi: 0x93},
+ {value: 0x0040, lo: 0x94, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xac},
+ {value: 0x0040, lo: 0xad, hi: 0xad},
+ {value: 0x0008, lo: 0xae, hi: 0xb0},
+ {value: 0x0040, lo: 0xb1, hi: 0xb1},
+ {value: 0x1308, lo: 0xb2, hi: 0xb3},
+ {value: 0x0040, lo: 0xb4, hi: 0xbf},
+ // Block 0x30, offset 0x1c6
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0xb3},
+ {value: 0x1340, lo: 0xb4, hi: 0xb5},
+ {value: 0x1008, lo: 0xb6, hi: 0xb6},
+ {value: 0x1308, lo: 0xb7, hi: 0xbd},
+ {value: 0x1008, lo: 0xbe, hi: 0xbf},
+ // Block 0x31, offset 0x1cc
+ {value: 0x0000, lo: 0x10},
+ {value: 0x1008, lo: 0x80, hi: 0x85},
+ {value: 0x1308, lo: 0x86, hi: 0x86},
+ {value: 0x1008, lo: 0x87, hi: 0x88},
+ {value: 0x1308, lo: 0x89, hi: 0x91},
+ {value: 0x1b08, lo: 0x92, hi: 0x92},
+ {value: 0x1308, lo: 0x93, hi: 0x93},
+ {value: 0x0018, lo: 0x94, hi: 0x96},
+ {value: 0x0008, lo: 0x97, hi: 0x97},
+ {value: 0x0018, lo: 0x98, hi: 0x9b},
+ {value: 0x0008, lo: 0x9c, hi: 0x9c},
+ {value: 0x1308, lo: 0x9d, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa9},
+ {value: 0x0040, lo: 0xaa, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbf},
+ // Block 0x32, offset 0x1dd
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0018, lo: 0x80, hi: 0x85},
+ {value: 0x0040, lo: 0x86, hi: 0x86},
+ {value: 0x0218, lo: 0x87, hi: 0x87},
+ {value: 0x0018, lo: 0x88, hi: 0x8a},
+ {value: 0x13c0, lo: 0x8b, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9f},
+ {value: 0x0208, lo: 0xa0, hi: 0xbf},
+ // Block 0x33, offset 0x1e7
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0208, lo: 0x80, hi: 0xb7},
+ {value: 0x0040, lo: 0xb8, hi: 0xbf},
+ // Block 0x34, offset 0x1ea
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0x84},
+ {value: 0x1308, lo: 0x85, hi: 0x86},
+ {value: 0x0208, lo: 0x87, hi: 0xa8},
+ {value: 0x1308, lo: 0xa9, hi: 0xa9},
+ {value: 0x0208, lo: 0xaa, hi: 0xaa},
+ {value: 0x0040, lo: 0xab, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x35, offset 0x1f2
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xbf},
+ // Block 0x36, offset 0x1f5
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0008, lo: 0x80, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0x9f},
+ {value: 0x1308, lo: 0xa0, hi: 0xa2},
+ {value: 0x1008, lo: 0xa3, hi: 0xa6},
+ {value: 0x1308, lo: 0xa7, hi: 0xa8},
+ {value: 0x1008, lo: 0xa9, hi: 0xab},
+ {value: 0x0040, lo: 0xac, hi: 0xaf},
+ {value: 0x1008, lo: 0xb0, hi: 0xb1},
+ {value: 0x1308, lo: 0xb2, hi: 0xb2},
+ {value: 0x1008, lo: 0xb3, hi: 0xb8},
+ {value: 0x1308, lo: 0xb9, hi: 0xbb},
+ {value: 0x0040, lo: 0xbc, hi: 0xbf},
+ // Block 0x37, offset 0x202
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0018, lo: 0x80, hi: 0x80},
+ {value: 0x0040, lo: 0x81, hi: 0x83},
+ {value: 0x0018, lo: 0x84, hi: 0x85},
+ {value: 0x0008, lo: 0x86, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xbf},
+ // Block 0x38, offset 0x20a
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xab},
+ {value: 0x0040, lo: 0xac, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x39, offset 0x20e
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0008, lo: 0x80, hi: 0x89},
+ {value: 0x0040, lo: 0x8a, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0028, lo: 0x9a, hi: 0x9a},
+ {value: 0x0040, lo: 0x9b, hi: 0x9d},
+ {value: 0x0018, lo: 0x9e, hi: 0xbf},
+ // Block 0x3a, offset 0x215
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0x96},
+ {value: 0x1308, lo: 0x97, hi: 0x98},
+ {value: 0x1008, lo: 0x99, hi: 0x9a},
+ {value: 0x1308, lo: 0x9b, hi: 0x9b},
+ {value: 0x0040, lo: 0x9c, hi: 0x9d},
+ {value: 0x0018, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbf},
+ // Block 0x3b, offset 0x21d
+ {value: 0x0000, lo: 0x0f},
+ {value: 0x0008, lo: 0x80, hi: 0x94},
+ {value: 0x1008, lo: 0x95, hi: 0x95},
+ {value: 0x1308, lo: 0x96, hi: 0x96},
+ {value: 0x1008, lo: 0x97, hi: 0x97},
+ {value: 0x1308, lo: 0x98, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0x9f},
+ {value: 0x1b08, lo: 0xa0, hi: 0xa0},
+ {value: 0x1008, lo: 0xa1, hi: 0xa1},
+ {value: 0x1308, lo: 0xa2, hi: 0xa2},
+ {value: 0x1008, lo: 0xa3, hi: 0xa4},
+ {value: 0x1308, lo: 0xa5, hi: 0xac},
+ {value: 0x1008, lo: 0xad, hi: 0xb2},
+ {value: 0x1308, lo: 0xb3, hi: 0xbc},
+ {value: 0x0040, lo: 0xbd, hi: 0xbe},
+ {value: 0x1308, lo: 0xbf, hi: 0xbf},
+ // Block 0x3c, offset 0x22d
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0x89},
+ {value: 0x0040, lo: 0x8a, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xa6},
+ {value: 0x0008, lo: 0xa7, hi: 0xa7},
+ {value: 0x0018, lo: 0xa8, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xaf},
+ {value: 0x1308, lo: 0xb0, hi: 0xbd},
+ {value: 0x1318, lo: 0xbe, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0x3d, offset 0x239
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0040, lo: 0x80, hi: 0xbf},
+ // Block 0x3e, offset 0x23b
+ {value: 0x0000, lo: 0x09},
+ {value: 0x1308, lo: 0x80, hi: 0x83},
+ {value: 0x1008, lo: 0x84, hi: 0x84},
+ {value: 0x0008, lo: 0x85, hi: 0xb3},
+ {value: 0x1308, lo: 0xb4, hi: 0xb4},
+ {value: 0x1008, lo: 0xb5, hi: 0xb5},
+ {value: 0x1308, lo: 0xb6, hi: 0xba},
+ {value: 0x1008, lo: 0xbb, hi: 0xbb},
+ {value: 0x1308, lo: 0xbc, hi: 0xbc},
+ {value: 0x1008, lo: 0xbd, hi: 0xbf},
+ // Block 0x3f, offset 0x245
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x1008, lo: 0x80, hi: 0x81},
+ {value: 0x1308, lo: 0x82, hi: 0x82},
+ {value: 0x1008, lo: 0x83, hi: 0x83},
+ {value: 0x1808, lo: 0x84, hi: 0x84},
+ {value: 0x0008, lo: 0x85, hi: 0x8b},
+ {value: 0x0040, lo: 0x8c, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0018, lo: 0x9a, hi: 0xaa},
+ {value: 0x1308, lo: 0xab, hi: 0xb3},
+ {value: 0x0018, lo: 0xb4, hi: 0xbc},
+ {value: 0x0040, lo: 0xbd, hi: 0xbf},
+ // Block 0x40, offset 0x251
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x1308, lo: 0x80, hi: 0x81},
+ {value: 0x1008, lo: 0x82, hi: 0x82},
+ {value: 0x0008, lo: 0x83, hi: 0xa0},
+ {value: 0x1008, lo: 0xa1, hi: 0xa1},
+ {value: 0x1308, lo: 0xa2, hi: 0xa5},
+ {value: 0x1008, lo: 0xa6, hi: 0xa7},
+ {value: 0x1308, lo: 0xa8, hi: 0xa9},
+ {value: 0x1808, lo: 0xaa, hi: 0xaa},
+ {value: 0x1b08, lo: 0xab, hi: 0xab},
+ {value: 0x1308, lo: 0xac, hi: 0xad},
+ {value: 0x0008, lo: 0xae, hi: 0xbf},
+ // Block 0x41, offset 0x25d
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0xa5},
+ {value: 0x1308, lo: 0xa6, hi: 0xa6},
+ {value: 0x1008, lo: 0xa7, hi: 0xa7},
+ {value: 0x1308, lo: 0xa8, hi: 0xa9},
+ {value: 0x1008, lo: 0xaa, hi: 0xac},
+ {value: 0x1308, lo: 0xad, hi: 0xad},
+ {value: 0x1008, lo: 0xae, hi: 0xae},
+ {value: 0x1308, lo: 0xaf, hi: 0xb1},
+ {value: 0x1808, lo: 0xb2, hi: 0xb3},
+ {value: 0x0040, lo: 0xb4, hi: 0xbb},
+ {value: 0x0018, lo: 0xbc, hi: 0xbf},
+ // Block 0x42, offset 0x269
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0xa3},
+ {value: 0x1008, lo: 0xa4, hi: 0xab},
+ {value: 0x1308, lo: 0xac, hi: 0xb3},
+ {value: 0x1008, lo: 0xb4, hi: 0xb5},
+ {value: 0x1308, lo: 0xb6, hi: 0xb7},
+ {value: 0x0040, lo: 0xb8, hi: 0xba},
+ {value: 0x0018, lo: 0xbb, hi: 0xbf},
+ // Block 0x43, offset 0x271
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x89},
+ {value: 0x0040, lo: 0x8a, hi: 0x8c},
+ {value: 0x0008, lo: 0x8d, hi: 0xbd},
+ {value: 0x0018, lo: 0xbe, hi: 0xbf},
+ // Block 0x44, offset 0x276
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0e29, lo: 0x80, hi: 0x80},
+ {value: 0x0e41, lo: 0x81, hi: 0x81},
+ {value: 0x0e59, lo: 0x82, hi: 0x82},
+ {value: 0x0e71, lo: 0x83, hi: 0x83},
+ {value: 0x0e89, lo: 0x84, hi: 0x85},
+ {value: 0x0ea1, lo: 0x86, hi: 0x86},
+ {value: 0x0eb9, lo: 0x87, hi: 0x87},
+ {value: 0x057d, lo: 0x88, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0xbf},
+ // Block 0x45, offset 0x280
+ {value: 0x0000, lo: 0x10},
+ {value: 0x0018, lo: 0x80, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8f},
+ {value: 0x1308, lo: 0x90, hi: 0x92},
+ {value: 0x0018, lo: 0x93, hi: 0x93},
+ {value: 0x1308, lo: 0x94, hi: 0xa0},
+ {value: 0x1008, lo: 0xa1, hi: 0xa1},
+ {value: 0x1308, lo: 0xa2, hi: 0xa8},
+ {value: 0x0008, lo: 0xa9, hi: 0xac},
+ {value: 0x1308, lo: 0xad, hi: 0xad},
+ {value: 0x0008, lo: 0xae, hi: 0xb1},
+ {value: 0x1008, lo: 0xb2, hi: 0xb3},
+ {value: 0x1308, lo: 0xb4, hi: 0xb4},
+ {value: 0x0008, lo: 0xb5, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xb7},
+ {value: 0x1308, lo: 0xb8, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbf},
+ // Block 0x46, offset 0x291
+ {value: 0x0000, lo: 0x03},
+ {value: 0x1308, lo: 0x80, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xba},
+ {value: 0x1308, lo: 0xbb, hi: 0xbf},
+ // Block 0x47, offset 0x295
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x0008, lo: 0x80, hi: 0x87},
+ {value: 0xe045, lo: 0x88, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0x97},
+ {value: 0xe045, lo: 0x98, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa7},
+ {value: 0xe045, lo: 0xa8, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb7},
+ {value: 0xe045, lo: 0xb8, hi: 0xbf},
+ // Block 0x48, offset 0x2a0
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0040, lo: 0x80, hi: 0x8f},
+ {value: 0x1318, lo: 0x90, hi: 0xb0},
+ {value: 0x0040, lo: 0xb1, hi: 0xbf},
+ // Block 0x49, offset 0x2a4
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0018, lo: 0x80, hi: 0x82},
+ {value: 0x0040, lo: 0x83, hi: 0x83},
+ {value: 0x0008, lo: 0x84, hi: 0x84},
+ {value: 0x0018, lo: 0x85, hi: 0x88},
+ {value: 0x24c1, lo: 0x89, hi: 0x89},
+ {value: 0x0018, lo: 0x8a, hi: 0x8b},
+ {value: 0x0040, lo: 0x8c, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0xbf},
+ // Block 0x4a, offset 0x2ad
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0018, lo: 0x80, hi: 0xab},
+ {value: 0x24f1, lo: 0xac, hi: 0xac},
+ {value: 0x2529, lo: 0xad, hi: 0xad},
+ {value: 0x0018, lo: 0xae, hi: 0xae},
+ {value: 0x2579, lo: 0xaf, hi: 0xaf},
+ {value: 0x25b1, lo: 0xb0, hi: 0xb0},
+ {value: 0x0018, lo: 0xb1, hi: 0xbf},
+ // Block 0x4b, offset 0x2b5
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0018, lo: 0x80, hi: 0x9f},
+ {value: 0x0080, lo: 0xa0, hi: 0xa0},
+ {value: 0x0018, lo: 0xa1, hi: 0xad},
+ {value: 0x0080, lo: 0xae, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xbf},
+ // Block 0x4c, offset 0x2bb
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0xa8},
+ {value: 0x09c5, lo: 0xa9, hi: 0xa9},
+ {value: 0x09e5, lo: 0xaa, hi: 0xaa},
+ {value: 0x0018, lo: 0xab, hi: 0xbf},
+ // Block 0x4d, offset 0x2c0
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0x4e, offset 0x2c3
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0xa6},
+ {value: 0x0040, lo: 0xa7, hi: 0xbf},
+ // Block 0x4f, offset 0x2c6
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0x8b},
+ {value: 0x28c1, lo: 0x8c, hi: 0x8c},
+ {value: 0x0018, lo: 0x8d, hi: 0xbf},
+ // Block 0x50, offset 0x2ca
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0018, lo: 0x80, hi: 0xb3},
+ {value: 0x0e66, lo: 0xb4, hi: 0xb4},
+ {value: 0x292a, lo: 0xb5, hi: 0xb5},
+ {value: 0x0e86, lo: 0xb6, hi: 0xb6},
+ {value: 0x0018, lo: 0xb7, hi: 0xbf},
+ // Block 0x51, offset 0x2d0
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0x9b},
+ {value: 0x2941, lo: 0x9c, hi: 0x9c},
+ {value: 0x0018, lo: 0x9d, hi: 0xbf},
+ // Block 0x52, offset 0x2d4
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0xb3},
+ {value: 0x0040, lo: 0xb4, hi: 0xb5},
+ {value: 0x0018, lo: 0xb6, hi: 0xbf},
+ // Block 0x53, offset 0x2d8
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0018, lo: 0x80, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0x97},
+ {value: 0x0018, lo: 0x98, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbc},
+ {value: 0x0018, lo: 0xbd, hi: 0xbf},
+ // Block 0x54, offset 0x2de
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0018, lo: 0x80, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x89},
+ {value: 0x0018, lo: 0x8a, hi: 0x91},
+ {value: 0x0040, lo: 0x92, hi: 0xab},
+ {value: 0x0018, lo: 0xac, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xbf},
+ // Block 0x55, offset 0x2e5
+ {value: 0x0000, lo: 0x05},
+ {value: 0xe185, lo: 0x80, hi: 0x8f},
+ {value: 0x03f5, lo: 0x90, hi: 0x9f},
+ {value: 0x0ea5, lo: 0xa0, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x56, offset 0x2eb
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0xa5},
+ {value: 0x0040, lo: 0xa6, hi: 0xa6},
+ {value: 0x0008, lo: 0xa7, hi: 0xa7},
+ {value: 0x0040, lo: 0xa8, hi: 0xac},
+ {value: 0x0008, lo: 0xad, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x57, offset 0x2f3
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0008, lo: 0x80, hi: 0xa7},
+ {value: 0x0040, lo: 0xa8, hi: 0xae},
+ {value: 0xe075, lo: 0xaf, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb0},
+ {value: 0x0040, lo: 0xb1, hi: 0xbe},
+ {value: 0x1b08, lo: 0xbf, hi: 0xbf},
+ // Block 0x58, offset 0x2fa
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x0008, lo: 0x80, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa6},
+ {value: 0x0040, lo: 0xa7, hi: 0xa7},
+ {value: 0x0008, lo: 0xa8, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xb7},
+ {value: 0x0008, lo: 0xb8, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0x59, offset 0x305
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x87},
+ {value: 0x0008, lo: 0x88, hi: 0x8e},
+ {value: 0x0040, lo: 0x8f, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x97},
+ {value: 0x0008, lo: 0x98, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0x9f},
+ {value: 0x1308, lo: 0xa0, hi: 0xbf},
+ // Block 0x5a, offset 0x30f
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0xae},
+ {value: 0x0008, lo: 0xaf, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xbf},
+ // Block 0x5b, offset 0x313
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0x84},
+ {value: 0x0040, lo: 0x85, hi: 0xbf},
+ // Block 0x5c, offset 0x316
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0018, lo: 0x80, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9a},
+ {value: 0x0018, lo: 0x9b, hi: 0x9e},
+ {value: 0x0edd, lo: 0x9f, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xbf},
+ // Block 0x5d, offset 0x31c
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0xb2},
+ {value: 0x0efd, lo: 0xb3, hi: 0xb3},
+ {value: 0x0040, lo: 0xb4, hi: 0xbf},
+ // Block 0x5e, offset 0x320
+ {value: 0x0020, lo: 0x01},
+ {value: 0x0f1d, lo: 0x80, hi: 0xbf},
+ // Block 0x5f, offset 0x322
+ {value: 0x0020, lo: 0x02},
+ {value: 0x171d, lo: 0x80, hi: 0x8f},
+ {value: 0x18fd, lo: 0x90, hi: 0xbf},
+ // Block 0x60, offset 0x325
+ {value: 0x0020, lo: 0x01},
+ {value: 0x1efd, lo: 0x80, hi: 0xbf},
+ // Block 0x61, offset 0x327
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0040, lo: 0x80, hi: 0x80},
+ {value: 0x0008, lo: 0x81, hi: 0xbf},
+ // Block 0x62, offset 0x32a
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x98},
+ {value: 0x1308, lo: 0x99, hi: 0x9a},
+ {value: 0x29e2, lo: 0x9b, hi: 0x9b},
+ {value: 0x2a0a, lo: 0x9c, hi: 0x9c},
+ {value: 0x0008, lo: 0x9d, hi: 0x9e},
+ {value: 0x2a31, lo: 0x9f, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xa0},
+ {value: 0x0008, lo: 0xa1, hi: 0xbf},
+ // Block 0x63, offset 0x334
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xbe},
+ {value: 0x2a69, lo: 0xbf, hi: 0xbf},
+ // Block 0x64, offset 0x337
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x0040, lo: 0x80, hi: 0x84},
+ {value: 0x0008, lo: 0x85, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xb0},
+ {value: 0x2a1d, lo: 0xb1, hi: 0xb1},
+ {value: 0x2a3d, lo: 0xb2, hi: 0xb2},
+ {value: 0x2a5d, lo: 0xb3, hi: 0xb3},
+ {value: 0x2a7d, lo: 0xb4, hi: 0xb4},
+ {value: 0x2a5d, lo: 0xb5, hi: 0xb5},
+ {value: 0x2a9d, lo: 0xb6, hi: 0xb6},
+ {value: 0x2abd, lo: 0xb7, hi: 0xb7},
+ {value: 0x2add, lo: 0xb8, hi: 0xb9},
+ {value: 0x2afd, lo: 0xba, hi: 0xbb},
+ {value: 0x2b1d, lo: 0xbc, hi: 0xbd},
+ {value: 0x2afd, lo: 0xbe, hi: 0xbf},
+ // Block 0x65, offset 0x346
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0xa3},
+ {value: 0x0040, lo: 0xa4, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x66, offset 0x34a
+ {value: 0x0030, lo: 0x04},
+ {value: 0x2aa2, lo: 0x80, hi: 0x9d},
+ {value: 0x305a, lo: 0x9e, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0x9f},
+ {value: 0x30a2, lo: 0xa0, hi: 0xbf},
+ // Block 0x67, offset 0x34f
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0xbf},
+ // Block 0x68, offset 0x352
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0x8c},
+ {value: 0x0040, lo: 0x8d, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0xbf},
+ // Block 0x69, offset 0x356
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xbd},
+ {value: 0x0018, lo: 0xbe, hi: 0xbf},
+ // Block 0x6a, offset 0x35b
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x8c},
+ {value: 0x0018, lo: 0x8d, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xab},
+ {value: 0x0040, lo: 0xac, hi: 0xbf},
+ // Block 0x6b, offset 0x360
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0xa5},
+ {value: 0x0018, lo: 0xa6, hi: 0xaf},
+ {value: 0x1308, lo: 0xb0, hi: 0xb1},
+ {value: 0x0018, lo: 0xb2, hi: 0xb7},
+ {value: 0x0040, lo: 0xb8, hi: 0xbf},
+ // Block 0x6c, offset 0x366
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0040, lo: 0x80, hi: 0xb6},
+ {value: 0x0008, lo: 0xb7, hi: 0xb7},
+ {value: 0x2009, lo: 0xb8, hi: 0xb8},
+ {value: 0x6e89, lo: 0xb9, hi: 0xb9},
+ {value: 0x0008, lo: 0xba, hi: 0xbf},
+ // Block 0x6d, offset 0x36c
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x0008, lo: 0x80, hi: 0x81},
+ {value: 0x1308, lo: 0x82, hi: 0x82},
+ {value: 0x0008, lo: 0x83, hi: 0x85},
+ {value: 0x1b08, lo: 0x86, hi: 0x86},
+ {value: 0x0008, lo: 0x87, hi: 0x8a},
+ {value: 0x1308, lo: 0x8b, hi: 0x8b},
+ {value: 0x0008, lo: 0x8c, hi: 0xa2},
+ {value: 0x1008, lo: 0xa3, hi: 0xa4},
+ {value: 0x1308, lo: 0xa5, hi: 0xa6},
+ {value: 0x1008, lo: 0xa7, hi: 0xa7},
+ {value: 0x0018, lo: 0xa8, hi: 0xab},
+ {value: 0x0040, lo: 0xac, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbf},
+ // Block 0x6e, offset 0x37b
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0208, lo: 0x80, hi: 0xb1},
+ {value: 0x0108, lo: 0xb2, hi: 0xb2},
+ {value: 0x0008, lo: 0xb3, hi: 0xb3},
+ {value: 0x0018, lo: 0xb4, hi: 0xb7},
+ {value: 0x0040, lo: 0xb8, hi: 0xbf},
+ // Block 0x6f, offset 0x381
+ {value: 0x0000, lo: 0x03},
+ {value: 0x1008, lo: 0x80, hi: 0x81},
+ {value: 0x0008, lo: 0x82, hi: 0xb3},
+ {value: 0x1008, lo: 0xb4, hi: 0xbf},
+ // Block 0x70, offset 0x385
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x1008, lo: 0x80, hi: 0x83},
+ {value: 0x1b08, lo: 0x84, hi: 0x84},
+ {value: 0x1308, lo: 0x85, hi: 0x85},
+ {value: 0x0040, lo: 0x86, hi: 0x8d},
+ {value: 0x0018, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9f},
+ {value: 0x1308, lo: 0xa0, hi: 0xb1},
+ {value: 0x0008, lo: 0xb2, hi: 0xb7},
+ {value: 0x0018, lo: 0xb8, hi: 0xba},
+ {value: 0x0008, lo: 0xbb, hi: 0xbb},
+ {value: 0x0018, lo: 0xbc, hi: 0xbc},
+ {value: 0x0008, lo: 0xbd, hi: 0xbd},
+ {value: 0x0040, lo: 0xbe, hi: 0xbf},
+ // Block 0x71, offset 0x394
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0xa5},
+ {value: 0x1308, lo: 0xa6, hi: 0xad},
+ {value: 0x0018, lo: 0xae, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x72, offset 0x399
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x1308, lo: 0x87, hi: 0x91},
+ {value: 0x1008, lo: 0x92, hi: 0x92},
+ {value: 0x1808, lo: 0x93, hi: 0x93},
+ {value: 0x0040, lo: 0x94, hi: 0x9e},
+ {value: 0x0018, lo: 0x9f, hi: 0xbc},
+ {value: 0x0040, lo: 0xbd, hi: 0xbf},
+ // Block 0x73, offset 0x3a1
+ {value: 0x0000, lo: 0x09},
+ {value: 0x1308, lo: 0x80, hi: 0x82},
+ {value: 0x1008, lo: 0x83, hi: 0x83},
+ {value: 0x0008, lo: 0x84, hi: 0xb2},
+ {value: 0x1308, lo: 0xb3, hi: 0xb3},
+ {value: 0x1008, lo: 0xb4, hi: 0xb5},
+ {value: 0x1308, lo: 0xb6, hi: 0xb9},
+ {value: 0x1008, lo: 0xba, hi: 0xbb},
+ {value: 0x1308, lo: 0xbc, hi: 0xbc},
+ {value: 0x1008, lo: 0xbd, hi: 0xbf},
+ // Block 0x74, offset 0x3ab
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x1808, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8e},
+ {value: 0x0008, lo: 0x8f, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9d},
+ {value: 0x0018, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa4},
+ {value: 0x1308, lo: 0xa5, hi: 0xa5},
+ {value: 0x0008, lo: 0xa6, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0x75, offset 0x3b6
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0xa8},
+ {value: 0x1308, lo: 0xa9, hi: 0xae},
+ {value: 0x1008, lo: 0xaf, hi: 0xb0},
+ {value: 0x1308, lo: 0xb1, hi: 0xb2},
+ {value: 0x1008, lo: 0xb3, hi: 0xb4},
+ {value: 0x1308, lo: 0xb5, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xbf},
+ // Block 0x76, offset 0x3be
+ {value: 0x0000, lo: 0x10},
+ {value: 0x0008, lo: 0x80, hi: 0x82},
+ {value: 0x1308, lo: 0x83, hi: 0x83},
+ {value: 0x0008, lo: 0x84, hi: 0x8b},
+ {value: 0x1308, lo: 0x8c, hi: 0x8c},
+ {value: 0x1008, lo: 0x8d, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9b},
+ {value: 0x0018, lo: 0x9c, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xb6},
+ {value: 0x0018, lo: 0xb7, hi: 0xb9},
+ {value: 0x0008, lo: 0xba, hi: 0xba},
+ {value: 0x1008, lo: 0xbb, hi: 0xbb},
+ {value: 0x1308, lo: 0xbc, hi: 0xbc},
+ {value: 0x1008, lo: 0xbd, hi: 0xbd},
+ {value: 0x0008, lo: 0xbe, hi: 0xbf},
+ // Block 0x77, offset 0x3cf
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0008, lo: 0x80, hi: 0xaf},
+ {value: 0x1308, lo: 0xb0, hi: 0xb0},
+ {value: 0x0008, lo: 0xb1, hi: 0xb1},
+ {value: 0x1308, lo: 0xb2, hi: 0xb4},
+ {value: 0x0008, lo: 0xb5, hi: 0xb6},
+ {value: 0x1308, lo: 0xb7, hi: 0xb8},
+ {value: 0x0008, lo: 0xb9, hi: 0xbd},
+ {value: 0x1308, lo: 0xbe, hi: 0xbf},
+ // Block 0x78, offset 0x3d8
+ {value: 0x0000, lo: 0x0f},
+ {value: 0x0008, lo: 0x80, hi: 0x80},
+ {value: 0x1308, lo: 0x81, hi: 0x81},
+ {value: 0x0008, lo: 0x82, hi: 0x82},
+ {value: 0x0040, lo: 0x83, hi: 0x9a},
+ {value: 0x0008, lo: 0x9b, hi: 0x9d},
+ {value: 0x0018, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xaa},
+ {value: 0x1008, lo: 0xab, hi: 0xab},
+ {value: 0x1308, lo: 0xac, hi: 0xad},
+ {value: 0x1008, lo: 0xae, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb1},
+ {value: 0x0008, lo: 0xb2, hi: 0xb4},
+ {value: 0x1008, lo: 0xb5, hi: 0xb5},
+ {value: 0x1b08, lo: 0xb6, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xbf},
+ // Block 0x79, offset 0x3e8
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0040, lo: 0x80, hi: 0x80},
+ {value: 0x0008, lo: 0x81, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x88},
+ {value: 0x0008, lo: 0x89, hi: 0x8e},
+ {value: 0x0040, lo: 0x8f, hi: 0x90},
+ {value: 0x0008, lo: 0x91, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa6},
+ {value: 0x0040, lo: 0xa7, hi: 0xa7},
+ {value: 0x0008, lo: 0xa8, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x7a, offset 0x3f5
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0x9a},
+ {value: 0x0018, lo: 0x9b, hi: 0x9b},
+ {value: 0x4465, lo: 0x9c, hi: 0x9c},
+ {value: 0x447d, lo: 0x9d, hi: 0x9d},
+ {value: 0x2971, lo: 0x9e, hi: 0x9e},
+ {value: 0xe06d, lo: 0x9f, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa5},
+ {value: 0x0040, lo: 0xa6, hi: 0xaf},
+ {value: 0x4495, lo: 0xb0, hi: 0xbf},
+ // Block 0x7b, offset 0x3ff
+ {value: 0x0000, lo: 0x04},
+ {value: 0x44b5, lo: 0x80, hi: 0x8f},
+ {value: 0x44d5, lo: 0x90, hi: 0x9f},
+ {value: 0x44f5, lo: 0xa0, hi: 0xaf},
+ {value: 0x44d5, lo: 0xb0, hi: 0xbf},
+ // Block 0x7c, offset 0x404
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0008, lo: 0x80, hi: 0xa2},
+ {value: 0x1008, lo: 0xa3, hi: 0xa4},
+ {value: 0x1308, lo: 0xa5, hi: 0xa5},
+ {value: 0x1008, lo: 0xa6, hi: 0xa7},
+ {value: 0x1308, lo: 0xa8, hi: 0xa8},
+ {value: 0x1008, lo: 0xa9, hi: 0xaa},
+ {value: 0x0018, lo: 0xab, hi: 0xab},
+ {value: 0x1008, lo: 0xac, hi: 0xac},
+ {value: 0x1b08, lo: 0xad, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbf},
+ // Block 0x7d, offset 0x411
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xa3},
+ {value: 0x0040, lo: 0xa4, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xbf},
+ // Block 0x7e, offset 0x415
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x8a},
+ {value: 0x0018, lo: 0x8b, hi: 0xbb},
+ {value: 0x0040, lo: 0xbc, hi: 0xbf},
+ // Block 0x7f, offset 0x41a
+ {value: 0x0020, lo: 0x01},
+ {value: 0x4515, lo: 0x80, hi: 0xbf},
+ // Block 0x80, offset 0x41c
+ {value: 0x0020, lo: 0x03},
+ {value: 0x4d15, lo: 0x80, hi: 0x94},
+ {value: 0x4ad5, lo: 0x95, hi: 0x95},
+ {value: 0x4fb5, lo: 0x96, hi: 0xbf},
+ // Block 0x81, offset 0x420
+ {value: 0x0020, lo: 0x01},
+ {value: 0x54f5, lo: 0x80, hi: 0xbf},
+ // Block 0x82, offset 0x422
+ {value: 0x0020, lo: 0x03},
+ {value: 0x5cf5, lo: 0x80, hi: 0x84},
+ {value: 0x5655, lo: 0x85, hi: 0x85},
+ {value: 0x5d95, lo: 0x86, hi: 0xbf},
+ // Block 0x83, offset 0x426
+ {value: 0x0020, lo: 0x08},
+ {value: 0x6b55, lo: 0x80, hi: 0x8f},
+ {value: 0x6d15, lo: 0x90, hi: 0x90},
+ {value: 0x6d55, lo: 0x91, hi: 0xab},
+ {value: 0x6ea1, lo: 0xac, hi: 0xac},
+ {value: 0x70b5, lo: 0xad, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xaf},
+ {value: 0x70d5, lo: 0xb0, hi: 0xbf},
+ // Block 0x84, offset 0x42f
+ {value: 0x0020, lo: 0x05},
+ {value: 0x72d5, lo: 0x80, hi: 0xad},
+ {value: 0x6535, lo: 0xae, hi: 0xae},
+ {value: 0x7895, lo: 0xaf, hi: 0xb5},
+ {value: 0x6f55, lo: 0xb6, hi: 0xb6},
+ {value: 0x7975, lo: 0xb7, hi: 0xbf},
+ // Block 0x85, offset 0x435
+ {value: 0x0028, lo: 0x03},
+ {value: 0x7c21, lo: 0x80, hi: 0x82},
+ {value: 0x7be1, lo: 0x83, hi: 0x83},
+ {value: 0x7c99, lo: 0x84, hi: 0xbf},
+ // Block 0x86, offset 0x439
+ {value: 0x0038, lo: 0x0f},
+ {value: 0x9db1, lo: 0x80, hi: 0x83},
+ {value: 0x9e59, lo: 0x84, hi: 0x85},
+ {value: 0x9e91, lo: 0x86, hi: 0x87},
+ {value: 0x9ec9, lo: 0x88, hi: 0x8f},
+ {value: 0x0040, lo: 0x90, hi: 0x90},
+ {value: 0x0040, lo: 0x91, hi: 0x91},
+ {value: 0xa089, lo: 0x92, hi: 0x97},
+ {value: 0xa1a1, lo: 0x98, hi: 0x9c},
+ {value: 0xa281, lo: 0x9d, hi: 0xb3},
+ {value: 0x9d41, lo: 0xb4, hi: 0xb4},
+ {value: 0x9db1, lo: 0xb5, hi: 0xb5},
+ {value: 0xa789, lo: 0xb6, hi: 0xbb},
+ {value: 0xa869, lo: 0xbc, hi: 0xbc},
+ {value: 0xa7f9, lo: 0xbd, hi: 0xbd},
+ {value: 0xa8d9, lo: 0xbe, hi: 0xbf},
+ // Block 0x87, offset 0x449
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0x8b},
+ {value: 0x0040, lo: 0x8c, hi: 0x8c},
+ {value: 0x0008, lo: 0x8d, hi: 0xa6},
+ {value: 0x0040, lo: 0xa7, hi: 0xa7},
+ {value: 0x0008, lo: 0xa8, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbb},
+ {value: 0x0008, lo: 0xbc, hi: 0xbd},
+ {value: 0x0040, lo: 0xbe, hi: 0xbe},
+ {value: 0x0008, lo: 0xbf, hi: 0xbf},
+ // Block 0x88, offset 0x453
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0xbf},
+ // Block 0x89, offset 0x458
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbf},
+ // Block 0x8a, offset 0x45b
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0018, lo: 0x80, hi: 0x82},
+ {value: 0x0040, lo: 0x83, hi: 0x86},
+ {value: 0x0018, lo: 0x87, hi: 0xb3},
+ {value: 0x0040, lo: 0xb4, hi: 0xb6},
+ {value: 0x0018, lo: 0xb7, hi: 0xbf},
+ // Block 0x8b, offset 0x461
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0018, lo: 0x80, hi: 0x8e},
+ {value: 0x0040, lo: 0x8f, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0x9b},
+ {value: 0x0040, lo: 0x9c, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xa0},
+ {value: 0x0040, lo: 0xa1, hi: 0xbf},
+ // Block 0x8c, offset 0x468
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0040, lo: 0x80, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0xbc},
+ {value: 0x1308, lo: 0xbd, hi: 0xbd},
+ {value: 0x0040, lo: 0xbe, hi: 0xbf},
+ // Block 0x8d, offset 0x46d
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0x9c},
+ {value: 0x0040, lo: 0x9d, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbf},
+ // Block 0x8e, offset 0x471
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0x90},
+ {value: 0x0040, lo: 0x91, hi: 0x9f},
+ {value: 0x1308, lo: 0xa0, hi: 0xa0},
+ {value: 0x0018, lo: 0xa1, hi: 0xbb},
+ {value: 0x0040, lo: 0xbc, hi: 0xbf},
+ // Block 0x8f, offset 0x477
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xa3},
+ {value: 0x0040, lo: 0xa4, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x90, offset 0x47c
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0008, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0x81},
+ {value: 0x0008, lo: 0x82, hi: 0x89},
+ {value: 0x0018, lo: 0x8a, hi: 0x8a},
+ {value: 0x0040, lo: 0x8b, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xb5},
+ {value: 0x1308, lo: 0xb6, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbf},
+ // Block 0x91, offset 0x485
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0x9e},
+ {value: 0x0018, lo: 0x9f, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbf},
+ // Block 0x92, offset 0x48a
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0x87},
+ {value: 0x0008, lo: 0x88, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0xbf},
+ // Block 0x93, offset 0x490
+ {value: 0x0000, lo: 0x06},
+ {value: 0xe145, lo: 0x80, hi: 0x87},
+ {value: 0xe1c5, lo: 0x88, hi: 0x8f},
+ {value: 0xe145, lo: 0x90, hi: 0x97},
+ {value: 0x8ad5, lo: 0x98, hi: 0x9f},
+ {value: 0x8aed, lo: 0xa0, hi: 0xa7},
+ {value: 0x0008, lo: 0xa8, hi: 0xbf},
+ // Block 0x94, offset 0x497
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0008, lo: 0x80, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa9},
+ {value: 0x0040, lo: 0xaa, hi: 0xaf},
+ {value: 0x8aed, lo: 0xb0, hi: 0xb7},
+ {value: 0x8ad5, lo: 0xb8, hi: 0xbf},
+ // Block 0x95, offset 0x49e
+ {value: 0x0000, lo: 0x06},
+ {value: 0xe145, lo: 0x80, hi: 0x87},
+ {value: 0xe1c5, lo: 0x88, hi: 0x8f},
+ {value: 0xe145, lo: 0x90, hi: 0x93},
+ {value: 0x0040, lo: 0x94, hi: 0x97},
+ {value: 0x0008, lo: 0x98, hi: 0xbb},
+ {value: 0x0040, lo: 0xbc, hi: 0xbf},
+ // Block 0x96, offset 0x4a5
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xa7},
+ {value: 0x0040, lo: 0xa8, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0x97, offset 0x4a9
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0xa3},
+ {value: 0x0040, lo: 0xa4, hi: 0xae},
+ {value: 0x0018, lo: 0xaf, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xbf},
+ // Block 0x98, offset 0x4ae
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xbf},
+ // Block 0x99, offset 0x4b1
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa7},
+ {value: 0x0040, lo: 0xa8, hi: 0xbf},
+ // Block 0x9a, offset 0x4b6
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0x85},
+ {value: 0x0040, lo: 0x86, hi: 0x87},
+ {value: 0x0008, lo: 0x88, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x89},
+ {value: 0x0008, lo: 0x8a, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xb6},
+ {value: 0x0008, lo: 0xb7, hi: 0xb8},
+ {value: 0x0040, lo: 0xb9, hi: 0xbb},
+ {value: 0x0008, lo: 0xbc, hi: 0xbc},
+ {value: 0x0040, lo: 0xbd, hi: 0xbe},
+ {value: 0x0008, lo: 0xbf, hi: 0xbf},
+ // Block 0x9b, offset 0x4c2
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0x96},
+ {value: 0x0018, lo: 0x97, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xb6},
+ {value: 0x0018, lo: 0xb7, hi: 0xbf},
+ // Block 0x9c, offset 0x4c8
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0xa6},
+ {value: 0x0018, lo: 0xa7, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xbf},
+ // Block 0x9d, offset 0x4cd
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0040, lo: 0x80, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xb2},
+ {value: 0x0040, lo: 0xb3, hi: 0xb3},
+ {value: 0x0008, lo: 0xb4, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xba},
+ {value: 0x0018, lo: 0xbb, hi: 0xbf},
+ // Block 0x9e, offset 0x4d4
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0x95},
+ {value: 0x0018, lo: 0x96, hi: 0x9b},
+ {value: 0x0040, lo: 0x9c, hi: 0x9e},
+ {value: 0x0018, lo: 0x9f, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbe},
+ {value: 0x0018, lo: 0xbf, hi: 0xbf},
+ // Block 0x9f, offset 0x4dc
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0xb7},
+ {value: 0x0040, lo: 0xb8, hi: 0xbb},
+ {value: 0x0018, lo: 0xbc, hi: 0xbd},
+ {value: 0x0008, lo: 0xbe, hi: 0xbf},
+ // Block 0xa0, offset 0x4e1
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0x8f},
+ {value: 0x0040, lo: 0x90, hi: 0x91},
+ {value: 0x0018, lo: 0x92, hi: 0xbf},
+ // Block 0xa1, offset 0x4e5
+ {value: 0x0000, lo: 0x0f},
+ {value: 0x0008, lo: 0x80, hi: 0x80},
+ {value: 0x1308, lo: 0x81, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0x84},
+ {value: 0x1308, lo: 0x85, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x8b},
+ {value: 0x1308, lo: 0x8c, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x93},
+ {value: 0x0040, lo: 0x94, hi: 0x94},
+ {value: 0x0008, lo: 0x95, hi: 0x97},
+ {value: 0x0040, lo: 0x98, hi: 0x98},
+ {value: 0x0008, lo: 0x99, hi: 0xb3},
+ {value: 0x0040, lo: 0xb4, hi: 0xb7},
+ {value: 0x1308, lo: 0xb8, hi: 0xba},
+ {value: 0x0040, lo: 0xbb, hi: 0xbe},
+ {value: 0x1b08, lo: 0xbf, hi: 0xbf},
+ // Block 0xa2, offset 0x4f5
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0018, lo: 0x80, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0x98},
+ {value: 0x0040, lo: 0x99, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbc},
+ {value: 0x0018, lo: 0xbd, hi: 0xbf},
+ // Block 0xa3, offset 0x4fc
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0x9c},
+ {value: 0x0018, lo: 0x9d, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xbf},
+ // Block 0xa4, offset 0x500
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xb8},
+ {value: 0x0018, lo: 0xb9, hi: 0xbf},
+ // Block 0xa5, offset 0x504
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0008, lo: 0x80, hi: 0x95},
+ {value: 0x0040, lo: 0x96, hi: 0x97},
+ {value: 0x0018, lo: 0x98, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xb2},
+ {value: 0x0040, lo: 0xb3, hi: 0xb7},
+ {value: 0x0018, lo: 0xb8, hi: 0xbf},
+ // Block 0xa6, offset 0x50b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0xbf},
+ // Block 0xa7, offset 0x50e
+ {value: 0x0000, lo: 0x02},
+ {value: 0x03dd, lo: 0x80, hi: 0xb2},
+ {value: 0x0040, lo: 0xb3, hi: 0xbf},
+ // Block 0xa8, offset 0x511
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xb2},
+ {value: 0x0040, lo: 0xb3, hi: 0xb9},
+ {value: 0x0018, lo: 0xba, hi: 0xbf},
+ // Block 0xa9, offset 0x515
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0040, lo: 0x80, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0xaa, offset 0x519
+ {value: 0x0000, lo: 0x05},
+ {value: 0x1008, lo: 0x80, hi: 0x80},
+ {value: 0x1308, lo: 0x81, hi: 0x81},
+ {value: 0x1008, lo: 0x82, hi: 0x82},
+ {value: 0x0008, lo: 0x83, hi: 0xb7},
+ {value: 0x1308, lo: 0xb8, hi: 0xbf},
+ // Block 0xab, offset 0x51f
+ {value: 0x0000, lo: 0x08},
+ {value: 0x1308, lo: 0x80, hi: 0x85},
+ {value: 0x1b08, lo: 0x86, hi: 0x86},
+ {value: 0x0018, lo: 0x87, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x91},
+ {value: 0x0018, lo: 0x92, hi: 0xa5},
+ {value: 0x0008, lo: 0xa6, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xbe},
+ {value: 0x1b08, lo: 0xbf, hi: 0xbf},
+ // Block 0xac, offset 0x528
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x1308, lo: 0x80, hi: 0x81},
+ {value: 0x1008, lo: 0x82, hi: 0x82},
+ {value: 0x0008, lo: 0x83, hi: 0xaf},
+ {value: 0x1008, lo: 0xb0, hi: 0xb2},
+ {value: 0x1308, lo: 0xb3, hi: 0xb6},
+ {value: 0x1008, lo: 0xb7, hi: 0xb8},
+ {value: 0x1b08, lo: 0xb9, hi: 0xb9},
+ {value: 0x1308, lo: 0xba, hi: 0xba},
+ {value: 0x0018, lo: 0xbb, hi: 0xbc},
+ {value: 0x0340, lo: 0xbd, hi: 0xbd},
+ {value: 0x0018, lo: 0xbe, hi: 0xbf},
+ // Block 0xad, offset 0x534
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0018, lo: 0x80, hi: 0x81},
+ {value: 0x0040, lo: 0x82, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xa8},
+ {value: 0x0040, lo: 0xa9, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbf},
+ // Block 0xae, offset 0x53b
+ {value: 0x0000, lo: 0x08},
+ {value: 0x1308, lo: 0x80, hi: 0x82},
+ {value: 0x0008, lo: 0x83, hi: 0xa6},
+ {value: 0x1308, lo: 0xa7, hi: 0xab},
+ {value: 0x1008, lo: 0xac, hi: 0xac},
+ {value: 0x1308, lo: 0xad, hi: 0xb2},
+ {value: 0x1b08, lo: 0xb3, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xb5},
+ {value: 0x0008, lo: 0xb6, hi: 0xbf},
+ // Block 0xaf, offset 0x544
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0018, lo: 0x80, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xb2},
+ {value: 0x1308, lo: 0xb3, hi: 0xb3},
+ {value: 0x0018, lo: 0xb4, hi: 0xb5},
+ {value: 0x0008, lo: 0xb6, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xbf},
+ // Block 0xb0, offset 0x54c
+ {value: 0x0000, lo: 0x06},
+ {value: 0x1308, lo: 0x80, hi: 0x81},
+ {value: 0x1008, lo: 0x82, hi: 0x82},
+ {value: 0x0008, lo: 0x83, hi: 0xb2},
+ {value: 0x1008, lo: 0xb3, hi: 0xb5},
+ {value: 0x1308, lo: 0xb6, hi: 0xbe},
+ {value: 0x1008, lo: 0xbf, hi: 0xbf},
+ // Block 0xb1, offset 0x553
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x1808, lo: 0x80, hi: 0x80},
+ {value: 0x0008, lo: 0x81, hi: 0x84},
+ {value: 0x0018, lo: 0x85, hi: 0x89},
+ {value: 0x1308, lo: 0x8a, hi: 0x8c},
+ {value: 0x0018, lo: 0x8d, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x9a},
+ {value: 0x0018, lo: 0x9b, hi: 0x9b},
+ {value: 0x0008, lo: 0x9c, hi: 0x9c},
+ {value: 0x0018, lo: 0x9d, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xa0},
+ {value: 0x0018, lo: 0xa1, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xbf},
+ // Block 0xb2, offset 0x561
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0008, lo: 0x80, hi: 0x91},
+ {value: 0x0040, lo: 0x92, hi: 0x92},
+ {value: 0x0008, lo: 0x93, hi: 0xab},
+ {value: 0x1008, lo: 0xac, hi: 0xae},
+ {value: 0x1308, lo: 0xaf, hi: 0xb1},
+ {value: 0x1008, lo: 0xb2, hi: 0xb3},
+ {value: 0x1308, lo: 0xb4, hi: 0xb4},
+ {value: 0x1808, lo: 0xb5, hi: 0xb5},
+ {value: 0x1308, lo: 0xb6, hi: 0xb7},
+ {value: 0x0018, lo: 0xb8, hi: 0xbd},
+ {value: 0x1308, lo: 0xbe, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0xb3, offset 0x56e
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x87},
+ {value: 0x0008, lo: 0x88, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x89},
+ {value: 0x0008, lo: 0x8a, hi: 0x8d},
+ {value: 0x0040, lo: 0x8e, hi: 0x8e},
+ {value: 0x0008, lo: 0x8f, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0x9e},
+ {value: 0x0008, lo: 0x9f, hi: 0xa8},
+ {value: 0x0018, lo: 0xa9, hi: 0xa9},
+ {value: 0x0040, lo: 0xaa, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbf},
+ // Block 0xb4, offset 0x57b
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0008, lo: 0x80, hi: 0x9e},
+ {value: 0x1308, lo: 0x9f, hi: 0x9f},
+ {value: 0x1008, lo: 0xa0, hi: 0xa2},
+ {value: 0x1308, lo: 0xa3, hi: 0xa9},
+ {value: 0x1b08, lo: 0xaa, hi: 0xaa},
+ {value: 0x0040, lo: 0xab, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb9},
+ {value: 0x0040, lo: 0xba, hi: 0xbf},
+ // Block 0xb5, offset 0x584
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xb4},
+ {value: 0x1008, lo: 0xb5, hi: 0xb7},
+ {value: 0x1308, lo: 0xb8, hi: 0xbf},
+ // Block 0xb6, offset 0x588
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x1008, lo: 0x80, hi: 0x81},
+ {value: 0x1b08, lo: 0x82, hi: 0x82},
+ {value: 0x1308, lo: 0x83, hi: 0x84},
+ {value: 0x1008, lo: 0x85, hi: 0x85},
+ {value: 0x1308, lo: 0x86, hi: 0x86},
+ {value: 0x0008, lo: 0x87, hi: 0x8a},
+ {value: 0x0018, lo: 0x8b, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9a},
+ {value: 0x0018, lo: 0x9b, hi: 0x9b},
+ {value: 0x0040, lo: 0x9c, hi: 0x9c},
+ {value: 0x0018, lo: 0x9d, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0xbf},
+ // Block 0xb7, offset 0x596
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0xaf},
+ {value: 0x1008, lo: 0xb0, hi: 0xb2},
+ {value: 0x1308, lo: 0xb3, hi: 0xb8},
+ {value: 0x1008, lo: 0xb9, hi: 0xb9},
+ {value: 0x1308, lo: 0xba, hi: 0xba},
+ {value: 0x1008, lo: 0xbb, hi: 0xbe},
+ {value: 0x1308, lo: 0xbf, hi: 0xbf},
+ // Block 0xb8, offset 0x59e
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x1308, lo: 0x80, hi: 0x80},
+ {value: 0x1008, lo: 0x81, hi: 0x81},
+ {value: 0x1b08, lo: 0x82, hi: 0x82},
+ {value: 0x1308, lo: 0x83, hi: 0x83},
+ {value: 0x0008, lo: 0x84, hi: 0x85},
+ {value: 0x0018, lo: 0x86, hi: 0x86},
+ {value: 0x0008, lo: 0x87, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0xbf},
+ // Block 0xb9, offset 0x5a9
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0008, lo: 0x80, hi: 0xae},
+ {value: 0x1008, lo: 0xaf, hi: 0xb1},
+ {value: 0x1308, lo: 0xb2, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xb7},
+ {value: 0x1008, lo: 0xb8, hi: 0xbb},
+ {value: 0x1308, lo: 0xbc, hi: 0xbd},
+ {value: 0x1008, lo: 0xbe, hi: 0xbe},
+ {value: 0x1b08, lo: 0xbf, hi: 0xbf},
+ // Block 0xba, offset 0x5b2
+ {value: 0x0000, lo: 0x05},
+ {value: 0x1308, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0x97},
+ {value: 0x0008, lo: 0x98, hi: 0x9b},
+ {value: 0x1308, lo: 0x9c, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0xbf},
+ // Block 0xbb, offset 0x5b8
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0008, lo: 0x80, hi: 0xaf},
+ {value: 0x1008, lo: 0xb0, hi: 0xb2},
+ {value: 0x1308, lo: 0xb3, hi: 0xba},
+ {value: 0x1008, lo: 0xbb, hi: 0xbc},
+ {value: 0x1308, lo: 0xbd, hi: 0xbd},
+ {value: 0x1008, lo: 0xbe, hi: 0xbe},
+ {value: 0x1b08, lo: 0xbf, hi: 0xbf},
+ // Block 0xbc, offset 0x5c0
+ {value: 0x0000, lo: 0x08},
+ {value: 0x1308, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0x83},
+ {value: 0x0008, lo: 0x84, hi: 0x84},
+ {value: 0x0040, lo: 0x85, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xac},
+ {value: 0x0040, lo: 0xad, hi: 0xbf},
+ // Block 0xbd, offset 0x5c9
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0xaa},
+ {value: 0x1308, lo: 0xab, hi: 0xab},
+ {value: 0x1008, lo: 0xac, hi: 0xac},
+ {value: 0x1308, lo: 0xad, hi: 0xad},
+ {value: 0x1008, lo: 0xae, hi: 0xaf},
+ {value: 0x1308, lo: 0xb0, hi: 0xb5},
+ {value: 0x1808, lo: 0xb6, hi: 0xb6},
+ {value: 0x1308, lo: 0xb7, hi: 0xb7},
+ {value: 0x0040, lo: 0xb8, hi: 0xbf},
+ // Block 0xbe, offset 0x5d3
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x89},
+ {value: 0x0040, lo: 0x8a, hi: 0xbf},
+ // Block 0xbf, offset 0x5d6
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9c},
+ {value: 0x1308, lo: 0x9d, hi: 0x9f},
+ {value: 0x1008, lo: 0xa0, hi: 0xa1},
+ {value: 0x1308, lo: 0xa2, hi: 0xa5},
+ {value: 0x1008, lo: 0xa6, hi: 0xa6},
+ {value: 0x1308, lo: 0xa7, hi: 0xaa},
+ {value: 0x1b08, lo: 0xab, hi: 0xab},
+ {value: 0x0040, lo: 0xac, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xb9},
+ {value: 0x0018, lo: 0xba, hi: 0xbf},
+ // Block 0xc0, offset 0x5e2
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0040, lo: 0x80, hi: 0x9f},
+ {value: 0x049d, lo: 0xa0, hi: 0xbf},
+ // Block 0xc1, offset 0x5e5
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0xa9},
+ {value: 0x0018, lo: 0xaa, hi: 0xb2},
+ {value: 0x0040, lo: 0xb3, hi: 0xbe},
+ {value: 0x0008, lo: 0xbf, hi: 0xbf},
+ // Block 0xc2, offset 0x5ea
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xb8},
+ {value: 0x0040, lo: 0xb9, hi: 0xbf},
+ // Block 0xc3, offset 0x5ed
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x89},
+ {value: 0x0008, lo: 0x8a, hi: 0xae},
+ {value: 0x1008, lo: 0xaf, hi: 0xaf},
+ {value: 0x1308, lo: 0xb0, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xb7},
+ {value: 0x1308, lo: 0xb8, hi: 0xbd},
+ {value: 0x1008, lo: 0xbe, hi: 0xbe},
+ {value: 0x1b08, lo: 0xbf, hi: 0xbf},
+ // Block 0xc4, offset 0x5f7
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0008, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0x85},
+ {value: 0x0040, lo: 0x86, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0018, lo: 0x9a, hi: 0xac},
+ {value: 0x0040, lo: 0xad, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb1},
+ {value: 0x0008, lo: 0xb2, hi: 0xbf},
+ // Block 0xc5, offset 0x600
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0008, lo: 0x80, hi: 0x8f},
+ {value: 0x0040, lo: 0x90, hi: 0x91},
+ {value: 0x1308, lo: 0x92, hi: 0xa7},
+ {value: 0x0040, lo: 0xa8, hi: 0xa8},
+ {value: 0x1008, lo: 0xa9, hi: 0xa9},
+ {value: 0x1308, lo: 0xaa, hi: 0xb0},
+ {value: 0x1008, lo: 0xb1, hi: 0xb1},
+ {value: 0x1308, lo: 0xb2, hi: 0xb3},
+ {value: 0x1008, lo: 0xb4, hi: 0xb4},
+ {value: 0x1308, lo: 0xb5, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xbf},
+ // Block 0xc6, offset 0x60c
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0xbf},
+ // Block 0xc7, offset 0x60f
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xbf},
+ // Block 0xc8, offset 0x614
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x83},
+ {value: 0x0040, lo: 0x84, hi: 0xbf},
+ // Block 0xc9, offset 0x617
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xbf},
+ // Block 0xca, offset 0x61a
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0xbf},
+ // Block 0xcb, offset 0x61d
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0008, lo: 0x80, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa9},
+ {value: 0x0040, lo: 0xaa, hi: 0xad},
+ {value: 0x0018, lo: 0xae, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xbf},
+ // Block 0xcc, offset 0x624
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0040, lo: 0x80, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xaf},
+ {value: 0x1308, lo: 0xb0, hi: 0xb4},
+ {value: 0x0018, lo: 0xb5, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xbf},
+ // Block 0xcd, offset 0x62b
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0xaf},
+ {value: 0x1308, lo: 0xb0, hi: 0xb6},
+ {value: 0x0018, lo: 0xb7, hi: 0xbf},
+ // Block 0xce, offset 0x62f
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x0008, lo: 0x80, hi: 0x83},
+ {value: 0x0018, lo: 0x84, hi: 0x85},
+ {value: 0x0040, lo: 0x86, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9a},
+ {value: 0x0018, lo: 0x9b, hi: 0xa1},
+ {value: 0x0040, lo: 0xa2, hi: 0xa2},
+ {value: 0x0008, lo: 0xa3, hi: 0xb7},
+ {value: 0x0040, lo: 0xb8, hi: 0xbc},
+ {value: 0x0008, lo: 0xbd, hi: 0xbf},
+ // Block 0xcf, offset 0x63a
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x8f},
+ {value: 0x0040, lo: 0x90, hi: 0xbf},
+ // Block 0xd0, offset 0x63d
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0x84},
+ {value: 0x0040, lo: 0x85, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x90},
+ {value: 0x1008, lo: 0x91, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0xd1, offset 0x643
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0040, lo: 0x80, hi: 0x8e},
+ {value: 0x1308, lo: 0x8f, hi: 0x92},
+ {value: 0x0008, lo: 0x93, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xbf},
+ // Block 0xd2, offset 0x648
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0040, lo: 0x80, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xa0},
+ {value: 0x0040, lo: 0xa1, hi: 0xbf},
+ // Block 0xd3, offset 0x64c
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xac},
+ {value: 0x0040, lo: 0xad, hi: 0xbf},
+ // Block 0xd4, offset 0x64f
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xb2},
+ {value: 0x0040, lo: 0xb3, hi: 0xbf},
+ // Block 0xd5, offset 0x652
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x81},
+ {value: 0x0040, lo: 0x82, hi: 0xbf},
+ // Block 0xd6, offset 0x655
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0008, lo: 0x80, hi: 0xaa},
+ {value: 0x0040, lo: 0xab, hi: 0xaf},
+ {value: 0x0008, lo: 0xb0, hi: 0xbc},
+ {value: 0x0040, lo: 0xbd, hi: 0xbf},
+ // Block 0xd7, offset 0x65a
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0008, lo: 0x80, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9b},
+ {value: 0x0018, lo: 0x9c, hi: 0x9c},
+ {value: 0x1308, lo: 0x9d, hi: 0x9e},
+ {value: 0x0018, lo: 0x9f, hi: 0x9f},
+ {value: 0x03c0, lo: 0xa0, hi: 0xa3},
+ {value: 0x0040, lo: 0xa4, hi: 0xbf},
+ // Block 0xd8, offset 0x664
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xbf},
+ // Block 0xd9, offset 0x667
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0xa6},
+ {value: 0x0040, lo: 0xa7, hi: 0xa8},
+ {value: 0x0018, lo: 0xa9, hi: 0xbf},
+ // Block 0xda, offset 0x66b
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x0018, lo: 0x80, hi: 0x9d},
+ {value: 0xb5b9, lo: 0x9e, hi: 0x9e},
+ {value: 0xb601, lo: 0x9f, hi: 0x9f},
+ {value: 0xb649, lo: 0xa0, hi: 0xa0},
+ {value: 0xb6b1, lo: 0xa1, hi: 0xa1},
+ {value: 0xb719, lo: 0xa2, hi: 0xa2},
+ {value: 0xb781, lo: 0xa3, hi: 0xa3},
+ {value: 0xb7e9, lo: 0xa4, hi: 0xa4},
+ {value: 0x1018, lo: 0xa5, hi: 0xa6},
+ {value: 0x1318, lo: 0xa7, hi: 0xa9},
+ {value: 0x0018, lo: 0xaa, hi: 0xac},
+ {value: 0x1018, lo: 0xad, hi: 0xb2},
+ {value: 0x0340, lo: 0xb3, hi: 0xba},
+ {value: 0x1318, lo: 0xbb, hi: 0xbf},
+ // Block 0xdb, offset 0x67a
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x1318, lo: 0x80, hi: 0x82},
+ {value: 0x0018, lo: 0x83, hi: 0x84},
+ {value: 0x1318, lo: 0x85, hi: 0x8b},
+ {value: 0x0018, lo: 0x8c, hi: 0xa9},
+ {value: 0x1318, lo: 0xaa, hi: 0xad},
+ {value: 0x0018, lo: 0xae, hi: 0xba},
+ {value: 0xb851, lo: 0xbb, hi: 0xbb},
+ {value: 0xb899, lo: 0xbc, hi: 0xbc},
+ {value: 0xb8e1, lo: 0xbd, hi: 0xbd},
+ {value: 0xb949, lo: 0xbe, hi: 0xbe},
+ {value: 0xb9b1, lo: 0xbf, hi: 0xbf},
+ // Block 0xdc, offset 0x686
+ {value: 0x0000, lo: 0x03},
+ {value: 0xba19, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0xa8},
+ {value: 0x0040, lo: 0xa9, hi: 0xbf},
+ // Block 0xdd, offset 0x68a
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x81},
+ {value: 0x1318, lo: 0x82, hi: 0x84},
+ {value: 0x0018, lo: 0x85, hi: 0x85},
+ {value: 0x0040, lo: 0x86, hi: 0xbf},
+ // Block 0xde, offset 0x68f
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xb1},
+ {value: 0x0040, lo: 0xb2, hi: 0xbf},
+ // Block 0xdf, offset 0x694
+ {value: 0x0000, lo: 0x03},
+ {value: 0x1308, lo: 0x80, hi: 0xb6},
+ {value: 0x0018, lo: 0xb7, hi: 0xba},
+ {value: 0x1308, lo: 0xbb, hi: 0xbf},
+ // Block 0xe0, offset 0x698
+ {value: 0x0000, lo: 0x04},
+ {value: 0x1308, lo: 0x80, hi: 0xac},
+ {value: 0x0018, lo: 0xad, hi: 0xb4},
+ {value: 0x1308, lo: 0xb5, hi: 0xb5},
+ {value: 0x0018, lo: 0xb6, hi: 0xbf},
+ // Block 0xe1, offset 0x69d
+ {value: 0x0000, lo: 0x08},
+ {value: 0x0018, lo: 0x80, hi: 0x83},
+ {value: 0x1308, lo: 0x84, hi: 0x84},
+ {value: 0x0018, lo: 0x85, hi: 0x8b},
+ {value: 0x0040, lo: 0x8c, hi: 0x9a},
+ {value: 0x1308, lo: 0x9b, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xa0},
+ {value: 0x1308, lo: 0xa1, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xbf},
+ // Block 0xe2, offset 0x6a6
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x1308, lo: 0x80, hi: 0x86},
+ {value: 0x0040, lo: 0x87, hi: 0x87},
+ {value: 0x1308, lo: 0x88, hi: 0x98},
+ {value: 0x0040, lo: 0x99, hi: 0x9a},
+ {value: 0x1308, lo: 0x9b, hi: 0xa1},
+ {value: 0x0040, lo: 0xa2, hi: 0xa2},
+ {value: 0x1308, lo: 0xa3, hi: 0xa4},
+ {value: 0x0040, lo: 0xa5, hi: 0xa5},
+ {value: 0x1308, lo: 0xa6, hi: 0xaa},
+ {value: 0x0040, lo: 0xab, hi: 0xbf},
+ // Block 0xe3, offset 0x6b1
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0008, lo: 0x80, hi: 0x84},
+ {value: 0x0040, lo: 0x85, hi: 0x86},
+ {value: 0x0018, lo: 0x87, hi: 0x8f},
+ {value: 0x1308, lo: 0x90, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0xbf},
+ // Block 0xe4, offset 0x6b7
+ {value: 0x0000, lo: 0x07},
+ {value: 0x0208, lo: 0x80, hi: 0x83},
+ {value: 0x1308, lo: 0x84, hi: 0x8a},
+ {value: 0x0040, lo: 0x8b, hi: 0x8f},
+ {value: 0x0008, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9d},
+ {value: 0x0018, lo: 0x9e, hi: 0x9f},
+ {value: 0x0040, lo: 0xa0, hi: 0xbf},
+ // Block 0xe5, offset 0x6bf
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0040, lo: 0x80, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb1},
+ {value: 0x0040, lo: 0xb2, hi: 0xbf},
+ // Block 0xe6, offset 0x6c3
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0xab},
+ {value: 0x0040, lo: 0xac, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xbf},
+ // Block 0xe7, offset 0x6c7
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0018, lo: 0x80, hi: 0x93},
+ {value: 0x0040, lo: 0x94, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xae},
+ {value: 0x0040, lo: 0xaf, hi: 0xb0},
+ {value: 0x0018, lo: 0xb1, hi: 0xbf},
+ // Block 0xe8, offset 0x6cd
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0040, lo: 0x80, hi: 0x80},
+ {value: 0x0018, lo: 0x81, hi: 0x8f},
+ {value: 0x0040, lo: 0x90, hi: 0x90},
+ {value: 0x0018, lo: 0x91, hi: 0xb5},
+ {value: 0x0040, lo: 0xb6, hi: 0xbf},
+ // Block 0xe9, offset 0x6d3
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x8f},
+ {value: 0xc1c1, lo: 0x90, hi: 0x90},
+ {value: 0x0018, lo: 0x91, hi: 0xac},
+ {value: 0x0040, lo: 0xad, hi: 0xbf},
+ // Block 0xea, offset 0x6d8
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0040, lo: 0x80, hi: 0xa5},
+ {value: 0x0018, lo: 0xa6, hi: 0xbf},
+ // Block 0xeb, offset 0x6db
+ {value: 0x0000, lo: 0x0d},
+ {value: 0xc7e9, lo: 0x80, hi: 0x80},
+ {value: 0xc839, lo: 0x81, hi: 0x81},
+ {value: 0xc889, lo: 0x82, hi: 0x82},
+ {value: 0xc8d9, lo: 0x83, hi: 0x83},
+ {value: 0xc929, lo: 0x84, hi: 0x84},
+ {value: 0xc979, lo: 0x85, hi: 0x85},
+ {value: 0xc9c9, lo: 0x86, hi: 0x86},
+ {value: 0xca19, lo: 0x87, hi: 0x87},
+ {value: 0xca69, lo: 0x88, hi: 0x88},
+ {value: 0x0040, lo: 0x89, hi: 0x8f},
+ {value: 0xcab9, lo: 0x90, hi: 0x90},
+ {value: 0xcad9, lo: 0x91, hi: 0x91},
+ {value: 0x0040, lo: 0x92, hi: 0xbf},
+ // Block 0xec, offset 0x6e9
+ {value: 0x0000, lo: 0x06},
+ {value: 0x0018, lo: 0x80, hi: 0x92},
+ {value: 0x0040, lo: 0x93, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xac},
+ {value: 0x0040, lo: 0xad, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb6},
+ {value: 0x0040, lo: 0xb7, hi: 0xbf},
+ // Block 0xed, offset 0x6f0
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0xb3},
+ {value: 0x0040, lo: 0xb4, hi: 0xbf},
+ // Block 0xee, offset 0x6f3
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0x94},
+ {value: 0x0040, lo: 0x95, hi: 0xbf},
+ // Block 0xef, offset 0x6f6
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0018, lo: 0x80, hi: 0x8b},
+ {value: 0x0040, lo: 0x8c, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0xbf},
+ // Block 0xf0, offset 0x6fa
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0018, lo: 0x80, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0x99},
+ {value: 0x0040, lo: 0x9a, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xbf},
+ // Block 0xf1, offset 0x700
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x87},
+ {value: 0x0040, lo: 0x88, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0xad},
+ {value: 0x0040, lo: 0xae, hi: 0xbf},
+ // Block 0xf2, offset 0x705
+ {value: 0x0000, lo: 0x09},
+ {value: 0x0040, lo: 0x80, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0x9f},
+ {value: 0x0018, lo: 0xa0, hi: 0xa7},
+ {value: 0x0040, lo: 0xa8, hi: 0xaf},
+ {value: 0x0018, lo: 0xb0, hi: 0xb0},
+ {value: 0x0040, lo: 0xb1, hi: 0xb2},
+ {value: 0x0018, lo: 0xb3, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0xf3, offset 0x70f
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0018, lo: 0x80, hi: 0x8b},
+ {value: 0x0040, lo: 0x8c, hi: 0x8f},
+ {value: 0x0018, lo: 0x90, hi: 0x9e},
+ {value: 0x0040, lo: 0x9f, hi: 0xbf},
+ // Block 0xf4, offset 0x714
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0x91},
+ {value: 0x0040, lo: 0x92, hi: 0xbf},
+ // Block 0xf5, offset 0x717
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0018, lo: 0x80, hi: 0x80},
+ {value: 0x0040, lo: 0x81, hi: 0xbf},
+ // Block 0xf6, offset 0x71a
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0x96},
+ {value: 0x0040, lo: 0x97, hi: 0xbf},
+ // Block 0xf7, offset 0x71d
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xb4},
+ {value: 0x0040, lo: 0xb5, hi: 0xbf},
+ // Block 0xf8, offset 0x720
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0008, lo: 0x80, hi: 0x9d},
+ {value: 0x0040, lo: 0x9e, hi: 0x9f},
+ {value: 0x0008, lo: 0xa0, hi: 0xbf},
+ // Block 0xf9, offset 0x724
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0008, lo: 0x80, hi: 0xa1},
+ {value: 0x0040, lo: 0xa2, hi: 0xbf},
+ // Block 0xfa, offset 0x727
+ {value: 0x0020, lo: 0x0f},
+ {value: 0xdeb9, lo: 0x80, hi: 0x89},
+ {value: 0x8dfd, lo: 0x8a, hi: 0x8a},
+ {value: 0xdff9, lo: 0x8b, hi: 0x9c},
+ {value: 0x8e1d, lo: 0x9d, hi: 0x9d},
+ {value: 0xe239, lo: 0x9e, hi: 0xa2},
+ {value: 0x8e3d, lo: 0xa3, hi: 0xa3},
+ {value: 0xe2d9, lo: 0xa4, hi: 0xab},
+ {value: 0x7ed5, lo: 0xac, hi: 0xac},
+ {value: 0xe3d9, lo: 0xad, hi: 0xaf},
+ {value: 0x8e5d, lo: 0xb0, hi: 0xb0},
+ {value: 0xe439, lo: 0xb1, hi: 0xb6},
+ {value: 0x8e7d, lo: 0xb7, hi: 0xb9},
+ {value: 0xe4f9, lo: 0xba, hi: 0xba},
+ {value: 0x8edd, lo: 0xbb, hi: 0xbb},
+ {value: 0xe519, lo: 0xbc, hi: 0xbf},
+ // Block 0xfb, offset 0x737
+ {value: 0x0020, lo: 0x10},
+ {value: 0x937d, lo: 0x80, hi: 0x80},
+ {value: 0xf099, lo: 0x81, hi: 0x86},
+ {value: 0x939d, lo: 0x87, hi: 0x8a},
+ {value: 0xd9f9, lo: 0x8b, hi: 0x8b},
+ {value: 0xf159, lo: 0x8c, hi: 0x96},
+ {value: 0x941d, lo: 0x97, hi: 0x97},
+ {value: 0xf2b9, lo: 0x98, hi: 0xa3},
+ {value: 0x943d, lo: 0xa4, hi: 0xa6},
+ {value: 0xf439, lo: 0xa7, hi: 0xaa},
+ {value: 0x949d, lo: 0xab, hi: 0xab},
+ {value: 0xf4b9, lo: 0xac, hi: 0xac},
+ {value: 0x94bd, lo: 0xad, hi: 0xad},
+ {value: 0xf4d9, lo: 0xae, hi: 0xaf},
+ {value: 0x94dd, lo: 0xb0, hi: 0xb1},
+ {value: 0xf519, lo: 0xb2, hi: 0xbe},
+ {value: 0x0040, lo: 0xbf, hi: 0xbf},
+ // Block 0xfc, offset 0x748
+ {value: 0x0000, lo: 0x04},
+ {value: 0x0040, lo: 0x80, hi: 0x80},
+ {value: 0x0340, lo: 0x81, hi: 0x81},
+ {value: 0x0040, lo: 0x82, hi: 0x9f},
+ {value: 0x0340, lo: 0xa0, hi: 0xbf},
+ // Block 0xfd, offset 0x74d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0340, lo: 0x80, hi: 0xbf},
+ // Block 0xfe, offset 0x74f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x13c0, lo: 0x80, hi: 0xbf},
+ // Block 0xff, offset 0x751
+ {value: 0x0000, lo: 0x02},
+ {value: 0x13c0, lo: 0x80, hi: 0xaf},
+ {value: 0x0040, lo: 0xb0, hi: 0xbf},
+}
+
+// Total table size 41559 bytes (40KiB); checksum: F4A1FA4E
diff --git a/vendor/golang.org/x/net/idna/trie.go b/vendor/golang.org/x/net/idna/trie.go
new file mode 100644
index 0000000..c4ef847
--- /dev/null
+++ b/vendor/golang.org/x/net/idna/trie.go
@@ -0,0 +1,72 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package idna
+
+// appendMapping appends the mapping for the respective rune. isMapped must be
+// true. A mapping is a categorization of a rune as defined in UTS #46.
+func (c info) appendMapping(b []byte, s string) []byte {
+ index := int(c >> indexShift)
+ if c&xorBit == 0 {
+ s := mappings[index:]
+ return append(b, s[1:s[0]+1]...)
+ }
+ b = append(b, s...)
+ if c&inlineXOR == inlineXOR {
+ // TODO: support and handle two-byte inline masks
+ b[len(b)-1] ^= byte(index)
+ } else {
+ for p := len(b) - int(xorData[index]); p < len(b); p++ {
+ index++
+ b[p] ^= xorData[index]
+ }
+ }
+ return b
+}
+
+// Sparse block handling code.
+
+type valueRange struct {
+ value uint16 // header: value:stride
+ lo, hi byte // header: lo:n
+}
+
+type sparseBlocks struct {
+ values []valueRange
+ offset []uint16
+}
+
+var idnaSparse = sparseBlocks{
+ values: idnaSparseValues[:],
+ offset: idnaSparseOffset[:],
+}
+
+// Don't use newIdnaTrie to avoid unconditional linking in of the table.
+var trie = &idnaTrie{}
+
+// lookup determines the type of block n and looks up the value for b.
+// For n < t.cutoff, the block is a simple lookup table. Otherwise, the block
+// is a list of ranges with an accompanying value. Given a matching range r,
+// the value for b is by r.value + (b - r.lo) * stride.
+func (t *sparseBlocks) lookup(n uint32, b byte) uint16 {
+ offset := t.offset[n]
+ header := t.values[offset]
+ lo := offset + 1
+ hi := lo + uint16(header.lo)
+ for lo < hi {
+ m := lo + (hi-lo)/2
+ r := t.values[m]
+ if r.lo <= b && b <= r.hi {
+ return r.value + uint16(b-r.lo)*header.value
+ }
+ if b < r.lo {
+ hi = m
+ } else {
+ lo = m + 1
+ }
+ }
+ return 0
+}
diff --git a/vendor/golang.org/x/net/idna/trieval.go b/vendor/golang.org/x/net/idna/trieval.go
new file mode 100644
index 0000000..63cb03b
--- /dev/null
+++ b/vendor/golang.org/x/net/idna/trieval.go
@@ -0,0 +1,114 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package idna
+
+// This file contains definitions for interpreting the trie value of the idna
+// trie generated by "go run gen*.go". It is shared by both the generator
+// program and the resultant package. Sharing is achieved by the generator
+// copying gen_trieval.go to trieval.go and changing what's above this comment.
+
+// info holds information from the IDNA mapping table for a single rune. It is
+// the value returned by a trie lookup. In most cases, all information fits in
+// a 16-bit value. For mappings, this value may contain an index into a slice
+// with the mapped string. Such mappings can consist of the actual mapped value
+// or an XOR pattern to be applied to the bytes of the UTF8 encoding of the
+// input rune. This technique is used by the cases packages and reduces the
+// table size significantly.
+//
+// The per-rune values have the following format:
+//
+// if mapped {
+// if inlinedXOR {
+// 15..13 inline XOR marker
+// 12..11 unused
+// 10..3 inline XOR mask
+// } else {
+// 15..3 index into xor or mapping table
+// }
+// } else {
+// 15..13 unused
+// 12 modifier (including virama)
+// 11 virama modifier
+// 10..8 joining type
+// 7..3 category type
+// }
+// 2 use xor pattern
+// 1..0 mapped category
+//
+// See the definitions below for a more detailed description of the various
+// bits.
+type info uint16
+
+const (
+ catSmallMask = 0x3
+ catBigMask = 0xF8
+ indexShift = 3
+ xorBit = 0x4 // interpret the index as an xor pattern
+ inlineXOR = 0xE000 // These bits are set if the XOR pattern is inlined.
+
+ joinShift = 8
+ joinMask = 0x07
+
+ viramaModifier = 0x0800
+ modifier = 0x1000
+)
+
+// A category corresponds to a category defined in the IDNA mapping table.
+type category uint16
+
+const (
+ unknown category = 0 // not defined currently in unicode.
+ mapped category = 1
+ disallowedSTD3Mapped category = 2
+ deviation category = 3
+)
+
+const (
+ valid category = 0x08
+ validNV8 category = 0x18
+ validXV8 category = 0x28
+ disallowed category = 0x40
+ disallowedSTD3Valid category = 0x80
+ ignored category = 0xC0
+)
+
+// join types and additional rune information
+const (
+ joiningL = (iota + 1)
+ joiningD
+ joiningT
+ joiningR
+
+ //the following types are derived during processing
+ joinZWJ
+ joinZWNJ
+ joinVirama
+ numJoinTypes
+)
+
+func (c info) isMapped() bool {
+ return c&0x3 != 0
+}
+
+func (c info) category() category {
+ small := c & catSmallMask
+ if small != 0 {
+ return category(small)
+ }
+ return category(c & catBigMask)
+}
+
+func (c info) joinType() info {
+ if c.isMapped() {
+ return 0
+ }
+ return (c >> joinShift) & joinMask
+}
+
+func (c info) isModifier() bool {
+ return c&(modifier|catSmallMask) == modifier
+}
+
+func (c info) isViramaModifier() bool {
+ return c&(viramaModifier|catSmallMask) == viramaModifier
+}
diff --git a/cmd/gost/vendor/golang.org/x/net/internal/iana/const.go b/vendor/golang.org/x/net/internal/iana/const.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/internal/iana/const.go
rename to vendor/golang.org/x/net/internal/iana/const.go
diff --git a/cmd/gost/vendor/golang.org/x/net/internal/iana/gen.go b/vendor/golang.org/x/net/internal/iana/gen.go
similarity index 99%
rename from cmd/gost/vendor/golang.org/x/net/internal/iana/gen.go
rename to vendor/golang.org/x/net/internal/iana/gen.go
index 2d8c07c..86c78b3 100644
--- a/cmd/gost/vendor/golang.org/x/net/internal/iana/gen.go
+++ b/vendor/golang.org/x/net/internal/iana/gen.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/internal/netreflect/socket.go b/vendor/golang.org/x/net/internal/netreflect/socket.go
similarity index 92%
rename from cmd/gost/vendor/golang.org/x/net/internal/netreflect/socket.go
rename to vendor/golang.org/x/net/internal/netreflect/socket.go
index e82e51c..1495b65 100644
--- a/cmd/gost/vendor/golang.org/x/net/internal/netreflect/socket.go
+++ b/vendor/golang.org/x/net/internal/netreflect/socket.go
@@ -2,8 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build !go1.9
+
// Package netreflect implements run-time reflection for the
// facilities of net package.
+//
+// This package works only for Go 1.8 or below.
package netreflect
import (
diff --git a/vendor/golang.org/x/net/internal/netreflect/socket_19.go b/vendor/golang.org/x/net/internal/netreflect/socket_19.go
new file mode 100644
index 0000000..74df52e
--- /dev/null
+++ b/vendor/golang.org/x/net/internal/netreflect/socket_19.go
@@ -0,0 +1,37 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.9
+
+package netreflect
+
+import (
+ "errors"
+ "net"
+)
+
+var (
+ errInvalidType = errors.New("invalid type")
+ errOpNoSupport = errors.New("operation not supported")
+)
+
+// SocketOf returns the socket descriptor of c.
+func SocketOf(c net.Conn) (uintptr, error) {
+ switch c.(type) {
+ case *net.TCPConn, *net.UDPConn, *net.IPConn, *net.UnixConn:
+ return 0, errOpNoSupport
+ default:
+ return 0, errInvalidType
+ }
+}
+
+// PacketSocketOf returns the socket descriptor of c.
+func PacketSocketOf(c net.PacketConn) (uintptr, error) {
+ switch c.(type) {
+ case *net.UDPConn, *net.IPConn, *net.UnixConn:
+ return 0, errOpNoSupport
+ default:
+ return 0, errInvalidType
+ }
+}
diff --git a/cmd/gost/vendor/golang.org/x/net/internal/netreflect/socket_posix.go b/vendor/golang.org/x/net/internal/netreflect/socket_posix.go
similarity index 97%
rename from cmd/gost/vendor/golang.org/x/net/internal/netreflect/socket_posix.go
rename to vendor/golang.org/x/net/internal/netreflect/socket_posix.go
index df475a2..410c092 100644
--- a/cmd/gost/vendor/golang.org/x/net/internal/netreflect/socket_posix.go
+++ b/vendor/golang.org/x/net/internal/netreflect/socket_posix.go
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build !go1.9
// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
package netreflect
diff --git a/cmd/gost/vendor/golang.org/x/net/internal/netreflect/socket_stub.go b/vendor/golang.org/x/net/internal/netreflect/socket_stub.go
similarity index 95%
rename from cmd/gost/vendor/golang.org/x/net/internal/netreflect/socket_stub.go
rename to vendor/golang.org/x/net/internal/netreflect/socket_stub.go
index 85adb4b..17b20c4 100644
--- a/cmd/gost/vendor/golang.org/x/net/internal/netreflect/socket_stub.go
+++ b/vendor/golang.org/x/net/internal/netreflect/socket_stub.go
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build !go1.9
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
package netreflect
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/bpfopt_linux.go b/vendor/golang.org/x/net/ipv4/bpfopt_linux.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/bpfopt_linux.go
rename to vendor/golang.org/x/net/ipv4/bpfopt_linux.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/bpfopt_stub.go b/vendor/golang.org/x/net/ipv4/bpfopt_stub.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/bpfopt_stub.go
rename to vendor/golang.org/x/net/ipv4/bpfopt_stub.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/control.go b/vendor/golang.org/x/net/ipv4/control.go
similarity index 97%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/control.go
rename to vendor/golang.org/x/net/ipv4/control.go
index 8cadfd7..da4da2d 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/control.go
+++ b/vendor/golang.org/x/net/ipv4/control.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/control_bsd.go b/vendor/golang.org/x/net/ipv4/control_bsd.go
similarity index 94%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/control_bsd.go
rename to vendor/golang.org/x/net/ipv4/control_bsd.go
index 33d8bc8..3f27f99 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/control_bsd.go
+++ b/vendor/golang.org/x/net/ipv4/control_bsd.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/control_pktinfo.go b/vendor/golang.org/x/net/ipv4/control_pktinfo.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/control_pktinfo.go
rename to vendor/golang.org/x/net/ipv4/control_pktinfo.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/control_stub.go b/vendor/golang.org/x/net/ipv4/control_stub.go
similarity index 89%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/control_stub.go
rename to vendor/golang.org/x/net/ipv4/control_stub.go
index 88602c3..27e618b 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/control_stub.go
+++ b/vendor/golang.org/x/net/ipv4/control_stub.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/control_unix.go b/vendor/golang.org/x/net/ipv4/control_unix.go
similarity index 98%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/control_unix.go
rename to vendor/golang.org/x/net/ipv4/control_unix.go
index 211f4b4..25ef661 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/control_unix.go
+++ b/vendor/golang.org/x/net/ipv4/control_unix.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/control_windows.go b/vendor/golang.org/x/net/ipv4/control_windows.go
similarity index 91%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/control_windows.go
rename to vendor/golang.org/x/net/ipv4/control_windows.go
index 49a113b..b27407d 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/control_windows.go
+++ b/vendor/golang.org/x/net/ipv4/control_windows.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/defs_darwin.go b/vendor/golang.org/x/net/ipv4/defs_darwin.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/defs_darwin.go
rename to vendor/golang.org/x/net/ipv4/defs_darwin.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/defs_dragonfly.go b/vendor/golang.org/x/net/ipv4/defs_dragonfly.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/defs_dragonfly.go
rename to vendor/golang.org/x/net/ipv4/defs_dragonfly.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/defs_freebsd.go b/vendor/golang.org/x/net/ipv4/defs_freebsd.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/defs_freebsd.go
rename to vendor/golang.org/x/net/ipv4/defs_freebsd.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/defs_linux.go b/vendor/golang.org/x/net/ipv4/defs_linux.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/defs_linux.go
rename to vendor/golang.org/x/net/ipv4/defs_linux.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/defs_netbsd.go b/vendor/golang.org/x/net/ipv4/defs_netbsd.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/defs_netbsd.go
rename to vendor/golang.org/x/net/ipv4/defs_netbsd.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/defs_openbsd.go b/vendor/golang.org/x/net/ipv4/defs_openbsd.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/defs_openbsd.go
rename to vendor/golang.org/x/net/ipv4/defs_openbsd.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/defs_solaris.go b/vendor/golang.org/x/net/ipv4/defs_solaris.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/defs_solaris.go
rename to vendor/golang.org/x/net/ipv4/defs_solaris.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/dgramopt_posix.go b/vendor/golang.org/x/net/ipv4/dgramopt_posix.go
similarity index 99%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/dgramopt_posix.go
rename to vendor/golang.org/x/net/ipv4/dgramopt_posix.go
index 693c137..fbc5df1 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/dgramopt_posix.go
+++ b/vendor/golang.org/x/net/ipv4/dgramopt_posix.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/dgramopt_stub.go b/vendor/golang.org/x/net/ipv4/dgramopt_stub.go
similarity index 98%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/dgramopt_stub.go
rename to vendor/golang.org/x/net/ipv4/dgramopt_stub.go
index 53cf1c6..f6b867f 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/dgramopt_stub.go
+++ b/vendor/golang.org/x/net/ipv4/dgramopt_stub.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/doc.go b/vendor/golang.org/x/net/ipv4/doc.go
similarity index 90%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/doc.go
rename to vendor/golang.org/x/net/ipv4/doc.go
index d58a4c9..b43935a 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/doc.go
+++ b/vendor/golang.org/x/net/ipv4/doc.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -21,10 +21,10 @@
//
// The options for unicasting are available for net.TCPConn,
// net.UDPConn and net.IPConn which are created as network connections
-// that use the IPv4 transport. When a single TCP connection carrying
+// that use the IPv4 transport. When a single TCP connection carrying
// a data flow of multiple packets needs to indicate the flow is
-// important, ipv4.Conn is used to set the type-of-service field on
-// the IPv4 header for each packet.
+// important, Conn is used to set the type-of-service field on the
+// IPv4 header for each packet.
//
// ln, err := net.Listen("tcp4", "0.0.0.0:1024")
// if err != nil {
@@ -56,7 +56,7 @@
//
// The options for multicasting are available for net.UDPConn and
// net.IPconn which are created as network connections that use the
-// IPv4 transport. A few network facilities must be prepared before
+// IPv4 transport. A few network facilities must be prepared before
// you begin multicasting, at a minimum joining network interfaces and
// multicast groups.
//
@@ -80,7 +80,7 @@
// defer c.Close()
//
// Second, the application joins multicast groups, starts listening to
-// the groups on the specified network interfaces. Note that the
+// the groups on the specified network interfaces. Note that the
// service port for transport layer protocol does not matter with this
// operation as joining groups affects only network and link layer
// protocols, such as IPv4 and Ethernet.
@@ -94,10 +94,10 @@
// }
//
// The application might set per packet control message transmissions
-// between the protocol stack within the kernel. When the application
+// between the protocol stack within the kernel. When the application
// needs a destination address on an incoming packet,
-// SetControlMessage of ipv4.PacketConn is used to enable control
-// message transmissions.
+// SetControlMessage of PacketConn is used to enable control message
+// transmissions.
//
// if err := p.SetControlMessage(ipv4.FlagDst, true); err != nil {
// // error handling
@@ -145,7 +145,7 @@
// More multicasting
//
// An application that uses PacketConn or RawConn may join multiple
-// multicast groups. For example, a UDP listener with port 1024 might
+// multicast groups. For example, a UDP listener with port 1024 might
// join two different groups across over two different network
// interfaces by using:
//
@@ -166,7 +166,7 @@
// }
//
// It is possible for multiple UDP listeners that listen on the same
-// UDP port to join the same multicast group. The net package will
+// UDP port to join the same multicast group. The net package will
// provide a socket that listens to a wildcard address with reusable
// UDP port when an appropriate multicast address prefix is passed to
// the net.ListenPacket or net.ListenUDP.
@@ -240,3 +240,5 @@
// In the fallback case, ExcludeSourceSpecificGroup and
// IncludeSourceSpecificGroup may return an error.
package ipv4 // import "golang.org/x/net/ipv4"
+
+// BUG(mikio): This package is not implemented on NaCl and Plan 9.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/endpoint.go b/vendor/golang.org/x/net/ipv4/endpoint.go
similarity index 89%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/endpoint.go
rename to vendor/golang.org/x/net/ipv4/endpoint.go
index a8ca2ff..8f7e07a 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/endpoint.go
+++ b/vendor/golang.org/x/net/ipv4/endpoint.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -12,6 +12,11 @@ import (
"golang.org/x/net/internal/netreflect"
)
+// BUG(mikio): On Windows, the JoinSourceSpecificGroup,
+// LeaveSourceSpecificGroup, ExcludeSourceSpecificGroup and
+// IncludeSourceSpecificGroup methods of PacketConn and RawConn are
+// not implemented.
+
// A Conn represents a network endpoint that uses the IPv4 transport.
// It is used to control basic IP-level socket options such as TOS and
// TTL.
@@ -33,8 +38,8 @@ func NewConn(c net.Conn) *Conn {
}
// A PacketConn represents a packet network endpoint that uses the
-// IPv4 transport. It is used to control several IP-level socket
-// options including multicasting. It also provides datagram based
+// IPv4 transport. It is used to control several IP-level socket
+// options including multicasting. It also provides datagram based
// network I/O methods specific to the IPv4 and higher layer protocols
// such as UDP.
type PacketConn struct {
@@ -113,8 +118,8 @@ func NewPacketConn(c net.PacketConn) *PacketConn {
}
// A RawConn represents a packet network endpoint that uses the IPv4
-// transport. It is used to control several IP-level socket options
-// including IPv4 header manipulation. It also provides datagram
+// transport. It is used to control several IP-level socket options
+// including IPv4 header manipulation. It also provides datagram
// based network I/O methods specific to the IPv4 and higher layer
// protocols that handle IPv4 datagram directly such as OSPF, GRE.
type RawConn struct {
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/gen.go b/vendor/golang.org/x/net/ipv4/gen.go
similarity index 98%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/gen.go
rename to vendor/golang.org/x/net/ipv4/gen.go
index 187d648..ffb44fe 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/gen.go
+++ b/vendor/golang.org/x/net/ipv4/gen.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/genericopt_posix.go b/vendor/golang.org/x/net/ipv4/genericopt_posix.go
similarity index 96%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/genericopt_posix.go
rename to vendor/golang.org/x/net/ipv4/genericopt_posix.go
index f333581..58168b7 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/genericopt_posix.go
+++ b/vendor/golang.org/x/net/ipv4/genericopt_posix.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/genericopt_stub.go b/vendor/golang.org/x/net/ipv4/genericopt_stub.go
similarity index 92%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/genericopt_stub.go
rename to vendor/golang.org/x/net/ipv4/genericopt_stub.go
index f907189..661a4d1 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/genericopt_stub.go
+++ b/vendor/golang.org/x/net/ipv4/genericopt_stub.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/header.go b/vendor/golang.org/x/net/ipv4/header.go
similarity index 98%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/header.go
rename to vendor/golang.org/x/net/ipv4/header.go
index f31be59..6dc26d4 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/header.go
+++ b/vendor/golang.org/x/net/ipv4/header.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/helper.go b/vendor/golang.org/x/net/ipv4/helper.go
similarity index 95%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/helper.go
rename to vendor/golang.org/x/net/ipv4/helper.go
index acecfd0..0838979 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/helper.go
+++ b/vendor/golang.org/x/net/ipv4/helper.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/iana.go b/vendor/golang.org/x/net/ipv4/iana.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/iana.go
rename to vendor/golang.org/x/net/ipv4/iana.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/icmp.go b/vendor/golang.org/x/net/ipv4/icmp.go
similarity index 96%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/icmp.go
rename to vendor/golang.org/x/net/ipv4/icmp.go
index e869c23..097bea8 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/icmp.go
+++ b/vendor/golang.org/x/net/ipv4/icmp.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/icmp_linux.go b/vendor/golang.org/x/net/ipv4/icmp_linux.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/icmp_linux.go
rename to vendor/golang.org/x/net/ipv4/icmp_linux.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/icmp_stub.go b/vendor/golang.org/x/net/ipv4/icmp_stub.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/icmp_stub.go
rename to vendor/golang.org/x/net/ipv4/icmp_stub.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/packet.go b/vendor/golang.org/x/net/ipv4/packet.go
similarity index 86%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/packet.go
rename to vendor/golang.org/x/net/ipv4/packet.go
index 0986431..d43723c 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/packet.go
+++ b/vendor/golang.org/x/net/ipv4/packet.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -9,6 +9,9 @@ import (
"syscall"
)
+// BUG(mikio): On Windows, the ReadFrom and WriteTo methods of RawConn
+// are not implemented.
+
// A packetHandler represents the IPv4 datagram handler.
type packetHandler struct {
c *net.IPConn
@@ -18,7 +21,7 @@ type packetHandler struct {
func (c *packetHandler) ok() bool { return c != nil && c.c != nil }
// ReadFrom reads an IPv4 datagram from the endpoint c, copying the
-// datagram into b. It returns the received datagram as the IPv4
+// datagram into b. It returns the received datagram as the IPv4
// header h, the payload p and the control message cm.
func (c *packetHandler) ReadFrom(b []byte) (h *Header, p []byte, cm *ControlMessage, err error) {
if !c.ok() {
@@ -54,14 +57,14 @@ func slicePacket(b []byte) (h, p []byte, err error) {
}
// WriteTo writes an IPv4 datagram through the endpoint c, copying the
-// datagram from the IPv4 header h and the payload p. The control
+// datagram from the IPv4 header h and the payload p. The control
// message cm allows the datagram path and the outgoing interface to be
-// specified. Currently only Darwin and Linux support this. The cm
+// specified. Currently only Darwin and Linux support this. The cm
// may be nil if control of the outgoing datagram is not required.
//
// The IPv4 header h must contain appropriate fields that include:
//
-// Version = ipv4.Version
+// Version =
// Len =
// TOS =
// TotalLen =
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/payload.go b/vendor/golang.org/x/net/ipv4/payload.go
similarity index 65%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/payload.go
rename to vendor/golang.org/x/net/ipv4/payload.go
index d7698cb..be130e4 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/payload.go
+++ b/vendor/golang.org/x/net/ipv4/payload.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -6,6 +6,9 @@ package ipv4
import "net"
+// BUG(mikio): On Windows, the ControlMessage for ReadFrom and WriteTo
+// methods of PacketConn is not implemented.
+
// A payloadHandler represents the IPv4 datagram payload handler.
type payloadHandler struct {
net.PacketConn
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/payload_cmsg.go b/vendor/golang.org/x/net/ipv4/payload_cmsg.go
similarity index 88%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/payload_cmsg.go
rename to vendor/golang.org/x/net/ipv4/payload_cmsg.go
index 5da0cbe..5e6e55c 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/payload_cmsg.go
+++ b/vendor/golang.org/x/net/ipv4/payload_cmsg.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -12,7 +12,7 @@ import (
)
// ReadFrom reads a payload of the received IPv4 datagram, from the
-// endpoint c, copying the payload into b. It returns the number of
+// endpoint c, copying the payload into b. It returns the number of
// bytes copied into b, the control message cm and the source address
// src of the received datagram.
func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
@@ -53,10 +53,10 @@ func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.
}
// WriteTo writes a payload of the IPv4 datagram, to the destination
-// address dst through the endpoint c, copying the payload from b. It
-// returns the number of bytes written. The control message cm allows
+// address dst through the endpoint c, copying the payload from b. It
+// returns the number of bytes written. The control message cm allows
// the datagram path and the outgoing interface to be specified.
-// Currently only Darwin and Linux support this. The cm may be nil if
+// Currently only Darwin and Linux support this. The cm may be nil if
// control of the outgoing datagram is not required.
func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
if !c.ok() {
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/payload_nocmsg.go b/vendor/golang.org/x/net/ipv4/payload_nocmsg.go
similarity index 79%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/payload_nocmsg.go
rename to vendor/golang.org/x/net/ipv4/payload_nocmsg.go
index b874de0..6f9d5b0 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/payload_nocmsg.go
+++ b/vendor/golang.org/x/net/ipv4/payload_nocmsg.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -12,7 +12,7 @@ import (
)
// ReadFrom reads a payload of the received IPv4 datagram, from the
-// endpoint c, copying the payload into b. It returns the number of
+// endpoint c, copying the payload into b. It returns the number of
// bytes copied into b, the control message cm and the source address
// src of the received datagram.
func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
@@ -26,10 +26,10 @@ func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.
}
// WriteTo writes a payload of the IPv4 datagram, to the destination
-// address dst through the endpoint c, copying the payload from b. It
-// returns the number of bytes written. The control message cm allows
+// address dst through the endpoint c, copying the payload from b. It
+// returns the number of bytes written. The control message cm allows
// the datagram path and the outgoing interface to be specified.
-// Currently only Darwin and Linux support this. The cm may be nil if
+// Currently only Darwin and Linux support this. The cm may be nil if
// control of the outgoing datagram is not required.
func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
if !c.ok() {
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt.go b/vendor/golang.org/x/net/ipv4/sockopt.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sockopt.go
rename to vendor/golang.org/x/net/ipv4/sockopt.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_asmreq.go b/vendor/golang.org/x/net/ipv4/sockopt_asmreq.go
similarity index 96%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_asmreq.go
rename to vendor/golang.org/x/net/ipv4/sockopt_asmreq.go
index 04b5a30..8092f1d 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_asmreq.go
+++ b/vendor/golang.org/x/net/ipv4/sockopt_asmreq.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_asmreq_posix.go b/vendor/golang.org/x/net/ipv4/sockopt_asmreq_posix.go
similarity index 95%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_asmreq_posix.go
rename to vendor/golang.org/x/net/ipv4/sockopt_asmreq_posix.go
index 1db5f24..2259a39 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_asmreq_posix.go
+++ b/vendor/golang.org/x/net/ipv4/sockopt_asmreq_posix.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_asmreq_stub.go b/vendor/golang.org/x/net/ipv4/sockopt_asmreq_stub.go
similarity index 90%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_asmreq_stub.go
rename to vendor/golang.org/x/net/ipv4/sockopt_asmreq_stub.go
index 0fbdf47..e655635 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_asmreq_stub.go
+++ b/vendor/golang.org/x/net/ipv4/sockopt_asmreq_stub.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_asmreqn_stub.go b/vendor/golang.org/x/net/ipv4/sockopt_asmreqn_stub.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_asmreqn_stub.go
rename to vendor/golang.org/x/net/ipv4/sockopt_asmreqn_stub.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_asmreqn_unix.go b/vendor/golang.org/x/net/ipv4/sockopt_asmreqn_unix.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_asmreqn_unix.go
rename to vendor/golang.org/x/net/ipv4/sockopt_asmreqn_unix.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_posix.go b/vendor/golang.org/x/net/ipv4/sockopt_posix.go
similarity index 98%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_posix.go
rename to vendor/golang.org/x/net/ipv4/sockopt_posix.go
index 30dd2d7..d806803 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_posix.go
+++ b/vendor/golang.org/x/net/ipv4/sockopt_posix.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_ssmreq_stub.go b/vendor/golang.org/x/net/ipv4/sockopt_ssmreq_stub.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_ssmreq_stub.go
rename to vendor/golang.org/x/net/ipv4/sockopt_ssmreq_stub.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_ssmreq_unix.go b/vendor/golang.org/x/net/ipv4/sockopt_ssmreq_unix.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_ssmreq_unix.go
rename to vendor/golang.org/x/net/ipv4/sockopt_ssmreq_unix.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_stub.go b/vendor/golang.org/x/net/ipv4/sockopt_stub.go
similarity index 79%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_stub.go
rename to vendor/golang.org/x/net/ipv4/sockopt_stub.go
index c7278c1..4ff6099 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/sockopt_stub.go
+++ b/vendor/golang.org/x/net/ipv4/sockopt_stub.go
@@ -1,4 +1,4 @@
-// Copyright 2012 The Go Authors. All rights reserved.
+// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sys_bsd.go b/vendor/golang.org/x/net/ipv4/sys_bsd.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sys_bsd.go
rename to vendor/golang.org/x/net/ipv4/sys_bsd.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sys_darwin.go b/vendor/golang.org/x/net/ipv4/sys_darwin.go
similarity index 60%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sys_darwin.go
rename to vendor/golang.org/x/net/ipv4/sys_darwin.go
index bc69414..abfffca 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/sys_darwin.go
+++ b/vendor/golang.org/x/net/ipv4/sys_darwin.go
@@ -6,6 +6,8 @@ package ipv4
import (
"net"
+ "strconv"
+ "strings"
"syscall"
"unsafe"
)
@@ -36,41 +38,40 @@ var (
func init() {
// Seems like kern.osreldate is veiled on latest OS X. We use
// kern.osrelease instead.
- osver, err := syscall.Sysctl("kern.osrelease")
+ s, err := syscall.Sysctl("kern.osrelease")
if err != nil {
return
}
- var i int
- for i = range osver {
- if osver[i] == '.' {
- break
- }
+ ss := strings.Split(s, ".")
+ if len(ss) == 0 {
+ return
}
// The IP_PKTINFO and protocol-independent multicast API were
- // introduced in OS X 10.7 (Darwin 11.0.0). But it looks like
- // those features require OS X 10.8 (Darwin 12.0.0) and above.
+ // introduced in OS X 10.7 (Darwin 11). But it looks like
+ // those features require OS X 10.8 (Darwin 12) or above.
// See http://support.apple.com/kb/HT1633.
- if i > 2 || i == 2 && osver[0] >= '1' && osver[1] >= '2' {
- ctlOpts[ctlPacketInfo].name = sysIP_PKTINFO
- ctlOpts[ctlPacketInfo].length = sizeofInetPktinfo
- ctlOpts[ctlPacketInfo].marshal = marshalPacketInfo
- ctlOpts[ctlPacketInfo].parse = parsePacketInfo
- sockOpts[ssoPacketInfo].name = sysIP_RECVPKTINFO
- sockOpts[ssoPacketInfo].typ = ssoTypeInt
- sockOpts[ssoMulticastInterface].typ = ssoTypeIPMreqn
- sockOpts[ssoJoinGroup].name = sysMCAST_JOIN_GROUP
- sockOpts[ssoJoinGroup].typ = ssoTypeGroupReq
- sockOpts[ssoLeaveGroup].name = sysMCAST_LEAVE_GROUP
- sockOpts[ssoLeaveGroup].typ = ssoTypeGroupReq
- sockOpts[ssoJoinSourceGroup].name = sysMCAST_JOIN_SOURCE_GROUP
- sockOpts[ssoJoinSourceGroup].typ = ssoTypeGroupSourceReq
- sockOpts[ssoLeaveSourceGroup].name = sysMCAST_LEAVE_SOURCE_GROUP
- sockOpts[ssoLeaveSourceGroup].typ = ssoTypeGroupSourceReq
- sockOpts[ssoBlockSourceGroup].name = sysMCAST_BLOCK_SOURCE
- sockOpts[ssoBlockSourceGroup].typ = ssoTypeGroupSourceReq
- sockOpts[ssoUnblockSourceGroup].name = sysMCAST_UNBLOCK_SOURCE
- sockOpts[ssoUnblockSourceGroup].typ = ssoTypeGroupSourceReq
+ if mjver, err := strconv.Atoi(ss[0]); err != nil || mjver < 12 {
+ return
}
+ ctlOpts[ctlPacketInfo].name = sysIP_PKTINFO
+ ctlOpts[ctlPacketInfo].length = sizeofInetPktinfo
+ ctlOpts[ctlPacketInfo].marshal = marshalPacketInfo
+ ctlOpts[ctlPacketInfo].parse = parsePacketInfo
+ sockOpts[ssoPacketInfo].name = sysIP_RECVPKTINFO
+ sockOpts[ssoPacketInfo].typ = ssoTypeInt
+ sockOpts[ssoMulticastInterface].typ = ssoTypeIPMreqn
+ sockOpts[ssoJoinGroup].name = sysMCAST_JOIN_GROUP
+ sockOpts[ssoJoinGroup].typ = ssoTypeGroupReq
+ sockOpts[ssoLeaveGroup].name = sysMCAST_LEAVE_GROUP
+ sockOpts[ssoLeaveGroup].typ = ssoTypeGroupReq
+ sockOpts[ssoJoinSourceGroup].name = sysMCAST_JOIN_SOURCE_GROUP
+ sockOpts[ssoJoinSourceGroup].typ = ssoTypeGroupSourceReq
+ sockOpts[ssoLeaveSourceGroup].name = sysMCAST_LEAVE_SOURCE_GROUP
+ sockOpts[ssoLeaveSourceGroup].typ = ssoTypeGroupSourceReq
+ sockOpts[ssoBlockSourceGroup].name = sysMCAST_BLOCK_SOURCE
+ sockOpts[ssoBlockSourceGroup].typ = ssoTypeGroupSourceReq
+ sockOpts[ssoUnblockSourceGroup].name = sysMCAST_UNBLOCK_SOURCE
+ sockOpts[ssoUnblockSourceGroup].typ = ssoTypeGroupSourceReq
}
func (pi *inetPktinfo) setIfindex(i int) {
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sys_freebsd.go b/vendor/golang.org/x/net/ipv4/sys_freebsd.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sys_freebsd.go
rename to vendor/golang.org/x/net/ipv4/sys_freebsd.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sys_linux.go b/vendor/golang.org/x/net/ipv4/sys_linux.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sys_linux.go
rename to vendor/golang.org/x/net/ipv4/sys_linux.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sys_linux_386.s b/vendor/golang.org/x/net/ipv4/sys_linux_386.s
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sys_linux_386.s
rename to vendor/golang.org/x/net/ipv4/sys_linux_386.s
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sys_openbsd.go b/vendor/golang.org/x/net/ipv4/sys_openbsd.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sys_openbsd.go
rename to vendor/golang.org/x/net/ipv4/sys_openbsd.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sys_solaris.go b/vendor/golang.org/x/net/ipv4/sys_solaris.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sys_solaris.go
rename to vendor/golang.org/x/net/ipv4/sys_solaris.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sys_solaris_amd64.s b/vendor/golang.org/x/net/ipv4/sys_solaris_amd64.s
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sys_solaris_amd64.s
rename to vendor/golang.org/x/net/ipv4/sys_solaris_amd64.s
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sys_stub.go b/vendor/golang.org/x/net/ipv4/sys_stub.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sys_stub.go
rename to vendor/golang.org/x/net/ipv4/sys_stub.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/sys_windows.go b/vendor/golang.org/x/net/ipv4/sys_windows.go
similarity index 96%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/sys_windows.go
rename to vendor/golang.org/x/net/ipv4/sys_windows.go
index 3f4c535..fac00bd 100644
--- a/cmd/gost/vendor/golang.org/x/net/ipv4/sys_windows.go
+++ b/vendor/golang.org/x/net/ipv4/sys_windows.go
@@ -51,6 +51,7 @@ var (
ssoMulticastTTL: {sysIP_MULTICAST_TTL, ssoTypeInt},
ssoMulticastInterface: {sysIP_MULTICAST_IF, ssoTypeInterface},
ssoMulticastLoopback: {sysIP_MULTICAST_LOOP, ssoTypeInt},
+ ssoHeaderPrepend: {sysIP_HDRINCL, ssoTypeInt},
ssoJoinGroup: {sysIP_ADD_MEMBERSHIP, ssoTypeIPMreq},
ssoLeaveGroup: {sysIP_DROP_MEMBERSHIP, ssoTypeIPMreq},
}
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/syscall_linux_386.go b/vendor/golang.org/x/net/ipv4/syscall_linux_386.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/syscall_linux_386.go
rename to vendor/golang.org/x/net/ipv4/syscall_linux_386.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/syscall_solaris.go b/vendor/golang.org/x/net/ipv4/syscall_solaris.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/syscall_solaris.go
rename to vendor/golang.org/x/net/ipv4/syscall_solaris.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/syscall_unix.go b/vendor/golang.org/x/net/ipv4/syscall_unix.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/syscall_unix.go
rename to vendor/golang.org/x/net/ipv4/syscall_unix.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/syscall_windows.go b/vendor/golang.org/x/net/ipv4/syscall_windows.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/syscall_windows.go
rename to vendor/golang.org/x/net/ipv4/syscall_windows.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_darwin.go b/vendor/golang.org/x/net/ipv4/zsys_darwin.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_darwin.go
rename to vendor/golang.org/x/net/ipv4/zsys_darwin.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_dragonfly.go b/vendor/golang.org/x/net/ipv4/zsys_dragonfly.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_dragonfly.go
rename to vendor/golang.org/x/net/ipv4/zsys_dragonfly.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_freebsd_386.go b/vendor/golang.org/x/net/ipv4/zsys_freebsd_386.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_freebsd_386.go
rename to vendor/golang.org/x/net/ipv4/zsys_freebsd_386.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_freebsd_amd64.go b/vendor/golang.org/x/net/ipv4/zsys_freebsd_amd64.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_freebsd_amd64.go
rename to vendor/golang.org/x/net/ipv4/zsys_freebsd_amd64.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_freebsd_arm.go b/vendor/golang.org/x/net/ipv4/zsys_freebsd_arm.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_freebsd_arm.go
rename to vendor/golang.org/x/net/ipv4/zsys_freebsd_arm.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_386.go b/vendor/golang.org/x/net/ipv4/zsys_linux_386.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_386.go
rename to vendor/golang.org/x/net/ipv4/zsys_linux_386.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_amd64.go b/vendor/golang.org/x/net/ipv4/zsys_linux_amd64.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_amd64.go
rename to vendor/golang.org/x/net/ipv4/zsys_linux_amd64.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_arm.go b/vendor/golang.org/x/net/ipv4/zsys_linux_arm.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_arm.go
rename to vendor/golang.org/x/net/ipv4/zsys_linux_arm.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_arm64.go b/vendor/golang.org/x/net/ipv4/zsys_linux_arm64.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_arm64.go
rename to vendor/golang.org/x/net/ipv4/zsys_linux_arm64.go
diff --git a/vendor/golang.org/x/net/ipv4/zsys_linux_mips.go b/vendor/golang.org/x/net/ipv4/zsys_linux_mips.go
new file mode 100644
index 0000000..4da6720
--- /dev/null
+++ b/vendor/golang.org/x/net/ipv4/zsys_linux_mips.go
@@ -0,0 +1,146 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv4
+
+const (
+ sysIP_TOS = 0x1
+ sysIP_TTL = 0x2
+ sysIP_HDRINCL = 0x3
+ sysIP_OPTIONS = 0x4
+ sysIP_ROUTER_ALERT = 0x5
+ sysIP_RECVOPTS = 0x6
+ sysIP_RETOPTS = 0x7
+ sysIP_PKTINFO = 0x8
+ sysIP_PKTOPTIONS = 0x9
+ sysIP_MTU_DISCOVER = 0xa
+ sysIP_RECVERR = 0xb
+ sysIP_RECVTTL = 0xc
+ sysIP_RECVTOS = 0xd
+ sysIP_MTU = 0xe
+ sysIP_FREEBIND = 0xf
+ sysIP_TRANSPARENT = 0x13
+ sysIP_RECVRETOPTS = 0x7
+ sysIP_ORIGDSTADDR = 0x14
+ sysIP_RECVORIGDSTADDR = 0x14
+ sysIP_MINTTL = 0x15
+ sysIP_NODEFRAG = 0x16
+ sysIP_UNICAST_IF = 0x32
+
+ sysIP_MULTICAST_IF = 0x20
+ sysIP_MULTICAST_TTL = 0x21
+ sysIP_MULTICAST_LOOP = 0x22
+ sysIP_ADD_MEMBERSHIP = 0x23
+ sysIP_DROP_MEMBERSHIP = 0x24
+ sysIP_UNBLOCK_SOURCE = 0x25
+ sysIP_BLOCK_SOURCE = 0x26
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x27
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
+ sysIP_MSFILTER = 0x29
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIP_MULTICAST_ALL = 0x31
+
+ sysICMP_FILTER = 0x1
+
+ sysSO_EE_ORIGIN_NONE = 0x0
+ sysSO_EE_ORIGIN_LOCAL = 0x1
+ sysSO_EE_ORIGIN_ICMP = 0x2
+ sysSO_EE_ORIGIN_ICMP6 = 0x3
+ sysSO_EE_ORIGIN_TXSTATUS = 0x4
+ sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+
+ sizeofICMPFilter = 0x4
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [2]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_mips64.go b/vendor/golang.org/x/net/ipv4/zsys_linux_mips64.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_mips64.go
rename to vendor/golang.org/x/net/ipv4/zsys_linux_mips64.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_mips64le.go b/vendor/golang.org/x/net/ipv4/zsys_linux_mips64le.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_mips64le.go
rename to vendor/golang.org/x/net/ipv4/zsys_linux_mips64le.go
diff --git a/vendor/golang.org/x/net/ipv4/zsys_linux_mipsle.go b/vendor/golang.org/x/net/ipv4/zsys_linux_mipsle.go
new file mode 100644
index 0000000..4da6720
--- /dev/null
+++ b/vendor/golang.org/x/net/ipv4/zsys_linux_mipsle.go
@@ -0,0 +1,146 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_linux.go
+
+package ipv4
+
+const (
+ sysIP_TOS = 0x1
+ sysIP_TTL = 0x2
+ sysIP_HDRINCL = 0x3
+ sysIP_OPTIONS = 0x4
+ sysIP_ROUTER_ALERT = 0x5
+ sysIP_RECVOPTS = 0x6
+ sysIP_RETOPTS = 0x7
+ sysIP_PKTINFO = 0x8
+ sysIP_PKTOPTIONS = 0x9
+ sysIP_MTU_DISCOVER = 0xa
+ sysIP_RECVERR = 0xb
+ sysIP_RECVTTL = 0xc
+ sysIP_RECVTOS = 0xd
+ sysIP_MTU = 0xe
+ sysIP_FREEBIND = 0xf
+ sysIP_TRANSPARENT = 0x13
+ sysIP_RECVRETOPTS = 0x7
+ sysIP_ORIGDSTADDR = 0x14
+ sysIP_RECVORIGDSTADDR = 0x14
+ sysIP_MINTTL = 0x15
+ sysIP_NODEFRAG = 0x16
+ sysIP_UNICAST_IF = 0x32
+
+ sysIP_MULTICAST_IF = 0x20
+ sysIP_MULTICAST_TTL = 0x21
+ sysIP_MULTICAST_LOOP = 0x22
+ sysIP_ADD_MEMBERSHIP = 0x23
+ sysIP_DROP_MEMBERSHIP = 0x24
+ sysIP_UNBLOCK_SOURCE = 0x25
+ sysIP_BLOCK_SOURCE = 0x26
+ sysIP_ADD_SOURCE_MEMBERSHIP = 0x27
+ sysIP_DROP_SOURCE_MEMBERSHIP = 0x28
+ sysIP_MSFILTER = 0x29
+ sysMCAST_JOIN_GROUP = 0x2a
+ sysMCAST_LEAVE_GROUP = 0x2d
+ sysMCAST_JOIN_SOURCE_GROUP = 0x2e
+ sysMCAST_LEAVE_SOURCE_GROUP = 0x2f
+ sysMCAST_BLOCK_SOURCE = 0x2b
+ sysMCAST_UNBLOCK_SOURCE = 0x2c
+ sysMCAST_MSFILTER = 0x30
+ sysIP_MULTICAST_ALL = 0x31
+
+ sysICMP_FILTER = 0x1
+
+ sysSO_EE_ORIGIN_NONE = 0x0
+ sysSO_EE_ORIGIN_LOCAL = 0x1
+ sysSO_EE_ORIGIN_ICMP = 0x2
+ sysSO_EE_ORIGIN_ICMP6 = 0x3
+ sysSO_EE_ORIGIN_TXSTATUS = 0x4
+ sysSO_EE_ORIGIN_TIMESTAMPING = 0x4
+
+ sysSOL_SOCKET = 0x1
+ sysSO_ATTACH_FILTER = 0x1a
+
+ sizeofKernelSockaddrStorage = 0x80
+ sizeofSockaddrInet = 0x10
+ sizeofInetPktinfo = 0xc
+ sizeofSockExtendedErr = 0x10
+
+ sizeofIPMreq = 0x8
+ sizeofIPMreqn = 0xc
+ sizeofIPMreqSource = 0xc
+ sizeofGroupReq = 0x84
+ sizeofGroupSourceReq = 0x104
+
+ sizeofICMPFilter = 0x4
+)
+
+type kernelSockaddrStorage struct {
+ Family uint16
+ X__data [126]int8
+}
+
+type sockaddrInet struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ X__pad [8]uint8
+}
+
+type inetPktinfo struct {
+ Ifindex int32
+ Spec_dst [4]byte /* in_addr */
+ Addr [4]byte /* in_addr */
+}
+
+type sockExtendedErr struct {
+ Errno uint32
+ Origin uint8
+ Type uint8
+ Code uint8
+ Pad uint8
+ Info uint32
+ Data uint32
+}
+
+type ipMreq struct {
+ Multiaddr [4]byte /* in_addr */
+ Interface [4]byte /* in_addr */
+}
+
+type ipMreqn struct {
+ Multiaddr [4]byte /* in_addr */
+ Address [4]byte /* in_addr */
+ Ifindex int32
+}
+
+type ipMreqSource struct {
+ Multiaddr uint32
+ Interface uint32
+ Sourceaddr uint32
+}
+
+type groupReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+}
+
+type groupSourceReq struct {
+ Interface uint32
+ Group kernelSockaddrStorage
+ Source kernelSockaddrStorage
+}
+
+type icmpFilter struct {
+ Data uint32
+}
+
+type sockFProg struct {
+ Len uint16
+ Pad_cgo_0 [2]byte
+ Filter *sockFilter
+}
+
+type sockFilter struct {
+ Code uint16
+ Jt uint8
+ Jf uint8
+ K uint32
+}
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_ppc.go b/vendor/golang.org/x/net/ipv4/zsys_linux_ppc.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_ppc.go
rename to vendor/golang.org/x/net/ipv4/zsys_linux_ppc.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_ppc64.go b/vendor/golang.org/x/net/ipv4/zsys_linux_ppc64.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_ppc64.go
rename to vendor/golang.org/x/net/ipv4/zsys_linux_ppc64.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_ppc64le.go b/vendor/golang.org/x/net/ipv4/zsys_linux_ppc64le.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_ppc64le.go
rename to vendor/golang.org/x/net/ipv4/zsys_linux_ppc64le.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_s390x.go b/vendor/golang.org/x/net/ipv4/zsys_linux_s390x.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_linux_s390x.go
rename to vendor/golang.org/x/net/ipv4/zsys_linux_s390x.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_netbsd.go b/vendor/golang.org/x/net/ipv4/zsys_netbsd.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_netbsd.go
rename to vendor/golang.org/x/net/ipv4/zsys_netbsd.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_openbsd.go b/vendor/golang.org/x/net/ipv4/zsys_openbsd.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_openbsd.go
rename to vendor/golang.org/x/net/ipv4/zsys_openbsd.go
diff --git a/cmd/gost/vendor/golang.org/x/net/ipv4/zsys_solaris.go b/vendor/golang.org/x/net/ipv4/zsys_solaris.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/ipv4/zsys_solaris.go
rename to vendor/golang.org/x/net/ipv4/zsys_solaris.go
diff --git a/cmd/gost/vendor/golang.org/x/net/lex/httplex/httplex.go b/vendor/golang.org/x/net/lex/httplex/httplex.go
similarity index 100%
rename from cmd/gost/vendor/golang.org/x/net/lex/httplex/httplex.go
rename to vendor/golang.org/x/net/lex/httplex/httplex.go
diff --git a/vendor/golang.org/x/text/LICENSE b/vendor/golang.org/x/text/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/text/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/text/PATENTS b/vendor/golang.org/x/text/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/text/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google 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,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/text/secure/bidirule/bidirule.go b/vendor/golang.org/x/text/secure/bidirule/bidirule.go
new file mode 100644
index 0000000..a7161bd
--- /dev/null
+++ b/vendor/golang.org/x/text/secure/bidirule/bidirule.go
@@ -0,0 +1,342 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package bidirule implements the Bidi Rule defined by RFC 5893.
+//
+// This package is under development. The API may change without notice and
+// without preserving backward compatibility.
+package bidirule
+
+import (
+ "errors"
+ "unicode/utf8"
+
+ "golang.org/x/text/transform"
+ "golang.org/x/text/unicode/bidi"
+)
+
+// This file contains an implementation of RFC 5893: Right-to-Left Scripts for
+// Internationalized Domain Names for Applications (IDNA)
+//
+// A label is an individual component of a domain name. Labels are usually
+// shown separated by dots; for example, the domain name "www.example.com" is
+// composed of three labels: "www", "example", and "com".
+//
+// An RTL label is a label that contains at least one character of class R, AL,
+// or AN. An LTR label is any label that is not an RTL label.
+//
+// A "Bidi domain name" is a domain name that contains at least one RTL label.
+//
+// The following guarantees can be made based on the above:
+//
+// o In a domain name consisting of only labels that satisfy the rule,
+// the requirements of Section 3 are satisfied. Note that even LTR
+// labels and pure ASCII labels have to be tested.
+//
+// o In a domain name consisting of only LDH labels (as defined in the
+// Definitions document [RFC5890]) and labels that satisfy the rule,
+// the requirements of Section 3 are satisfied as long as a label
+// that starts with an ASCII digit does not come after a
+// right-to-left label.
+//
+// No guarantee is given for other combinations.
+
+// ErrInvalid indicates a label is invalid according to the Bidi Rule.
+var ErrInvalid = errors.New("bidirule: failed Bidi Rule")
+
+type ruleState uint8
+
+const (
+ ruleInitial ruleState = iota
+ ruleLTR
+ ruleLTRFinal
+ ruleRTL
+ ruleRTLFinal
+ ruleInvalid
+)
+
+type ruleTransition struct {
+ next ruleState
+ mask uint16
+}
+
+var transitions = [...][2]ruleTransition{
+ // [2.1] The first character must be a character with Bidi property L, R, or
+ // AL. If it has the R or AL property, it is an RTL label; if it has the L
+ // property, it is an LTR label.
+ ruleInitial: {
+ {ruleLTRFinal, 1 << bidi.L},
+ {ruleRTLFinal, 1< 0 bytes returned
+ // before considering the error".
+ if r.src0 != r.src1 || r.err != nil {
+ r.dst0 = 0
+ r.dst1, n, err = r.t.Transform(r.dst, r.src[r.src0:r.src1], r.err == io.EOF)
+ r.src0 += n
+
+ switch {
+ case err == nil:
+ if r.src0 != r.src1 {
+ r.err = errInconsistentByteCount
+ }
+ // The Transform call was successful; we are complete if we
+ // cannot read more bytes into src.
+ r.transformComplete = r.err != nil
+ continue
+ case err == ErrShortDst && (r.dst1 != 0 || n != 0):
+ // Make room in dst by copying out, and try again.
+ continue
+ case err == ErrShortSrc && r.src1-r.src0 != len(r.src) && r.err == nil:
+ // Read more bytes into src via the code below, and try again.
+ default:
+ r.transformComplete = true
+ // The reader error (r.err) takes precedence over the
+ // transformer error (err) unless r.err is nil or io.EOF.
+ if r.err == nil || r.err == io.EOF {
+ r.err = err
+ }
+ continue
+ }
+ }
+
+ // Move any untransformed source bytes to the start of the buffer
+ // and read more bytes.
+ if r.src0 != 0 {
+ r.src0, r.src1 = 0, copy(r.src, r.src[r.src0:r.src1])
+ }
+ n, r.err = r.r.Read(r.src[r.src1:])
+ r.src1 += n
+ }
+}
+
+// TODO: implement ReadByte (and ReadRune??).
+
+// Writer wraps another io.Writer by transforming the bytes read.
+// The user needs to call Close to flush unwritten bytes that may
+// be buffered.
+type Writer struct {
+ w io.Writer
+ t Transformer
+ dst []byte
+
+ // src[:n] contains bytes that have not yet passed through t.
+ src []byte
+ n int
+}
+
+// NewWriter returns a new Writer that wraps w by transforming the bytes written
+// via t. It calls Reset on t.
+func NewWriter(w io.Writer, t Transformer) *Writer {
+ t.Reset()
+ return &Writer{
+ w: w,
+ t: t,
+ dst: make([]byte, defaultBufSize),
+ src: make([]byte, defaultBufSize),
+ }
+}
+
+// Write implements the io.Writer interface. If there are not enough
+// bytes available to complete a Transform, the bytes will be buffered
+// for the next write. Call Close to convert the remaining bytes.
+func (w *Writer) Write(data []byte) (n int, err error) {
+ src := data
+ if w.n > 0 {
+ // Append bytes from data to the last remainder.
+ // TODO: limit the amount copied on first try.
+ n = copy(w.src[w.n:], data)
+ w.n += n
+ src = w.src[:w.n]
+ }
+ for {
+ nDst, nSrc, err := w.t.Transform(w.dst, src, false)
+ if _, werr := w.w.Write(w.dst[:nDst]); werr != nil {
+ return n, werr
+ }
+ src = src[nSrc:]
+ if w.n == 0 {
+ n += nSrc
+ } else if len(src) <= n {
+ // Enough bytes from w.src have been consumed. We make src point
+ // to data instead to reduce the copying.
+ w.n = 0
+ n -= len(src)
+ src = data[n:]
+ if n < len(data) && (err == nil || err == ErrShortSrc) {
+ continue
+ }
+ }
+ switch err {
+ case ErrShortDst:
+ // This error is okay as long as we are making progress.
+ if nDst > 0 || nSrc > 0 {
+ continue
+ }
+ case ErrShortSrc:
+ if len(src) < len(w.src) {
+ m := copy(w.src, src)
+ // If w.n > 0, bytes from data were already copied to w.src and n
+ // was already set to the number of bytes consumed.
+ if w.n == 0 {
+ n += m
+ }
+ w.n = m
+ err = nil
+ } else if nDst > 0 || nSrc > 0 {
+ // Not enough buffer to store the remainder. Keep processing as
+ // long as there is progress. Without this case, transforms that
+ // require a lookahead larger than the buffer may result in an
+ // error. This is not something one may expect to be common in
+ // practice, but it may occur when buffers are set to small
+ // sizes during testing.
+ continue
+ }
+ case nil:
+ if w.n > 0 {
+ err = errInconsistentByteCount
+ }
+ }
+ return n, err
+ }
+}
+
+// Close implements the io.Closer interface.
+func (w *Writer) Close() error {
+ src := w.src[:w.n]
+ for {
+ nDst, nSrc, err := w.t.Transform(w.dst, src, true)
+ if _, werr := w.w.Write(w.dst[:nDst]); werr != nil {
+ return werr
+ }
+ if err != ErrShortDst {
+ return err
+ }
+ src = src[nSrc:]
+ }
+}
+
+type nop struct{ NopResetter }
+
+func (nop) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ n := copy(dst, src)
+ if n < len(src) {
+ err = ErrShortDst
+ }
+ return n, n, err
+}
+
+func (nop) Span(src []byte, atEOF bool) (n int, err error) {
+ return len(src), nil
+}
+
+type discard struct{ NopResetter }
+
+func (discard) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ return 0, len(src), nil
+}
+
+var (
+ // Discard is a Transformer for which all Transform calls succeed
+ // by consuming all bytes and writing nothing.
+ Discard Transformer = discard{}
+
+ // Nop is a SpanningTransformer that copies src to dst.
+ Nop SpanningTransformer = nop{}
+)
+
+// chain is a sequence of links. A chain with N Transformers has N+1 links and
+// N+1 buffers. Of those N+1 buffers, the first and last are the src and dst
+// buffers given to chain.Transform and the middle N-1 buffers are intermediate
+// buffers owned by the chain. The i'th link transforms bytes from the i'th
+// buffer chain.link[i].b at read offset chain.link[i].p to the i+1'th buffer
+// chain.link[i+1].b at write offset chain.link[i+1].n, for i in [0, N).
+type chain struct {
+ link []link
+ err error
+ // errStart is the index at which the error occurred plus 1. Processing
+ // errStart at this level at the next call to Transform. As long as
+ // errStart > 0, chain will not consume any more source bytes.
+ errStart int
+}
+
+func (c *chain) fatalError(errIndex int, err error) {
+ if i := errIndex + 1; i > c.errStart {
+ c.errStart = i
+ c.err = err
+ }
+}
+
+type link struct {
+ t Transformer
+ // b[p:n] holds the bytes to be transformed by t.
+ b []byte
+ p int
+ n int
+}
+
+func (l *link) src() []byte {
+ return l.b[l.p:l.n]
+}
+
+func (l *link) dst() []byte {
+ return l.b[l.n:]
+}
+
+// Chain returns a Transformer that applies t in sequence.
+func Chain(t ...Transformer) Transformer {
+ if len(t) == 0 {
+ return nop{}
+ }
+ c := &chain{link: make([]link, len(t)+1)}
+ for i, tt := range t {
+ c.link[i].t = tt
+ }
+ // Allocate intermediate buffers.
+ b := make([][defaultBufSize]byte, len(t)-1)
+ for i := range b {
+ c.link[i+1].b = b[i][:]
+ }
+ return c
+}
+
+// Reset resets the state of Chain. It calls Reset on all the Transformers.
+func (c *chain) Reset() {
+ for i, l := range c.link {
+ if l.t != nil {
+ l.t.Reset()
+ }
+ c.link[i].p, c.link[i].n = 0, 0
+ }
+}
+
+// TODO: make chain use Span (is going to be fun to implement!)
+
+// Transform applies the transformers of c in sequence.
+func (c *chain) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ // Set up src and dst in the chain.
+ srcL := &c.link[0]
+ dstL := &c.link[len(c.link)-1]
+ srcL.b, srcL.p, srcL.n = src, 0, len(src)
+ dstL.b, dstL.n = dst, 0
+ var lastFull, needProgress bool // for detecting progress
+
+ // i is the index of the next Transformer to apply, for i in [low, high].
+ // low is the lowest index for which c.link[low] may still produce bytes.
+ // high is the highest index for which c.link[high] has a Transformer.
+ // The error returned by Transform determines whether to increase or
+ // decrease i. We try to completely fill a buffer before converting it.
+ for low, i, high := c.errStart, c.errStart, len(c.link)-2; low <= i && i <= high; {
+ in, out := &c.link[i], &c.link[i+1]
+ nDst, nSrc, err0 := in.t.Transform(out.dst(), in.src(), atEOF && low == i)
+ out.n += nDst
+ in.p += nSrc
+ if i > 0 && in.p == in.n {
+ in.p, in.n = 0, 0
+ }
+ needProgress, lastFull = lastFull, false
+ switch err0 {
+ case ErrShortDst:
+ // Process the destination buffer next. Return if we are already
+ // at the high index.
+ if i == high {
+ return dstL.n, srcL.p, ErrShortDst
+ }
+ if out.n != 0 {
+ i++
+ // If the Transformer at the next index is not able to process any
+ // source bytes there is nothing that can be done to make progress
+ // and the bytes will remain unprocessed. lastFull is used to
+ // detect this and break out of the loop with a fatal error.
+ lastFull = true
+ continue
+ }
+ // The destination buffer was too small, but is completely empty.
+ // Return a fatal error as this transformation can never complete.
+ c.fatalError(i, errShortInternal)
+ case ErrShortSrc:
+ if i == 0 {
+ // Save ErrShortSrc in err. All other errors take precedence.
+ err = ErrShortSrc
+ break
+ }
+ // Source bytes were depleted before filling up the destination buffer.
+ // Verify we made some progress, move the remaining bytes to the errStart
+ // and try to get more source bytes.
+ if needProgress && nSrc == 0 || in.n-in.p == len(in.b) {
+ // There were not enough source bytes to proceed while the source
+ // buffer cannot hold any more bytes. Return a fatal error as this
+ // transformation can never complete.
+ c.fatalError(i, errShortInternal)
+ break
+ }
+ // in.b is an internal buffer and we can make progress.
+ in.p, in.n = 0, copy(in.b, in.src())
+ fallthrough
+ case nil:
+ // if i == low, we have depleted the bytes at index i or any lower levels.
+ // In that case we increase low and i. In all other cases we decrease i to
+ // fetch more bytes before proceeding to the next index.
+ if i > low {
+ i--
+ continue
+ }
+ default:
+ c.fatalError(i, err0)
+ }
+ // Exhausted level low or fatal error: increase low and continue
+ // to process the bytes accepted so far.
+ i++
+ low = i
+ }
+
+ // If c.errStart > 0, this means we found a fatal error. We will clear
+ // all upstream buffers. At this point, no more progress can be made
+ // downstream, as Transform would have bailed while handling ErrShortDst.
+ if c.errStart > 0 {
+ for i := 1; i < c.errStart; i++ {
+ c.link[i].p, c.link[i].n = 0, 0
+ }
+ err, c.errStart, c.err = c.err, 0, nil
+ }
+ return dstL.n, srcL.p, err
+}
+
+// Deprecated: use runes.Remove instead.
+func RemoveFunc(f func(r rune) bool) Transformer {
+ return removeF(f)
+}
+
+type removeF func(r rune) bool
+
+func (removeF) Reset() {}
+
+// Transform implements the Transformer interface.
+func (t removeF) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ for r, sz := rune(0), 0; len(src) > 0; src = src[sz:] {
+
+ if r = rune(src[0]); r < utf8.RuneSelf {
+ sz = 1
+ } else {
+ r, sz = utf8.DecodeRune(src)
+
+ if sz == 1 {
+ // Invalid rune.
+ if !atEOF && !utf8.FullRune(src) {
+ err = ErrShortSrc
+ break
+ }
+ // We replace illegal bytes with RuneError. Not doing so might
+ // otherwise turn a sequence of invalid UTF-8 into valid UTF-8.
+ // The resulting byte sequence may subsequently contain runes
+ // for which t(r) is true that were passed unnoticed.
+ if !t(r) {
+ if nDst+3 > len(dst) {
+ err = ErrShortDst
+ break
+ }
+ nDst += copy(dst[nDst:], "\uFFFD")
+ }
+ nSrc++
+ continue
+ }
+ }
+
+ if !t(r) {
+ if nDst+sz > len(dst) {
+ err = ErrShortDst
+ break
+ }
+ nDst += copy(dst[nDst:], src[:sz])
+ }
+ nSrc += sz
+ }
+ return
+}
+
+// grow returns a new []byte that is longer than b, and copies the first n bytes
+// of b to the start of the new slice.
+func grow(b []byte, n int) []byte {
+ m := len(b)
+ if m <= 32 {
+ m = 64
+ } else if m <= 256 {
+ m *= 2
+ } else {
+ m += m >> 1
+ }
+ buf := make([]byte, m)
+ copy(buf, b[:n])
+ return buf
+}
+
+const initialBufSize = 128
+
+// String returns a string with the result of converting s[:n] using t, where
+// n <= len(s). If err == nil, n will be len(s). It calls Reset on t.
+func String(t Transformer, s string) (result string, n int, err error) {
+ t.Reset()
+ if s == "" {
+ // Fast path for the common case for empty input. Results in about a
+ // 86% reduction of running time for BenchmarkStringLowerEmpty.
+ if _, _, err := t.Transform(nil, nil, true); err == nil {
+ return "", 0, nil
+ }
+ }
+
+ // Allocate only once. Note that both dst and src escape when passed to
+ // Transform.
+ buf := [2 * initialBufSize]byte{}
+ dst := buf[:initialBufSize:initialBufSize]
+ src := buf[initialBufSize : 2*initialBufSize]
+
+ // The input string s is transformed in multiple chunks (starting with a
+ // chunk size of initialBufSize). nDst and nSrc are per-chunk (or
+ // per-Transform-call) indexes, pDst and pSrc are overall indexes.
+ nDst, nSrc := 0, 0
+ pDst, pSrc := 0, 0
+
+ // pPrefix is the length of a common prefix: the first pPrefix bytes of the
+ // result will equal the first pPrefix bytes of s. It is not guaranteed to
+ // be the largest such value, but if pPrefix, len(result) and len(s) are
+ // all equal after the final transform (i.e. calling Transform with atEOF
+ // being true returned nil error) then we don't need to allocate a new
+ // result string.
+ pPrefix := 0
+ for {
+ // Invariant: pDst == pPrefix && pSrc == pPrefix.
+
+ n := copy(src, s[pSrc:])
+ nDst, nSrc, err = t.Transform(dst, src[:n], pSrc+n == len(s))
+ pDst += nDst
+ pSrc += nSrc
+
+ // TODO: let transformers implement an optional Spanner interface, akin
+ // to norm's QuickSpan. This would even allow us to avoid any allocation.
+ if !bytes.Equal(dst[:nDst], src[:nSrc]) {
+ break
+ }
+ pPrefix = pSrc
+ if err == ErrShortDst {
+ // A buffer can only be short if a transformer modifies its input.
+ break
+ } else if err == ErrShortSrc {
+ if nSrc == 0 {
+ // No progress was made.
+ break
+ }
+ // Equal so far and !atEOF, so continue checking.
+ } else if err != nil || pPrefix == len(s) {
+ return string(s[:pPrefix]), pPrefix, err
+ }
+ }
+ // Post-condition: pDst == pPrefix + nDst && pSrc == pPrefix + nSrc.
+
+ // We have transformed the first pSrc bytes of the input s to become pDst
+ // transformed bytes. Those transformed bytes are discontiguous: the first
+ // pPrefix of them equal s[:pPrefix] and the last nDst of them equal
+ // dst[:nDst]. We copy them around, into a new dst buffer if necessary, so
+ // that they become one contiguous slice: dst[:pDst].
+ if pPrefix != 0 {
+ newDst := dst
+ if pDst > len(newDst) {
+ newDst = make([]byte, len(s)+nDst-nSrc)
+ }
+ copy(newDst[pPrefix:pDst], dst[:nDst])
+ copy(newDst[:pPrefix], s[:pPrefix])
+ dst = newDst
+ }
+
+ // Prevent duplicate Transform calls with atEOF being true at the end of
+ // the input. Also return if we have an unrecoverable error.
+ if (err == nil && pSrc == len(s)) ||
+ (err != nil && err != ErrShortDst && err != ErrShortSrc) {
+ return string(dst[:pDst]), pSrc, err
+ }
+
+ // Transform the remaining input, growing dst and src buffers as necessary.
+ for {
+ n := copy(src, s[pSrc:])
+ nDst, nSrc, err := t.Transform(dst[pDst:], src[:n], pSrc+n == len(s))
+ pDst += nDst
+ pSrc += nSrc
+
+ // If we got ErrShortDst or ErrShortSrc, do not grow as long as we can
+ // make progress. This may avoid excessive allocations.
+ if err == ErrShortDst {
+ if nDst == 0 {
+ dst = grow(dst, pDst)
+ }
+ } else if err == ErrShortSrc {
+ if nSrc == 0 {
+ src = grow(src, 0)
+ }
+ } else if err != nil || pSrc == len(s) {
+ return string(dst[:pDst]), pSrc, err
+ }
+ }
+}
+
+// Bytes returns a new byte slice with the result of converting b[:n] using t,
+// where n <= len(b). If err == nil, n will be len(b). It calls Reset on t.
+func Bytes(t Transformer, b []byte) (result []byte, n int, err error) {
+ return doAppend(t, 0, make([]byte, len(b)), b)
+}
+
+// Append appends the result of converting src[:n] using t to dst, where
+// n <= len(src), If err == nil, n will be len(src). It calls Reset on t.
+func Append(t Transformer, dst, src []byte) (result []byte, n int, err error) {
+ if len(dst) == cap(dst) {
+ n := len(src) + len(dst) // It is okay for this to be 0.
+ b := make([]byte, n)
+ dst = b[:copy(b, dst)]
+ }
+ return doAppend(t, len(dst), dst[:cap(dst)], src)
+}
+
+func doAppend(t Transformer, pDst int, dst, src []byte) (result []byte, n int, err error) {
+ t.Reset()
+ pSrc := 0
+ for {
+ nDst, nSrc, err := t.Transform(dst[pDst:], src[pSrc:], true)
+ pDst += nDst
+ pSrc += nSrc
+ if err != ErrShortDst {
+ return dst[:pDst], pSrc, err
+ }
+
+ // Grow the destination buffer, but do not grow as long as we can make
+ // progress. This may avoid excessive allocations.
+ if nDst == 0 {
+ dst = grow(dst, pDst)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/text/unicode/bidi/bidi.go b/vendor/golang.org/x/text/unicode/bidi/bidi.go
new file mode 100644
index 0000000..3fc4a62
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/bidi/bidi.go
@@ -0,0 +1,198 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:generate go run gen.go gen_trieval.go gen_ranges.go
+
+// Package bidi contains functionality for bidirectional text support.
+//
+// See http://www.unicode.org/reports/tr9.
+//
+// NOTE: UNDER CONSTRUCTION. This API may change in backwards incompatible ways
+// and without notice.
+package bidi // import "golang.org/x/text/unicode/bidi"
+
+// TODO:
+// The following functionality would not be hard to implement, but hinges on
+// the definition of a Segmenter interface. For now this is up to the user.
+// - Iterate over paragraphs
+// - Segmenter to iterate over runs directly from a given text.
+// Also:
+// - Transformer for reordering?
+// - Transformer (validator, really) for Bidi Rule.
+
+// This API tries to avoid dealing with embedding levels for now. Under the hood
+// these will be computed, but the question is to which extent the user should
+// know they exist. We should at some point allow the user to specify an
+// embedding hierarchy, though.
+
+// A Direction indicates the overall flow of text.
+type Direction int
+
+const (
+ // LeftToRight indicates the text contains no right-to-left characters and
+ // that either there are some left-to-right characters or the option
+ // DefaultDirection(LeftToRight) was passed.
+ LeftToRight Direction = iota
+
+ // RightToLeft indicates the text contains no left-to-right characters and
+ // that either there are some right-to-left characters or the option
+ // DefaultDirection(RightToLeft) was passed.
+ RightToLeft
+
+ // Mixed indicates text contains both left-to-right and right-to-left
+ // characters.
+ Mixed
+
+ // Neutral means that text contains no left-to-right and right-to-left
+ // characters and that no default direction has been set.
+ Neutral
+)
+
+type options struct{}
+
+// An Option is an option for Bidi processing.
+type Option func(*options)
+
+// ICU allows the user to define embedding levels. This may be used, for example,
+// to use hierarchical structure of markup languages to define embeddings.
+// The following option may be a way to expose this functionality in this API.
+// // LevelFunc sets a function that associates nesting levels with the given text.
+// // The levels function will be called with monotonically increasing values for p.
+// func LevelFunc(levels func(p int) int) Option {
+// panic("unimplemented")
+// }
+
+// DefaultDirection sets the default direction for a Paragraph. The direction is
+// overridden if the text contains directional characters.
+func DefaultDirection(d Direction) Option {
+ panic("unimplemented")
+}
+
+// A Paragraph holds a single Paragraph for Bidi processing.
+type Paragraph struct {
+ // buffers
+}
+
+// SetBytes configures p for the given paragraph text. It replaces text
+// previously set by SetBytes or SetString. If b contains a paragraph separator
+// it will only process the first paragraph and report the number of bytes
+// consumed from b including this separator. Error may be non-nil if options are
+// given.
+func (p *Paragraph) SetBytes(b []byte, opts ...Option) (n int, err error) {
+ panic("unimplemented")
+}
+
+// SetString configures p for the given paragraph text. It replaces text
+// previously set by SetBytes or SetString. If b contains a paragraph separator
+// it will only process the first paragraph and report the number of bytes
+// consumed from b including this separator. Error may be non-nil if options are
+// given.
+func (p *Paragraph) SetString(s string, opts ...Option) (n int, err error) {
+ panic("unimplemented")
+}
+
+// IsLeftToRight reports whether the principle direction of rendering for this
+// paragraphs is left-to-right. If this returns false, the principle direction
+// of rendering is right-to-left.
+func (p *Paragraph) IsLeftToRight() bool {
+ panic("unimplemented")
+}
+
+// Direction returns the direction of the text of this paragraph.
+//
+// The direction may be LeftToRight, RightToLeft, Mixed, or Neutral.
+func (p *Paragraph) Direction() Direction {
+ panic("unimplemented")
+}
+
+// RunAt reports the Run at the given position of the input text.
+//
+// This method can be used for computing line breaks on paragraphs.
+func (p *Paragraph) RunAt(pos int) Run {
+ panic("unimplemented")
+}
+
+// Order computes the visual ordering of all the runs in a Paragraph.
+func (p *Paragraph) Order() (Ordering, error) {
+ panic("unimplemented")
+}
+
+// Line computes the visual ordering of runs for a single line starting and
+// ending at the given positions in the original text.
+func (p *Paragraph) Line(start, end int) (Ordering, error) {
+ panic("unimplemented")
+}
+
+// An Ordering holds the computed visual order of runs of a Paragraph. Calling
+// SetBytes or SetString on the originating Paragraph invalidates an Ordering.
+// The methods of an Ordering should only be called by one goroutine at a time.
+type Ordering struct{}
+
+// Direction reports the directionality of the runs.
+//
+// The direction may be LeftToRight, RightToLeft, Mixed, or Neutral.
+func (o *Ordering) Direction() Direction {
+ panic("unimplemented")
+}
+
+// NumRuns returns the number of runs.
+func (o *Ordering) NumRuns() int {
+ panic("unimplemented")
+}
+
+// Run returns the ith run within the ordering.
+func (o *Ordering) Run(i int) Run {
+ panic("unimplemented")
+}
+
+// TODO: perhaps with options.
+// // Reorder creates a reader that reads the runes in visual order per character.
+// // Modifiers remain after the runes they modify.
+// func (l *Runs) Reorder() io.Reader {
+// panic("unimplemented")
+// }
+
+// A Run is a continuous sequence of characters of a single direction.
+type Run struct {
+}
+
+// String returns the text of the run in its original order.
+func (r *Run) String() string {
+ panic("unimplemented")
+}
+
+// Bytes returns the text of the run in its original order.
+func (r *Run) Bytes() []byte {
+ panic("unimplemented")
+}
+
+// TODO: methods for
+// - Display order
+// - headers and footers
+// - bracket replacement.
+
+// Direction reports the direction of the run.
+func (r *Run) Direction() Direction {
+ panic("unimplemented")
+}
+
+// Position of the Run within the text passed to SetBytes or SetString of the
+// originating Paragraph value.
+func (r *Run) Pos() (start, end int) {
+ panic("unimplemented")
+}
+
+// AppendReverse reverses the order of characters of in, appends them to out,
+// and returns the result. Modifiers will still follow the runes they modify.
+// Brackets are replaced with their counterparts.
+func AppendReverse(out, in []byte) []byte {
+ panic("unimplemented")
+}
+
+// ReverseString reverses the order of characters in s and returns a new string.
+// Modifiers will still follow the runes they modify. Brackets are replaced with
+// their counterparts.
+func ReverseString(s string) string {
+ panic("unimplemented")
+}
diff --git a/vendor/golang.org/x/text/unicode/bidi/bracket.go b/vendor/golang.org/x/text/unicode/bidi/bracket.go
new file mode 100644
index 0000000..601e259
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/bidi/bracket.go
@@ -0,0 +1,335 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bidi
+
+import (
+ "container/list"
+ "fmt"
+ "sort"
+)
+
+// This file contains a port of the reference implementation of the
+// Bidi Parentheses Algorithm:
+// http://www.unicode.org/Public/PROGRAMS/BidiReferenceJava/BidiPBAReference.java
+//
+// The implementation in this file covers definitions BD14-BD16 and rule N0
+// of UAX#9.
+//
+// Some preprocessing is done for each rune before data is passed to this
+// algorithm:
+// - opening and closing brackets are identified
+// - a bracket pair type, like '(' and ')' is assigned a unique identifier that
+// is identical for the opening and closing bracket. It is left to do these
+// mappings.
+// - The BPA algorithm requires that bracket characters that are canonical
+// equivalents of each other be able to be substituted for each other.
+// It is the responsibility of the caller to do this canonicalization.
+//
+// In implementing BD16, this implementation departs slightly from the "logical"
+// algorithm defined in UAX#9. In particular, the stack referenced there
+// supports operations that go beyond a "basic" stack. An equivalent
+// implementation based on a linked list is used here.
+
+// Bidi_Paired_Bracket_Type
+// BD14. An opening paired bracket is a character whose
+// Bidi_Paired_Bracket_Type property value is Open.
+//
+// BD15. A closing paired bracket is a character whose
+// Bidi_Paired_Bracket_Type property value is Close.
+type bracketType byte
+
+const (
+ bpNone bracketType = iota
+ bpOpen
+ bpClose
+)
+
+// bracketPair holds a pair of index values for opening and closing bracket
+// location of a bracket pair.
+type bracketPair struct {
+ opener int
+ closer int
+}
+
+func (b *bracketPair) String() string {
+ return fmt.Sprintf("(%v, %v)", b.opener, b.closer)
+}
+
+// bracketPairs is a slice of bracketPairs with a sort.Interface implementation.
+type bracketPairs []bracketPair
+
+func (b bracketPairs) Len() int { return len(b) }
+func (b bracketPairs) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
+func (b bracketPairs) Less(i, j int) bool { return b[i].opener < b[j].opener }
+
+// resolvePairedBrackets runs the paired bracket part of the UBA algorithm.
+//
+// For each rune, it takes the indexes into the original string, the class the
+// bracket type (in pairTypes) and the bracket identifier (pairValues). It also
+// takes the direction type for the start-of-sentence and the embedding level.
+//
+// The identifiers for bracket types are the rune of the canonicalized opening
+// bracket for brackets (open or close) or 0 for runes that are not brackets.
+func resolvePairedBrackets(s *isolatingRunSequence) {
+ p := bracketPairer{
+ sos: s.sos,
+ openers: list.New(),
+ codesIsolatedRun: s.types,
+ indexes: s.indexes,
+ }
+ dirEmbed := L
+ if s.level&1 != 0 {
+ dirEmbed = R
+ }
+ p.locateBrackets(s.p.pairTypes, s.p.pairValues)
+ p.resolveBrackets(dirEmbed, s.p.initialTypes)
+}
+
+type bracketPairer struct {
+ sos Class // direction corresponding to start of sequence
+
+ // The following is a restatement of BD 16 using non-algorithmic language.
+ //
+ // A bracket pair is a pair of characters consisting of an opening
+ // paired bracket and a closing paired bracket such that the
+ // Bidi_Paired_Bracket property value of the former equals the latter,
+ // subject to the following constraints.
+ // - both characters of a pair occur in the same isolating run sequence
+ // - the closing character of a pair follows the opening character
+ // - any bracket character can belong at most to one pair, the earliest possible one
+ // - any bracket character not part of a pair is treated like an ordinary character
+ // - pairs may nest properly, but their spans may not overlap otherwise
+
+ // Bracket characters with canonical decompositions are supposed to be
+ // treated as if they had been normalized, to allow normalized and non-
+ // normalized text to give the same result. In this implementation that step
+ // is pushed out to the caller. The caller has to ensure that the pairValue
+ // slices contain the rune of the opening bracket after normalization for
+ // any opening or closing bracket.
+
+ openers *list.List // list of positions for opening brackets
+
+ // bracket pair positions sorted by location of opening bracket
+ pairPositions bracketPairs
+
+ codesIsolatedRun []Class // directional bidi codes for an isolated run
+ indexes []int // array of index values into the original string
+
+}
+
+// matchOpener reports whether characters at given positions form a matching
+// bracket pair.
+func (p *bracketPairer) matchOpener(pairValues []rune, opener, closer int) bool {
+ return pairValues[p.indexes[opener]] == pairValues[p.indexes[closer]]
+}
+
+const maxPairingDepth = 63
+
+// locateBrackets locates matching bracket pairs according to BD16.
+//
+// This implementation uses a linked list instead of a stack, because, while
+// elements are added at the front (like a push) they are not generally removed
+// in atomic 'pop' operations, reducing the benefit of the stack archetype.
+func (p *bracketPairer) locateBrackets(pairTypes []bracketType, pairValues []rune) {
+ // traverse the run
+ // do that explicitly (not in a for-each) so we can record position
+ for i, index := range p.indexes {
+
+ // look at the bracket type for each character
+ if pairTypes[index] == bpNone || p.codesIsolatedRun[i] != ON {
+ // continue scanning
+ continue
+ }
+ switch pairTypes[index] {
+ case bpOpen:
+ // check if maximum pairing depth reached
+ if p.openers.Len() == maxPairingDepth {
+ p.openers.Init()
+ return
+ }
+ // remember opener location, most recent first
+ p.openers.PushFront(i)
+
+ case bpClose:
+ // see if there is a match
+ count := 0
+ for elem := p.openers.Front(); elem != nil; elem = elem.Next() {
+ count++
+ opener := elem.Value.(int)
+ if p.matchOpener(pairValues, opener, i) {
+ // if the opener matches, add nested pair to the ordered list
+ p.pairPositions = append(p.pairPositions, bracketPair{opener, i})
+ // remove up to and including matched opener
+ for ; count > 0; count-- {
+ p.openers.Remove(p.openers.Front())
+ }
+ break
+ }
+ }
+ sort.Sort(p.pairPositions)
+ // if we get here, the closing bracket matched no openers
+ // and gets ignored
+ }
+ }
+}
+
+// Bracket pairs within an isolating run sequence are processed as units so
+// that both the opening and the closing paired bracket in a pair resolve to
+// the same direction.
+//
+// N0. Process bracket pairs in an isolating run sequence sequentially in
+// the logical order of the text positions of the opening paired brackets
+// using the logic given below. Within this scope, bidirectional types EN
+// and AN are treated as R.
+//
+// Identify the bracket pairs in the current isolating run sequence
+// according to BD16. For each bracket-pair element in the list of pairs of
+// text positions:
+//
+// a Inspect the bidirectional types of the characters enclosed within the
+// bracket pair.
+//
+// b If any strong type (either L or R) matching the embedding direction is
+// found, set the type for both brackets in the pair to match the embedding
+// direction.
+//
+// o [ e ] o -> o e e e o
+//
+// o [ o e ] -> o e o e e
+//
+// o [ NI e ] -> o e NI e e
+//
+// c Otherwise, if a strong type (opposite the embedding direction) is
+// found, test for adjacent strong types as follows: 1 First, check
+// backwards before the opening paired bracket until the first strong type
+// (L, R, or sos) is found. If that first preceding strong type is opposite
+// the embedding direction, then set the type for both brackets in the pair
+// to that type. 2 Otherwise, set the type for both brackets in the pair to
+// the embedding direction.
+//
+// o [ o ] e -> o o o o e
+//
+// o [ o NI ] o -> o o o NI o o
+//
+// e [ o ] o -> e e o e o
+//
+// e [ o ] e -> e e o e e
+//
+// e ( o [ o ] NI ) e -> e e o o o o NI e e
+//
+// d Otherwise, do not set the type for the current bracket pair. Note that
+// if the enclosed text contains no strong types the paired brackets will
+// both resolve to the same level when resolved individually using rules N1
+// and N2.
+//
+// e ( NI ) o -> e ( NI ) o
+
+// getStrongTypeN0 maps character's directional code to strong type as required
+// by rule N0.
+//
+// TODO: have separate type for "strong" directionality.
+func (p *bracketPairer) getStrongTypeN0(index int) Class {
+ switch p.codesIsolatedRun[index] {
+ // in the scope of N0, number types are treated as R
+ case EN, AN, AL, R:
+ return R
+ case L:
+ return L
+ default:
+ return ON
+ }
+}
+
+// classifyPairContent reports the strong types contained inside a Bracket Pair,
+// assuming the given embedding direction.
+//
+// It returns ON if no strong type is found. If a single strong type is found,
+// it returns this this type. Otherwise it returns the embedding direction.
+//
+// TODO: use separate type for "strong" directionality.
+func (p *bracketPairer) classifyPairContent(loc bracketPair, dirEmbed Class) Class {
+ dirOpposite := ON
+ for i := loc.opener + 1; i < loc.closer; i++ {
+ dir := p.getStrongTypeN0(i)
+ if dir == ON {
+ continue
+ }
+ if dir == dirEmbed {
+ return dir // type matching embedding direction found
+ }
+ dirOpposite = dir
+ }
+ // return ON if no strong type found, or class opposite to dirEmbed
+ return dirOpposite
+}
+
+// classBeforePair determines which strong types are present before a Bracket
+// Pair. Return R or L if strong type found, otherwise ON.
+func (p *bracketPairer) classBeforePair(loc bracketPair) Class {
+ for i := loc.opener - 1; i >= 0; i-- {
+ if dir := p.getStrongTypeN0(i); dir != ON {
+ return dir
+ }
+ }
+ // no strong types found, return sos
+ return p.sos
+}
+
+// assignBracketType implements rule N0 for a single bracket pair.
+func (p *bracketPairer) assignBracketType(loc bracketPair, dirEmbed Class, initialTypes []Class) {
+ // rule "N0, a", inspect contents of pair
+ dirPair := p.classifyPairContent(loc, dirEmbed)
+
+ // dirPair is now L, R, or N (no strong type found)
+
+ // the following logical tests are performed out of order compared to
+ // the statement of the rules but yield the same results
+ if dirPair == ON {
+ return // case "d" - nothing to do
+ }
+
+ if dirPair != dirEmbed {
+ // case "c": strong type found, opposite - check before (c.1)
+ dirPair = p.classBeforePair(loc)
+ if dirPair == dirEmbed || dirPair == ON {
+ // no strong opposite type found before - use embedding (c.2)
+ dirPair = dirEmbed
+ }
+ }
+ // else: case "b", strong type found matching embedding,
+ // no explicit action needed, as dirPair is already set to embedding
+ // direction
+
+ // set the bracket types to the type found
+ p.setBracketsToType(loc, dirPair, initialTypes)
+}
+
+func (p *bracketPairer) setBracketsToType(loc bracketPair, dirPair Class, initialTypes []Class) {
+ p.codesIsolatedRun[loc.opener] = dirPair
+ p.codesIsolatedRun[loc.closer] = dirPair
+
+ for i := loc.opener + 1; i < loc.closer; i++ {
+ index := p.indexes[i]
+ if initialTypes[index] != NSM {
+ break
+ }
+ p.codesIsolatedRun[i] = dirPair
+ }
+
+ for i := loc.closer + 1; i < len(p.indexes); i++ {
+ index := p.indexes[i]
+ if initialTypes[index] != NSM {
+ break
+ }
+ p.codesIsolatedRun[i] = dirPair
+ }
+}
+
+// resolveBrackets implements rule N0 for a list of pairs.
+func (p *bracketPairer) resolveBrackets(dirEmbed Class, initialTypes []Class) {
+ for _, loc := range p.pairPositions {
+ p.assignBracketType(loc, dirEmbed, initialTypes)
+ }
+}
diff --git a/vendor/golang.org/x/text/unicode/bidi/core.go b/vendor/golang.org/x/text/unicode/bidi/core.go
new file mode 100644
index 0000000..d4c1399
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/bidi/core.go
@@ -0,0 +1,1058 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bidi
+
+import "log"
+
+// This implementation is a port based on the reference implementation found at:
+// http://www.unicode.org/Public/PROGRAMS/BidiReferenceJava/
+//
+// described in Unicode Bidirectional Algorithm (UAX #9).
+//
+// Input:
+// There are two levels of input to the algorithm, since clients may prefer to
+// supply some information from out-of-band sources rather than relying on the
+// default behavior.
+//
+// - Bidi class array
+// - Bidi class array, with externally supplied base line direction
+//
+// Output:
+// Output is separated into several stages:
+//
+// - levels array over entire paragraph
+// - reordering array over entire paragraph
+// - levels array over line
+// - reordering array over line
+//
+// Note that for conformance to the Unicode Bidirectional Algorithm,
+// implementations are only required to generate correct reordering and
+// character directionality (odd or even levels) over a line. Generating
+// identical level arrays over a line is not required. Bidi explicit format
+// codes (LRE, RLE, LRO, RLO, PDF) and BN can be assigned arbitrary levels and
+// positions as long as the rest of the input is properly reordered.
+//
+// As the algorithm is defined to operate on a single paragraph at a time, this
+// implementation is written to handle single paragraphs. Thus rule P1 is
+// presumed by this implementation-- the data provided to the implementation is
+// assumed to be a single paragraph, and either contains no 'B' codes, or a
+// single 'B' code at the end of the input. 'B' is allowed as input to
+// illustrate how the algorithm assigns it a level.
+//
+// Also note that rules L3 and L4 depend on the rendering engine that uses the
+// result of the bidi algorithm. This implementation assumes that the rendering
+// engine expects combining marks in visual order (e.g. to the left of their
+// base character in RTL runs) and that it adjusts the glyphs used to render
+// mirrored characters that are in RTL runs so that they render appropriately.
+
+// level is the embedding level of a character. Even embedding levels indicate
+// left-to-right order and odd levels indicate right-to-left order. The special
+// level of -1 is reserved for undefined order.
+type level int8
+
+const implicitLevel level = -1
+
+// in returns if x is equal to any of the values in set.
+func (c Class) in(set ...Class) bool {
+ for _, s := range set {
+ if c == s {
+ return true
+ }
+ }
+ return false
+}
+
+// A paragraph contains the state of a paragraph.
+type paragraph struct {
+ initialTypes []Class
+
+ // Arrays of properties needed for paired bracket evaluation in N0
+ pairTypes []bracketType // paired Bracket types for paragraph
+ pairValues []rune // rune for opening bracket or pbOpen and pbClose; 0 for pbNone
+
+ embeddingLevel level // default: = implicitLevel;
+
+ // at the paragraph levels
+ resultTypes []Class
+ resultLevels []level
+
+ // Index of matching PDI for isolate initiator characters. For other
+ // characters, the value of matchingPDI will be set to -1. For isolate
+ // initiators with no matching PDI, matchingPDI will be set to the length of
+ // the input string.
+ matchingPDI []int
+
+ // Index of matching isolate initiator for PDI characters. For other
+ // characters, and for PDIs with no matching isolate initiator, the value of
+ // matchingIsolateInitiator will be set to -1.
+ matchingIsolateInitiator []int
+}
+
+// newParagraph initializes a paragraph. The user needs to supply a few arrays
+// corresponding to the preprocessed text input. The types correspond to the
+// Unicode BiDi classes for each rune. pairTypes indicates the bracket type for
+// each rune. pairValues provides a unique bracket class identifier for each
+// rune (suggested is the rune of the open bracket for opening and matching
+// close brackets, after normalization). The embedding levels are optional, but
+// may be supplied to encode embedding levels of styled text.
+//
+// TODO: return an error.
+func newParagraph(types []Class, pairTypes []bracketType, pairValues []rune, levels level) *paragraph {
+ validateTypes(types)
+ validatePbTypes(pairTypes)
+ validatePbValues(pairValues, pairTypes)
+ validateParagraphEmbeddingLevel(levels)
+
+ p := ¶graph{
+ initialTypes: append([]Class(nil), types...),
+ embeddingLevel: levels,
+
+ pairTypes: pairTypes,
+ pairValues: pairValues,
+
+ resultTypes: append([]Class(nil), types...),
+ }
+ p.run()
+ return p
+}
+
+func (p *paragraph) Len() int { return len(p.initialTypes) }
+
+// The algorithm. Does not include line-based processing (Rules L1, L2).
+// These are applied later in the line-based phase of the algorithm.
+func (p *paragraph) run() {
+ p.determineMatchingIsolates()
+
+ // 1) determining the paragraph level
+ // Rule P1 is the requirement for entering this algorithm.
+ // Rules P2, P3.
+ // If no externally supplied paragraph embedding level, use default.
+ if p.embeddingLevel == implicitLevel {
+ p.embeddingLevel = p.determineParagraphEmbeddingLevel(0, p.Len())
+ }
+
+ // Initialize result levels to paragraph embedding level.
+ p.resultLevels = make([]level, p.Len())
+ setLevels(p.resultLevels, p.embeddingLevel)
+
+ // 2) Explicit levels and directions
+ // Rules X1-X8.
+ p.determineExplicitEmbeddingLevels()
+
+ // Rule X9.
+ // We do not remove the embeddings, the overrides, the PDFs, and the BNs
+ // from the string explicitly. But they are not copied into isolating run
+ // sequences when they are created, so they are removed for all
+ // practical purposes.
+
+ // Rule X10.
+ // Run remainder of algorithm one isolating run sequence at a time
+ for _, seq := range p.determineIsolatingRunSequences() {
+ // 3) resolving weak types
+ // Rules W1-W7.
+ seq.resolveWeakTypes()
+
+ // 4a) resolving paired brackets
+ // Rule N0
+ resolvePairedBrackets(seq)
+
+ // 4b) resolving neutral types
+ // Rules N1-N3.
+ seq.resolveNeutralTypes()
+
+ // 5) resolving implicit embedding levels
+ // Rules I1, I2.
+ seq.resolveImplicitLevels()
+
+ // Apply the computed levels and types
+ seq.applyLevelsAndTypes()
+ }
+
+ // Assign appropriate levels to 'hide' LREs, RLEs, LROs, RLOs, PDFs, and
+ // BNs. This is for convenience, so the resulting level array will have
+ // a value for every character.
+ p.assignLevelsToCharactersRemovedByX9()
+}
+
+// determineMatchingIsolates determines the matching PDI for each isolate
+// initiator and vice versa.
+//
+// Definition BD9.
+//
+// At the end of this function:
+//
+// - The member variable matchingPDI is set to point to the index of the
+// matching PDI character for each isolate initiator character. If there is
+// no matching PDI, it is set to the length of the input text. For other
+// characters, it is set to -1.
+// - The member variable matchingIsolateInitiator is set to point to the
+// index of the matching isolate initiator character for each PDI character.
+// If there is no matching isolate initiator, or the character is not a PDI,
+// it is set to -1.
+func (p *paragraph) determineMatchingIsolates() {
+ p.matchingPDI = make([]int, p.Len())
+ p.matchingIsolateInitiator = make([]int, p.Len())
+
+ for i := range p.matchingIsolateInitiator {
+ p.matchingIsolateInitiator[i] = -1
+ }
+
+ for i := range p.matchingPDI {
+ p.matchingPDI[i] = -1
+
+ if t := p.resultTypes[i]; t.in(LRI, RLI, FSI) {
+ depthCounter := 1
+ for j := i + 1; j < p.Len(); j++ {
+ if u := p.resultTypes[j]; u.in(LRI, RLI, FSI) {
+ depthCounter++
+ } else if u == PDI {
+ if depthCounter--; depthCounter == 0 {
+ p.matchingPDI[i] = j
+ p.matchingIsolateInitiator[j] = i
+ break
+ }
+ }
+ }
+ if p.matchingPDI[i] == -1 {
+ p.matchingPDI[i] = p.Len()
+ }
+ }
+ }
+}
+
+// determineParagraphEmbeddingLevel reports the resolved paragraph direction of
+// the substring limited by the given range [start, end).
+//
+// Determines the paragraph level based on rules P2, P3. This is also used
+// in rule X5c to find if an FSI should resolve to LRI or RLI.
+func (p *paragraph) determineParagraphEmbeddingLevel(start, end int) level {
+ var strongType Class = unknownClass
+
+ // Rule P2.
+ for i := start; i < end; i++ {
+ if t := p.resultTypes[i]; t.in(L, AL, R) {
+ strongType = t
+ break
+ } else if t.in(FSI, LRI, RLI) {
+ i = p.matchingPDI[i] // skip over to the matching PDI
+ if i > end {
+ log.Panic("assert (i <= end)")
+ }
+ }
+ }
+ // Rule P3.
+ switch strongType {
+ case unknownClass: // none found
+ // default embedding level when no strong types found is 0.
+ return 0
+ case L:
+ return 0
+ default: // AL, R
+ return 1
+ }
+}
+
+const maxDepth = 125
+
+// This stack will store the embedding levels and override and isolated
+// statuses
+type directionalStatusStack struct {
+ stackCounter int
+ embeddingLevelStack [maxDepth + 1]level
+ overrideStatusStack [maxDepth + 1]Class
+ isolateStatusStack [maxDepth + 1]bool
+}
+
+func (s *directionalStatusStack) empty() { s.stackCounter = 0 }
+func (s *directionalStatusStack) pop() { s.stackCounter-- }
+func (s *directionalStatusStack) depth() int { return s.stackCounter }
+
+func (s *directionalStatusStack) push(level level, overrideStatus Class, isolateStatus bool) {
+ s.embeddingLevelStack[s.stackCounter] = level
+ s.overrideStatusStack[s.stackCounter] = overrideStatus
+ s.isolateStatusStack[s.stackCounter] = isolateStatus
+ s.stackCounter++
+}
+
+func (s *directionalStatusStack) lastEmbeddingLevel() level {
+ return s.embeddingLevelStack[s.stackCounter-1]
+}
+
+func (s *directionalStatusStack) lastDirectionalOverrideStatus() Class {
+ return s.overrideStatusStack[s.stackCounter-1]
+}
+
+func (s *directionalStatusStack) lastDirectionalIsolateStatus() bool {
+ return s.isolateStatusStack[s.stackCounter-1]
+}
+
+// Determine explicit levels using rules X1 - X8
+func (p *paragraph) determineExplicitEmbeddingLevels() {
+ var stack directionalStatusStack
+ var overflowIsolateCount, overflowEmbeddingCount, validIsolateCount int
+
+ // Rule X1.
+ stack.push(p.embeddingLevel, ON, false)
+
+ for i, t := range p.resultTypes {
+ // Rules X2, X3, X4, X5, X5a, X5b, X5c
+ switch t {
+ case RLE, LRE, RLO, LRO, RLI, LRI, FSI:
+ isIsolate := t.in(RLI, LRI, FSI)
+ isRTL := t.in(RLE, RLO, RLI)
+
+ // override if this is an FSI that resolves to RLI
+ if t == FSI {
+ isRTL = (p.determineParagraphEmbeddingLevel(i+1, p.matchingPDI[i]) == 1)
+ }
+ if isIsolate {
+ p.resultLevels[i] = stack.lastEmbeddingLevel()
+ if stack.lastDirectionalOverrideStatus() != ON {
+ p.resultTypes[i] = stack.lastDirectionalOverrideStatus()
+ }
+ }
+
+ var newLevel level
+ if isRTL {
+ // least greater odd
+ newLevel = (stack.lastEmbeddingLevel() + 1) | 1
+ } else {
+ // least greater even
+ newLevel = (stack.lastEmbeddingLevel() + 2) &^ 1
+ }
+
+ if newLevel <= maxDepth && overflowIsolateCount == 0 && overflowEmbeddingCount == 0 {
+ if isIsolate {
+ validIsolateCount++
+ }
+ // Push new embedding level, override status, and isolated
+ // status.
+ // No check for valid stack counter, since the level check
+ // suffices.
+ switch t {
+ case LRO:
+ stack.push(newLevel, L, isIsolate)
+ case RLO:
+ stack.push(newLevel, R, isIsolate)
+ default:
+ stack.push(newLevel, ON, isIsolate)
+ }
+ // Not really part of the spec
+ if !isIsolate {
+ p.resultLevels[i] = newLevel
+ }
+ } else {
+ // This is an invalid explicit formatting character,
+ // so apply the "Otherwise" part of rules X2-X5b.
+ if isIsolate {
+ overflowIsolateCount++
+ } else { // !isIsolate
+ if overflowIsolateCount == 0 {
+ overflowEmbeddingCount++
+ }
+ }
+ }
+
+ // Rule X6a
+ case PDI:
+ if overflowIsolateCount > 0 {
+ overflowIsolateCount--
+ } else if validIsolateCount == 0 {
+ // do nothing
+ } else {
+ overflowEmbeddingCount = 0
+ for !stack.lastDirectionalIsolateStatus() {
+ stack.pop()
+ }
+ stack.pop()
+ validIsolateCount--
+ }
+ p.resultLevels[i] = stack.lastEmbeddingLevel()
+
+ // Rule X7
+ case PDF:
+ // Not really part of the spec
+ p.resultLevels[i] = stack.lastEmbeddingLevel()
+
+ if overflowIsolateCount > 0 {
+ // do nothing
+ } else if overflowEmbeddingCount > 0 {
+ overflowEmbeddingCount--
+ } else if !stack.lastDirectionalIsolateStatus() && stack.depth() >= 2 {
+ stack.pop()
+ }
+
+ case B: // paragraph separator.
+ // Rule X8.
+
+ // These values are reset for clarity, in this implementation B
+ // can only occur as the last code in the array.
+ stack.empty()
+ overflowIsolateCount = 0
+ overflowEmbeddingCount = 0
+ validIsolateCount = 0
+ p.resultLevels[i] = p.embeddingLevel
+
+ default:
+ p.resultLevels[i] = stack.lastEmbeddingLevel()
+ if stack.lastDirectionalOverrideStatus() != ON {
+ p.resultTypes[i] = stack.lastDirectionalOverrideStatus()
+ }
+ }
+ }
+}
+
+type isolatingRunSequence struct {
+ p *paragraph
+
+ indexes []int // indexes to the original string
+
+ types []Class // type of each character using the index
+ resolvedLevels []level // resolved levels after application of rules
+ level level
+ sos, eos Class
+}
+
+func (i *isolatingRunSequence) Len() int { return len(i.indexes) }
+
+func maxLevel(a, b level) level {
+ if a > b {
+ return a
+ }
+ return b
+}
+
+// Rule X10, second bullet: Determine the start-of-sequence (sos) and end-of-sequence (eos) types,
+// either L or R, for each isolating run sequence.
+func (p *paragraph) isolatingRunSequence(indexes []int) *isolatingRunSequence {
+ length := len(indexes)
+ types := make([]Class, length)
+ for i, x := range indexes {
+ types[i] = p.resultTypes[x]
+ }
+
+ // assign level, sos and eos
+ prevChar := indexes[0] - 1
+ for prevChar >= 0 && isRemovedByX9(p.initialTypes[prevChar]) {
+ prevChar--
+ }
+ prevLevel := p.embeddingLevel
+ if prevChar >= 0 {
+ prevLevel = p.resultLevels[prevChar]
+ }
+
+ var succLevel level
+ lastType := types[length-1]
+ if lastType.in(LRI, RLI, FSI) {
+ succLevel = p.embeddingLevel
+ } else {
+ // the first character after the end of run sequence
+ limit := indexes[length-1] + 1
+ for ; limit < p.Len() && isRemovedByX9(p.initialTypes[limit]); limit++ {
+
+ }
+ succLevel = p.embeddingLevel
+ if limit < p.Len() {
+ succLevel = p.resultLevels[limit]
+ }
+ }
+ level := p.resultLevels[indexes[0]]
+ return &isolatingRunSequence{
+ p: p,
+ indexes: indexes,
+ types: types,
+ level: level,
+ sos: typeForLevel(maxLevel(prevLevel, level)),
+ eos: typeForLevel(maxLevel(succLevel, level)),
+ }
+}
+
+// Resolving weak types Rules W1-W7.
+//
+// Note that some weak types (EN, AN) remain after this processing is
+// complete.
+func (s *isolatingRunSequence) resolveWeakTypes() {
+
+ // on entry, only these types remain
+ s.assertOnly(L, R, AL, EN, ES, ET, AN, CS, B, S, WS, ON, NSM, LRI, RLI, FSI, PDI)
+
+ // Rule W1.
+ // Changes all NSMs.
+ preceedingCharacterType := s.sos
+ for i, t := range s.types {
+ if t == NSM {
+ s.types[i] = preceedingCharacterType
+ } else {
+ if t.in(LRI, RLI, FSI, PDI) {
+ preceedingCharacterType = ON
+ }
+ preceedingCharacterType = t
+ }
+ }
+
+ // Rule W2.
+ // EN does not change at the start of the run, because sos != AL.
+ for i, t := range s.types {
+ if t == EN {
+ for j := i - 1; j >= 0; j-- {
+ if t := s.types[j]; t.in(L, R, AL) {
+ if t == AL {
+ s.types[i] = AN
+ }
+ break
+ }
+ }
+ }
+ }
+
+ // Rule W3.
+ for i, t := range s.types {
+ if t == AL {
+ s.types[i] = R
+ }
+ }
+
+ // Rule W4.
+ // Since there must be values on both sides for this rule to have an
+ // effect, the scan skips the first and last value.
+ //
+ // Although the scan proceeds left to right, and changes the type
+ // values in a way that would appear to affect the computations
+ // later in the scan, there is actually no problem. A change in the
+ // current value can only affect the value to its immediate right,
+ // and only affect it if it is ES or CS. But the current value can
+ // only change if the value to its right is not ES or CS. Thus
+ // either the current value will not change, or its change will have
+ // no effect on the remainder of the analysis.
+
+ for i := 1; i < s.Len()-1; i++ {
+ t := s.types[i]
+ if t == ES || t == CS {
+ prevSepType := s.types[i-1]
+ succSepType := s.types[i+1]
+ if prevSepType == EN && succSepType == EN {
+ s.types[i] = EN
+ } else if s.types[i] == CS && prevSepType == AN && succSepType == AN {
+ s.types[i] = AN
+ }
+ }
+ }
+
+ // Rule W5.
+ for i, t := range s.types {
+ if t == ET {
+ // locate end of sequence
+ runStart := i
+ runEnd := s.findRunLimit(runStart, ET)
+
+ // check values at ends of sequence
+ t := s.sos
+ if runStart > 0 {
+ t = s.types[runStart-1]
+ }
+ if t != EN {
+ t = s.eos
+ if runEnd < len(s.types) {
+ t = s.types[runEnd]
+ }
+ }
+ if t == EN {
+ setTypes(s.types[runStart:runEnd], EN)
+ }
+ // continue at end of sequence
+ i = runEnd
+ }
+ }
+
+ // Rule W6.
+ for i, t := range s.types {
+ if t.in(ES, ET, CS) {
+ s.types[i] = ON
+ }
+ }
+
+ // Rule W7.
+ for i, t := range s.types {
+ if t == EN {
+ // set default if we reach start of run
+ prevStrongType := s.sos
+ for j := i - 1; j >= 0; j-- {
+ t = s.types[j]
+ if t == L || t == R { // AL's have been changed to R
+ prevStrongType = t
+ break
+ }
+ }
+ if prevStrongType == L {
+ s.types[i] = L
+ }
+ }
+ }
+}
+
+// 6) resolving neutral types Rules N1-N2.
+func (s *isolatingRunSequence) resolveNeutralTypes() {
+
+ // on entry, only these types can be in resultTypes
+ s.assertOnly(L, R, EN, AN, B, S, WS, ON, RLI, LRI, FSI, PDI)
+
+ for i, t := range s.types {
+ switch t {
+ case WS, ON, B, S, RLI, LRI, FSI, PDI:
+ // find bounds of run of neutrals
+ runStart := i
+ runEnd := s.findRunLimit(runStart, B, S, WS, ON, RLI, LRI, FSI, PDI)
+
+ // determine effective types at ends of run
+ var leadType, trailType Class
+
+ // Note that the character found can only be L, R, AN, or
+ // EN.
+ if runStart == 0 {
+ leadType = s.sos
+ } else {
+ leadType = s.types[runStart-1]
+ if leadType.in(AN, EN) {
+ leadType = R
+ }
+ }
+ if runEnd == len(s.types) {
+ trailType = s.eos
+ } else {
+ trailType = s.types[runEnd]
+ if trailType.in(AN, EN) {
+ trailType = R
+ }
+ }
+
+ var resolvedType Class
+ if leadType == trailType {
+ // Rule N1.
+ resolvedType = leadType
+ } else {
+ // Rule N2.
+ // Notice the embedding level of the run is used, not
+ // the paragraph embedding level.
+ resolvedType = typeForLevel(s.level)
+ }
+
+ setTypes(s.types[runStart:runEnd], resolvedType)
+
+ // skip over run of (former) neutrals
+ i = runEnd
+ }
+ }
+}
+
+func setLevels(levels []level, newLevel level) {
+ for i := range levels {
+ levels[i] = newLevel
+ }
+}
+
+func setTypes(types []Class, newType Class) {
+ for i := range types {
+ types[i] = newType
+ }
+}
+
+// 7) resolving implicit embedding levels Rules I1, I2.
+func (s *isolatingRunSequence) resolveImplicitLevels() {
+
+ // on entry, only these types can be in resultTypes
+ s.assertOnly(L, R, EN, AN)
+
+ s.resolvedLevels = make([]level, len(s.types))
+ setLevels(s.resolvedLevels, s.level)
+
+ if (s.level & 1) == 0 { // even level
+ for i, t := range s.types {
+ // Rule I1.
+ if t == L {
+ // no change
+ } else if t == R {
+ s.resolvedLevels[i] += 1
+ } else { // t == AN || t == EN
+ s.resolvedLevels[i] += 2
+ }
+ }
+ } else { // odd level
+ for i, t := range s.types {
+ // Rule I2.
+ if t == R {
+ // no change
+ } else { // t == L || t == AN || t == EN
+ s.resolvedLevels[i] += 1
+ }
+ }
+ }
+}
+
+// Applies the levels and types resolved in rules W1-I2 to the
+// resultLevels array.
+func (s *isolatingRunSequence) applyLevelsAndTypes() {
+ for i, x := range s.indexes {
+ s.p.resultTypes[x] = s.types[i]
+ s.p.resultLevels[x] = s.resolvedLevels[i]
+ }
+}
+
+// Return the limit of the run consisting only of the types in validSet
+// starting at index. This checks the value at index, and will return
+// index if that value is not in validSet.
+func (s *isolatingRunSequence) findRunLimit(index int, validSet ...Class) int {
+loop:
+ for ; index < len(s.types); index++ {
+ t := s.types[index]
+ for _, valid := range validSet {
+ if t == valid {
+ continue loop
+ }
+ }
+ return index // didn't find a match in validSet
+ }
+ return len(s.types)
+}
+
+// Algorithm validation. Assert that all values in types are in the
+// provided set.
+func (s *isolatingRunSequence) assertOnly(codes ...Class) {
+loop:
+ for i, t := range s.types {
+ for _, c := range codes {
+ if t == c {
+ continue loop
+ }
+ }
+ log.Panicf("invalid bidi code %v present in assertOnly at position %d", t, s.indexes[i])
+ }
+}
+
+// determineLevelRuns returns an array of level runs. Each level run is
+// described as an array of indexes into the input string.
+//
+// Determines the level runs. Rule X9 will be applied in determining the
+// runs, in the way that makes sure the characters that are supposed to be
+// removed are not included in the runs.
+func (p *paragraph) determineLevelRuns() [][]int {
+ run := []int{}
+ allRuns := [][]int{}
+ currentLevel := implicitLevel
+
+ for i := range p.initialTypes {
+ if !isRemovedByX9(p.initialTypes[i]) {
+ if p.resultLevels[i] != currentLevel {
+ // we just encountered a new run; wrap up last run
+ if currentLevel >= 0 { // only wrap it up if there was a run
+ allRuns = append(allRuns, run)
+ run = nil
+ }
+ // Start new run
+ currentLevel = p.resultLevels[i]
+ }
+ run = append(run, i)
+ }
+ }
+ // Wrap up the final run, if any
+ if len(run) > 0 {
+ allRuns = append(allRuns, run)
+ }
+ return allRuns
+}
+
+// Definition BD13. Determine isolating run sequences.
+func (p *paragraph) determineIsolatingRunSequences() []*isolatingRunSequence {
+ levelRuns := p.determineLevelRuns()
+
+ // Compute the run that each character belongs to
+ runForCharacter := make([]int, p.Len())
+ for i, run := range levelRuns {
+ for _, index := range run {
+ runForCharacter[index] = i
+ }
+ }
+
+ sequences := []*isolatingRunSequence{}
+
+ var currentRunSequence []int
+
+ for _, run := range levelRuns {
+ first := run[0]
+ if p.initialTypes[first] != PDI || p.matchingIsolateInitiator[first] == -1 {
+ currentRunSequence = nil
+ // int run = i;
+ for {
+ // Copy this level run into currentRunSequence
+ currentRunSequence = append(currentRunSequence, run...)
+
+ last := currentRunSequence[len(currentRunSequence)-1]
+ lastT := p.initialTypes[last]
+ if lastT.in(LRI, RLI, FSI) && p.matchingPDI[last] != p.Len() {
+ run = levelRuns[runForCharacter[p.matchingPDI[last]]]
+ } else {
+ break
+ }
+ }
+ sequences = append(sequences, p.isolatingRunSequence(currentRunSequence))
+ }
+ }
+ return sequences
+}
+
+// Assign level information to characters removed by rule X9. This is for
+// ease of relating the level information to the original input data. Note
+// that the levels assigned to these codes are arbitrary, they're chosen so
+// as to avoid breaking level runs.
+func (p *paragraph) assignLevelsToCharactersRemovedByX9() {
+ for i, t := range p.initialTypes {
+ if t.in(LRE, RLE, LRO, RLO, PDF, BN) {
+ p.resultTypes[i] = t
+ p.resultLevels[i] = -1
+ }
+ }
+ // now propagate forward the levels information (could have
+ // propagated backward, the main thing is not to introduce a level
+ // break where one doesn't already exist).
+
+ if p.resultLevels[0] == -1 {
+ p.resultLevels[0] = p.embeddingLevel
+ }
+ for i := 1; i < len(p.initialTypes); i++ {
+ if p.resultLevels[i] == -1 {
+ p.resultLevels[i] = p.resultLevels[i-1]
+ }
+ }
+ // Embedding information is for informational purposes only so need not be
+ // adjusted.
+}
+
+//
+// Output
+//
+
+// getLevels computes levels array breaking lines at offsets in linebreaks.
+// Rule L1.
+//
+// The linebreaks array must include at least one value. The values must be
+// in strictly increasing order (no duplicates) between 1 and the length of
+// the text, inclusive. The last value must be the length of the text.
+func (p *paragraph) getLevels(linebreaks []int) []level {
+ // Note that since the previous processing has removed all
+ // P, S, and WS values from resultTypes, the values referred to
+ // in these rules are the initial types, before any processing
+ // has been applied (including processing of overrides).
+ //
+ // This example implementation has reinserted explicit format codes
+ // and BN, in order that the levels array correspond to the
+ // initial text. Their final placement is not normative.
+ // These codes are treated like WS in this implementation,
+ // so they don't interrupt sequences of WS.
+
+ validateLineBreaks(linebreaks, p.Len())
+
+ result := append([]level(nil), p.resultLevels...)
+
+ // don't worry about linebreaks since if there is a break within
+ // a series of WS values preceding S, the linebreak itself
+ // causes the reset.
+ for i, t := range p.initialTypes {
+ if t.in(B, S) {
+ // Rule L1, clauses one and two.
+ result[i] = p.embeddingLevel
+
+ // Rule L1, clause three.
+ for j := i - 1; j >= 0; j-- {
+ if isWhitespace(p.initialTypes[j]) { // including format codes
+ result[j] = p.embeddingLevel
+ } else {
+ break
+ }
+ }
+ }
+ }
+
+ // Rule L1, clause four.
+ start := 0
+ for _, limit := range linebreaks {
+ for j := limit - 1; j >= start; j-- {
+ if isWhitespace(p.initialTypes[j]) { // including format codes
+ result[j] = p.embeddingLevel
+ } else {
+ break
+ }
+ }
+ start = limit
+ }
+
+ return result
+}
+
+// getReordering returns the reordering of lines from a visual index to a
+// logical index for line breaks at the given offsets.
+//
+// Lines are concatenated from left to right. So for example, the fifth
+// character from the left on the third line is
+//
+// getReordering(linebreaks)[linebreaks[1] + 4]
+//
+// (linebreaks[1] is the position after the last character of the second
+// line, which is also the index of the first character on the third line,
+// and adding four gets the fifth character from the left).
+//
+// The linebreaks array must include at least one value. The values must be
+// in strictly increasing order (no duplicates) between 1 and the length of
+// the text, inclusive. The last value must be the length of the text.
+func (p *paragraph) getReordering(linebreaks []int) []int {
+ validateLineBreaks(linebreaks, p.Len())
+
+ return computeMultilineReordering(p.getLevels(linebreaks), linebreaks)
+}
+
+// Return multiline reordering array for a given level array. Reordering
+// does not occur across a line break.
+func computeMultilineReordering(levels []level, linebreaks []int) []int {
+ result := make([]int, len(levels))
+
+ start := 0
+ for _, limit := range linebreaks {
+ tempLevels := make([]level, limit-start)
+ copy(tempLevels, levels[start:])
+
+ for j, order := range computeReordering(tempLevels) {
+ result[start+j] = order + start
+ }
+ start = limit
+ }
+ return result
+}
+
+// Return reordering array for a given level array. This reorders a single
+// line. The reordering is a visual to logical map. For example, the
+// leftmost char is string.charAt(order[0]). Rule L2.
+func computeReordering(levels []level) []int {
+ result := make([]int, len(levels))
+ // initialize order
+ for i := range result {
+ result[i] = i
+ }
+
+ // locate highest level found on line.
+ // Note the rules say text, but no reordering across line bounds is
+ // performed, so this is sufficient.
+ highestLevel := level(0)
+ lowestOddLevel := level(maxDepth + 2)
+ for _, level := range levels {
+ if level > highestLevel {
+ highestLevel = level
+ }
+ if level&1 != 0 && level < lowestOddLevel {
+ lowestOddLevel = level
+ }
+ }
+
+ for level := highestLevel; level >= lowestOddLevel; level-- {
+ for i := 0; i < len(levels); i++ {
+ if levels[i] >= level {
+ // find range of text at or above this level
+ start := i
+ limit := i + 1
+ for limit < len(levels) && levels[limit] >= level {
+ limit++
+ }
+
+ for j, k := start, limit-1; j < k; j, k = j+1, k-1 {
+ result[j], result[k] = result[k], result[j]
+ }
+ // skip to end of level run
+ i = limit
+ }
+ }
+ }
+
+ return result
+}
+
+// isWhitespace reports whether the type is considered a whitespace type for the
+// line break rules.
+func isWhitespace(c Class) bool {
+ switch c {
+ case LRE, RLE, LRO, RLO, PDF, LRI, RLI, FSI, PDI, BN, WS:
+ return true
+ }
+ return false
+}
+
+// isRemovedByX9 reports whether the type is one of the types removed in X9.
+func isRemovedByX9(c Class) bool {
+ switch c {
+ case LRE, RLE, LRO, RLO, PDF, BN:
+ return true
+ }
+ return false
+}
+
+// typeForLevel reports the strong type (L or R) corresponding to the level.
+func typeForLevel(level level) Class {
+ if (level & 0x1) == 0 {
+ return L
+ }
+ return R
+}
+
+// TODO: change validation to not panic
+
+func validateTypes(types []Class) {
+ if len(types) == 0 {
+ log.Panic("types is null")
+ }
+ for i, t := range types[:len(types)-1] {
+ if t == B {
+ log.Panicf("B type before end of paragraph at index: %d", i)
+ }
+ }
+}
+
+func validateParagraphEmbeddingLevel(embeddingLevel level) {
+ if embeddingLevel != implicitLevel &&
+ embeddingLevel != 0 &&
+ embeddingLevel != 1 {
+ log.Panicf("illegal paragraph embedding level: %d", embeddingLevel)
+ }
+}
+
+func validateLineBreaks(linebreaks []int, textLength int) {
+ prev := 0
+ for i, next := range linebreaks {
+ if next <= prev {
+ log.Panicf("bad linebreak: %d at index: %d", next, i)
+ }
+ prev = next
+ }
+ if prev != textLength {
+ log.Panicf("last linebreak was %d, want %d", prev, textLength)
+ }
+}
+
+func validatePbTypes(pairTypes []bracketType) {
+ if len(pairTypes) == 0 {
+ log.Panic("pairTypes is null")
+ }
+ for i, pt := range pairTypes {
+ switch pt {
+ case bpNone, bpOpen, bpClose:
+ default:
+ log.Panicf("illegal pairType value at %d: %v", i, pairTypes[i])
+ }
+ }
+}
+
+func validatePbValues(pairValues []rune, pairTypes []bracketType) {
+ if pairValues == nil {
+ log.Panic("pairValues is null")
+ }
+ if len(pairTypes) != len(pairValues) {
+ log.Panic("pairTypes is different length from pairValues")
+ }
+}
diff --git a/vendor/golang.org/x/text/unicode/bidi/gen.go b/vendor/golang.org/x/text/unicode/bidi/gen.go
new file mode 100644
index 0000000..040f301
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/bidi/gen.go
@@ -0,0 +1,133 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import (
+ "flag"
+ "log"
+
+ "golang.org/x/text/internal/gen"
+ "golang.org/x/text/internal/triegen"
+ "golang.org/x/text/internal/ucd"
+)
+
+var outputFile = flag.String("out", "tables.go", "output file")
+
+func main() {
+ gen.Init()
+ gen.Repackage("gen_trieval.go", "trieval.go", "bidi")
+ gen.Repackage("gen_ranges.go", "ranges_test.go", "bidi")
+
+ genTables()
+}
+
+// bidiClass names and codes taken from class "bc" in
+// http://www.unicode.org/Public/8.0.0/ucd/PropertyValueAliases.txt
+var bidiClass = map[string]Class{
+ "AL": AL, // ArabicLetter
+ "AN": AN, // ArabicNumber
+ "B": B, // ParagraphSeparator
+ "BN": BN, // BoundaryNeutral
+ "CS": CS, // CommonSeparator
+ "EN": EN, // EuropeanNumber
+ "ES": ES, // EuropeanSeparator
+ "ET": ET, // EuropeanTerminator
+ "L": L, // LeftToRight
+ "NSM": NSM, // NonspacingMark
+ "ON": ON, // OtherNeutral
+ "R": R, // RightToLeft
+ "S": S, // SegmentSeparator
+ "WS": WS, // WhiteSpace
+
+ "FSI": Control,
+ "PDF": Control,
+ "PDI": Control,
+ "LRE": Control,
+ "LRI": Control,
+ "LRO": Control,
+ "RLE": Control,
+ "RLI": Control,
+ "RLO": Control,
+}
+
+func genTables() {
+ if numClass > 0x0F {
+ log.Fatalf("Too many Class constants (%#x > 0x0F).", numClass)
+ }
+ w := gen.NewCodeWriter()
+ defer w.WriteGoFile(*outputFile, "bidi")
+
+ gen.WriteUnicodeVersion(w)
+
+ t := triegen.NewTrie("bidi")
+
+ // Build data about bracket mapping. These bits need to be or-ed with
+ // any other bits.
+ orMask := map[rune]uint64{}
+
+ xorMap := map[rune]int{}
+ xorMasks := []rune{0} // First value is no-op.
+
+ ucd.Parse(gen.OpenUCDFile("BidiBrackets.txt"), func(p *ucd.Parser) {
+ r1 := p.Rune(0)
+ r2 := p.Rune(1)
+ xor := r1 ^ r2
+ if _, ok := xorMap[xor]; !ok {
+ xorMap[xor] = len(xorMasks)
+ xorMasks = append(xorMasks, xor)
+ }
+ entry := uint64(xorMap[xor]) << xorMaskShift
+ switch p.String(2) {
+ case "o":
+ entry |= openMask
+ case "c", "n":
+ default:
+ log.Fatalf("Unknown bracket class %q.", p.String(2))
+ }
+ orMask[r1] = entry
+ })
+
+ w.WriteComment(`
+ xorMasks contains masks to be xor-ed with brackets to get the reverse
+ version.`)
+ w.WriteVar("xorMasks", xorMasks)
+
+ done := map[rune]bool{}
+
+ insert := func(r rune, c Class) {
+ if !done[r] {
+ t.Insert(r, orMask[r]|uint64(c))
+ done[r] = true
+ }
+ }
+
+ // Insert the derived BiDi properties.
+ ucd.Parse(gen.OpenUCDFile("extracted/DerivedBidiClass.txt"), func(p *ucd.Parser) {
+ r := p.Rune(0)
+ class, ok := bidiClass[p.String(1)]
+ if !ok {
+ log.Fatalf("%U: Unknown BiDi class %q", r, p.String(1))
+ }
+ insert(r, class)
+ })
+ visitDefaults(insert)
+
+ // TODO: use sparse blocks. This would reduce table size considerably
+ // from the looks of it.
+
+ sz, err := t.Gen(w)
+ if err != nil {
+ log.Fatal(err)
+ }
+ w.Size += sz
+}
+
+// dummy values to make methods in gen_common compile. The real versions
+// will be generated by this file to tables.go.
+var (
+ xorMasks []rune
+)
diff --git a/vendor/golang.org/x/text/unicode/bidi/gen_ranges.go b/vendor/golang.org/x/text/unicode/bidi/gen_ranges.go
new file mode 100644
index 0000000..51bd68f
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/bidi/gen_ranges.go
@@ -0,0 +1,57 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import (
+ "unicode"
+
+ "golang.org/x/text/internal/gen"
+ "golang.org/x/text/internal/ucd"
+ "golang.org/x/text/unicode/rangetable"
+)
+
+// These tables are hand-extracted from:
+// http://www.unicode.org/Public/8.0.0/ucd/extracted/DerivedBidiClass.txt
+func visitDefaults(fn func(r rune, c Class)) {
+ // first write default values for ranges listed above.
+ visitRunes(fn, AL, []rune{
+ 0x0600, 0x07BF, // Arabic
+ 0x08A0, 0x08FF, // Arabic Extended-A
+ 0xFB50, 0xFDCF, // Arabic Presentation Forms
+ 0xFDF0, 0xFDFF,
+ 0xFE70, 0xFEFF,
+ 0x0001EE00, 0x0001EEFF, // Arabic Mathematical Alpha Symbols
+ })
+ visitRunes(fn, R, []rune{
+ 0x0590, 0x05FF, // Hebrew
+ 0x07C0, 0x089F, // Nko et al.
+ 0xFB1D, 0xFB4F,
+ 0x00010800, 0x00010FFF, // Cypriot Syllabary et. al.
+ 0x0001E800, 0x0001EDFF,
+ 0x0001EF00, 0x0001EFFF,
+ })
+ visitRunes(fn, ET, []rune{ // European Terminator
+ 0x20A0, 0x20Cf, // Currency symbols
+ })
+ rangetable.Visit(unicode.Noncharacter_Code_Point, func(r rune) {
+ fn(r, BN) // Boundary Neutral
+ })
+ ucd.Parse(gen.OpenUCDFile("DerivedCoreProperties.txt"), func(p *ucd.Parser) {
+ if p.String(1) == "Default_Ignorable_Code_Point" {
+ fn(p.Rune(0), BN) // Boundary Neutral
+ }
+ })
+}
+
+func visitRunes(fn func(r rune, c Class), c Class, runes []rune) {
+ for i := 0; i < len(runes); i += 2 {
+ lo, hi := runes[i], runes[i+1]
+ for j := lo; j <= hi; j++ {
+ fn(j, c)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/text/unicode/bidi/gen_trieval.go b/vendor/golang.org/x/text/unicode/bidi/gen_trieval.go
new file mode 100644
index 0000000..9cb9942
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/bidi/gen_trieval.go
@@ -0,0 +1,64 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+// Class is the Unicode BiDi class. Each rune has a single class.
+type Class uint
+
+const (
+ L Class = iota // LeftToRight
+ R // RightToLeft
+ EN // EuropeanNumber
+ ES // EuropeanSeparator
+ ET // EuropeanTerminator
+ AN // ArabicNumber
+ CS // CommonSeparator
+ B // ParagraphSeparator
+ S // SegmentSeparator
+ WS // WhiteSpace
+ ON // OtherNeutral
+ BN // BoundaryNeutral
+ NSM // NonspacingMark
+ AL // ArabicLetter
+ Control // Control LRO - PDI
+
+ numClass
+
+ LRO // LeftToRightOverride
+ RLO // RightToLeftOverride
+ LRE // LeftToRightEmbedding
+ RLE // RightToLeftEmbedding
+ PDF // PopDirectionalFormat
+ LRI // LeftToRightIsolate
+ RLI // RightToLeftIsolate
+ FSI // FirstStrongIsolate
+ PDI // PopDirectionalIsolate
+
+ unknownClass = ^Class(0)
+)
+
+var controlToClass = map[rune]Class{
+ 0x202D: LRO, // LeftToRightOverride,
+ 0x202E: RLO, // RightToLeftOverride,
+ 0x202A: LRE, // LeftToRightEmbedding,
+ 0x202B: RLE, // RightToLeftEmbedding,
+ 0x202C: PDF, // PopDirectionalFormat,
+ 0x2066: LRI, // LeftToRightIsolate,
+ 0x2067: RLI, // RightToLeftIsolate,
+ 0x2068: FSI, // FirstStrongIsolate,
+ 0x2069: PDI, // PopDirectionalIsolate,
+}
+
+// A trie entry has the following bits:
+// 7..5 XOR mask for brackets
+// 4 1: Bracket open, 0: Bracket close
+// 3..0 Class type
+
+const (
+ openMask = 0x10
+ xorMaskShift = 5
+)
diff --git a/vendor/golang.org/x/text/unicode/bidi/prop.go b/vendor/golang.org/x/text/unicode/bidi/prop.go
new file mode 100644
index 0000000..7c9484e
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/bidi/prop.go
@@ -0,0 +1,206 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bidi
+
+import "unicode/utf8"
+
+// Properties provides access to BiDi properties of runes.
+type Properties struct {
+ entry uint8
+ last uint8
+}
+
+var trie = newBidiTrie(0)
+
+// TODO: using this for bidirule reduces the running time by about 5%. Consider
+// if this is worth exposing or if we can find a way to speed up the Class
+// method.
+//
+// // CompactClass is like Class, but maps all of the BiDi control classes
+// // (LRO, RLO, LRE, RLE, PDF, LRI, RLI, FSI, PDI) to the class Control.
+// func (p Properties) CompactClass() Class {
+// return Class(p.entry & 0x0F)
+// }
+
+// Class returns the Bidi class for p.
+func (p Properties) Class() Class {
+ c := Class(p.entry & 0x0F)
+ if c == Control {
+ c = controlByteToClass[p.last&0xF]
+ }
+ return c
+}
+
+// IsBracket reports whether the rune is a bracket.
+func (p Properties) IsBracket() bool { return p.entry&0xF0 != 0 }
+
+// IsOpeningBracket reports whether the rune is an opening bracket.
+// IsBracket must return true.
+func (p Properties) IsOpeningBracket() bool { return p.entry&openMask != 0 }
+
+// TODO: find a better API and expose.
+func (p Properties) reverseBracket(r rune) rune {
+ return xorMasks[p.entry>>xorMaskShift] ^ r
+}
+
+var controlByteToClass = [16]Class{
+ 0xD: LRO, // U+202D LeftToRightOverride,
+ 0xE: RLO, // U+202E RightToLeftOverride,
+ 0xA: LRE, // U+202A LeftToRightEmbedding,
+ 0xB: RLE, // U+202B RightToLeftEmbedding,
+ 0xC: PDF, // U+202C PopDirectionalFormat,
+ 0x6: LRI, // U+2066 LeftToRightIsolate,
+ 0x7: RLI, // U+2067 RightToLeftIsolate,
+ 0x8: FSI, // U+2068 FirstStrongIsolate,
+ 0x9: PDI, // U+2069 PopDirectionalIsolate,
+}
+
+// LookupRune returns properties for r.
+func LookupRune(r rune) (p Properties, size int) {
+ var buf [4]byte
+ n := utf8.EncodeRune(buf[:], r)
+ return Lookup(buf[:n])
+}
+
+// TODO: these lookup methods are based on the generated trie code. The returned
+// sizes have slightly different semantics from the generated code, in that it
+// always returns size==1 for an illegal UTF-8 byte (instead of the length
+// of the maximum invalid subsequence). Most Transformers, like unicode/norm,
+// leave invalid UTF-8 untouched, in which case it has performance benefits to
+// do so (without changing the semantics). Bidi requires the semantics used here
+// for the bidirule implementation to be compatible with the Go semantics.
+// They ultimately should perhaps be adopted by all trie implementations, for
+// convenience sake.
+// This unrolled code also boosts performance of the secure/bidirule package by
+// about 30%.
+// So, to remove this code:
+// - add option to trie generator to define return type.
+// - always return 1 byte size for ill-formed UTF-8 runes.
+
+// Lookup returns properties for the first rune in s and the width in bytes of
+// its encoding. The size will be 0 if s does not hold enough bytes to complete
+// the encoding.
+func Lookup(s []byte) (p Properties, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return Properties{entry: bidiValues[c0]}, 1
+ case c0 < 0xC2:
+ return Properties{}, 1
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return Properties{}, 0
+ }
+ i := bidiIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return Properties{}, 1
+ }
+ return Properties{entry: trie.lookupValue(uint32(i), c1)}, 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return Properties{}, 0
+ }
+ i := bidiIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return Properties{}, 1
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = bidiIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return Properties{}, 1
+ }
+ return Properties{entry: trie.lookupValue(uint32(i), c2), last: c2}, 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return Properties{}, 0
+ }
+ i := bidiIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return Properties{}, 1
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = bidiIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return Properties{}, 1
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = bidiIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return Properties{}, 1
+ }
+ return Properties{entry: trie.lookupValue(uint32(i), c3)}, 4
+ }
+ // Illegal rune
+ return Properties{}, 1
+}
+
+// LookupString returns properties for the first rune in s and the width in
+// bytes of its encoding. The size will be 0 if s does not hold enough bytes to
+// complete the encoding.
+func LookupString(s string) (p Properties, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return Properties{entry: bidiValues[c0]}, 1
+ case c0 < 0xC2:
+ return Properties{}, 1
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return Properties{}, 0
+ }
+ i := bidiIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return Properties{}, 1
+ }
+ return Properties{entry: trie.lookupValue(uint32(i), c1)}, 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return Properties{}, 0
+ }
+ i := bidiIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return Properties{}, 1
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = bidiIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return Properties{}, 1
+ }
+ return Properties{entry: trie.lookupValue(uint32(i), c2), last: c2}, 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return Properties{}, 0
+ }
+ i := bidiIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return Properties{}, 1
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = bidiIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return Properties{}, 1
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = bidiIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return Properties{}, 1
+ }
+ return Properties{entry: trie.lookupValue(uint32(i), c3)}, 4
+ }
+ // Illegal rune
+ return Properties{}, 1
+}
diff --git a/vendor/golang.org/x/text/unicode/bidi/tables.go b/vendor/golang.org/x/text/unicode/bidi/tables.go
new file mode 100644
index 0000000..7212d5a
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/bidi/tables.go
@@ -0,0 +1,1779 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package bidi
+
+// UnicodeVersion is the Unicode version from which the tables in this package are derived.
+const UnicodeVersion = "9.0.0"
+
+// xorMasks contains masks to be xor-ed with brackets to get the reverse
+// version.
+var xorMasks = []int32{ // 8 elements
+ 0, 1, 6, 7, 3, 15, 29, 63,
+} // Size: 56 bytes
+
+// lookup returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *bidiTrie) lookup(s []byte) (v uint8, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return bidiValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := bidiIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := bidiIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = bidiIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := bidiIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = bidiIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = bidiIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *bidiTrie) lookupUnsafe(s []byte) uint8 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return bidiValues[c0]
+ }
+ i := bidiIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = bidiIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = bidiIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// lookupString returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *bidiTrie) lookupString(s string) (v uint8, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return bidiValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := bidiIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := bidiIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = bidiIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := bidiIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = bidiIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = bidiIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *bidiTrie) lookupStringUnsafe(s string) uint8 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return bidiValues[c0]
+ }
+ i := bidiIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = bidiIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = bidiIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// bidiTrie. Total size: 15744 bytes (15.38 KiB). Checksum: b4c3b70954803b86.
+type bidiTrie struct{}
+
+func newBidiTrie(i int) *bidiTrie {
+ return &bidiTrie{}
+}
+
+// lookupValue determines the type of block n and looks up the value for b.
+func (t *bidiTrie) lookupValue(n uint32, b byte) uint8 {
+ switch {
+ default:
+ return uint8(bidiValues[n<<6+uint32(b)])
+ }
+}
+
+// bidiValues: 222 blocks, 14208 entries, 14208 bytes
+// The third block is the zero block.
+var bidiValues = [14208]uint8{
+ // Block 0x0, offset 0x0
+ 0x00: 0x000b, 0x01: 0x000b, 0x02: 0x000b, 0x03: 0x000b, 0x04: 0x000b, 0x05: 0x000b,
+ 0x06: 0x000b, 0x07: 0x000b, 0x08: 0x000b, 0x09: 0x0008, 0x0a: 0x0007, 0x0b: 0x0008,
+ 0x0c: 0x0009, 0x0d: 0x0007, 0x0e: 0x000b, 0x0f: 0x000b, 0x10: 0x000b, 0x11: 0x000b,
+ 0x12: 0x000b, 0x13: 0x000b, 0x14: 0x000b, 0x15: 0x000b, 0x16: 0x000b, 0x17: 0x000b,
+ 0x18: 0x000b, 0x19: 0x000b, 0x1a: 0x000b, 0x1b: 0x000b, 0x1c: 0x0007, 0x1d: 0x0007,
+ 0x1e: 0x0007, 0x1f: 0x0008, 0x20: 0x0009, 0x21: 0x000a, 0x22: 0x000a, 0x23: 0x0004,
+ 0x24: 0x0004, 0x25: 0x0004, 0x26: 0x000a, 0x27: 0x000a, 0x28: 0x003a, 0x29: 0x002a,
+ 0x2a: 0x000a, 0x2b: 0x0003, 0x2c: 0x0006, 0x2d: 0x0003, 0x2e: 0x0006, 0x2f: 0x0006,
+ 0x30: 0x0002, 0x31: 0x0002, 0x32: 0x0002, 0x33: 0x0002, 0x34: 0x0002, 0x35: 0x0002,
+ 0x36: 0x0002, 0x37: 0x0002, 0x38: 0x0002, 0x39: 0x0002, 0x3a: 0x0006, 0x3b: 0x000a,
+ 0x3c: 0x000a, 0x3d: 0x000a, 0x3e: 0x000a, 0x3f: 0x000a,
+ // Block 0x1, offset 0x40
+ 0x40: 0x000a,
+ 0x5b: 0x005a, 0x5c: 0x000a, 0x5d: 0x004a,
+ 0x5e: 0x000a, 0x5f: 0x000a, 0x60: 0x000a,
+ 0x7b: 0x005a,
+ 0x7c: 0x000a, 0x7d: 0x004a, 0x7e: 0x000a, 0x7f: 0x000b,
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc0: 0x000b, 0xc1: 0x000b, 0xc2: 0x000b, 0xc3: 0x000b, 0xc4: 0x000b, 0xc5: 0x0007,
+ 0xc6: 0x000b, 0xc7: 0x000b, 0xc8: 0x000b, 0xc9: 0x000b, 0xca: 0x000b, 0xcb: 0x000b,
+ 0xcc: 0x000b, 0xcd: 0x000b, 0xce: 0x000b, 0xcf: 0x000b, 0xd0: 0x000b, 0xd1: 0x000b,
+ 0xd2: 0x000b, 0xd3: 0x000b, 0xd4: 0x000b, 0xd5: 0x000b, 0xd6: 0x000b, 0xd7: 0x000b,
+ 0xd8: 0x000b, 0xd9: 0x000b, 0xda: 0x000b, 0xdb: 0x000b, 0xdc: 0x000b, 0xdd: 0x000b,
+ 0xde: 0x000b, 0xdf: 0x000b, 0xe0: 0x0006, 0xe1: 0x000a, 0xe2: 0x0004, 0xe3: 0x0004,
+ 0xe4: 0x0004, 0xe5: 0x0004, 0xe6: 0x000a, 0xe7: 0x000a, 0xe8: 0x000a, 0xe9: 0x000a,
+ 0xeb: 0x000a, 0xec: 0x000a, 0xed: 0x000b, 0xee: 0x000a, 0xef: 0x000a,
+ 0xf0: 0x0004, 0xf1: 0x0004, 0xf2: 0x0002, 0xf3: 0x0002, 0xf4: 0x000a,
+ 0xf6: 0x000a, 0xf7: 0x000a, 0xf8: 0x000a, 0xf9: 0x0002, 0xfb: 0x000a,
+ 0xfc: 0x000a, 0xfd: 0x000a, 0xfe: 0x000a, 0xff: 0x000a,
+ // Block 0x4, offset 0x100
+ 0x117: 0x000a,
+ 0x137: 0x000a,
+ // Block 0x5, offset 0x140
+ 0x179: 0x000a, 0x17a: 0x000a,
+ // Block 0x6, offset 0x180
+ 0x182: 0x000a, 0x183: 0x000a, 0x184: 0x000a, 0x185: 0x000a,
+ 0x186: 0x000a, 0x187: 0x000a, 0x188: 0x000a, 0x189: 0x000a, 0x18a: 0x000a, 0x18b: 0x000a,
+ 0x18c: 0x000a, 0x18d: 0x000a, 0x18e: 0x000a, 0x18f: 0x000a,
+ 0x192: 0x000a, 0x193: 0x000a, 0x194: 0x000a, 0x195: 0x000a, 0x196: 0x000a, 0x197: 0x000a,
+ 0x198: 0x000a, 0x199: 0x000a, 0x19a: 0x000a, 0x19b: 0x000a, 0x19c: 0x000a, 0x19d: 0x000a,
+ 0x19e: 0x000a, 0x19f: 0x000a,
+ 0x1a5: 0x000a, 0x1a6: 0x000a, 0x1a7: 0x000a, 0x1a8: 0x000a, 0x1a9: 0x000a,
+ 0x1aa: 0x000a, 0x1ab: 0x000a, 0x1ac: 0x000a, 0x1ad: 0x000a, 0x1af: 0x000a,
+ 0x1b0: 0x000a, 0x1b1: 0x000a, 0x1b2: 0x000a, 0x1b3: 0x000a, 0x1b4: 0x000a, 0x1b5: 0x000a,
+ 0x1b6: 0x000a, 0x1b7: 0x000a, 0x1b8: 0x000a, 0x1b9: 0x000a, 0x1ba: 0x000a, 0x1bb: 0x000a,
+ 0x1bc: 0x000a, 0x1bd: 0x000a, 0x1be: 0x000a, 0x1bf: 0x000a,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x000c, 0x1c1: 0x000c, 0x1c2: 0x000c, 0x1c3: 0x000c, 0x1c4: 0x000c, 0x1c5: 0x000c,
+ 0x1c6: 0x000c, 0x1c7: 0x000c, 0x1c8: 0x000c, 0x1c9: 0x000c, 0x1ca: 0x000c, 0x1cb: 0x000c,
+ 0x1cc: 0x000c, 0x1cd: 0x000c, 0x1ce: 0x000c, 0x1cf: 0x000c, 0x1d0: 0x000c, 0x1d1: 0x000c,
+ 0x1d2: 0x000c, 0x1d3: 0x000c, 0x1d4: 0x000c, 0x1d5: 0x000c, 0x1d6: 0x000c, 0x1d7: 0x000c,
+ 0x1d8: 0x000c, 0x1d9: 0x000c, 0x1da: 0x000c, 0x1db: 0x000c, 0x1dc: 0x000c, 0x1dd: 0x000c,
+ 0x1de: 0x000c, 0x1df: 0x000c, 0x1e0: 0x000c, 0x1e1: 0x000c, 0x1e2: 0x000c, 0x1e3: 0x000c,
+ 0x1e4: 0x000c, 0x1e5: 0x000c, 0x1e6: 0x000c, 0x1e7: 0x000c, 0x1e8: 0x000c, 0x1e9: 0x000c,
+ 0x1ea: 0x000c, 0x1eb: 0x000c, 0x1ec: 0x000c, 0x1ed: 0x000c, 0x1ee: 0x000c, 0x1ef: 0x000c,
+ 0x1f0: 0x000c, 0x1f1: 0x000c, 0x1f2: 0x000c, 0x1f3: 0x000c, 0x1f4: 0x000c, 0x1f5: 0x000c,
+ 0x1f6: 0x000c, 0x1f7: 0x000c, 0x1f8: 0x000c, 0x1f9: 0x000c, 0x1fa: 0x000c, 0x1fb: 0x000c,
+ 0x1fc: 0x000c, 0x1fd: 0x000c, 0x1fe: 0x000c, 0x1ff: 0x000c,
+ // Block 0x8, offset 0x200
+ 0x200: 0x000c, 0x201: 0x000c, 0x202: 0x000c, 0x203: 0x000c, 0x204: 0x000c, 0x205: 0x000c,
+ 0x206: 0x000c, 0x207: 0x000c, 0x208: 0x000c, 0x209: 0x000c, 0x20a: 0x000c, 0x20b: 0x000c,
+ 0x20c: 0x000c, 0x20d: 0x000c, 0x20e: 0x000c, 0x20f: 0x000c, 0x210: 0x000c, 0x211: 0x000c,
+ 0x212: 0x000c, 0x213: 0x000c, 0x214: 0x000c, 0x215: 0x000c, 0x216: 0x000c, 0x217: 0x000c,
+ 0x218: 0x000c, 0x219: 0x000c, 0x21a: 0x000c, 0x21b: 0x000c, 0x21c: 0x000c, 0x21d: 0x000c,
+ 0x21e: 0x000c, 0x21f: 0x000c, 0x220: 0x000c, 0x221: 0x000c, 0x222: 0x000c, 0x223: 0x000c,
+ 0x224: 0x000c, 0x225: 0x000c, 0x226: 0x000c, 0x227: 0x000c, 0x228: 0x000c, 0x229: 0x000c,
+ 0x22a: 0x000c, 0x22b: 0x000c, 0x22c: 0x000c, 0x22d: 0x000c, 0x22e: 0x000c, 0x22f: 0x000c,
+ 0x234: 0x000a, 0x235: 0x000a,
+ 0x23e: 0x000a,
+ // Block 0x9, offset 0x240
+ 0x244: 0x000a, 0x245: 0x000a,
+ 0x247: 0x000a,
+ // Block 0xa, offset 0x280
+ 0x2b6: 0x000a,
+ // Block 0xb, offset 0x2c0
+ 0x2c3: 0x000c, 0x2c4: 0x000c, 0x2c5: 0x000c,
+ 0x2c6: 0x000c, 0x2c7: 0x000c, 0x2c8: 0x000c, 0x2c9: 0x000c,
+ // Block 0xc, offset 0x300
+ 0x30a: 0x000a,
+ 0x30d: 0x000a, 0x30e: 0x000a, 0x30f: 0x0004, 0x310: 0x0001, 0x311: 0x000c,
+ 0x312: 0x000c, 0x313: 0x000c, 0x314: 0x000c, 0x315: 0x000c, 0x316: 0x000c, 0x317: 0x000c,
+ 0x318: 0x000c, 0x319: 0x000c, 0x31a: 0x000c, 0x31b: 0x000c, 0x31c: 0x000c, 0x31d: 0x000c,
+ 0x31e: 0x000c, 0x31f: 0x000c, 0x320: 0x000c, 0x321: 0x000c, 0x322: 0x000c, 0x323: 0x000c,
+ 0x324: 0x000c, 0x325: 0x000c, 0x326: 0x000c, 0x327: 0x000c, 0x328: 0x000c, 0x329: 0x000c,
+ 0x32a: 0x000c, 0x32b: 0x000c, 0x32c: 0x000c, 0x32d: 0x000c, 0x32e: 0x000c, 0x32f: 0x000c,
+ 0x330: 0x000c, 0x331: 0x000c, 0x332: 0x000c, 0x333: 0x000c, 0x334: 0x000c, 0x335: 0x000c,
+ 0x336: 0x000c, 0x337: 0x000c, 0x338: 0x000c, 0x339: 0x000c, 0x33a: 0x000c, 0x33b: 0x000c,
+ 0x33c: 0x000c, 0x33d: 0x000c, 0x33e: 0x0001, 0x33f: 0x000c,
+ // Block 0xd, offset 0x340
+ 0x340: 0x0001, 0x341: 0x000c, 0x342: 0x000c, 0x343: 0x0001, 0x344: 0x000c, 0x345: 0x000c,
+ 0x346: 0x0001, 0x347: 0x000c, 0x348: 0x0001, 0x349: 0x0001, 0x34a: 0x0001, 0x34b: 0x0001,
+ 0x34c: 0x0001, 0x34d: 0x0001, 0x34e: 0x0001, 0x34f: 0x0001, 0x350: 0x0001, 0x351: 0x0001,
+ 0x352: 0x0001, 0x353: 0x0001, 0x354: 0x0001, 0x355: 0x0001, 0x356: 0x0001, 0x357: 0x0001,
+ 0x358: 0x0001, 0x359: 0x0001, 0x35a: 0x0001, 0x35b: 0x0001, 0x35c: 0x0001, 0x35d: 0x0001,
+ 0x35e: 0x0001, 0x35f: 0x0001, 0x360: 0x0001, 0x361: 0x0001, 0x362: 0x0001, 0x363: 0x0001,
+ 0x364: 0x0001, 0x365: 0x0001, 0x366: 0x0001, 0x367: 0x0001, 0x368: 0x0001, 0x369: 0x0001,
+ 0x36a: 0x0001, 0x36b: 0x0001, 0x36c: 0x0001, 0x36d: 0x0001, 0x36e: 0x0001, 0x36f: 0x0001,
+ 0x370: 0x0001, 0x371: 0x0001, 0x372: 0x0001, 0x373: 0x0001, 0x374: 0x0001, 0x375: 0x0001,
+ 0x376: 0x0001, 0x377: 0x0001, 0x378: 0x0001, 0x379: 0x0001, 0x37a: 0x0001, 0x37b: 0x0001,
+ 0x37c: 0x0001, 0x37d: 0x0001, 0x37e: 0x0001, 0x37f: 0x0001,
+ // Block 0xe, offset 0x380
+ 0x380: 0x0005, 0x381: 0x0005, 0x382: 0x0005, 0x383: 0x0005, 0x384: 0x0005, 0x385: 0x0005,
+ 0x386: 0x000a, 0x387: 0x000a, 0x388: 0x000d, 0x389: 0x0004, 0x38a: 0x0004, 0x38b: 0x000d,
+ 0x38c: 0x0006, 0x38d: 0x000d, 0x38e: 0x000a, 0x38f: 0x000a, 0x390: 0x000c, 0x391: 0x000c,
+ 0x392: 0x000c, 0x393: 0x000c, 0x394: 0x000c, 0x395: 0x000c, 0x396: 0x000c, 0x397: 0x000c,
+ 0x398: 0x000c, 0x399: 0x000c, 0x39a: 0x000c, 0x39b: 0x000d, 0x39c: 0x000d, 0x39d: 0x000d,
+ 0x39e: 0x000d, 0x39f: 0x000d, 0x3a0: 0x000d, 0x3a1: 0x000d, 0x3a2: 0x000d, 0x3a3: 0x000d,
+ 0x3a4: 0x000d, 0x3a5: 0x000d, 0x3a6: 0x000d, 0x3a7: 0x000d, 0x3a8: 0x000d, 0x3a9: 0x000d,
+ 0x3aa: 0x000d, 0x3ab: 0x000d, 0x3ac: 0x000d, 0x3ad: 0x000d, 0x3ae: 0x000d, 0x3af: 0x000d,
+ 0x3b0: 0x000d, 0x3b1: 0x000d, 0x3b2: 0x000d, 0x3b3: 0x000d, 0x3b4: 0x000d, 0x3b5: 0x000d,
+ 0x3b6: 0x000d, 0x3b7: 0x000d, 0x3b8: 0x000d, 0x3b9: 0x000d, 0x3ba: 0x000d, 0x3bb: 0x000d,
+ 0x3bc: 0x000d, 0x3bd: 0x000d, 0x3be: 0x000d, 0x3bf: 0x000d,
+ // Block 0xf, offset 0x3c0
+ 0x3c0: 0x000d, 0x3c1: 0x000d, 0x3c2: 0x000d, 0x3c3: 0x000d, 0x3c4: 0x000d, 0x3c5: 0x000d,
+ 0x3c6: 0x000d, 0x3c7: 0x000d, 0x3c8: 0x000d, 0x3c9: 0x000d, 0x3ca: 0x000d, 0x3cb: 0x000c,
+ 0x3cc: 0x000c, 0x3cd: 0x000c, 0x3ce: 0x000c, 0x3cf: 0x000c, 0x3d0: 0x000c, 0x3d1: 0x000c,
+ 0x3d2: 0x000c, 0x3d3: 0x000c, 0x3d4: 0x000c, 0x3d5: 0x000c, 0x3d6: 0x000c, 0x3d7: 0x000c,
+ 0x3d8: 0x000c, 0x3d9: 0x000c, 0x3da: 0x000c, 0x3db: 0x000c, 0x3dc: 0x000c, 0x3dd: 0x000c,
+ 0x3de: 0x000c, 0x3df: 0x000c, 0x3e0: 0x0005, 0x3e1: 0x0005, 0x3e2: 0x0005, 0x3e3: 0x0005,
+ 0x3e4: 0x0005, 0x3e5: 0x0005, 0x3e6: 0x0005, 0x3e7: 0x0005, 0x3e8: 0x0005, 0x3e9: 0x0005,
+ 0x3ea: 0x0004, 0x3eb: 0x0005, 0x3ec: 0x0005, 0x3ed: 0x000d, 0x3ee: 0x000d, 0x3ef: 0x000d,
+ 0x3f0: 0x000c, 0x3f1: 0x000d, 0x3f2: 0x000d, 0x3f3: 0x000d, 0x3f4: 0x000d, 0x3f5: 0x000d,
+ 0x3f6: 0x000d, 0x3f7: 0x000d, 0x3f8: 0x000d, 0x3f9: 0x000d, 0x3fa: 0x000d, 0x3fb: 0x000d,
+ 0x3fc: 0x000d, 0x3fd: 0x000d, 0x3fe: 0x000d, 0x3ff: 0x000d,
+ // Block 0x10, offset 0x400
+ 0x400: 0x000d, 0x401: 0x000d, 0x402: 0x000d, 0x403: 0x000d, 0x404: 0x000d, 0x405: 0x000d,
+ 0x406: 0x000d, 0x407: 0x000d, 0x408: 0x000d, 0x409: 0x000d, 0x40a: 0x000d, 0x40b: 0x000d,
+ 0x40c: 0x000d, 0x40d: 0x000d, 0x40e: 0x000d, 0x40f: 0x000d, 0x410: 0x000d, 0x411: 0x000d,
+ 0x412: 0x000d, 0x413: 0x000d, 0x414: 0x000d, 0x415: 0x000d, 0x416: 0x000d, 0x417: 0x000d,
+ 0x418: 0x000d, 0x419: 0x000d, 0x41a: 0x000d, 0x41b: 0x000d, 0x41c: 0x000d, 0x41d: 0x000d,
+ 0x41e: 0x000d, 0x41f: 0x000d, 0x420: 0x000d, 0x421: 0x000d, 0x422: 0x000d, 0x423: 0x000d,
+ 0x424: 0x000d, 0x425: 0x000d, 0x426: 0x000d, 0x427: 0x000d, 0x428: 0x000d, 0x429: 0x000d,
+ 0x42a: 0x000d, 0x42b: 0x000d, 0x42c: 0x000d, 0x42d: 0x000d, 0x42e: 0x000d, 0x42f: 0x000d,
+ 0x430: 0x000d, 0x431: 0x000d, 0x432: 0x000d, 0x433: 0x000d, 0x434: 0x000d, 0x435: 0x000d,
+ 0x436: 0x000d, 0x437: 0x000d, 0x438: 0x000d, 0x439: 0x000d, 0x43a: 0x000d, 0x43b: 0x000d,
+ 0x43c: 0x000d, 0x43d: 0x000d, 0x43e: 0x000d, 0x43f: 0x000d,
+ // Block 0x11, offset 0x440
+ 0x440: 0x000d, 0x441: 0x000d, 0x442: 0x000d, 0x443: 0x000d, 0x444: 0x000d, 0x445: 0x000d,
+ 0x446: 0x000d, 0x447: 0x000d, 0x448: 0x000d, 0x449: 0x000d, 0x44a: 0x000d, 0x44b: 0x000d,
+ 0x44c: 0x000d, 0x44d: 0x000d, 0x44e: 0x000d, 0x44f: 0x000d, 0x450: 0x000d, 0x451: 0x000d,
+ 0x452: 0x000d, 0x453: 0x000d, 0x454: 0x000d, 0x455: 0x000d, 0x456: 0x000c, 0x457: 0x000c,
+ 0x458: 0x000c, 0x459: 0x000c, 0x45a: 0x000c, 0x45b: 0x000c, 0x45c: 0x000c, 0x45d: 0x0005,
+ 0x45e: 0x000a, 0x45f: 0x000c, 0x460: 0x000c, 0x461: 0x000c, 0x462: 0x000c, 0x463: 0x000c,
+ 0x464: 0x000c, 0x465: 0x000d, 0x466: 0x000d, 0x467: 0x000c, 0x468: 0x000c, 0x469: 0x000a,
+ 0x46a: 0x000c, 0x46b: 0x000c, 0x46c: 0x000c, 0x46d: 0x000c, 0x46e: 0x000d, 0x46f: 0x000d,
+ 0x470: 0x0002, 0x471: 0x0002, 0x472: 0x0002, 0x473: 0x0002, 0x474: 0x0002, 0x475: 0x0002,
+ 0x476: 0x0002, 0x477: 0x0002, 0x478: 0x0002, 0x479: 0x0002, 0x47a: 0x000d, 0x47b: 0x000d,
+ 0x47c: 0x000d, 0x47d: 0x000d, 0x47e: 0x000d, 0x47f: 0x000d,
+ // Block 0x12, offset 0x480
+ 0x480: 0x000d, 0x481: 0x000d, 0x482: 0x000d, 0x483: 0x000d, 0x484: 0x000d, 0x485: 0x000d,
+ 0x486: 0x000d, 0x487: 0x000d, 0x488: 0x000d, 0x489: 0x000d, 0x48a: 0x000d, 0x48b: 0x000d,
+ 0x48c: 0x000d, 0x48d: 0x000d, 0x48e: 0x000d, 0x48f: 0x000d, 0x490: 0x000d, 0x491: 0x000c,
+ 0x492: 0x000d, 0x493: 0x000d, 0x494: 0x000d, 0x495: 0x000d, 0x496: 0x000d, 0x497: 0x000d,
+ 0x498: 0x000d, 0x499: 0x000d, 0x49a: 0x000d, 0x49b: 0x000d, 0x49c: 0x000d, 0x49d: 0x000d,
+ 0x49e: 0x000d, 0x49f: 0x000d, 0x4a0: 0x000d, 0x4a1: 0x000d, 0x4a2: 0x000d, 0x4a3: 0x000d,
+ 0x4a4: 0x000d, 0x4a5: 0x000d, 0x4a6: 0x000d, 0x4a7: 0x000d, 0x4a8: 0x000d, 0x4a9: 0x000d,
+ 0x4aa: 0x000d, 0x4ab: 0x000d, 0x4ac: 0x000d, 0x4ad: 0x000d, 0x4ae: 0x000d, 0x4af: 0x000d,
+ 0x4b0: 0x000c, 0x4b1: 0x000c, 0x4b2: 0x000c, 0x4b3: 0x000c, 0x4b4: 0x000c, 0x4b5: 0x000c,
+ 0x4b6: 0x000c, 0x4b7: 0x000c, 0x4b8: 0x000c, 0x4b9: 0x000c, 0x4ba: 0x000c, 0x4bb: 0x000c,
+ 0x4bc: 0x000c, 0x4bd: 0x000c, 0x4be: 0x000c, 0x4bf: 0x000c,
+ // Block 0x13, offset 0x4c0
+ 0x4c0: 0x000c, 0x4c1: 0x000c, 0x4c2: 0x000c, 0x4c3: 0x000c, 0x4c4: 0x000c, 0x4c5: 0x000c,
+ 0x4c6: 0x000c, 0x4c7: 0x000c, 0x4c8: 0x000c, 0x4c9: 0x000c, 0x4ca: 0x000c, 0x4cb: 0x000d,
+ 0x4cc: 0x000d, 0x4cd: 0x000d, 0x4ce: 0x000d, 0x4cf: 0x000d, 0x4d0: 0x000d, 0x4d1: 0x000d,
+ 0x4d2: 0x000d, 0x4d3: 0x000d, 0x4d4: 0x000d, 0x4d5: 0x000d, 0x4d6: 0x000d, 0x4d7: 0x000d,
+ 0x4d8: 0x000d, 0x4d9: 0x000d, 0x4da: 0x000d, 0x4db: 0x000d, 0x4dc: 0x000d, 0x4dd: 0x000d,
+ 0x4de: 0x000d, 0x4df: 0x000d, 0x4e0: 0x000d, 0x4e1: 0x000d, 0x4e2: 0x000d, 0x4e3: 0x000d,
+ 0x4e4: 0x000d, 0x4e5: 0x000d, 0x4e6: 0x000d, 0x4e7: 0x000d, 0x4e8: 0x000d, 0x4e9: 0x000d,
+ 0x4ea: 0x000d, 0x4eb: 0x000d, 0x4ec: 0x000d, 0x4ed: 0x000d, 0x4ee: 0x000d, 0x4ef: 0x000d,
+ 0x4f0: 0x000d, 0x4f1: 0x000d, 0x4f2: 0x000d, 0x4f3: 0x000d, 0x4f4: 0x000d, 0x4f5: 0x000d,
+ 0x4f6: 0x000d, 0x4f7: 0x000d, 0x4f8: 0x000d, 0x4f9: 0x000d, 0x4fa: 0x000d, 0x4fb: 0x000d,
+ 0x4fc: 0x000d, 0x4fd: 0x000d, 0x4fe: 0x000d, 0x4ff: 0x000d,
+ // Block 0x14, offset 0x500
+ 0x500: 0x000d, 0x501: 0x000d, 0x502: 0x000d, 0x503: 0x000d, 0x504: 0x000d, 0x505: 0x000d,
+ 0x506: 0x000d, 0x507: 0x000d, 0x508: 0x000d, 0x509: 0x000d, 0x50a: 0x000d, 0x50b: 0x000d,
+ 0x50c: 0x000d, 0x50d: 0x000d, 0x50e: 0x000d, 0x50f: 0x000d, 0x510: 0x000d, 0x511: 0x000d,
+ 0x512: 0x000d, 0x513: 0x000d, 0x514: 0x000d, 0x515: 0x000d, 0x516: 0x000d, 0x517: 0x000d,
+ 0x518: 0x000d, 0x519: 0x000d, 0x51a: 0x000d, 0x51b: 0x000d, 0x51c: 0x000d, 0x51d: 0x000d,
+ 0x51e: 0x000d, 0x51f: 0x000d, 0x520: 0x000d, 0x521: 0x000d, 0x522: 0x000d, 0x523: 0x000d,
+ 0x524: 0x000d, 0x525: 0x000d, 0x526: 0x000c, 0x527: 0x000c, 0x528: 0x000c, 0x529: 0x000c,
+ 0x52a: 0x000c, 0x52b: 0x000c, 0x52c: 0x000c, 0x52d: 0x000c, 0x52e: 0x000c, 0x52f: 0x000c,
+ 0x530: 0x000c, 0x531: 0x000d, 0x532: 0x000d, 0x533: 0x000d, 0x534: 0x000d, 0x535: 0x000d,
+ 0x536: 0x000d, 0x537: 0x000d, 0x538: 0x000d, 0x539: 0x000d, 0x53a: 0x000d, 0x53b: 0x000d,
+ 0x53c: 0x000d, 0x53d: 0x000d, 0x53e: 0x000d, 0x53f: 0x000d,
+ // Block 0x15, offset 0x540
+ 0x540: 0x0001, 0x541: 0x0001, 0x542: 0x0001, 0x543: 0x0001, 0x544: 0x0001, 0x545: 0x0001,
+ 0x546: 0x0001, 0x547: 0x0001, 0x548: 0x0001, 0x549: 0x0001, 0x54a: 0x0001, 0x54b: 0x0001,
+ 0x54c: 0x0001, 0x54d: 0x0001, 0x54e: 0x0001, 0x54f: 0x0001, 0x550: 0x0001, 0x551: 0x0001,
+ 0x552: 0x0001, 0x553: 0x0001, 0x554: 0x0001, 0x555: 0x0001, 0x556: 0x0001, 0x557: 0x0001,
+ 0x558: 0x0001, 0x559: 0x0001, 0x55a: 0x0001, 0x55b: 0x0001, 0x55c: 0x0001, 0x55d: 0x0001,
+ 0x55e: 0x0001, 0x55f: 0x0001, 0x560: 0x0001, 0x561: 0x0001, 0x562: 0x0001, 0x563: 0x0001,
+ 0x564: 0x0001, 0x565: 0x0001, 0x566: 0x0001, 0x567: 0x0001, 0x568: 0x0001, 0x569: 0x0001,
+ 0x56a: 0x0001, 0x56b: 0x000c, 0x56c: 0x000c, 0x56d: 0x000c, 0x56e: 0x000c, 0x56f: 0x000c,
+ 0x570: 0x000c, 0x571: 0x000c, 0x572: 0x000c, 0x573: 0x000c, 0x574: 0x0001, 0x575: 0x0001,
+ 0x576: 0x000a, 0x577: 0x000a, 0x578: 0x000a, 0x579: 0x000a, 0x57a: 0x0001, 0x57b: 0x0001,
+ 0x57c: 0x0001, 0x57d: 0x0001, 0x57e: 0x0001, 0x57f: 0x0001,
+ // Block 0x16, offset 0x580
+ 0x580: 0x0001, 0x581: 0x0001, 0x582: 0x0001, 0x583: 0x0001, 0x584: 0x0001, 0x585: 0x0001,
+ 0x586: 0x0001, 0x587: 0x0001, 0x588: 0x0001, 0x589: 0x0001, 0x58a: 0x0001, 0x58b: 0x0001,
+ 0x58c: 0x0001, 0x58d: 0x0001, 0x58e: 0x0001, 0x58f: 0x0001, 0x590: 0x0001, 0x591: 0x0001,
+ 0x592: 0x0001, 0x593: 0x0001, 0x594: 0x0001, 0x595: 0x0001, 0x596: 0x000c, 0x597: 0x000c,
+ 0x598: 0x000c, 0x599: 0x000c, 0x59a: 0x0001, 0x59b: 0x000c, 0x59c: 0x000c, 0x59d: 0x000c,
+ 0x59e: 0x000c, 0x59f: 0x000c, 0x5a0: 0x000c, 0x5a1: 0x000c, 0x5a2: 0x000c, 0x5a3: 0x000c,
+ 0x5a4: 0x0001, 0x5a5: 0x000c, 0x5a6: 0x000c, 0x5a7: 0x000c, 0x5a8: 0x0001, 0x5a9: 0x000c,
+ 0x5aa: 0x000c, 0x5ab: 0x000c, 0x5ac: 0x000c, 0x5ad: 0x000c, 0x5ae: 0x0001, 0x5af: 0x0001,
+ 0x5b0: 0x0001, 0x5b1: 0x0001, 0x5b2: 0x0001, 0x5b3: 0x0001, 0x5b4: 0x0001, 0x5b5: 0x0001,
+ 0x5b6: 0x0001, 0x5b7: 0x0001, 0x5b8: 0x0001, 0x5b9: 0x0001, 0x5ba: 0x0001, 0x5bb: 0x0001,
+ 0x5bc: 0x0001, 0x5bd: 0x0001, 0x5be: 0x0001, 0x5bf: 0x0001,
+ // Block 0x17, offset 0x5c0
+ 0x5c0: 0x0001, 0x5c1: 0x0001, 0x5c2: 0x0001, 0x5c3: 0x0001, 0x5c4: 0x0001, 0x5c5: 0x0001,
+ 0x5c6: 0x0001, 0x5c7: 0x0001, 0x5c8: 0x0001, 0x5c9: 0x0001, 0x5ca: 0x0001, 0x5cb: 0x0001,
+ 0x5cc: 0x0001, 0x5cd: 0x0001, 0x5ce: 0x0001, 0x5cf: 0x0001, 0x5d0: 0x0001, 0x5d1: 0x0001,
+ 0x5d2: 0x0001, 0x5d3: 0x0001, 0x5d4: 0x0001, 0x5d5: 0x0001, 0x5d6: 0x0001, 0x5d7: 0x0001,
+ 0x5d8: 0x0001, 0x5d9: 0x000c, 0x5da: 0x000c, 0x5db: 0x000c, 0x5dc: 0x0001, 0x5dd: 0x0001,
+ 0x5de: 0x0001, 0x5df: 0x0001, 0x5e0: 0x0001, 0x5e1: 0x0001, 0x5e2: 0x0001, 0x5e3: 0x0001,
+ 0x5e4: 0x0001, 0x5e5: 0x0001, 0x5e6: 0x0001, 0x5e7: 0x0001, 0x5e8: 0x0001, 0x5e9: 0x0001,
+ 0x5ea: 0x0001, 0x5eb: 0x0001, 0x5ec: 0x0001, 0x5ed: 0x0001, 0x5ee: 0x0001, 0x5ef: 0x0001,
+ 0x5f0: 0x0001, 0x5f1: 0x0001, 0x5f2: 0x0001, 0x5f3: 0x0001, 0x5f4: 0x0001, 0x5f5: 0x0001,
+ 0x5f6: 0x0001, 0x5f7: 0x0001, 0x5f8: 0x0001, 0x5f9: 0x0001, 0x5fa: 0x0001, 0x5fb: 0x0001,
+ 0x5fc: 0x0001, 0x5fd: 0x0001, 0x5fe: 0x0001, 0x5ff: 0x0001,
+ // Block 0x18, offset 0x600
+ 0x600: 0x0001, 0x601: 0x0001, 0x602: 0x0001, 0x603: 0x0001, 0x604: 0x0001, 0x605: 0x0001,
+ 0x606: 0x0001, 0x607: 0x0001, 0x608: 0x0001, 0x609: 0x0001, 0x60a: 0x0001, 0x60b: 0x0001,
+ 0x60c: 0x0001, 0x60d: 0x0001, 0x60e: 0x0001, 0x60f: 0x0001, 0x610: 0x0001, 0x611: 0x0001,
+ 0x612: 0x0001, 0x613: 0x0001, 0x614: 0x0001, 0x615: 0x0001, 0x616: 0x0001, 0x617: 0x0001,
+ 0x618: 0x0001, 0x619: 0x0001, 0x61a: 0x0001, 0x61b: 0x0001, 0x61c: 0x0001, 0x61d: 0x0001,
+ 0x61e: 0x0001, 0x61f: 0x0001, 0x620: 0x000d, 0x621: 0x000d, 0x622: 0x000d, 0x623: 0x000d,
+ 0x624: 0x000d, 0x625: 0x000d, 0x626: 0x000d, 0x627: 0x000d, 0x628: 0x000d, 0x629: 0x000d,
+ 0x62a: 0x000d, 0x62b: 0x000d, 0x62c: 0x000d, 0x62d: 0x000d, 0x62e: 0x000d, 0x62f: 0x000d,
+ 0x630: 0x000d, 0x631: 0x000d, 0x632: 0x000d, 0x633: 0x000d, 0x634: 0x000d, 0x635: 0x000d,
+ 0x636: 0x000d, 0x637: 0x000d, 0x638: 0x000d, 0x639: 0x000d, 0x63a: 0x000d, 0x63b: 0x000d,
+ 0x63c: 0x000d, 0x63d: 0x000d, 0x63e: 0x000d, 0x63f: 0x000d,
+ // Block 0x19, offset 0x640
+ 0x640: 0x000d, 0x641: 0x000d, 0x642: 0x000d, 0x643: 0x000d, 0x644: 0x000d, 0x645: 0x000d,
+ 0x646: 0x000d, 0x647: 0x000d, 0x648: 0x000d, 0x649: 0x000d, 0x64a: 0x000d, 0x64b: 0x000d,
+ 0x64c: 0x000d, 0x64d: 0x000d, 0x64e: 0x000d, 0x64f: 0x000d, 0x650: 0x000d, 0x651: 0x000d,
+ 0x652: 0x000d, 0x653: 0x000d, 0x654: 0x000c, 0x655: 0x000c, 0x656: 0x000c, 0x657: 0x000c,
+ 0x658: 0x000c, 0x659: 0x000c, 0x65a: 0x000c, 0x65b: 0x000c, 0x65c: 0x000c, 0x65d: 0x000c,
+ 0x65e: 0x000c, 0x65f: 0x000c, 0x660: 0x000c, 0x661: 0x000c, 0x662: 0x0005, 0x663: 0x000c,
+ 0x664: 0x000c, 0x665: 0x000c, 0x666: 0x000c, 0x667: 0x000c, 0x668: 0x000c, 0x669: 0x000c,
+ 0x66a: 0x000c, 0x66b: 0x000c, 0x66c: 0x000c, 0x66d: 0x000c, 0x66e: 0x000c, 0x66f: 0x000c,
+ 0x670: 0x000c, 0x671: 0x000c, 0x672: 0x000c, 0x673: 0x000c, 0x674: 0x000c, 0x675: 0x000c,
+ 0x676: 0x000c, 0x677: 0x000c, 0x678: 0x000c, 0x679: 0x000c, 0x67a: 0x000c, 0x67b: 0x000c,
+ 0x67c: 0x000c, 0x67d: 0x000c, 0x67e: 0x000c, 0x67f: 0x000c,
+ // Block 0x1a, offset 0x680
+ 0x680: 0x000c, 0x681: 0x000c, 0x682: 0x000c,
+ 0x6ba: 0x000c,
+ 0x6bc: 0x000c,
+ // Block 0x1b, offset 0x6c0
+ 0x6c1: 0x000c, 0x6c2: 0x000c, 0x6c3: 0x000c, 0x6c4: 0x000c, 0x6c5: 0x000c,
+ 0x6c6: 0x000c, 0x6c7: 0x000c, 0x6c8: 0x000c,
+ 0x6cd: 0x000c, 0x6d1: 0x000c,
+ 0x6d2: 0x000c, 0x6d3: 0x000c, 0x6d4: 0x000c, 0x6d5: 0x000c, 0x6d6: 0x000c, 0x6d7: 0x000c,
+ 0x6e2: 0x000c, 0x6e3: 0x000c,
+ // Block 0x1c, offset 0x700
+ 0x701: 0x000c,
+ 0x73c: 0x000c,
+ // Block 0x1d, offset 0x740
+ 0x741: 0x000c, 0x742: 0x000c, 0x743: 0x000c, 0x744: 0x000c,
+ 0x74d: 0x000c,
+ 0x762: 0x000c, 0x763: 0x000c,
+ 0x772: 0x0004, 0x773: 0x0004,
+ 0x77b: 0x0004,
+ // Block 0x1e, offset 0x780
+ 0x781: 0x000c, 0x782: 0x000c,
+ 0x7bc: 0x000c,
+ // Block 0x1f, offset 0x7c0
+ 0x7c1: 0x000c, 0x7c2: 0x000c,
+ 0x7c7: 0x000c, 0x7c8: 0x000c, 0x7cb: 0x000c,
+ 0x7cc: 0x000c, 0x7cd: 0x000c, 0x7d1: 0x000c,
+ 0x7f0: 0x000c, 0x7f1: 0x000c, 0x7f5: 0x000c,
+ // Block 0x20, offset 0x800
+ 0x801: 0x000c, 0x802: 0x000c, 0x803: 0x000c, 0x804: 0x000c, 0x805: 0x000c,
+ 0x807: 0x000c, 0x808: 0x000c,
+ 0x80d: 0x000c,
+ 0x822: 0x000c, 0x823: 0x000c,
+ 0x831: 0x0004,
+ // Block 0x21, offset 0x840
+ 0x841: 0x000c,
+ 0x87c: 0x000c, 0x87f: 0x000c,
+ // Block 0x22, offset 0x880
+ 0x881: 0x000c, 0x882: 0x000c, 0x883: 0x000c, 0x884: 0x000c,
+ 0x88d: 0x000c,
+ 0x896: 0x000c,
+ 0x8a2: 0x000c, 0x8a3: 0x000c,
+ // Block 0x23, offset 0x8c0
+ 0x8c2: 0x000c,
+ // Block 0x24, offset 0x900
+ 0x900: 0x000c,
+ 0x90d: 0x000c,
+ 0x933: 0x000a, 0x934: 0x000a, 0x935: 0x000a,
+ 0x936: 0x000a, 0x937: 0x000a, 0x938: 0x000a, 0x939: 0x0004, 0x93a: 0x000a,
+ // Block 0x25, offset 0x940
+ 0x940: 0x000c,
+ 0x97e: 0x000c, 0x97f: 0x000c,
+ // Block 0x26, offset 0x980
+ 0x980: 0x000c,
+ 0x986: 0x000c, 0x987: 0x000c, 0x988: 0x000c, 0x98a: 0x000c, 0x98b: 0x000c,
+ 0x98c: 0x000c, 0x98d: 0x000c,
+ 0x995: 0x000c, 0x996: 0x000c,
+ 0x9a2: 0x000c, 0x9a3: 0x000c,
+ 0x9b8: 0x000a, 0x9b9: 0x000a, 0x9ba: 0x000a, 0x9bb: 0x000a,
+ 0x9bc: 0x000a, 0x9bd: 0x000a, 0x9be: 0x000a,
+ // Block 0x27, offset 0x9c0
+ 0x9cc: 0x000c, 0x9cd: 0x000c,
+ 0x9e2: 0x000c, 0x9e3: 0x000c,
+ // Block 0x28, offset 0xa00
+ 0xa01: 0x000c,
+ // Block 0x29, offset 0xa40
+ 0xa41: 0x000c, 0xa42: 0x000c, 0xa43: 0x000c, 0xa44: 0x000c,
+ 0xa4d: 0x000c,
+ 0xa62: 0x000c, 0xa63: 0x000c,
+ // Block 0x2a, offset 0xa80
+ 0xa8a: 0x000c,
+ 0xa92: 0x000c, 0xa93: 0x000c, 0xa94: 0x000c, 0xa96: 0x000c,
+ // Block 0x2b, offset 0xac0
+ 0xaf1: 0x000c, 0xaf4: 0x000c, 0xaf5: 0x000c,
+ 0xaf6: 0x000c, 0xaf7: 0x000c, 0xaf8: 0x000c, 0xaf9: 0x000c, 0xafa: 0x000c,
+ 0xaff: 0x0004,
+ // Block 0x2c, offset 0xb00
+ 0xb07: 0x000c, 0xb08: 0x000c, 0xb09: 0x000c, 0xb0a: 0x000c, 0xb0b: 0x000c,
+ 0xb0c: 0x000c, 0xb0d: 0x000c, 0xb0e: 0x000c,
+ // Block 0x2d, offset 0xb40
+ 0xb71: 0x000c, 0xb74: 0x000c, 0xb75: 0x000c,
+ 0xb76: 0x000c, 0xb77: 0x000c, 0xb78: 0x000c, 0xb79: 0x000c, 0xb7b: 0x000c,
+ 0xb7c: 0x000c,
+ // Block 0x2e, offset 0xb80
+ 0xb88: 0x000c, 0xb89: 0x000c, 0xb8a: 0x000c, 0xb8b: 0x000c,
+ 0xb8c: 0x000c, 0xb8d: 0x000c,
+ // Block 0x2f, offset 0xbc0
+ 0xbd8: 0x000c, 0xbd9: 0x000c,
+ 0xbf5: 0x000c,
+ 0xbf7: 0x000c, 0xbf9: 0x000c, 0xbfa: 0x003a, 0xbfb: 0x002a,
+ 0xbfc: 0x003a, 0xbfd: 0x002a,
+ // Block 0x30, offset 0xc00
+ 0xc31: 0x000c, 0xc32: 0x000c, 0xc33: 0x000c, 0xc34: 0x000c, 0xc35: 0x000c,
+ 0xc36: 0x000c, 0xc37: 0x000c, 0xc38: 0x000c, 0xc39: 0x000c, 0xc3a: 0x000c, 0xc3b: 0x000c,
+ 0xc3c: 0x000c, 0xc3d: 0x000c, 0xc3e: 0x000c,
+ // Block 0x31, offset 0xc40
+ 0xc40: 0x000c, 0xc41: 0x000c, 0xc42: 0x000c, 0xc43: 0x000c, 0xc44: 0x000c,
+ 0xc46: 0x000c, 0xc47: 0x000c,
+ 0xc4d: 0x000c, 0xc4e: 0x000c, 0xc4f: 0x000c, 0xc50: 0x000c, 0xc51: 0x000c,
+ 0xc52: 0x000c, 0xc53: 0x000c, 0xc54: 0x000c, 0xc55: 0x000c, 0xc56: 0x000c, 0xc57: 0x000c,
+ 0xc59: 0x000c, 0xc5a: 0x000c, 0xc5b: 0x000c, 0xc5c: 0x000c, 0xc5d: 0x000c,
+ 0xc5e: 0x000c, 0xc5f: 0x000c, 0xc60: 0x000c, 0xc61: 0x000c, 0xc62: 0x000c, 0xc63: 0x000c,
+ 0xc64: 0x000c, 0xc65: 0x000c, 0xc66: 0x000c, 0xc67: 0x000c, 0xc68: 0x000c, 0xc69: 0x000c,
+ 0xc6a: 0x000c, 0xc6b: 0x000c, 0xc6c: 0x000c, 0xc6d: 0x000c, 0xc6e: 0x000c, 0xc6f: 0x000c,
+ 0xc70: 0x000c, 0xc71: 0x000c, 0xc72: 0x000c, 0xc73: 0x000c, 0xc74: 0x000c, 0xc75: 0x000c,
+ 0xc76: 0x000c, 0xc77: 0x000c, 0xc78: 0x000c, 0xc79: 0x000c, 0xc7a: 0x000c, 0xc7b: 0x000c,
+ 0xc7c: 0x000c,
+ // Block 0x32, offset 0xc80
+ 0xc86: 0x000c,
+ // Block 0x33, offset 0xcc0
+ 0xced: 0x000c, 0xcee: 0x000c, 0xcef: 0x000c,
+ 0xcf0: 0x000c, 0xcf2: 0x000c, 0xcf3: 0x000c, 0xcf4: 0x000c, 0xcf5: 0x000c,
+ 0xcf6: 0x000c, 0xcf7: 0x000c, 0xcf9: 0x000c, 0xcfa: 0x000c,
+ 0xcfd: 0x000c, 0xcfe: 0x000c,
+ // Block 0x34, offset 0xd00
+ 0xd18: 0x000c, 0xd19: 0x000c,
+ 0xd1e: 0x000c, 0xd1f: 0x000c, 0xd20: 0x000c,
+ 0xd31: 0x000c, 0xd32: 0x000c, 0xd33: 0x000c, 0xd34: 0x000c,
+ // Block 0x35, offset 0xd40
+ 0xd42: 0x000c, 0xd45: 0x000c,
+ 0xd46: 0x000c,
+ 0xd4d: 0x000c,
+ 0xd5d: 0x000c,
+ // Block 0x36, offset 0xd80
+ 0xd9d: 0x000c,
+ 0xd9e: 0x000c, 0xd9f: 0x000c,
+ // Block 0x37, offset 0xdc0
+ 0xdd0: 0x000a, 0xdd1: 0x000a,
+ 0xdd2: 0x000a, 0xdd3: 0x000a, 0xdd4: 0x000a, 0xdd5: 0x000a, 0xdd6: 0x000a, 0xdd7: 0x000a,
+ 0xdd8: 0x000a, 0xdd9: 0x000a,
+ // Block 0x38, offset 0xe00
+ 0xe00: 0x000a,
+ // Block 0x39, offset 0xe40
+ 0xe40: 0x0009,
+ 0xe5b: 0x007a, 0xe5c: 0x006a,
+ // Block 0x3a, offset 0xe80
+ 0xe92: 0x000c, 0xe93: 0x000c, 0xe94: 0x000c,
+ 0xeb2: 0x000c, 0xeb3: 0x000c, 0xeb4: 0x000c,
+ // Block 0x3b, offset 0xec0
+ 0xed2: 0x000c, 0xed3: 0x000c,
+ 0xef2: 0x000c, 0xef3: 0x000c,
+ // Block 0x3c, offset 0xf00
+ 0xf34: 0x000c, 0xf35: 0x000c,
+ 0xf37: 0x000c, 0xf38: 0x000c, 0xf39: 0x000c, 0xf3a: 0x000c, 0xf3b: 0x000c,
+ 0xf3c: 0x000c, 0xf3d: 0x000c,
+ // Block 0x3d, offset 0xf40
+ 0xf46: 0x000c, 0xf49: 0x000c, 0xf4a: 0x000c, 0xf4b: 0x000c,
+ 0xf4c: 0x000c, 0xf4d: 0x000c, 0xf4e: 0x000c, 0xf4f: 0x000c, 0xf50: 0x000c, 0xf51: 0x000c,
+ 0xf52: 0x000c, 0xf53: 0x000c,
+ 0xf5b: 0x0004, 0xf5d: 0x000c,
+ 0xf70: 0x000a, 0xf71: 0x000a, 0xf72: 0x000a, 0xf73: 0x000a, 0xf74: 0x000a, 0xf75: 0x000a,
+ 0xf76: 0x000a, 0xf77: 0x000a, 0xf78: 0x000a, 0xf79: 0x000a,
+ // Block 0x3e, offset 0xf80
+ 0xf80: 0x000a, 0xf81: 0x000a, 0xf82: 0x000a, 0xf83: 0x000a, 0xf84: 0x000a, 0xf85: 0x000a,
+ 0xf86: 0x000a, 0xf87: 0x000a, 0xf88: 0x000a, 0xf89: 0x000a, 0xf8a: 0x000a, 0xf8b: 0x000c,
+ 0xf8c: 0x000c, 0xf8d: 0x000c, 0xf8e: 0x000b,
+ // Block 0x3f, offset 0xfc0
+ 0xfc5: 0x000c,
+ 0xfc6: 0x000c,
+ 0xfe9: 0x000c,
+ // Block 0x40, offset 0x1000
+ 0x1020: 0x000c, 0x1021: 0x000c, 0x1022: 0x000c,
+ 0x1027: 0x000c, 0x1028: 0x000c,
+ 0x1032: 0x000c,
+ 0x1039: 0x000c, 0x103a: 0x000c, 0x103b: 0x000c,
+ // Block 0x41, offset 0x1040
+ 0x1040: 0x000a, 0x1044: 0x000a, 0x1045: 0x000a,
+ // Block 0x42, offset 0x1080
+ 0x109e: 0x000a, 0x109f: 0x000a, 0x10a0: 0x000a, 0x10a1: 0x000a, 0x10a2: 0x000a, 0x10a3: 0x000a,
+ 0x10a4: 0x000a, 0x10a5: 0x000a, 0x10a6: 0x000a, 0x10a7: 0x000a, 0x10a8: 0x000a, 0x10a9: 0x000a,
+ 0x10aa: 0x000a, 0x10ab: 0x000a, 0x10ac: 0x000a, 0x10ad: 0x000a, 0x10ae: 0x000a, 0x10af: 0x000a,
+ 0x10b0: 0x000a, 0x10b1: 0x000a, 0x10b2: 0x000a, 0x10b3: 0x000a, 0x10b4: 0x000a, 0x10b5: 0x000a,
+ 0x10b6: 0x000a, 0x10b7: 0x000a, 0x10b8: 0x000a, 0x10b9: 0x000a, 0x10ba: 0x000a, 0x10bb: 0x000a,
+ 0x10bc: 0x000a, 0x10bd: 0x000a, 0x10be: 0x000a, 0x10bf: 0x000a,
+ // Block 0x43, offset 0x10c0
+ 0x10d7: 0x000c,
+ 0x10d8: 0x000c, 0x10db: 0x000c,
+ // Block 0x44, offset 0x1100
+ 0x1116: 0x000c,
+ 0x1118: 0x000c, 0x1119: 0x000c, 0x111a: 0x000c, 0x111b: 0x000c, 0x111c: 0x000c, 0x111d: 0x000c,
+ 0x111e: 0x000c, 0x1120: 0x000c, 0x1122: 0x000c,
+ 0x1125: 0x000c, 0x1126: 0x000c, 0x1127: 0x000c, 0x1128: 0x000c, 0x1129: 0x000c,
+ 0x112a: 0x000c, 0x112b: 0x000c, 0x112c: 0x000c,
+ 0x1133: 0x000c, 0x1134: 0x000c, 0x1135: 0x000c,
+ 0x1136: 0x000c, 0x1137: 0x000c, 0x1138: 0x000c, 0x1139: 0x000c, 0x113a: 0x000c, 0x113b: 0x000c,
+ 0x113c: 0x000c, 0x113f: 0x000c,
+ // Block 0x45, offset 0x1140
+ 0x1170: 0x000c, 0x1171: 0x000c, 0x1172: 0x000c, 0x1173: 0x000c, 0x1174: 0x000c, 0x1175: 0x000c,
+ 0x1176: 0x000c, 0x1177: 0x000c, 0x1178: 0x000c, 0x1179: 0x000c, 0x117a: 0x000c, 0x117b: 0x000c,
+ 0x117c: 0x000c, 0x117d: 0x000c, 0x117e: 0x000c,
+ // Block 0x46, offset 0x1180
+ 0x1180: 0x000c, 0x1181: 0x000c, 0x1182: 0x000c, 0x1183: 0x000c,
+ 0x11b4: 0x000c,
+ 0x11b6: 0x000c, 0x11b7: 0x000c, 0x11b8: 0x000c, 0x11b9: 0x000c, 0x11ba: 0x000c,
+ 0x11bc: 0x000c,
+ // Block 0x47, offset 0x11c0
+ 0x11c2: 0x000c,
+ 0x11eb: 0x000c, 0x11ec: 0x000c, 0x11ed: 0x000c, 0x11ee: 0x000c, 0x11ef: 0x000c,
+ 0x11f0: 0x000c, 0x11f1: 0x000c, 0x11f2: 0x000c, 0x11f3: 0x000c,
+ // Block 0x48, offset 0x1200
+ 0x1200: 0x000c, 0x1201: 0x000c,
+ 0x1222: 0x000c, 0x1223: 0x000c,
+ 0x1224: 0x000c, 0x1225: 0x000c, 0x1228: 0x000c, 0x1229: 0x000c,
+ 0x122b: 0x000c, 0x122c: 0x000c, 0x122d: 0x000c,
+ // Block 0x49, offset 0x1240
+ 0x1266: 0x000c, 0x1268: 0x000c, 0x1269: 0x000c,
+ 0x126d: 0x000c, 0x126f: 0x000c,
+ 0x1270: 0x000c, 0x1271: 0x000c,
+ // Block 0x4a, offset 0x1280
+ 0x12ac: 0x000c, 0x12ad: 0x000c, 0x12ae: 0x000c, 0x12af: 0x000c,
+ 0x12b0: 0x000c, 0x12b1: 0x000c, 0x12b2: 0x000c, 0x12b3: 0x000c,
+ 0x12b6: 0x000c, 0x12b7: 0x000c,
+ // Block 0x4b, offset 0x12c0
+ 0x12d0: 0x000c, 0x12d1: 0x000c,
+ 0x12d2: 0x000c, 0x12d4: 0x000c, 0x12d5: 0x000c, 0x12d6: 0x000c, 0x12d7: 0x000c,
+ 0x12d8: 0x000c, 0x12d9: 0x000c, 0x12da: 0x000c, 0x12db: 0x000c, 0x12dc: 0x000c, 0x12dd: 0x000c,
+ 0x12de: 0x000c, 0x12df: 0x000c, 0x12e0: 0x000c, 0x12e2: 0x000c, 0x12e3: 0x000c,
+ 0x12e4: 0x000c, 0x12e5: 0x000c, 0x12e6: 0x000c, 0x12e7: 0x000c, 0x12e8: 0x000c,
+ 0x12ed: 0x000c,
+ 0x12f4: 0x000c,
+ 0x12f8: 0x000c, 0x12f9: 0x000c,
+ // Block 0x4c, offset 0x1300
+ 0x1300: 0x000c, 0x1301: 0x000c, 0x1302: 0x000c, 0x1303: 0x000c, 0x1304: 0x000c, 0x1305: 0x000c,
+ 0x1306: 0x000c, 0x1307: 0x000c, 0x1308: 0x000c, 0x1309: 0x000c, 0x130a: 0x000c, 0x130b: 0x000c,
+ 0x130c: 0x000c, 0x130d: 0x000c, 0x130e: 0x000c, 0x130f: 0x000c, 0x1310: 0x000c, 0x1311: 0x000c,
+ 0x1312: 0x000c, 0x1313: 0x000c, 0x1314: 0x000c, 0x1315: 0x000c, 0x1316: 0x000c, 0x1317: 0x000c,
+ 0x1318: 0x000c, 0x1319: 0x000c, 0x131a: 0x000c, 0x131b: 0x000c, 0x131c: 0x000c, 0x131d: 0x000c,
+ 0x131e: 0x000c, 0x131f: 0x000c, 0x1320: 0x000c, 0x1321: 0x000c, 0x1322: 0x000c, 0x1323: 0x000c,
+ 0x1324: 0x000c, 0x1325: 0x000c, 0x1326: 0x000c, 0x1327: 0x000c, 0x1328: 0x000c, 0x1329: 0x000c,
+ 0x132a: 0x000c, 0x132b: 0x000c, 0x132c: 0x000c, 0x132d: 0x000c, 0x132e: 0x000c, 0x132f: 0x000c,
+ 0x1330: 0x000c, 0x1331: 0x000c, 0x1332: 0x000c, 0x1333: 0x000c, 0x1334: 0x000c, 0x1335: 0x000c,
+ 0x133b: 0x000c,
+ 0x133c: 0x000c, 0x133d: 0x000c, 0x133e: 0x000c, 0x133f: 0x000c,
+ // Block 0x4d, offset 0x1340
+ 0x137d: 0x000a, 0x137f: 0x000a,
+ // Block 0x4e, offset 0x1380
+ 0x1380: 0x000a, 0x1381: 0x000a,
+ 0x138d: 0x000a, 0x138e: 0x000a, 0x138f: 0x000a,
+ 0x139d: 0x000a,
+ 0x139e: 0x000a, 0x139f: 0x000a,
+ 0x13ad: 0x000a, 0x13ae: 0x000a, 0x13af: 0x000a,
+ 0x13bd: 0x000a, 0x13be: 0x000a,
+ // Block 0x4f, offset 0x13c0
+ 0x13c0: 0x0009, 0x13c1: 0x0009, 0x13c2: 0x0009, 0x13c3: 0x0009, 0x13c4: 0x0009, 0x13c5: 0x0009,
+ 0x13c6: 0x0009, 0x13c7: 0x0009, 0x13c8: 0x0009, 0x13c9: 0x0009, 0x13ca: 0x0009, 0x13cb: 0x000b,
+ 0x13cc: 0x000b, 0x13cd: 0x000b, 0x13cf: 0x0001, 0x13d0: 0x000a, 0x13d1: 0x000a,
+ 0x13d2: 0x000a, 0x13d3: 0x000a, 0x13d4: 0x000a, 0x13d5: 0x000a, 0x13d6: 0x000a, 0x13d7: 0x000a,
+ 0x13d8: 0x000a, 0x13d9: 0x000a, 0x13da: 0x000a, 0x13db: 0x000a, 0x13dc: 0x000a, 0x13dd: 0x000a,
+ 0x13de: 0x000a, 0x13df: 0x000a, 0x13e0: 0x000a, 0x13e1: 0x000a, 0x13e2: 0x000a, 0x13e3: 0x000a,
+ 0x13e4: 0x000a, 0x13e5: 0x000a, 0x13e6: 0x000a, 0x13e7: 0x000a, 0x13e8: 0x0009, 0x13e9: 0x0007,
+ 0x13ea: 0x000e, 0x13eb: 0x000e, 0x13ec: 0x000e, 0x13ed: 0x000e, 0x13ee: 0x000e, 0x13ef: 0x0006,
+ 0x13f0: 0x0004, 0x13f1: 0x0004, 0x13f2: 0x0004, 0x13f3: 0x0004, 0x13f4: 0x0004, 0x13f5: 0x000a,
+ 0x13f6: 0x000a, 0x13f7: 0x000a, 0x13f8: 0x000a, 0x13f9: 0x000a, 0x13fa: 0x000a, 0x13fb: 0x000a,
+ 0x13fc: 0x000a, 0x13fd: 0x000a, 0x13fe: 0x000a, 0x13ff: 0x000a,
+ // Block 0x50, offset 0x1400
+ 0x1400: 0x000a, 0x1401: 0x000a, 0x1402: 0x000a, 0x1403: 0x000a, 0x1404: 0x0006, 0x1405: 0x009a,
+ 0x1406: 0x008a, 0x1407: 0x000a, 0x1408: 0x000a, 0x1409: 0x000a, 0x140a: 0x000a, 0x140b: 0x000a,
+ 0x140c: 0x000a, 0x140d: 0x000a, 0x140e: 0x000a, 0x140f: 0x000a, 0x1410: 0x000a, 0x1411: 0x000a,
+ 0x1412: 0x000a, 0x1413: 0x000a, 0x1414: 0x000a, 0x1415: 0x000a, 0x1416: 0x000a, 0x1417: 0x000a,
+ 0x1418: 0x000a, 0x1419: 0x000a, 0x141a: 0x000a, 0x141b: 0x000a, 0x141c: 0x000a, 0x141d: 0x000a,
+ 0x141e: 0x000a, 0x141f: 0x0009, 0x1420: 0x000b, 0x1421: 0x000b, 0x1422: 0x000b, 0x1423: 0x000b,
+ 0x1424: 0x000b, 0x1425: 0x000b, 0x1426: 0x000e, 0x1427: 0x000e, 0x1428: 0x000e, 0x1429: 0x000e,
+ 0x142a: 0x000b, 0x142b: 0x000b, 0x142c: 0x000b, 0x142d: 0x000b, 0x142e: 0x000b, 0x142f: 0x000b,
+ 0x1430: 0x0002, 0x1434: 0x0002, 0x1435: 0x0002,
+ 0x1436: 0x0002, 0x1437: 0x0002, 0x1438: 0x0002, 0x1439: 0x0002, 0x143a: 0x0003, 0x143b: 0x0003,
+ 0x143c: 0x000a, 0x143d: 0x009a, 0x143e: 0x008a,
+ // Block 0x51, offset 0x1440
+ 0x1440: 0x0002, 0x1441: 0x0002, 0x1442: 0x0002, 0x1443: 0x0002, 0x1444: 0x0002, 0x1445: 0x0002,
+ 0x1446: 0x0002, 0x1447: 0x0002, 0x1448: 0x0002, 0x1449: 0x0002, 0x144a: 0x0003, 0x144b: 0x0003,
+ 0x144c: 0x000a, 0x144d: 0x009a, 0x144e: 0x008a,
+ 0x1460: 0x0004, 0x1461: 0x0004, 0x1462: 0x0004, 0x1463: 0x0004,
+ 0x1464: 0x0004, 0x1465: 0x0004, 0x1466: 0x0004, 0x1467: 0x0004, 0x1468: 0x0004, 0x1469: 0x0004,
+ 0x146a: 0x0004, 0x146b: 0x0004, 0x146c: 0x0004, 0x146d: 0x0004, 0x146e: 0x0004, 0x146f: 0x0004,
+ 0x1470: 0x0004, 0x1471: 0x0004, 0x1472: 0x0004, 0x1473: 0x0004, 0x1474: 0x0004, 0x1475: 0x0004,
+ 0x1476: 0x0004, 0x1477: 0x0004, 0x1478: 0x0004, 0x1479: 0x0004, 0x147a: 0x0004, 0x147b: 0x0004,
+ 0x147c: 0x0004, 0x147d: 0x0004, 0x147e: 0x0004, 0x147f: 0x0004,
+ // Block 0x52, offset 0x1480
+ 0x1480: 0x0004, 0x1481: 0x0004, 0x1482: 0x0004, 0x1483: 0x0004, 0x1484: 0x0004, 0x1485: 0x0004,
+ 0x1486: 0x0004, 0x1487: 0x0004, 0x1488: 0x0004, 0x1489: 0x0004, 0x148a: 0x0004, 0x148b: 0x0004,
+ 0x148c: 0x0004, 0x148d: 0x0004, 0x148e: 0x0004, 0x148f: 0x0004, 0x1490: 0x000c, 0x1491: 0x000c,
+ 0x1492: 0x000c, 0x1493: 0x000c, 0x1494: 0x000c, 0x1495: 0x000c, 0x1496: 0x000c, 0x1497: 0x000c,
+ 0x1498: 0x000c, 0x1499: 0x000c, 0x149a: 0x000c, 0x149b: 0x000c, 0x149c: 0x000c, 0x149d: 0x000c,
+ 0x149e: 0x000c, 0x149f: 0x000c, 0x14a0: 0x000c, 0x14a1: 0x000c, 0x14a2: 0x000c, 0x14a3: 0x000c,
+ 0x14a4: 0x000c, 0x14a5: 0x000c, 0x14a6: 0x000c, 0x14a7: 0x000c, 0x14a8: 0x000c, 0x14a9: 0x000c,
+ 0x14aa: 0x000c, 0x14ab: 0x000c, 0x14ac: 0x000c, 0x14ad: 0x000c, 0x14ae: 0x000c, 0x14af: 0x000c,
+ 0x14b0: 0x000c,
+ // Block 0x53, offset 0x14c0
+ 0x14c0: 0x000a, 0x14c1: 0x000a, 0x14c3: 0x000a, 0x14c4: 0x000a, 0x14c5: 0x000a,
+ 0x14c6: 0x000a, 0x14c8: 0x000a, 0x14c9: 0x000a,
+ 0x14d4: 0x000a, 0x14d6: 0x000a, 0x14d7: 0x000a,
+ 0x14d8: 0x000a,
+ 0x14de: 0x000a, 0x14df: 0x000a, 0x14e0: 0x000a, 0x14e1: 0x000a, 0x14e2: 0x000a, 0x14e3: 0x000a,
+ 0x14e5: 0x000a, 0x14e7: 0x000a, 0x14e9: 0x000a,
+ 0x14ee: 0x0004,
+ 0x14fa: 0x000a, 0x14fb: 0x000a,
+ // Block 0x54, offset 0x1500
+ 0x1500: 0x000a, 0x1501: 0x000a, 0x1502: 0x000a, 0x1503: 0x000a, 0x1504: 0x000a,
+ 0x150a: 0x000a, 0x150b: 0x000a,
+ 0x150c: 0x000a, 0x150d: 0x000a, 0x1510: 0x000a, 0x1511: 0x000a,
+ 0x1512: 0x000a, 0x1513: 0x000a, 0x1514: 0x000a, 0x1515: 0x000a, 0x1516: 0x000a, 0x1517: 0x000a,
+ 0x1518: 0x000a, 0x1519: 0x000a, 0x151a: 0x000a, 0x151b: 0x000a, 0x151c: 0x000a, 0x151d: 0x000a,
+ 0x151e: 0x000a, 0x151f: 0x000a,
+ // Block 0x55, offset 0x1540
+ 0x1549: 0x000a, 0x154a: 0x000a, 0x154b: 0x000a,
+ 0x1550: 0x000a, 0x1551: 0x000a,
+ 0x1552: 0x000a, 0x1553: 0x000a, 0x1554: 0x000a, 0x1555: 0x000a, 0x1556: 0x000a, 0x1557: 0x000a,
+ 0x1558: 0x000a, 0x1559: 0x000a, 0x155a: 0x000a, 0x155b: 0x000a, 0x155c: 0x000a, 0x155d: 0x000a,
+ 0x155e: 0x000a, 0x155f: 0x000a, 0x1560: 0x000a, 0x1561: 0x000a, 0x1562: 0x000a, 0x1563: 0x000a,
+ 0x1564: 0x000a, 0x1565: 0x000a, 0x1566: 0x000a, 0x1567: 0x000a, 0x1568: 0x000a, 0x1569: 0x000a,
+ 0x156a: 0x000a, 0x156b: 0x000a, 0x156c: 0x000a, 0x156d: 0x000a, 0x156e: 0x000a, 0x156f: 0x000a,
+ 0x1570: 0x000a, 0x1571: 0x000a, 0x1572: 0x000a, 0x1573: 0x000a, 0x1574: 0x000a, 0x1575: 0x000a,
+ 0x1576: 0x000a, 0x1577: 0x000a, 0x1578: 0x000a, 0x1579: 0x000a, 0x157a: 0x000a, 0x157b: 0x000a,
+ 0x157c: 0x000a, 0x157d: 0x000a, 0x157e: 0x000a, 0x157f: 0x000a,
+ // Block 0x56, offset 0x1580
+ 0x1580: 0x000a, 0x1581: 0x000a, 0x1582: 0x000a, 0x1583: 0x000a, 0x1584: 0x000a, 0x1585: 0x000a,
+ 0x1586: 0x000a, 0x1587: 0x000a, 0x1588: 0x000a, 0x1589: 0x000a, 0x158a: 0x000a, 0x158b: 0x000a,
+ 0x158c: 0x000a, 0x158d: 0x000a, 0x158e: 0x000a, 0x158f: 0x000a, 0x1590: 0x000a, 0x1591: 0x000a,
+ 0x1592: 0x000a, 0x1593: 0x000a, 0x1594: 0x000a, 0x1595: 0x000a, 0x1596: 0x000a, 0x1597: 0x000a,
+ 0x1598: 0x000a, 0x1599: 0x000a, 0x159a: 0x000a, 0x159b: 0x000a, 0x159c: 0x000a, 0x159d: 0x000a,
+ 0x159e: 0x000a, 0x159f: 0x000a, 0x15a0: 0x000a, 0x15a1: 0x000a, 0x15a2: 0x000a, 0x15a3: 0x000a,
+ 0x15a4: 0x000a, 0x15a5: 0x000a, 0x15a6: 0x000a, 0x15a7: 0x000a, 0x15a8: 0x000a, 0x15a9: 0x000a,
+ 0x15aa: 0x000a, 0x15ab: 0x000a, 0x15ac: 0x000a, 0x15ad: 0x000a, 0x15ae: 0x000a, 0x15af: 0x000a,
+ 0x15b0: 0x000a, 0x15b1: 0x000a, 0x15b2: 0x000a, 0x15b3: 0x000a, 0x15b4: 0x000a, 0x15b5: 0x000a,
+ 0x15b6: 0x000a, 0x15b7: 0x000a, 0x15b8: 0x000a, 0x15b9: 0x000a, 0x15ba: 0x000a, 0x15bb: 0x000a,
+ 0x15bc: 0x000a, 0x15bd: 0x000a, 0x15be: 0x000a, 0x15bf: 0x000a,
+ // Block 0x57, offset 0x15c0
+ 0x15c0: 0x000a, 0x15c1: 0x000a, 0x15c2: 0x000a, 0x15c3: 0x000a, 0x15c4: 0x000a, 0x15c5: 0x000a,
+ 0x15c6: 0x000a, 0x15c7: 0x000a, 0x15c8: 0x000a, 0x15c9: 0x000a, 0x15ca: 0x000a, 0x15cb: 0x000a,
+ 0x15cc: 0x000a, 0x15cd: 0x000a, 0x15ce: 0x000a, 0x15cf: 0x000a, 0x15d0: 0x000a, 0x15d1: 0x000a,
+ 0x15d2: 0x0003, 0x15d3: 0x0004, 0x15d4: 0x000a, 0x15d5: 0x000a, 0x15d6: 0x000a, 0x15d7: 0x000a,
+ 0x15d8: 0x000a, 0x15d9: 0x000a, 0x15da: 0x000a, 0x15db: 0x000a, 0x15dc: 0x000a, 0x15dd: 0x000a,
+ 0x15de: 0x000a, 0x15df: 0x000a, 0x15e0: 0x000a, 0x15e1: 0x000a, 0x15e2: 0x000a, 0x15e3: 0x000a,
+ 0x15e4: 0x000a, 0x15e5: 0x000a, 0x15e6: 0x000a, 0x15e7: 0x000a, 0x15e8: 0x000a, 0x15e9: 0x000a,
+ 0x15ea: 0x000a, 0x15eb: 0x000a, 0x15ec: 0x000a, 0x15ed: 0x000a, 0x15ee: 0x000a, 0x15ef: 0x000a,
+ 0x15f0: 0x000a, 0x15f1: 0x000a, 0x15f2: 0x000a, 0x15f3: 0x000a, 0x15f4: 0x000a, 0x15f5: 0x000a,
+ 0x15f6: 0x000a, 0x15f7: 0x000a, 0x15f8: 0x000a, 0x15f9: 0x000a, 0x15fa: 0x000a, 0x15fb: 0x000a,
+ 0x15fc: 0x000a, 0x15fd: 0x000a, 0x15fe: 0x000a, 0x15ff: 0x000a,
+ // Block 0x58, offset 0x1600
+ 0x1600: 0x000a, 0x1601: 0x000a, 0x1602: 0x000a, 0x1603: 0x000a, 0x1604: 0x000a, 0x1605: 0x000a,
+ 0x1606: 0x000a, 0x1607: 0x000a, 0x1608: 0x003a, 0x1609: 0x002a, 0x160a: 0x003a, 0x160b: 0x002a,
+ 0x160c: 0x000a, 0x160d: 0x000a, 0x160e: 0x000a, 0x160f: 0x000a, 0x1610: 0x000a, 0x1611: 0x000a,
+ 0x1612: 0x000a, 0x1613: 0x000a, 0x1614: 0x000a, 0x1615: 0x000a, 0x1616: 0x000a, 0x1617: 0x000a,
+ 0x1618: 0x000a, 0x1619: 0x000a, 0x161a: 0x000a, 0x161b: 0x000a, 0x161c: 0x000a, 0x161d: 0x000a,
+ 0x161e: 0x000a, 0x161f: 0x000a, 0x1620: 0x000a, 0x1621: 0x000a, 0x1622: 0x000a, 0x1623: 0x000a,
+ 0x1624: 0x000a, 0x1625: 0x000a, 0x1626: 0x000a, 0x1627: 0x000a, 0x1628: 0x000a, 0x1629: 0x009a,
+ 0x162a: 0x008a, 0x162b: 0x000a, 0x162c: 0x000a, 0x162d: 0x000a, 0x162e: 0x000a, 0x162f: 0x000a,
+ 0x1630: 0x000a, 0x1631: 0x000a, 0x1632: 0x000a, 0x1633: 0x000a, 0x1634: 0x000a, 0x1635: 0x000a,
+ // Block 0x59, offset 0x1640
+ 0x167b: 0x000a,
+ 0x167c: 0x000a, 0x167d: 0x000a, 0x167e: 0x000a, 0x167f: 0x000a,
+ // Block 0x5a, offset 0x1680
+ 0x1680: 0x000a, 0x1681: 0x000a, 0x1682: 0x000a, 0x1683: 0x000a, 0x1684: 0x000a, 0x1685: 0x000a,
+ 0x1686: 0x000a, 0x1687: 0x000a, 0x1688: 0x000a, 0x1689: 0x000a, 0x168a: 0x000a, 0x168b: 0x000a,
+ 0x168c: 0x000a, 0x168d: 0x000a, 0x168e: 0x000a, 0x168f: 0x000a, 0x1690: 0x000a, 0x1691: 0x000a,
+ 0x1692: 0x000a, 0x1693: 0x000a, 0x1694: 0x000a, 0x1696: 0x000a, 0x1697: 0x000a,
+ 0x1698: 0x000a, 0x1699: 0x000a, 0x169a: 0x000a, 0x169b: 0x000a, 0x169c: 0x000a, 0x169d: 0x000a,
+ 0x169e: 0x000a, 0x169f: 0x000a, 0x16a0: 0x000a, 0x16a1: 0x000a, 0x16a2: 0x000a, 0x16a3: 0x000a,
+ 0x16a4: 0x000a, 0x16a5: 0x000a, 0x16a6: 0x000a, 0x16a7: 0x000a, 0x16a8: 0x000a, 0x16a9: 0x000a,
+ 0x16aa: 0x000a, 0x16ab: 0x000a, 0x16ac: 0x000a, 0x16ad: 0x000a, 0x16ae: 0x000a, 0x16af: 0x000a,
+ 0x16b0: 0x000a, 0x16b1: 0x000a, 0x16b2: 0x000a, 0x16b3: 0x000a, 0x16b4: 0x000a, 0x16b5: 0x000a,
+ 0x16b6: 0x000a, 0x16b7: 0x000a, 0x16b8: 0x000a, 0x16b9: 0x000a, 0x16ba: 0x000a, 0x16bb: 0x000a,
+ 0x16bc: 0x000a, 0x16bd: 0x000a, 0x16be: 0x000a, 0x16bf: 0x000a,
+ // Block 0x5b, offset 0x16c0
+ 0x16c0: 0x000a, 0x16c1: 0x000a, 0x16c2: 0x000a, 0x16c3: 0x000a, 0x16c4: 0x000a, 0x16c5: 0x000a,
+ 0x16c6: 0x000a, 0x16c7: 0x000a, 0x16c8: 0x000a, 0x16c9: 0x000a, 0x16ca: 0x000a, 0x16cb: 0x000a,
+ 0x16cc: 0x000a, 0x16cd: 0x000a, 0x16ce: 0x000a, 0x16cf: 0x000a, 0x16d0: 0x000a, 0x16d1: 0x000a,
+ 0x16d2: 0x000a, 0x16d3: 0x000a, 0x16d4: 0x000a, 0x16d5: 0x000a, 0x16d6: 0x000a, 0x16d7: 0x000a,
+ 0x16d8: 0x000a, 0x16d9: 0x000a, 0x16da: 0x000a, 0x16db: 0x000a, 0x16dc: 0x000a, 0x16dd: 0x000a,
+ 0x16de: 0x000a, 0x16df: 0x000a, 0x16e0: 0x000a, 0x16e1: 0x000a, 0x16e2: 0x000a, 0x16e3: 0x000a,
+ 0x16e4: 0x000a, 0x16e5: 0x000a, 0x16e6: 0x000a, 0x16e7: 0x000a, 0x16e8: 0x000a, 0x16e9: 0x000a,
+ 0x16ea: 0x000a, 0x16eb: 0x000a, 0x16ec: 0x000a, 0x16ed: 0x000a, 0x16ee: 0x000a, 0x16ef: 0x000a,
+ 0x16f0: 0x000a, 0x16f1: 0x000a, 0x16f2: 0x000a, 0x16f3: 0x000a, 0x16f4: 0x000a, 0x16f5: 0x000a,
+ 0x16f6: 0x000a, 0x16f7: 0x000a, 0x16f8: 0x000a, 0x16f9: 0x000a, 0x16fa: 0x000a, 0x16fb: 0x000a,
+ 0x16fc: 0x000a, 0x16fd: 0x000a, 0x16fe: 0x000a,
+ // Block 0x5c, offset 0x1700
+ 0x1700: 0x000a, 0x1701: 0x000a, 0x1702: 0x000a, 0x1703: 0x000a, 0x1704: 0x000a, 0x1705: 0x000a,
+ 0x1706: 0x000a, 0x1707: 0x000a, 0x1708: 0x000a, 0x1709: 0x000a, 0x170a: 0x000a, 0x170b: 0x000a,
+ 0x170c: 0x000a, 0x170d: 0x000a, 0x170e: 0x000a, 0x170f: 0x000a, 0x1710: 0x000a, 0x1711: 0x000a,
+ 0x1712: 0x000a, 0x1713: 0x000a, 0x1714: 0x000a, 0x1715: 0x000a, 0x1716: 0x000a, 0x1717: 0x000a,
+ 0x1718: 0x000a, 0x1719: 0x000a, 0x171a: 0x000a, 0x171b: 0x000a, 0x171c: 0x000a, 0x171d: 0x000a,
+ 0x171e: 0x000a, 0x171f: 0x000a, 0x1720: 0x000a, 0x1721: 0x000a, 0x1722: 0x000a, 0x1723: 0x000a,
+ 0x1724: 0x000a, 0x1725: 0x000a, 0x1726: 0x000a,
+ // Block 0x5d, offset 0x1740
+ 0x1740: 0x000a, 0x1741: 0x000a, 0x1742: 0x000a, 0x1743: 0x000a, 0x1744: 0x000a, 0x1745: 0x000a,
+ 0x1746: 0x000a, 0x1747: 0x000a, 0x1748: 0x000a, 0x1749: 0x000a, 0x174a: 0x000a,
+ 0x1760: 0x000a, 0x1761: 0x000a, 0x1762: 0x000a, 0x1763: 0x000a,
+ 0x1764: 0x000a, 0x1765: 0x000a, 0x1766: 0x000a, 0x1767: 0x000a, 0x1768: 0x000a, 0x1769: 0x000a,
+ 0x176a: 0x000a, 0x176b: 0x000a, 0x176c: 0x000a, 0x176d: 0x000a, 0x176e: 0x000a, 0x176f: 0x000a,
+ 0x1770: 0x000a, 0x1771: 0x000a, 0x1772: 0x000a, 0x1773: 0x000a, 0x1774: 0x000a, 0x1775: 0x000a,
+ 0x1776: 0x000a, 0x1777: 0x000a, 0x1778: 0x000a, 0x1779: 0x000a, 0x177a: 0x000a, 0x177b: 0x000a,
+ 0x177c: 0x000a, 0x177d: 0x000a, 0x177e: 0x000a, 0x177f: 0x000a,
+ // Block 0x5e, offset 0x1780
+ 0x1780: 0x000a, 0x1781: 0x000a, 0x1782: 0x000a, 0x1783: 0x000a, 0x1784: 0x000a, 0x1785: 0x000a,
+ 0x1786: 0x000a, 0x1787: 0x000a, 0x1788: 0x0002, 0x1789: 0x0002, 0x178a: 0x0002, 0x178b: 0x0002,
+ 0x178c: 0x0002, 0x178d: 0x0002, 0x178e: 0x0002, 0x178f: 0x0002, 0x1790: 0x0002, 0x1791: 0x0002,
+ 0x1792: 0x0002, 0x1793: 0x0002, 0x1794: 0x0002, 0x1795: 0x0002, 0x1796: 0x0002, 0x1797: 0x0002,
+ 0x1798: 0x0002, 0x1799: 0x0002, 0x179a: 0x0002, 0x179b: 0x0002,
+ // Block 0x5f, offset 0x17c0
+ 0x17ea: 0x000a, 0x17eb: 0x000a, 0x17ec: 0x000a, 0x17ed: 0x000a, 0x17ee: 0x000a, 0x17ef: 0x000a,
+ 0x17f0: 0x000a, 0x17f1: 0x000a, 0x17f2: 0x000a, 0x17f3: 0x000a, 0x17f4: 0x000a, 0x17f5: 0x000a,
+ 0x17f6: 0x000a, 0x17f7: 0x000a, 0x17f8: 0x000a, 0x17f9: 0x000a, 0x17fa: 0x000a, 0x17fb: 0x000a,
+ 0x17fc: 0x000a, 0x17fd: 0x000a, 0x17fe: 0x000a, 0x17ff: 0x000a,
+ // Block 0x60, offset 0x1800
+ 0x1800: 0x000a, 0x1801: 0x000a, 0x1802: 0x000a, 0x1803: 0x000a, 0x1804: 0x000a, 0x1805: 0x000a,
+ 0x1806: 0x000a, 0x1807: 0x000a, 0x1808: 0x000a, 0x1809: 0x000a, 0x180a: 0x000a, 0x180b: 0x000a,
+ 0x180c: 0x000a, 0x180d: 0x000a, 0x180e: 0x000a, 0x180f: 0x000a, 0x1810: 0x000a, 0x1811: 0x000a,
+ 0x1812: 0x000a, 0x1813: 0x000a, 0x1814: 0x000a, 0x1815: 0x000a, 0x1816: 0x000a, 0x1817: 0x000a,
+ 0x1818: 0x000a, 0x1819: 0x000a, 0x181a: 0x000a, 0x181b: 0x000a, 0x181c: 0x000a, 0x181d: 0x000a,
+ 0x181e: 0x000a, 0x181f: 0x000a, 0x1820: 0x000a, 0x1821: 0x000a, 0x1822: 0x000a, 0x1823: 0x000a,
+ 0x1824: 0x000a, 0x1825: 0x000a, 0x1826: 0x000a, 0x1827: 0x000a, 0x1828: 0x000a, 0x1829: 0x000a,
+ 0x182a: 0x000a, 0x182b: 0x000a, 0x182d: 0x000a, 0x182e: 0x000a, 0x182f: 0x000a,
+ 0x1830: 0x000a, 0x1831: 0x000a, 0x1832: 0x000a, 0x1833: 0x000a, 0x1834: 0x000a, 0x1835: 0x000a,
+ 0x1836: 0x000a, 0x1837: 0x000a, 0x1838: 0x000a, 0x1839: 0x000a, 0x183a: 0x000a, 0x183b: 0x000a,
+ 0x183c: 0x000a, 0x183d: 0x000a, 0x183e: 0x000a, 0x183f: 0x000a,
+ // Block 0x61, offset 0x1840
+ 0x1840: 0x000a, 0x1841: 0x000a, 0x1842: 0x000a, 0x1843: 0x000a, 0x1844: 0x000a, 0x1845: 0x000a,
+ 0x1846: 0x000a, 0x1847: 0x000a, 0x1848: 0x000a, 0x1849: 0x000a, 0x184a: 0x000a, 0x184b: 0x000a,
+ 0x184c: 0x000a, 0x184d: 0x000a, 0x184e: 0x000a, 0x184f: 0x000a, 0x1850: 0x000a, 0x1851: 0x000a,
+ 0x1852: 0x000a, 0x1853: 0x000a, 0x1854: 0x000a, 0x1855: 0x000a, 0x1856: 0x000a, 0x1857: 0x000a,
+ 0x1858: 0x000a, 0x1859: 0x000a, 0x185a: 0x000a, 0x185b: 0x000a, 0x185c: 0x000a, 0x185d: 0x000a,
+ 0x185e: 0x000a, 0x185f: 0x000a, 0x1860: 0x000a, 0x1861: 0x000a, 0x1862: 0x000a, 0x1863: 0x000a,
+ 0x1864: 0x000a, 0x1865: 0x000a, 0x1866: 0x000a, 0x1867: 0x000a, 0x1868: 0x003a, 0x1869: 0x002a,
+ 0x186a: 0x003a, 0x186b: 0x002a, 0x186c: 0x003a, 0x186d: 0x002a, 0x186e: 0x003a, 0x186f: 0x002a,
+ 0x1870: 0x003a, 0x1871: 0x002a, 0x1872: 0x003a, 0x1873: 0x002a, 0x1874: 0x003a, 0x1875: 0x002a,
+ 0x1876: 0x000a, 0x1877: 0x000a, 0x1878: 0x000a, 0x1879: 0x000a, 0x187a: 0x000a, 0x187b: 0x000a,
+ 0x187c: 0x000a, 0x187d: 0x000a, 0x187e: 0x000a, 0x187f: 0x000a,
+ // Block 0x62, offset 0x1880
+ 0x1880: 0x000a, 0x1881: 0x000a, 0x1882: 0x000a, 0x1883: 0x000a, 0x1884: 0x000a, 0x1885: 0x009a,
+ 0x1886: 0x008a, 0x1887: 0x000a, 0x1888: 0x000a, 0x1889: 0x000a, 0x188a: 0x000a, 0x188b: 0x000a,
+ 0x188c: 0x000a, 0x188d: 0x000a, 0x188e: 0x000a, 0x188f: 0x000a, 0x1890: 0x000a, 0x1891: 0x000a,
+ 0x1892: 0x000a, 0x1893: 0x000a, 0x1894: 0x000a, 0x1895: 0x000a, 0x1896: 0x000a, 0x1897: 0x000a,
+ 0x1898: 0x000a, 0x1899: 0x000a, 0x189a: 0x000a, 0x189b: 0x000a, 0x189c: 0x000a, 0x189d: 0x000a,
+ 0x189e: 0x000a, 0x189f: 0x000a, 0x18a0: 0x000a, 0x18a1: 0x000a, 0x18a2: 0x000a, 0x18a3: 0x000a,
+ 0x18a4: 0x000a, 0x18a5: 0x000a, 0x18a6: 0x003a, 0x18a7: 0x002a, 0x18a8: 0x003a, 0x18a9: 0x002a,
+ 0x18aa: 0x003a, 0x18ab: 0x002a, 0x18ac: 0x003a, 0x18ad: 0x002a, 0x18ae: 0x003a, 0x18af: 0x002a,
+ 0x18b0: 0x000a, 0x18b1: 0x000a, 0x18b2: 0x000a, 0x18b3: 0x000a, 0x18b4: 0x000a, 0x18b5: 0x000a,
+ 0x18b6: 0x000a, 0x18b7: 0x000a, 0x18b8: 0x000a, 0x18b9: 0x000a, 0x18ba: 0x000a, 0x18bb: 0x000a,
+ 0x18bc: 0x000a, 0x18bd: 0x000a, 0x18be: 0x000a, 0x18bf: 0x000a,
+ // Block 0x63, offset 0x18c0
+ 0x18c0: 0x000a, 0x18c1: 0x000a, 0x18c2: 0x000a, 0x18c3: 0x007a, 0x18c4: 0x006a, 0x18c5: 0x009a,
+ 0x18c6: 0x008a, 0x18c7: 0x00ba, 0x18c8: 0x00aa, 0x18c9: 0x009a, 0x18ca: 0x008a, 0x18cb: 0x007a,
+ 0x18cc: 0x006a, 0x18cd: 0x00da, 0x18ce: 0x002a, 0x18cf: 0x003a, 0x18d0: 0x00ca, 0x18d1: 0x009a,
+ 0x18d2: 0x008a, 0x18d3: 0x007a, 0x18d4: 0x006a, 0x18d5: 0x009a, 0x18d6: 0x008a, 0x18d7: 0x00ba,
+ 0x18d8: 0x00aa, 0x18d9: 0x000a, 0x18da: 0x000a, 0x18db: 0x000a, 0x18dc: 0x000a, 0x18dd: 0x000a,
+ 0x18de: 0x000a, 0x18df: 0x000a, 0x18e0: 0x000a, 0x18e1: 0x000a, 0x18e2: 0x000a, 0x18e3: 0x000a,
+ 0x18e4: 0x000a, 0x18e5: 0x000a, 0x18e6: 0x000a, 0x18e7: 0x000a, 0x18e8: 0x000a, 0x18e9: 0x000a,
+ 0x18ea: 0x000a, 0x18eb: 0x000a, 0x18ec: 0x000a, 0x18ed: 0x000a, 0x18ee: 0x000a, 0x18ef: 0x000a,
+ 0x18f0: 0x000a, 0x18f1: 0x000a, 0x18f2: 0x000a, 0x18f3: 0x000a, 0x18f4: 0x000a, 0x18f5: 0x000a,
+ 0x18f6: 0x000a, 0x18f7: 0x000a, 0x18f8: 0x000a, 0x18f9: 0x000a, 0x18fa: 0x000a, 0x18fb: 0x000a,
+ 0x18fc: 0x000a, 0x18fd: 0x000a, 0x18fe: 0x000a, 0x18ff: 0x000a,
+ // Block 0x64, offset 0x1900
+ 0x1900: 0x000a, 0x1901: 0x000a, 0x1902: 0x000a, 0x1903: 0x000a, 0x1904: 0x000a, 0x1905: 0x000a,
+ 0x1906: 0x000a, 0x1907: 0x000a, 0x1908: 0x000a, 0x1909: 0x000a, 0x190a: 0x000a, 0x190b: 0x000a,
+ 0x190c: 0x000a, 0x190d: 0x000a, 0x190e: 0x000a, 0x190f: 0x000a, 0x1910: 0x000a, 0x1911: 0x000a,
+ 0x1912: 0x000a, 0x1913: 0x000a, 0x1914: 0x000a, 0x1915: 0x000a, 0x1916: 0x000a, 0x1917: 0x000a,
+ 0x1918: 0x003a, 0x1919: 0x002a, 0x191a: 0x003a, 0x191b: 0x002a, 0x191c: 0x000a, 0x191d: 0x000a,
+ 0x191e: 0x000a, 0x191f: 0x000a, 0x1920: 0x000a, 0x1921: 0x000a, 0x1922: 0x000a, 0x1923: 0x000a,
+ 0x1924: 0x000a, 0x1925: 0x000a, 0x1926: 0x000a, 0x1927: 0x000a, 0x1928: 0x000a, 0x1929: 0x000a,
+ 0x192a: 0x000a, 0x192b: 0x000a, 0x192c: 0x000a, 0x192d: 0x000a, 0x192e: 0x000a, 0x192f: 0x000a,
+ 0x1930: 0x000a, 0x1931: 0x000a, 0x1932: 0x000a, 0x1933: 0x000a, 0x1934: 0x000a, 0x1935: 0x000a,
+ 0x1936: 0x000a, 0x1937: 0x000a, 0x1938: 0x000a, 0x1939: 0x000a, 0x193a: 0x000a, 0x193b: 0x000a,
+ 0x193c: 0x003a, 0x193d: 0x002a, 0x193e: 0x000a, 0x193f: 0x000a,
+ // Block 0x65, offset 0x1940
+ 0x1940: 0x000a, 0x1941: 0x000a, 0x1942: 0x000a, 0x1943: 0x000a, 0x1944: 0x000a, 0x1945: 0x000a,
+ 0x1946: 0x000a, 0x1947: 0x000a, 0x1948: 0x000a, 0x1949: 0x000a, 0x194a: 0x000a, 0x194b: 0x000a,
+ 0x194c: 0x000a, 0x194d: 0x000a, 0x194e: 0x000a, 0x194f: 0x000a, 0x1950: 0x000a, 0x1951: 0x000a,
+ 0x1952: 0x000a, 0x1953: 0x000a, 0x1954: 0x000a, 0x1955: 0x000a, 0x1956: 0x000a, 0x1957: 0x000a,
+ 0x1958: 0x000a, 0x1959: 0x000a, 0x195a: 0x000a, 0x195b: 0x000a, 0x195c: 0x000a, 0x195d: 0x000a,
+ 0x195e: 0x000a, 0x195f: 0x000a, 0x1960: 0x000a, 0x1961: 0x000a, 0x1962: 0x000a, 0x1963: 0x000a,
+ 0x1964: 0x000a, 0x1965: 0x000a, 0x1966: 0x000a, 0x1967: 0x000a, 0x1968: 0x000a, 0x1969: 0x000a,
+ 0x196a: 0x000a, 0x196b: 0x000a, 0x196c: 0x000a, 0x196d: 0x000a, 0x196e: 0x000a, 0x196f: 0x000a,
+ 0x1970: 0x000a, 0x1971: 0x000a, 0x1972: 0x000a, 0x1973: 0x000a,
+ 0x1976: 0x000a, 0x1977: 0x000a, 0x1978: 0x000a, 0x1979: 0x000a, 0x197a: 0x000a, 0x197b: 0x000a,
+ 0x197c: 0x000a, 0x197d: 0x000a, 0x197e: 0x000a, 0x197f: 0x000a,
+ // Block 0x66, offset 0x1980
+ 0x1980: 0x000a, 0x1981: 0x000a, 0x1982: 0x000a, 0x1983: 0x000a, 0x1984: 0x000a, 0x1985: 0x000a,
+ 0x1986: 0x000a, 0x1987: 0x000a, 0x1988: 0x000a, 0x1989: 0x000a, 0x198a: 0x000a, 0x198b: 0x000a,
+ 0x198c: 0x000a, 0x198d: 0x000a, 0x198e: 0x000a, 0x198f: 0x000a, 0x1990: 0x000a, 0x1991: 0x000a,
+ 0x1992: 0x000a, 0x1993: 0x000a, 0x1994: 0x000a, 0x1995: 0x000a,
+ 0x1998: 0x000a, 0x1999: 0x000a, 0x199a: 0x000a, 0x199b: 0x000a, 0x199c: 0x000a, 0x199d: 0x000a,
+ 0x199e: 0x000a, 0x199f: 0x000a, 0x19a0: 0x000a, 0x19a1: 0x000a, 0x19a2: 0x000a, 0x19a3: 0x000a,
+ 0x19a4: 0x000a, 0x19a5: 0x000a, 0x19a6: 0x000a, 0x19a7: 0x000a, 0x19a8: 0x000a, 0x19a9: 0x000a,
+ 0x19aa: 0x000a, 0x19ab: 0x000a, 0x19ac: 0x000a, 0x19ad: 0x000a, 0x19ae: 0x000a, 0x19af: 0x000a,
+ 0x19b0: 0x000a, 0x19b1: 0x000a, 0x19b2: 0x000a, 0x19b3: 0x000a, 0x19b4: 0x000a, 0x19b5: 0x000a,
+ 0x19b6: 0x000a, 0x19b7: 0x000a, 0x19b8: 0x000a, 0x19b9: 0x000a,
+ 0x19bd: 0x000a, 0x19be: 0x000a, 0x19bf: 0x000a,
+ // Block 0x67, offset 0x19c0
+ 0x19c0: 0x000a, 0x19c1: 0x000a, 0x19c2: 0x000a, 0x19c3: 0x000a, 0x19c4: 0x000a, 0x19c5: 0x000a,
+ 0x19c6: 0x000a, 0x19c7: 0x000a, 0x19c8: 0x000a, 0x19ca: 0x000a, 0x19cb: 0x000a,
+ 0x19cc: 0x000a, 0x19cd: 0x000a, 0x19ce: 0x000a, 0x19cf: 0x000a, 0x19d0: 0x000a, 0x19d1: 0x000a,
+ 0x19ec: 0x000a, 0x19ed: 0x000a, 0x19ee: 0x000a, 0x19ef: 0x000a,
+ // Block 0x68, offset 0x1a00
+ 0x1a25: 0x000a, 0x1a26: 0x000a, 0x1a27: 0x000a, 0x1a28: 0x000a, 0x1a29: 0x000a,
+ 0x1a2a: 0x000a, 0x1a2f: 0x000c,
+ 0x1a30: 0x000c, 0x1a31: 0x000c,
+ 0x1a39: 0x000a, 0x1a3a: 0x000a, 0x1a3b: 0x000a,
+ 0x1a3c: 0x000a, 0x1a3d: 0x000a, 0x1a3e: 0x000a, 0x1a3f: 0x000a,
+ // Block 0x69, offset 0x1a40
+ 0x1a7f: 0x000c,
+ // Block 0x6a, offset 0x1a80
+ 0x1aa0: 0x000c, 0x1aa1: 0x000c, 0x1aa2: 0x000c, 0x1aa3: 0x000c,
+ 0x1aa4: 0x000c, 0x1aa5: 0x000c, 0x1aa6: 0x000c, 0x1aa7: 0x000c, 0x1aa8: 0x000c, 0x1aa9: 0x000c,
+ 0x1aaa: 0x000c, 0x1aab: 0x000c, 0x1aac: 0x000c, 0x1aad: 0x000c, 0x1aae: 0x000c, 0x1aaf: 0x000c,
+ 0x1ab0: 0x000c, 0x1ab1: 0x000c, 0x1ab2: 0x000c, 0x1ab3: 0x000c, 0x1ab4: 0x000c, 0x1ab5: 0x000c,
+ 0x1ab6: 0x000c, 0x1ab7: 0x000c, 0x1ab8: 0x000c, 0x1ab9: 0x000c, 0x1aba: 0x000c, 0x1abb: 0x000c,
+ 0x1abc: 0x000c, 0x1abd: 0x000c, 0x1abe: 0x000c, 0x1abf: 0x000c,
+ // Block 0x6b, offset 0x1ac0
+ 0x1ac0: 0x000a, 0x1ac1: 0x000a, 0x1ac2: 0x000a, 0x1ac3: 0x000a, 0x1ac4: 0x000a, 0x1ac5: 0x000a,
+ 0x1ac6: 0x000a, 0x1ac7: 0x000a, 0x1ac8: 0x000a, 0x1ac9: 0x000a, 0x1aca: 0x000a, 0x1acb: 0x000a,
+ 0x1acc: 0x000a, 0x1acd: 0x000a, 0x1ace: 0x000a, 0x1acf: 0x000a, 0x1ad0: 0x000a, 0x1ad1: 0x000a,
+ 0x1ad2: 0x000a, 0x1ad3: 0x000a, 0x1ad4: 0x000a, 0x1ad5: 0x000a, 0x1ad6: 0x000a, 0x1ad7: 0x000a,
+ 0x1ad8: 0x000a, 0x1ad9: 0x000a, 0x1ada: 0x000a, 0x1adb: 0x000a, 0x1adc: 0x000a, 0x1add: 0x000a,
+ 0x1ade: 0x000a, 0x1adf: 0x000a, 0x1ae0: 0x000a, 0x1ae1: 0x000a, 0x1ae2: 0x003a, 0x1ae3: 0x002a,
+ 0x1ae4: 0x003a, 0x1ae5: 0x002a, 0x1ae6: 0x003a, 0x1ae7: 0x002a, 0x1ae8: 0x003a, 0x1ae9: 0x002a,
+ 0x1aea: 0x000a, 0x1aeb: 0x000a, 0x1aec: 0x000a, 0x1aed: 0x000a, 0x1aee: 0x000a, 0x1aef: 0x000a,
+ 0x1af0: 0x000a, 0x1af1: 0x000a, 0x1af2: 0x000a, 0x1af3: 0x000a, 0x1af4: 0x000a, 0x1af5: 0x000a,
+ 0x1af6: 0x000a, 0x1af7: 0x000a, 0x1af8: 0x000a, 0x1af9: 0x000a, 0x1afa: 0x000a, 0x1afb: 0x000a,
+ 0x1afc: 0x000a, 0x1afd: 0x000a, 0x1afe: 0x000a, 0x1aff: 0x000a,
+ // Block 0x6c, offset 0x1b00
+ 0x1b00: 0x000a, 0x1b01: 0x000a, 0x1b02: 0x000a, 0x1b03: 0x000a, 0x1b04: 0x000a,
+ // Block 0x6d, offset 0x1b40
+ 0x1b40: 0x000a, 0x1b41: 0x000a, 0x1b42: 0x000a, 0x1b43: 0x000a, 0x1b44: 0x000a, 0x1b45: 0x000a,
+ 0x1b46: 0x000a, 0x1b47: 0x000a, 0x1b48: 0x000a, 0x1b49: 0x000a, 0x1b4a: 0x000a, 0x1b4b: 0x000a,
+ 0x1b4c: 0x000a, 0x1b4d: 0x000a, 0x1b4e: 0x000a, 0x1b4f: 0x000a, 0x1b50: 0x000a, 0x1b51: 0x000a,
+ 0x1b52: 0x000a, 0x1b53: 0x000a, 0x1b54: 0x000a, 0x1b55: 0x000a, 0x1b56: 0x000a, 0x1b57: 0x000a,
+ 0x1b58: 0x000a, 0x1b59: 0x000a, 0x1b5b: 0x000a, 0x1b5c: 0x000a, 0x1b5d: 0x000a,
+ 0x1b5e: 0x000a, 0x1b5f: 0x000a, 0x1b60: 0x000a, 0x1b61: 0x000a, 0x1b62: 0x000a, 0x1b63: 0x000a,
+ 0x1b64: 0x000a, 0x1b65: 0x000a, 0x1b66: 0x000a, 0x1b67: 0x000a, 0x1b68: 0x000a, 0x1b69: 0x000a,
+ 0x1b6a: 0x000a, 0x1b6b: 0x000a, 0x1b6c: 0x000a, 0x1b6d: 0x000a, 0x1b6e: 0x000a, 0x1b6f: 0x000a,
+ 0x1b70: 0x000a, 0x1b71: 0x000a, 0x1b72: 0x000a, 0x1b73: 0x000a, 0x1b74: 0x000a, 0x1b75: 0x000a,
+ 0x1b76: 0x000a, 0x1b77: 0x000a, 0x1b78: 0x000a, 0x1b79: 0x000a, 0x1b7a: 0x000a, 0x1b7b: 0x000a,
+ 0x1b7c: 0x000a, 0x1b7d: 0x000a, 0x1b7e: 0x000a, 0x1b7f: 0x000a,
+ // Block 0x6e, offset 0x1b80
+ 0x1b80: 0x000a, 0x1b81: 0x000a, 0x1b82: 0x000a, 0x1b83: 0x000a, 0x1b84: 0x000a, 0x1b85: 0x000a,
+ 0x1b86: 0x000a, 0x1b87: 0x000a, 0x1b88: 0x000a, 0x1b89: 0x000a, 0x1b8a: 0x000a, 0x1b8b: 0x000a,
+ 0x1b8c: 0x000a, 0x1b8d: 0x000a, 0x1b8e: 0x000a, 0x1b8f: 0x000a, 0x1b90: 0x000a, 0x1b91: 0x000a,
+ 0x1b92: 0x000a, 0x1b93: 0x000a, 0x1b94: 0x000a, 0x1b95: 0x000a, 0x1b96: 0x000a, 0x1b97: 0x000a,
+ 0x1b98: 0x000a, 0x1b99: 0x000a, 0x1b9a: 0x000a, 0x1b9b: 0x000a, 0x1b9c: 0x000a, 0x1b9d: 0x000a,
+ 0x1b9e: 0x000a, 0x1b9f: 0x000a, 0x1ba0: 0x000a, 0x1ba1: 0x000a, 0x1ba2: 0x000a, 0x1ba3: 0x000a,
+ 0x1ba4: 0x000a, 0x1ba5: 0x000a, 0x1ba6: 0x000a, 0x1ba7: 0x000a, 0x1ba8: 0x000a, 0x1ba9: 0x000a,
+ 0x1baa: 0x000a, 0x1bab: 0x000a, 0x1bac: 0x000a, 0x1bad: 0x000a, 0x1bae: 0x000a, 0x1baf: 0x000a,
+ 0x1bb0: 0x000a, 0x1bb1: 0x000a, 0x1bb2: 0x000a, 0x1bb3: 0x000a,
+ // Block 0x6f, offset 0x1bc0
+ 0x1bc0: 0x000a, 0x1bc1: 0x000a, 0x1bc2: 0x000a, 0x1bc3: 0x000a, 0x1bc4: 0x000a, 0x1bc5: 0x000a,
+ 0x1bc6: 0x000a, 0x1bc7: 0x000a, 0x1bc8: 0x000a, 0x1bc9: 0x000a, 0x1bca: 0x000a, 0x1bcb: 0x000a,
+ 0x1bcc: 0x000a, 0x1bcd: 0x000a, 0x1bce: 0x000a, 0x1bcf: 0x000a, 0x1bd0: 0x000a, 0x1bd1: 0x000a,
+ 0x1bd2: 0x000a, 0x1bd3: 0x000a, 0x1bd4: 0x000a, 0x1bd5: 0x000a,
+ 0x1bf0: 0x000a, 0x1bf1: 0x000a, 0x1bf2: 0x000a, 0x1bf3: 0x000a, 0x1bf4: 0x000a, 0x1bf5: 0x000a,
+ 0x1bf6: 0x000a, 0x1bf7: 0x000a, 0x1bf8: 0x000a, 0x1bf9: 0x000a, 0x1bfa: 0x000a, 0x1bfb: 0x000a,
+ // Block 0x70, offset 0x1c00
+ 0x1c00: 0x0009, 0x1c01: 0x000a, 0x1c02: 0x000a, 0x1c03: 0x000a, 0x1c04: 0x000a,
+ 0x1c08: 0x003a, 0x1c09: 0x002a, 0x1c0a: 0x003a, 0x1c0b: 0x002a,
+ 0x1c0c: 0x003a, 0x1c0d: 0x002a, 0x1c0e: 0x003a, 0x1c0f: 0x002a, 0x1c10: 0x003a, 0x1c11: 0x002a,
+ 0x1c12: 0x000a, 0x1c13: 0x000a, 0x1c14: 0x003a, 0x1c15: 0x002a, 0x1c16: 0x003a, 0x1c17: 0x002a,
+ 0x1c18: 0x003a, 0x1c19: 0x002a, 0x1c1a: 0x003a, 0x1c1b: 0x002a, 0x1c1c: 0x000a, 0x1c1d: 0x000a,
+ 0x1c1e: 0x000a, 0x1c1f: 0x000a, 0x1c20: 0x000a,
+ 0x1c2a: 0x000c, 0x1c2b: 0x000c, 0x1c2c: 0x000c, 0x1c2d: 0x000c,
+ 0x1c30: 0x000a,
+ 0x1c36: 0x000a, 0x1c37: 0x000a,
+ 0x1c3d: 0x000a, 0x1c3e: 0x000a, 0x1c3f: 0x000a,
+ // Block 0x71, offset 0x1c40
+ 0x1c59: 0x000c, 0x1c5a: 0x000c, 0x1c5b: 0x000a, 0x1c5c: 0x000a,
+ 0x1c60: 0x000a,
+ // Block 0x72, offset 0x1c80
+ 0x1cbb: 0x000a,
+ // Block 0x73, offset 0x1cc0
+ 0x1cc0: 0x000a, 0x1cc1: 0x000a, 0x1cc2: 0x000a, 0x1cc3: 0x000a, 0x1cc4: 0x000a, 0x1cc5: 0x000a,
+ 0x1cc6: 0x000a, 0x1cc7: 0x000a, 0x1cc8: 0x000a, 0x1cc9: 0x000a, 0x1cca: 0x000a, 0x1ccb: 0x000a,
+ 0x1ccc: 0x000a, 0x1ccd: 0x000a, 0x1cce: 0x000a, 0x1ccf: 0x000a, 0x1cd0: 0x000a, 0x1cd1: 0x000a,
+ 0x1cd2: 0x000a, 0x1cd3: 0x000a, 0x1cd4: 0x000a, 0x1cd5: 0x000a, 0x1cd6: 0x000a, 0x1cd7: 0x000a,
+ 0x1cd8: 0x000a, 0x1cd9: 0x000a, 0x1cda: 0x000a, 0x1cdb: 0x000a, 0x1cdc: 0x000a, 0x1cdd: 0x000a,
+ 0x1cde: 0x000a, 0x1cdf: 0x000a, 0x1ce0: 0x000a, 0x1ce1: 0x000a, 0x1ce2: 0x000a, 0x1ce3: 0x000a,
+ // Block 0x74, offset 0x1d00
+ 0x1d1d: 0x000a,
+ 0x1d1e: 0x000a,
+ // Block 0x75, offset 0x1d40
+ 0x1d50: 0x000a, 0x1d51: 0x000a,
+ 0x1d52: 0x000a, 0x1d53: 0x000a, 0x1d54: 0x000a, 0x1d55: 0x000a, 0x1d56: 0x000a, 0x1d57: 0x000a,
+ 0x1d58: 0x000a, 0x1d59: 0x000a, 0x1d5a: 0x000a, 0x1d5b: 0x000a, 0x1d5c: 0x000a, 0x1d5d: 0x000a,
+ 0x1d5e: 0x000a, 0x1d5f: 0x000a,
+ 0x1d7c: 0x000a, 0x1d7d: 0x000a, 0x1d7e: 0x000a,
+ // Block 0x76, offset 0x1d80
+ 0x1db1: 0x000a, 0x1db2: 0x000a, 0x1db3: 0x000a, 0x1db4: 0x000a, 0x1db5: 0x000a,
+ 0x1db6: 0x000a, 0x1db7: 0x000a, 0x1db8: 0x000a, 0x1db9: 0x000a, 0x1dba: 0x000a, 0x1dbb: 0x000a,
+ 0x1dbc: 0x000a, 0x1dbd: 0x000a, 0x1dbe: 0x000a, 0x1dbf: 0x000a,
+ // Block 0x77, offset 0x1dc0
+ 0x1dcc: 0x000a, 0x1dcd: 0x000a, 0x1dce: 0x000a, 0x1dcf: 0x000a,
+ // Block 0x78, offset 0x1e00
+ 0x1e37: 0x000a, 0x1e38: 0x000a, 0x1e39: 0x000a, 0x1e3a: 0x000a,
+ // Block 0x79, offset 0x1e40
+ 0x1e5e: 0x000a, 0x1e5f: 0x000a,
+ 0x1e7f: 0x000a,
+ // Block 0x7a, offset 0x1e80
+ 0x1e90: 0x000a, 0x1e91: 0x000a,
+ 0x1e92: 0x000a, 0x1e93: 0x000a, 0x1e94: 0x000a, 0x1e95: 0x000a, 0x1e96: 0x000a, 0x1e97: 0x000a,
+ 0x1e98: 0x000a, 0x1e99: 0x000a, 0x1e9a: 0x000a, 0x1e9b: 0x000a, 0x1e9c: 0x000a, 0x1e9d: 0x000a,
+ 0x1e9e: 0x000a, 0x1e9f: 0x000a, 0x1ea0: 0x000a, 0x1ea1: 0x000a, 0x1ea2: 0x000a, 0x1ea3: 0x000a,
+ 0x1ea4: 0x000a, 0x1ea5: 0x000a, 0x1ea6: 0x000a, 0x1ea7: 0x000a, 0x1ea8: 0x000a, 0x1ea9: 0x000a,
+ 0x1eaa: 0x000a, 0x1eab: 0x000a, 0x1eac: 0x000a, 0x1ead: 0x000a, 0x1eae: 0x000a, 0x1eaf: 0x000a,
+ 0x1eb0: 0x000a, 0x1eb1: 0x000a, 0x1eb2: 0x000a, 0x1eb3: 0x000a, 0x1eb4: 0x000a, 0x1eb5: 0x000a,
+ 0x1eb6: 0x000a, 0x1eb7: 0x000a, 0x1eb8: 0x000a, 0x1eb9: 0x000a, 0x1eba: 0x000a, 0x1ebb: 0x000a,
+ 0x1ebc: 0x000a, 0x1ebd: 0x000a, 0x1ebe: 0x000a, 0x1ebf: 0x000a,
+ // Block 0x7b, offset 0x1ec0
+ 0x1ec0: 0x000a, 0x1ec1: 0x000a, 0x1ec2: 0x000a, 0x1ec3: 0x000a, 0x1ec4: 0x000a, 0x1ec5: 0x000a,
+ 0x1ec6: 0x000a,
+ // Block 0x7c, offset 0x1f00
+ 0x1f0d: 0x000a, 0x1f0e: 0x000a, 0x1f0f: 0x000a,
+ // Block 0x7d, offset 0x1f40
+ 0x1f6f: 0x000c,
+ 0x1f70: 0x000c, 0x1f71: 0x000c, 0x1f72: 0x000c, 0x1f73: 0x000a, 0x1f74: 0x000c, 0x1f75: 0x000c,
+ 0x1f76: 0x000c, 0x1f77: 0x000c, 0x1f78: 0x000c, 0x1f79: 0x000c, 0x1f7a: 0x000c, 0x1f7b: 0x000c,
+ 0x1f7c: 0x000c, 0x1f7d: 0x000c, 0x1f7e: 0x000a, 0x1f7f: 0x000a,
+ // Block 0x7e, offset 0x1f80
+ 0x1f9e: 0x000c, 0x1f9f: 0x000c,
+ // Block 0x7f, offset 0x1fc0
+ 0x1ff0: 0x000c, 0x1ff1: 0x000c,
+ // Block 0x80, offset 0x2000
+ 0x2000: 0x000a, 0x2001: 0x000a, 0x2002: 0x000a, 0x2003: 0x000a, 0x2004: 0x000a, 0x2005: 0x000a,
+ 0x2006: 0x000a, 0x2007: 0x000a, 0x2008: 0x000a, 0x2009: 0x000a, 0x200a: 0x000a, 0x200b: 0x000a,
+ 0x200c: 0x000a, 0x200d: 0x000a, 0x200e: 0x000a, 0x200f: 0x000a, 0x2010: 0x000a, 0x2011: 0x000a,
+ 0x2012: 0x000a, 0x2013: 0x000a, 0x2014: 0x000a, 0x2015: 0x000a, 0x2016: 0x000a, 0x2017: 0x000a,
+ 0x2018: 0x000a, 0x2019: 0x000a, 0x201a: 0x000a, 0x201b: 0x000a, 0x201c: 0x000a, 0x201d: 0x000a,
+ 0x201e: 0x000a, 0x201f: 0x000a, 0x2020: 0x000a, 0x2021: 0x000a,
+ // Block 0x81, offset 0x2040
+ 0x2048: 0x000a,
+ // Block 0x82, offset 0x2080
+ 0x2082: 0x000c,
+ 0x2086: 0x000c, 0x208b: 0x000c,
+ 0x20a5: 0x000c, 0x20a6: 0x000c, 0x20a8: 0x000a, 0x20a9: 0x000a,
+ 0x20aa: 0x000a, 0x20ab: 0x000a,
+ 0x20b8: 0x0004, 0x20b9: 0x0004,
+ // Block 0x83, offset 0x20c0
+ 0x20f4: 0x000a, 0x20f5: 0x000a,
+ 0x20f6: 0x000a, 0x20f7: 0x000a,
+ // Block 0x84, offset 0x2100
+ 0x2104: 0x000c, 0x2105: 0x000c,
+ 0x2120: 0x000c, 0x2121: 0x000c, 0x2122: 0x000c, 0x2123: 0x000c,
+ 0x2124: 0x000c, 0x2125: 0x000c, 0x2126: 0x000c, 0x2127: 0x000c, 0x2128: 0x000c, 0x2129: 0x000c,
+ 0x212a: 0x000c, 0x212b: 0x000c, 0x212c: 0x000c, 0x212d: 0x000c, 0x212e: 0x000c, 0x212f: 0x000c,
+ 0x2130: 0x000c, 0x2131: 0x000c,
+ // Block 0x85, offset 0x2140
+ 0x2166: 0x000c, 0x2167: 0x000c, 0x2168: 0x000c, 0x2169: 0x000c,
+ 0x216a: 0x000c, 0x216b: 0x000c, 0x216c: 0x000c, 0x216d: 0x000c,
+ // Block 0x86, offset 0x2180
+ 0x2187: 0x000c, 0x2188: 0x000c, 0x2189: 0x000c, 0x218a: 0x000c, 0x218b: 0x000c,
+ 0x218c: 0x000c, 0x218d: 0x000c, 0x218e: 0x000c, 0x218f: 0x000c, 0x2190: 0x000c, 0x2191: 0x000c,
+ // Block 0x87, offset 0x21c0
+ 0x21c0: 0x000c, 0x21c1: 0x000c, 0x21c2: 0x000c,
+ 0x21f3: 0x000c,
+ 0x21f6: 0x000c, 0x21f7: 0x000c, 0x21f8: 0x000c, 0x21f9: 0x000c,
+ 0x21fc: 0x000c,
+ // Block 0x88, offset 0x2200
+ 0x2225: 0x000c,
+ // Block 0x89, offset 0x2240
+ 0x2269: 0x000c,
+ 0x226a: 0x000c, 0x226b: 0x000c, 0x226c: 0x000c, 0x226d: 0x000c, 0x226e: 0x000c,
+ 0x2271: 0x000c, 0x2272: 0x000c, 0x2275: 0x000c,
+ 0x2276: 0x000c,
+ // Block 0x8a, offset 0x2280
+ 0x2283: 0x000c,
+ 0x228c: 0x000c,
+ 0x22bc: 0x000c,
+ // Block 0x8b, offset 0x22c0
+ 0x22f0: 0x000c, 0x22f2: 0x000c, 0x22f3: 0x000c, 0x22f4: 0x000c,
+ 0x22f7: 0x000c, 0x22f8: 0x000c,
+ 0x22fe: 0x000c, 0x22ff: 0x000c,
+ // Block 0x8c, offset 0x2300
+ 0x2301: 0x000c,
+ 0x232c: 0x000c, 0x232d: 0x000c,
+ 0x2336: 0x000c,
+ // Block 0x8d, offset 0x2340
+ 0x2365: 0x000c, 0x2368: 0x000c,
+ 0x236d: 0x000c,
+ // Block 0x8e, offset 0x2380
+ 0x239d: 0x0001,
+ 0x239e: 0x000c, 0x239f: 0x0001, 0x23a0: 0x0001, 0x23a1: 0x0001, 0x23a2: 0x0001, 0x23a3: 0x0001,
+ 0x23a4: 0x0001, 0x23a5: 0x0001, 0x23a6: 0x0001, 0x23a7: 0x0001, 0x23a8: 0x0001, 0x23a9: 0x0003,
+ 0x23aa: 0x0001, 0x23ab: 0x0001, 0x23ac: 0x0001, 0x23ad: 0x0001, 0x23ae: 0x0001, 0x23af: 0x0001,
+ 0x23b0: 0x0001, 0x23b1: 0x0001, 0x23b2: 0x0001, 0x23b3: 0x0001, 0x23b4: 0x0001, 0x23b5: 0x0001,
+ 0x23b6: 0x0001, 0x23b7: 0x0001, 0x23b8: 0x0001, 0x23b9: 0x0001, 0x23ba: 0x0001, 0x23bb: 0x0001,
+ 0x23bc: 0x0001, 0x23bd: 0x0001, 0x23be: 0x0001, 0x23bf: 0x0001,
+ // Block 0x8f, offset 0x23c0
+ 0x23c0: 0x0001, 0x23c1: 0x0001, 0x23c2: 0x0001, 0x23c3: 0x0001, 0x23c4: 0x0001, 0x23c5: 0x0001,
+ 0x23c6: 0x0001, 0x23c7: 0x0001, 0x23c8: 0x0001, 0x23c9: 0x0001, 0x23ca: 0x0001, 0x23cb: 0x0001,
+ 0x23cc: 0x0001, 0x23cd: 0x0001, 0x23ce: 0x0001, 0x23cf: 0x0001, 0x23d0: 0x000d, 0x23d1: 0x000d,
+ 0x23d2: 0x000d, 0x23d3: 0x000d, 0x23d4: 0x000d, 0x23d5: 0x000d, 0x23d6: 0x000d, 0x23d7: 0x000d,
+ 0x23d8: 0x000d, 0x23d9: 0x000d, 0x23da: 0x000d, 0x23db: 0x000d, 0x23dc: 0x000d, 0x23dd: 0x000d,
+ 0x23de: 0x000d, 0x23df: 0x000d, 0x23e0: 0x000d, 0x23e1: 0x000d, 0x23e2: 0x000d, 0x23e3: 0x000d,
+ 0x23e4: 0x000d, 0x23e5: 0x000d, 0x23e6: 0x000d, 0x23e7: 0x000d, 0x23e8: 0x000d, 0x23e9: 0x000d,
+ 0x23ea: 0x000d, 0x23eb: 0x000d, 0x23ec: 0x000d, 0x23ed: 0x000d, 0x23ee: 0x000d, 0x23ef: 0x000d,
+ 0x23f0: 0x000d, 0x23f1: 0x000d, 0x23f2: 0x000d, 0x23f3: 0x000d, 0x23f4: 0x000d, 0x23f5: 0x000d,
+ 0x23f6: 0x000d, 0x23f7: 0x000d, 0x23f8: 0x000d, 0x23f9: 0x000d, 0x23fa: 0x000d, 0x23fb: 0x000d,
+ 0x23fc: 0x000d, 0x23fd: 0x000d, 0x23fe: 0x000d, 0x23ff: 0x000d,
+ // Block 0x90, offset 0x2400
+ 0x2400: 0x000d, 0x2401: 0x000d, 0x2402: 0x000d, 0x2403: 0x000d, 0x2404: 0x000d, 0x2405: 0x000d,
+ 0x2406: 0x000d, 0x2407: 0x000d, 0x2408: 0x000d, 0x2409: 0x000d, 0x240a: 0x000d, 0x240b: 0x000d,
+ 0x240c: 0x000d, 0x240d: 0x000d, 0x240e: 0x000d, 0x240f: 0x000d, 0x2410: 0x000d, 0x2411: 0x000d,
+ 0x2412: 0x000d, 0x2413: 0x000d, 0x2414: 0x000d, 0x2415: 0x000d, 0x2416: 0x000d, 0x2417: 0x000d,
+ 0x2418: 0x000d, 0x2419: 0x000d, 0x241a: 0x000d, 0x241b: 0x000d, 0x241c: 0x000d, 0x241d: 0x000d,
+ 0x241e: 0x000d, 0x241f: 0x000d, 0x2420: 0x000d, 0x2421: 0x000d, 0x2422: 0x000d, 0x2423: 0x000d,
+ 0x2424: 0x000d, 0x2425: 0x000d, 0x2426: 0x000d, 0x2427: 0x000d, 0x2428: 0x000d, 0x2429: 0x000d,
+ 0x242a: 0x000d, 0x242b: 0x000d, 0x242c: 0x000d, 0x242d: 0x000d, 0x242e: 0x000d, 0x242f: 0x000d,
+ 0x2430: 0x000d, 0x2431: 0x000d, 0x2432: 0x000d, 0x2433: 0x000d, 0x2434: 0x000d, 0x2435: 0x000d,
+ 0x2436: 0x000d, 0x2437: 0x000d, 0x2438: 0x000d, 0x2439: 0x000d, 0x243a: 0x000d, 0x243b: 0x000d,
+ 0x243c: 0x000d, 0x243d: 0x000d, 0x243e: 0x000a, 0x243f: 0x000a,
+ // Block 0x91, offset 0x2440
+ 0x2440: 0x000d, 0x2441: 0x000d, 0x2442: 0x000d, 0x2443: 0x000d, 0x2444: 0x000d, 0x2445: 0x000d,
+ 0x2446: 0x000d, 0x2447: 0x000d, 0x2448: 0x000d, 0x2449: 0x000d, 0x244a: 0x000d, 0x244b: 0x000d,
+ 0x244c: 0x000d, 0x244d: 0x000d, 0x244e: 0x000d, 0x244f: 0x000d, 0x2450: 0x000b, 0x2451: 0x000b,
+ 0x2452: 0x000b, 0x2453: 0x000b, 0x2454: 0x000b, 0x2455: 0x000b, 0x2456: 0x000b, 0x2457: 0x000b,
+ 0x2458: 0x000b, 0x2459: 0x000b, 0x245a: 0x000b, 0x245b: 0x000b, 0x245c: 0x000b, 0x245d: 0x000b,
+ 0x245e: 0x000b, 0x245f: 0x000b, 0x2460: 0x000b, 0x2461: 0x000b, 0x2462: 0x000b, 0x2463: 0x000b,
+ 0x2464: 0x000b, 0x2465: 0x000b, 0x2466: 0x000b, 0x2467: 0x000b, 0x2468: 0x000b, 0x2469: 0x000b,
+ 0x246a: 0x000b, 0x246b: 0x000b, 0x246c: 0x000b, 0x246d: 0x000b, 0x246e: 0x000b, 0x246f: 0x000b,
+ 0x2470: 0x000d, 0x2471: 0x000d, 0x2472: 0x000d, 0x2473: 0x000d, 0x2474: 0x000d, 0x2475: 0x000d,
+ 0x2476: 0x000d, 0x2477: 0x000d, 0x2478: 0x000d, 0x2479: 0x000d, 0x247a: 0x000d, 0x247b: 0x000d,
+ 0x247c: 0x000d, 0x247d: 0x000a, 0x247e: 0x000d, 0x247f: 0x000d,
+ // Block 0x92, offset 0x2480
+ 0x2480: 0x000c, 0x2481: 0x000c, 0x2482: 0x000c, 0x2483: 0x000c, 0x2484: 0x000c, 0x2485: 0x000c,
+ 0x2486: 0x000c, 0x2487: 0x000c, 0x2488: 0x000c, 0x2489: 0x000c, 0x248a: 0x000c, 0x248b: 0x000c,
+ 0x248c: 0x000c, 0x248d: 0x000c, 0x248e: 0x000c, 0x248f: 0x000c, 0x2490: 0x000a, 0x2491: 0x000a,
+ 0x2492: 0x000a, 0x2493: 0x000a, 0x2494: 0x000a, 0x2495: 0x000a, 0x2496: 0x000a, 0x2497: 0x000a,
+ 0x2498: 0x000a, 0x2499: 0x000a,
+ 0x24a0: 0x000c, 0x24a1: 0x000c, 0x24a2: 0x000c, 0x24a3: 0x000c,
+ 0x24a4: 0x000c, 0x24a5: 0x000c, 0x24a6: 0x000c, 0x24a7: 0x000c, 0x24a8: 0x000c, 0x24a9: 0x000c,
+ 0x24aa: 0x000c, 0x24ab: 0x000c, 0x24ac: 0x000c, 0x24ad: 0x000c, 0x24ae: 0x000c, 0x24af: 0x000c,
+ 0x24b0: 0x000a, 0x24b1: 0x000a, 0x24b2: 0x000a, 0x24b3: 0x000a, 0x24b4: 0x000a, 0x24b5: 0x000a,
+ 0x24b6: 0x000a, 0x24b7: 0x000a, 0x24b8: 0x000a, 0x24b9: 0x000a, 0x24ba: 0x000a, 0x24bb: 0x000a,
+ 0x24bc: 0x000a, 0x24bd: 0x000a, 0x24be: 0x000a, 0x24bf: 0x000a,
+ // Block 0x93, offset 0x24c0
+ 0x24c0: 0x000a, 0x24c1: 0x000a, 0x24c2: 0x000a, 0x24c3: 0x000a, 0x24c4: 0x000a, 0x24c5: 0x000a,
+ 0x24c6: 0x000a, 0x24c7: 0x000a, 0x24c8: 0x000a, 0x24c9: 0x000a, 0x24ca: 0x000a, 0x24cb: 0x000a,
+ 0x24cc: 0x000a, 0x24cd: 0x000a, 0x24ce: 0x000a, 0x24cf: 0x000a, 0x24d0: 0x0006, 0x24d1: 0x000a,
+ 0x24d2: 0x0006, 0x24d4: 0x000a, 0x24d5: 0x0006, 0x24d6: 0x000a, 0x24d7: 0x000a,
+ 0x24d8: 0x000a, 0x24d9: 0x009a, 0x24da: 0x008a, 0x24db: 0x007a, 0x24dc: 0x006a, 0x24dd: 0x009a,
+ 0x24de: 0x008a, 0x24df: 0x0004, 0x24e0: 0x000a, 0x24e1: 0x000a, 0x24e2: 0x0003, 0x24e3: 0x0003,
+ 0x24e4: 0x000a, 0x24e5: 0x000a, 0x24e6: 0x000a, 0x24e8: 0x000a, 0x24e9: 0x0004,
+ 0x24ea: 0x0004, 0x24eb: 0x000a,
+ 0x24f0: 0x000d, 0x24f1: 0x000d, 0x24f2: 0x000d, 0x24f3: 0x000d, 0x24f4: 0x000d, 0x24f5: 0x000d,
+ 0x24f6: 0x000d, 0x24f7: 0x000d, 0x24f8: 0x000d, 0x24f9: 0x000d, 0x24fa: 0x000d, 0x24fb: 0x000d,
+ 0x24fc: 0x000d, 0x24fd: 0x000d, 0x24fe: 0x000d, 0x24ff: 0x000d,
+ // Block 0x94, offset 0x2500
+ 0x2500: 0x000d, 0x2501: 0x000d, 0x2502: 0x000d, 0x2503: 0x000d, 0x2504: 0x000d, 0x2505: 0x000d,
+ 0x2506: 0x000d, 0x2507: 0x000d, 0x2508: 0x000d, 0x2509: 0x000d, 0x250a: 0x000d, 0x250b: 0x000d,
+ 0x250c: 0x000d, 0x250d: 0x000d, 0x250e: 0x000d, 0x250f: 0x000d, 0x2510: 0x000d, 0x2511: 0x000d,
+ 0x2512: 0x000d, 0x2513: 0x000d, 0x2514: 0x000d, 0x2515: 0x000d, 0x2516: 0x000d, 0x2517: 0x000d,
+ 0x2518: 0x000d, 0x2519: 0x000d, 0x251a: 0x000d, 0x251b: 0x000d, 0x251c: 0x000d, 0x251d: 0x000d,
+ 0x251e: 0x000d, 0x251f: 0x000d, 0x2520: 0x000d, 0x2521: 0x000d, 0x2522: 0x000d, 0x2523: 0x000d,
+ 0x2524: 0x000d, 0x2525: 0x000d, 0x2526: 0x000d, 0x2527: 0x000d, 0x2528: 0x000d, 0x2529: 0x000d,
+ 0x252a: 0x000d, 0x252b: 0x000d, 0x252c: 0x000d, 0x252d: 0x000d, 0x252e: 0x000d, 0x252f: 0x000d,
+ 0x2530: 0x000d, 0x2531: 0x000d, 0x2532: 0x000d, 0x2533: 0x000d, 0x2534: 0x000d, 0x2535: 0x000d,
+ 0x2536: 0x000d, 0x2537: 0x000d, 0x2538: 0x000d, 0x2539: 0x000d, 0x253a: 0x000d, 0x253b: 0x000d,
+ 0x253c: 0x000d, 0x253d: 0x000d, 0x253e: 0x000d, 0x253f: 0x000b,
+ // Block 0x95, offset 0x2540
+ 0x2541: 0x000a, 0x2542: 0x000a, 0x2543: 0x0004, 0x2544: 0x0004, 0x2545: 0x0004,
+ 0x2546: 0x000a, 0x2547: 0x000a, 0x2548: 0x003a, 0x2549: 0x002a, 0x254a: 0x000a, 0x254b: 0x0003,
+ 0x254c: 0x0006, 0x254d: 0x0003, 0x254e: 0x0006, 0x254f: 0x0006, 0x2550: 0x0002, 0x2551: 0x0002,
+ 0x2552: 0x0002, 0x2553: 0x0002, 0x2554: 0x0002, 0x2555: 0x0002, 0x2556: 0x0002, 0x2557: 0x0002,
+ 0x2558: 0x0002, 0x2559: 0x0002, 0x255a: 0x0006, 0x255b: 0x000a, 0x255c: 0x000a, 0x255d: 0x000a,
+ 0x255e: 0x000a, 0x255f: 0x000a, 0x2560: 0x000a,
+ 0x257b: 0x005a,
+ 0x257c: 0x000a, 0x257d: 0x004a, 0x257e: 0x000a, 0x257f: 0x000a,
+ // Block 0x96, offset 0x2580
+ 0x2580: 0x000a,
+ 0x259b: 0x005a, 0x259c: 0x000a, 0x259d: 0x004a,
+ 0x259e: 0x000a, 0x259f: 0x00fa, 0x25a0: 0x00ea, 0x25a1: 0x000a, 0x25a2: 0x003a, 0x25a3: 0x002a,
+ 0x25a4: 0x000a, 0x25a5: 0x000a,
+ // Block 0x97, offset 0x25c0
+ 0x25e0: 0x0004, 0x25e1: 0x0004, 0x25e2: 0x000a, 0x25e3: 0x000a,
+ 0x25e4: 0x000a, 0x25e5: 0x0004, 0x25e6: 0x0004, 0x25e8: 0x000a, 0x25e9: 0x000a,
+ 0x25ea: 0x000a, 0x25eb: 0x000a, 0x25ec: 0x000a, 0x25ed: 0x000a, 0x25ee: 0x000a,
+ 0x25f0: 0x000b, 0x25f1: 0x000b, 0x25f2: 0x000b, 0x25f3: 0x000b, 0x25f4: 0x000b, 0x25f5: 0x000b,
+ 0x25f6: 0x000b, 0x25f7: 0x000b, 0x25f8: 0x000b, 0x25f9: 0x000a, 0x25fa: 0x000a, 0x25fb: 0x000a,
+ 0x25fc: 0x000a, 0x25fd: 0x000a, 0x25fe: 0x000b, 0x25ff: 0x000b,
+ // Block 0x98, offset 0x2600
+ 0x2601: 0x000a,
+ // Block 0x99, offset 0x2640
+ 0x2640: 0x000a, 0x2641: 0x000a, 0x2642: 0x000a, 0x2643: 0x000a, 0x2644: 0x000a, 0x2645: 0x000a,
+ 0x2646: 0x000a, 0x2647: 0x000a, 0x2648: 0x000a, 0x2649: 0x000a, 0x264a: 0x000a, 0x264b: 0x000a,
+ 0x264c: 0x000a, 0x2650: 0x000a, 0x2651: 0x000a,
+ 0x2652: 0x000a, 0x2653: 0x000a, 0x2654: 0x000a, 0x2655: 0x000a, 0x2656: 0x000a, 0x2657: 0x000a,
+ 0x2658: 0x000a, 0x2659: 0x000a, 0x265a: 0x000a, 0x265b: 0x000a,
+ 0x2660: 0x000a,
+ // Block 0x9a, offset 0x2680
+ 0x26bd: 0x000c,
+ // Block 0x9b, offset 0x26c0
+ 0x26e0: 0x000c, 0x26e1: 0x0002, 0x26e2: 0x0002, 0x26e3: 0x0002,
+ 0x26e4: 0x0002, 0x26e5: 0x0002, 0x26e6: 0x0002, 0x26e7: 0x0002, 0x26e8: 0x0002, 0x26e9: 0x0002,
+ 0x26ea: 0x0002, 0x26eb: 0x0002, 0x26ec: 0x0002, 0x26ed: 0x0002, 0x26ee: 0x0002, 0x26ef: 0x0002,
+ 0x26f0: 0x0002, 0x26f1: 0x0002, 0x26f2: 0x0002, 0x26f3: 0x0002, 0x26f4: 0x0002, 0x26f5: 0x0002,
+ 0x26f6: 0x0002, 0x26f7: 0x0002, 0x26f8: 0x0002, 0x26f9: 0x0002, 0x26fa: 0x0002, 0x26fb: 0x0002,
+ // Block 0x9c, offset 0x2700
+ 0x2736: 0x000c, 0x2737: 0x000c, 0x2738: 0x000c, 0x2739: 0x000c, 0x273a: 0x000c,
+ // Block 0x9d, offset 0x2740
+ 0x2740: 0x0001, 0x2741: 0x0001, 0x2742: 0x0001, 0x2743: 0x0001, 0x2744: 0x0001, 0x2745: 0x0001,
+ 0x2746: 0x0001, 0x2747: 0x0001, 0x2748: 0x0001, 0x2749: 0x0001, 0x274a: 0x0001, 0x274b: 0x0001,
+ 0x274c: 0x0001, 0x274d: 0x0001, 0x274e: 0x0001, 0x274f: 0x0001, 0x2750: 0x0001, 0x2751: 0x0001,
+ 0x2752: 0x0001, 0x2753: 0x0001, 0x2754: 0x0001, 0x2755: 0x0001, 0x2756: 0x0001, 0x2757: 0x0001,
+ 0x2758: 0x0001, 0x2759: 0x0001, 0x275a: 0x0001, 0x275b: 0x0001, 0x275c: 0x0001, 0x275d: 0x0001,
+ 0x275e: 0x0001, 0x275f: 0x0001, 0x2760: 0x0001, 0x2761: 0x0001, 0x2762: 0x0001, 0x2763: 0x0001,
+ 0x2764: 0x0001, 0x2765: 0x0001, 0x2766: 0x0001, 0x2767: 0x0001, 0x2768: 0x0001, 0x2769: 0x0001,
+ 0x276a: 0x0001, 0x276b: 0x0001, 0x276c: 0x0001, 0x276d: 0x0001, 0x276e: 0x0001, 0x276f: 0x0001,
+ 0x2770: 0x0001, 0x2771: 0x0001, 0x2772: 0x0001, 0x2773: 0x0001, 0x2774: 0x0001, 0x2775: 0x0001,
+ 0x2776: 0x0001, 0x2777: 0x0001, 0x2778: 0x0001, 0x2779: 0x0001, 0x277a: 0x0001, 0x277b: 0x0001,
+ 0x277c: 0x0001, 0x277d: 0x0001, 0x277e: 0x0001, 0x277f: 0x0001,
+ // Block 0x9e, offset 0x2780
+ 0x2780: 0x0001, 0x2781: 0x0001, 0x2782: 0x0001, 0x2783: 0x0001, 0x2784: 0x0001, 0x2785: 0x0001,
+ 0x2786: 0x0001, 0x2787: 0x0001, 0x2788: 0x0001, 0x2789: 0x0001, 0x278a: 0x0001, 0x278b: 0x0001,
+ 0x278c: 0x0001, 0x278d: 0x0001, 0x278e: 0x0001, 0x278f: 0x0001, 0x2790: 0x0001, 0x2791: 0x0001,
+ 0x2792: 0x0001, 0x2793: 0x0001, 0x2794: 0x0001, 0x2795: 0x0001, 0x2796: 0x0001, 0x2797: 0x0001,
+ 0x2798: 0x0001, 0x2799: 0x0001, 0x279a: 0x0001, 0x279b: 0x0001, 0x279c: 0x0001, 0x279d: 0x0001,
+ 0x279e: 0x0001, 0x279f: 0x000a, 0x27a0: 0x0001, 0x27a1: 0x0001, 0x27a2: 0x0001, 0x27a3: 0x0001,
+ 0x27a4: 0x0001, 0x27a5: 0x0001, 0x27a6: 0x0001, 0x27a7: 0x0001, 0x27a8: 0x0001, 0x27a9: 0x0001,
+ 0x27aa: 0x0001, 0x27ab: 0x0001, 0x27ac: 0x0001, 0x27ad: 0x0001, 0x27ae: 0x0001, 0x27af: 0x0001,
+ 0x27b0: 0x0001, 0x27b1: 0x0001, 0x27b2: 0x0001, 0x27b3: 0x0001, 0x27b4: 0x0001, 0x27b5: 0x0001,
+ 0x27b6: 0x0001, 0x27b7: 0x0001, 0x27b8: 0x0001, 0x27b9: 0x0001, 0x27ba: 0x0001, 0x27bb: 0x0001,
+ 0x27bc: 0x0001, 0x27bd: 0x0001, 0x27be: 0x0001, 0x27bf: 0x0001,
+ // Block 0x9f, offset 0x27c0
+ 0x27c0: 0x0001, 0x27c1: 0x000c, 0x27c2: 0x000c, 0x27c3: 0x000c, 0x27c4: 0x0001, 0x27c5: 0x000c,
+ 0x27c6: 0x000c, 0x27c7: 0x0001, 0x27c8: 0x0001, 0x27c9: 0x0001, 0x27ca: 0x0001, 0x27cb: 0x0001,
+ 0x27cc: 0x000c, 0x27cd: 0x000c, 0x27ce: 0x000c, 0x27cf: 0x000c, 0x27d0: 0x0001, 0x27d1: 0x0001,
+ 0x27d2: 0x0001, 0x27d3: 0x0001, 0x27d4: 0x0001, 0x27d5: 0x0001, 0x27d6: 0x0001, 0x27d7: 0x0001,
+ 0x27d8: 0x0001, 0x27d9: 0x0001, 0x27da: 0x0001, 0x27db: 0x0001, 0x27dc: 0x0001, 0x27dd: 0x0001,
+ 0x27de: 0x0001, 0x27df: 0x0001, 0x27e0: 0x0001, 0x27e1: 0x0001, 0x27e2: 0x0001, 0x27e3: 0x0001,
+ 0x27e4: 0x0001, 0x27e5: 0x0001, 0x27e6: 0x0001, 0x27e7: 0x0001, 0x27e8: 0x0001, 0x27e9: 0x0001,
+ 0x27ea: 0x0001, 0x27eb: 0x0001, 0x27ec: 0x0001, 0x27ed: 0x0001, 0x27ee: 0x0001, 0x27ef: 0x0001,
+ 0x27f0: 0x0001, 0x27f1: 0x0001, 0x27f2: 0x0001, 0x27f3: 0x0001, 0x27f4: 0x0001, 0x27f5: 0x0001,
+ 0x27f6: 0x0001, 0x27f7: 0x0001, 0x27f8: 0x000c, 0x27f9: 0x000c, 0x27fa: 0x000c, 0x27fb: 0x0001,
+ 0x27fc: 0x0001, 0x27fd: 0x0001, 0x27fe: 0x0001, 0x27ff: 0x000c,
+ // Block 0xa0, offset 0x2800
+ 0x2800: 0x0001, 0x2801: 0x0001, 0x2802: 0x0001, 0x2803: 0x0001, 0x2804: 0x0001, 0x2805: 0x0001,
+ 0x2806: 0x0001, 0x2807: 0x0001, 0x2808: 0x0001, 0x2809: 0x0001, 0x280a: 0x0001, 0x280b: 0x0001,
+ 0x280c: 0x0001, 0x280d: 0x0001, 0x280e: 0x0001, 0x280f: 0x0001, 0x2810: 0x0001, 0x2811: 0x0001,
+ 0x2812: 0x0001, 0x2813: 0x0001, 0x2814: 0x0001, 0x2815: 0x0001, 0x2816: 0x0001, 0x2817: 0x0001,
+ 0x2818: 0x0001, 0x2819: 0x0001, 0x281a: 0x0001, 0x281b: 0x0001, 0x281c: 0x0001, 0x281d: 0x0001,
+ 0x281e: 0x0001, 0x281f: 0x0001, 0x2820: 0x0001, 0x2821: 0x0001, 0x2822: 0x0001, 0x2823: 0x0001,
+ 0x2824: 0x0001, 0x2825: 0x000c, 0x2826: 0x000c, 0x2827: 0x0001, 0x2828: 0x0001, 0x2829: 0x0001,
+ 0x282a: 0x0001, 0x282b: 0x0001, 0x282c: 0x0001, 0x282d: 0x0001, 0x282e: 0x0001, 0x282f: 0x0001,
+ 0x2830: 0x0001, 0x2831: 0x0001, 0x2832: 0x0001, 0x2833: 0x0001, 0x2834: 0x0001, 0x2835: 0x0001,
+ 0x2836: 0x0001, 0x2837: 0x0001, 0x2838: 0x0001, 0x2839: 0x0001, 0x283a: 0x0001, 0x283b: 0x0001,
+ 0x283c: 0x0001, 0x283d: 0x0001, 0x283e: 0x0001, 0x283f: 0x0001,
+ // Block 0xa1, offset 0x2840
+ 0x2840: 0x0001, 0x2841: 0x0001, 0x2842: 0x0001, 0x2843: 0x0001, 0x2844: 0x0001, 0x2845: 0x0001,
+ 0x2846: 0x0001, 0x2847: 0x0001, 0x2848: 0x0001, 0x2849: 0x0001, 0x284a: 0x0001, 0x284b: 0x0001,
+ 0x284c: 0x0001, 0x284d: 0x0001, 0x284e: 0x0001, 0x284f: 0x0001, 0x2850: 0x0001, 0x2851: 0x0001,
+ 0x2852: 0x0001, 0x2853: 0x0001, 0x2854: 0x0001, 0x2855: 0x0001, 0x2856: 0x0001, 0x2857: 0x0001,
+ 0x2858: 0x0001, 0x2859: 0x0001, 0x285a: 0x0001, 0x285b: 0x0001, 0x285c: 0x0001, 0x285d: 0x0001,
+ 0x285e: 0x0001, 0x285f: 0x0001, 0x2860: 0x0001, 0x2861: 0x0001, 0x2862: 0x0001, 0x2863: 0x0001,
+ 0x2864: 0x0001, 0x2865: 0x0001, 0x2866: 0x0001, 0x2867: 0x0001, 0x2868: 0x0001, 0x2869: 0x0001,
+ 0x286a: 0x0001, 0x286b: 0x0001, 0x286c: 0x0001, 0x286d: 0x0001, 0x286e: 0x0001, 0x286f: 0x0001,
+ 0x2870: 0x0001, 0x2871: 0x0001, 0x2872: 0x0001, 0x2873: 0x0001, 0x2874: 0x0001, 0x2875: 0x0001,
+ 0x2876: 0x0001, 0x2877: 0x0001, 0x2878: 0x0001, 0x2879: 0x000a, 0x287a: 0x000a, 0x287b: 0x000a,
+ 0x287c: 0x000a, 0x287d: 0x000a, 0x287e: 0x000a, 0x287f: 0x000a,
+ // Block 0xa2, offset 0x2880
+ 0x2880: 0x0001, 0x2881: 0x0001, 0x2882: 0x0001, 0x2883: 0x0001, 0x2884: 0x0001, 0x2885: 0x0001,
+ 0x2886: 0x0001, 0x2887: 0x0001, 0x2888: 0x0001, 0x2889: 0x0001, 0x288a: 0x0001, 0x288b: 0x0001,
+ 0x288c: 0x0001, 0x288d: 0x0001, 0x288e: 0x0001, 0x288f: 0x0001, 0x2890: 0x0001, 0x2891: 0x0001,
+ 0x2892: 0x0001, 0x2893: 0x0001, 0x2894: 0x0001, 0x2895: 0x0001, 0x2896: 0x0001, 0x2897: 0x0001,
+ 0x2898: 0x0001, 0x2899: 0x0001, 0x289a: 0x0001, 0x289b: 0x0001, 0x289c: 0x0001, 0x289d: 0x0001,
+ 0x289e: 0x0001, 0x289f: 0x0001, 0x28a0: 0x0005, 0x28a1: 0x0005, 0x28a2: 0x0005, 0x28a3: 0x0005,
+ 0x28a4: 0x0005, 0x28a5: 0x0005, 0x28a6: 0x0005, 0x28a7: 0x0005, 0x28a8: 0x0005, 0x28a9: 0x0005,
+ 0x28aa: 0x0005, 0x28ab: 0x0005, 0x28ac: 0x0005, 0x28ad: 0x0005, 0x28ae: 0x0005, 0x28af: 0x0005,
+ 0x28b0: 0x0005, 0x28b1: 0x0005, 0x28b2: 0x0005, 0x28b3: 0x0005, 0x28b4: 0x0005, 0x28b5: 0x0005,
+ 0x28b6: 0x0005, 0x28b7: 0x0005, 0x28b8: 0x0005, 0x28b9: 0x0005, 0x28ba: 0x0005, 0x28bb: 0x0005,
+ 0x28bc: 0x0005, 0x28bd: 0x0005, 0x28be: 0x0005, 0x28bf: 0x0001,
+ // Block 0xa3, offset 0x28c0
+ 0x28c1: 0x000c,
+ 0x28f8: 0x000c, 0x28f9: 0x000c, 0x28fa: 0x000c, 0x28fb: 0x000c,
+ 0x28fc: 0x000c, 0x28fd: 0x000c, 0x28fe: 0x000c, 0x28ff: 0x000c,
+ // Block 0xa4, offset 0x2900
+ 0x2900: 0x000c, 0x2901: 0x000c, 0x2902: 0x000c, 0x2903: 0x000c, 0x2904: 0x000c, 0x2905: 0x000c,
+ 0x2906: 0x000c,
+ 0x2912: 0x000a, 0x2913: 0x000a, 0x2914: 0x000a, 0x2915: 0x000a, 0x2916: 0x000a, 0x2917: 0x000a,
+ 0x2918: 0x000a, 0x2919: 0x000a, 0x291a: 0x000a, 0x291b: 0x000a, 0x291c: 0x000a, 0x291d: 0x000a,
+ 0x291e: 0x000a, 0x291f: 0x000a, 0x2920: 0x000a, 0x2921: 0x000a, 0x2922: 0x000a, 0x2923: 0x000a,
+ 0x2924: 0x000a, 0x2925: 0x000a,
+ 0x293f: 0x000c,
+ // Block 0xa5, offset 0x2940
+ 0x2940: 0x000c, 0x2941: 0x000c,
+ 0x2973: 0x000c, 0x2974: 0x000c, 0x2975: 0x000c,
+ 0x2976: 0x000c, 0x2979: 0x000c, 0x297a: 0x000c,
+ // Block 0xa6, offset 0x2980
+ 0x2980: 0x000c, 0x2981: 0x000c, 0x2982: 0x000c,
+ 0x29a7: 0x000c, 0x29a8: 0x000c, 0x29a9: 0x000c,
+ 0x29aa: 0x000c, 0x29ab: 0x000c, 0x29ad: 0x000c, 0x29ae: 0x000c, 0x29af: 0x000c,
+ 0x29b0: 0x000c, 0x29b1: 0x000c, 0x29b2: 0x000c, 0x29b3: 0x000c, 0x29b4: 0x000c,
+ // Block 0xa7, offset 0x29c0
+ 0x29f3: 0x000c,
+ // Block 0xa8, offset 0x2a00
+ 0x2a00: 0x000c, 0x2a01: 0x000c,
+ 0x2a36: 0x000c, 0x2a37: 0x000c, 0x2a38: 0x000c, 0x2a39: 0x000c, 0x2a3a: 0x000c, 0x2a3b: 0x000c,
+ 0x2a3c: 0x000c, 0x2a3d: 0x000c, 0x2a3e: 0x000c,
+ // Block 0xa9, offset 0x2a40
+ 0x2a4a: 0x000c, 0x2a4b: 0x000c,
+ 0x2a4c: 0x000c,
+ // Block 0xaa, offset 0x2a80
+ 0x2aaf: 0x000c,
+ 0x2ab0: 0x000c, 0x2ab1: 0x000c, 0x2ab4: 0x000c,
+ 0x2ab6: 0x000c, 0x2ab7: 0x000c,
+ 0x2abe: 0x000c,
+ // Block 0xab, offset 0x2ac0
+ 0x2adf: 0x000c, 0x2ae3: 0x000c,
+ 0x2ae4: 0x000c, 0x2ae5: 0x000c, 0x2ae6: 0x000c, 0x2ae7: 0x000c, 0x2ae8: 0x000c, 0x2ae9: 0x000c,
+ 0x2aea: 0x000c,
+ // Block 0xac, offset 0x2b00
+ 0x2b00: 0x000c, 0x2b01: 0x000c,
+ 0x2b3c: 0x000c,
+ // Block 0xad, offset 0x2b40
+ 0x2b40: 0x000c,
+ 0x2b66: 0x000c, 0x2b67: 0x000c, 0x2b68: 0x000c, 0x2b69: 0x000c,
+ 0x2b6a: 0x000c, 0x2b6b: 0x000c, 0x2b6c: 0x000c,
+ 0x2b70: 0x000c, 0x2b71: 0x000c, 0x2b72: 0x000c, 0x2b73: 0x000c, 0x2b74: 0x000c,
+ // Block 0xae, offset 0x2b80
+ 0x2bb8: 0x000c, 0x2bb9: 0x000c, 0x2bba: 0x000c, 0x2bbb: 0x000c,
+ 0x2bbc: 0x000c, 0x2bbd: 0x000c, 0x2bbe: 0x000c, 0x2bbf: 0x000c,
+ // Block 0xaf, offset 0x2bc0
+ 0x2bc2: 0x000c, 0x2bc3: 0x000c, 0x2bc4: 0x000c,
+ 0x2bc6: 0x000c,
+ // Block 0xb0, offset 0x2c00
+ 0x2c33: 0x000c, 0x2c34: 0x000c, 0x2c35: 0x000c,
+ 0x2c36: 0x000c, 0x2c37: 0x000c, 0x2c38: 0x000c, 0x2c3a: 0x000c,
+ 0x2c3f: 0x000c,
+ // Block 0xb1, offset 0x2c40
+ 0x2c40: 0x000c, 0x2c42: 0x000c, 0x2c43: 0x000c,
+ // Block 0xb2, offset 0x2c80
+ 0x2cb2: 0x000c, 0x2cb3: 0x000c, 0x2cb4: 0x000c, 0x2cb5: 0x000c,
+ 0x2cbc: 0x000c, 0x2cbd: 0x000c, 0x2cbf: 0x000c,
+ // Block 0xb3, offset 0x2cc0
+ 0x2cc0: 0x000c,
+ 0x2cdc: 0x000c, 0x2cdd: 0x000c,
+ // Block 0xb4, offset 0x2d00
+ 0x2d33: 0x000c, 0x2d34: 0x000c, 0x2d35: 0x000c,
+ 0x2d36: 0x000c, 0x2d37: 0x000c, 0x2d38: 0x000c, 0x2d39: 0x000c, 0x2d3a: 0x000c,
+ 0x2d3d: 0x000c, 0x2d3f: 0x000c,
+ // Block 0xb5, offset 0x2d40
+ 0x2d40: 0x000c,
+ 0x2d60: 0x000a, 0x2d61: 0x000a, 0x2d62: 0x000a, 0x2d63: 0x000a,
+ 0x2d64: 0x000a, 0x2d65: 0x000a, 0x2d66: 0x000a, 0x2d67: 0x000a, 0x2d68: 0x000a, 0x2d69: 0x000a,
+ 0x2d6a: 0x000a, 0x2d6b: 0x000a, 0x2d6c: 0x000a,
+ // Block 0xb6, offset 0x2d80
+ 0x2dab: 0x000c, 0x2dad: 0x000c,
+ 0x2db0: 0x000c, 0x2db1: 0x000c, 0x2db2: 0x000c, 0x2db3: 0x000c, 0x2db4: 0x000c, 0x2db5: 0x000c,
+ 0x2db7: 0x000c,
+ // Block 0xb7, offset 0x2dc0
+ 0x2ddd: 0x000c,
+ 0x2dde: 0x000c, 0x2ddf: 0x000c, 0x2de2: 0x000c, 0x2de3: 0x000c,
+ 0x2de4: 0x000c, 0x2de5: 0x000c, 0x2de7: 0x000c, 0x2de8: 0x000c, 0x2de9: 0x000c,
+ 0x2dea: 0x000c, 0x2deb: 0x000c,
+ // Block 0xb8, offset 0x2e00
+ 0x2e30: 0x000c, 0x2e31: 0x000c, 0x2e32: 0x000c, 0x2e33: 0x000c, 0x2e34: 0x000c, 0x2e35: 0x000c,
+ 0x2e36: 0x000c, 0x2e38: 0x000c, 0x2e39: 0x000c, 0x2e3a: 0x000c, 0x2e3b: 0x000c,
+ 0x2e3c: 0x000c, 0x2e3d: 0x000c,
+ // Block 0xb9, offset 0x2e40
+ 0x2e52: 0x000c, 0x2e53: 0x000c, 0x2e54: 0x000c, 0x2e55: 0x000c, 0x2e56: 0x000c, 0x2e57: 0x000c,
+ 0x2e58: 0x000c, 0x2e59: 0x000c, 0x2e5a: 0x000c, 0x2e5b: 0x000c, 0x2e5c: 0x000c, 0x2e5d: 0x000c,
+ 0x2e5e: 0x000c, 0x2e5f: 0x000c, 0x2e60: 0x000c, 0x2e61: 0x000c, 0x2e62: 0x000c, 0x2e63: 0x000c,
+ 0x2e64: 0x000c, 0x2e65: 0x000c, 0x2e66: 0x000c, 0x2e67: 0x000c,
+ 0x2e6a: 0x000c, 0x2e6b: 0x000c, 0x2e6c: 0x000c, 0x2e6d: 0x000c, 0x2e6e: 0x000c, 0x2e6f: 0x000c,
+ 0x2e70: 0x000c, 0x2e72: 0x000c, 0x2e73: 0x000c, 0x2e75: 0x000c,
+ 0x2e76: 0x000c,
+ // Block 0xba, offset 0x2e80
+ 0x2eb0: 0x000c, 0x2eb1: 0x000c, 0x2eb2: 0x000c, 0x2eb3: 0x000c, 0x2eb4: 0x000c,
+ // Block 0xbb, offset 0x2ec0
+ 0x2ef0: 0x000c, 0x2ef1: 0x000c, 0x2ef2: 0x000c, 0x2ef3: 0x000c, 0x2ef4: 0x000c, 0x2ef5: 0x000c,
+ 0x2ef6: 0x000c,
+ // Block 0xbc, offset 0x2f00
+ 0x2f0f: 0x000c, 0x2f10: 0x000c, 0x2f11: 0x000c,
+ 0x2f12: 0x000c,
+ // Block 0xbd, offset 0x2f40
+ 0x2f5d: 0x000c,
+ 0x2f5e: 0x000c, 0x2f60: 0x000b, 0x2f61: 0x000b, 0x2f62: 0x000b, 0x2f63: 0x000b,
+ // Block 0xbe, offset 0x2f80
+ 0x2fa7: 0x000c, 0x2fa8: 0x000c, 0x2fa9: 0x000c,
+ 0x2fb3: 0x000b, 0x2fb4: 0x000b, 0x2fb5: 0x000b,
+ 0x2fb6: 0x000b, 0x2fb7: 0x000b, 0x2fb8: 0x000b, 0x2fb9: 0x000b, 0x2fba: 0x000b, 0x2fbb: 0x000c,
+ 0x2fbc: 0x000c, 0x2fbd: 0x000c, 0x2fbe: 0x000c, 0x2fbf: 0x000c,
+ // Block 0xbf, offset 0x2fc0
+ 0x2fc0: 0x000c, 0x2fc1: 0x000c, 0x2fc2: 0x000c, 0x2fc5: 0x000c,
+ 0x2fc6: 0x000c, 0x2fc7: 0x000c, 0x2fc8: 0x000c, 0x2fc9: 0x000c, 0x2fca: 0x000c, 0x2fcb: 0x000c,
+ 0x2fea: 0x000c, 0x2feb: 0x000c, 0x2fec: 0x000c, 0x2fed: 0x000c,
+ // Block 0xc0, offset 0x3000
+ 0x3000: 0x000a, 0x3001: 0x000a, 0x3002: 0x000c, 0x3003: 0x000c, 0x3004: 0x000c, 0x3005: 0x000a,
+ // Block 0xc1, offset 0x3040
+ 0x3040: 0x000a, 0x3041: 0x000a, 0x3042: 0x000a, 0x3043: 0x000a, 0x3044: 0x000a, 0x3045: 0x000a,
+ 0x3046: 0x000a, 0x3047: 0x000a, 0x3048: 0x000a, 0x3049: 0x000a, 0x304a: 0x000a, 0x304b: 0x000a,
+ 0x304c: 0x000a, 0x304d: 0x000a, 0x304e: 0x000a, 0x304f: 0x000a, 0x3050: 0x000a, 0x3051: 0x000a,
+ 0x3052: 0x000a, 0x3053: 0x000a, 0x3054: 0x000a, 0x3055: 0x000a, 0x3056: 0x000a,
+ // Block 0xc2, offset 0x3080
+ 0x309b: 0x000a,
+ // Block 0xc3, offset 0x30c0
+ 0x30d5: 0x000a,
+ // Block 0xc4, offset 0x3100
+ 0x310f: 0x000a,
+ // Block 0xc5, offset 0x3140
+ 0x3149: 0x000a,
+ // Block 0xc6, offset 0x3180
+ 0x3183: 0x000a,
+ 0x318e: 0x0002, 0x318f: 0x0002, 0x3190: 0x0002, 0x3191: 0x0002,
+ 0x3192: 0x0002, 0x3193: 0x0002, 0x3194: 0x0002, 0x3195: 0x0002, 0x3196: 0x0002, 0x3197: 0x0002,
+ 0x3198: 0x0002, 0x3199: 0x0002, 0x319a: 0x0002, 0x319b: 0x0002, 0x319c: 0x0002, 0x319d: 0x0002,
+ 0x319e: 0x0002, 0x319f: 0x0002, 0x31a0: 0x0002, 0x31a1: 0x0002, 0x31a2: 0x0002, 0x31a3: 0x0002,
+ 0x31a4: 0x0002, 0x31a5: 0x0002, 0x31a6: 0x0002, 0x31a7: 0x0002, 0x31a8: 0x0002, 0x31a9: 0x0002,
+ 0x31aa: 0x0002, 0x31ab: 0x0002, 0x31ac: 0x0002, 0x31ad: 0x0002, 0x31ae: 0x0002, 0x31af: 0x0002,
+ 0x31b0: 0x0002, 0x31b1: 0x0002, 0x31b2: 0x0002, 0x31b3: 0x0002, 0x31b4: 0x0002, 0x31b5: 0x0002,
+ 0x31b6: 0x0002, 0x31b7: 0x0002, 0x31b8: 0x0002, 0x31b9: 0x0002, 0x31ba: 0x0002, 0x31bb: 0x0002,
+ 0x31bc: 0x0002, 0x31bd: 0x0002, 0x31be: 0x0002, 0x31bf: 0x0002,
+ // Block 0xc7, offset 0x31c0
+ 0x31c0: 0x000c, 0x31c1: 0x000c, 0x31c2: 0x000c, 0x31c3: 0x000c, 0x31c4: 0x000c, 0x31c5: 0x000c,
+ 0x31c6: 0x000c, 0x31c7: 0x000c, 0x31c8: 0x000c, 0x31c9: 0x000c, 0x31ca: 0x000c, 0x31cb: 0x000c,
+ 0x31cc: 0x000c, 0x31cd: 0x000c, 0x31ce: 0x000c, 0x31cf: 0x000c, 0x31d0: 0x000c, 0x31d1: 0x000c,
+ 0x31d2: 0x000c, 0x31d3: 0x000c, 0x31d4: 0x000c, 0x31d5: 0x000c, 0x31d6: 0x000c, 0x31d7: 0x000c,
+ 0x31d8: 0x000c, 0x31d9: 0x000c, 0x31da: 0x000c, 0x31db: 0x000c, 0x31dc: 0x000c, 0x31dd: 0x000c,
+ 0x31de: 0x000c, 0x31df: 0x000c, 0x31e0: 0x000c, 0x31e1: 0x000c, 0x31e2: 0x000c, 0x31e3: 0x000c,
+ 0x31e4: 0x000c, 0x31e5: 0x000c, 0x31e6: 0x000c, 0x31e7: 0x000c, 0x31e8: 0x000c, 0x31e9: 0x000c,
+ 0x31ea: 0x000c, 0x31eb: 0x000c, 0x31ec: 0x000c, 0x31ed: 0x000c, 0x31ee: 0x000c, 0x31ef: 0x000c,
+ 0x31f0: 0x000c, 0x31f1: 0x000c, 0x31f2: 0x000c, 0x31f3: 0x000c, 0x31f4: 0x000c, 0x31f5: 0x000c,
+ 0x31f6: 0x000c, 0x31fb: 0x000c,
+ 0x31fc: 0x000c, 0x31fd: 0x000c, 0x31fe: 0x000c, 0x31ff: 0x000c,
+ // Block 0xc8, offset 0x3200
+ 0x3200: 0x000c, 0x3201: 0x000c, 0x3202: 0x000c, 0x3203: 0x000c, 0x3204: 0x000c, 0x3205: 0x000c,
+ 0x3206: 0x000c, 0x3207: 0x000c, 0x3208: 0x000c, 0x3209: 0x000c, 0x320a: 0x000c, 0x320b: 0x000c,
+ 0x320c: 0x000c, 0x320d: 0x000c, 0x320e: 0x000c, 0x320f: 0x000c, 0x3210: 0x000c, 0x3211: 0x000c,
+ 0x3212: 0x000c, 0x3213: 0x000c, 0x3214: 0x000c, 0x3215: 0x000c, 0x3216: 0x000c, 0x3217: 0x000c,
+ 0x3218: 0x000c, 0x3219: 0x000c, 0x321a: 0x000c, 0x321b: 0x000c, 0x321c: 0x000c, 0x321d: 0x000c,
+ 0x321e: 0x000c, 0x321f: 0x000c, 0x3220: 0x000c, 0x3221: 0x000c, 0x3222: 0x000c, 0x3223: 0x000c,
+ 0x3224: 0x000c, 0x3225: 0x000c, 0x3226: 0x000c, 0x3227: 0x000c, 0x3228: 0x000c, 0x3229: 0x000c,
+ 0x322a: 0x000c, 0x322b: 0x000c, 0x322c: 0x000c,
+ 0x3235: 0x000c,
+ // Block 0xc9, offset 0x3240
+ 0x3244: 0x000c,
+ 0x325b: 0x000c, 0x325c: 0x000c, 0x325d: 0x000c,
+ 0x325e: 0x000c, 0x325f: 0x000c, 0x3261: 0x000c, 0x3262: 0x000c, 0x3263: 0x000c,
+ 0x3264: 0x000c, 0x3265: 0x000c, 0x3266: 0x000c, 0x3267: 0x000c, 0x3268: 0x000c, 0x3269: 0x000c,
+ 0x326a: 0x000c, 0x326b: 0x000c, 0x326c: 0x000c, 0x326d: 0x000c, 0x326e: 0x000c, 0x326f: 0x000c,
+ // Block 0xca, offset 0x3280
+ 0x3280: 0x000c, 0x3281: 0x000c, 0x3282: 0x000c, 0x3283: 0x000c, 0x3284: 0x000c, 0x3285: 0x000c,
+ 0x3286: 0x000c, 0x3288: 0x000c, 0x3289: 0x000c, 0x328a: 0x000c, 0x328b: 0x000c,
+ 0x328c: 0x000c, 0x328d: 0x000c, 0x328e: 0x000c, 0x328f: 0x000c, 0x3290: 0x000c, 0x3291: 0x000c,
+ 0x3292: 0x000c, 0x3293: 0x000c, 0x3294: 0x000c, 0x3295: 0x000c, 0x3296: 0x000c, 0x3297: 0x000c,
+ 0x3298: 0x000c, 0x329b: 0x000c, 0x329c: 0x000c, 0x329d: 0x000c,
+ 0x329e: 0x000c, 0x329f: 0x000c, 0x32a0: 0x000c, 0x32a1: 0x000c, 0x32a3: 0x000c,
+ 0x32a4: 0x000c, 0x32a6: 0x000c, 0x32a7: 0x000c, 0x32a8: 0x000c, 0x32a9: 0x000c,
+ 0x32aa: 0x000c,
+ // Block 0xcb, offset 0x32c0
+ 0x32c0: 0x0001, 0x32c1: 0x0001, 0x32c2: 0x0001, 0x32c3: 0x0001, 0x32c4: 0x0001, 0x32c5: 0x0001,
+ 0x32c6: 0x0001, 0x32c7: 0x0001, 0x32c8: 0x0001, 0x32c9: 0x0001, 0x32ca: 0x0001, 0x32cb: 0x0001,
+ 0x32cc: 0x0001, 0x32cd: 0x0001, 0x32ce: 0x0001, 0x32cf: 0x0001, 0x32d0: 0x000c, 0x32d1: 0x000c,
+ 0x32d2: 0x000c, 0x32d3: 0x000c, 0x32d4: 0x000c, 0x32d5: 0x000c, 0x32d6: 0x000c, 0x32d7: 0x0001,
+ 0x32d8: 0x0001, 0x32d9: 0x0001, 0x32da: 0x0001, 0x32db: 0x0001, 0x32dc: 0x0001, 0x32dd: 0x0001,
+ 0x32de: 0x0001, 0x32df: 0x0001, 0x32e0: 0x0001, 0x32e1: 0x0001, 0x32e2: 0x0001, 0x32e3: 0x0001,
+ 0x32e4: 0x0001, 0x32e5: 0x0001, 0x32e6: 0x0001, 0x32e7: 0x0001, 0x32e8: 0x0001, 0x32e9: 0x0001,
+ 0x32ea: 0x0001, 0x32eb: 0x0001, 0x32ec: 0x0001, 0x32ed: 0x0001, 0x32ee: 0x0001, 0x32ef: 0x0001,
+ 0x32f0: 0x0001, 0x32f1: 0x0001, 0x32f2: 0x0001, 0x32f3: 0x0001, 0x32f4: 0x0001, 0x32f5: 0x0001,
+ 0x32f6: 0x0001, 0x32f7: 0x0001, 0x32f8: 0x0001, 0x32f9: 0x0001, 0x32fa: 0x0001, 0x32fb: 0x0001,
+ 0x32fc: 0x0001, 0x32fd: 0x0001, 0x32fe: 0x0001, 0x32ff: 0x0001,
+ // Block 0xcc, offset 0x3300
+ 0x3300: 0x0001, 0x3301: 0x0001, 0x3302: 0x0001, 0x3303: 0x0001, 0x3304: 0x000c, 0x3305: 0x000c,
+ 0x3306: 0x000c, 0x3307: 0x000c, 0x3308: 0x000c, 0x3309: 0x000c, 0x330a: 0x000c, 0x330b: 0x0001,
+ 0x330c: 0x0001, 0x330d: 0x0001, 0x330e: 0x0001, 0x330f: 0x0001, 0x3310: 0x0001, 0x3311: 0x0001,
+ 0x3312: 0x0001, 0x3313: 0x0001, 0x3314: 0x0001, 0x3315: 0x0001, 0x3316: 0x0001, 0x3317: 0x0001,
+ 0x3318: 0x0001, 0x3319: 0x0001, 0x331a: 0x0001, 0x331b: 0x0001, 0x331c: 0x0001, 0x331d: 0x0001,
+ 0x331e: 0x0001, 0x331f: 0x0001, 0x3320: 0x0001, 0x3321: 0x0001, 0x3322: 0x0001, 0x3323: 0x0001,
+ 0x3324: 0x0001, 0x3325: 0x0001, 0x3326: 0x0001, 0x3327: 0x0001, 0x3328: 0x0001, 0x3329: 0x0001,
+ 0x332a: 0x0001, 0x332b: 0x0001, 0x332c: 0x0001, 0x332d: 0x0001, 0x332e: 0x0001, 0x332f: 0x0001,
+ 0x3330: 0x0001, 0x3331: 0x0001, 0x3332: 0x0001, 0x3333: 0x0001, 0x3334: 0x0001, 0x3335: 0x0001,
+ 0x3336: 0x0001, 0x3337: 0x0001, 0x3338: 0x0001, 0x3339: 0x0001, 0x333a: 0x0001, 0x333b: 0x0001,
+ 0x333c: 0x0001, 0x333d: 0x0001, 0x333e: 0x0001, 0x333f: 0x0001,
+ // Block 0xcd, offset 0x3340
+ 0x3340: 0x000d, 0x3341: 0x000d, 0x3342: 0x000d, 0x3343: 0x000d, 0x3344: 0x000d, 0x3345: 0x000d,
+ 0x3346: 0x000d, 0x3347: 0x000d, 0x3348: 0x000d, 0x3349: 0x000d, 0x334a: 0x000d, 0x334b: 0x000d,
+ 0x334c: 0x000d, 0x334d: 0x000d, 0x334e: 0x000d, 0x334f: 0x000d, 0x3350: 0x000d, 0x3351: 0x000d,
+ 0x3352: 0x000d, 0x3353: 0x000d, 0x3354: 0x000d, 0x3355: 0x000d, 0x3356: 0x000d, 0x3357: 0x000d,
+ 0x3358: 0x000d, 0x3359: 0x000d, 0x335a: 0x000d, 0x335b: 0x000d, 0x335c: 0x000d, 0x335d: 0x000d,
+ 0x335e: 0x000d, 0x335f: 0x000d, 0x3360: 0x000d, 0x3361: 0x000d, 0x3362: 0x000d, 0x3363: 0x000d,
+ 0x3364: 0x000d, 0x3365: 0x000d, 0x3366: 0x000d, 0x3367: 0x000d, 0x3368: 0x000d, 0x3369: 0x000d,
+ 0x336a: 0x000d, 0x336b: 0x000d, 0x336c: 0x000d, 0x336d: 0x000d, 0x336e: 0x000d, 0x336f: 0x000d,
+ 0x3370: 0x000a, 0x3371: 0x000a, 0x3372: 0x000d, 0x3373: 0x000d, 0x3374: 0x000d, 0x3375: 0x000d,
+ 0x3376: 0x000d, 0x3377: 0x000d, 0x3378: 0x000d, 0x3379: 0x000d, 0x337a: 0x000d, 0x337b: 0x000d,
+ 0x337c: 0x000d, 0x337d: 0x000d, 0x337e: 0x000d, 0x337f: 0x000d,
+ // Block 0xce, offset 0x3380
+ 0x3380: 0x000a, 0x3381: 0x000a, 0x3382: 0x000a, 0x3383: 0x000a, 0x3384: 0x000a, 0x3385: 0x000a,
+ 0x3386: 0x000a, 0x3387: 0x000a, 0x3388: 0x000a, 0x3389: 0x000a, 0x338a: 0x000a, 0x338b: 0x000a,
+ 0x338c: 0x000a, 0x338d: 0x000a, 0x338e: 0x000a, 0x338f: 0x000a, 0x3390: 0x000a, 0x3391: 0x000a,
+ 0x3392: 0x000a, 0x3393: 0x000a, 0x3394: 0x000a, 0x3395: 0x000a, 0x3396: 0x000a, 0x3397: 0x000a,
+ 0x3398: 0x000a, 0x3399: 0x000a, 0x339a: 0x000a, 0x339b: 0x000a, 0x339c: 0x000a, 0x339d: 0x000a,
+ 0x339e: 0x000a, 0x339f: 0x000a, 0x33a0: 0x000a, 0x33a1: 0x000a, 0x33a2: 0x000a, 0x33a3: 0x000a,
+ 0x33a4: 0x000a, 0x33a5: 0x000a, 0x33a6: 0x000a, 0x33a7: 0x000a, 0x33a8: 0x000a, 0x33a9: 0x000a,
+ 0x33aa: 0x000a, 0x33ab: 0x000a,
+ 0x33b0: 0x000a, 0x33b1: 0x000a, 0x33b2: 0x000a, 0x33b3: 0x000a, 0x33b4: 0x000a, 0x33b5: 0x000a,
+ 0x33b6: 0x000a, 0x33b7: 0x000a, 0x33b8: 0x000a, 0x33b9: 0x000a, 0x33ba: 0x000a, 0x33bb: 0x000a,
+ 0x33bc: 0x000a, 0x33bd: 0x000a, 0x33be: 0x000a, 0x33bf: 0x000a,
+ // Block 0xcf, offset 0x33c0
+ 0x33c0: 0x000a, 0x33c1: 0x000a, 0x33c2: 0x000a, 0x33c3: 0x000a, 0x33c4: 0x000a, 0x33c5: 0x000a,
+ 0x33c6: 0x000a, 0x33c7: 0x000a, 0x33c8: 0x000a, 0x33c9: 0x000a, 0x33ca: 0x000a, 0x33cb: 0x000a,
+ 0x33cc: 0x000a, 0x33cd: 0x000a, 0x33ce: 0x000a, 0x33cf: 0x000a, 0x33d0: 0x000a, 0x33d1: 0x000a,
+ 0x33d2: 0x000a, 0x33d3: 0x000a,
+ 0x33e0: 0x000a, 0x33e1: 0x000a, 0x33e2: 0x000a, 0x33e3: 0x000a,
+ 0x33e4: 0x000a, 0x33e5: 0x000a, 0x33e6: 0x000a, 0x33e7: 0x000a, 0x33e8: 0x000a, 0x33e9: 0x000a,
+ 0x33ea: 0x000a, 0x33eb: 0x000a, 0x33ec: 0x000a, 0x33ed: 0x000a, 0x33ee: 0x000a,
+ 0x33f1: 0x000a, 0x33f2: 0x000a, 0x33f3: 0x000a, 0x33f4: 0x000a, 0x33f5: 0x000a,
+ 0x33f6: 0x000a, 0x33f7: 0x000a, 0x33f8: 0x000a, 0x33f9: 0x000a, 0x33fa: 0x000a, 0x33fb: 0x000a,
+ 0x33fc: 0x000a, 0x33fd: 0x000a, 0x33fe: 0x000a, 0x33ff: 0x000a,
+ // Block 0xd0, offset 0x3400
+ 0x3401: 0x000a, 0x3402: 0x000a, 0x3403: 0x000a, 0x3404: 0x000a, 0x3405: 0x000a,
+ 0x3406: 0x000a, 0x3407: 0x000a, 0x3408: 0x000a, 0x3409: 0x000a, 0x340a: 0x000a, 0x340b: 0x000a,
+ 0x340c: 0x000a, 0x340d: 0x000a, 0x340e: 0x000a, 0x340f: 0x000a, 0x3411: 0x000a,
+ 0x3412: 0x000a, 0x3413: 0x000a, 0x3414: 0x000a, 0x3415: 0x000a, 0x3416: 0x000a, 0x3417: 0x000a,
+ 0x3418: 0x000a, 0x3419: 0x000a, 0x341a: 0x000a, 0x341b: 0x000a, 0x341c: 0x000a, 0x341d: 0x000a,
+ 0x341e: 0x000a, 0x341f: 0x000a, 0x3420: 0x000a, 0x3421: 0x000a, 0x3422: 0x000a, 0x3423: 0x000a,
+ 0x3424: 0x000a, 0x3425: 0x000a, 0x3426: 0x000a, 0x3427: 0x000a, 0x3428: 0x000a, 0x3429: 0x000a,
+ 0x342a: 0x000a, 0x342b: 0x000a, 0x342c: 0x000a, 0x342d: 0x000a, 0x342e: 0x000a, 0x342f: 0x000a,
+ 0x3430: 0x000a, 0x3431: 0x000a, 0x3432: 0x000a, 0x3433: 0x000a, 0x3434: 0x000a, 0x3435: 0x000a,
+ // Block 0xd1, offset 0x3440
+ 0x3440: 0x0002, 0x3441: 0x0002, 0x3442: 0x0002, 0x3443: 0x0002, 0x3444: 0x0002, 0x3445: 0x0002,
+ 0x3446: 0x0002, 0x3447: 0x0002, 0x3448: 0x0002, 0x3449: 0x0002, 0x344a: 0x0002, 0x344b: 0x000a,
+ 0x344c: 0x000a,
+ // Block 0xd2, offset 0x3480
+ 0x34aa: 0x000a, 0x34ab: 0x000a,
+ // Block 0xd3, offset 0x34c0
+ 0x34c0: 0x000a, 0x34c1: 0x000a, 0x34c2: 0x000a, 0x34c3: 0x000a, 0x34c4: 0x000a, 0x34c5: 0x000a,
+ 0x34c6: 0x000a, 0x34c7: 0x000a, 0x34c8: 0x000a, 0x34c9: 0x000a, 0x34ca: 0x000a, 0x34cb: 0x000a,
+ 0x34cc: 0x000a, 0x34cd: 0x000a, 0x34ce: 0x000a, 0x34cf: 0x000a, 0x34d0: 0x000a, 0x34d1: 0x000a,
+ 0x34d2: 0x000a,
+ 0x34e0: 0x000a, 0x34e1: 0x000a, 0x34e2: 0x000a, 0x34e3: 0x000a,
+ 0x34e4: 0x000a, 0x34e5: 0x000a, 0x34e6: 0x000a, 0x34e7: 0x000a, 0x34e8: 0x000a, 0x34e9: 0x000a,
+ 0x34ea: 0x000a, 0x34eb: 0x000a, 0x34ec: 0x000a,
+ 0x34f0: 0x000a, 0x34f1: 0x000a, 0x34f2: 0x000a, 0x34f3: 0x000a, 0x34f4: 0x000a, 0x34f5: 0x000a,
+ 0x34f6: 0x000a,
+ // Block 0xd4, offset 0x3500
+ 0x3500: 0x000a, 0x3501: 0x000a, 0x3502: 0x000a, 0x3503: 0x000a, 0x3504: 0x000a, 0x3505: 0x000a,
+ 0x3506: 0x000a, 0x3507: 0x000a, 0x3508: 0x000a, 0x3509: 0x000a, 0x350a: 0x000a, 0x350b: 0x000a,
+ 0x350c: 0x000a, 0x350d: 0x000a, 0x350e: 0x000a, 0x350f: 0x000a, 0x3510: 0x000a, 0x3511: 0x000a,
+ 0x3512: 0x000a, 0x3513: 0x000a, 0x3514: 0x000a,
+ // Block 0xd5, offset 0x3540
+ 0x3540: 0x000a, 0x3541: 0x000a, 0x3542: 0x000a, 0x3543: 0x000a, 0x3544: 0x000a, 0x3545: 0x000a,
+ 0x3546: 0x000a, 0x3547: 0x000a, 0x3548: 0x000a, 0x3549: 0x000a, 0x354a: 0x000a, 0x354b: 0x000a,
+ 0x3550: 0x000a, 0x3551: 0x000a,
+ 0x3552: 0x000a, 0x3553: 0x000a, 0x3554: 0x000a, 0x3555: 0x000a, 0x3556: 0x000a, 0x3557: 0x000a,
+ 0x3558: 0x000a, 0x3559: 0x000a, 0x355a: 0x000a, 0x355b: 0x000a, 0x355c: 0x000a, 0x355d: 0x000a,
+ 0x355e: 0x000a, 0x355f: 0x000a, 0x3560: 0x000a, 0x3561: 0x000a, 0x3562: 0x000a, 0x3563: 0x000a,
+ 0x3564: 0x000a, 0x3565: 0x000a, 0x3566: 0x000a, 0x3567: 0x000a, 0x3568: 0x000a, 0x3569: 0x000a,
+ 0x356a: 0x000a, 0x356b: 0x000a, 0x356c: 0x000a, 0x356d: 0x000a, 0x356e: 0x000a, 0x356f: 0x000a,
+ 0x3570: 0x000a, 0x3571: 0x000a, 0x3572: 0x000a, 0x3573: 0x000a, 0x3574: 0x000a, 0x3575: 0x000a,
+ 0x3576: 0x000a, 0x3577: 0x000a, 0x3578: 0x000a, 0x3579: 0x000a, 0x357a: 0x000a, 0x357b: 0x000a,
+ 0x357c: 0x000a, 0x357d: 0x000a, 0x357e: 0x000a, 0x357f: 0x000a,
+ // Block 0xd6, offset 0x3580
+ 0x3580: 0x000a, 0x3581: 0x000a, 0x3582: 0x000a, 0x3583: 0x000a, 0x3584: 0x000a, 0x3585: 0x000a,
+ 0x3586: 0x000a, 0x3587: 0x000a,
+ 0x3590: 0x000a, 0x3591: 0x000a,
+ 0x3592: 0x000a, 0x3593: 0x000a, 0x3594: 0x000a, 0x3595: 0x000a, 0x3596: 0x000a, 0x3597: 0x000a,
+ 0x3598: 0x000a, 0x3599: 0x000a,
+ 0x35a0: 0x000a, 0x35a1: 0x000a, 0x35a2: 0x000a, 0x35a3: 0x000a,
+ 0x35a4: 0x000a, 0x35a5: 0x000a, 0x35a6: 0x000a, 0x35a7: 0x000a, 0x35a8: 0x000a, 0x35a9: 0x000a,
+ 0x35aa: 0x000a, 0x35ab: 0x000a, 0x35ac: 0x000a, 0x35ad: 0x000a, 0x35ae: 0x000a, 0x35af: 0x000a,
+ 0x35b0: 0x000a, 0x35b1: 0x000a, 0x35b2: 0x000a, 0x35b3: 0x000a, 0x35b4: 0x000a, 0x35b5: 0x000a,
+ 0x35b6: 0x000a, 0x35b7: 0x000a, 0x35b8: 0x000a, 0x35b9: 0x000a, 0x35ba: 0x000a, 0x35bb: 0x000a,
+ 0x35bc: 0x000a, 0x35bd: 0x000a, 0x35be: 0x000a, 0x35bf: 0x000a,
+ // Block 0xd7, offset 0x35c0
+ 0x35c0: 0x000a, 0x35c1: 0x000a, 0x35c2: 0x000a, 0x35c3: 0x000a, 0x35c4: 0x000a, 0x35c5: 0x000a,
+ 0x35c6: 0x000a, 0x35c7: 0x000a,
+ 0x35d0: 0x000a, 0x35d1: 0x000a,
+ 0x35d2: 0x000a, 0x35d3: 0x000a, 0x35d4: 0x000a, 0x35d5: 0x000a, 0x35d6: 0x000a, 0x35d7: 0x000a,
+ 0x35d8: 0x000a, 0x35d9: 0x000a, 0x35da: 0x000a, 0x35db: 0x000a, 0x35dc: 0x000a, 0x35dd: 0x000a,
+ 0x35de: 0x000a, 0x35df: 0x000a, 0x35e0: 0x000a, 0x35e1: 0x000a, 0x35e2: 0x000a, 0x35e3: 0x000a,
+ 0x35e4: 0x000a, 0x35e5: 0x000a, 0x35e6: 0x000a, 0x35e7: 0x000a, 0x35e8: 0x000a, 0x35e9: 0x000a,
+ 0x35ea: 0x000a, 0x35eb: 0x000a, 0x35ec: 0x000a, 0x35ed: 0x000a,
+ // Block 0xd8, offset 0x3600
+ 0x3610: 0x000a, 0x3611: 0x000a,
+ 0x3612: 0x000a, 0x3613: 0x000a, 0x3614: 0x000a, 0x3615: 0x000a, 0x3616: 0x000a, 0x3617: 0x000a,
+ 0x3618: 0x000a, 0x3619: 0x000a, 0x361a: 0x000a, 0x361b: 0x000a, 0x361c: 0x000a, 0x361d: 0x000a,
+ 0x361e: 0x000a, 0x3620: 0x000a, 0x3621: 0x000a, 0x3622: 0x000a, 0x3623: 0x000a,
+ 0x3624: 0x000a, 0x3625: 0x000a, 0x3626: 0x000a, 0x3627: 0x000a,
+ 0x3630: 0x000a, 0x3633: 0x000a, 0x3634: 0x000a, 0x3635: 0x000a,
+ 0x3636: 0x000a, 0x3637: 0x000a, 0x3638: 0x000a, 0x3639: 0x000a, 0x363a: 0x000a, 0x363b: 0x000a,
+ 0x363c: 0x000a, 0x363d: 0x000a, 0x363e: 0x000a,
+ // Block 0xd9, offset 0x3640
+ 0x3640: 0x000a, 0x3641: 0x000a, 0x3642: 0x000a, 0x3643: 0x000a, 0x3644: 0x000a, 0x3645: 0x000a,
+ 0x3646: 0x000a, 0x3647: 0x000a, 0x3648: 0x000a, 0x3649: 0x000a, 0x364a: 0x000a, 0x364b: 0x000a,
+ 0x3650: 0x000a, 0x3651: 0x000a,
+ 0x3652: 0x000a, 0x3653: 0x000a, 0x3654: 0x000a, 0x3655: 0x000a, 0x3656: 0x000a, 0x3657: 0x000a,
+ 0x3658: 0x000a, 0x3659: 0x000a, 0x365a: 0x000a, 0x365b: 0x000a, 0x365c: 0x000a, 0x365d: 0x000a,
+ 0x365e: 0x000a,
+ // Block 0xda, offset 0x3680
+ 0x3680: 0x000a, 0x3681: 0x000a, 0x3682: 0x000a, 0x3683: 0x000a, 0x3684: 0x000a, 0x3685: 0x000a,
+ 0x3686: 0x000a, 0x3687: 0x000a, 0x3688: 0x000a, 0x3689: 0x000a, 0x368a: 0x000a, 0x368b: 0x000a,
+ 0x368c: 0x000a, 0x368d: 0x000a, 0x368e: 0x000a, 0x368f: 0x000a, 0x3690: 0x000a, 0x3691: 0x000a,
+ // Block 0xdb, offset 0x36c0
+ 0x36fe: 0x000b, 0x36ff: 0x000b,
+ // Block 0xdc, offset 0x3700
+ 0x3700: 0x000b, 0x3701: 0x000b, 0x3702: 0x000b, 0x3703: 0x000b, 0x3704: 0x000b, 0x3705: 0x000b,
+ 0x3706: 0x000b, 0x3707: 0x000b, 0x3708: 0x000b, 0x3709: 0x000b, 0x370a: 0x000b, 0x370b: 0x000b,
+ 0x370c: 0x000b, 0x370d: 0x000b, 0x370e: 0x000b, 0x370f: 0x000b, 0x3710: 0x000b, 0x3711: 0x000b,
+ 0x3712: 0x000b, 0x3713: 0x000b, 0x3714: 0x000b, 0x3715: 0x000b, 0x3716: 0x000b, 0x3717: 0x000b,
+ 0x3718: 0x000b, 0x3719: 0x000b, 0x371a: 0x000b, 0x371b: 0x000b, 0x371c: 0x000b, 0x371d: 0x000b,
+ 0x371e: 0x000b, 0x371f: 0x000b, 0x3720: 0x000b, 0x3721: 0x000b, 0x3722: 0x000b, 0x3723: 0x000b,
+ 0x3724: 0x000b, 0x3725: 0x000b, 0x3726: 0x000b, 0x3727: 0x000b, 0x3728: 0x000b, 0x3729: 0x000b,
+ 0x372a: 0x000b, 0x372b: 0x000b, 0x372c: 0x000b, 0x372d: 0x000b, 0x372e: 0x000b, 0x372f: 0x000b,
+ 0x3730: 0x000b, 0x3731: 0x000b, 0x3732: 0x000b, 0x3733: 0x000b, 0x3734: 0x000b, 0x3735: 0x000b,
+ 0x3736: 0x000b, 0x3737: 0x000b, 0x3738: 0x000b, 0x3739: 0x000b, 0x373a: 0x000b, 0x373b: 0x000b,
+ 0x373c: 0x000b, 0x373d: 0x000b, 0x373e: 0x000b, 0x373f: 0x000b,
+ // Block 0xdd, offset 0x3740
+ 0x3740: 0x000c, 0x3741: 0x000c, 0x3742: 0x000c, 0x3743: 0x000c, 0x3744: 0x000c, 0x3745: 0x000c,
+ 0x3746: 0x000c, 0x3747: 0x000c, 0x3748: 0x000c, 0x3749: 0x000c, 0x374a: 0x000c, 0x374b: 0x000c,
+ 0x374c: 0x000c, 0x374d: 0x000c, 0x374e: 0x000c, 0x374f: 0x000c, 0x3750: 0x000c, 0x3751: 0x000c,
+ 0x3752: 0x000c, 0x3753: 0x000c, 0x3754: 0x000c, 0x3755: 0x000c, 0x3756: 0x000c, 0x3757: 0x000c,
+ 0x3758: 0x000c, 0x3759: 0x000c, 0x375a: 0x000c, 0x375b: 0x000c, 0x375c: 0x000c, 0x375d: 0x000c,
+ 0x375e: 0x000c, 0x375f: 0x000c, 0x3760: 0x000c, 0x3761: 0x000c, 0x3762: 0x000c, 0x3763: 0x000c,
+ 0x3764: 0x000c, 0x3765: 0x000c, 0x3766: 0x000c, 0x3767: 0x000c, 0x3768: 0x000c, 0x3769: 0x000c,
+ 0x376a: 0x000c, 0x376b: 0x000c, 0x376c: 0x000c, 0x376d: 0x000c, 0x376e: 0x000c, 0x376f: 0x000c,
+ 0x3770: 0x000b, 0x3771: 0x000b, 0x3772: 0x000b, 0x3773: 0x000b, 0x3774: 0x000b, 0x3775: 0x000b,
+ 0x3776: 0x000b, 0x3777: 0x000b, 0x3778: 0x000b, 0x3779: 0x000b, 0x377a: 0x000b, 0x377b: 0x000b,
+ 0x377c: 0x000b, 0x377d: 0x000b, 0x377e: 0x000b, 0x377f: 0x000b,
+}
+
+// bidiIndex: 24 blocks, 1536 entries, 1536 bytes
+// Block 0 is the zero block.
+var bidiIndex = [1536]uint8{
+ // Block 0x0, offset 0x0
+ // Block 0x1, offset 0x40
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc2: 0x01, 0xc3: 0x02,
+ 0xca: 0x03, 0xcb: 0x04, 0xcc: 0x05, 0xcd: 0x06, 0xce: 0x07, 0xcf: 0x08,
+ 0xd2: 0x09, 0xd6: 0x0a, 0xd7: 0x0b,
+ 0xd8: 0x0c, 0xd9: 0x0d, 0xda: 0x0e, 0xdb: 0x0f, 0xdc: 0x10, 0xdd: 0x11, 0xde: 0x12, 0xdf: 0x13,
+ 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05, 0xe4: 0x06,
+ 0xea: 0x07, 0xef: 0x08,
+ 0xf0: 0x11, 0xf1: 0x12, 0xf2: 0x12, 0xf3: 0x14, 0xf4: 0x15,
+ // Block 0x4, offset 0x100
+ 0x120: 0x14, 0x121: 0x15, 0x122: 0x16, 0x123: 0x17, 0x124: 0x18, 0x125: 0x19, 0x126: 0x1a, 0x127: 0x1b,
+ 0x128: 0x1c, 0x129: 0x1d, 0x12a: 0x1c, 0x12b: 0x1e, 0x12c: 0x1f, 0x12d: 0x20, 0x12e: 0x21, 0x12f: 0x22,
+ 0x130: 0x23, 0x131: 0x24, 0x132: 0x1a, 0x133: 0x25, 0x134: 0x26, 0x135: 0x27, 0x137: 0x28,
+ 0x138: 0x29, 0x139: 0x2a, 0x13a: 0x2b, 0x13b: 0x2c, 0x13c: 0x2d, 0x13d: 0x2e, 0x13e: 0x2f, 0x13f: 0x30,
+ // Block 0x5, offset 0x140
+ 0x140: 0x31, 0x141: 0x32, 0x142: 0x33,
+ 0x14d: 0x34, 0x14e: 0x35,
+ 0x150: 0x36,
+ 0x15a: 0x37, 0x15c: 0x38, 0x15d: 0x39, 0x15e: 0x3a, 0x15f: 0x3b,
+ 0x160: 0x3c, 0x162: 0x3d, 0x164: 0x3e, 0x165: 0x3f, 0x167: 0x40,
+ 0x168: 0x41, 0x169: 0x42, 0x16a: 0x43, 0x16c: 0x44, 0x16d: 0x45, 0x16e: 0x46, 0x16f: 0x47,
+ 0x170: 0x48, 0x173: 0x49, 0x177: 0x4a,
+ 0x17e: 0x4b, 0x17f: 0x4c,
+ // Block 0x6, offset 0x180
+ 0x180: 0x4d, 0x181: 0x4e, 0x182: 0x4f, 0x183: 0x50, 0x184: 0x51, 0x185: 0x52, 0x186: 0x53, 0x187: 0x54,
+ 0x188: 0x55, 0x189: 0x54, 0x18a: 0x54, 0x18b: 0x54, 0x18c: 0x56, 0x18d: 0x57, 0x18e: 0x58, 0x18f: 0x59,
+ 0x190: 0x5a, 0x191: 0x5b, 0x192: 0x5c, 0x193: 0x5d, 0x194: 0x54, 0x195: 0x54, 0x196: 0x54, 0x197: 0x54,
+ 0x198: 0x54, 0x199: 0x54, 0x19a: 0x5e, 0x19b: 0x54, 0x19c: 0x54, 0x19d: 0x5f, 0x19e: 0x54, 0x19f: 0x60,
+ 0x1a4: 0x54, 0x1a5: 0x54, 0x1a6: 0x61, 0x1a7: 0x62,
+ 0x1a8: 0x54, 0x1a9: 0x54, 0x1aa: 0x54, 0x1ab: 0x54, 0x1ac: 0x54, 0x1ad: 0x63, 0x1ae: 0x64, 0x1af: 0x65,
+ 0x1b3: 0x66, 0x1b5: 0x67, 0x1b7: 0x68,
+ 0x1b8: 0x69, 0x1b9: 0x6a, 0x1ba: 0x6b, 0x1bb: 0x6c, 0x1bc: 0x54, 0x1bd: 0x54, 0x1be: 0x54, 0x1bf: 0x6d,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x6e, 0x1c2: 0x6f, 0x1c3: 0x70, 0x1c7: 0x71,
+ 0x1c8: 0x72, 0x1c9: 0x73, 0x1ca: 0x74, 0x1cb: 0x75, 0x1cd: 0x76, 0x1cf: 0x77,
+ // Block 0x8, offset 0x200
+ 0x237: 0x54,
+ // Block 0x9, offset 0x240
+ 0x252: 0x78, 0x253: 0x79,
+ 0x258: 0x7a, 0x259: 0x7b, 0x25a: 0x7c, 0x25b: 0x7d, 0x25c: 0x7e, 0x25e: 0x7f,
+ 0x260: 0x80, 0x261: 0x81, 0x263: 0x82, 0x264: 0x83, 0x265: 0x84, 0x266: 0x85, 0x267: 0x86,
+ 0x268: 0x87, 0x269: 0x88, 0x26a: 0x89, 0x26b: 0x8a, 0x26f: 0x8b,
+ // Block 0xa, offset 0x280
+ 0x2ac: 0x8c, 0x2ad: 0x8d, 0x2ae: 0x0e, 0x2af: 0x0e,
+ 0x2b0: 0x0e, 0x2b1: 0x0e, 0x2b2: 0x0e, 0x2b3: 0x0e, 0x2b4: 0x8e, 0x2b5: 0x0e, 0x2b6: 0x0e, 0x2b7: 0x8f,
+ 0x2b8: 0x90, 0x2b9: 0x91, 0x2ba: 0x0e, 0x2bb: 0x92, 0x2bc: 0x93, 0x2bd: 0x94, 0x2bf: 0x95,
+ // Block 0xb, offset 0x2c0
+ 0x2c4: 0x96, 0x2c5: 0x54, 0x2c6: 0x97, 0x2c7: 0x98,
+ 0x2cb: 0x99, 0x2cd: 0x9a,
+ 0x2e0: 0x9b, 0x2e1: 0x9b, 0x2e2: 0x9b, 0x2e3: 0x9b, 0x2e4: 0x9c, 0x2e5: 0x9b, 0x2e6: 0x9b, 0x2e7: 0x9b,
+ 0x2e8: 0x9d, 0x2e9: 0x9b, 0x2ea: 0x9b, 0x2eb: 0x9e, 0x2ec: 0x9f, 0x2ed: 0x9b, 0x2ee: 0x9b, 0x2ef: 0x9b,
+ 0x2f0: 0x9b, 0x2f1: 0x9b, 0x2f2: 0x9b, 0x2f3: 0x9b, 0x2f4: 0x9b, 0x2f5: 0x9b, 0x2f6: 0x9b, 0x2f7: 0x9b,
+ 0x2f8: 0x9b, 0x2f9: 0xa0, 0x2fa: 0x9b, 0x2fb: 0x9b, 0x2fc: 0x9b, 0x2fd: 0x9b, 0x2fe: 0x9b, 0x2ff: 0x9b,
+ // Block 0xc, offset 0x300
+ 0x300: 0xa1, 0x301: 0xa2, 0x302: 0xa3, 0x304: 0xa4, 0x305: 0xa5, 0x306: 0xa6, 0x307: 0xa7,
+ 0x308: 0xa8, 0x30b: 0xa9, 0x30c: 0xaa, 0x30d: 0xab,
+ 0x310: 0xac, 0x311: 0xad, 0x312: 0xae, 0x313: 0xaf, 0x316: 0xb0, 0x317: 0xb1,
+ 0x318: 0xb2, 0x319: 0xb3, 0x31a: 0xb4, 0x31c: 0xb5,
+ 0x330: 0xb6, 0x332: 0xb7,
+ // Block 0xd, offset 0x340
+ 0x36b: 0xb8, 0x36c: 0xb9,
+ 0x37e: 0xba,
+ // Block 0xe, offset 0x380
+ 0x3b2: 0xbb,
+ // Block 0xf, offset 0x3c0
+ 0x3c5: 0xbc, 0x3c6: 0xbd,
+ 0x3c8: 0x54, 0x3c9: 0xbe, 0x3cc: 0x54, 0x3cd: 0xbf,
+ 0x3db: 0xc0, 0x3dc: 0xc1, 0x3dd: 0xc2, 0x3de: 0xc3, 0x3df: 0xc4,
+ 0x3e8: 0xc5, 0x3e9: 0xc6, 0x3ea: 0xc7,
+ // Block 0x10, offset 0x400
+ 0x400: 0xc8,
+ 0x420: 0x9b, 0x421: 0x9b, 0x422: 0x9b, 0x423: 0xc9, 0x424: 0x9b, 0x425: 0xca, 0x426: 0x9b, 0x427: 0x9b,
+ 0x428: 0x9b, 0x429: 0x9b, 0x42a: 0x9b, 0x42b: 0x9b, 0x42c: 0x9b, 0x42d: 0x9b, 0x42e: 0x9b, 0x42f: 0x9b,
+ 0x430: 0x9b, 0x431: 0x9b, 0x432: 0x9b, 0x433: 0x9b, 0x434: 0x9b, 0x435: 0x9b, 0x436: 0x9b, 0x437: 0x9b,
+ 0x438: 0x0e, 0x439: 0x0e, 0x43a: 0x0e, 0x43b: 0xcb, 0x43c: 0x9b, 0x43d: 0x9b, 0x43e: 0x9b, 0x43f: 0x9b,
+ // Block 0x11, offset 0x440
+ 0x440: 0xcc, 0x441: 0x54, 0x442: 0xcd, 0x443: 0xce, 0x444: 0xcf, 0x445: 0xd0,
+ 0x44c: 0x54, 0x44d: 0x54, 0x44e: 0x54, 0x44f: 0x54,
+ 0x450: 0x54, 0x451: 0x54, 0x452: 0x54, 0x453: 0x54, 0x454: 0x54, 0x455: 0x54, 0x456: 0x54, 0x457: 0x54,
+ 0x458: 0x54, 0x459: 0x54, 0x45a: 0x54, 0x45b: 0xd1, 0x45c: 0x54, 0x45d: 0x6c, 0x45e: 0x54, 0x45f: 0xd2,
+ 0x460: 0xd3, 0x461: 0xd4, 0x462: 0xd5, 0x464: 0xd6, 0x465: 0xd7, 0x466: 0xd8, 0x467: 0x36,
+ 0x47f: 0xd9,
+ // Block 0x12, offset 0x480
+ 0x4bf: 0xd9,
+ // Block 0x13, offset 0x4c0
+ 0x4d0: 0x09, 0x4d1: 0x0a, 0x4d6: 0x0b,
+ 0x4db: 0x0c, 0x4dd: 0x0d, 0x4de: 0x0e, 0x4df: 0x0f,
+ 0x4ef: 0x10,
+ 0x4ff: 0x10,
+ // Block 0x14, offset 0x500
+ 0x50f: 0x10,
+ 0x51f: 0x10,
+ 0x52f: 0x10,
+ 0x53f: 0x10,
+ // Block 0x15, offset 0x540
+ 0x540: 0xda, 0x541: 0xda, 0x542: 0xda, 0x543: 0xda, 0x544: 0x05, 0x545: 0x05, 0x546: 0x05, 0x547: 0xdb,
+ 0x548: 0xda, 0x549: 0xda, 0x54a: 0xda, 0x54b: 0xda, 0x54c: 0xda, 0x54d: 0xda, 0x54e: 0xda, 0x54f: 0xda,
+ 0x550: 0xda, 0x551: 0xda, 0x552: 0xda, 0x553: 0xda, 0x554: 0xda, 0x555: 0xda, 0x556: 0xda, 0x557: 0xda,
+ 0x558: 0xda, 0x559: 0xda, 0x55a: 0xda, 0x55b: 0xda, 0x55c: 0xda, 0x55d: 0xda, 0x55e: 0xda, 0x55f: 0xda,
+ 0x560: 0xda, 0x561: 0xda, 0x562: 0xda, 0x563: 0xda, 0x564: 0xda, 0x565: 0xda, 0x566: 0xda, 0x567: 0xda,
+ 0x568: 0xda, 0x569: 0xda, 0x56a: 0xda, 0x56b: 0xda, 0x56c: 0xda, 0x56d: 0xda, 0x56e: 0xda, 0x56f: 0xda,
+ 0x570: 0xda, 0x571: 0xda, 0x572: 0xda, 0x573: 0xda, 0x574: 0xda, 0x575: 0xda, 0x576: 0xda, 0x577: 0xda,
+ 0x578: 0xda, 0x579: 0xda, 0x57a: 0xda, 0x57b: 0xda, 0x57c: 0xda, 0x57d: 0xda, 0x57e: 0xda, 0x57f: 0xda,
+ // Block 0x16, offset 0x580
+ 0x58f: 0x10,
+ 0x59f: 0x10,
+ 0x5a0: 0x13,
+ 0x5af: 0x10,
+ 0x5bf: 0x10,
+ // Block 0x17, offset 0x5c0
+ 0x5cf: 0x10,
+}
+
+// Total table size 15800 bytes (15KiB); checksum: F50EF68C
diff --git a/vendor/golang.org/x/text/unicode/bidi/trieval.go b/vendor/golang.org/x/text/unicode/bidi/trieval.go
new file mode 100644
index 0000000..4c459c4
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/bidi/trieval.go
@@ -0,0 +1,60 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package bidi
+
+// Class is the Unicode BiDi class. Each rune has a single class.
+type Class uint
+
+const (
+ L Class = iota // LeftToRight
+ R // RightToLeft
+ EN // EuropeanNumber
+ ES // EuropeanSeparator
+ ET // EuropeanTerminator
+ AN // ArabicNumber
+ CS // CommonSeparator
+ B // ParagraphSeparator
+ S // SegmentSeparator
+ WS // WhiteSpace
+ ON // OtherNeutral
+ BN // BoundaryNeutral
+ NSM // NonspacingMark
+ AL // ArabicLetter
+ Control // Control LRO - PDI
+
+ numClass
+
+ LRO // LeftToRightOverride
+ RLO // RightToLeftOverride
+ LRE // LeftToRightEmbedding
+ RLE // RightToLeftEmbedding
+ PDF // PopDirectionalFormat
+ LRI // LeftToRightIsolate
+ RLI // RightToLeftIsolate
+ FSI // FirstStrongIsolate
+ PDI // PopDirectionalIsolate
+
+ unknownClass = ^Class(0)
+)
+
+var controlToClass = map[rune]Class{
+ 0x202D: LRO, // LeftToRightOverride,
+ 0x202E: RLO, // RightToLeftOverride,
+ 0x202A: LRE, // LeftToRightEmbedding,
+ 0x202B: RLE, // RightToLeftEmbedding,
+ 0x202C: PDF, // PopDirectionalFormat,
+ 0x2066: LRI, // LeftToRightIsolate,
+ 0x2067: RLI, // RightToLeftIsolate,
+ 0x2068: FSI, // FirstStrongIsolate,
+ 0x2069: PDI, // PopDirectionalIsolate,
+}
+
+// A trie entry has the following bits:
+// 7..5 XOR mask for brackets
+// 4 1: Bracket open, 0: Bracket close
+// 3..0 Class type
+
+const (
+ openMask = 0x10
+ xorMaskShift = 5
+)
diff --git a/vendor/golang.org/x/text/unicode/norm/composition.go b/vendor/golang.org/x/text/unicode/norm/composition.go
new file mode 100644
index 0000000..bab4c5d
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/norm/composition.go
@@ -0,0 +1,508 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package norm
+
+import "unicode/utf8"
+
+const (
+ maxNonStarters = 30
+ // The maximum number of characters needed for a buffer is
+ // maxNonStarters + 1 for the starter + 1 for the GCJ
+ maxBufferSize = maxNonStarters + 2
+ maxNFCExpansion = 3 // NFC(0x1D160)
+ maxNFKCExpansion = 18 // NFKC(0xFDFA)
+
+ maxByteBufferSize = utf8.UTFMax * maxBufferSize // 128
+)
+
+// ssState is used for reporting the segment state after inserting a rune.
+// It is returned by streamSafe.next.
+type ssState int
+
+const (
+ // Indicates a rune was successfully added to the segment.
+ ssSuccess ssState = iota
+ // Indicates a rune starts a new segment and should not be added.
+ ssStarter
+ // Indicates a rune caused a segment overflow and a CGJ should be inserted.
+ ssOverflow
+)
+
+// streamSafe implements the policy of when a CGJ should be inserted.
+type streamSafe uint8
+
+// first inserts the first rune of a segment. It is a faster version of next if
+// it is known p represents the first rune in a segment.
+func (ss *streamSafe) first(p Properties) {
+ *ss = streamSafe(p.nTrailingNonStarters())
+}
+
+// insert returns a ssState value to indicate whether a rune represented by p
+// can be inserted.
+func (ss *streamSafe) next(p Properties) ssState {
+ if *ss > maxNonStarters {
+ panic("streamSafe was not reset")
+ }
+ n := p.nLeadingNonStarters()
+ if *ss += streamSafe(n); *ss > maxNonStarters {
+ *ss = 0
+ return ssOverflow
+ }
+ // The Stream-Safe Text Processing prescribes that the counting can stop
+ // as soon as a starter is encountered. However, there are some starters,
+ // like Jamo V and T, that can combine with other runes, leaving their
+ // successive non-starters appended to the previous, possibly causing an
+ // overflow. We will therefore consider any rune with a non-zero nLead to
+ // be a non-starter. Note that it always hold that if nLead > 0 then
+ // nLead == nTrail.
+ if n == 0 {
+ *ss = streamSafe(p.nTrailingNonStarters())
+ return ssStarter
+ }
+ return ssSuccess
+}
+
+// backwards is used for checking for overflow and segment starts
+// when traversing a string backwards. Users do not need to call first
+// for the first rune. The state of the streamSafe retains the count of
+// the non-starters loaded.
+func (ss *streamSafe) backwards(p Properties) ssState {
+ if *ss > maxNonStarters {
+ panic("streamSafe was not reset")
+ }
+ c := *ss + streamSafe(p.nTrailingNonStarters())
+ if c > maxNonStarters {
+ return ssOverflow
+ }
+ *ss = c
+ if p.nLeadingNonStarters() == 0 {
+ return ssStarter
+ }
+ return ssSuccess
+}
+
+func (ss streamSafe) isMax() bool {
+ return ss == maxNonStarters
+}
+
+// GraphemeJoiner is inserted after maxNonStarters non-starter runes.
+const GraphemeJoiner = "\u034F"
+
+// reorderBuffer is used to normalize a single segment. Characters inserted with
+// insert are decomposed and reordered based on CCC. The compose method can
+// be used to recombine characters. Note that the byte buffer does not hold
+// the UTF-8 characters in order. Only the rune array is maintained in sorted
+// order. flush writes the resulting segment to a byte array.
+type reorderBuffer struct {
+ rune [maxBufferSize]Properties // Per character info.
+ byte [maxByteBufferSize]byte // UTF-8 buffer. Referenced by runeInfo.pos.
+ nbyte uint8 // Number or bytes.
+ ss streamSafe // For limiting length of non-starter sequence.
+ nrune int // Number of runeInfos.
+ f formInfo
+
+ src input
+ nsrc int
+ tmpBytes input
+
+ out []byte
+ flushF func(*reorderBuffer) bool
+}
+
+func (rb *reorderBuffer) init(f Form, src []byte) {
+ rb.f = *formTable[f]
+ rb.src.setBytes(src)
+ rb.nsrc = len(src)
+ rb.ss = 0
+}
+
+func (rb *reorderBuffer) initString(f Form, src string) {
+ rb.f = *formTable[f]
+ rb.src.setString(src)
+ rb.nsrc = len(src)
+ rb.ss = 0
+}
+
+func (rb *reorderBuffer) setFlusher(out []byte, f func(*reorderBuffer) bool) {
+ rb.out = out
+ rb.flushF = f
+}
+
+// reset discards all characters from the buffer.
+func (rb *reorderBuffer) reset() {
+ rb.nrune = 0
+ rb.nbyte = 0
+}
+
+func (rb *reorderBuffer) doFlush() bool {
+ if rb.f.composing {
+ rb.compose()
+ }
+ res := rb.flushF(rb)
+ rb.reset()
+ return res
+}
+
+// appendFlush appends the normalized segment to rb.out.
+func appendFlush(rb *reorderBuffer) bool {
+ for i := 0; i < rb.nrune; i++ {
+ start := rb.rune[i].pos
+ end := start + rb.rune[i].size
+ rb.out = append(rb.out, rb.byte[start:end]...)
+ }
+ return true
+}
+
+// flush appends the normalized segment to out and resets rb.
+func (rb *reorderBuffer) flush(out []byte) []byte {
+ for i := 0; i < rb.nrune; i++ {
+ start := rb.rune[i].pos
+ end := start + rb.rune[i].size
+ out = append(out, rb.byte[start:end]...)
+ }
+ rb.reset()
+ return out
+}
+
+// flushCopy copies the normalized segment to buf and resets rb.
+// It returns the number of bytes written to buf.
+func (rb *reorderBuffer) flushCopy(buf []byte) int {
+ p := 0
+ for i := 0; i < rb.nrune; i++ {
+ runep := rb.rune[i]
+ p += copy(buf[p:], rb.byte[runep.pos:runep.pos+runep.size])
+ }
+ rb.reset()
+ return p
+}
+
+// insertOrdered inserts a rune in the buffer, ordered by Canonical Combining Class.
+// It returns false if the buffer is not large enough to hold the rune.
+// It is used internally by insert and insertString only.
+func (rb *reorderBuffer) insertOrdered(info Properties) {
+ n := rb.nrune
+ b := rb.rune[:]
+ cc := info.ccc
+ if cc > 0 {
+ // Find insertion position + move elements to make room.
+ for ; n > 0; n-- {
+ if b[n-1].ccc <= cc {
+ break
+ }
+ b[n] = b[n-1]
+ }
+ }
+ rb.nrune += 1
+ pos := uint8(rb.nbyte)
+ rb.nbyte += utf8.UTFMax
+ info.pos = pos
+ b[n] = info
+}
+
+// insertErr is an error code returned by insert. Using this type instead
+// of error improves performance up to 20% for many of the benchmarks.
+type insertErr int
+
+const (
+ iSuccess insertErr = -iota
+ iShortDst
+ iShortSrc
+)
+
+// insertFlush inserts the given rune in the buffer ordered by CCC.
+// If a decomposition with multiple segments are encountered, they leading
+// ones are flushed.
+// It returns a non-zero error code if the rune was not inserted.
+func (rb *reorderBuffer) insertFlush(src input, i int, info Properties) insertErr {
+ if rune := src.hangul(i); rune != 0 {
+ rb.decomposeHangul(rune)
+ return iSuccess
+ }
+ if info.hasDecomposition() {
+ return rb.insertDecomposed(info.Decomposition())
+ }
+ rb.insertSingle(src, i, info)
+ return iSuccess
+}
+
+// insertUnsafe inserts the given rune in the buffer ordered by CCC.
+// It is assumed there is sufficient space to hold the runes. It is the
+// responsibility of the caller to ensure this. This can be done by checking
+// the state returned by the streamSafe type.
+func (rb *reorderBuffer) insertUnsafe(src input, i int, info Properties) {
+ if rune := src.hangul(i); rune != 0 {
+ rb.decomposeHangul(rune)
+ }
+ if info.hasDecomposition() {
+ // TODO: inline.
+ rb.insertDecomposed(info.Decomposition())
+ } else {
+ rb.insertSingle(src, i, info)
+ }
+}
+
+// insertDecomposed inserts an entry in to the reorderBuffer for each rune
+// in dcomp. dcomp must be a sequence of decomposed UTF-8-encoded runes.
+// It flushes the buffer on each new segment start.
+func (rb *reorderBuffer) insertDecomposed(dcomp []byte) insertErr {
+ rb.tmpBytes.setBytes(dcomp)
+ // As the streamSafe accounting already handles the counting for modifiers,
+ // we don't have to call next. However, we do need to keep the accounting
+ // intact when flushing the buffer.
+ for i := 0; i < len(dcomp); {
+ info := rb.f.info(rb.tmpBytes, i)
+ if info.BoundaryBefore() && rb.nrune > 0 && !rb.doFlush() {
+ return iShortDst
+ }
+ i += copy(rb.byte[rb.nbyte:], dcomp[i:i+int(info.size)])
+ rb.insertOrdered(info)
+ }
+ return iSuccess
+}
+
+// insertSingle inserts an entry in the reorderBuffer for the rune at
+// position i. info is the runeInfo for the rune at position i.
+func (rb *reorderBuffer) insertSingle(src input, i int, info Properties) {
+ src.copySlice(rb.byte[rb.nbyte:], i, i+int(info.size))
+ rb.insertOrdered(info)
+}
+
+// insertCGJ inserts a Combining Grapheme Joiner (0x034f) into rb.
+func (rb *reorderBuffer) insertCGJ() {
+ rb.insertSingle(input{str: GraphemeJoiner}, 0, Properties{size: uint8(len(GraphemeJoiner))})
+}
+
+// appendRune inserts a rune at the end of the buffer. It is used for Hangul.
+func (rb *reorderBuffer) appendRune(r rune) {
+ bn := rb.nbyte
+ sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
+ rb.nbyte += utf8.UTFMax
+ rb.rune[rb.nrune] = Properties{pos: bn, size: uint8(sz)}
+ rb.nrune++
+}
+
+// assignRune sets a rune at position pos. It is used for Hangul and recomposition.
+func (rb *reorderBuffer) assignRune(pos int, r rune) {
+ bn := rb.rune[pos].pos
+ sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
+ rb.rune[pos] = Properties{pos: bn, size: uint8(sz)}
+}
+
+// runeAt returns the rune at position n. It is used for Hangul and recomposition.
+func (rb *reorderBuffer) runeAt(n int) rune {
+ inf := rb.rune[n]
+ r, _ := utf8.DecodeRune(rb.byte[inf.pos : inf.pos+inf.size])
+ return r
+}
+
+// bytesAt returns the UTF-8 encoding of the rune at position n.
+// It is used for Hangul and recomposition.
+func (rb *reorderBuffer) bytesAt(n int) []byte {
+ inf := rb.rune[n]
+ return rb.byte[inf.pos : int(inf.pos)+int(inf.size)]
+}
+
+// For Hangul we combine algorithmically, instead of using tables.
+const (
+ hangulBase = 0xAC00 // UTF-8(hangulBase) -> EA B0 80
+ hangulBase0 = 0xEA
+ hangulBase1 = 0xB0
+ hangulBase2 = 0x80
+
+ hangulEnd = hangulBase + jamoLVTCount // UTF-8(0xD7A4) -> ED 9E A4
+ hangulEnd0 = 0xED
+ hangulEnd1 = 0x9E
+ hangulEnd2 = 0xA4
+
+ jamoLBase = 0x1100 // UTF-8(jamoLBase) -> E1 84 00
+ jamoLBase0 = 0xE1
+ jamoLBase1 = 0x84
+ jamoLEnd = 0x1113
+ jamoVBase = 0x1161
+ jamoVEnd = 0x1176
+ jamoTBase = 0x11A7
+ jamoTEnd = 0x11C3
+
+ jamoTCount = 28
+ jamoVCount = 21
+ jamoVTCount = 21 * 28
+ jamoLVTCount = 19 * 21 * 28
+)
+
+const hangulUTF8Size = 3
+
+func isHangul(b []byte) bool {
+ if len(b) < hangulUTF8Size {
+ return false
+ }
+ b0 := b[0]
+ if b0 < hangulBase0 {
+ return false
+ }
+ b1 := b[1]
+ switch {
+ case b0 == hangulBase0:
+ return b1 >= hangulBase1
+ case b0 < hangulEnd0:
+ return true
+ case b0 > hangulEnd0:
+ return false
+ case b1 < hangulEnd1:
+ return true
+ }
+ return b1 == hangulEnd1 && b[2] < hangulEnd2
+}
+
+func isHangulString(b string) bool {
+ if len(b) < hangulUTF8Size {
+ return false
+ }
+ b0 := b[0]
+ if b0 < hangulBase0 {
+ return false
+ }
+ b1 := b[1]
+ switch {
+ case b0 == hangulBase0:
+ return b1 >= hangulBase1
+ case b0 < hangulEnd0:
+ return true
+ case b0 > hangulEnd0:
+ return false
+ case b1 < hangulEnd1:
+ return true
+ }
+ return b1 == hangulEnd1 && b[2] < hangulEnd2
+}
+
+// Caller must ensure len(b) >= 2.
+func isJamoVT(b []byte) bool {
+ // True if (rune & 0xff00) == jamoLBase
+ return b[0] == jamoLBase0 && (b[1]&0xFC) == jamoLBase1
+}
+
+func isHangulWithoutJamoT(b []byte) bool {
+ c, _ := utf8.DecodeRune(b)
+ c -= hangulBase
+ return c < jamoLVTCount && c%jamoTCount == 0
+}
+
+// decomposeHangul writes the decomposed Hangul to buf and returns the number
+// of bytes written. len(buf) should be at least 9.
+func decomposeHangul(buf []byte, r rune) int {
+ const JamoUTF8Len = 3
+ r -= hangulBase
+ x := r % jamoTCount
+ r /= jamoTCount
+ utf8.EncodeRune(buf, jamoLBase+r/jamoVCount)
+ utf8.EncodeRune(buf[JamoUTF8Len:], jamoVBase+r%jamoVCount)
+ if x != 0 {
+ utf8.EncodeRune(buf[2*JamoUTF8Len:], jamoTBase+x)
+ return 3 * JamoUTF8Len
+ }
+ return 2 * JamoUTF8Len
+}
+
+// decomposeHangul algorithmically decomposes a Hangul rune into
+// its Jamo components.
+// See http://unicode.org/reports/tr15/#Hangul for details on decomposing Hangul.
+func (rb *reorderBuffer) decomposeHangul(r rune) {
+ r -= hangulBase
+ x := r % jamoTCount
+ r /= jamoTCount
+ rb.appendRune(jamoLBase + r/jamoVCount)
+ rb.appendRune(jamoVBase + r%jamoVCount)
+ if x != 0 {
+ rb.appendRune(jamoTBase + x)
+ }
+}
+
+// combineHangul algorithmically combines Jamo character components into Hangul.
+// See http://unicode.org/reports/tr15/#Hangul for details on combining Hangul.
+func (rb *reorderBuffer) combineHangul(s, i, k int) {
+ b := rb.rune[:]
+ bn := rb.nrune
+ for ; i < bn; i++ {
+ cccB := b[k-1].ccc
+ cccC := b[i].ccc
+ if cccB == 0 {
+ s = k - 1
+ }
+ if s != k-1 && cccB >= cccC {
+ // b[i] is blocked by greater-equal cccX below it
+ b[k] = b[i]
+ k++
+ } else {
+ l := rb.runeAt(s) // also used to compare to hangulBase
+ v := rb.runeAt(i) // also used to compare to jamoT
+ switch {
+ case jamoLBase <= l && l < jamoLEnd &&
+ jamoVBase <= v && v < jamoVEnd:
+ // 11xx plus 116x to LV
+ rb.assignRune(s, hangulBase+
+ (l-jamoLBase)*jamoVTCount+(v-jamoVBase)*jamoTCount)
+ case hangulBase <= l && l < hangulEnd &&
+ jamoTBase < v && v < jamoTEnd &&
+ ((l-hangulBase)%jamoTCount) == 0:
+ // ACxx plus 11Ax to LVT
+ rb.assignRune(s, l+v-jamoTBase)
+ default:
+ b[k] = b[i]
+ k++
+ }
+ }
+ }
+ rb.nrune = k
+}
+
+// compose recombines the runes in the buffer.
+// It should only be used to recompose a single segment, as it will not
+// handle alternations between Hangul and non-Hangul characters correctly.
+func (rb *reorderBuffer) compose() {
+ // UAX #15, section X5 , including Corrigendum #5
+ // "In any character sequence beginning with starter S, a character C is
+ // blocked from S if and only if there is some character B between S
+ // and C, and either B is a starter or it has the same or higher
+ // combining class as C."
+ bn := rb.nrune
+ if bn == 0 {
+ return
+ }
+ k := 1
+ b := rb.rune[:]
+ for s, i := 0, 1; i < bn; i++ {
+ if isJamoVT(rb.bytesAt(i)) {
+ // Redo from start in Hangul mode. Necessary to support
+ // U+320E..U+321E in NFKC mode.
+ rb.combineHangul(s, i, k)
+ return
+ }
+ ii := b[i]
+ // We can only use combineForward as a filter if we later
+ // get the info for the combined character. This is more
+ // expensive than using the filter. Using combinesBackward()
+ // is safe.
+ if ii.combinesBackward() {
+ cccB := b[k-1].ccc
+ cccC := ii.ccc
+ blocked := false // b[i] blocked by starter or greater or equal CCC?
+ if cccB == 0 {
+ s = k - 1
+ } else {
+ blocked = s != k-1 && cccB >= cccC
+ }
+ if !blocked {
+ combined := combine(rb.runeAt(s), rb.runeAt(i))
+ if combined != 0 {
+ rb.assignRune(s, combined)
+ continue
+ }
+ }
+ }
+ b[k] = b[i]
+ k++
+ }
+ rb.nrune = k
+}
diff --git a/vendor/golang.org/x/text/unicode/norm/forminfo.go b/vendor/golang.org/x/text/unicode/norm/forminfo.go
new file mode 100644
index 0000000..e67e765
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/norm/forminfo.go
@@ -0,0 +1,259 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package norm
+
+// This file contains Form-specific logic and wrappers for data in tables.go.
+
+// Rune info is stored in a separate trie per composing form. A composing form
+// and its corresponding decomposing form share the same trie. Each trie maps
+// a rune to a uint16. The values take two forms. For v >= 0x8000:
+// bits
+// 15: 1 (inverse of NFD_QC bit of qcInfo)
+// 13..7: qcInfo (see below). isYesD is always true (no decompostion).
+// 6..0: ccc (compressed CCC value).
+// For v < 0x8000, the respective rune has a decomposition and v is an index
+// into a byte array of UTF-8 decomposition sequences and additional info and
+// has the form:
+// * [ []]
+// The header contains the number of bytes in the decomposition (excluding this
+// length byte). The two most significant bits of this length byte correspond
+// to bit 5 and 4 of qcInfo (see below). The byte sequence itself starts at v+1.
+// The byte sequence is followed by a trailing and leading CCC if the values
+// for these are not zero. The value of v determines which ccc are appended
+// to the sequences. For v < firstCCC, there are none, for v >= firstCCC,
+// the sequence is followed by a trailing ccc, and for v >= firstLeadingCC
+// there is an additional leading ccc. The value of tccc itself is the
+// trailing CCC shifted left 2 bits. The two least-significant bits of tccc
+// are the number of trailing non-starters.
+
+const (
+ qcInfoMask = 0x3F // to clear all but the relevant bits in a qcInfo
+ headerLenMask = 0x3F // extract the length value from the header byte
+ headerFlagsMask = 0xC0 // extract the qcInfo bits from the header byte
+)
+
+// Properties provides access to normalization properties of a rune.
+type Properties struct {
+ pos uint8 // start position in reorderBuffer; used in composition.go
+ size uint8 // length of UTF-8 encoding of this rune
+ ccc uint8 // leading canonical combining class (ccc if not decomposition)
+ tccc uint8 // trailing canonical combining class (ccc if not decomposition)
+ nLead uint8 // number of leading non-starters.
+ flags qcInfo // quick check flags
+ index uint16
+}
+
+// functions dispatchable per form
+type lookupFunc func(b input, i int) Properties
+
+// formInfo holds Form-specific functions and tables.
+type formInfo struct {
+ form Form
+ composing, compatibility bool // form type
+ info lookupFunc
+ nextMain iterFunc
+}
+
+var formTable = []*formInfo{{
+ form: NFC,
+ composing: true,
+ compatibility: false,
+ info: lookupInfoNFC,
+ nextMain: nextComposed,
+}, {
+ form: NFD,
+ composing: false,
+ compatibility: false,
+ info: lookupInfoNFC,
+ nextMain: nextDecomposed,
+}, {
+ form: NFKC,
+ composing: true,
+ compatibility: true,
+ info: lookupInfoNFKC,
+ nextMain: nextComposed,
+}, {
+ form: NFKD,
+ composing: false,
+ compatibility: true,
+ info: lookupInfoNFKC,
+ nextMain: nextDecomposed,
+}}
+
+// We do not distinguish between boundaries for NFC, NFD, etc. to avoid
+// unexpected behavior for the user. For example, in NFD, there is a boundary
+// after 'a'. However, 'a' might combine with modifiers, so from the application's
+// perspective it is not a good boundary. We will therefore always use the
+// boundaries for the combining variants.
+
+// BoundaryBefore returns true if this rune starts a new segment and
+// cannot combine with any rune on the left.
+func (p Properties) BoundaryBefore() bool {
+ if p.ccc == 0 && !p.combinesBackward() {
+ return true
+ }
+ // We assume that the CCC of the first character in a decomposition
+ // is always non-zero if different from info.ccc and that we can return
+ // false at this point. This is verified by maketables.
+ return false
+}
+
+// BoundaryAfter returns true if runes cannot combine with or otherwise
+// interact with this or previous runes.
+func (p Properties) BoundaryAfter() bool {
+ // TODO: loosen these conditions.
+ return p.isInert()
+}
+
+// We pack quick check data in 4 bits:
+// 5: Combines forward (0 == false, 1 == true)
+// 4..3: NFC_QC Yes(00), No (10), or Maybe (11)
+// 2: NFD_QC Yes (0) or No (1). No also means there is a decomposition.
+// 1..0: Number of trailing non-starters.
+//
+// When all 4 bits are zero, the character is inert, meaning it is never
+// influenced by normalization.
+type qcInfo uint8
+
+func (p Properties) isYesC() bool { return p.flags&0x10 == 0 }
+func (p Properties) isYesD() bool { return p.flags&0x4 == 0 }
+
+func (p Properties) combinesForward() bool { return p.flags&0x20 != 0 }
+func (p Properties) combinesBackward() bool { return p.flags&0x8 != 0 } // == isMaybe
+func (p Properties) hasDecomposition() bool { return p.flags&0x4 != 0 } // == isNoD
+
+func (p Properties) isInert() bool {
+ return p.flags&qcInfoMask == 0 && p.ccc == 0
+}
+
+func (p Properties) multiSegment() bool {
+ return p.index >= firstMulti && p.index < endMulti
+}
+
+func (p Properties) nLeadingNonStarters() uint8 {
+ return p.nLead
+}
+
+func (p Properties) nTrailingNonStarters() uint8 {
+ return uint8(p.flags & 0x03)
+}
+
+// Decomposition returns the decomposition for the underlying rune
+// or nil if there is none.
+func (p Properties) Decomposition() []byte {
+ // TODO: create the decomposition for Hangul?
+ if p.index == 0 {
+ return nil
+ }
+ i := p.index
+ n := decomps[i] & headerLenMask
+ i++
+ return decomps[i : i+uint16(n)]
+}
+
+// Size returns the length of UTF-8 encoding of the rune.
+func (p Properties) Size() int {
+ return int(p.size)
+}
+
+// CCC returns the canonical combining class of the underlying rune.
+func (p Properties) CCC() uint8 {
+ if p.index >= firstCCCZeroExcept {
+ return 0
+ }
+ return ccc[p.ccc]
+}
+
+// LeadCCC returns the CCC of the first rune in the decomposition.
+// If there is no decomposition, LeadCCC equals CCC.
+func (p Properties) LeadCCC() uint8 {
+ return ccc[p.ccc]
+}
+
+// TrailCCC returns the CCC of the last rune in the decomposition.
+// If there is no decomposition, TrailCCC equals CCC.
+func (p Properties) TrailCCC() uint8 {
+ return ccc[p.tccc]
+}
+
+// Recomposition
+// We use 32-bit keys instead of 64-bit for the two codepoint keys.
+// This clips off the bits of three entries, but we know this will not
+// result in a collision. In the unlikely event that changes to
+// UnicodeData.txt introduce collisions, the compiler will catch it.
+// Note that the recomposition map for NFC and NFKC are identical.
+
+// combine returns the combined rune or 0 if it doesn't exist.
+func combine(a, b rune) rune {
+ key := uint32(uint16(a))<<16 + uint32(uint16(b))
+ return recompMap[key]
+}
+
+func lookupInfoNFC(b input, i int) Properties {
+ v, sz := b.charinfoNFC(i)
+ return compInfo(v, sz)
+}
+
+func lookupInfoNFKC(b input, i int) Properties {
+ v, sz := b.charinfoNFKC(i)
+ return compInfo(v, sz)
+}
+
+// Properties returns properties for the first rune in s.
+func (f Form) Properties(s []byte) Properties {
+ if f == NFC || f == NFD {
+ return compInfo(nfcData.lookup(s))
+ }
+ return compInfo(nfkcData.lookup(s))
+}
+
+// PropertiesString returns properties for the first rune in s.
+func (f Form) PropertiesString(s string) Properties {
+ if f == NFC || f == NFD {
+ return compInfo(nfcData.lookupString(s))
+ }
+ return compInfo(nfkcData.lookupString(s))
+}
+
+// compInfo converts the information contained in v and sz
+// to a Properties. See the comment at the top of the file
+// for more information on the format.
+func compInfo(v uint16, sz int) Properties {
+ if v == 0 {
+ return Properties{size: uint8(sz)}
+ } else if v >= 0x8000 {
+ p := Properties{
+ size: uint8(sz),
+ ccc: uint8(v),
+ tccc: uint8(v),
+ flags: qcInfo(v >> 8),
+ }
+ if p.ccc > 0 || p.combinesBackward() {
+ p.nLead = uint8(p.flags & 0x3)
+ }
+ return p
+ }
+ // has decomposition
+ h := decomps[v]
+ f := (qcInfo(h&headerFlagsMask) >> 2) | 0x4
+ p := Properties{size: uint8(sz), flags: f, index: v}
+ if v >= firstCCC {
+ v += uint16(h&headerLenMask) + 1
+ c := decomps[v]
+ p.tccc = c >> 2
+ p.flags |= qcInfo(c & 0x3)
+ if v >= firstLeadingCCC {
+ p.nLead = c & 0x3
+ if v >= firstStarterWithNLead {
+ // We were tricked. Remove the decomposition.
+ p.flags &= 0x03
+ p.index = 0
+ return p
+ }
+ p.ccc = decomps[v+1]
+ }
+ }
+ return p
+}
diff --git a/vendor/golang.org/x/text/unicode/norm/input.go b/vendor/golang.org/x/text/unicode/norm/input.go
new file mode 100644
index 0000000..479e35b
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/norm/input.go
@@ -0,0 +1,109 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package norm
+
+import "unicode/utf8"
+
+type input struct {
+ str string
+ bytes []byte
+}
+
+func inputBytes(str []byte) input {
+ return input{bytes: str}
+}
+
+func inputString(str string) input {
+ return input{str: str}
+}
+
+func (in *input) setBytes(str []byte) {
+ in.str = ""
+ in.bytes = str
+}
+
+func (in *input) setString(str string) {
+ in.str = str
+ in.bytes = nil
+}
+
+func (in *input) _byte(p int) byte {
+ if in.bytes == nil {
+ return in.str[p]
+ }
+ return in.bytes[p]
+}
+
+func (in *input) skipASCII(p, max int) int {
+ if in.bytes == nil {
+ for ; p < max && in.str[p] < utf8.RuneSelf; p++ {
+ }
+ } else {
+ for ; p < max && in.bytes[p] < utf8.RuneSelf; p++ {
+ }
+ }
+ return p
+}
+
+func (in *input) skipContinuationBytes(p int) int {
+ if in.bytes == nil {
+ for ; p < len(in.str) && !utf8.RuneStart(in.str[p]); p++ {
+ }
+ } else {
+ for ; p < len(in.bytes) && !utf8.RuneStart(in.bytes[p]); p++ {
+ }
+ }
+ return p
+}
+
+func (in *input) appendSlice(buf []byte, b, e int) []byte {
+ if in.bytes != nil {
+ return append(buf, in.bytes[b:e]...)
+ }
+ for i := b; i < e; i++ {
+ buf = append(buf, in.str[i])
+ }
+ return buf
+}
+
+func (in *input) copySlice(buf []byte, b, e int) int {
+ if in.bytes == nil {
+ return copy(buf, in.str[b:e])
+ }
+ return copy(buf, in.bytes[b:e])
+}
+
+func (in *input) charinfoNFC(p int) (uint16, int) {
+ if in.bytes == nil {
+ return nfcData.lookupString(in.str[p:])
+ }
+ return nfcData.lookup(in.bytes[p:])
+}
+
+func (in *input) charinfoNFKC(p int) (uint16, int) {
+ if in.bytes == nil {
+ return nfkcData.lookupString(in.str[p:])
+ }
+ return nfkcData.lookup(in.bytes[p:])
+}
+
+func (in *input) hangul(p int) (r rune) {
+ var size int
+ if in.bytes == nil {
+ if !isHangulString(in.str[p:]) {
+ return 0
+ }
+ r, size = utf8.DecodeRuneInString(in.str[p:])
+ } else {
+ if !isHangul(in.bytes[p:]) {
+ return 0
+ }
+ r, size = utf8.DecodeRune(in.bytes[p:])
+ }
+ if size != hangulUTF8Size {
+ return 0
+ }
+ return r
+}
diff --git a/vendor/golang.org/x/text/unicode/norm/iter.go b/vendor/golang.org/x/text/unicode/norm/iter.go
new file mode 100644
index 0000000..ce17f96
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/norm/iter.go
@@ -0,0 +1,457 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package norm
+
+import (
+ "fmt"
+ "unicode/utf8"
+)
+
+// MaxSegmentSize is the maximum size of a byte buffer needed to consider any
+// sequence of starter and non-starter runes for the purpose of normalization.
+const MaxSegmentSize = maxByteBufferSize
+
+// An Iter iterates over a string or byte slice, while normalizing it
+// to a given Form.
+type Iter struct {
+ rb reorderBuffer
+ buf [maxByteBufferSize]byte
+ info Properties // first character saved from previous iteration
+ next iterFunc // implementation of next depends on form
+ asciiF iterFunc
+
+ p int // current position in input source
+ multiSeg []byte // remainder of multi-segment decomposition
+}
+
+type iterFunc func(*Iter) []byte
+
+// Init initializes i to iterate over src after normalizing it to Form f.
+func (i *Iter) Init(f Form, src []byte) {
+ i.p = 0
+ if len(src) == 0 {
+ i.setDone()
+ i.rb.nsrc = 0
+ return
+ }
+ i.multiSeg = nil
+ i.rb.init(f, src)
+ i.next = i.rb.f.nextMain
+ i.asciiF = nextASCIIBytes
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ i.rb.ss.first(i.info)
+}
+
+// InitString initializes i to iterate over src after normalizing it to Form f.
+func (i *Iter) InitString(f Form, src string) {
+ i.p = 0
+ if len(src) == 0 {
+ i.setDone()
+ i.rb.nsrc = 0
+ return
+ }
+ i.multiSeg = nil
+ i.rb.initString(f, src)
+ i.next = i.rb.f.nextMain
+ i.asciiF = nextASCIIString
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ i.rb.ss.first(i.info)
+}
+
+// Seek sets the segment to be returned by the next call to Next to start
+// at position p. It is the responsibility of the caller to set p to the
+// start of a segment.
+func (i *Iter) Seek(offset int64, whence int) (int64, error) {
+ var abs int64
+ switch whence {
+ case 0:
+ abs = offset
+ case 1:
+ abs = int64(i.p) + offset
+ case 2:
+ abs = int64(i.rb.nsrc) + offset
+ default:
+ return 0, fmt.Errorf("norm: invalid whence")
+ }
+ if abs < 0 {
+ return 0, fmt.Errorf("norm: negative position")
+ }
+ if int(abs) >= i.rb.nsrc {
+ i.setDone()
+ return int64(i.p), nil
+ }
+ i.p = int(abs)
+ i.multiSeg = nil
+ i.next = i.rb.f.nextMain
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ i.rb.ss.first(i.info)
+ return abs, nil
+}
+
+// returnSlice returns a slice of the underlying input type as a byte slice.
+// If the underlying is of type []byte, it will simply return a slice.
+// If the underlying is of type string, it will copy the slice to the buffer
+// and return that.
+func (i *Iter) returnSlice(a, b int) []byte {
+ if i.rb.src.bytes == nil {
+ return i.buf[:copy(i.buf[:], i.rb.src.str[a:b])]
+ }
+ return i.rb.src.bytes[a:b]
+}
+
+// Pos returns the byte position at which the next call to Next will commence processing.
+func (i *Iter) Pos() int {
+ return i.p
+}
+
+func (i *Iter) setDone() {
+ i.next = nextDone
+ i.p = i.rb.nsrc
+}
+
+// Done returns true if there is no more input to process.
+func (i *Iter) Done() bool {
+ return i.p >= i.rb.nsrc
+}
+
+// Next returns f(i.input[i.Pos():n]), where n is a boundary of i.input.
+// For any input a and b for which f(a) == f(b), subsequent calls
+// to Next will return the same segments.
+// Modifying runes are grouped together with the preceding starter, if such a starter exists.
+// Although not guaranteed, n will typically be the smallest possible n.
+func (i *Iter) Next() []byte {
+ return i.next(i)
+}
+
+func nextASCIIBytes(i *Iter) []byte {
+ p := i.p + 1
+ if p >= i.rb.nsrc {
+ i.setDone()
+ return i.rb.src.bytes[i.p:p]
+ }
+ if i.rb.src.bytes[p] < utf8.RuneSelf {
+ p0 := i.p
+ i.p = p
+ return i.rb.src.bytes[p0:p]
+ }
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ i.next = i.rb.f.nextMain
+ return i.next(i)
+}
+
+func nextASCIIString(i *Iter) []byte {
+ p := i.p + 1
+ if p >= i.rb.nsrc {
+ i.buf[0] = i.rb.src.str[i.p]
+ i.setDone()
+ return i.buf[:1]
+ }
+ if i.rb.src.str[p] < utf8.RuneSelf {
+ i.buf[0] = i.rb.src.str[i.p]
+ i.p = p
+ return i.buf[:1]
+ }
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ i.next = i.rb.f.nextMain
+ return i.next(i)
+}
+
+func nextHangul(i *Iter) []byte {
+ p := i.p
+ next := p + hangulUTF8Size
+ if next >= i.rb.nsrc {
+ i.setDone()
+ } else if i.rb.src.hangul(next) == 0 {
+ i.rb.ss.next(i.info)
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ i.next = i.rb.f.nextMain
+ return i.next(i)
+ }
+ i.p = next
+ return i.buf[:decomposeHangul(i.buf[:], i.rb.src.hangul(p))]
+}
+
+func nextDone(i *Iter) []byte {
+ return nil
+}
+
+// nextMulti is used for iterating over multi-segment decompositions
+// for decomposing normal forms.
+func nextMulti(i *Iter) []byte {
+ j := 0
+ d := i.multiSeg
+ // skip first rune
+ for j = 1; j < len(d) && !utf8.RuneStart(d[j]); j++ {
+ }
+ for j < len(d) {
+ info := i.rb.f.info(input{bytes: d}, j)
+ if info.BoundaryBefore() {
+ i.multiSeg = d[j:]
+ return d[:j]
+ }
+ j += int(info.size)
+ }
+ // treat last segment as normal decomposition
+ i.next = i.rb.f.nextMain
+ return i.next(i)
+}
+
+// nextMultiNorm is used for iterating over multi-segment decompositions
+// for composing normal forms.
+func nextMultiNorm(i *Iter) []byte {
+ j := 0
+ d := i.multiSeg
+ for j < len(d) {
+ info := i.rb.f.info(input{bytes: d}, j)
+ if info.BoundaryBefore() {
+ i.rb.compose()
+ seg := i.buf[:i.rb.flushCopy(i.buf[:])]
+ i.rb.insertUnsafe(input{bytes: d}, j, info)
+ i.multiSeg = d[j+int(info.size):]
+ return seg
+ }
+ i.rb.insertUnsafe(input{bytes: d}, j, info)
+ j += int(info.size)
+ }
+ i.multiSeg = nil
+ i.next = nextComposed
+ return doNormComposed(i)
+}
+
+// nextDecomposed is the implementation of Next for forms NFD and NFKD.
+func nextDecomposed(i *Iter) (next []byte) {
+ outp := 0
+ inCopyStart, outCopyStart := i.p, 0
+ for {
+ if sz := int(i.info.size); sz <= 1 {
+ i.rb.ss = 0
+ p := i.p
+ i.p++ // ASCII or illegal byte. Either way, advance by 1.
+ if i.p >= i.rb.nsrc {
+ i.setDone()
+ return i.returnSlice(p, i.p)
+ } else if i.rb.src._byte(i.p) < utf8.RuneSelf {
+ i.next = i.asciiF
+ return i.returnSlice(p, i.p)
+ }
+ outp++
+ } else if d := i.info.Decomposition(); d != nil {
+ // Note: If leading CCC != 0, then len(d) == 2 and last is also non-zero.
+ // Case 1: there is a leftover to copy. In this case the decomposition
+ // must begin with a modifier and should always be appended.
+ // Case 2: no leftover. Simply return d if followed by a ccc == 0 value.
+ p := outp + len(d)
+ if outp > 0 {
+ i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
+ // TODO: this condition should not be possible, but we leave it
+ // in for defensive purposes.
+ if p > len(i.buf) {
+ return i.buf[:outp]
+ }
+ } else if i.info.multiSegment() {
+ // outp must be 0 as multi-segment decompositions always
+ // start a new segment.
+ if i.multiSeg == nil {
+ i.multiSeg = d
+ i.next = nextMulti
+ return nextMulti(i)
+ }
+ // We are in the last segment. Treat as normal decomposition.
+ d = i.multiSeg
+ i.multiSeg = nil
+ p = len(d)
+ }
+ prevCC := i.info.tccc
+ if i.p += sz; i.p >= i.rb.nsrc {
+ i.setDone()
+ i.info = Properties{} // Force BoundaryBefore to succeed.
+ } else {
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ }
+ switch i.rb.ss.next(i.info) {
+ case ssOverflow:
+ i.next = nextCGJDecompose
+ fallthrough
+ case ssStarter:
+ if outp > 0 {
+ copy(i.buf[outp:], d)
+ return i.buf[:p]
+ }
+ return d
+ }
+ copy(i.buf[outp:], d)
+ outp = p
+ inCopyStart, outCopyStart = i.p, outp
+ if i.info.ccc < prevCC {
+ goto doNorm
+ }
+ continue
+ } else if r := i.rb.src.hangul(i.p); r != 0 {
+ outp = decomposeHangul(i.buf[:], r)
+ i.p += hangulUTF8Size
+ inCopyStart, outCopyStart = i.p, outp
+ if i.p >= i.rb.nsrc {
+ i.setDone()
+ break
+ } else if i.rb.src.hangul(i.p) != 0 {
+ i.next = nextHangul
+ return i.buf[:outp]
+ }
+ } else {
+ p := outp + sz
+ if p > len(i.buf) {
+ break
+ }
+ outp = p
+ i.p += sz
+ }
+ if i.p >= i.rb.nsrc {
+ i.setDone()
+ break
+ }
+ prevCC := i.info.tccc
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ if v := i.rb.ss.next(i.info); v == ssStarter {
+ break
+ } else if v == ssOverflow {
+ i.next = nextCGJDecompose
+ break
+ }
+ if i.info.ccc < prevCC {
+ goto doNorm
+ }
+ }
+ if outCopyStart == 0 {
+ return i.returnSlice(inCopyStart, i.p)
+ } else if inCopyStart < i.p {
+ i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
+ }
+ return i.buf[:outp]
+doNorm:
+ // Insert what we have decomposed so far in the reorderBuffer.
+ // As we will only reorder, there will always be enough room.
+ i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
+ i.rb.insertDecomposed(i.buf[0:outp])
+ return doNormDecomposed(i)
+}
+
+func doNormDecomposed(i *Iter) []byte {
+ for {
+ i.rb.insertUnsafe(i.rb.src, i.p, i.info)
+ if i.p += int(i.info.size); i.p >= i.rb.nsrc {
+ i.setDone()
+ break
+ }
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ if i.info.ccc == 0 {
+ break
+ }
+ if s := i.rb.ss.next(i.info); s == ssOverflow {
+ i.next = nextCGJDecompose
+ break
+ }
+ }
+ // new segment or too many combining characters: exit normalization
+ return i.buf[:i.rb.flushCopy(i.buf[:])]
+}
+
+func nextCGJDecompose(i *Iter) []byte {
+ i.rb.ss = 0
+ i.rb.insertCGJ()
+ i.next = nextDecomposed
+ i.rb.ss.first(i.info)
+ buf := doNormDecomposed(i)
+ return buf
+}
+
+// nextComposed is the implementation of Next for forms NFC and NFKC.
+func nextComposed(i *Iter) []byte {
+ outp, startp := 0, i.p
+ var prevCC uint8
+ for {
+ if !i.info.isYesC() {
+ goto doNorm
+ }
+ prevCC = i.info.tccc
+ sz := int(i.info.size)
+ if sz == 0 {
+ sz = 1 // illegal rune: copy byte-by-byte
+ }
+ p := outp + sz
+ if p > len(i.buf) {
+ break
+ }
+ outp = p
+ i.p += sz
+ if i.p >= i.rb.nsrc {
+ i.setDone()
+ break
+ } else if i.rb.src._byte(i.p) < utf8.RuneSelf {
+ i.rb.ss = 0
+ i.next = i.asciiF
+ break
+ }
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ if v := i.rb.ss.next(i.info); v == ssStarter {
+ break
+ } else if v == ssOverflow {
+ i.next = nextCGJCompose
+ break
+ }
+ if i.info.ccc < prevCC {
+ goto doNorm
+ }
+ }
+ return i.returnSlice(startp, i.p)
+doNorm:
+ // reset to start position
+ i.p = startp
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ i.rb.ss.first(i.info)
+ if i.info.multiSegment() {
+ d := i.info.Decomposition()
+ info := i.rb.f.info(input{bytes: d}, 0)
+ i.rb.insertUnsafe(input{bytes: d}, 0, info)
+ i.multiSeg = d[int(info.size):]
+ i.next = nextMultiNorm
+ return nextMultiNorm(i)
+ }
+ i.rb.ss.first(i.info)
+ i.rb.insertUnsafe(i.rb.src, i.p, i.info)
+ return doNormComposed(i)
+}
+
+func doNormComposed(i *Iter) []byte {
+ // First rune should already be inserted.
+ for {
+ if i.p += int(i.info.size); i.p >= i.rb.nsrc {
+ i.setDone()
+ break
+ }
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ if s := i.rb.ss.next(i.info); s == ssStarter {
+ break
+ } else if s == ssOverflow {
+ i.next = nextCGJCompose
+ break
+ }
+ i.rb.insertUnsafe(i.rb.src, i.p, i.info)
+ }
+ i.rb.compose()
+ seg := i.buf[:i.rb.flushCopy(i.buf[:])]
+ return seg
+}
+
+func nextCGJCompose(i *Iter) []byte {
+ i.rb.ss = 0 // instead of first
+ i.rb.insertCGJ()
+ i.next = nextComposed
+ // Note that we treat any rune with nLeadingNonStarters > 0 as a non-starter,
+ // even if they are not. This is particularly dubious for U+FF9E and UFF9A.
+ // If we ever change that, insert a check here.
+ i.rb.ss.first(i.info)
+ i.rb.insertUnsafe(i.rb.src, i.p, i.info)
+ return doNormComposed(i)
+}
diff --git a/vendor/golang.org/x/text/unicode/norm/maketables.go b/vendor/golang.org/x/text/unicode/norm/maketables.go
new file mode 100644
index 0000000..8d41816
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/norm/maketables.go
@@ -0,0 +1,976 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// Normalization table generator.
+// Data read from the web.
+// See forminfo.go for a description of the trie values associated with each rune.
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "io"
+ "log"
+ "sort"
+ "strconv"
+ "strings"
+
+ "golang.org/x/text/internal/gen"
+ "golang.org/x/text/internal/triegen"
+ "golang.org/x/text/internal/ucd"
+)
+
+func main() {
+ gen.Init()
+ loadUnicodeData()
+ compactCCC()
+ loadCompositionExclusions()
+ completeCharFields(FCanonical)
+ completeCharFields(FCompatibility)
+ computeNonStarterCounts()
+ verifyComputed()
+ printChars()
+ testDerived()
+ printTestdata()
+ makeTables()
+}
+
+var (
+ tablelist = flag.String("tables",
+ "all",
+ "comma-separated list of which tables to generate; "+
+ "can be 'decomp', 'recomp', 'info' and 'all'")
+ test = flag.Bool("test",
+ false,
+ "test existing tables against DerivedNormalizationProps and generate test data for regression testing")
+ verbose = flag.Bool("verbose",
+ false,
+ "write data to stdout as it is parsed")
+)
+
+const MaxChar = 0x10FFFF // anything above this shouldn't exist
+
+// Quick Check properties of runes allow us to quickly
+// determine whether a rune may occur in a normal form.
+// For a given normal form, a rune may be guaranteed to occur
+// verbatim (QC=Yes), may or may not combine with another
+// rune (QC=Maybe), or may not occur (QC=No).
+type QCResult int
+
+const (
+ QCUnknown QCResult = iota
+ QCYes
+ QCNo
+ QCMaybe
+)
+
+func (r QCResult) String() string {
+ switch r {
+ case QCYes:
+ return "Yes"
+ case QCNo:
+ return "No"
+ case QCMaybe:
+ return "Maybe"
+ }
+ return "***UNKNOWN***"
+}
+
+const (
+ FCanonical = iota // NFC or NFD
+ FCompatibility // NFKC or NFKD
+ FNumberOfFormTypes
+)
+
+const (
+ MComposed = iota // NFC or NFKC
+ MDecomposed // NFD or NFKD
+ MNumberOfModes
+)
+
+// This contains only the properties we're interested in.
+type Char struct {
+ name string
+ codePoint rune // if zero, this index is not a valid code point.
+ ccc uint8 // canonical combining class
+ origCCC uint8
+ excludeInComp bool // from CompositionExclusions.txt
+ compatDecomp bool // it has a compatibility expansion
+
+ nTrailingNonStarters uint8
+ nLeadingNonStarters uint8 // must be equal to trailing if non-zero
+
+ forms [FNumberOfFormTypes]FormInfo // For FCanonical and FCompatibility
+
+ state State
+}
+
+var chars = make([]Char, MaxChar+1)
+var cccMap = make(map[uint8]uint8)
+
+func (c Char) String() string {
+ buf := new(bytes.Buffer)
+
+ fmt.Fprintf(buf, "%U [%s]:\n", c.codePoint, c.name)
+ fmt.Fprintf(buf, " ccc: %v\n", c.ccc)
+ fmt.Fprintf(buf, " excludeInComp: %v\n", c.excludeInComp)
+ fmt.Fprintf(buf, " compatDecomp: %v\n", c.compatDecomp)
+ fmt.Fprintf(buf, " state: %v\n", c.state)
+ fmt.Fprintf(buf, " NFC:\n")
+ fmt.Fprint(buf, c.forms[FCanonical])
+ fmt.Fprintf(buf, " NFKC:\n")
+ fmt.Fprint(buf, c.forms[FCompatibility])
+
+ return buf.String()
+}
+
+// In UnicodeData.txt, some ranges are marked like this:
+// 3400;;Lo;0;L;;;;;N;;;;;
+// 4DB5;;Lo;0;L;;;;;N;;;;;
+// parseCharacter keeps a state variable indicating the weirdness.
+type State int
+
+const (
+ SNormal State = iota // known to be zero for the type
+ SFirst
+ SLast
+ SMissing
+)
+
+var lastChar = rune('\u0000')
+
+func (c Char) isValid() bool {
+ return c.codePoint != 0 && c.state != SMissing
+}
+
+type FormInfo struct {
+ quickCheck [MNumberOfModes]QCResult // index: MComposed or MDecomposed
+ verified [MNumberOfModes]bool // index: MComposed or MDecomposed
+
+ combinesForward bool // May combine with rune on the right
+ combinesBackward bool // May combine with rune on the left
+ isOneWay bool // Never appears in result
+ inDecomp bool // Some decompositions result in this char.
+ decomp Decomposition
+ expandedDecomp Decomposition
+}
+
+func (f FormInfo) String() string {
+ buf := bytes.NewBuffer(make([]byte, 0))
+
+ fmt.Fprintf(buf, " quickCheck[C]: %v\n", f.quickCheck[MComposed])
+ fmt.Fprintf(buf, " quickCheck[D]: %v\n", f.quickCheck[MDecomposed])
+ fmt.Fprintf(buf, " cmbForward: %v\n", f.combinesForward)
+ fmt.Fprintf(buf, " cmbBackward: %v\n", f.combinesBackward)
+ fmt.Fprintf(buf, " isOneWay: %v\n", f.isOneWay)
+ fmt.Fprintf(buf, " inDecomp: %v\n", f.inDecomp)
+ fmt.Fprintf(buf, " decomposition: %X\n", f.decomp)
+ fmt.Fprintf(buf, " expandedDecomp: %X\n", f.expandedDecomp)
+
+ return buf.String()
+}
+
+type Decomposition []rune
+
+func parseDecomposition(s string, skipfirst bool) (a []rune, err error) {
+ decomp := strings.Split(s, " ")
+ if len(decomp) > 0 && skipfirst {
+ decomp = decomp[1:]
+ }
+ for _, d := range decomp {
+ point, err := strconv.ParseUint(d, 16, 64)
+ if err != nil {
+ return a, err
+ }
+ a = append(a, rune(point))
+ }
+ return a, nil
+}
+
+func loadUnicodeData() {
+ f := gen.OpenUCDFile("UnicodeData.txt")
+ defer f.Close()
+ p := ucd.New(f)
+ for p.Next() {
+ r := p.Rune(ucd.CodePoint)
+ char := &chars[r]
+
+ char.ccc = uint8(p.Uint(ucd.CanonicalCombiningClass))
+ decmap := p.String(ucd.DecompMapping)
+
+ exp, err := parseDecomposition(decmap, false)
+ isCompat := false
+ if err != nil {
+ if len(decmap) > 0 {
+ exp, err = parseDecomposition(decmap, true)
+ if err != nil {
+ log.Fatalf(`%U: bad decomp |%v|: "%s"`, r, decmap, err)
+ }
+ isCompat = true
+ }
+ }
+
+ char.name = p.String(ucd.Name)
+ char.codePoint = r
+ char.forms[FCompatibility].decomp = exp
+ if !isCompat {
+ char.forms[FCanonical].decomp = exp
+ } else {
+ char.compatDecomp = true
+ }
+ if len(decmap) > 0 {
+ char.forms[FCompatibility].decomp = exp
+ }
+ }
+ if err := p.Err(); err != nil {
+ log.Fatal(err)
+ }
+}
+
+// compactCCC converts the sparse set of CCC values to a continguous one,
+// reducing the number of bits needed from 8 to 6.
+func compactCCC() {
+ m := make(map[uint8]uint8)
+ for i := range chars {
+ c := &chars[i]
+ m[c.ccc] = 0
+ }
+ cccs := []int{}
+ for v, _ := range m {
+ cccs = append(cccs, int(v))
+ }
+ sort.Ints(cccs)
+ for i, c := range cccs {
+ cccMap[uint8(i)] = uint8(c)
+ m[uint8(c)] = uint8(i)
+ }
+ for i := range chars {
+ c := &chars[i]
+ c.origCCC = c.ccc
+ c.ccc = m[c.ccc]
+ }
+ if len(m) >= 1<<6 {
+ log.Fatalf("too many difference CCC values: %d >= 64", len(m))
+ }
+}
+
+// CompositionExclusions.txt has form:
+// 0958 # ...
+// See http://unicode.org/reports/tr44/ for full explanation
+func loadCompositionExclusions() {
+ f := gen.OpenUCDFile("CompositionExclusions.txt")
+ defer f.Close()
+ p := ucd.New(f)
+ for p.Next() {
+ c := &chars[p.Rune(0)]
+ if c.excludeInComp {
+ log.Fatalf("%U: Duplicate entry in exclusions.", c.codePoint)
+ }
+ c.excludeInComp = true
+ }
+ if e := p.Err(); e != nil {
+ log.Fatal(e)
+ }
+}
+
+// hasCompatDecomp returns true if any of the recursive
+// decompositions contains a compatibility expansion.
+// In this case, the character may not occur in NFK*.
+func hasCompatDecomp(r rune) bool {
+ c := &chars[r]
+ if c.compatDecomp {
+ return true
+ }
+ for _, d := range c.forms[FCompatibility].decomp {
+ if hasCompatDecomp(d) {
+ return true
+ }
+ }
+ return false
+}
+
+// Hangul related constants.
+const (
+ HangulBase = 0xAC00
+ HangulEnd = 0xD7A4 // hangulBase + Jamo combinations (19 * 21 * 28)
+
+ JamoLBase = 0x1100
+ JamoLEnd = 0x1113
+ JamoVBase = 0x1161
+ JamoVEnd = 0x1176
+ JamoTBase = 0x11A8
+ JamoTEnd = 0x11C3
+
+ JamoLVTCount = 19 * 21 * 28
+ JamoTCount = 28
+)
+
+func isHangul(r rune) bool {
+ return HangulBase <= r && r < HangulEnd
+}
+
+func isHangulWithoutJamoT(r rune) bool {
+ if !isHangul(r) {
+ return false
+ }
+ r -= HangulBase
+ return r < JamoLVTCount && r%JamoTCount == 0
+}
+
+func ccc(r rune) uint8 {
+ return chars[r].ccc
+}
+
+// Insert a rune in a buffer, ordered by Canonical Combining Class.
+func insertOrdered(b Decomposition, r rune) Decomposition {
+ n := len(b)
+ b = append(b, 0)
+ cc := ccc(r)
+ if cc > 0 {
+ // Use bubble sort.
+ for ; n > 0; n-- {
+ if ccc(b[n-1]) <= cc {
+ break
+ }
+ b[n] = b[n-1]
+ }
+ }
+ b[n] = r
+ return b
+}
+
+// Recursively decompose.
+func decomposeRecursive(form int, r rune, d Decomposition) Decomposition {
+ dcomp := chars[r].forms[form].decomp
+ if len(dcomp) == 0 {
+ return insertOrdered(d, r)
+ }
+ for _, c := range dcomp {
+ d = decomposeRecursive(form, c, d)
+ }
+ return d
+}
+
+func completeCharFields(form int) {
+ // Phase 0: pre-expand decomposition.
+ for i := range chars {
+ f := &chars[i].forms[form]
+ if len(f.decomp) == 0 {
+ continue
+ }
+ exp := make(Decomposition, 0)
+ for _, c := range f.decomp {
+ exp = decomposeRecursive(form, c, exp)
+ }
+ f.expandedDecomp = exp
+ }
+
+ // Phase 1: composition exclusion, mark decomposition.
+ for i := range chars {
+ c := &chars[i]
+ f := &c.forms[form]
+
+ // Marks script-specific exclusions and version restricted.
+ f.isOneWay = c.excludeInComp
+
+ // Singletons
+ f.isOneWay = f.isOneWay || len(f.decomp) == 1
+
+ // Non-starter decompositions
+ if len(f.decomp) > 1 {
+ chk := c.ccc != 0 || chars[f.decomp[0]].ccc != 0
+ f.isOneWay = f.isOneWay || chk
+ }
+
+ // Runes that decompose into more than two runes.
+ f.isOneWay = f.isOneWay || len(f.decomp) > 2
+
+ if form == FCompatibility {
+ f.isOneWay = f.isOneWay || hasCompatDecomp(c.codePoint)
+ }
+
+ for _, r := range f.decomp {
+ chars[r].forms[form].inDecomp = true
+ }
+ }
+
+ // Phase 2: forward and backward combining.
+ for i := range chars {
+ c := &chars[i]
+ f := &c.forms[form]
+
+ if !f.isOneWay && len(f.decomp) == 2 {
+ f0 := &chars[f.decomp[0]].forms[form]
+ f1 := &chars[f.decomp[1]].forms[form]
+ if !f0.isOneWay {
+ f0.combinesForward = true
+ }
+ if !f1.isOneWay {
+ f1.combinesBackward = true
+ }
+ }
+ if isHangulWithoutJamoT(rune(i)) {
+ f.combinesForward = true
+ }
+ }
+
+ // Phase 3: quick check values.
+ for i := range chars {
+ c := &chars[i]
+ f := &c.forms[form]
+
+ switch {
+ case len(f.decomp) > 0:
+ f.quickCheck[MDecomposed] = QCNo
+ case isHangul(rune(i)):
+ f.quickCheck[MDecomposed] = QCNo
+ default:
+ f.quickCheck[MDecomposed] = QCYes
+ }
+ switch {
+ case f.isOneWay:
+ f.quickCheck[MComposed] = QCNo
+ case (i & 0xffff00) == JamoLBase:
+ f.quickCheck[MComposed] = QCYes
+ if JamoLBase <= i && i < JamoLEnd {
+ f.combinesForward = true
+ }
+ if JamoVBase <= i && i < JamoVEnd {
+ f.quickCheck[MComposed] = QCMaybe
+ f.combinesBackward = true
+ f.combinesForward = true
+ }
+ if JamoTBase <= i && i < JamoTEnd {
+ f.quickCheck[MComposed] = QCMaybe
+ f.combinesBackward = true
+ }
+ case !f.combinesBackward:
+ f.quickCheck[MComposed] = QCYes
+ default:
+ f.quickCheck[MComposed] = QCMaybe
+ }
+ }
+}
+
+func computeNonStarterCounts() {
+ // Phase 4: leading and trailing non-starter count
+ for i := range chars {
+ c := &chars[i]
+
+ runes := []rune{rune(i)}
+ // We always use FCompatibility so that the CGJ insertion points do not
+ // change for repeated normalizations with different forms.
+ if exp := c.forms[FCompatibility].expandedDecomp; len(exp) > 0 {
+ runes = exp
+ }
+ // We consider runes that combine backwards to be non-starters for the
+ // purpose of Stream-Safe Text Processing.
+ for _, r := range runes {
+ if cr := &chars[r]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward {
+ break
+ }
+ c.nLeadingNonStarters++
+ }
+ for i := len(runes) - 1; i >= 0; i-- {
+ if cr := &chars[runes[i]]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward {
+ break
+ }
+ c.nTrailingNonStarters++
+ }
+ if c.nTrailingNonStarters > 3 {
+ log.Fatalf("%U: Decomposition with more than 3 (%d) trailing modifiers (%U)", i, c.nTrailingNonStarters, runes)
+ }
+
+ if isHangul(rune(i)) {
+ c.nTrailingNonStarters = 2
+ if isHangulWithoutJamoT(rune(i)) {
+ c.nTrailingNonStarters = 1
+ }
+ }
+
+ if l, t := c.nLeadingNonStarters, c.nTrailingNonStarters; l > 0 && l != t {
+ log.Fatalf("%U: number of leading and trailing non-starters should be equal (%d vs %d)", i, l, t)
+ }
+ if t := c.nTrailingNonStarters; t > 3 {
+ log.Fatalf("%U: number of trailing non-starters is %d > 3", t)
+ }
+ }
+}
+
+func printBytes(w io.Writer, b []byte, name string) {
+ fmt.Fprintf(w, "// %s: %d bytes\n", name, len(b))
+ fmt.Fprintf(w, "var %s = [...]byte {", name)
+ for i, c := range b {
+ switch {
+ case i%64 == 0:
+ fmt.Fprintf(w, "\n// Bytes %x - %x\n", i, i+63)
+ case i%8 == 0:
+ fmt.Fprintf(w, "\n")
+ }
+ fmt.Fprintf(w, "0x%.2X, ", c)
+ }
+ fmt.Fprint(w, "\n}\n\n")
+}
+
+// See forminfo.go for format.
+func makeEntry(f *FormInfo, c *Char) uint16 {
+ e := uint16(0)
+ if r := c.codePoint; HangulBase <= r && r < HangulEnd {
+ e |= 0x40
+ }
+ if f.combinesForward {
+ e |= 0x20
+ }
+ if f.quickCheck[MDecomposed] == QCNo {
+ e |= 0x4
+ }
+ switch f.quickCheck[MComposed] {
+ case QCYes:
+ case QCNo:
+ e |= 0x10
+ case QCMaybe:
+ e |= 0x18
+ default:
+ log.Fatalf("Illegal quickcheck value %v.", f.quickCheck[MComposed])
+ }
+ e |= uint16(c.nTrailingNonStarters)
+ return e
+}
+
+// decompSet keeps track of unique decompositions, grouped by whether
+// the decomposition is followed by a trailing and/or leading CCC.
+type decompSet [7]map[string]bool
+
+const (
+ normalDecomp = iota
+ firstMulti
+ firstCCC
+ endMulti
+ firstLeadingCCC
+ firstCCCZeroExcept
+ firstStarterWithNLead
+ lastDecomp
+)
+
+var cname = []string{"firstMulti", "firstCCC", "endMulti", "firstLeadingCCC", "firstCCCZeroExcept", "firstStarterWithNLead", "lastDecomp"}
+
+func makeDecompSet() decompSet {
+ m := decompSet{}
+ for i := range m {
+ m[i] = make(map[string]bool)
+ }
+ return m
+}
+func (m *decompSet) insert(key int, s string) {
+ m[key][s] = true
+}
+
+func printCharInfoTables(w io.Writer) int {
+ mkstr := func(r rune, f *FormInfo) (int, string) {
+ d := f.expandedDecomp
+ s := string([]rune(d))
+ if max := 1 << 6; len(s) >= max {
+ const msg = "%U: too many bytes in decomposition: %d >= %d"
+ log.Fatalf(msg, r, len(s), max)
+ }
+ head := uint8(len(s))
+ if f.quickCheck[MComposed] != QCYes {
+ head |= 0x40
+ }
+ if f.combinesForward {
+ head |= 0x80
+ }
+ s = string([]byte{head}) + s
+
+ lccc := ccc(d[0])
+ tccc := ccc(d[len(d)-1])
+ cc := ccc(r)
+ if cc != 0 && lccc == 0 && tccc == 0 {
+ log.Fatalf("%U: trailing and leading ccc are 0 for non-zero ccc %d", r, cc)
+ }
+ if tccc < lccc && lccc != 0 {
+ const msg = "%U: lccc (%d) must be <= tcc (%d)"
+ log.Fatalf(msg, r, lccc, tccc)
+ }
+ index := normalDecomp
+ nTrail := chars[r].nTrailingNonStarters
+ nLead := chars[r].nLeadingNonStarters
+ if tccc > 0 || lccc > 0 || nTrail > 0 {
+ tccc <<= 2
+ tccc |= nTrail
+ s += string([]byte{tccc})
+ index = endMulti
+ for _, r := range d[1:] {
+ if ccc(r) == 0 {
+ index = firstCCC
+ }
+ }
+ if lccc > 0 || nLead > 0 {
+ s += string([]byte{lccc})
+ if index == firstCCC {
+ log.Fatalf("%U: multi-segment decomposition not supported for decompositions with leading CCC != 0", r)
+ }
+ index = firstLeadingCCC
+ }
+ if cc != lccc {
+ if cc != 0 {
+ log.Fatalf("%U: for lccc != ccc, expected ccc to be 0; was %d", r, cc)
+ }
+ index = firstCCCZeroExcept
+ }
+ } else if len(d) > 1 {
+ index = firstMulti
+ }
+ return index, s
+ }
+
+ decompSet := makeDecompSet()
+ const nLeadStr = "\x00\x01" // 0-byte length and tccc with nTrail.
+ decompSet.insert(firstStarterWithNLead, nLeadStr)
+
+ // Store the uniqued decompositions in a byte buffer,
+ // preceded by their byte length.
+ for _, c := range chars {
+ for _, f := range c.forms {
+ if len(f.expandedDecomp) == 0 {
+ continue
+ }
+ if f.combinesBackward {
+ log.Fatalf("%U: combinesBackward and decompose", c.codePoint)
+ }
+ index, s := mkstr(c.codePoint, &f)
+ decompSet.insert(index, s)
+ }
+ }
+
+ decompositions := bytes.NewBuffer(make([]byte, 0, 10000))
+ size := 0
+ positionMap := make(map[string]uint16)
+ decompositions.WriteString("\000")
+ fmt.Fprintln(w, "const (")
+ for i, m := range decompSet {
+ sa := []string{}
+ for s := range m {
+ sa = append(sa, s)
+ }
+ sort.Strings(sa)
+ for _, s := range sa {
+ p := decompositions.Len()
+ decompositions.WriteString(s)
+ positionMap[s] = uint16(p)
+ }
+ if cname[i] != "" {
+ fmt.Fprintf(w, "%s = 0x%X\n", cname[i], decompositions.Len())
+ }
+ }
+ fmt.Fprintln(w, "maxDecomp = 0x8000")
+ fmt.Fprintln(w, ")")
+ b := decompositions.Bytes()
+ printBytes(w, b, "decomps")
+ size += len(b)
+
+ varnames := []string{"nfc", "nfkc"}
+ for i := 0; i < FNumberOfFormTypes; i++ {
+ trie := triegen.NewTrie(varnames[i])
+
+ for r, c := range chars {
+ f := c.forms[i]
+ d := f.expandedDecomp
+ if len(d) != 0 {
+ _, key := mkstr(c.codePoint, &f)
+ trie.Insert(rune(r), uint64(positionMap[key]))
+ if c.ccc != ccc(d[0]) {
+ // We assume the lead ccc of a decomposition !=0 in this case.
+ if ccc(d[0]) == 0 {
+ log.Fatalf("Expected leading CCC to be non-zero; ccc is %d", c.ccc)
+ }
+ }
+ } else if c.nLeadingNonStarters > 0 && len(f.expandedDecomp) == 0 && c.ccc == 0 && !f.combinesBackward {
+ // Handle cases where it can't be detected that the nLead should be equal
+ // to nTrail.
+ trie.Insert(c.codePoint, uint64(positionMap[nLeadStr]))
+ } else if v := makeEntry(&f, &c)<<8 | uint16(c.ccc); v != 0 {
+ trie.Insert(c.codePoint, uint64(0x8000|v))
+ }
+ }
+ sz, err := trie.Gen(w, triegen.Compact(&normCompacter{name: varnames[i]}))
+ if err != nil {
+ log.Fatal(err)
+ }
+ size += sz
+ }
+ return size
+}
+
+func contains(sa []string, s string) bool {
+ for _, a := range sa {
+ if a == s {
+ return true
+ }
+ }
+ return false
+}
+
+func makeTables() {
+ w := &bytes.Buffer{}
+
+ size := 0
+ if *tablelist == "" {
+ return
+ }
+ list := strings.Split(*tablelist, ",")
+ if *tablelist == "all" {
+ list = []string{"recomp", "info"}
+ }
+
+ // Compute maximum decomposition size.
+ max := 0
+ for _, c := range chars {
+ if n := len(string(c.forms[FCompatibility].expandedDecomp)); n > max {
+ max = n
+ }
+ }
+
+ fmt.Fprintln(w, "const (")
+ fmt.Fprintln(w, "\t// Version is the Unicode edition from which the tables are derived.")
+ fmt.Fprintf(w, "\tVersion = %q\n", gen.UnicodeVersion())
+ fmt.Fprintln(w)
+ fmt.Fprintln(w, "\t// MaxTransformChunkSize indicates the maximum number of bytes that Transform")
+ fmt.Fprintln(w, "\t// may need to write atomically for any Form. Making a destination buffer at")
+ fmt.Fprintln(w, "\t// least this size ensures that Transform can always make progress and that")
+ fmt.Fprintln(w, "\t// the user does not need to grow the buffer on an ErrShortDst.")
+ fmt.Fprintf(w, "\tMaxTransformChunkSize = %d+maxNonStarters*4\n", len(string(0x034F))+max)
+ fmt.Fprintln(w, ")\n")
+
+ // Print the CCC remap table.
+ size += len(cccMap)
+ fmt.Fprintf(w, "var ccc = [%d]uint8{", len(cccMap))
+ for i := 0; i < len(cccMap); i++ {
+ if i%8 == 0 {
+ fmt.Fprintln(w)
+ }
+ fmt.Fprintf(w, "%3d, ", cccMap[uint8(i)])
+ }
+ fmt.Fprintln(w, "\n}\n")
+
+ if contains(list, "info") {
+ size += printCharInfoTables(w)
+ }
+
+ if contains(list, "recomp") {
+ // Note that we use 32 bit keys, instead of 64 bit.
+ // This clips the bits of three entries, but we know
+ // this won't cause a collision. The compiler will catch
+ // any changes made to UnicodeData.txt that introduces
+ // a collision.
+ // Note that the recomposition map for NFC and NFKC
+ // are identical.
+
+ // Recomposition map
+ nrentries := 0
+ for _, c := range chars {
+ f := c.forms[FCanonical]
+ if !f.isOneWay && len(f.decomp) > 0 {
+ nrentries++
+ }
+ }
+ sz := nrentries * 8
+ size += sz
+ fmt.Fprintf(w, "// recompMap: %d bytes (entries only)\n", sz)
+ fmt.Fprintln(w, "var recompMap = map[uint32]rune{")
+ for i, c := range chars {
+ f := c.forms[FCanonical]
+ d := f.decomp
+ if !f.isOneWay && len(d) > 0 {
+ key := uint32(uint16(d[0]))<<16 + uint32(uint16(d[1]))
+ fmt.Fprintf(w, "0x%.8X: 0x%.4X,\n", key, i)
+ }
+ }
+ fmt.Fprintf(w, "}\n\n")
+ }
+
+ fmt.Fprintf(w, "// Total size of tables: %dKB (%d bytes)\n", (size+512)/1024, size)
+ gen.WriteGoFile("tables.go", "norm", w.Bytes())
+}
+
+func printChars() {
+ if *verbose {
+ for _, c := range chars {
+ if !c.isValid() || c.state == SMissing {
+ continue
+ }
+ fmt.Println(c)
+ }
+ }
+}
+
+// verifyComputed does various consistency tests.
+func verifyComputed() {
+ for i, c := range chars {
+ for _, f := range c.forms {
+ isNo := (f.quickCheck[MDecomposed] == QCNo)
+ if (len(f.decomp) > 0) != isNo && !isHangul(rune(i)) {
+ log.Fatalf("%U: NF*D QC must be No if rune decomposes", i)
+ }
+
+ isMaybe := f.quickCheck[MComposed] == QCMaybe
+ if f.combinesBackward != isMaybe {
+ log.Fatalf("%U: NF*C QC must be Maybe if combinesBackward", i)
+ }
+ if len(f.decomp) > 0 && f.combinesForward && isMaybe {
+ log.Fatalf("%U: NF*C QC must be Yes or No if combinesForward and decomposes", i)
+ }
+
+ if len(f.expandedDecomp) != 0 {
+ continue
+ }
+ if a, b := c.nLeadingNonStarters > 0, (c.ccc > 0 || f.combinesBackward); a != b {
+ // We accept these runes to be treated differently (it only affects
+ // segment breaking in iteration, most likely on improper use), but
+ // reconsider if more characters are added.
+ // U+FF9E HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L; 3099;;;;N;;;;;
+ // U+FF9F HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L; 309A;;;;N;;;;;
+ // U+3133 HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;;
+ // U+318E HANGUL LETTER ARAEAE;Lo;0;L; 11A1;;;;N;HANGUL LETTER ALAE AE;;;;
+ // U+FFA3 HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L; 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;;
+ // U+FFDC HALFWIDTH HANGUL LETTER I;Lo;0;L; 3163;;;;N;;;;;
+ if i != 0xFF9E && i != 0xFF9F && !(0x3133 <= i && i <= 0x318E) && !(0xFFA3 <= i && i <= 0xFFDC) {
+ log.Fatalf("%U: nLead was %v; want %v", i, a, b)
+ }
+ }
+ }
+ nfc := c.forms[FCanonical]
+ nfkc := c.forms[FCompatibility]
+ if nfc.combinesBackward != nfkc.combinesBackward {
+ log.Fatalf("%U: Cannot combine combinesBackward\n", c.codePoint)
+ }
+ }
+}
+
+// Use values in DerivedNormalizationProps.txt to compare against the
+// values we computed.
+// DerivedNormalizationProps.txt has form:
+// 00C0..00C5 ; NFD_QC; N # ...
+// 0374 ; NFD_QC; N # ...
+// See http://unicode.org/reports/tr44/ for full explanation
+func testDerived() {
+ f := gen.OpenUCDFile("DerivedNormalizationProps.txt")
+ defer f.Close()
+ p := ucd.New(f)
+ for p.Next() {
+ r := p.Rune(0)
+ c := &chars[r]
+
+ var ftype, mode int
+ qt := p.String(1)
+ switch qt {
+ case "NFC_QC":
+ ftype, mode = FCanonical, MComposed
+ case "NFD_QC":
+ ftype, mode = FCanonical, MDecomposed
+ case "NFKC_QC":
+ ftype, mode = FCompatibility, MComposed
+ case "NFKD_QC":
+ ftype, mode = FCompatibility, MDecomposed
+ default:
+ continue
+ }
+ var qr QCResult
+ switch p.String(2) {
+ case "Y":
+ qr = QCYes
+ case "N":
+ qr = QCNo
+ case "M":
+ qr = QCMaybe
+ default:
+ log.Fatalf(`Unexpected quick check value "%s"`, p.String(2))
+ }
+ if got := c.forms[ftype].quickCheck[mode]; got != qr {
+ log.Printf("%U: FAILED %s (was %v need %v)\n", r, qt, got, qr)
+ }
+ c.forms[ftype].verified[mode] = true
+ }
+ if err := p.Err(); err != nil {
+ log.Fatal(err)
+ }
+ // Any unspecified value must be QCYes. Verify this.
+ for i, c := range chars {
+ for j, fd := range c.forms {
+ for k, qr := range fd.quickCheck {
+ if !fd.verified[k] && qr != QCYes {
+ m := "%U: FAIL F:%d M:%d (was %v need Yes) %s\n"
+ log.Printf(m, i, j, k, qr, c.name)
+ }
+ }
+ }
+ }
+}
+
+var testHeader = `const (
+ Yes = iota
+ No
+ Maybe
+)
+
+type formData struct {
+ qc uint8
+ combinesForward bool
+ decomposition string
+}
+
+type runeData struct {
+ r rune
+ ccc uint8
+ nLead uint8
+ nTrail uint8
+ f [2]formData // 0: canonical; 1: compatibility
+}
+
+func f(qc uint8, cf bool, dec string) [2]formData {
+ return [2]formData{{qc, cf, dec}, {qc, cf, dec}}
+}
+
+func g(qc, qck uint8, cf, cfk bool, d, dk string) [2]formData {
+ return [2]formData{{qc, cf, d}, {qck, cfk, dk}}
+}
+
+var testData = []runeData{
+`
+
+func printTestdata() {
+ type lastInfo struct {
+ ccc uint8
+ nLead uint8
+ nTrail uint8
+ f string
+ }
+
+ last := lastInfo{}
+ w := &bytes.Buffer{}
+ fmt.Fprintf(w, testHeader)
+ for r, c := range chars {
+ f := c.forms[FCanonical]
+ qc, cf, d := f.quickCheck[MComposed], f.combinesForward, string(f.expandedDecomp)
+ f = c.forms[FCompatibility]
+ qck, cfk, dk := f.quickCheck[MComposed], f.combinesForward, string(f.expandedDecomp)
+ s := ""
+ if d == dk && qc == qck && cf == cfk {
+ s = fmt.Sprintf("f(%s, %v, %q)", qc, cf, d)
+ } else {
+ s = fmt.Sprintf("g(%s, %s, %v, %v, %q, %q)", qc, qck, cf, cfk, d, dk)
+ }
+ current := lastInfo{c.ccc, c.nLeadingNonStarters, c.nTrailingNonStarters, s}
+ if last != current {
+ fmt.Fprintf(w, "\t{0x%x, %d, %d, %d, %s},\n", r, c.origCCC, c.nLeadingNonStarters, c.nTrailingNonStarters, s)
+ last = current
+ }
+ }
+ fmt.Fprintln(w, "}")
+ gen.WriteGoFile("data_test.go", "norm", w.Bytes())
+}
diff --git a/vendor/golang.org/x/text/unicode/norm/normalize.go b/vendor/golang.org/x/text/unicode/norm/normalize.go
new file mode 100644
index 0000000..e28ac64
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/norm/normalize.go
@@ -0,0 +1,609 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Note: the file data_test.go that is generated should not be checked in.
+//go:generate go run maketables.go triegen.go
+//go:generate go test -tags test
+
+// Package norm contains types and functions for normalizing Unicode strings.
+package norm // import "golang.org/x/text/unicode/norm"
+
+import (
+ "unicode/utf8"
+
+ "golang.org/x/text/transform"
+)
+
+// A Form denotes a canonical representation of Unicode code points.
+// The Unicode-defined normalization and equivalence forms are:
+//
+// NFC Unicode Normalization Form C
+// NFD Unicode Normalization Form D
+// NFKC Unicode Normalization Form KC
+// NFKD Unicode Normalization Form KD
+//
+// For a Form f, this documentation uses the notation f(x) to mean
+// the bytes or string x converted to the given form.
+// A position n in x is called a boundary if conversion to the form can
+// proceed independently on both sides:
+// f(x) == append(f(x[0:n]), f(x[n:])...)
+//
+// References: http://unicode.org/reports/tr15/ and
+// http://unicode.org/notes/tn5/.
+type Form int
+
+const (
+ NFC Form = iota
+ NFD
+ NFKC
+ NFKD
+)
+
+// Bytes returns f(b). May return b if f(b) = b.
+func (f Form) Bytes(b []byte) []byte {
+ src := inputBytes(b)
+ ft := formTable[f]
+ n, ok := ft.quickSpan(src, 0, len(b), true)
+ if ok {
+ return b
+ }
+ out := make([]byte, n, len(b))
+ copy(out, b[0:n])
+ rb := reorderBuffer{f: *ft, src: src, nsrc: len(b), out: out, flushF: appendFlush}
+ return doAppendInner(&rb, n)
+}
+
+// String returns f(s).
+func (f Form) String(s string) string {
+ src := inputString(s)
+ ft := formTable[f]
+ n, ok := ft.quickSpan(src, 0, len(s), true)
+ if ok {
+ return s
+ }
+ out := make([]byte, n, len(s))
+ copy(out, s[0:n])
+ rb := reorderBuffer{f: *ft, src: src, nsrc: len(s), out: out, flushF: appendFlush}
+ return string(doAppendInner(&rb, n))
+}
+
+// IsNormal returns true if b == f(b).
+func (f Form) IsNormal(b []byte) bool {
+ src := inputBytes(b)
+ ft := formTable[f]
+ bp, ok := ft.quickSpan(src, 0, len(b), true)
+ if ok {
+ return true
+ }
+ rb := reorderBuffer{f: *ft, src: src, nsrc: len(b)}
+ rb.setFlusher(nil, cmpNormalBytes)
+ for bp < len(b) {
+ rb.out = b[bp:]
+ if bp = decomposeSegment(&rb, bp, true); bp < 0 {
+ return false
+ }
+ bp, _ = rb.f.quickSpan(rb.src, bp, len(b), true)
+ }
+ return true
+}
+
+func cmpNormalBytes(rb *reorderBuffer) bool {
+ b := rb.out
+ for i := 0; i < rb.nrune; i++ {
+ info := rb.rune[i]
+ if int(info.size) > len(b) {
+ return false
+ }
+ p := info.pos
+ pe := p + info.size
+ for ; p < pe; p++ {
+ if b[0] != rb.byte[p] {
+ return false
+ }
+ b = b[1:]
+ }
+ }
+ return true
+}
+
+// IsNormalString returns true if s == f(s).
+func (f Form) IsNormalString(s string) bool {
+ src := inputString(s)
+ ft := formTable[f]
+ bp, ok := ft.quickSpan(src, 0, len(s), true)
+ if ok {
+ return true
+ }
+ rb := reorderBuffer{f: *ft, src: src, nsrc: len(s)}
+ rb.setFlusher(nil, func(rb *reorderBuffer) bool {
+ for i := 0; i < rb.nrune; i++ {
+ info := rb.rune[i]
+ if bp+int(info.size) > len(s) {
+ return false
+ }
+ p := info.pos
+ pe := p + info.size
+ for ; p < pe; p++ {
+ if s[bp] != rb.byte[p] {
+ return false
+ }
+ bp++
+ }
+ }
+ return true
+ })
+ for bp < len(s) {
+ if bp = decomposeSegment(&rb, bp, true); bp < 0 {
+ return false
+ }
+ bp, _ = rb.f.quickSpan(rb.src, bp, len(s), true)
+ }
+ return true
+}
+
+// patchTail fixes a case where a rune may be incorrectly normalized
+// if it is followed by illegal continuation bytes. It returns the
+// patched buffer and whether the decomposition is still in progress.
+func patchTail(rb *reorderBuffer) bool {
+ info, p := lastRuneStart(&rb.f, rb.out)
+ if p == -1 || info.size == 0 {
+ return true
+ }
+ end := p + int(info.size)
+ extra := len(rb.out) - end
+ if extra > 0 {
+ // Potentially allocating memory. However, this only
+ // happens with ill-formed UTF-8.
+ x := make([]byte, 0)
+ x = append(x, rb.out[len(rb.out)-extra:]...)
+ rb.out = rb.out[:end]
+ decomposeToLastBoundary(rb)
+ rb.doFlush()
+ rb.out = append(rb.out, x...)
+ return false
+ }
+ buf := rb.out[p:]
+ rb.out = rb.out[:p]
+ decomposeToLastBoundary(rb)
+ if s := rb.ss.next(info); s == ssStarter {
+ rb.doFlush()
+ rb.ss.first(info)
+ } else if s == ssOverflow {
+ rb.doFlush()
+ rb.insertCGJ()
+ rb.ss = 0
+ }
+ rb.insertUnsafe(inputBytes(buf), 0, info)
+ return true
+}
+
+func appendQuick(rb *reorderBuffer, i int) int {
+ if rb.nsrc == i {
+ return i
+ }
+ end, _ := rb.f.quickSpan(rb.src, i, rb.nsrc, true)
+ rb.out = rb.src.appendSlice(rb.out, i, end)
+ return end
+}
+
+// Append returns f(append(out, b...)).
+// The buffer out must be nil, empty, or equal to f(out).
+func (f Form) Append(out []byte, src ...byte) []byte {
+ return f.doAppend(out, inputBytes(src), len(src))
+}
+
+func (f Form) doAppend(out []byte, src input, n int) []byte {
+ if n == 0 {
+ return out
+ }
+ ft := formTable[f]
+ // Attempt to do a quickSpan first so we can avoid initializing the reorderBuffer.
+ if len(out) == 0 {
+ p, _ := ft.quickSpan(src, 0, n, true)
+ out = src.appendSlice(out, 0, p)
+ if p == n {
+ return out
+ }
+ rb := reorderBuffer{f: *ft, src: src, nsrc: n, out: out, flushF: appendFlush}
+ return doAppendInner(&rb, p)
+ }
+ rb := reorderBuffer{f: *ft, src: src, nsrc: n}
+ return doAppend(&rb, out, 0)
+}
+
+func doAppend(rb *reorderBuffer, out []byte, p int) []byte {
+ rb.setFlusher(out, appendFlush)
+ src, n := rb.src, rb.nsrc
+ doMerge := len(out) > 0
+ if q := src.skipContinuationBytes(p); q > p {
+ // Move leading non-starters to destination.
+ rb.out = src.appendSlice(rb.out, p, q)
+ p = q
+ doMerge = patchTail(rb)
+ }
+ fd := &rb.f
+ if doMerge {
+ var info Properties
+ if p < n {
+ info = fd.info(src, p)
+ if !info.BoundaryBefore() || info.nLeadingNonStarters() > 0 {
+ if p == 0 {
+ decomposeToLastBoundary(rb)
+ }
+ p = decomposeSegment(rb, p, true)
+ }
+ }
+ if info.size == 0 {
+ rb.doFlush()
+ // Append incomplete UTF-8 encoding.
+ return src.appendSlice(rb.out, p, n)
+ }
+ if rb.nrune > 0 {
+ return doAppendInner(rb, p)
+ }
+ }
+ p = appendQuick(rb, p)
+ return doAppendInner(rb, p)
+}
+
+func doAppendInner(rb *reorderBuffer, p int) []byte {
+ for n := rb.nsrc; p < n; {
+ p = decomposeSegment(rb, p, true)
+ p = appendQuick(rb, p)
+ }
+ return rb.out
+}
+
+// AppendString returns f(append(out, []byte(s))).
+// The buffer out must be nil, empty, or equal to f(out).
+func (f Form) AppendString(out []byte, src string) []byte {
+ return f.doAppend(out, inputString(src), len(src))
+}
+
+// QuickSpan returns a boundary n such that b[0:n] == f(b[0:n]).
+// It is not guaranteed to return the largest such n.
+func (f Form) QuickSpan(b []byte) int {
+ n, _ := formTable[f].quickSpan(inputBytes(b), 0, len(b), true)
+ return n
+}
+
+// Span implements transform.SpanningTransformer. It returns a boundary n such
+// that b[0:n] == f(b[0:n]). It is not guaranteed to return the largest such n.
+func (f Form) Span(b []byte, atEOF bool) (n int, err error) {
+ n, ok := formTable[f].quickSpan(inputBytes(b), 0, len(b), atEOF)
+ if n < len(b) {
+ if !ok {
+ err = transform.ErrEndOfSpan
+ } else {
+ err = transform.ErrShortSrc
+ }
+ }
+ return n, err
+}
+
+// SpanString returns a boundary n such that s[0:n] == f(s[0:n]).
+// It is not guaranteed to return the largest such n.
+func (f Form) SpanString(s string, atEOF bool) (n int, err error) {
+ n, ok := formTable[f].quickSpan(inputString(s), 0, len(s), atEOF)
+ if n < len(s) {
+ if !ok {
+ err = transform.ErrEndOfSpan
+ } else {
+ err = transform.ErrShortSrc
+ }
+ }
+ return n, err
+}
+
+// quickSpan returns a boundary n such that src[0:n] == f(src[0:n]) and
+// whether any non-normalized parts were found. If atEOF is false, n will
+// not point past the last segment if this segment might be become
+// non-normalized by appending other runes.
+func (f *formInfo) quickSpan(src input, i, end int, atEOF bool) (n int, ok bool) {
+ var lastCC uint8
+ ss := streamSafe(0)
+ lastSegStart := i
+ for n = end; i < n; {
+ if j := src.skipASCII(i, n); i != j {
+ i = j
+ lastSegStart = i - 1
+ lastCC = 0
+ ss = 0
+ continue
+ }
+ info := f.info(src, i)
+ if info.size == 0 {
+ if atEOF {
+ // include incomplete runes
+ return n, true
+ }
+ return lastSegStart, true
+ }
+ // This block needs to be before the next, because it is possible to
+ // have an overflow for runes that are starters (e.g. with U+FF9E).
+ switch ss.next(info) {
+ case ssStarter:
+ lastSegStart = i
+ case ssOverflow:
+ return lastSegStart, false
+ case ssSuccess:
+ if lastCC > info.ccc {
+ return lastSegStart, false
+ }
+ }
+ if f.composing {
+ if !info.isYesC() {
+ break
+ }
+ } else {
+ if !info.isYesD() {
+ break
+ }
+ }
+ lastCC = info.ccc
+ i += int(info.size)
+ }
+ if i == n {
+ if !atEOF {
+ n = lastSegStart
+ }
+ return n, true
+ }
+ return lastSegStart, false
+}
+
+// QuickSpanString returns a boundary n such that s[0:n] == f(s[0:n]).
+// It is not guaranteed to return the largest such n.
+func (f Form) QuickSpanString(s string) int {
+ n, _ := formTable[f].quickSpan(inputString(s), 0, len(s), true)
+ return n
+}
+
+// FirstBoundary returns the position i of the first boundary in b
+// or -1 if b contains no boundary.
+func (f Form) FirstBoundary(b []byte) int {
+ return f.firstBoundary(inputBytes(b), len(b))
+}
+
+func (f Form) firstBoundary(src input, nsrc int) int {
+ i := src.skipContinuationBytes(0)
+ if i >= nsrc {
+ return -1
+ }
+ fd := formTable[f]
+ ss := streamSafe(0)
+ // We should call ss.first here, but we can't as the first rune is
+ // skipped already. This means FirstBoundary can't really determine
+ // CGJ insertion points correctly. Luckily it doesn't have to.
+ for {
+ info := fd.info(src, i)
+ if info.size == 0 {
+ return -1
+ }
+ if s := ss.next(info); s != ssSuccess {
+ return i
+ }
+ i += int(info.size)
+ if i >= nsrc {
+ if !info.BoundaryAfter() && !ss.isMax() {
+ return -1
+ }
+ return nsrc
+ }
+ }
+}
+
+// FirstBoundaryInString returns the position i of the first boundary in s
+// or -1 if s contains no boundary.
+func (f Form) FirstBoundaryInString(s string) int {
+ return f.firstBoundary(inputString(s), len(s))
+}
+
+// NextBoundary reports the index of the boundary between the first and next
+// segment in b or -1 if atEOF is false and there are not enough bytes to
+// determine this boundary.
+func (f Form) NextBoundary(b []byte, atEOF bool) int {
+ return f.nextBoundary(inputBytes(b), len(b), atEOF)
+}
+
+// NextBoundaryInString reports the index of the boundary between the first and
+// next segment in b or -1 if atEOF is false and there are not enough bytes to
+// determine this boundary.
+func (f Form) NextBoundaryInString(s string, atEOF bool) int {
+ return f.nextBoundary(inputString(s), len(s), atEOF)
+}
+
+func (f Form) nextBoundary(src input, nsrc int, atEOF bool) int {
+ if nsrc == 0 {
+ if atEOF {
+ return 0
+ }
+ return -1
+ }
+ fd := formTable[f]
+ info := fd.info(src, 0)
+ if info.size == 0 {
+ if atEOF {
+ return 1
+ }
+ return -1
+ }
+ ss := streamSafe(0)
+ ss.first(info)
+
+ for i := int(info.size); i < nsrc; i += int(info.size) {
+ info = fd.info(src, i)
+ if info.size == 0 {
+ if atEOF {
+ return i
+ }
+ return -1
+ }
+ // TODO: Using streamSafe to determine the boundary isn't the same as
+ // using BoundaryBefore. Determine which should be used.
+ if s := ss.next(info); s != ssSuccess {
+ return i
+ }
+ }
+ if !atEOF && !info.BoundaryAfter() && !ss.isMax() {
+ return -1
+ }
+ return nsrc
+}
+
+// LastBoundary returns the position i of the last boundary in b
+// or -1 if b contains no boundary.
+func (f Form) LastBoundary(b []byte) int {
+ return lastBoundary(formTable[f], b)
+}
+
+func lastBoundary(fd *formInfo, b []byte) int {
+ i := len(b)
+ info, p := lastRuneStart(fd, b)
+ if p == -1 {
+ return -1
+ }
+ if info.size == 0 { // ends with incomplete rune
+ if p == 0 { // starts with incomplete rune
+ return -1
+ }
+ i = p
+ info, p = lastRuneStart(fd, b[:i])
+ if p == -1 { // incomplete UTF-8 encoding or non-starter bytes without a starter
+ return i
+ }
+ }
+ if p+int(info.size) != i { // trailing non-starter bytes: illegal UTF-8
+ return i
+ }
+ if info.BoundaryAfter() {
+ return i
+ }
+ ss := streamSafe(0)
+ v := ss.backwards(info)
+ for i = p; i >= 0 && v != ssStarter; i = p {
+ info, p = lastRuneStart(fd, b[:i])
+ if v = ss.backwards(info); v == ssOverflow {
+ break
+ }
+ if p+int(info.size) != i {
+ if p == -1 { // no boundary found
+ return -1
+ }
+ return i // boundary after an illegal UTF-8 encoding
+ }
+ }
+ return i
+}
+
+// decomposeSegment scans the first segment in src into rb. It inserts 0x034f
+// (Grapheme Joiner) when it encounters a sequence of more than 30 non-starters
+// and returns the number of bytes consumed from src or iShortDst or iShortSrc.
+func decomposeSegment(rb *reorderBuffer, sp int, atEOF bool) int {
+ // Force one character to be consumed.
+ info := rb.f.info(rb.src, sp)
+ if info.size == 0 {
+ return 0
+ }
+ if s := rb.ss.next(info); s == ssStarter {
+ // TODO: this could be removed if we don't support merging.
+ if rb.nrune > 0 {
+ goto end
+ }
+ } else if s == ssOverflow {
+ rb.insertCGJ()
+ goto end
+ }
+ if err := rb.insertFlush(rb.src, sp, info); err != iSuccess {
+ return int(err)
+ }
+ for {
+ sp += int(info.size)
+ if sp >= rb.nsrc {
+ if !atEOF && !info.BoundaryAfter() {
+ return int(iShortSrc)
+ }
+ break
+ }
+ info = rb.f.info(rb.src, sp)
+ if info.size == 0 {
+ if !atEOF {
+ return int(iShortSrc)
+ }
+ break
+ }
+ if s := rb.ss.next(info); s == ssStarter {
+ break
+ } else if s == ssOverflow {
+ rb.insertCGJ()
+ break
+ }
+ if err := rb.insertFlush(rb.src, sp, info); err != iSuccess {
+ return int(err)
+ }
+ }
+end:
+ if !rb.doFlush() {
+ return int(iShortDst)
+ }
+ return sp
+}
+
+// lastRuneStart returns the runeInfo and position of the last
+// rune in buf or the zero runeInfo and -1 if no rune was found.
+func lastRuneStart(fd *formInfo, buf []byte) (Properties, int) {
+ p := len(buf) - 1
+ for ; p >= 0 && !utf8.RuneStart(buf[p]); p-- {
+ }
+ if p < 0 {
+ return Properties{}, -1
+ }
+ return fd.info(inputBytes(buf), p), p
+}
+
+// decomposeToLastBoundary finds an open segment at the end of the buffer
+// and scans it into rb. Returns the buffer minus the last segment.
+func decomposeToLastBoundary(rb *reorderBuffer) {
+ fd := &rb.f
+ info, i := lastRuneStart(fd, rb.out)
+ if int(info.size) != len(rb.out)-i {
+ // illegal trailing continuation bytes
+ return
+ }
+ if info.BoundaryAfter() {
+ return
+ }
+ var add [maxNonStarters + 1]Properties // stores runeInfo in reverse order
+ padd := 0
+ ss := streamSafe(0)
+ p := len(rb.out)
+ for {
+ add[padd] = info
+ v := ss.backwards(info)
+ if v == ssOverflow {
+ // Note that if we have an overflow, it the string we are appending to
+ // is not correctly normalized. In this case the behavior is undefined.
+ break
+ }
+ padd++
+ p -= int(info.size)
+ if v == ssStarter || p < 0 {
+ break
+ }
+ info, i = lastRuneStart(fd, rb.out[:p])
+ if int(info.size) != p-i {
+ break
+ }
+ }
+ rb.ss = ss
+ // Copy bytes for insertion as we may need to overwrite rb.out.
+ var buf [maxBufferSize * utf8.UTFMax]byte
+ cp := buf[:copy(buf[:], rb.out[p:])]
+ rb.out = rb.out[:p]
+ for padd--; padd >= 0; padd-- {
+ info = add[padd]
+ rb.insertUnsafe(inputBytes(cp), 0, info)
+ cp = cp[info.size:]
+ }
+}
diff --git a/vendor/golang.org/x/text/unicode/norm/readwriter.go b/vendor/golang.org/x/text/unicode/norm/readwriter.go
new file mode 100644
index 0000000..d926ee9
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/norm/readwriter.go
@@ -0,0 +1,125 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package norm
+
+import "io"
+
+type normWriter struct {
+ rb reorderBuffer
+ w io.Writer
+ buf []byte
+}
+
+// Write implements the standard write interface. If the last characters are
+// not at a normalization boundary, the bytes will be buffered for the next
+// write. The remaining bytes will be written on close.
+func (w *normWriter) Write(data []byte) (n int, err error) {
+ // Process data in pieces to keep w.buf size bounded.
+ const chunk = 4000
+
+ for len(data) > 0 {
+ // Normalize into w.buf.
+ m := len(data)
+ if m > chunk {
+ m = chunk
+ }
+ w.rb.src = inputBytes(data[:m])
+ w.rb.nsrc = m
+ w.buf = doAppend(&w.rb, w.buf, 0)
+ data = data[m:]
+ n += m
+
+ // Write out complete prefix, save remainder.
+ // Note that lastBoundary looks back at most 31 runes.
+ i := lastBoundary(&w.rb.f, w.buf)
+ if i == -1 {
+ i = 0
+ }
+ if i > 0 {
+ if _, err = w.w.Write(w.buf[:i]); err != nil {
+ break
+ }
+ bn := copy(w.buf, w.buf[i:])
+ w.buf = w.buf[:bn]
+ }
+ }
+ return n, err
+}
+
+// Close forces data that remains in the buffer to be written.
+func (w *normWriter) Close() error {
+ if len(w.buf) > 0 {
+ _, err := w.w.Write(w.buf)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Writer returns a new writer that implements Write(b)
+// by writing f(b) to w. The returned writer may use an
+// an internal buffer to maintain state across Write calls.
+// Calling its Close method writes any buffered data to w.
+func (f Form) Writer(w io.Writer) io.WriteCloser {
+ wr := &normWriter{rb: reorderBuffer{}, w: w}
+ wr.rb.init(f, nil)
+ return wr
+}
+
+type normReader struct {
+ rb reorderBuffer
+ r io.Reader
+ inbuf []byte
+ outbuf []byte
+ bufStart int
+ lastBoundary int
+ err error
+}
+
+// Read implements the standard read interface.
+func (r *normReader) Read(p []byte) (int, error) {
+ for {
+ if r.lastBoundary-r.bufStart > 0 {
+ n := copy(p, r.outbuf[r.bufStart:r.lastBoundary])
+ r.bufStart += n
+ if r.lastBoundary-r.bufStart > 0 {
+ return n, nil
+ }
+ return n, r.err
+ }
+ if r.err != nil {
+ return 0, r.err
+ }
+ outn := copy(r.outbuf, r.outbuf[r.lastBoundary:])
+ r.outbuf = r.outbuf[0:outn]
+ r.bufStart = 0
+
+ n, err := r.r.Read(r.inbuf)
+ r.rb.src = inputBytes(r.inbuf[0:n])
+ r.rb.nsrc, r.err = n, err
+ if n > 0 {
+ r.outbuf = doAppend(&r.rb, r.outbuf, 0)
+ }
+ if err == io.EOF {
+ r.lastBoundary = len(r.outbuf)
+ } else {
+ r.lastBoundary = lastBoundary(&r.rb.f, r.outbuf)
+ if r.lastBoundary == -1 {
+ r.lastBoundary = 0
+ }
+ }
+ }
+}
+
+// Reader returns a new reader that implements Read
+// by reading data from r and returning f(data).
+func (f Form) Reader(r io.Reader) io.Reader {
+ const chunk = 4000
+ buf := make([]byte, chunk)
+ rr := &normReader{rb: reorderBuffer{}, r: r, inbuf: buf}
+ rr.rb.init(f, buf)
+ return rr
+}
diff --git a/vendor/golang.org/x/text/unicode/norm/tables.go b/vendor/golang.org/x/text/unicode/norm/tables.go
new file mode 100644
index 0000000..bf9ff80
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/norm/tables.go
@@ -0,0 +1,7631 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package norm
+
+const (
+ // Version is the Unicode edition from which the tables are derived.
+ Version = "9.0.0"
+
+ // MaxTransformChunkSize indicates the maximum number of bytes that Transform
+ // may need to write atomically for any Form. Making a destination buffer at
+ // least this size ensures that Transform can always make progress and that
+ // the user does not need to grow the buffer on an ErrShortDst.
+ MaxTransformChunkSize = 35 + maxNonStarters*4
+)
+
+var ccc = [55]uint8{
+ 0, 1, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36,
+ 84, 91, 103, 107, 118, 122, 129, 130,
+ 132, 202, 214, 216, 218, 220, 222, 224,
+ 226, 228, 230, 232, 233, 234, 240,
+}
+
+const (
+ firstMulti = 0x186D
+ firstCCC = 0x2C9E
+ endMulti = 0x2F60
+ firstLeadingCCC = 0x49AE
+ firstCCCZeroExcept = 0x4A78
+ firstStarterWithNLead = 0x4A9F
+ lastDecomp = 0x4AA1
+ maxDecomp = 0x8000
+)
+
+// decomps: 19105 bytes
+var decomps = [...]byte{
+ // Bytes 0 - 3f
+ 0x00, 0x41, 0x20, 0x41, 0x21, 0x41, 0x22, 0x41,
+ 0x23, 0x41, 0x24, 0x41, 0x25, 0x41, 0x26, 0x41,
+ 0x27, 0x41, 0x28, 0x41, 0x29, 0x41, 0x2A, 0x41,
+ 0x2B, 0x41, 0x2C, 0x41, 0x2D, 0x41, 0x2E, 0x41,
+ 0x2F, 0x41, 0x30, 0x41, 0x31, 0x41, 0x32, 0x41,
+ 0x33, 0x41, 0x34, 0x41, 0x35, 0x41, 0x36, 0x41,
+ 0x37, 0x41, 0x38, 0x41, 0x39, 0x41, 0x3A, 0x41,
+ 0x3B, 0x41, 0x3C, 0x41, 0x3D, 0x41, 0x3E, 0x41,
+ // Bytes 40 - 7f
+ 0x3F, 0x41, 0x40, 0x41, 0x41, 0x41, 0x42, 0x41,
+ 0x43, 0x41, 0x44, 0x41, 0x45, 0x41, 0x46, 0x41,
+ 0x47, 0x41, 0x48, 0x41, 0x49, 0x41, 0x4A, 0x41,
+ 0x4B, 0x41, 0x4C, 0x41, 0x4D, 0x41, 0x4E, 0x41,
+ 0x4F, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41,
+ 0x53, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41,
+ 0x57, 0x41, 0x58, 0x41, 0x59, 0x41, 0x5A, 0x41,
+ 0x5B, 0x41, 0x5C, 0x41, 0x5D, 0x41, 0x5E, 0x41,
+ // Bytes 80 - bf
+ 0x5F, 0x41, 0x60, 0x41, 0x61, 0x41, 0x62, 0x41,
+ 0x63, 0x41, 0x64, 0x41, 0x65, 0x41, 0x66, 0x41,
+ 0x67, 0x41, 0x68, 0x41, 0x69, 0x41, 0x6A, 0x41,
+ 0x6B, 0x41, 0x6C, 0x41, 0x6D, 0x41, 0x6E, 0x41,
+ 0x6F, 0x41, 0x70, 0x41, 0x71, 0x41, 0x72, 0x41,
+ 0x73, 0x41, 0x74, 0x41, 0x75, 0x41, 0x76, 0x41,
+ 0x77, 0x41, 0x78, 0x41, 0x79, 0x41, 0x7A, 0x41,
+ 0x7B, 0x41, 0x7C, 0x41, 0x7D, 0x41, 0x7E, 0x42,
+ // Bytes c0 - ff
+ 0xC2, 0xA2, 0x42, 0xC2, 0xA3, 0x42, 0xC2, 0xA5,
+ 0x42, 0xC2, 0xA6, 0x42, 0xC2, 0xAC, 0x42, 0xC2,
+ 0xB7, 0x42, 0xC3, 0x86, 0x42, 0xC3, 0xB0, 0x42,
+ 0xC4, 0xA6, 0x42, 0xC4, 0xA7, 0x42, 0xC4, 0xB1,
+ 0x42, 0xC5, 0x8B, 0x42, 0xC5, 0x93, 0x42, 0xC6,
+ 0x8E, 0x42, 0xC6, 0x90, 0x42, 0xC6, 0xAB, 0x42,
+ 0xC8, 0xA2, 0x42, 0xC8, 0xB7, 0x42, 0xC9, 0x90,
+ 0x42, 0xC9, 0x91, 0x42, 0xC9, 0x92, 0x42, 0xC9,
+ // Bytes 100 - 13f
+ 0x94, 0x42, 0xC9, 0x95, 0x42, 0xC9, 0x99, 0x42,
+ 0xC9, 0x9B, 0x42, 0xC9, 0x9C, 0x42, 0xC9, 0x9F,
+ 0x42, 0xC9, 0xA1, 0x42, 0xC9, 0xA3, 0x42, 0xC9,
+ 0xA5, 0x42, 0xC9, 0xA6, 0x42, 0xC9, 0xA8, 0x42,
+ 0xC9, 0xA9, 0x42, 0xC9, 0xAA, 0x42, 0xC9, 0xAB,
+ 0x42, 0xC9, 0xAD, 0x42, 0xC9, 0xAF, 0x42, 0xC9,
+ 0xB0, 0x42, 0xC9, 0xB1, 0x42, 0xC9, 0xB2, 0x42,
+ 0xC9, 0xB3, 0x42, 0xC9, 0xB4, 0x42, 0xC9, 0xB5,
+ // Bytes 140 - 17f
+ 0x42, 0xC9, 0xB8, 0x42, 0xC9, 0xB9, 0x42, 0xC9,
+ 0xBB, 0x42, 0xCA, 0x81, 0x42, 0xCA, 0x82, 0x42,
+ 0xCA, 0x83, 0x42, 0xCA, 0x89, 0x42, 0xCA, 0x8A,
+ 0x42, 0xCA, 0x8B, 0x42, 0xCA, 0x8C, 0x42, 0xCA,
+ 0x90, 0x42, 0xCA, 0x91, 0x42, 0xCA, 0x92, 0x42,
+ 0xCA, 0x95, 0x42, 0xCA, 0x9D, 0x42, 0xCA, 0x9F,
+ 0x42, 0xCA, 0xB9, 0x42, 0xCE, 0x91, 0x42, 0xCE,
+ 0x92, 0x42, 0xCE, 0x93, 0x42, 0xCE, 0x94, 0x42,
+ // Bytes 180 - 1bf
+ 0xCE, 0x95, 0x42, 0xCE, 0x96, 0x42, 0xCE, 0x97,
+ 0x42, 0xCE, 0x98, 0x42, 0xCE, 0x99, 0x42, 0xCE,
+ 0x9A, 0x42, 0xCE, 0x9B, 0x42, 0xCE, 0x9C, 0x42,
+ 0xCE, 0x9D, 0x42, 0xCE, 0x9E, 0x42, 0xCE, 0x9F,
+ 0x42, 0xCE, 0xA0, 0x42, 0xCE, 0xA1, 0x42, 0xCE,
+ 0xA3, 0x42, 0xCE, 0xA4, 0x42, 0xCE, 0xA5, 0x42,
+ 0xCE, 0xA6, 0x42, 0xCE, 0xA7, 0x42, 0xCE, 0xA8,
+ 0x42, 0xCE, 0xA9, 0x42, 0xCE, 0xB1, 0x42, 0xCE,
+ // Bytes 1c0 - 1ff
+ 0xB2, 0x42, 0xCE, 0xB3, 0x42, 0xCE, 0xB4, 0x42,
+ 0xCE, 0xB5, 0x42, 0xCE, 0xB6, 0x42, 0xCE, 0xB7,
+ 0x42, 0xCE, 0xB8, 0x42, 0xCE, 0xB9, 0x42, 0xCE,
+ 0xBA, 0x42, 0xCE, 0xBB, 0x42, 0xCE, 0xBC, 0x42,
+ 0xCE, 0xBD, 0x42, 0xCE, 0xBE, 0x42, 0xCE, 0xBF,
+ 0x42, 0xCF, 0x80, 0x42, 0xCF, 0x81, 0x42, 0xCF,
+ 0x82, 0x42, 0xCF, 0x83, 0x42, 0xCF, 0x84, 0x42,
+ 0xCF, 0x85, 0x42, 0xCF, 0x86, 0x42, 0xCF, 0x87,
+ // Bytes 200 - 23f
+ 0x42, 0xCF, 0x88, 0x42, 0xCF, 0x89, 0x42, 0xCF,
+ 0x9C, 0x42, 0xCF, 0x9D, 0x42, 0xD0, 0xBD, 0x42,
+ 0xD1, 0x8A, 0x42, 0xD1, 0x8C, 0x42, 0xD7, 0x90,
+ 0x42, 0xD7, 0x91, 0x42, 0xD7, 0x92, 0x42, 0xD7,
+ 0x93, 0x42, 0xD7, 0x94, 0x42, 0xD7, 0x9B, 0x42,
+ 0xD7, 0x9C, 0x42, 0xD7, 0x9D, 0x42, 0xD7, 0xA2,
+ 0x42, 0xD7, 0xA8, 0x42, 0xD7, 0xAA, 0x42, 0xD8,
+ 0xA1, 0x42, 0xD8, 0xA7, 0x42, 0xD8, 0xA8, 0x42,
+ // Bytes 240 - 27f
+ 0xD8, 0xA9, 0x42, 0xD8, 0xAA, 0x42, 0xD8, 0xAB,
+ 0x42, 0xD8, 0xAC, 0x42, 0xD8, 0xAD, 0x42, 0xD8,
+ 0xAE, 0x42, 0xD8, 0xAF, 0x42, 0xD8, 0xB0, 0x42,
+ 0xD8, 0xB1, 0x42, 0xD8, 0xB2, 0x42, 0xD8, 0xB3,
+ 0x42, 0xD8, 0xB4, 0x42, 0xD8, 0xB5, 0x42, 0xD8,
+ 0xB6, 0x42, 0xD8, 0xB7, 0x42, 0xD8, 0xB8, 0x42,
+ 0xD8, 0xB9, 0x42, 0xD8, 0xBA, 0x42, 0xD9, 0x81,
+ 0x42, 0xD9, 0x82, 0x42, 0xD9, 0x83, 0x42, 0xD9,
+ // Bytes 280 - 2bf
+ 0x84, 0x42, 0xD9, 0x85, 0x42, 0xD9, 0x86, 0x42,
+ 0xD9, 0x87, 0x42, 0xD9, 0x88, 0x42, 0xD9, 0x89,
+ 0x42, 0xD9, 0x8A, 0x42, 0xD9, 0xAE, 0x42, 0xD9,
+ 0xAF, 0x42, 0xD9, 0xB1, 0x42, 0xD9, 0xB9, 0x42,
+ 0xD9, 0xBA, 0x42, 0xD9, 0xBB, 0x42, 0xD9, 0xBE,
+ 0x42, 0xD9, 0xBF, 0x42, 0xDA, 0x80, 0x42, 0xDA,
+ 0x83, 0x42, 0xDA, 0x84, 0x42, 0xDA, 0x86, 0x42,
+ 0xDA, 0x87, 0x42, 0xDA, 0x88, 0x42, 0xDA, 0x8C,
+ // Bytes 2c0 - 2ff
+ 0x42, 0xDA, 0x8D, 0x42, 0xDA, 0x8E, 0x42, 0xDA,
+ 0x91, 0x42, 0xDA, 0x98, 0x42, 0xDA, 0xA1, 0x42,
+ 0xDA, 0xA4, 0x42, 0xDA, 0xA6, 0x42, 0xDA, 0xA9,
+ 0x42, 0xDA, 0xAD, 0x42, 0xDA, 0xAF, 0x42, 0xDA,
+ 0xB1, 0x42, 0xDA, 0xB3, 0x42, 0xDA, 0xBA, 0x42,
+ 0xDA, 0xBB, 0x42, 0xDA, 0xBE, 0x42, 0xDB, 0x81,
+ 0x42, 0xDB, 0x85, 0x42, 0xDB, 0x86, 0x42, 0xDB,
+ 0x87, 0x42, 0xDB, 0x88, 0x42, 0xDB, 0x89, 0x42,
+ // Bytes 300 - 33f
+ 0xDB, 0x8B, 0x42, 0xDB, 0x8C, 0x42, 0xDB, 0x90,
+ 0x42, 0xDB, 0x92, 0x43, 0xE0, 0xBC, 0x8B, 0x43,
+ 0xE1, 0x83, 0x9C, 0x43, 0xE1, 0x84, 0x80, 0x43,
+ 0xE1, 0x84, 0x81, 0x43, 0xE1, 0x84, 0x82, 0x43,
+ 0xE1, 0x84, 0x83, 0x43, 0xE1, 0x84, 0x84, 0x43,
+ 0xE1, 0x84, 0x85, 0x43, 0xE1, 0x84, 0x86, 0x43,
+ 0xE1, 0x84, 0x87, 0x43, 0xE1, 0x84, 0x88, 0x43,
+ 0xE1, 0x84, 0x89, 0x43, 0xE1, 0x84, 0x8A, 0x43,
+ // Bytes 340 - 37f
+ 0xE1, 0x84, 0x8B, 0x43, 0xE1, 0x84, 0x8C, 0x43,
+ 0xE1, 0x84, 0x8D, 0x43, 0xE1, 0x84, 0x8E, 0x43,
+ 0xE1, 0x84, 0x8F, 0x43, 0xE1, 0x84, 0x90, 0x43,
+ 0xE1, 0x84, 0x91, 0x43, 0xE1, 0x84, 0x92, 0x43,
+ 0xE1, 0x84, 0x94, 0x43, 0xE1, 0x84, 0x95, 0x43,
+ 0xE1, 0x84, 0x9A, 0x43, 0xE1, 0x84, 0x9C, 0x43,
+ 0xE1, 0x84, 0x9D, 0x43, 0xE1, 0x84, 0x9E, 0x43,
+ 0xE1, 0x84, 0xA0, 0x43, 0xE1, 0x84, 0xA1, 0x43,
+ // Bytes 380 - 3bf
+ 0xE1, 0x84, 0xA2, 0x43, 0xE1, 0x84, 0xA3, 0x43,
+ 0xE1, 0x84, 0xA7, 0x43, 0xE1, 0x84, 0xA9, 0x43,
+ 0xE1, 0x84, 0xAB, 0x43, 0xE1, 0x84, 0xAC, 0x43,
+ 0xE1, 0x84, 0xAD, 0x43, 0xE1, 0x84, 0xAE, 0x43,
+ 0xE1, 0x84, 0xAF, 0x43, 0xE1, 0x84, 0xB2, 0x43,
+ 0xE1, 0x84, 0xB6, 0x43, 0xE1, 0x85, 0x80, 0x43,
+ 0xE1, 0x85, 0x87, 0x43, 0xE1, 0x85, 0x8C, 0x43,
+ 0xE1, 0x85, 0x97, 0x43, 0xE1, 0x85, 0x98, 0x43,
+ // Bytes 3c0 - 3ff
+ 0xE1, 0x85, 0x99, 0x43, 0xE1, 0x85, 0xA0, 0x43,
+ 0xE1, 0x86, 0x84, 0x43, 0xE1, 0x86, 0x85, 0x43,
+ 0xE1, 0x86, 0x88, 0x43, 0xE1, 0x86, 0x91, 0x43,
+ 0xE1, 0x86, 0x92, 0x43, 0xE1, 0x86, 0x94, 0x43,
+ 0xE1, 0x86, 0x9E, 0x43, 0xE1, 0x86, 0xA1, 0x43,
+ 0xE1, 0x87, 0x87, 0x43, 0xE1, 0x87, 0x88, 0x43,
+ 0xE1, 0x87, 0x8C, 0x43, 0xE1, 0x87, 0x8E, 0x43,
+ 0xE1, 0x87, 0x93, 0x43, 0xE1, 0x87, 0x97, 0x43,
+ // Bytes 400 - 43f
+ 0xE1, 0x87, 0x99, 0x43, 0xE1, 0x87, 0x9D, 0x43,
+ 0xE1, 0x87, 0x9F, 0x43, 0xE1, 0x87, 0xB1, 0x43,
+ 0xE1, 0x87, 0xB2, 0x43, 0xE1, 0xB4, 0x82, 0x43,
+ 0xE1, 0xB4, 0x96, 0x43, 0xE1, 0xB4, 0x97, 0x43,
+ 0xE1, 0xB4, 0x9C, 0x43, 0xE1, 0xB4, 0x9D, 0x43,
+ 0xE1, 0xB4, 0xA5, 0x43, 0xE1, 0xB5, 0xBB, 0x43,
+ 0xE1, 0xB6, 0x85, 0x43, 0xE2, 0x80, 0x82, 0x43,
+ 0xE2, 0x80, 0x83, 0x43, 0xE2, 0x80, 0x90, 0x43,
+ // Bytes 440 - 47f
+ 0xE2, 0x80, 0x93, 0x43, 0xE2, 0x80, 0x94, 0x43,
+ 0xE2, 0x82, 0xA9, 0x43, 0xE2, 0x86, 0x90, 0x43,
+ 0xE2, 0x86, 0x91, 0x43, 0xE2, 0x86, 0x92, 0x43,
+ 0xE2, 0x86, 0x93, 0x43, 0xE2, 0x88, 0x82, 0x43,
+ 0xE2, 0x88, 0x87, 0x43, 0xE2, 0x88, 0x91, 0x43,
+ 0xE2, 0x88, 0x92, 0x43, 0xE2, 0x94, 0x82, 0x43,
+ 0xE2, 0x96, 0xA0, 0x43, 0xE2, 0x97, 0x8B, 0x43,
+ 0xE2, 0xA6, 0x85, 0x43, 0xE2, 0xA6, 0x86, 0x43,
+ // Bytes 480 - 4bf
+ 0xE2, 0xB5, 0xA1, 0x43, 0xE3, 0x80, 0x81, 0x43,
+ 0xE3, 0x80, 0x82, 0x43, 0xE3, 0x80, 0x88, 0x43,
+ 0xE3, 0x80, 0x89, 0x43, 0xE3, 0x80, 0x8A, 0x43,
+ 0xE3, 0x80, 0x8B, 0x43, 0xE3, 0x80, 0x8C, 0x43,
+ 0xE3, 0x80, 0x8D, 0x43, 0xE3, 0x80, 0x8E, 0x43,
+ 0xE3, 0x80, 0x8F, 0x43, 0xE3, 0x80, 0x90, 0x43,
+ 0xE3, 0x80, 0x91, 0x43, 0xE3, 0x80, 0x92, 0x43,
+ 0xE3, 0x80, 0x94, 0x43, 0xE3, 0x80, 0x95, 0x43,
+ // Bytes 4c0 - 4ff
+ 0xE3, 0x80, 0x96, 0x43, 0xE3, 0x80, 0x97, 0x43,
+ 0xE3, 0x82, 0xA1, 0x43, 0xE3, 0x82, 0xA2, 0x43,
+ 0xE3, 0x82, 0xA3, 0x43, 0xE3, 0x82, 0xA4, 0x43,
+ 0xE3, 0x82, 0xA5, 0x43, 0xE3, 0x82, 0xA6, 0x43,
+ 0xE3, 0x82, 0xA7, 0x43, 0xE3, 0x82, 0xA8, 0x43,
+ 0xE3, 0x82, 0xA9, 0x43, 0xE3, 0x82, 0xAA, 0x43,
+ 0xE3, 0x82, 0xAB, 0x43, 0xE3, 0x82, 0xAD, 0x43,
+ 0xE3, 0x82, 0xAF, 0x43, 0xE3, 0x82, 0xB1, 0x43,
+ // Bytes 500 - 53f
+ 0xE3, 0x82, 0xB3, 0x43, 0xE3, 0x82, 0xB5, 0x43,
+ 0xE3, 0x82, 0xB7, 0x43, 0xE3, 0x82, 0xB9, 0x43,
+ 0xE3, 0x82, 0xBB, 0x43, 0xE3, 0x82, 0xBD, 0x43,
+ 0xE3, 0x82, 0xBF, 0x43, 0xE3, 0x83, 0x81, 0x43,
+ 0xE3, 0x83, 0x83, 0x43, 0xE3, 0x83, 0x84, 0x43,
+ 0xE3, 0x83, 0x86, 0x43, 0xE3, 0x83, 0x88, 0x43,
+ 0xE3, 0x83, 0x8A, 0x43, 0xE3, 0x83, 0x8B, 0x43,
+ 0xE3, 0x83, 0x8C, 0x43, 0xE3, 0x83, 0x8D, 0x43,
+ // Bytes 540 - 57f
+ 0xE3, 0x83, 0x8E, 0x43, 0xE3, 0x83, 0x8F, 0x43,
+ 0xE3, 0x83, 0x92, 0x43, 0xE3, 0x83, 0x95, 0x43,
+ 0xE3, 0x83, 0x98, 0x43, 0xE3, 0x83, 0x9B, 0x43,
+ 0xE3, 0x83, 0x9E, 0x43, 0xE3, 0x83, 0x9F, 0x43,
+ 0xE3, 0x83, 0xA0, 0x43, 0xE3, 0x83, 0xA1, 0x43,
+ 0xE3, 0x83, 0xA2, 0x43, 0xE3, 0x83, 0xA3, 0x43,
+ 0xE3, 0x83, 0xA4, 0x43, 0xE3, 0x83, 0xA5, 0x43,
+ 0xE3, 0x83, 0xA6, 0x43, 0xE3, 0x83, 0xA7, 0x43,
+ // Bytes 580 - 5bf
+ 0xE3, 0x83, 0xA8, 0x43, 0xE3, 0x83, 0xA9, 0x43,
+ 0xE3, 0x83, 0xAA, 0x43, 0xE3, 0x83, 0xAB, 0x43,
+ 0xE3, 0x83, 0xAC, 0x43, 0xE3, 0x83, 0xAD, 0x43,
+ 0xE3, 0x83, 0xAF, 0x43, 0xE3, 0x83, 0xB0, 0x43,
+ 0xE3, 0x83, 0xB1, 0x43, 0xE3, 0x83, 0xB2, 0x43,
+ 0xE3, 0x83, 0xB3, 0x43, 0xE3, 0x83, 0xBB, 0x43,
+ 0xE3, 0x83, 0xBC, 0x43, 0xE3, 0x92, 0x9E, 0x43,
+ 0xE3, 0x92, 0xB9, 0x43, 0xE3, 0x92, 0xBB, 0x43,
+ // Bytes 5c0 - 5ff
+ 0xE3, 0x93, 0x9F, 0x43, 0xE3, 0x94, 0x95, 0x43,
+ 0xE3, 0x9B, 0xAE, 0x43, 0xE3, 0x9B, 0xBC, 0x43,
+ 0xE3, 0x9E, 0x81, 0x43, 0xE3, 0xA0, 0xAF, 0x43,
+ 0xE3, 0xA1, 0xA2, 0x43, 0xE3, 0xA1, 0xBC, 0x43,
+ 0xE3, 0xA3, 0x87, 0x43, 0xE3, 0xA3, 0xA3, 0x43,
+ 0xE3, 0xA4, 0x9C, 0x43, 0xE3, 0xA4, 0xBA, 0x43,
+ 0xE3, 0xA8, 0xAE, 0x43, 0xE3, 0xA9, 0xAC, 0x43,
+ 0xE3, 0xAB, 0xA4, 0x43, 0xE3, 0xAC, 0x88, 0x43,
+ // Bytes 600 - 63f
+ 0xE3, 0xAC, 0x99, 0x43, 0xE3, 0xAD, 0x89, 0x43,
+ 0xE3, 0xAE, 0x9D, 0x43, 0xE3, 0xB0, 0x98, 0x43,
+ 0xE3, 0xB1, 0x8E, 0x43, 0xE3, 0xB4, 0xB3, 0x43,
+ 0xE3, 0xB6, 0x96, 0x43, 0xE3, 0xBA, 0xAC, 0x43,
+ 0xE3, 0xBA, 0xB8, 0x43, 0xE3, 0xBC, 0x9B, 0x43,
+ 0xE3, 0xBF, 0xBC, 0x43, 0xE4, 0x80, 0x88, 0x43,
+ 0xE4, 0x80, 0x98, 0x43, 0xE4, 0x80, 0xB9, 0x43,
+ 0xE4, 0x81, 0x86, 0x43, 0xE4, 0x82, 0x96, 0x43,
+ // Bytes 640 - 67f
+ 0xE4, 0x83, 0xA3, 0x43, 0xE4, 0x84, 0xAF, 0x43,
+ 0xE4, 0x88, 0x82, 0x43, 0xE4, 0x88, 0xA7, 0x43,
+ 0xE4, 0x8A, 0xA0, 0x43, 0xE4, 0x8C, 0x81, 0x43,
+ 0xE4, 0x8C, 0xB4, 0x43, 0xE4, 0x8D, 0x99, 0x43,
+ 0xE4, 0x8F, 0x95, 0x43, 0xE4, 0x8F, 0x99, 0x43,
+ 0xE4, 0x90, 0x8B, 0x43, 0xE4, 0x91, 0xAB, 0x43,
+ 0xE4, 0x94, 0xAB, 0x43, 0xE4, 0x95, 0x9D, 0x43,
+ 0xE4, 0x95, 0xA1, 0x43, 0xE4, 0x95, 0xAB, 0x43,
+ // Bytes 680 - 6bf
+ 0xE4, 0x97, 0x97, 0x43, 0xE4, 0x97, 0xB9, 0x43,
+ 0xE4, 0x98, 0xB5, 0x43, 0xE4, 0x9A, 0xBE, 0x43,
+ 0xE4, 0x9B, 0x87, 0x43, 0xE4, 0xA6, 0x95, 0x43,
+ 0xE4, 0xA7, 0xA6, 0x43, 0xE4, 0xA9, 0xAE, 0x43,
+ 0xE4, 0xA9, 0xB6, 0x43, 0xE4, 0xAA, 0xB2, 0x43,
+ 0xE4, 0xAC, 0xB3, 0x43, 0xE4, 0xAF, 0x8E, 0x43,
+ 0xE4, 0xB3, 0x8E, 0x43, 0xE4, 0xB3, 0xAD, 0x43,
+ 0xE4, 0xB3, 0xB8, 0x43, 0xE4, 0xB5, 0x96, 0x43,
+ // Bytes 6c0 - 6ff
+ 0xE4, 0xB8, 0x80, 0x43, 0xE4, 0xB8, 0x81, 0x43,
+ 0xE4, 0xB8, 0x83, 0x43, 0xE4, 0xB8, 0x89, 0x43,
+ 0xE4, 0xB8, 0x8A, 0x43, 0xE4, 0xB8, 0x8B, 0x43,
+ 0xE4, 0xB8, 0x8D, 0x43, 0xE4, 0xB8, 0x99, 0x43,
+ 0xE4, 0xB8, 0xA6, 0x43, 0xE4, 0xB8, 0xA8, 0x43,
+ 0xE4, 0xB8, 0xAD, 0x43, 0xE4, 0xB8, 0xB2, 0x43,
+ 0xE4, 0xB8, 0xB6, 0x43, 0xE4, 0xB8, 0xB8, 0x43,
+ 0xE4, 0xB8, 0xB9, 0x43, 0xE4, 0xB8, 0xBD, 0x43,
+ // Bytes 700 - 73f
+ 0xE4, 0xB8, 0xBF, 0x43, 0xE4, 0xB9, 0x81, 0x43,
+ 0xE4, 0xB9, 0x99, 0x43, 0xE4, 0xB9, 0x9D, 0x43,
+ 0xE4, 0xBA, 0x82, 0x43, 0xE4, 0xBA, 0x85, 0x43,
+ 0xE4, 0xBA, 0x86, 0x43, 0xE4, 0xBA, 0x8C, 0x43,
+ 0xE4, 0xBA, 0x94, 0x43, 0xE4, 0xBA, 0xA0, 0x43,
+ 0xE4, 0xBA, 0xA4, 0x43, 0xE4, 0xBA, 0xAE, 0x43,
+ 0xE4, 0xBA, 0xBA, 0x43, 0xE4, 0xBB, 0x80, 0x43,
+ 0xE4, 0xBB, 0x8C, 0x43, 0xE4, 0xBB, 0xA4, 0x43,
+ // Bytes 740 - 77f
+ 0xE4, 0xBC, 0x81, 0x43, 0xE4, 0xBC, 0x91, 0x43,
+ 0xE4, 0xBD, 0xA0, 0x43, 0xE4, 0xBE, 0x80, 0x43,
+ 0xE4, 0xBE, 0x86, 0x43, 0xE4, 0xBE, 0x8B, 0x43,
+ 0xE4, 0xBE, 0xAE, 0x43, 0xE4, 0xBE, 0xBB, 0x43,
+ 0xE4, 0xBE, 0xBF, 0x43, 0xE5, 0x80, 0x82, 0x43,
+ 0xE5, 0x80, 0xAB, 0x43, 0xE5, 0x81, 0xBA, 0x43,
+ 0xE5, 0x82, 0x99, 0x43, 0xE5, 0x83, 0x8F, 0x43,
+ 0xE5, 0x83, 0x9A, 0x43, 0xE5, 0x83, 0xA7, 0x43,
+ // Bytes 780 - 7bf
+ 0xE5, 0x84, 0xAA, 0x43, 0xE5, 0x84, 0xBF, 0x43,
+ 0xE5, 0x85, 0x80, 0x43, 0xE5, 0x85, 0x85, 0x43,
+ 0xE5, 0x85, 0x8D, 0x43, 0xE5, 0x85, 0x94, 0x43,
+ 0xE5, 0x85, 0xA4, 0x43, 0xE5, 0x85, 0xA5, 0x43,
+ 0xE5, 0x85, 0xA7, 0x43, 0xE5, 0x85, 0xA8, 0x43,
+ 0xE5, 0x85, 0xA9, 0x43, 0xE5, 0x85, 0xAB, 0x43,
+ 0xE5, 0x85, 0xAD, 0x43, 0xE5, 0x85, 0xB7, 0x43,
+ 0xE5, 0x86, 0x80, 0x43, 0xE5, 0x86, 0x82, 0x43,
+ // Bytes 7c0 - 7ff
+ 0xE5, 0x86, 0x8D, 0x43, 0xE5, 0x86, 0x92, 0x43,
+ 0xE5, 0x86, 0x95, 0x43, 0xE5, 0x86, 0x96, 0x43,
+ 0xE5, 0x86, 0x97, 0x43, 0xE5, 0x86, 0x99, 0x43,
+ 0xE5, 0x86, 0xA4, 0x43, 0xE5, 0x86, 0xAB, 0x43,
+ 0xE5, 0x86, 0xAC, 0x43, 0xE5, 0x86, 0xB5, 0x43,
+ 0xE5, 0x86, 0xB7, 0x43, 0xE5, 0x87, 0x89, 0x43,
+ 0xE5, 0x87, 0x8C, 0x43, 0xE5, 0x87, 0x9C, 0x43,
+ 0xE5, 0x87, 0x9E, 0x43, 0xE5, 0x87, 0xA0, 0x43,
+ // Bytes 800 - 83f
+ 0xE5, 0x87, 0xB5, 0x43, 0xE5, 0x88, 0x80, 0x43,
+ 0xE5, 0x88, 0x83, 0x43, 0xE5, 0x88, 0x87, 0x43,
+ 0xE5, 0x88, 0x97, 0x43, 0xE5, 0x88, 0x9D, 0x43,
+ 0xE5, 0x88, 0xA9, 0x43, 0xE5, 0x88, 0xBA, 0x43,
+ 0xE5, 0x88, 0xBB, 0x43, 0xE5, 0x89, 0x86, 0x43,
+ 0xE5, 0x89, 0x8D, 0x43, 0xE5, 0x89, 0xB2, 0x43,
+ 0xE5, 0x89, 0xB7, 0x43, 0xE5, 0x8A, 0x89, 0x43,
+ 0xE5, 0x8A, 0x9B, 0x43, 0xE5, 0x8A, 0xA3, 0x43,
+ // Bytes 840 - 87f
+ 0xE5, 0x8A, 0xB3, 0x43, 0xE5, 0x8A, 0xB4, 0x43,
+ 0xE5, 0x8B, 0x87, 0x43, 0xE5, 0x8B, 0x89, 0x43,
+ 0xE5, 0x8B, 0x92, 0x43, 0xE5, 0x8B, 0x9E, 0x43,
+ 0xE5, 0x8B, 0xA4, 0x43, 0xE5, 0x8B, 0xB5, 0x43,
+ 0xE5, 0x8B, 0xB9, 0x43, 0xE5, 0x8B, 0xBA, 0x43,
+ 0xE5, 0x8C, 0x85, 0x43, 0xE5, 0x8C, 0x86, 0x43,
+ 0xE5, 0x8C, 0x95, 0x43, 0xE5, 0x8C, 0x97, 0x43,
+ 0xE5, 0x8C, 0x9A, 0x43, 0xE5, 0x8C, 0xB8, 0x43,
+ // Bytes 880 - 8bf
+ 0xE5, 0x8C, 0xBB, 0x43, 0xE5, 0x8C, 0xBF, 0x43,
+ 0xE5, 0x8D, 0x81, 0x43, 0xE5, 0x8D, 0x84, 0x43,
+ 0xE5, 0x8D, 0x85, 0x43, 0xE5, 0x8D, 0x89, 0x43,
+ 0xE5, 0x8D, 0x91, 0x43, 0xE5, 0x8D, 0x94, 0x43,
+ 0xE5, 0x8D, 0x9A, 0x43, 0xE5, 0x8D, 0x9C, 0x43,
+ 0xE5, 0x8D, 0xA9, 0x43, 0xE5, 0x8D, 0xB0, 0x43,
+ 0xE5, 0x8D, 0xB3, 0x43, 0xE5, 0x8D, 0xB5, 0x43,
+ 0xE5, 0x8D, 0xBD, 0x43, 0xE5, 0x8D, 0xBF, 0x43,
+ // Bytes 8c0 - 8ff
+ 0xE5, 0x8E, 0x82, 0x43, 0xE5, 0x8E, 0xB6, 0x43,
+ 0xE5, 0x8F, 0x83, 0x43, 0xE5, 0x8F, 0x88, 0x43,
+ 0xE5, 0x8F, 0x8A, 0x43, 0xE5, 0x8F, 0x8C, 0x43,
+ 0xE5, 0x8F, 0x9F, 0x43, 0xE5, 0x8F, 0xA3, 0x43,
+ 0xE5, 0x8F, 0xA5, 0x43, 0xE5, 0x8F, 0xAB, 0x43,
+ 0xE5, 0x8F, 0xAF, 0x43, 0xE5, 0x8F, 0xB1, 0x43,
+ 0xE5, 0x8F, 0xB3, 0x43, 0xE5, 0x90, 0x86, 0x43,
+ 0xE5, 0x90, 0x88, 0x43, 0xE5, 0x90, 0x8D, 0x43,
+ // Bytes 900 - 93f
+ 0xE5, 0x90, 0x8F, 0x43, 0xE5, 0x90, 0x9D, 0x43,
+ 0xE5, 0x90, 0xB8, 0x43, 0xE5, 0x90, 0xB9, 0x43,
+ 0xE5, 0x91, 0x82, 0x43, 0xE5, 0x91, 0x88, 0x43,
+ 0xE5, 0x91, 0xA8, 0x43, 0xE5, 0x92, 0x9E, 0x43,
+ 0xE5, 0x92, 0xA2, 0x43, 0xE5, 0x92, 0xBD, 0x43,
+ 0xE5, 0x93, 0xB6, 0x43, 0xE5, 0x94, 0x90, 0x43,
+ 0xE5, 0x95, 0x8F, 0x43, 0xE5, 0x95, 0x93, 0x43,
+ 0xE5, 0x95, 0x95, 0x43, 0xE5, 0x95, 0xA3, 0x43,
+ // Bytes 940 - 97f
+ 0xE5, 0x96, 0x84, 0x43, 0xE5, 0x96, 0x87, 0x43,
+ 0xE5, 0x96, 0x99, 0x43, 0xE5, 0x96, 0x9D, 0x43,
+ 0xE5, 0x96, 0xAB, 0x43, 0xE5, 0x96, 0xB3, 0x43,
+ 0xE5, 0x96, 0xB6, 0x43, 0xE5, 0x97, 0x80, 0x43,
+ 0xE5, 0x97, 0x82, 0x43, 0xE5, 0x97, 0xA2, 0x43,
+ 0xE5, 0x98, 0x86, 0x43, 0xE5, 0x99, 0x91, 0x43,
+ 0xE5, 0x99, 0xA8, 0x43, 0xE5, 0x99, 0xB4, 0x43,
+ 0xE5, 0x9B, 0x97, 0x43, 0xE5, 0x9B, 0x9B, 0x43,
+ // Bytes 980 - 9bf
+ 0xE5, 0x9B, 0xB9, 0x43, 0xE5, 0x9C, 0x96, 0x43,
+ 0xE5, 0x9C, 0x97, 0x43, 0xE5, 0x9C, 0x9F, 0x43,
+ 0xE5, 0x9C, 0xB0, 0x43, 0xE5, 0x9E, 0x8B, 0x43,
+ 0xE5, 0x9F, 0x8E, 0x43, 0xE5, 0x9F, 0xB4, 0x43,
+ 0xE5, 0xA0, 0x8D, 0x43, 0xE5, 0xA0, 0xB1, 0x43,
+ 0xE5, 0xA0, 0xB2, 0x43, 0xE5, 0xA1, 0x80, 0x43,
+ 0xE5, 0xA1, 0x9A, 0x43, 0xE5, 0xA1, 0x9E, 0x43,
+ 0xE5, 0xA2, 0xA8, 0x43, 0xE5, 0xA2, 0xAC, 0x43,
+ // Bytes 9c0 - 9ff
+ 0xE5, 0xA2, 0xB3, 0x43, 0xE5, 0xA3, 0x98, 0x43,
+ 0xE5, 0xA3, 0x9F, 0x43, 0xE5, 0xA3, 0xAB, 0x43,
+ 0xE5, 0xA3, 0xAE, 0x43, 0xE5, 0xA3, 0xB0, 0x43,
+ 0xE5, 0xA3, 0xB2, 0x43, 0xE5, 0xA3, 0xB7, 0x43,
+ 0xE5, 0xA4, 0x82, 0x43, 0xE5, 0xA4, 0x86, 0x43,
+ 0xE5, 0xA4, 0x8A, 0x43, 0xE5, 0xA4, 0x95, 0x43,
+ 0xE5, 0xA4, 0x9A, 0x43, 0xE5, 0xA4, 0x9C, 0x43,
+ 0xE5, 0xA4, 0xA2, 0x43, 0xE5, 0xA4, 0xA7, 0x43,
+ // Bytes a00 - a3f
+ 0xE5, 0xA4, 0xA9, 0x43, 0xE5, 0xA5, 0x84, 0x43,
+ 0xE5, 0xA5, 0x88, 0x43, 0xE5, 0xA5, 0x91, 0x43,
+ 0xE5, 0xA5, 0x94, 0x43, 0xE5, 0xA5, 0xA2, 0x43,
+ 0xE5, 0xA5, 0xB3, 0x43, 0xE5, 0xA7, 0x98, 0x43,
+ 0xE5, 0xA7, 0xAC, 0x43, 0xE5, 0xA8, 0x9B, 0x43,
+ 0xE5, 0xA8, 0xA7, 0x43, 0xE5, 0xA9, 0xA2, 0x43,
+ 0xE5, 0xA9, 0xA6, 0x43, 0xE5, 0xAA, 0xB5, 0x43,
+ 0xE5, 0xAC, 0x88, 0x43, 0xE5, 0xAC, 0xA8, 0x43,
+ // Bytes a40 - a7f
+ 0xE5, 0xAC, 0xBE, 0x43, 0xE5, 0xAD, 0x90, 0x43,
+ 0xE5, 0xAD, 0x97, 0x43, 0xE5, 0xAD, 0xA6, 0x43,
+ 0xE5, 0xAE, 0x80, 0x43, 0xE5, 0xAE, 0x85, 0x43,
+ 0xE5, 0xAE, 0x97, 0x43, 0xE5, 0xAF, 0x83, 0x43,
+ 0xE5, 0xAF, 0x98, 0x43, 0xE5, 0xAF, 0xA7, 0x43,
+ 0xE5, 0xAF, 0xAE, 0x43, 0xE5, 0xAF, 0xB3, 0x43,
+ 0xE5, 0xAF, 0xB8, 0x43, 0xE5, 0xAF, 0xBF, 0x43,
+ 0xE5, 0xB0, 0x86, 0x43, 0xE5, 0xB0, 0x8F, 0x43,
+ // Bytes a80 - abf
+ 0xE5, 0xB0, 0xA2, 0x43, 0xE5, 0xB0, 0xB8, 0x43,
+ 0xE5, 0xB0, 0xBF, 0x43, 0xE5, 0xB1, 0xA0, 0x43,
+ 0xE5, 0xB1, 0xA2, 0x43, 0xE5, 0xB1, 0xA4, 0x43,
+ 0xE5, 0xB1, 0xA5, 0x43, 0xE5, 0xB1, 0xAE, 0x43,
+ 0xE5, 0xB1, 0xB1, 0x43, 0xE5, 0xB2, 0x8D, 0x43,
+ 0xE5, 0xB3, 0x80, 0x43, 0xE5, 0xB4, 0x99, 0x43,
+ 0xE5, 0xB5, 0x83, 0x43, 0xE5, 0xB5, 0x90, 0x43,
+ 0xE5, 0xB5, 0xAB, 0x43, 0xE5, 0xB5, 0xAE, 0x43,
+ // Bytes ac0 - aff
+ 0xE5, 0xB5, 0xBC, 0x43, 0xE5, 0xB6, 0xB2, 0x43,
+ 0xE5, 0xB6, 0xBA, 0x43, 0xE5, 0xB7, 0x9B, 0x43,
+ 0xE5, 0xB7, 0xA1, 0x43, 0xE5, 0xB7, 0xA2, 0x43,
+ 0xE5, 0xB7, 0xA5, 0x43, 0xE5, 0xB7, 0xA6, 0x43,
+ 0xE5, 0xB7, 0xB1, 0x43, 0xE5, 0xB7, 0xBD, 0x43,
+ 0xE5, 0xB7, 0xBE, 0x43, 0xE5, 0xB8, 0xA8, 0x43,
+ 0xE5, 0xB8, 0xBD, 0x43, 0xE5, 0xB9, 0xA9, 0x43,
+ 0xE5, 0xB9, 0xB2, 0x43, 0xE5, 0xB9, 0xB4, 0x43,
+ // Bytes b00 - b3f
+ 0xE5, 0xB9, 0xBA, 0x43, 0xE5, 0xB9, 0xBC, 0x43,
+ 0xE5, 0xB9, 0xBF, 0x43, 0xE5, 0xBA, 0xA6, 0x43,
+ 0xE5, 0xBA, 0xB0, 0x43, 0xE5, 0xBA, 0xB3, 0x43,
+ 0xE5, 0xBA, 0xB6, 0x43, 0xE5, 0xBB, 0x89, 0x43,
+ 0xE5, 0xBB, 0x8A, 0x43, 0xE5, 0xBB, 0x92, 0x43,
+ 0xE5, 0xBB, 0x93, 0x43, 0xE5, 0xBB, 0x99, 0x43,
+ 0xE5, 0xBB, 0xAC, 0x43, 0xE5, 0xBB, 0xB4, 0x43,
+ 0xE5, 0xBB, 0xBE, 0x43, 0xE5, 0xBC, 0x84, 0x43,
+ // Bytes b40 - b7f
+ 0xE5, 0xBC, 0x8B, 0x43, 0xE5, 0xBC, 0x93, 0x43,
+ 0xE5, 0xBC, 0xA2, 0x43, 0xE5, 0xBD, 0x90, 0x43,
+ 0xE5, 0xBD, 0x93, 0x43, 0xE5, 0xBD, 0xA1, 0x43,
+ 0xE5, 0xBD, 0xA2, 0x43, 0xE5, 0xBD, 0xA9, 0x43,
+ 0xE5, 0xBD, 0xAB, 0x43, 0xE5, 0xBD, 0xB3, 0x43,
+ 0xE5, 0xBE, 0x8B, 0x43, 0xE5, 0xBE, 0x8C, 0x43,
+ 0xE5, 0xBE, 0x97, 0x43, 0xE5, 0xBE, 0x9A, 0x43,
+ 0xE5, 0xBE, 0xA9, 0x43, 0xE5, 0xBE, 0xAD, 0x43,
+ // Bytes b80 - bbf
+ 0xE5, 0xBF, 0x83, 0x43, 0xE5, 0xBF, 0x8D, 0x43,
+ 0xE5, 0xBF, 0x97, 0x43, 0xE5, 0xBF, 0xB5, 0x43,
+ 0xE5, 0xBF, 0xB9, 0x43, 0xE6, 0x80, 0x92, 0x43,
+ 0xE6, 0x80, 0x9C, 0x43, 0xE6, 0x81, 0xB5, 0x43,
+ 0xE6, 0x82, 0x81, 0x43, 0xE6, 0x82, 0x94, 0x43,
+ 0xE6, 0x83, 0x87, 0x43, 0xE6, 0x83, 0x98, 0x43,
+ 0xE6, 0x83, 0xA1, 0x43, 0xE6, 0x84, 0x88, 0x43,
+ 0xE6, 0x85, 0x84, 0x43, 0xE6, 0x85, 0x88, 0x43,
+ // Bytes bc0 - bff
+ 0xE6, 0x85, 0x8C, 0x43, 0xE6, 0x85, 0x8E, 0x43,
+ 0xE6, 0x85, 0xA0, 0x43, 0xE6, 0x85, 0xA8, 0x43,
+ 0xE6, 0x85, 0xBA, 0x43, 0xE6, 0x86, 0x8E, 0x43,
+ 0xE6, 0x86, 0x90, 0x43, 0xE6, 0x86, 0xA4, 0x43,
+ 0xE6, 0x86, 0xAF, 0x43, 0xE6, 0x86, 0xB2, 0x43,
+ 0xE6, 0x87, 0x9E, 0x43, 0xE6, 0x87, 0xB2, 0x43,
+ 0xE6, 0x87, 0xB6, 0x43, 0xE6, 0x88, 0x80, 0x43,
+ 0xE6, 0x88, 0x88, 0x43, 0xE6, 0x88, 0x90, 0x43,
+ // Bytes c00 - c3f
+ 0xE6, 0x88, 0x9B, 0x43, 0xE6, 0x88, 0xAE, 0x43,
+ 0xE6, 0x88, 0xB4, 0x43, 0xE6, 0x88, 0xB6, 0x43,
+ 0xE6, 0x89, 0x8B, 0x43, 0xE6, 0x89, 0x93, 0x43,
+ 0xE6, 0x89, 0x9D, 0x43, 0xE6, 0x8A, 0x95, 0x43,
+ 0xE6, 0x8A, 0xB1, 0x43, 0xE6, 0x8B, 0x89, 0x43,
+ 0xE6, 0x8B, 0x8F, 0x43, 0xE6, 0x8B, 0x93, 0x43,
+ 0xE6, 0x8B, 0x94, 0x43, 0xE6, 0x8B, 0xBC, 0x43,
+ 0xE6, 0x8B, 0xBE, 0x43, 0xE6, 0x8C, 0x87, 0x43,
+ // Bytes c40 - c7f
+ 0xE6, 0x8C, 0xBD, 0x43, 0xE6, 0x8D, 0x90, 0x43,
+ 0xE6, 0x8D, 0x95, 0x43, 0xE6, 0x8D, 0xA8, 0x43,
+ 0xE6, 0x8D, 0xBB, 0x43, 0xE6, 0x8E, 0x83, 0x43,
+ 0xE6, 0x8E, 0xA0, 0x43, 0xE6, 0x8E, 0xA9, 0x43,
+ 0xE6, 0x8F, 0x84, 0x43, 0xE6, 0x8F, 0x85, 0x43,
+ 0xE6, 0x8F, 0xA4, 0x43, 0xE6, 0x90, 0x9C, 0x43,
+ 0xE6, 0x90, 0xA2, 0x43, 0xE6, 0x91, 0x92, 0x43,
+ 0xE6, 0x91, 0xA9, 0x43, 0xE6, 0x91, 0xB7, 0x43,
+ // Bytes c80 - cbf
+ 0xE6, 0x91, 0xBE, 0x43, 0xE6, 0x92, 0x9A, 0x43,
+ 0xE6, 0x92, 0x9D, 0x43, 0xE6, 0x93, 0x84, 0x43,
+ 0xE6, 0x94, 0xAF, 0x43, 0xE6, 0x94, 0xB4, 0x43,
+ 0xE6, 0x95, 0x8F, 0x43, 0xE6, 0x95, 0x96, 0x43,
+ 0xE6, 0x95, 0xAC, 0x43, 0xE6, 0x95, 0xB8, 0x43,
+ 0xE6, 0x96, 0x87, 0x43, 0xE6, 0x96, 0x97, 0x43,
+ 0xE6, 0x96, 0x99, 0x43, 0xE6, 0x96, 0xA4, 0x43,
+ 0xE6, 0x96, 0xB0, 0x43, 0xE6, 0x96, 0xB9, 0x43,
+ // Bytes cc0 - cff
+ 0xE6, 0x97, 0x85, 0x43, 0xE6, 0x97, 0xA0, 0x43,
+ 0xE6, 0x97, 0xA2, 0x43, 0xE6, 0x97, 0xA3, 0x43,
+ 0xE6, 0x97, 0xA5, 0x43, 0xE6, 0x98, 0x93, 0x43,
+ 0xE6, 0x98, 0xA0, 0x43, 0xE6, 0x99, 0x89, 0x43,
+ 0xE6, 0x99, 0xB4, 0x43, 0xE6, 0x9A, 0x88, 0x43,
+ 0xE6, 0x9A, 0x91, 0x43, 0xE6, 0x9A, 0x9C, 0x43,
+ 0xE6, 0x9A, 0xB4, 0x43, 0xE6, 0x9B, 0x86, 0x43,
+ 0xE6, 0x9B, 0xB0, 0x43, 0xE6, 0x9B, 0xB4, 0x43,
+ // Bytes d00 - d3f
+ 0xE6, 0x9B, 0xB8, 0x43, 0xE6, 0x9C, 0x80, 0x43,
+ 0xE6, 0x9C, 0x88, 0x43, 0xE6, 0x9C, 0x89, 0x43,
+ 0xE6, 0x9C, 0x97, 0x43, 0xE6, 0x9C, 0x9B, 0x43,
+ 0xE6, 0x9C, 0xA1, 0x43, 0xE6, 0x9C, 0xA8, 0x43,
+ 0xE6, 0x9D, 0x8E, 0x43, 0xE6, 0x9D, 0x93, 0x43,
+ 0xE6, 0x9D, 0x96, 0x43, 0xE6, 0x9D, 0x9E, 0x43,
+ 0xE6, 0x9D, 0xBB, 0x43, 0xE6, 0x9E, 0x85, 0x43,
+ 0xE6, 0x9E, 0x97, 0x43, 0xE6, 0x9F, 0xB3, 0x43,
+ // Bytes d40 - d7f
+ 0xE6, 0x9F, 0xBA, 0x43, 0xE6, 0xA0, 0x97, 0x43,
+ 0xE6, 0xA0, 0x9F, 0x43, 0xE6, 0xA0, 0xAA, 0x43,
+ 0xE6, 0xA1, 0x92, 0x43, 0xE6, 0xA2, 0x81, 0x43,
+ 0xE6, 0xA2, 0x85, 0x43, 0xE6, 0xA2, 0x8E, 0x43,
+ 0xE6, 0xA2, 0xA8, 0x43, 0xE6, 0xA4, 0x94, 0x43,
+ 0xE6, 0xA5, 0x82, 0x43, 0xE6, 0xA6, 0xA3, 0x43,
+ 0xE6, 0xA7, 0xAA, 0x43, 0xE6, 0xA8, 0x82, 0x43,
+ 0xE6, 0xA8, 0x93, 0x43, 0xE6, 0xAA, 0xA8, 0x43,
+ // Bytes d80 - dbf
+ 0xE6, 0xAB, 0x93, 0x43, 0xE6, 0xAB, 0x9B, 0x43,
+ 0xE6, 0xAC, 0x84, 0x43, 0xE6, 0xAC, 0xA0, 0x43,
+ 0xE6, 0xAC, 0xA1, 0x43, 0xE6, 0xAD, 0x94, 0x43,
+ 0xE6, 0xAD, 0xA2, 0x43, 0xE6, 0xAD, 0xA3, 0x43,
+ 0xE6, 0xAD, 0xB2, 0x43, 0xE6, 0xAD, 0xB7, 0x43,
+ 0xE6, 0xAD, 0xB9, 0x43, 0xE6, 0xAE, 0x9F, 0x43,
+ 0xE6, 0xAE, 0xAE, 0x43, 0xE6, 0xAE, 0xB3, 0x43,
+ 0xE6, 0xAE, 0xBA, 0x43, 0xE6, 0xAE, 0xBB, 0x43,
+ // Bytes dc0 - dff
+ 0xE6, 0xAF, 0x8B, 0x43, 0xE6, 0xAF, 0x8D, 0x43,
+ 0xE6, 0xAF, 0x94, 0x43, 0xE6, 0xAF, 0x9B, 0x43,
+ 0xE6, 0xB0, 0x8F, 0x43, 0xE6, 0xB0, 0x94, 0x43,
+ 0xE6, 0xB0, 0xB4, 0x43, 0xE6, 0xB1, 0x8E, 0x43,
+ 0xE6, 0xB1, 0xA7, 0x43, 0xE6, 0xB2, 0x88, 0x43,
+ 0xE6, 0xB2, 0xBF, 0x43, 0xE6, 0xB3, 0x8C, 0x43,
+ 0xE6, 0xB3, 0x8D, 0x43, 0xE6, 0xB3, 0xA5, 0x43,
+ 0xE6, 0xB3, 0xA8, 0x43, 0xE6, 0xB4, 0x96, 0x43,
+ // Bytes e00 - e3f
+ 0xE6, 0xB4, 0x9B, 0x43, 0xE6, 0xB4, 0x9E, 0x43,
+ 0xE6, 0xB4, 0xB4, 0x43, 0xE6, 0xB4, 0xBE, 0x43,
+ 0xE6, 0xB5, 0x81, 0x43, 0xE6, 0xB5, 0xA9, 0x43,
+ 0xE6, 0xB5, 0xAA, 0x43, 0xE6, 0xB5, 0xB7, 0x43,
+ 0xE6, 0xB5, 0xB8, 0x43, 0xE6, 0xB6, 0x85, 0x43,
+ 0xE6, 0xB7, 0x8B, 0x43, 0xE6, 0xB7, 0x9A, 0x43,
+ 0xE6, 0xB7, 0xAA, 0x43, 0xE6, 0xB7, 0xB9, 0x43,
+ 0xE6, 0xB8, 0x9A, 0x43, 0xE6, 0xB8, 0xAF, 0x43,
+ // Bytes e40 - e7f
+ 0xE6, 0xB9, 0xAE, 0x43, 0xE6, 0xBA, 0x80, 0x43,
+ 0xE6, 0xBA, 0x9C, 0x43, 0xE6, 0xBA, 0xBA, 0x43,
+ 0xE6, 0xBB, 0x87, 0x43, 0xE6, 0xBB, 0x8B, 0x43,
+ 0xE6, 0xBB, 0x91, 0x43, 0xE6, 0xBB, 0x9B, 0x43,
+ 0xE6, 0xBC, 0x8F, 0x43, 0xE6, 0xBC, 0x94, 0x43,
+ 0xE6, 0xBC, 0xA2, 0x43, 0xE6, 0xBC, 0xA3, 0x43,
+ 0xE6, 0xBD, 0xAE, 0x43, 0xE6, 0xBF, 0x86, 0x43,
+ 0xE6, 0xBF, 0xAB, 0x43, 0xE6, 0xBF, 0xBE, 0x43,
+ // Bytes e80 - ebf
+ 0xE7, 0x80, 0x9B, 0x43, 0xE7, 0x80, 0x9E, 0x43,
+ 0xE7, 0x80, 0xB9, 0x43, 0xE7, 0x81, 0x8A, 0x43,
+ 0xE7, 0x81, 0xAB, 0x43, 0xE7, 0x81, 0xB0, 0x43,
+ 0xE7, 0x81, 0xB7, 0x43, 0xE7, 0x81, 0xBD, 0x43,
+ 0xE7, 0x82, 0x99, 0x43, 0xE7, 0x82, 0xAD, 0x43,
+ 0xE7, 0x83, 0x88, 0x43, 0xE7, 0x83, 0x99, 0x43,
+ 0xE7, 0x84, 0xA1, 0x43, 0xE7, 0x85, 0x85, 0x43,
+ 0xE7, 0x85, 0x89, 0x43, 0xE7, 0x85, 0xAE, 0x43,
+ // Bytes ec0 - eff
+ 0xE7, 0x86, 0x9C, 0x43, 0xE7, 0x87, 0x8E, 0x43,
+ 0xE7, 0x87, 0x90, 0x43, 0xE7, 0x88, 0x90, 0x43,
+ 0xE7, 0x88, 0x9B, 0x43, 0xE7, 0x88, 0xA8, 0x43,
+ 0xE7, 0x88, 0xAA, 0x43, 0xE7, 0x88, 0xAB, 0x43,
+ 0xE7, 0x88, 0xB5, 0x43, 0xE7, 0x88, 0xB6, 0x43,
+ 0xE7, 0x88, 0xBB, 0x43, 0xE7, 0x88, 0xBF, 0x43,
+ 0xE7, 0x89, 0x87, 0x43, 0xE7, 0x89, 0x90, 0x43,
+ 0xE7, 0x89, 0x99, 0x43, 0xE7, 0x89, 0x9B, 0x43,
+ // Bytes f00 - f3f
+ 0xE7, 0x89, 0xA2, 0x43, 0xE7, 0x89, 0xB9, 0x43,
+ 0xE7, 0x8A, 0x80, 0x43, 0xE7, 0x8A, 0x95, 0x43,
+ 0xE7, 0x8A, 0xAC, 0x43, 0xE7, 0x8A, 0xAF, 0x43,
+ 0xE7, 0x8B, 0x80, 0x43, 0xE7, 0x8B, 0xBC, 0x43,
+ 0xE7, 0x8C, 0xAA, 0x43, 0xE7, 0x8D, 0xB5, 0x43,
+ 0xE7, 0x8D, 0xBA, 0x43, 0xE7, 0x8E, 0x84, 0x43,
+ 0xE7, 0x8E, 0x87, 0x43, 0xE7, 0x8E, 0x89, 0x43,
+ 0xE7, 0x8E, 0x8B, 0x43, 0xE7, 0x8E, 0xA5, 0x43,
+ // Bytes f40 - f7f
+ 0xE7, 0x8E, 0xB2, 0x43, 0xE7, 0x8F, 0x9E, 0x43,
+ 0xE7, 0x90, 0x86, 0x43, 0xE7, 0x90, 0x89, 0x43,
+ 0xE7, 0x90, 0xA2, 0x43, 0xE7, 0x91, 0x87, 0x43,
+ 0xE7, 0x91, 0x9C, 0x43, 0xE7, 0x91, 0xA9, 0x43,
+ 0xE7, 0x91, 0xB1, 0x43, 0xE7, 0x92, 0x85, 0x43,
+ 0xE7, 0x92, 0x89, 0x43, 0xE7, 0x92, 0x98, 0x43,
+ 0xE7, 0x93, 0x8A, 0x43, 0xE7, 0x93, 0x9C, 0x43,
+ 0xE7, 0x93, 0xA6, 0x43, 0xE7, 0x94, 0x86, 0x43,
+ // Bytes f80 - fbf
+ 0xE7, 0x94, 0x98, 0x43, 0xE7, 0x94, 0x9F, 0x43,
+ 0xE7, 0x94, 0xA4, 0x43, 0xE7, 0x94, 0xA8, 0x43,
+ 0xE7, 0x94, 0xB0, 0x43, 0xE7, 0x94, 0xB2, 0x43,
+ 0xE7, 0x94, 0xB3, 0x43, 0xE7, 0x94, 0xB7, 0x43,
+ 0xE7, 0x94, 0xBB, 0x43, 0xE7, 0x94, 0xBE, 0x43,
+ 0xE7, 0x95, 0x99, 0x43, 0xE7, 0x95, 0xA5, 0x43,
+ 0xE7, 0x95, 0xB0, 0x43, 0xE7, 0x96, 0x8B, 0x43,
+ 0xE7, 0x96, 0x92, 0x43, 0xE7, 0x97, 0xA2, 0x43,
+ // Bytes fc0 - fff
+ 0xE7, 0x98, 0x90, 0x43, 0xE7, 0x98, 0x9D, 0x43,
+ 0xE7, 0x98, 0x9F, 0x43, 0xE7, 0x99, 0x82, 0x43,
+ 0xE7, 0x99, 0xA9, 0x43, 0xE7, 0x99, 0xB6, 0x43,
+ 0xE7, 0x99, 0xBD, 0x43, 0xE7, 0x9A, 0xAE, 0x43,
+ 0xE7, 0x9A, 0xBF, 0x43, 0xE7, 0x9B, 0x8A, 0x43,
+ 0xE7, 0x9B, 0x9B, 0x43, 0xE7, 0x9B, 0xA3, 0x43,
+ 0xE7, 0x9B, 0xA7, 0x43, 0xE7, 0x9B, 0xAE, 0x43,
+ 0xE7, 0x9B, 0xB4, 0x43, 0xE7, 0x9C, 0x81, 0x43,
+ // Bytes 1000 - 103f
+ 0xE7, 0x9C, 0x9E, 0x43, 0xE7, 0x9C, 0x9F, 0x43,
+ 0xE7, 0x9D, 0x80, 0x43, 0xE7, 0x9D, 0x8A, 0x43,
+ 0xE7, 0x9E, 0x8B, 0x43, 0xE7, 0x9E, 0xA7, 0x43,
+ 0xE7, 0x9F, 0x9B, 0x43, 0xE7, 0x9F, 0xA2, 0x43,
+ 0xE7, 0x9F, 0xB3, 0x43, 0xE7, 0xA1, 0x8E, 0x43,
+ 0xE7, 0xA1, 0xAB, 0x43, 0xE7, 0xA2, 0x8C, 0x43,
+ 0xE7, 0xA2, 0x91, 0x43, 0xE7, 0xA3, 0x8A, 0x43,
+ 0xE7, 0xA3, 0x8C, 0x43, 0xE7, 0xA3, 0xBB, 0x43,
+ // Bytes 1040 - 107f
+ 0xE7, 0xA4, 0xAA, 0x43, 0xE7, 0xA4, 0xBA, 0x43,
+ 0xE7, 0xA4, 0xBC, 0x43, 0xE7, 0xA4, 0xBE, 0x43,
+ 0xE7, 0xA5, 0x88, 0x43, 0xE7, 0xA5, 0x89, 0x43,
+ 0xE7, 0xA5, 0x90, 0x43, 0xE7, 0xA5, 0x96, 0x43,
+ 0xE7, 0xA5, 0x9D, 0x43, 0xE7, 0xA5, 0x9E, 0x43,
+ 0xE7, 0xA5, 0xA5, 0x43, 0xE7, 0xA5, 0xBF, 0x43,
+ 0xE7, 0xA6, 0x81, 0x43, 0xE7, 0xA6, 0x8D, 0x43,
+ 0xE7, 0xA6, 0x8E, 0x43, 0xE7, 0xA6, 0x8F, 0x43,
+ // Bytes 1080 - 10bf
+ 0xE7, 0xA6, 0xAE, 0x43, 0xE7, 0xA6, 0xB8, 0x43,
+ 0xE7, 0xA6, 0xBE, 0x43, 0xE7, 0xA7, 0x8A, 0x43,
+ 0xE7, 0xA7, 0x98, 0x43, 0xE7, 0xA7, 0xAB, 0x43,
+ 0xE7, 0xA8, 0x9C, 0x43, 0xE7, 0xA9, 0x80, 0x43,
+ 0xE7, 0xA9, 0x8A, 0x43, 0xE7, 0xA9, 0x8F, 0x43,
+ 0xE7, 0xA9, 0xB4, 0x43, 0xE7, 0xA9, 0xBA, 0x43,
+ 0xE7, 0xAA, 0x81, 0x43, 0xE7, 0xAA, 0xB1, 0x43,
+ 0xE7, 0xAB, 0x8B, 0x43, 0xE7, 0xAB, 0xAE, 0x43,
+ // Bytes 10c0 - 10ff
+ 0xE7, 0xAB, 0xB9, 0x43, 0xE7, 0xAC, 0xA0, 0x43,
+ 0xE7, 0xAE, 0x8F, 0x43, 0xE7, 0xAF, 0x80, 0x43,
+ 0xE7, 0xAF, 0x86, 0x43, 0xE7, 0xAF, 0x89, 0x43,
+ 0xE7, 0xB0, 0xBE, 0x43, 0xE7, 0xB1, 0xA0, 0x43,
+ 0xE7, 0xB1, 0xB3, 0x43, 0xE7, 0xB1, 0xBB, 0x43,
+ 0xE7, 0xB2, 0x92, 0x43, 0xE7, 0xB2, 0xBE, 0x43,
+ 0xE7, 0xB3, 0x92, 0x43, 0xE7, 0xB3, 0x96, 0x43,
+ 0xE7, 0xB3, 0xA3, 0x43, 0xE7, 0xB3, 0xA7, 0x43,
+ // Bytes 1100 - 113f
+ 0xE7, 0xB3, 0xA8, 0x43, 0xE7, 0xB3, 0xB8, 0x43,
+ 0xE7, 0xB4, 0x80, 0x43, 0xE7, 0xB4, 0x90, 0x43,
+ 0xE7, 0xB4, 0xA2, 0x43, 0xE7, 0xB4, 0xAF, 0x43,
+ 0xE7, 0xB5, 0x82, 0x43, 0xE7, 0xB5, 0x9B, 0x43,
+ 0xE7, 0xB5, 0xA3, 0x43, 0xE7, 0xB6, 0xA0, 0x43,
+ 0xE7, 0xB6, 0xBE, 0x43, 0xE7, 0xB7, 0x87, 0x43,
+ 0xE7, 0xB7, 0xB4, 0x43, 0xE7, 0xB8, 0x82, 0x43,
+ 0xE7, 0xB8, 0x89, 0x43, 0xE7, 0xB8, 0xB7, 0x43,
+ // Bytes 1140 - 117f
+ 0xE7, 0xB9, 0x81, 0x43, 0xE7, 0xB9, 0x85, 0x43,
+ 0xE7, 0xBC, 0xB6, 0x43, 0xE7, 0xBC, 0xBE, 0x43,
+ 0xE7, 0xBD, 0x91, 0x43, 0xE7, 0xBD, 0xB2, 0x43,
+ 0xE7, 0xBD, 0xB9, 0x43, 0xE7, 0xBD, 0xBA, 0x43,
+ 0xE7, 0xBE, 0x85, 0x43, 0xE7, 0xBE, 0x8A, 0x43,
+ 0xE7, 0xBE, 0x95, 0x43, 0xE7, 0xBE, 0x9A, 0x43,
+ 0xE7, 0xBE, 0xBD, 0x43, 0xE7, 0xBF, 0xBA, 0x43,
+ 0xE8, 0x80, 0x81, 0x43, 0xE8, 0x80, 0x85, 0x43,
+ // Bytes 1180 - 11bf
+ 0xE8, 0x80, 0x8C, 0x43, 0xE8, 0x80, 0x92, 0x43,
+ 0xE8, 0x80, 0xB3, 0x43, 0xE8, 0x81, 0x86, 0x43,
+ 0xE8, 0x81, 0xA0, 0x43, 0xE8, 0x81, 0xAF, 0x43,
+ 0xE8, 0x81, 0xB0, 0x43, 0xE8, 0x81, 0xBE, 0x43,
+ 0xE8, 0x81, 0xBF, 0x43, 0xE8, 0x82, 0x89, 0x43,
+ 0xE8, 0x82, 0x8B, 0x43, 0xE8, 0x82, 0xAD, 0x43,
+ 0xE8, 0x82, 0xB2, 0x43, 0xE8, 0x84, 0x83, 0x43,
+ 0xE8, 0x84, 0xBE, 0x43, 0xE8, 0x87, 0x98, 0x43,
+ // Bytes 11c0 - 11ff
+ 0xE8, 0x87, 0xA3, 0x43, 0xE8, 0x87, 0xA8, 0x43,
+ 0xE8, 0x87, 0xAA, 0x43, 0xE8, 0x87, 0xAD, 0x43,
+ 0xE8, 0x87, 0xB3, 0x43, 0xE8, 0x87, 0xBC, 0x43,
+ 0xE8, 0x88, 0x81, 0x43, 0xE8, 0x88, 0x84, 0x43,
+ 0xE8, 0x88, 0x8C, 0x43, 0xE8, 0x88, 0x98, 0x43,
+ 0xE8, 0x88, 0x9B, 0x43, 0xE8, 0x88, 0x9F, 0x43,
+ 0xE8, 0x89, 0xAE, 0x43, 0xE8, 0x89, 0xAF, 0x43,
+ 0xE8, 0x89, 0xB2, 0x43, 0xE8, 0x89, 0xB8, 0x43,
+ // Bytes 1200 - 123f
+ 0xE8, 0x89, 0xB9, 0x43, 0xE8, 0x8A, 0x8B, 0x43,
+ 0xE8, 0x8A, 0x91, 0x43, 0xE8, 0x8A, 0x9D, 0x43,
+ 0xE8, 0x8A, 0xB1, 0x43, 0xE8, 0x8A, 0xB3, 0x43,
+ 0xE8, 0x8A, 0xBD, 0x43, 0xE8, 0x8B, 0xA5, 0x43,
+ 0xE8, 0x8B, 0xA6, 0x43, 0xE8, 0x8C, 0x9D, 0x43,
+ 0xE8, 0x8C, 0xA3, 0x43, 0xE8, 0x8C, 0xB6, 0x43,
+ 0xE8, 0x8D, 0x92, 0x43, 0xE8, 0x8D, 0x93, 0x43,
+ 0xE8, 0x8D, 0xA3, 0x43, 0xE8, 0x8E, 0xAD, 0x43,
+ // Bytes 1240 - 127f
+ 0xE8, 0x8E, 0xBD, 0x43, 0xE8, 0x8F, 0x89, 0x43,
+ 0xE8, 0x8F, 0x8A, 0x43, 0xE8, 0x8F, 0x8C, 0x43,
+ 0xE8, 0x8F, 0x9C, 0x43, 0xE8, 0x8F, 0xA7, 0x43,
+ 0xE8, 0x8F, 0xAF, 0x43, 0xE8, 0x8F, 0xB1, 0x43,
+ 0xE8, 0x90, 0xBD, 0x43, 0xE8, 0x91, 0x89, 0x43,
+ 0xE8, 0x91, 0x97, 0x43, 0xE8, 0x93, 0xAE, 0x43,
+ 0xE8, 0x93, 0xB1, 0x43, 0xE8, 0x93, 0xB3, 0x43,
+ 0xE8, 0x93, 0xBC, 0x43, 0xE8, 0x94, 0x96, 0x43,
+ // Bytes 1280 - 12bf
+ 0xE8, 0x95, 0xA4, 0x43, 0xE8, 0x97, 0x8D, 0x43,
+ 0xE8, 0x97, 0xBA, 0x43, 0xE8, 0x98, 0x86, 0x43,
+ 0xE8, 0x98, 0x92, 0x43, 0xE8, 0x98, 0xAD, 0x43,
+ 0xE8, 0x98, 0xBF, 0x43, 0xE8, 0x99, 0x8D, 0x43,
+ 0xE8, 0x99, 0x90, 0x43, 0xE8, 0x99, 0x9C, 0x43,
+ 0xE8, 0x99, 0xA7, 0x43, 0xE8, 0x99, 0xA9, 0x43,
+ 0xE8, 0x99, 0xAB, 0x43, 0xE8, 0x9A, 0x88, 0x43,
+ 0xE8, 0x9A, 0xA9, 0x43, 0xE8, 0x9B, 0xA2, 0x43,
+ // Bytes 12c0 - 12ff
+ 0xE8, 0x9C, 0x8E, 0x43, 0xE8, 0x9C, 0xA8, 0x43,
+ 0xE8, 0x9D, 0xAB, 0x43, 0xE8, 0x9D, 0xB9, 0x43,
+ 0xE8, 0x9E, 0x86, 0x43, 0xE8, 0x9E, 0xBA, 0x43,
+ 0xE8, 0x9F, 0xA1, 0x43, 0xE8, 0xA0, 0x81, 0x43,
+ 0xE8, 0xA0, 0x9F, 0x43, 0xE8, 0xA1, 0x80, 0x43,
+ 0xE8, 0xA1, 0x8C, 0x43, 0xE8, 0xA1, 0xA0, 0x43,
+ 0xE8, 0xA1, 0xA3, 0x43, 0xE8, 0xA3, 0x82, 0x43,
+ 0xE8, 0xA3, 0x8F, 0x43, 0xE8, 0xA3, 0x97, 0x43,
+ // Bytes 1300 - 133f
+ 0xE8, 0xA3, 0x9E, 0x43, 0xE8, 0xA3, 0xA1, 0x43,
+ 0xE8, 0xA3, 0xB8, 0x43, 0xE8, 0xA3, 0xBA, 0x43,
+ 0xE8, 0xA4, 0x90, 0x43, 0xE8, 0xA5, 0x81, 0x43,
+ 0xE8, 0xA5, 0xA4, 0x43, 0xE8, 0xA5, 0xBE, 0x43,
+ 0xE8, 0xA6, 0x86, 0x43, 0xE8, 0xA6, 0x8B, 0x43,
+ 0xE8, 0xA6, 0x96, 0x43, 0xE8, 0xA7, 0x92, 0x43,
+ 0xE8, 0xA7, 0xA3, 0x43, 0xE8, 0xA8, 0x80, 0x43,
+ 0xE8, 0xAA, 0xA0, 0x43, 0xE8, 0xAA, 0xAA, 0x43,
+ // Bytes 1340 - 137f
+ 0xE8, 0xAA, 0xBF, 0x43, 0xE8, 0xAB, 0x8B, 0x43,
+ 0xE8, 0xAB, 0x92, 0x43, 0xE8, 0xAB, 0x96, 0x43,
+ 0xE8, 0xAB, 0xAD, 0x43, 0xE8, 0xAB, 0xB8, 0x43,
+ 0xE8, 0xAB, 0xBE, 0x43, 0xE8, 0xAC, 0x81, 0x43,
+ 0xE8, 0xAC, 0xB9, 0x43, 0xE8, 0xAD, 0x98, 0x43,
+ 0xE8, 0xAE, 0x80, 0x43, 0xE8, 0xAE, 0x8A, 0x43,
+ 0xE8, 0xB0, 0xB7, 0x43, 0xE8, 0xB1, 0x86, 0x43,
+ 0xE8, 0xB1, 0x88, 0x43, 0xE8, 0xB1, 0x95, 0x43,
+ // Bytes 1380 - 13bf
+ 0xE8, 0xB1, 0xB8, 0x43, 0xE8, 0xB2, 0x9D, 0x43,
+ 0xE8, 0xB2, 0xA1, 0x43, 0xE8, 0xB2, 0xA9, 0x43,
+ 0xE8, 0xB2, 0xAB, 0x43, 0xE8, 0xB3, 0x81, 0x43,
+ 0xE8, 0xB3, 0x82, 0x43, 0xE8, 0xB3, 0x87, 0x43,
+ 0xE8, 0xB3, 0x88, 0x43, 0xE8, 0xB3, 0x93, 0x43,
+ 0xE8, 0xB4, 0x88, 0x43, 0xE8, 0xB4, 0x9B, 0x43,
+ 0xE8, 0xB5, 0xA4, 0x43, 0xE8, 0xB5, 0xB0, 0x43,
+ 0xE8, 0xB5, 0xB7, 0x43, 0xE8, 0xB6, 0xB3, 0x43,
+ // Bytes 13c0 - 13ff
+ 0xE8, 0xB6, 0xBC, 0x43, 0xE8, 0xB7, 0x8B, 0x43,
+ 0xE8, 0xB7, 0xAF, 0x43, 0xE8, 0xB7, 0xB0, 0x43,
+ 0xE8, 0xBA, 0xAB, 0x43, 0xE8, 0xBB, 0x8A, 0x43,
+ 0xE8, 0xBB, 0x94, 0x43, 0xE8, 0xBC, 0xA6, 0x43,
+ 0xE8, 0xBC, 0xAA, 0x43, 0xE8, 0xBC, 0xB8, 0x43,
+ 0xE8, 0xBC, 0xBB, 0x43, 0xE8, 0xBD, 0xA2, 0x43,
+ 0xE8, 0xBE, 0x9B, 0x43, 0xE8, 0xBE, 0x9E, 0x43,
+ 0xE8, 0xBE, 0xB0, 0x43, 0xE8, 0xBE, 0xB5, 0x43,
+ // Bytes 1400 - 143f
+ 0xE8, 0xBE, 0xB6, 0x43, 0xE9, 0x80, 0xA3, 0x43,
+ 0xE9, 0x80, 0xB8, 0x43, 0xE9, 0x81, 0x8A, 0x43,
+ 0xE9, 0x81, 0xA9, 0x43, 0xE9, 0x81, 0xB2, 0x43,
+ 0xE9, 0x81, 0xBC, 0x43, 0xE9, 0x82, 0x8F, 0x43,
+ 0xE9, 0x82, 0x91, 0x43, 0xE9, 0x82, 0x94, 0x43,
+ 0xE9, 0x83, 0x8E, 0x43, 0xE9, 0x83, 0x9E, 0x43,
+ 0xE9, 0x83, 0xB1, 0x43, 0xE9, 0x83, 0xBD, 0x43,
+ 0xE9, 0x84, 0x91, 0x43, 0xE9, 0x84, 0x9B, 0x43,
+ // Bytes 1440 - 147f
+ 0xE9, 0x85, 0x89, 0x43, 0xE9, 0x85, 0x8D, 0x43,
+ 0xE9, 0x85, 0xAA, 0x43, 0xE9, 0x86, 0x99, 0x43,
+ 0xE9, 0x86, 0xB4, 0x43, 0xE9, 0x87, 0x86, 0x43,
+ 0xE9, 0x87, 0x8C, 0x43, 0xE9, 0x87, 0x8F, 0x43,
+ 0xE9, 0x87, 0x91, 0x43, 0xE9, 0x88, 0xB4, 0x43,
+ 0xE9, 0x88, 0xB8, 0x43, 0xE9, 0x89, 0xB6, 0x43,
+ 0xE9, 0x89, 0xBC, 0x43, 0xE9, 0x8B, 0x97, 0x43,
+ 0xE9, 0x8B, 0x98, 0x43, 0xE9, 0x8C, 0x84, 0x43,
+ // Bytes 1480 - 14bf
+ 0xE9, 0x8D, 0x8A, 0x43, 0xE9, 0x8F, 0xB9, 0x43,
+ 0xE9, 0x90, 0x95, 0x43, 0xE9, 0x95, 0xB7, 0x43,
+ 0xE9, 0x96, 0x80, 0x43, 0xE9, 0x96, 0x8B, 0x43,
+ 0xE9, 0x96, 0xAD, 0x43, 0xE9, 0x96, 0xB7, 0x43,
+ 0xE9, 0x98, 0x9C, 0x43, 0xE9, 0x98, 0xAE, 0x43,
+ 0xE9, 0x99, 0x8B, 0x43, 0xE9, 0x99, 0x8D, 0x43,
+ 0xE9, 0x99, 0xB5, 0x43, 0xE9, 0x99, 0xB8, 0x43,
+ 0xE9, 0x99, 0xBC, 0x43, 0xE9, 0x9A, 0x86, 0x43,
+ // Bytes 14c0 - 14ff
+ 0xE9, 0x9A, 0xA3, 0x43, 0xE9, 0x9A, 0xB6, 0x43,
+ 0xE9, 0x9A, 0xB7, 0x43, 0xE9, 0x9A, 0xB8, 0x43,
+ 0xE9, 0x9A, 0xB9, 0x43, 0xE9, 0x9B, 0x83, 0x43,
+ 0xE9, 0x9B, 0xA2, 0x43, 0xE9, 0x9B, 0xA3, 0x43,
+ 0xE9, 0x9B, 0xA8, 0x43, 0xE9, 0x9B, 0xB6, 0x43,
+ 0xE9, 0x9B, 0xB7, 0x43, 0xE9, 0x9C, 0xA3, 0x43,
+ 0xE9, 0x9C, 0xB2, 0x43, 0xE9, 0x9D, 0x88, 0x43,
+ 0xE9, 0x9D, 0x91, 0x43, 0xE9, 0x9D, 0x96, 0x43,
+ // Bytes 1500 - 153f
+ 0xE9, 0x9D, 0x9E, 0x43, 0xE9, 0x9D, 0xA2, 0x43,
+ 0xE9, 0x9D, 0xA9, 0x43, 0xE9, 0x9F, 0x8B, 0x43,
+ 0xE9, 0x9F, 0x9B, 0x43, 0xE9, 0x9F, 0xA0, 0x43,
+ 0xE9, 0x9F, 0xAD, 0x43, 0xE9, 0x9F, 0xB3, 0x43,
+ 0xE9, 0x9F, 0xBF, 0x43, 0xE9, 0xA0, 0x81, 0x43,
+ 0xE9, 0xA0, 0x85, 0x43, 0xE9, 0xA0, 0x8B, 0x43,
+ 0xE9, 0xA0, 0x98, 0x43, 0xE9, 0xA0, 0xA9, 0x43,
+ 0xE9, 0xA0, 0xBB, 0x43, 0xE9, 0xA1, 0x9E, 0x43,
+ // Bytes 1540 - 157f
+ 0xE9, 0xA2, 0xA8, 0x43, 0xE9, 0xA3, 0x9B, 0x43,
+ 0xE9, 0xA3, 0x9F, 0x43, 0xE9, 0xA3, 0xA2, 0x43,
+ 0xE9, 0xA3, 0xAF, 0x43, 0xE9, 0xA3, 0xBC, 0x43,
+ 0xE9, 0xA4, 0xA8, 0x43, 0xE9, 0xA4, 0xA9, 0x43,
+ 0xE9, 0xA6, 0x96, 0x43, 0xE9, 0xA6, 0x99, 0x43,
+ 0xE9, 0xA6, 0xA7, 0x43, 0xE9, 0xA6, 0xAC, 0x43,
+ 0xE9, 0xA7, 0x82, 0x43, 0xE9, 0xA7, 0xB1, 0x43,
+ 0xE9, 0xA7, 0xBE, 0x43, 0xE9, 0xA9, 0xAA, 0x43,
+ // Bytes 1580 - 15bf
+ 0xE9, 0xAA, 0xA8, 0x43, 0xE9, 0xAB, 0x98, 0x43,
+ 0xE9, 0xAB, 0x9F, 0x43, 0xE9, 0xAC, 0x92, 0x43,
+ 0xE9, 0xAC, 0xA5, 0x43, 0xE9, 0xAC, 0xAF, 0x43,
+ 0xE9, 0xAC, 0xB2, 0x43, 0xE9, 0xAC, 0xBC, 0x43,
+ 0xE9, 0xAD, 0x9A, 0x43, 0xE9, 0xAD, 0xAF, 0x43,
+ 0xE9, 0xB1, 0x80, 0x43, 0xE9, 0xB1, 0x97, 0x43,
+ 0xE9, 0xB3, 0xA5, 0x43, 0xE9, 0xB3, 0xBD, 0x43,
+ 0xE9, 0xB5, 0xA7, 0x43, 0xE9, 0xB6, 0xB4, 0x43,
+ // Bytes 15c0 - 15ff
+ 0xE9, 0xB7, 0xBA, 0x43, 0xE9, 0xB8, 0x9E, 0x43,
+ 0xE9, 0xB9, 0xB5, 0x43, 0xE9, 0xB9, 0xBF, 0x43,
+ 0xE9, 0xBA, 0x97, 0x43, 0xE9, 0xBA, 0x9F, 0x43,
+ 0xE9, 0xBA, 0xA5, 0x43, 0xE9, 0xBA, 0xBB, 0x43,
+ 0xE9, 0xBB, 0x83, 0x43, 0xE9, 0xBB, 0x8D, 0x43,
+ 0xE9, 0xBB, 0x8E, 0x43, 0xE9, 0xBB, 0x91, 0x43,
+ 0xE9, 0xBB, 0xB9, 0x43, 0xE9, 0xBB, 0xBD, 0x43,
+ 0xE9, 0xBB, 0xBE, 0x43, 0xE9, 0xBC, 0x85, 0x43,
+ // Bytes 1600 - 163f
+ 0xE9, 0xBC, 0x8E, 0x43, 0xE9, 0xBC, 0x8F, 0x43,
+ 0xE9, 0xBC, 0x93, 0x43, 0xE9, 0xBC, 0x96, 0x43,
+ 0xE9, 0xBC, 0xA0, 0x43, 0xE9, 0xBC, 0xBB, 0x43,
+ 0xE9, 0xBD, 0x83, 0x43, 0xE9, 0xBD, 0x8A, 0x43,
+ 0xE9, 0xBD, 0x92, 0x43, 0xE9, 0xBE, 0x8D, 0x43,
+ 0xE9, 0xBE, 0x8E, 0x43, 0xE9, 0xBE, 0x9C, 0x43,
+ 0xE9, 0xBE, 0x9F, 0x43, 0xE9, 0xBE, 0xA0, 0x43,
+ 0xEA, 0x9C, 0xA7, 0x43, 0xEA, 0x9D, 0xAF, 0x43,
+ // Bytes 1640 - 167f
+ 0xEA, 0xAC, 0xB7, 0x43, 0xEA, 0xAD, 0x92, 0x44,
+ 0xF0, 0xA0, 0x84, 0xA2, 0x44, 0xF0, 0xA0, 0x94,
+ 0x9C, 0x44, 0xF0, 0xA0, 0x94, 0xA5, 0x44, 0xF0,
+ 0xA0, 0x95, 0x8B, 0x44, 0xF0, 0xA0, 0x98, 0xBA,
+ 0x44, 0xF0, 0xA0, 0xA0, 0x84, 0x44, 0xF0, 0xA0,
+ 0xA3, 0x9E, 0x44, 0xF0, 0xA0, 0xA8, 0xAC, 0x44,
+ 0xF0, 0xA0, 0xAD, 0xA3, 0x44, 0xF0, 0xA1, 0x93,
+ 0xA4, 0x44, 0xF0, 0xA1, 0x9A, 0xA8, 0x44, 0xF0,
+ // Bytes 1680 - 16bf
+ 0xA1, 0x9B, 0xAA, 0x44, 0xF0, 0xA1, 0xA7, 0x88,
+ 0x44, 0xF0, 0xA1, 0xAC, 0x98, 0x44, 0xF0, 0xA1,
+ 0xB4, 0x8B, 0x44, 0xF0, 0xA1, 0xB7, 0xA4, 0x44,
+ 0xF0, 0xA1, 0xB7, 0xA6, 0x44, 0xF0, 0xA2, 0x86,
+ 0x83, 0x44, 0xF0, 0xA2, 0x86, 0x9F, 0x44, 0xF0,
+ 0xA2, 0x8C, 0xB1, 0x44, 0xF0, 0xA2, 0x9B, 0x94,
+ 0x44, 0xF0, 0xA2, 0xA1, 0x84, 0x44, 0xF0, 0xA2,
+ 0xA1, 0x8A, 0x44, 0xF0, 0xA2, 0xAC, 0x8C, 0x44,
+ // Bytes 16c0 - 16ff
+ 0xF0, 0xA2, 0xAF, 0xB1, 0x44, 0xF0, 0xA3, 0x80,
+ 0x8A, 0x44, 0xF0, 0xA3, 0x8A, 0xB8, 0x44, 0xF0,
+ 0xA3, 0x8D, 0x9F, 0x44, 0xF0, 0xA3, 0x8E, 0x93,
+ 0x44, 0xF0, 0xA3, 0x8E, 0x9C, 0x44, 0xF0, 0xA3,
+ 0x8F, 0x83, 0x44, 0xF0, 0xA3, 0x8F, 0x95, 0x44,
+ 0xF0, 0xA3, 0x91, 0xAD, 0x44, 0xF0, 0xA3, 0x9A,
+ 0xA3, 0x44, 0xF0, 0xA3, 0xA2, 0xA7, 0x44, 0xF0,
+ 0xA3, 0xAA, 0x8D, 0x44, 0xF0, 0xA3, 0xAB, 0xBA,
+ // Bytes 1700 - 173f
+ 0x44, 0xF0, 0xA3, 0xB2, 0xBC, 0x44, 0xF0, 0xA3,
+ 0xB4, 0x9E, 0x44, 0xF0, 0xA3, 0xBB, 0x91, 0x44,
+ 0xF0, 0xA3, 0xBD, 0x9E, 0x44, 0xF0, 0xA3, 0xBE,
+ 0x8E, 0x44, 0xF0, 0xA4, 0x89, 0xA3, 0x44, 0xF0,
+ 0xA4, 0x8B, 0xAE, 0x44, 0xF0, 0xA4, 0x8E, 0xAB,
+ 0x44, 0xF0, 0xA4, 0x98, 0x88, 0x44, 0xF0, 0xA4,
+ 0x9C, 0xB5, 0x44, 0xF0, 0xA4, 0xA0, 0x94, 0x44,
+ 0xF0, 0xA4, 0xB0, 0xB6, 0x44, 0xF0, 0xA4, 0xB2,
+ // Bytes 1740 - 177f
+ 0x92, 0x44, 0xF0, 0xA4, 0xBE, 0xA1, 0x44, 0xF0,
+ 0xA4, 0xBE, 0xB8, 0x44, 0xF0, 0xA5, 0x81, 0x84,
+ 0x44, 0xF0, 0xA5, 0x83, 0xB2, 0x44, 0xF0, 0xA5,
+ 0x83, 0xB3, 0x44, 0xF0, 0xA5, 0x84, 0x99, 0x44,
+ 0xF0, 0xA5, 0x84, 0xB3, 0x44, 0xF0, 0xA5, 0x89,
+ 0x89, 0x44, 0xF0, 0xA5, 0x90, 0x9D, 0x44, 0xF0,
+ 0xA5, 0x98, 0xA6, 0x44, 0xF0, 0xA5, 0x9A, 0x9A,
+ 0x44, 0xF0, 0xA5, 0x9B, 0x85, 0x44, 0xF0, 0xA5,
+ // Bytes 1780 - 17bf
+ 0xA5, 0xBC, 0x44, 0xF0, 0xA5, 0xAA, 0xA7, 0x44,
+ 0xF0, 0xA5, 0xAE, 0xAB, 0x44, 0xF0, 0xA5, 0xB2,
+ 0x80, 0x44, 0xF0, 0xA5, 0xB3, 0x90, 0x44, 0xF0,
+ 0xA5, 0xBE, 0x86, 0x44, 0xF0, 0xA6, 0x87, 0x9A,
+ 0x44, 0xF0, 0xA6, 0x88, 0xA8, 0x44, 0xF0, 0xA6,
+ 0x89, 0x87, 0x44, 0xF0, 0xA6, 0x8B, 0x99, 0x44,
+ 0xF0, 0xA6, 0x8C, 0xBE, 0x44, 0xF0, 0xA6, 0x93,
+ 0x9A, 0x44, 0xF0, 0xA6, 0x94, 0xA3, 0x44, 0xF0,
+ // Bytes 17c0 - 17ff
+ 0xA6, 0x96, 0xA8, 0x44, 0xF0, 0xA6, 0x9E, 0xA7,
+ 0x44, 0xF0, 0xA6, 0x9E, 0xB5, 0x44, 0xF0, 0xA6,
+ 0xAC, 0xBC, 0x44, 0xF0, 0xA6, 0xB0, 0xB6, 0x44,
+ 0xF0, 0xA6, 0xB3, 0x95, 0x44, 0xF0, 0xA6, 0xB5,
+ 0xAB, 0x44, 0xF0, 0xA6, 0xBC, 0xAC, 0x44, 0xF0,
+ 0xA6, 0xBE, 0xB1, 0x44, 0xF0, 0xA7, 0x83, 0x92,
+ 0x44, 0xF0, 0xA7, 0x8F, 0x8A, 0x44, 0xF0, 0xA7,
+ 0x99, 0xA7, 0x44, 0xF0, 0xA7, 0xA2, 0xAE, 0x44,
+ // Bytes 1800 - 183f
+ 0xF0, 0xA7, 0xA5, 0xA6, 0x44, 0xF0, 0xA7, 0xB2,
+ 0xA8, 0x44, 0xF0, 0xA7, 0xBB, 0x93, 0x44, 0xF0,
+ 0xA7, 0xBC, 0xAF, 0x44, 0xF0, 0xA8, 0x97, 0x92,
+ 0x44, 0xF0, 0xA8, 0x97, 0xAD, 0x44, 0xF0, 0xA8,
+ 0x9C, 0xAE, 0x44, 0xF0, 0xA8, 0xAF, 0xBA, 0x44,
+ 0xF0, 0xA8, 0xB5, 0xB7, 0x44, 0xF0, 0xA9, 0x85,
+ 0x85, 0x44, 0xF0, 0xA9, 0x87, 0x9F, 0x44, 0xF0,
+ 0xA9, 0x88, 0x9A, 0x44, 0xF0, 0xA9, 0x90, 0x8A,
+ // Bytes 1840 - 187f
+ 0x44, 0xF0, 0xA9, 0x92, 0x96, 0x44, 0xF0, 0xA9,
+ 0x96, 0xB6, 0x44, 0xF0, 0xA9, 0xAC, 0xB0, 0x44,
+ 0xF0, 0xAA, 0x83, 0x8E, 0x44, 0xF0, 0xAA, 0x84,
+ 0x85, 0x44, 0xF0, 0xAA, 0x88, 0x8E, 0x44, 0xF0,
+ 0xAA, 0x8A, 0x91, 0x44, 0xF0, 0xAA, 0x8E, 0x92,
+ 0x44, 0xF0, 0xAA, 0x98, 0x80, 0x42, 0x21, 0x21,
+ 0x42, 0x21, 0x3F, 0x42, 0x2E, 0x2E, 0x42, 0x30,
+ 0x2C, 0x42, 0x30, 0x2E, 0x42, 0x31, 0x2C, 0x42,
+ // Bytes 1880 - 18bf
+ 0x31, 0x2E, 0x42, 0x31, 0x30, 0x42, 0x31, 0x31,
+ 0x42, 0x31, 0x32, 0x42, 0x31, 0x33, 0x42, 0x31,
+ 0x34, 0x42, 0x31, 0x35, 0x42, 0x31, 0x36, 0x42,
+ 0x31, 0x37, 0x42, 0x31, 0x38, 0x42, 0x31, 0x39,
+ 0x42, 0x32, 0x2C, 0x42, 0x32, 0x2E, 0x42, 0x32,
+ 0x30, 0x42, 0x32, 0x31, 0x42, 0x32, 0x32, 0x42,
+ 0x32, 0x33, 0x42, 0x32, 0x34, 0x42, 0x32, 0x35,
+ 0x42, 0x32, 0x36, 0x42, 0x32, 0x37, 0x42, 0x32,
+ // Bytes 18c0 - 18ff
+ 0x38, 0x42, 0x32, 0x39, 0x42, 0x33, 0x2C, 0x42,
+ 0x33, 0x2E, 0x42, 0x33, 0x30, 0x42, 0x33, 0x31,
+ 0x42, 0x33, 0x32, 0x42, 0x33, 0x33, 0x42, 0x33,
+ 0x34, 0x42, 0x33, 0x35, 0x42, 0x33, 0x36, 0x42,
+ 0x33, 0x37, 0x42, 0x33, 0x38, 0x42, 0x33, 0x39,
+ 0x42, 0x34, 0x2C, 0x42, 0x34, 0x2E, 0x42, 0x34,
+ 0x30, 0x42, 0x34, 0x31, 0x42, 0x34, 0x32, 0x42,
+ 0x34, 0x33, 0x42, 0x34, 0x34, 0x42, 0x34, 0x35,
+ // Bytes 1900 - 193f
+ 0x42, 0x34, 0x36, 0x42, 0x34, 0x37, 0x42, 0x34,
+ 0x38, 0x42, 0x34, 0x39, 0x42, 0x35, 0x2C, 0x42,
+ 0x35, 0x2E, 0x42, 0x35, 0x30, 0x42, 0x36, 0x2C,
+ 0x42, 0x36, 0x2E, 0x42, 0x37, 0x2C, 0x42, 0x37,
+ 0x2E, 0x42, 0x38, 0x2C, 0x42, 0x38, 0x2E, 0x42,
+ 0x39, 0x2C, 0x42, 0x39, 0x2E, 0x42, 0x3D, 0x3D,
+ 0x42, 0x3F, 0x21, 0x42, 0x3F, 0x3F, 0x42, 0x41,
+ 0x55, 0x42, 0x42, 0x71, 0x42, 0x43, 0x44, 0x42,
+ // Bytes 1940 - 197f
+ 0x44, 0x4A, 0x42, 0x44, 0x5A, 0x42, 0x44, 0x7A,
+ 0x42, 0x47, 0x42, 0x42, 0x47, 0x79, 0x42, 0x48,
+ 0x50, 0x42, 0x48, 0x56, 0x42, 0x48, 0x67, 0x42,
+ 0x48, 0x7A, 0x42, 0x49, 0x49, 0x42, 0x49, 0x4A,
+ 0x42, 0x49, 0x55, 0x42, 0x49, 0x56, 0x42, 0x49,
+ 0x58, 0x42, 0x4B, 0x42, 0x42, 0x4B, 0x4B, 0x42,
+ 0x4B, 0x4D, 0x42, 0x4C, 0x4A, 0x42, 0x4C, 0x6A,
+ 0x42, 0x4D, 0x42, 0x42, 0x4D, 0x43, 0x42, 0x4D,
+ // Bytes 1980 - 19bf
+ 0x44, 0x42, 0x4D, 0x56, 0x42, 0x4D, 0x57, 0x42,
+ 0x4E, 0x4A, 0x42, 0x4E, 0x6A, 0x42, 0x4E, 0x6F,
+ 0x42, 0x50, 0x48, 0x42, 0x50, 0x52, 0x42, 0x50,
+ 0x61, 0x42, 0x52, 0x73, 0x42, 0x53, 0x44, 0x42,
+ 0x53, 0x4D, 0x42, 0x53, 0x53, 0x42, 0x53, 0x76,
+ 0x42, 0x54, 0x4D, 0x42, 0x56, 0x49, 0x42, 0x57,
+ 0x43, 0x42, 0x57, 0x5A, 0x42, 0x57, 0x62, 0x42,
+ 0x58, 0x49, 0x42, 0x63, 0x63, 0x42, 0x63, 0x64,
+ // Bytes 19c0 - 19ff
+ 0x42, 0x63, 0x6D, 0x42, 0x64, 0x42, 0x42, 0x64,
+ 0x61, 0x42, 0x64, 0x6C, 0x42, 0x64, 0x6D, 0x42,
+ 0x64, 0x7A, 0x42, 0x65, 0x56, 0x42, 0x66, 0x66,
+ 0x42, 0x66, 0x69, 0x42, 0x66, 0x6C, 0x42, 0x66,
+ 0x6D, 0x42, 0x68, 0x61, 0x42, 0x69, 0x69, 0x42,
+ 0x69, 0x6A, 0x42, 0x69, 0x6E, 0x42, 0x69, 0x76,
+ 0x42, 0x69, 0x78, 0x42, 0x6B, 0x41, 0x42, 0x6B,
+ 0x56, 0x42, 0x6B, 0x57, 0x42, 0x6B, 0x67, 0x42,
+ // Bytes 1a00 - 1a3f
+ 0x6B, 0x6C, 0x42, 0x6B, 0x6D, 0x42, 0x6B, 0x74,
+ 0x42, 0x6C, 0x6A, 0x42, 0x6C, 0x6D, 0x42, 0x6C,
+ 0x6E, 0x42, 0x6C, 0x78, 0x42, 0x6D, 0x32, 0x42,
+ 0x6D, 0x33, 0x42, 0x6D, 0x41, 0x42, 0x6D, 0x56,
+ 0x42, 0x6D, 0x57, 0x42, 0x6D, 0x62, 0x42, 0x6D,
+ 0x67, 0x42, 0x6D, 0x6C, 0x42, 0x6D, 0x6D, 0x42,
+ 0x6D, 0x73, 0x42, 0x6E, 0x41, 0x42, 0x6E, 0x46,
+ 0x42, 0x6E, 0x56, 0x42, 0x6E, 0x57, 0x42, 0x6E,
+ // Bytes 1a40 - 1a7f
+ 0x6A, 0x42, 0x6E, 0x6D, 0x42, 0x6E, 0x73, 0x42,
+ 0x6F, 0x56, 0x42, 0x70, 0x41, 0x42, 0x70, 0x46,
+ 0x42, 0x70, 0x56, 0x42, 0x70, 0x57, 0x42, 0x70,
+ 0x63, 0x42, 0x70, 0x73, 0x42, 0x73, 0x72, 0x42,
+ 0x73, 0x74, 0x42, 0x76, 0x69, 0x42, 0x78, 0x69,
+ 0x43, 0x28, 0x31, 0x29, 0x43, 0x28, 0x32, 0x29,
+ 0x43, 0x28, 0x33, 0x29, 0x43, 0x28, 0x34, 0x29,
+ 0x43, 0x28, 0x35, 0x29, 0x43, 0x28, 0x36, 0x29,
+ // Bytes 1a80 - 1abf
+ 0x43, 0x28, 0x37, 0x29, 0x43, 0x28, 0x38, 0x29,
+ 0x43, 0x28, 0x39, 0x29, 0x43, 0x28, 0x41, 0x29,
+ 0x43, 0x28, 0x42, 0x29, 0x43, 0x28, 0x43, 0x29,
+ 0x43, 0x28, 0x44, 0x29, 0x43, 0x28, 0x45, 0x29,
+ 0x43, 0x28, 0x46, 0x29, 0x43, 0x28, 0x47, 0x29,
+ 0x43, 0x28, 0x48, 0x29, 0x43, 0x28, 0x49, 0x29,
+ 0x43, 0x28, 0x4A, 0x29, 0x43, 0x28, 0x4B, 0x29,
+ 0x43, 0x28, 0x4C, 0x29, 0x43, 0x28, 0x4D, 0x29,
+ // Bytes 1ac0 - 1aff
+ 0x43, 0x28, 0x4E, 0x29, 0x43, 0x28, 0x4F, 0x29,
+ 0x43, 0x28, 0x50, 0x29, 0x43, 0x28, 0x51, 0x29,
+ 0x43, 0x28, 0x52, 0x29, 0x43, 0x28, 0x53, 0x29,
+ 0x43, 0x28, 0x54, 0x29, 0x43, 0x28, 0x55, 0x29,
+ 0x43, 0x28, 0x56, 0x29, 0x43, 0x28, 0x57, 0x29,
+ 0x43, 0x28, 0x58, 0x29, 0x43, 0x28, 0x59, 0x29,
+ 0x43, 0x28, 0x5A, 0x29, 0x43, 0x28, 0x61, 0x29,
+ 0x43, 0x28, 0x62, 0x29, 0x43, 0x28, 0x63, 0x29,
+ // Bytes 1b00 - 1b3f
+ 0x43, 0x28, 0x64, 0x29, 0x43, 0x28, 0x65, 0x29,
+ 0x43, 0x28, 0x66, 0x29, 0x43, 0x28, 0x67, 0x29,
+ 0x43, 0x28, 0x68, 0x29, 0x43, 0x28, 0x69, 0x29,
+ 0x43, 0x28, 0x6A, 0x29, 0x43, 0x28, 0x6B, 0x29,
+ 0x43, 0x28, 0x6C, 0x29, 0x43, 0x28, 0x6D, 0x29,
+ 0x43, 0x28, 0x6E, 0x29, 0x43, 0x28, 0x6F, 0x29,
+ 0x43, 0x28, 0x70, 0x29, 0x43, 0x28, 0x71, 0x29,
+ 0x43, 0x28, 0x72, 0x29, 0x43, 0x28, 0x73, 0x29,
+ // Bytes 1b40 - 1b7f
+ 0x43, 0x28, 0x74, 0x29, 0x43, 0x28, 0x75, 0x29,
+ 0x43, 0x28, 0x76, 0x29, 0x43, 0x28, 0x77, 0x29,
+ 0x43, 0x28, 0x78, 0x29, 0x43, 0x28, 0x79, 0x29,
+ 0x43, 0x28, 0x7A, 0x29, 0x43, 0x2E, 0x2E, 0x2E,
+ 0x43, 0x31, 0x30, 0x2E, 0x43, 0x31, 0x31, 0x2E,
+ 0x43, 0x31, 0x32, 0x2E, 0x43, 0x31, 0x33, 0x2E,
+ 0x43, 0x31, 0x34, 0x2E, 0x43, 0x31, 0x35, 0x2E,
+ 0x43, 0x31, 0x36, 0x2E, 0x43, 0x31, 0x37, 0x2E,
+ // Bytes 1b80 - 1bbf
+ 0x43, 0x31, 0x38, 0x2E, 0x43, 0x31, 0x39, 0x2E,
+ 0x43, 0x32, 0x30, 0x2E, 0x43, 0x3A, 0x3A, 0x3D,
+ 0x43, 0x3D, 0x3D, 0x3D, 0x43, 0x43, 0x6F, 0x2E,
+ 0x43, 0x46, 0x41, 0x58, 0x43, 0x47, 0x48, 0x7A,
+ 0x43, 0x47, 0x50, 0x61, 0x43, 0x49, 0x49, 0x49,
+ 0x43, 0x4C, 0x54, 0x44, 0x43, 0x4C, 0xC2, 0xB7,
+ 0x43, 0x4D, 0x48, 0x7A, 0x43, 0x4D, 0x50, 0x61,
+ 0x43, 0x4D, 0xCE, 0xA9, 0x43, 0x50, 0x50, 0x4D,
+ // Bytes 1bc0 - 1bff
+ 0x43, 0x50, 0x50, 0x56, 0x43, 0x50, 0x54, 0x45,
+ 0x43, 0x54, 0x45, 0x4C, 0x43, 0x54, 0x48, 0x7A,
+ 0x43, 0x56, 0x49, 0x49, 0x43, 0x58, 0x49, 0x49,
+ 0x43, 0x61, 0x2F, 0x63, 0x43, 0x61, 0x2F, 0x73,
+ 0x43, 0x61, 0xCA, 0xBE, 0x43, 0x62, 0x61, 0x72,
+ 0x43, 0x63, 0x2F, 0x6F, 0x43, 0x63, 0x2F, 0x75,
+ 0x43, 0x63, 0x61, 0x6C, 0x43, 0x63, 0x6D, 0x32,
+ 0x43, 0x63, 0x6D, 0x33, 0x43, 0x64, 0x6D, 0x32,
+ // Bytes 1c00 - 1c3f
+ 0x43, 0x64, 0x6D, 0x33, 0x43, 0x65, 0x72, 0x67,
+ 0x43, 0x66, 0x66, 0x69, 0x43, 0x66, 0x66, 0x6C,
+ 0x43, 0x67, 0x61, 0x6C, 0x43, 0x68, 0x50, 0x61,
+ 0x43, 0x69, 0x69, 0x69, 0x43, 0x6B, 0x48, 0x7A,
+ 0x43, 0x6B, 0x50, 0x61, 0x43, 0x6B, 0x6D, 0x32,
+ 0x43, 0x6B, 0x6D, 0x33, 0x43, 0x6B, 0xCE, 0xA9,
+ 0x43, 0x6C, 0x6F, 0x67, 0x43, 0x6C, 0xC2, 0xB7,
+ 0x43, 0x6D, 0x69, 0x6C, 0x43, 0x6D, 0x6D, 0x32,
+ // Bytes 1c40 - 1c7f
+ 0x43, 0x6D, 0x6D, 0x33, 0x43, 0x6D, 0x6F, 0x6C,
+ 0x43, 0x72, 0x61, 0x64, 0x43, 0x76, 0x69, 0x69,
+ 0x43, 0x78, 0x69, 0x69, 0x43, 0xC2, 0xB0, 0x43,
+ 0x43, 0xC2, 0xB0, 0x46, 0x43, 0xCA, 0xBC, 0x6E,
+ 0x43, 0xCE, 0xBC, 0x41, 0x43, 0xCE, 0xBC, 0x46,
+ 0x43, 0xCE, 0xBC, 0x56, 0x43, 0xCE, 0xBC, 0x57,
+ 0x43, 0xCE, 0xBC, 0x67, 0x43, 0xCE, 0xBC, 0x6C,
+ 0x43, 0xCE, 0xBC, 0x6D, 0x43, 0xCE, 0xBC, 0x73,
+ // Bytes 1c80 - 1cbf
+ 0x44, 0x28, 0x31, 0x30, 0x29, 0x44, 0x28, 0x31,
+ 0x31, 0x29, 0x44, 0x28, 0x31, 0x32, 0x29, 0x44,
+ 0x28, 0x31, 0x33, 0x29, 0x44, 0x28, 0x31, 0x34,
+ 0x29, 0x44, 0x28, 0x31, 0x35, 0x29, 0x44, 0x28,
+ 0x31, 0x36, 0x29, 0x44, 0x28, 0x31, 0x37, 0x29,
+ 0x44, 0x28, 0x31, 0x38, 0x29, 0x44, 0x28, 0x31,
+ 0x39, 0x29, 0x44, 0x28, 0x32, 0x30, 0x29, 0x44,
+ 0x30, 0xE7, 0x82, 0xB9, 0x44, 0x31, 0xE2, 0x81,
+ // Bytes 1cc0 - 1cff
+ 0x84, 0x44, 0x31, 0xE6, 0x97, 0xA5, 0x44, 0x31,
+ 0xE6, 0x9C, 0x88, 0x44, 0x31, 0xE7, 0x82, 0xB9,
+ 0x44, 0x32, 0xE6, 0x97, 0xA5, 0x44, 0x32, 0xE6,
+ 0x9C, 0x88, 0x44, 0x32, 0xE7, 0x82, 0xB9, 0x44,
+ 0x33, 0xE6, 0x97, 0xA5, 0x44, 0x33, 0xE6, 0x9C,
+ 0x88, 0x44, 0x33, 0xE7, 0x82, 0xB9, 0x44, 0x34,
+ 0xE6, 0x97, 0xA5, 0x44, 0x34, 0xE6, 0x9C, 0x88,
+ 0x44, 0x34, 0xE7, 0x82, 0xB9, 0x44, 0x35, 0xE6,
+ // Bytes 1d00 - 1d3f
+ 0x97, 0xA5, 0x44, 0x35, 0xE6, 0x9C, 0x88, 0x44,
+ 0x35, 0xE7, 0x82, 0xB9, 0x44, 0x36, 0xE6, 0x97,
+ 0xA5, 0x44, 0x36, 0xE6, 0x9C, 0x88, 0x44, 0x36,
+ 0xE7, 0x82, 0xB9, 0x44, 0x37, 0xE6, 0x97, 0xA5,
+ 0x44, 0x37, 0xE6, 0x9C, 0x88, 0x44, 0x37, 0xE7,
+ 0x82, 0xB9, 0x44, 0x38, 0xE6, 0x97, 0xA5, 0x44,
+ 0x38, 0xE6, 0x9C, 0x88, 0x44, 0x38, 0xE7, 0x82,
+ 0xB9, 0x44, 0x39, 0xE6, 0x97, 0xA5, 0x44, 0x39,
+ // Bytes 1d40 - 1d7f
+ 0xE6, 0x9C, 0x88, 0x44, 0x39, 0xE7, 0x82, 0xB9,
+ 0x44, 0x56, 0x49, 0x49, 0x49, 0x44, 0x61, 0x2E,
+ 0x6D, 0x2E, 0x44, 0x6B, 0x63, 0x61, 0x6C, 0x44,
+ 0x70, 0x2E, 0x6D, 0x2E, 0x44, 0x76, 0x69, 0x69,
+ 0x69, 0x44, 0xD5, 0xA5, 0xD6, 0x82, 0x44, 0xD5,
+ 0xB4, 0xD5, 0xA5, 0x44, 0xD5, 0xB4, 0xD5, 0xAB,
+ 0x44, 0xD5, 0xB4, 0xD5, 0xAD, 0x44, 0xD5, 0xB4,
+ 0xD5, 0xB6, 0x44, 0xD5, 0xBE, 0xD5, 0xB6, 0x44,
+ // Bytes 1d80 - 1dbf
+ 0xD7, 0x90, 0xD7, 0x9C, 0x44, 0xD8, 0xA7, 0xD9,
+ 0xB4, 0x44, 0xD8, 0xA8, 0xD8, 0xAC, 0x44, 0xD8,
+ 0xA8, 0xD8, 0xAD, 0x44, 0xD8, 0xA8, 0xD8, 0xAE,
+ 0x44, 0xD8, 0xA8, 0xD8, 0xB1, 0x44, 0xD8, 0xA8,
+ 0xD8, 0xB2, 0x44, 0xD8, 0xA8, 0xD9, 0x85, 0x44,
+ 0xD8, 0xA8, 0xD9, 0x86, 0x44, 0xD8, 0xA8, 0xD9,
+ 0x87, 0x44, 0xD8, 0xA8, 0xD9, 0x89, 0x44, 0xD8,
+ 0xA8, 0xD9, 0x8A, 0x44, 0xD8, 0xAA, 0xD8, 0xAC,
+ // Bytes 1dc0 - 1dff
+ 0x44, 0xD8, 0xAA, 0xD8, 0xAD, 0x44, 0xD8, 0xAA,
+ 0xD8, 0xAE, 0x44, 0xD8, 0xAA, 0xD8, 0xB1, 0x44,
+ 0xD8, 0xAA, 0xD8, 0xB2, 0x44, 0xD8, 0xAA, 0xD9,
+ 0x85, 0x44, 0xD8, 0xAA, 0xD9, 0x86, 0x44, 0xD8,
+ 0xAA, 0xD9, 0x87, 0x44, 0xD8, 0xAA, 0xD9, 0x89,
+ 0x44, 0xD8, 0xAA, 0xD9, 0x8A, 0x44, 0xD8, 0xAB,
+ 0xD8, 0xAC, 0x44, 0xD8, 0xAB, 0xD8, 0xB1, 0x44,
+ 0xD8, 0xAB, 0xD8, 0xB2, 0x44, 0xD8, 0xAB, 0xD9,
+ // Bytes 1e00 - 1e3f
+ 0x85, 0x44, 0xD8, 0xAB, 0xD9, 0x86, 0x44, 0xD8,
+ 0xAB, 0xD9, 0x87, 0x44, 0xD8, 0xAB, 0xD9, 0x89,
+ 0x44, 0xD8, 0xAB, 0xD9, 0x8A, 0x44, 0xD8, 0xAC,
+ 0xD8, 0xAD, 0x44, 0xD8, 0xAC, 0xD9, 0x85, 0x44,
+ 0xD8, 0xAC, 0xD9, 0x89, 0x44, 0xD8, 0xAC, 0xD9,
+ 0x8A, 0x44, 0xD8, 0xAD, 0xD8, 0xAC, 0x44, 0xD8,
+ 0xAD, 0xD9, 0x85, 0x44, 0xD8, 0xAD, 0xD9, 0x89,
+ 0x44, 0xD8, 0xAD, 0xD9, 0x8A, 0x44, 0xD8, 0xAE,
+ // Bytes 1e40 - 1e7f
+ 0xD8, 0xAC, 0x44, 0xD8, 0xAE, 0xD8, 0xAD, 0x44,
+ 0xD8, 0xAE, 0xD9, 0x85, 0x44, 0xD8, 0xAE, 0xD9,
+ 0x89, 0x44, 0xD8, 0xAE, 0xD9, 0x8A, 0x44, 0xD8,
+ 0xB3, 0xD8, 0xAC, 0x44, 0xD8, 0xB3, 0xD8, 0xAD,
+ 0x44, 0xD8, 0xB3, 0xD8, 0xAE, 0x44, 0xD8, 0xB3,
+ 0xD8, 0xB1, 0x44, 0xD8, 0xB3, 0xD9, 0x85, 0x44,
+ 0xD8, 0xB3, 0xD9, 0x87, 0x44, 0xD8, 0xB3, 0xD9,
+ 0x89, 0x44, 0xD8, 0xB3, 0xD9, 0x8A, 0x44, 0xD8,
+ // Bytes 1e80 - 1ebf
+ 0xB4, 0xD8, 0xAC, 0x44, 0xD8, 0xB4, 0xD8, 0xAD,
+ 0x44, 0xD8, 0xB4, 0xD8, 0xAE, 0x44, 0xD8, 0xB4,
+ 0xD8, 0xB1, 0x44, 0xD8, 0xB4, 0xD9, 0x85, 0x44,
+ 0xD8, 0xB4, 0xD9, 0x87, 0x44, 0xD8, 0xB4, 0xD9,
+ 0x89, 0x44, 0xD8, 0xB4, 0xD9, 0x8A, 0x44, 0xD8,
+ 0xB5, 0xD8, 0xAD, 0x44, 0xD8, 0xB5, 0xD8, 0xAE,
+ 0x44, 0xD8, 0xB5, 0xD8, 0xB1, 0x44, 0xD8, 0xB5,
+ 0xD9, 0x85, 0x44, 0xD8, 0xB5, 0xD9, 0x89, 0x44,
+ // Bytes 1ec0 - 1eff
+ 0xD8, 0xB5, 0xD9, 0x8A, 0x44, 0xD8, 0xB6, 0xD8,
+ 0xAC, 0x44, 0xD8, 0xB6, 0xD8, 0xAD, 0x44, 0xD8,
+ 0xB6, 0xD8, 0xAE, 0x44, 0xD8, 0xB6, 0xD8, 0xB1,
+ 0x44, 0xD8, 0xB6, 0xD9, 0x85, 0x44, 0xD8, 0xB6,
+ 0xD9, 0x89, 0x44, 0xD8, 0xB6, 0xD9, 0x8A, 0x44,
+ 0xD8, 0xB7, 0xD8, 0xAD, 0x44, 0xD8, 0xB7, 0xD9,
+ 0x85, 0x44, 0xD8, 0xB7, 0xD9, 0x89, 0x44, 0xD8,
+ 0xB7, 0xD9, 0x8A, 0x44, 0xD8, 0xB8, 0xD9, 0x85,
+ // Bytes 1f00 - 1f3f
+ 0x44, 0xD8, 0xB9, 0xD8, 0xAC, 0x44, 0xD8, 0xB9,
+ 0xD9, 0x85, 0x44, 0xD8, 0xB9, 0xD9, 0x89, 0x44,
+ 0xD8, 0xB9, 0xD9, 0x8A, 0x44, 0xD8, 0xBA, 0xD8,
+ 0xAC, 0x44, 0xD8, 0xBA, 0xD9, 0x85, 0x44, 0xD8,
+ 0xBA, 0xD9, 0x89, 0x44, 0xD8, 0xBA, 0xD9, 0x8A,
+ 0x44, 0xD9, 0x81, 0xD8, 0xAC, 0x44, 0xD9, 0x81,
+ 0xD8, 0xAD, 0x44, 0xD9, 0x81, 0xD8, 0xAE, 0x44,
+ 0xD9, 0x81, 0xD9, 0x85, 0x44, 0xD9, 0x81, 0xD9,
+ // Bytes 1f40 - 1f7f
+ 0x89, 0x44, 0xD9, 0x81, 0xD9, 0x8A, 0x44, 0xD9,
+ 0x82, 0xD8, 0xAD, 0x44, 0xD9, 0x82, 0xD9, 0x85,
+ 0x44, 0xD9, 0x82, 0xD9, 0x89, 0x44, 0xD9, 0x82,
+ 0xD9, 0x8A, 0x44, 0xD9, 0x83, 0xD8, 0xA7, 0x44,
+ 0xD9, 0x83, 0xD8, 0xAC, 0x44, 0xD9, 0x83, 0xD8,
+ 0xAD, 0x44, 0xD9, 0x83, 0xD8, 0xAE, 0x44, 0xD9,
+ 0x83, 0xD9, 0x84, 0x44, 0xD9, 0x83, 0xD9, 0x85,
+ 0x44, 0xD9, 0x83, 0xD9, 0x89, 0x44, 0xD9, 0x83,
+ // Bytes 1f80 - 1fbf
+ 0xD9, 0x8A, 0x44, 0xD9, 0x84, 0xD8, 0xA7, 0x44,
+ 0xD9, 0x84, 0xD8, 0xAC, 0x44, 0xD9, 0x84, 0xD8,
+ 0xAD, 0x44, 0xD9, 0x84, 0xD8, 0xAE, 0x44, 0xD9,
+ 0x84, 0xD9, 0x85, 0x44, 0xD9, 0x84, 0xD9, 0x87,
+ 0x44, 0xD9, 0x84, 0xD9, 0x89, 0x44, 0xD9, 0x84,
+ 0xD9, 0x8A, 0x44, 0xD9, 0x85, 0xD8, 0xA7, 0x44,
+ 0xD9, 0x85, 0xD8, 0xAC, 0x44, 0xD9, 0x85, 0xD8,
+ 0xAD, 0x44, 0xD9, 0x85, 0xD8, 0xAE, 0x44, 0xD9,
+ // Bytes 1fc0 - 1fff
+ 0x85, 0xD9, 0x85, 0x44, 0xD9, 0x85, 0xD9, 0x89,
+ 0x44, 0xD9, 0x85, 0xD9, 0x8A, 0x44, 0xD9, 0x86,
+ 0xD8, 0xAC, 0x44, 0xD9, 0x86, 0xD8, 0xAD, 0x44,
+ 0xD9, 0x86, 0xD8, 0xAE, 0x44, 0xD9, 0x86, 0xD8,
+ 0xB1, 0x44, 0xD9, 0x86, 0xD8, 0xB2, 0x44, 0xD9,
+ 0x86, 0xD9, 0x85, 0x44, 0xD9, 0x86, 0xD9, 0x86,
+ 0x44, 0xD9, 0x86, 0xD9, 0x87, 0x44, 0xD9, 0x86,
+ 0xD9, 0x89, 0x44, 0xD9, 0x86, 0xD9, 0x8A, 0x44,
+ // Bytes 2000 - 203f
+ 0xD9, 0x87, 0xD8, 0xAC, 0x44, 0xD9, 0x87, 0xD9,
+ 0x85, 0x44, 0xD9, 0x87, 0xD9, 0x89, 0x44, 0xD9,
+ 0x87, 0xD9, 0x8A, 0x44, 0xD9, 0x88, 0xD9, 0xB4,
+ 0x44, 0xD9, 0x8A, 0xD8, 0xAC, 0x44, 0xD9, 0x8A,
+ 0xD8, 0xAD, 0x44, 0xD9, 0x8A, 0xD8, 0xAE, 0x44,
+ 0xD9, 0x8A, 0xD8, 0xB1, 0x44, 0xD9, 0x8A, 0xD8,
+ 0xB2, 0x44, 0xD9, 0x8A, 0xD9, 0x85, 0x44, 0xD9,
+ 0x8A, 0xD9, 0x86, 0x44, 0xD9, 0x8A, 0xD9, 0x87,
+ // Bytes 2040 - 207f
+ 0x44, 0xD9, 0x8A, 0xD9, 0x89, 0x44, 0xD9, 0x8A,
+ 0xD9, 0x8A, 0x44, 0xD9, 0x8A, 0xD9, 0xB4, 0x44,
+ 0xDB, 0x87, 0xD9, 0xB4, 0x45, 0x28, 0xE1, 0x84,
+ 0x80, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x82, 0x29,
+ 0x45, 0x28, 0xE1, 0x84, 0x83, 0x29, 0x45, 0x28,
+ 0xE1, 0x84, 0x85, 0x29, 0x45, 0x28, 0xE1, 0x84,
+ 0x86, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x87, 0x29,
+ 0x45, 0x28, 0xE1, 0x84, 0x89, 0x29, 0x45, 0x28,
+ // Bytes 2080 - 20bf
+ 0xE1, 0x84, 0x8B, 0x29, 0x45, 0x28, 0xE1, 0x84,
+ 0x8C, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x8E, 0x29,
+ 0x45, 0x28, 0xE1, 0x84, 0x8F, 0x29, 0x45, 0x28,
+ 0xE1, 0x84, 0x90, 0x29, 0x45, 0x28, 0xE1, 0x84,
+ 0x91, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x92, 0x29,
+ 0x45, 0x28, 0xE4, 0xB8, 0x80, 0x29, 0x45, 0x28,
+ 0xE4, 0xB8, 0x83, 0x29, 0x45, 0x28, 0xE4, 0xB8,
+ 0x89, 0x29, 0x45, 0x28, 0xE4, 0xB9, 0x9D, 0x29,
+ // Bytes 20c0 - 20ff
+ 0x45, 0x28, 0xE4, 0xBA, 0x8C, 0x29, 0x45, 0x28,
+ 0xE4, 0xBA, 0x94, 0x29, 0x45, 0x28, 0xE4, 0xBB,
+ 0xA3, 0x29, 0x45, 0x28, 0xE4, 0xBC, 0x81, 0x29,
+ 0x45, 0x28, 0xE4, 0xBC, 0x91, 0x29, 0x45, 0x28,
+ 0xE5, 0x85, 0xAB, 0x29, 0x45, 0x28, 0xE5, 0x85,
+ 0xAD, 0x29, 0x45, 0x28, 0xE5, 0x8A, 0xB4, 0x29,
+ 0x45, 0x28, 0xE5, 0x8D, 0x81, 0x29, 0x45, 0x28,
+ 0xE5, 0x8D, 0x94, 0x29, 0x45, 0x28, 0xE5, 0x90,
+ // Bytes 2100 - 213f
+ 0x8D, 0x29, 0x45, 0x28, 0xE5, 0x91, 0xBC, 0x29,
+ 0x45, 0x28, 0xE5, 0x9B, 0x9B, 0x29, 0x45, 0x28,
+ 0xE5, 0x9C, 0x9F, 0x29, 0x45, 0x28, 0xE5, 0xAD,
+ 0xA6, 0x29, 0x45, 0x28, 0xE6, 0x97, 0xA5, 0x29,
+ 0x45, 0x28, 0xE6, 0x9C, 0x88, 0x29, 0x45, 0x28,
+ 0xE6, 0x9C, 0x89, 0x29, 0x45, 0x28, 0xE6, 0x9C,
+ 0xA8, 0x29, 0x45, 0x28, 0xE6, 0xA0, 0xAA, 0x29,
+ 0x45, 0x28, 0xE6, 0xB0, 0xB4, 0x29, 0x45, 0x28,
+ // Bytes 2140 - 217f
+ 0xE7, 0x81, 0xAB, 0x29, 0x45, 0x28, 0xE7, 0x89,
+ 0xB9, 0x29, 0x45, 0x28, 0xE7, 0x9B, 0xA3, 0x29,
+ 0x45, 0x28, 0xE7, 0xA4, 0xBE, 0x29, 0x45, 0x28,
+ 0xE7, 0xA5, 0x9D, 0x29, 0x45, 0x28, 0xE7, 0xA5,
+ 0xAD, 0x29, 0x45, 0x28, 0xE8, 0x87, 0xAA, 0x29,
+ 0x45, 0x28, 0xE8, 0x87, 0xB3, 0x29, 0x45, 0x28,
+ 0xE8, 0xB2, 0xA1, 0x29, 0x45, 0x28, 0xE8, 0xB3,
+ 0x87, 0x29, 0x45, 0x28, 0xE9, 0x87, 0x91, 0x29,
+ // Bytes 2180 - 21bf
+ 0x45, 0x30, 0xE2, 0x81, 0x84, 0x33, 0x45, 0x31,
+ 0x30, 0xE6, 0x97, 0xA5, 0x45, 0x31, 0x30, 0xE6,
+ 0x9C, 0x88, 0x45, 0x31, 0x30, 0xE7, 0x82, 0xB9,
+ 0x45, 0x31, 0x31, 0xE6, 0x97, 0xA5, 0x45, 0x31,
+ 0x31, 0xE6, 0x9C, 0x88, 0x45, 0x31, 0x31, 0xE7,
+ 0x82, 0xB9, 0x45, 0x31, 0x32, 0xE6, 0x97, 0xA5,
+ 0x45, 0x31, 0x32, 0xE6, 0x9C, 0x88, 0x45, 0x31,
+ 0x32, 0xE7, 0x82, 0xB9, 0x45, 0x31, 0x33, 0xE6,
+ // Bytes 21c0 - 21ff
+ 0x97, 0xA5, 0x45, 0x31, 0x33, 0xE7, 0x82, 0xB9,
+ 0x45, 0x31, 0x34, 0xE6, 0x97, 0xA5, 0x45, 0x31,
+ 0x34, 0xE7, 0x82, 0xB9, 0x45, 0x31, 0x35, 0xE6,
+ 0x97, 0xA5, 0x45, 0x31, 0x35, 0xE7, 0x82, 0xB9,
+ 0x45, 0x31, 0x36, 0xE6, 0x97, 0xA5, 0x45, 0x31,
+ 0x36, 0xE7, 0x82, 0xB9, 0x45, 0x31, 0x37, 0xE6,
+ 0x97, 0xA5, 0x45, 0x31, 0x37, 0xE7, 0x82, 0xB9,
+ 0x45, 0x31, 0x38, 0xE6, 0x97, 0xA5, 0x45, 0x31,
+ // Bytes 2200 - 223f
+ 0x38, 0xE7, 0x82, 0xB9, 0x45, 0x31, 0x39, 0xE6,
+ 0x97, 0xA5, 0x45, 0x31, 0x39, 0xE7, 0x82, 0xB9,
+ 0x45, 0x31, 0xE2, 0x81, 0x84, 0x32, 0x45, 0x31,
+ 0xE2, 0x81, 0x84, 0x33, 0x45, 0x31, 0xE2, 0x81,
+ 0x84, 0x34, 0x45, 0x31, 0xE2, 0x81, 0x84, 0x35,
+ 0x45, 0x31, 0xE2, 0x81, 0x84, 0x36, 0x45, 0x31,
+ 0xE2, 0x81, 0x84, 0x37, 0x45, 0x31, 0xE2, 0x81,
+ 0x84, 0x38, 0x45, 0x31, 0xE2, 0x81, 0x84, 0x39,
+ // Bytes 2240 - 227f
+ 0x45, 0x32, 0x30, 0xE6, 0x97, 0xA5, 0x45, 0x32,
+ 0x30, 0xE7, 0x82, 0xB9, 0x45, 0x32, 0x31, 0xE6,
+ 0x97, 0xA5, 0x45, 0x32, 0x31, 0xE7, 0x82, 0xB9,
+ 0x45, 0x32, 0x32, 0xE6, 0x97, 0xA5, 0x45, 0x32,
+ 0x32, 0xE7, 0x82, 0xB9, 0x45, 0x32, 0x33, 0xE6,
+ 0x97, 0xA5, 0x45, 0x32, 0x33, 0xE7, 0x82, 0xB9,
+ 0x45, 0x32, 0x34, 0xE6, 0x97, 0xA5, 0x45, 0x32,
+ 0x34, 0xE7, 0x82, 0xB9, 0x45, 0x32, 0x35, 0xE6,
+ // Bytes 2280 - 22bf
+ 0x97, 0xA5, 0x45, 0x32, 0x36, 0xE6, 0x97, 0xA5,
+ 0x45, 0x32, 0x37, 0xE6, 0x97, 0xA5, 0x45, 0x32,
+ 0x38, 0xE6, 0x97, 0xA5, 0x45, 0x32, 0x39, 0xE6,
+ 0x97, 0xA5, 0x45, 0x32, 0xE2, 0x81, 0x84, 0x33,
+ 0x45, 0x32, 0xE2, 0x81, 0x84, 0x35, 0x45, 0x33,
+ 0x30, 0xE6, 0x97, 0xA5, 0x45, 0x33, 0x31, 0xE6,
+ 0x97, 0xA5, 0x45, 0x33, 0xE2, 0x81, 0x84, 0x34,
+ 0x45, 0x33, 0xE2, 0x81, 0x84, 0x35, 0x45, 0x33,
+ // Bytes 22c0 - 22ff
+ 0xE2, 0x81, 0x84, 0x38, 0x45, 0x34, 0xE2, 0x81,
+ 0x84, 0x35, 0x45, 0x35, 0xE2, 0x81, 0x84, 0x36,
+ 0x45, 0x35, 0xE2, 0x81, 0x84, 0x38, 0x45, 0x37,
+ 0xE2, 0x81, 0x84, 0x38, 0x45, 0x41, 0xE2, 0x88,
+ 0x95, 0x6D, 0x45, 0x56, 0xE2, 0x88, 0x95, 0x6D,
+ 0x45, 0x6D, 0xE2, 0x88, 0x95, 0x73, 0x46, 0x31,
+ 0xE2, 0x81, 0x84, 0x31, 0x30, 0x46, 0x43, 0xE2,
+ 0x88, 0x95, 0x6B, 0x67, 0x46, 0x6D, 0xE2, 0x88,
+ // Bytes 2300 - 233f
+ 0x95, 0x73, 0x32, 0x46, 0xD8, 0xA8, 0xD8, 0xAD,
+ 0xD9, 0x8A, 0x46, 0xD8, 0xA8, 0xD8, 0xAE, 0xD9,
+ 0x8A, 0x46, 0xD8, 0xAA, 0xD8, 0xAC, 0xD9, 0x85,
+ 0x46, 0xD8, 0xAA, 0xD8, 0xAC, 0xD9, 0x89, 0x46,
+ 0xD8, 0xAA, 0xD8, 0xAC, 0xD9, 0x8A, 0x46, 0xD8,
+ 0xAA, 0xD8, 0xAD, 0xD8, 0xAC, 0x46, 0xD8, 0xAA,
+ 0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD8, 0xAA, 0xD8,
+ 0xAE, 0xD9, 0x85, 0x46, 0xD8, 0xAA, 0xD8, 0xAE,
+ // Bytes 2340 - 237f
+ 0xD9, 0x89, 0x46, 0xD8, 0xAA, 0xD8, 0xAE, 0xD9,
+ 0x8A, 0x46, 0xD8, 0xAA, 0xD9, 0x85, 0xD8, 0xAC,
+ 0x46, 0xD8, 0xAA, 0xD9, 0x85, 0xD8, 0xAD, 0x46,
+ 0xD8, 0xAA, 0xD9, 0x85, 0xD8, 0xAE, 0x46, 0xD8,
+ 0xAA, 0xD9, 0x85, 0xD9, 0x89, 0x46, 0xD8, 0xAA,
+ 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD8, 0xAC, 0xD8,
+ 0xAD, 0xD9, 0x89, 0x46, 0xD8, 0xAC, 0xD8, 0xAD,
+ 0xD9, 0x8A, 0x46, 0xD8, 0xAC, 0xD9, 0x85, 0xD8,
+ // Bytes 2380 - 23bf
+ 0xAD, 0x46, 0xD8, 0xAC, 0xD9, 0x85, 0xD9, 0x89,
+ 0x46, 0xD8, 0xAC, 0xD9, 0x85, 0xD9, 0x8A, 0x46,
+ 0xD8, 0xAD, 0xD8, 0xAC, 0xD9, 0x8A, 0x46, 0xD8,
+ 0xAD, 0xD9, 0x85, 0xD9, 0x89, 0x46, 0xD8, 0xAD,
+ 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD8, 0xB3, 0xD8,
+ 0xAC, 0xD8, 0xAD, 0x46, 0xD8, 0xB3, 0xD8, 0xAC,
+ 0xD9, 0x89, 0x46, 0xD8, 0xB3, 0xD8, 0xAD, 0xD8,
+ 0xAC, 0x46, 0xD8, 0xB3, 0xD8, 0xAE, 0xD9, 0x89,
+ // Bytes 23c0 - 23ff
+ 0x46, 0xD8, 0xB3, 0xD8, 0xAE, 0xD9, 0x8A, 0x46,
+ 0xD8, 0xB3, 0xD9, 0x85, 0xD8, 0xAC, 0x46, 0xD8,
+ 0xB3, 0xD9, 0x85, 0xD8, 0xAD, 0x46, 0xD8, 0xB3,
+ 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD8, 0xB4, 0xD8,
+ 0xAC, 0xD9, 0x8A, 0x46, 0xD8, 0xB4, 0xD8, 0xAD,
+ 0xD9, 0x85, 0x46, 0xD8, 0xB4, 0xD8, 0xAD, 0xD9,
+ 0x8A, 0x46, 0xD8, 0xB4, 0xD9, 0x85, 0xD8, 0xAE,
+ 0x46, 0xD8, 0xB4, 0xD9, 0x85, 0xD9, 0x85, 0x46,
+ // Bytes 2400 - 243f
+ 0xD8, 0xB5, 0xD8, 0xAD, 0xD8, 0xAD, 0x46, 0xD8,
+ 0xB5, 0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD8, 0xB5,
+ 0xD9, 0x84, 0xD9, 0x89, 0x46, 0xD8, 0xB5, 0xD9,
+ 0x84, 0xDB, 0x92, 0x46, 0xD8, 0xB5, 0xD9, 0x85,
+ 0xD9, 0x85, 0x46, 0xD8, 0xB6, 0xD8, 0xAD, 0xD9,
+ 0x89, 0x46, 0xD8, 0xB6, 0xD8, 0xAD, 0xD9, 0x8A,
+ 0x46, 0xD8, 0xB6, 0xD8, 0xAE, 0xD9, 0x85, 0x46,
+ 0xD8, 0xB7, 0xD9, 0x85, 0xD8, 0xAD, 0x46, 0xD8,
+ // Bytes 2440 - 247f
+ 0xB7, 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD8, 0xB7,
+ 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD8, 0xB9, 0xD8,
+ 0xAC, 0xD9, 0x85, 0x46, 0xD8, 0xB9, 0xD9, 0x85,
+ 0xD9, 0x85, 0x46, 0xD8, 0xB9, 0xD9, 0x85, 0xD9,
+ 0x89, 0x46, 0xD8, 0xB9, 0xD9, 0x85, 0xD9, 0x8A,
+ 0x46, 0xD8, 0xBA, 0xD9, 0x85, 0xD9, 0x85, 0x46,
+ 0xD8, 0xBA, 0xD9, 0x85, 0xD9, 0x89, 0x46, 0xD8,
+ 0xBA, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x81,
+ // Bytes 2480 - 24bf
+ 0xD8, 0xAE, 0xD9, 0x85, 0x46, 0xD9, 0x81, 0xD9,
+ 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x82, 0xD9, 0x84,
+ 0xDB, 0x92, 0x46, 0xD9, 0x82, 0xD9, 0x85, 0xD8,
+ 0xAD, 0x46, 0xD9, 0x82, 0xD9, 0x85, 0xD9, 0x85,
+ 0x46, 0xD9, 0x82, 0xD9, 0x85, 0xD9, 0x8A, 0x46,
+ 0xD9, 0x83, 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD9,
+ 0x83, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x84,
+ 0xD8, 0xAC, 0xD8, 0xAC, 0x46, 0xD9, 0x84, 0xD8,
+ // Bytes 24c0 - 24ff
+ 0xAC, 0xD9, 0x85, 0x46, 0xD9, 0x84, 0xD8, 0xAC,
+ 0xD9, 0x8A, 0x46, 0xD9, 0x84, 0xD8, 0xAD, 0xD9,
+ 0x85, 0x46, 0xD9, 0x84, 0xD8, 0xAD, 0xD9, 0x89,
+ 0x46, 0xD9, 0x84, 0xD8, 0xAD, 0xD9, 0x8A, 0x46,
+ 0xD9, 0x84, 0xD8, 0xAE, 0xD9, 0x85, 0x46, 0xD9,
+ 0x84, 0xD9, 0x85, 0xD8, 0xAD, 0x46, 0xD9, 0x84,
+ 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x85, 0xD8,
+ 0xAC, 0xD8, 0xAD, 0x46, 0xD9, 0x85, 0xD8, 0xAC,
+ // Bytes 2500 - 253f
+ 0xD8, 0xAE, 0x46, 0xD9, 0x85, 0xD8, 0xAC, 0xD9,
+ 0x85, 0x46, 0xD9, 0x85, 0xD8, 0xAC, 0xD9, 0x8A,
+ 0x46, 0xD9, 0x85, 0xD8, 0xAD, 0xD8, 0xAC, 0x46,
+ 0xD9, 0x85, 0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD9,
+ 0x85, 0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD9, 0x85,
+ 0xD8, 0xAE, 0xD8, 0xAC, 0x46, 0xD9, 0x85, 0xD8,
+ 0xAE, 0xD9, 0x85, 0x46, 0xD9, 0x85, 0xD8, 0xAE,
+ 0xD9, 0x8A, 0x46, 0xD9, 0x85, 0xD9, 0x85, 0xD9,
+ // Bytes 2540 - 257f
+ 0x8A, 0x46, 0xD9, 0x86, 0xD8, 0xAC, 0xD8, 0xAD,
+ 0x46, 0xD9, 0x86, 0xD8, 0xAC, 0xD9, 0x85, 0x46,
+ 0xD9, 0x86, 0xD8, 0xAC, 0xD9, 0x89, 0x46, 0xD9,
+ 0x86, 0xD8, 0xAC, 0xD9, 0x8A, 0x46, 0xD9, 0x86,
+ 0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD9, 0x86, 0xD8,
+ 0xAD, 0xD9, 0x89, 0x46, 0xD9, 0x86, 0xD8, 0xAD,
+ 0xD9, 0x8A, 0x46, 0xD9, 0x86, 0xD9, 0x85, 0xD9,
+ 0x89, 0x46, 0xD9, 0x86, 0xD9, 0x85, 0xD9, 0x8A,
+ // Bytes 2580 - 25bf
+ 0x46, 0xD9, 0x87, 0xD9, 0x85, 0xD8, 0xAC, 0x46,
+ 0xD9, 0x87, 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD9,
+ 0x8A, 0xD8, 0xAC, 0xD9, 0x8A, 0x46, 0xD9, 0x8A,
+ 0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD9, 0x8A, 0xD9,
+ 0x85, 0xD9, 0x85, 0x46, 0xD9, 0x8A, 0xD9, 0x85,
+ 0xD9, 0x8A, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8,
+ 0xA7, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xAC,
+ 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xAD, 0x46,
+ // Bytes 25c0 - 25ff
+ 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xAE, 0x46, 0xD9,
+ 0x8A, 0xD9, 0x94, 0xD8, 0xB1, 0x46, 0xD9, 0x8A,
+ 0xD9, 0x94, 0xD8, 0xB2, 0x46, 0xD9, 0x8A, 0xD9,
+ 0x94, 0xD9, 0x85, 0x46, 0xD9, 0x8A, 0xD9, 0x94,
+ 0xD9, 0x86, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD9,
+ 0x87, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD9, 0x88,
+ 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD9, 0x89, 0x46,
+ 0xD9, 0x8A, 0xD9, 0x94, 0xD9, 0x8A, 0x46, 0xD9,
+ // Bytes 2600 - 263f
+ 0x8A, 0xD9, 0x94, 0xDB, 0x86, 0x46, 0xD9, 0x8A,
+ 0xD9, 0x94, 0xDB, 0x87, 0x46, 0xD9, 0x8A, 0xD9,
+ 0x94, 0xDB, 0x88, 0x46, 0xD9, 0x8A, 0xD9, 0x94,
+ 0xDB, 0x90, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xDB,
+ 0x95, 0x46, 0xE0, 0xB9, 0x8D, 0xE0, 0xB8, 0xB2,
+ 0x46, 0xE0, 0xBA, 0xAB, 0xE0, 0xBA, 0x99, 0x46,
+ 0xE0, 0xBA, 0xAB, 0xE0, 0xBA, 0xA1, 0x46, 0xE0,
+ 0xBB, 0x8D, 0xE0, 0xBA, 0xB2, 0x46, 0xE0, 0xBD,
+ // Bytes 2640 - 267f
+ 0x80, 0xE0, 0xBE, 0xB5, 0x46, 0xE0, 0xBD, 0x82,
+ 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBD, 0x8C, 0xE0,
+ 0xBE, 0xB7, 0x46, 0xE0, 0xBD, 0x91, 0xE0, 0xBE,
+ 0xB7, 0x46, 0xE0, 0xBD, 0x96, 0xE0, 0xBE, 0xB7,
+ 0x46, 0xE0, 0xBD, 0x9B, 0xE0, 0xBE, 0xB7, 0x46,
+ 0xE0, 0xBE, 0x90, 0xE0, 0xBE, 0xB5, 0x46, 0xE0,
+ 0xBE, 0x92, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBE,
+ 0x9C, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBE, 0xA1,
+ // Bytes 2680 - 26bf
+ 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBE, 0xA6, 0xE0,
+ 0xBE, 0xB7, 0x46, 0xE0, 0xBE, 0xAB, 0xE0, 0xBE,
+ 0xB7, 0x46, 0xE2, 0x80, 0xB2, 0xE2, 0x80, 0xB2,
+ 0x46, 0xE2, 0x80, 0xB5, 0xE2, 0x80, 0xB5, 0x46,
+ 0xE2, 0x88, 0xAB, 0xE2, 0x88, 0xAB, 0x46, 0xE2,
+ 0x88, 0xAE, 0xE2, 0x88, 0xAE, 0x46, 0xE3, 0x81,
+ 0xBB, 0xE3, 0x81, 0x8B, 0x46, 0xE3, 0x82, 0x88,
+ 0xE3, 0x82, 0x8A, 0x46, 0xE3, 0x82, 0xAD, 0xE3,
+ // Bytes 26c0 - 26ff
+ 0x83, 0xAD, 0x46, 0xE3, 0x82, 0xB3, 0xE3, 0x82,
+ 0xB3, 0x46, 0xE3, 0x82, 0xB3, 0xE3, 0x83, 0x88,
+ 0x46, 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xB3, 0x46,
+ 0xE3, 0x83, 0x8A, 0xE3, 0x83, 0x8E, 0x46, 0xE3,
+ 0x83, 0x9B, 0xE3, 0x83, 0xB3, 0x46, 0xE3, 0x83,
+ 0x9F, 0xE3, 0x83, 0xAA, 0x46, 0xE3, 0x83, 0xAA,
+ 0xE3, 0x83, 0xA9, 0x46, 0xE3, 0x83, 0xAC, 0xE3,
+ 0x83, 0xA0, 0x46, 0xE5, 0xA4, 0xA7, 0xE6, 0xAD,
+ // Bytes 2700 - 273f
+ 0xA3, 0x46, 0xE5, 0xB9, 0xB3, 0xE6, 0x88, 0x90,
+ 0x46, 0xE6, 0x98, 0x8E, 0xE6, 0xB2, 0xBB, 0x46,
+ 0xE6, 0x98, 0xAD, 0xE5, 0x92, 0x8C, 0x47, 0x72,
+ 0x61, 0x64, 0xE2, 0x88, 0x95, 0x73, 0x47, 0xE3,
+ 0x80, 0x94, 0x53, 0xE3, 0x80, 0x95, 0x48, 0x28,
+ 0xE1, 0x84, 0x80, 0xE1, 0x85, 0xA1, 0x29, 0x48,
+ 0x28, 0xE1, 0x84, 0x82, 0xE1, 0x85, 0xA1, 0x29,
+ 0x48, 0x28, 0xE1, 0x84, 0x83, 0xE1, 0x85, 0xA1,
+ // Bytes 2740 - 277f
+ 0x29, 0x48, 0x28, 0xE1, 0x84, 0x85, 0xE1, 0x85,
+ 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x86, 0xE1,
+ 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x87,
+ 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84,
+ 0x89, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1,
+ 0x84, 0x8B, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28,
+ 0xE1, 0x84, 0x8C, 0xE1, 0x85, 0xA1, 0x29, 0x48,
+ 0x28, 0xE1, 0x84, 0x8C, 0xE1, 0x85, 0xAE, 0x29,
+ // Bytes 2780 - 27bf
+ 0x48, 0x28, 0xE1, 0x84, 0x8E, 0xE1, 0x85, 0xA1,
+ 0x29, 0x48, 0x28, 0xE1, 0x84, 0x8F, 0xE1, 0x85,
+ 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x90, 0xE1,
+ 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x91,
+ 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84,
+ 0x92, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x72, 0x61,
+ 0x64, 0xE2, 0x88, 0x95, 0x73, 0x32, 0x48, 0xD8,
+ 0xA7, 0xD9, 0x83, 0xD8, 0xA8, 0xD8, 0xB1, 0x48,
+ // Bytes 27c0 - 27ff
+ 0xD8, 0xA7, 0xD9, 0x84, 0xD9, 0x84, 0xD9, 0x87,
+ 0x48, 0xD8, 0xB1, 0xD8, 0xB3, 0xD9, 0x88, 0xD9,
+ 0x84, 0x48, 0xD8, 0xB1, 0xDB, 0x8C, 0xD8, 0xA7,
+ 0xD9, 0x84, 0x48, 0xD8, 0xB5, 0xD9, 0x84, 0xD8,
+ 0xB9, 0xD9, 0x85, 0x48, 0xD8, 0xB9, 0xD9, 0x84,
+ 0xD9, 0x8A, 0xD9, 0x87, 0x48, 0xD9, 0x85, 0xD8,
+ 0xAD, 0xD9, 0x85, 0xD8, 0xAF, 0x48, 0xD9, 0x88,
+ 0xD8, 0xB3, 0xD9, 0x84, 0xD9, 0x85, 0x49, 0xE2,
+ // Bytes 2800 - 283f
+ 0x80, 0xB2, 0xE2, 0x80, 0xB2, 0xE2, 0x80, 0xB2,
+ 0x49, 0xE2, 0x80, 0xB5, 0xE2, 0x80, 0xB5, 0xE2,
+ 0x80, 0xB5, 0x49, 0xE2, 0x88, 0xAB, 0xE2, 0x88,
+ 0xAB, 0xE2, 0x88, 0xAB, 0x49, 0xE2, 0x88, 0xAE,
+ 0xE2, 0x88, 0xAE, 0xE2, 0x88, 0xAE, 0x49, 0xE3,
+ 0x80, 0x94, 0xE4, 0xB8, 0x89, 0xE3, 0x80, 0x95,
+ 0x49, 0xE3, 0x80, 0x94, 0xE4, 0xBA, 0x8C, 0xE3,
+ 0x80, 0x95, 0x49, 0xE3, 0x80, 0x94, 0xE5, 0x8B,
+ // Bytes 2840 - 287f
+ 0x9D, 0xE3, 0x80, 0x95, 0x49, 0xE3, 0x80, 0x94,
+ 0xE5, 0xAE, 0x89, 0xE3, 0x80, 0x95, 0x49, 0xE3,
+ 0x80, 0x94, 0xE6, 0x89, 0x93, 0xE3, 0x80, 0x95,
+ 0x49, 0xE3, 0x80, 0x94, 0xE6, 0x95, 0x97, 0xE3,
+ 0x80, 0x95, 0x49, 0xE3, 0x80, 0x94, 0xE6, 0x9C,
+ 0xAC, 0xE3, 0x80, 0x95, 0x49, 0xE3, 0x80, 0x94,
+ 0xE7, 0x82, 0xB9, 0xE3, 0x80, 0x95, 0x49, 0xE3,
+ 0x80, 0x94, 0xE7, 0x9B, 0x97, 0xE3, 0x80, 0x95,
+ // Bytes 2880 - 28bf
+ 0x49, 0xE3, 0x82, 0xA2, 0xE3, 0x83, 0xBC, 0xE3,
+ 0x83, 0xAB, 0x49, 0xE3, 0x82, 0xA4, 0xE3, 0x83,
+ 0xB3, 0xE3, 0x83, 0x81, 0x49, 0xE3, 0x82, 0xA6,
+ 0xE3, 0x82, 0xA9, 0xE3, 0x83, 0xB3, 0x49, 0xE3,
+ 0x82, 0xAA, 0xE3, 0x83, 0xB3, 0xE3, 0x82, 0xB9,
+ 0x49, 0xE3, 0x82, 0xAA, 0xE3, 0x83, 0xBC, 0xE3,
+ 0x83, 0xA0, 0x49, 0xE3, 0x82, 0xAB, 0xE3, 0x82,
+ 0xA4, 0xE3, 0x83, 0xAA, 0x49, 0xE3, 0x82, 0xB1,
+ // Bytes 28c0 - 28ff
+ 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xB9, 0x49, 0xE3,
+ 0x82, 0xB3, 0xE3, 0x83, 0xAB, 0xE3, 0x83, 0x8A,
+ 0x49, 0xE3, 0x82, 0xBB, 0xE3, 0x83, 0xB3, 0xE3,
+ 0x83, 0x81, 0x49, 0xE3, 0x82, 0xBB, 0xE3, 0x83,
+ 0xB3, 0xE3, 0x83, 0x88, 0x49, 0xE3, 0x83, 0x86,
+ 0xE3, 0x82, 0x99, 0xE3, 0x82, 0xB7, 0x49, 0xE3,
+ 0x83, 0x88, 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xAB,
+ 0x49, 0xE3, 0x83, 0x8E, 0xE3, 0x83, 0x83, 0xE3,
+ // Bytes 2900 - 293f
+ 0x83, 0x88, 0x49, 0xE3, 0x83, 0x8F, 0xE3, 0x82,
+ 0xA4, 0xE3, 0x83, 0x84, 0x49, 0xE3, 0x83, 0x92,
+ 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xAB, 0x49, 0xE3,
+ 0x83, 0x92, 0xE3, 0x82, 0x9A, 0xE3, 0x82, 0xB3,
+ 0x49, 0xE3, 0x83, 0x95, 0xE3, 0x83, 0xA9, 0xE3,
+ 0x83, 0xB3, 0x49, 0xE3, 0x83, 0x98, 0xE3, 0x82,
+ 0x9A, 0xE3, 0x82, 0xBD, 0x49, 0xE3, 0x83, 0x98,
+ 0xE3, 0x83, 0xAB, 0xE3, 0x83, 0x84, 0x49, 0xE3,
+ // Bytes 2940 - 297f
+ 0x83, 0x9B, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0xAB,
+ 0x49, 0xE3, 0x83, 0x9B, 0xE3, 0x83, 0xBC, 0xE3,
+ 0x83, 0xB3, 0x49, 0xE3, 0x83, 0x9E, 0xE3, 0x82,
+ 0xA4, 0xE3, 0x83, 0xAB, 0x49, 0xE3, 0x83, 0x9E,
+ 0xE3, 0x83, 0x83, 0xE3, 0x83, 0x8F, 0x49, 0xE3,
+ 0x83, 0x9E, 0xE3, 0x83, 0xAB, 0xE3, 0x82, 0xAF,
+ 0x49, 0xE3, 0x83, 0xA4, 0xE3, 0x83, 0xBC, 0xE3,
+ 0x83, 0xAB, 0x49, 0xE3, 0x83, 0xA6, 0xE3, 0x82,
+ // Bytes 2980 - 29bf
+ 0xA2, 0xE3, 0x83, 0xB3, 0x49, 0xE3, 0x83, 0xAF,
+ 0xE3, 0x83, 0x83, 0xE3, 0x83, 0x88, 0x4C, 0xE2,
+ 0x80, 0xB2, 0xE2, 0x80, 0xB2, 0xE2, 0x80, 0xB2,
+ 0xE2, 0x80, 0xB2, 0x4C, 0xE2, 0x88, 0xAB, 0xE2,
+ 0x88, 0xAB, 0xE2, 0x88, 0xAB, 0xE2, 0x88, 0xAB,
+ 0x4C, 0xE3, 0x82, 0xA2, 0xE3, 0x83, 0xAB, 0xE3,
+ 0x83, 0x95, 0xE3, 0x82, 0xA1, 0x4C, 0xE3, 0x82,
+ 0xA8, 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xAB, 0xE3,
+ // Bytes 29c0 - 29ff
+ 0x83, 0xBC, 0x4C, 0xE3, 0x82, 0xAB, 0xE3, 0x82,
+ 0x99, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xB3, 0x4C,
+ 0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+ 0xB3, 0xE3, 0x83, 0x9E, 0x4C, 0xE3, 0x82, 0xAB,
+ 0xE3, 0x83, 0xA9, 0xE3, 0x83, 0x83, 0xE3, 0x83,
+ 0x88, 0x4C, 0xE3, 0x82, 0xAB, 0xE3, 0x83, 0xAD,
+ 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xBC, 0x4C, 0xE3,
+ 0x82, 0xAD, 0xE3, 0x82, 0x99, 0xE3, 0x83, 0x8B,
+ // Bytes 2a00 - 2a3f
+ 0xE3, 0x83, 0xBC, 0x4C, 0xE3, 0x82, 0xAD, 0xE3,
+ 0x83, 0xA5, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xBC,
+ 0x4C, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0xE3,
+ 0x83, 0xA9, 0xE3, 0x83, 0xA0, 0x4C, 0xE3, 0x82,
+ 0xAF, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xBC, 0xE3,
+ 0x83, 0x8D, 0x4C, 0xE3, 0x82, 0xB5, 0xE3, 0x82,
+ 0xA4, 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAB, 0x4C,
+ 0xE3, 0x82, 0xBF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+ // Bytes 2a40 - 2a7f
+ 0xBC, 0xE3, 0x82, 0xB9, 0x4C, 0xE3, 0x83, 0x8F,
+ 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
+ 0x84, 0x4C, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x9A,
+ 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAB, 0x4C, 0xE3,
+ 0x83, 0x95, 0xE3, 0x82, 0xA3, 0xE3, 0x83, 0xBC,
+ 0xE3, 0x83, 0x88, 0x4C, 0xE3, 0x83, 0x98, 0xE3,
+ 0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xBF,
+ 0x4C, 0xE3, 0x83, 0x98, 0xE3, 0x82, 0x9A, 0xE3,
+ // Bytes 2a80 - 2abf
+ 0x83, 0x8B, 0xE3, 0x83, 0x92, 0x4C, 0xE3, 0x83,
+ 0x98, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xB3, 0xE3,
+ 0x82, 0xB9, 0x4C, 0xE3, 0x83, 0x9B, 0xE3, 0x82,
+ 0x99, 0xE3, 0x83, 0xAB, 0xE3, 0x83, 0x88, 0x4C,
+ 0xE3, 0x83, 0x9E, 0xE3, 0x82, 0xA4, 0xE3, 0x82,
+ 0xAF, 0xE3, 0x83, 0xAD, 0x4C, 0xE3, 0x83, 0x9F,
+ 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAD, 0xE3, 0x83,
+ 0xB3, 0x4C, 0xE3, 0x83, 0xA1, 0xE3, 0x83, 0xBC,
+ // Bytes 2ac0 - 2aff
+ 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xAB, 0x4C, 0xE3,
+ 0x83, 0xAA, 0xE3, 0x83, 0x83, 0xE3, 0x83, 0x88,
+ 0xE3, 0x83, 0xAB, 0x4C, 0xE3, 0x83, 0xAB, 0xE3,
+ 0x83, 0x92, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC,
+ 0x4C, 0xE6, 0xA0, 0xAA, 0xE5, 0xBC, 0x8F, 0xE4,
+ 0xBC, 0x9A, 0xE7, 0xA4, 0xBE, 0x4E, 0x28, 0xE1,
+ 0x84, 0x8B, 0xE1, 0x85, 0xA9, 0xE1, 0x84, 0x92,
+ 0xE1, 0x85, 0xAE, 0x29, 0x4F, 0xD8, 0xAC, 0xD9,
+ // Bytes 2b00 - 2b3f
+ 0x84, 0x20, 0xD8, 0xAC, 0xD9, 0x84, 0xD8, 0xA7,
+ 0xD9, 0x84, 0xD9, 0x87, 0x4F, 0xE3, 0x82, 0xA2,
+ 0xE3, 0x83, 0x8F, 0xE3, 0x82, 0x9A, 0xE3, 0x83,
+ 0xBC, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x82, 0xA2,
+ 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x98, 0xE3, 0x82,
+ 0x9A, 0xE3, 0x82, 0xA2, 0x4F, 0xE3, 0x82, 0xAD,
+ 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xAF, 0xE3, 0x83,
+ 0x83, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x82, 0xB5,
+ // Bytes 2b40 - 2b7f
+ 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x81, 0xE3, 0x83,
+ 0xBC, 0xE3, 0x83, 0xA0, 0x4F, 0xE3, 0x83, 0x8F,
+ 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
+ 0xAC, 0xE3, 0x83, 0xAB, 0x4F, 0xE3, 0x83, 0x98,
+ 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0xBF, 0xE3, 0x83,
+ 0xBC, 0xE3, 0x83, 0xAB, 0x4F, 0xE3, 0x83, 0x9B,
+ 0xE3, 0x82, 0x9A, 0xE3, 0x82, 0xA4, 0xE3, 0x83,
+ 0xB3, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x83, 0x9E,
+ // Bytes 2b80 - 2bbf
+ 0xE3, 0x83, 0xB3, 0xE3, 0x82, 0xB7, 0xE3, 0x83,
+ 0xA7, 0xE3, 0x83, 0xB3, 0x4F, 0xE3, 0x83, 0xA1,
+ 0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+ 0x88, 0xE3, 0x83, 0xB3, 0x4F, 0xE3, 0x83, 0xAB,
+ 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x95, 0xE3, 0x82,
+ 0x99, 0xE3, 0x83, 0xAB, 0x51, 0x28, 0xE1, 0x84,
+ 0x8B, 0xE1, 0x85, 0xA9, 0xE1, 0x84, 0x8C, 0xE1,
+ 0x85, 0xA5, 0xE1, 0x86, 0xAB, 0x29, 0x52, 0xE3,
+ // Bytes 2bc0 - 2bff
+ 0x82, 0xAD, 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xAB,
+ 0xE3, 0x82, 0xBF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+ 0xBC, 0x52, 0xE3, 0x82, 0xAD, 0xE3, 0x83, 0xAD,
+ 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+ 0xA9, 0xE3, 0x83, 0xA0, 0x52, 0xE3, 0x82, 0xAD,
+ 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xA1, 0xE3, 0x83,
+ 0xBC, 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xAB, 0x52,
+ 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+ // Bytes 2c00 - 2c3f
+ 0xA9, 0xE3, 0x83, 0xA0, 0xE3, 0x83, 0x88, 0xE3,
+ 0x83, 0xB3, 0x52, 0xE3, 0x82, 0xAF, 0xE3, 0x83,
+ 0xAB, 0xE3, 0x82, 0xBB, 0xE3, 0x82, 0x99, 0xE3,
+ 0x82, 0xA4, 0xE3, 0x83, 0xAD, 0x52, 0xE3, 0x83,
+ 0x8F, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC, 0xE3,
+ 0x82, 0xBB, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x88,
+ 0x52, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x9A, 0xE3,
+ 0x82, 0xA2, 0xE3, 0x82, 0xB9, 0xE3, 0x83, 0x88,
+ // Bytes 2c40 - 2c7f
+ 0xE3, 0x83, 0xAB, 0x52, 0xE3, 0x83, 0x95, 0xE3,
+ 0x82, 0x99, 0xE3, 0x83, 0x83, 0xE3, 0x82, 0xB7,
+ 0xE3, 0x82, 0xA7, 0xE3, 0x83, 0xAB, 0x52, 0xE3,
+ 0x83, 0x9F, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0x8F,
+ 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
+ 0xAB, 0x52, 0xE3, 0x83, 0xAC, 0xE3, 0x83, 0xB3,
+ 0xE3, 0x83, 0x88, 0xE3, 0x82, 0xB1, 0xE3, 0x82,
+ 0x99, 0xE3, 0x83, 0xB3, 0x61, 0xD8, 0xB5, 0xD9,
+ // Bytes 2c80 - 2cbf
+ 0x84, 0xD9, 0x89, 0x20, 0xD8, 0xA7, 0xD9, 0x84,
+ 0xD9, 0x84, 0xD9, 0x87, 0x20, 0xD8, 0xB9, 0xD9,
+ 0x84, 0xD9, 0x8A, 0xD9, 0x87, 0x20, 0xD9, 0x88,
+ 0xD8, 0xB3, 0xD9, 0x84, 0xD9, 0x85, 0x06, 0xE0,
+ 0xA7, 0x87, 0xE0, 0xA6, 0xBE, 0x01, 0x06, 0xE0,
+ 0xA7, 0x87, 0xE0, 0xA7, 0x97, 0x01, 0x06, 0xE0,
+ 0xAD, 0x87, 0xE0, 0xAC, 0xBE, 0x01, 0x06, 0xE0,
+ 0xAD, 0x87, 0xE0, 0xAD, 0x96, 0x01, 0x06, 0xE0,
+ // Bytes 2cc0 - 2cff
+ 0xAD, 0x87, 0xE0, 0xAD, 0x97, 0x01, 0x06, 0xE0,
+ 0xAE, 0x92, 0xE0, 0xAF, 0x97, 0x01, 0x06, 0xE0,
+ 0xAF, 0x86, 0xE0, 0xAE, 0xBE, 0x01, 0x06, 0xE0,
+ 0xAF, 0x86, 0xE0, 0xAF, 0x97, 0x01, 0x06, 0xE0,
+ 0xAF, 0x87, 0xE0, 0xAE, 0xBE, 0x01, 0x06, 0xE0,
+ 0xB2, 0xBF, 0xE0, 0xB3, 0x95, 0x01, 0x06, 0xE0,
+ 0xB3, 0x86, 0xE0, 0xB3, 0x95, 0x01, 0x06, 0xE0,
+ 0xB3, 0x86, 0xE0, 0xB3, 0x96, 0x01, 0x06, 0xE0,
+ // Bytes 2d00 - 2d3f
+ 0xB5, 0x86, 0xE0, 0xB4, 0xBE, 0x01, 0x06, 0xE0,
+ 0xB5, 0x86, 0xE0, 0xB5, 0x97, 0x01, 0x06, 0xE0,
+ 0xB5, 0x87, 0xE0, 0xB4, 0xBE, 0x01, 0x06, 0xE0,
+ 0xB7, 0x99, 0xE0, 0xB7, 0x9F, 0x01, 0x06, 0xE1,
+ 0x80, 0xA5, 0xE1, 0x80, 0xAE, 0x01, 0x06, 0xE1,
+ 0xAC, 0x85, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0x87, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0x89, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ // Bytes 2d40 - 2d7f
+ 0xAC, 0x8B, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0x8D, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0x91, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0xBA, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0xBC, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0xBE, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0xBF, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAD, 0x82, 0xE1, 0xAC, 0xB5, 0x01, 0x08, 0xF0,
+ // Bytes 2d80 - 2dbf
+ 0x91, 0x84, 0xB1, 0xF0, 0x91, 0x84, 0xA7, 0x01,
+ 0x08, 0xF0, 0x91, 0x84, 0xB2, 0xF0, 0x91, 0x84,
+ 0xA7, 0x01, 0x08, 0xF0, 0x91, 0x8D, 0x87, 0xF0,
+ 0x91, 0x8C, 0xBE, 0x01, 0x08, 0xF0, 0x91, 0x8D,
+ 0x87, 0xF0, 0x91, 0x8D, 0x97, 0x01, 0x08, 0xF0,
+ 0x91, 0x92, 0xB9, 0xF0, 0x91, 0x92, 0xB0, 0x01,
+ 0x08, 0xF0, 0x91, 0x92, 0xB9, 0xF0, 0x91, 0x92,
+ 0xBA, 0x01, 0x08, 0xF0, 0x91, 0x92, 0xB9, 0xF0,
+ // Bytes 2dc0 - 2dff
+ 0x91, 0x92, 0xBD, 0x01, 0x08, 0xF0, 0x91, 0x96,
+ 0xB8, 0xF0, 0x91, 0x96, 0xAF, 0x01, 0x08, 0xF0,
+ 0x91, 0x96, 0xB9, 0xF0, 0x91, 0x96, 0xAF, 0x01,
+ 0x09, 0xE0, 0xB3, 0x86, 0xE0, 0xB3, 0x82, 0xE0,
+ 0xB3, 0x95, 0x02, 0x09, 0xE0, 0xB7, 0x99, 0xE0,
+ 0xB7, 0x8F, 0xE0, 0xB7, 0x8A, 0x12, 0x44, 0x44,
+ 0x5A, 0xCC, 0x8C, 0xC9, 0x44, 0x44, 0x7A, 0xCC,
+ 0x8C, 0xC9, 0x44, 0x64, 0x7A, 0xCC, 0x8C, 0xC9,
+ // Bytes 2e00 - 2e3f
+ 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x93, 0xC9,
+ 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x94, 0xC9,
+ 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x95, 0xB5,
+ 0x46, 0xE1, 0x84, 0x80, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x82, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x83, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x85, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x86, 0xE1, 0x85, 0xA1, 0x01,
+ // Bytes 2e40 - 2e7f
+ 0x46, 0xE1, 0x84, 0x87, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x89, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xAE, 0x01,
+ 0x46, 0xE1, 0x84, 0x8C, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x8E, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x8F, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x90, 0xE1, 0x85, 0xA1, 0x01,
+ // Bytes 2e80 - 2ebf
+ 0x46, 0xE1, 0x84, 0x91, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x92, 0xE1, 0x85, 0xA1, 0x01,
+ 0x49, 0xE3, 0x83, 0xA1, 0xE3, 0x82, 0xAB, 0xE3,
+ 0x82, 0x99, 0x0D, 0x4C, 0xE1, 0x84, 0x8C, 0xE1,
+ 0x85, 0xAE, 0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xB4,
+ 0x01, 0x4C, 0xE3, 0x82, 0xAD, 0xE3, 0x82, 0x99,
+ 0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0x0D, 0x4C,
+ 0xE3, 0x82, 0xB3, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
+ // Bytes 2ec0 - 2eff
+ 0x9B, 0xE3, 0x82, 0x9A, 0x0D, 0x4C, 0xE3, 0x83,
+ 0xA4, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x88, 0xE3,
+ 0x82, 0x99, 0x0D, 0x4F, 0xE1, 0x84, 0x8E, 0xE1,
+ 0x85, 0xA1, 0xE1, 0x86, 0xB7, 0xE1, 0x84, 0x80,
+ 0xE1, 0x85, 0xA9, 0x01, 0x4F, 0xE3, 0x82, 0xA4,
+ 0xE3, 0x83, 0x8B, 0xE3, 0x83, 0xB3, 0xE3, 0x82,
+ 0xAF, 0xE3, 0x82, 0x99, 0x0D, 0x4F, 0xE3, 0x82,
+ 0xB7, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xB3, 0xE3,
+ // Bytes 2f00 - 2f3f
+ 0x82, 0xAF, 0xE3, 0x82, 0x99, 0x0D, 0x4F, 0xE3,
+ 0x83, 0x98, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC,
+ 0xE3, 0x82, 0xB7, 0xE3, 0x82, 0x99, 0x0D, 0x4F,
+ 0xE3, 0x83, 0x9B, 0xE3, 0x82, 0x9A, 0xE3, 0x83,
+ 0xB3, 0xE3, 0x83, 0x88, 0xE3, 0x82, 0x99, 0x0D,
+ 0x52, 0xE3, 0x82, 0xA8, 0xE3, 0x82, 0xB9, 0xE3,
+ 0x82, 0xAF, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x88,
+ 0xE3, 0x82, 0x99, 0x0D, 0x52, 0xE3, 0x83, 0x95,
+ // Bytes 2f40 - 2f7f
+ 0xE3, 0x82, 0xA1, 0xE3, 0x83, 0xA9, 0xE3, 0x83,
+ 0x83, 0xE3, 0x83, 0x88, 0xE3, 0x82, 0x99, 0x0D,
+ 0x86, 0xE0, 0xB3, 0x86, 0xE0, 0xB3, 0x82, 0x01,
+ 0x86, 0xE0, 0xB7, 0x99, 0xE0, 0xB7, 0x8F, 0x01,
+ 0x03, 0x3C, 0xCC, 0xB8, 0x05, 0x03, 0x3D, 0xCC,
+ 0xB8, 0x05, 0x03, 0x3E, 0xCC, 0xB8, 0x05, 0x03,
+ 0x41, 0xCC, 0x80, 0xC9, 0x03, 0x41, 0xCC, 0x81,
+ 0xC9, 0x03, 0x41, 0xCC, 0x83, 0xC9, 0x03, 0x41,
+ // Bytes 2f80 - 2fbf
+ 0xCC, 0x84, 0xC9, 0x03, 0x41, 0xCC, 0x89, 0xC9,
+ 0x03, 0x41, 0xCC, 0x8C, 0xC9, 0x03, 0x41, 0xCC,
+ 0x8F, 0xC9, 0x03, 0x41, 0xCC, 0x91, 0xC9, 0x03,
+ 0x41, 0xCC, 0xA5, 0xB5, 0x03, 0x41, 0xCC, 0xA8,
+ 0xA5, 0x03, 0x42, 0xCC, 0x87, 0xC9, 0x03, 0x42,
+ 0xCC, 0xA3, 0xB5, 0x03, 0x42, 0xCC, 0xB1, 0xB5,
+ 0x03, 0x43, 0xCC, 0x81, 0xC9, 0x03, 0x43, 0xCC,
+ 0x82, 0xC9, 0x03, 0x43, 0xCC, 0x87, 0xC9, 0x03,
+ // Bytes 2fc0 - 2fff
+ 0x43, 0xCC, 0x8C, 0xC9, 0x03, 0x44, 0xCC, 0x87,
+ 0xC9, 0x03, 0x44, 0xCC, 0x8C, 0xC9, 0x03, 0x44,
+ 0xCC, 0xA3, 0xB5, 0x03, 0x44, 0xCC, 0xA7, 0xA5,
+ 0x03, 0x44, 0xCC, 0xAD, 0xB5, 0x03, 0x44, 0xCC,
+ 0xB1, 0xB5, 0x03, 0x45, 0xCC, 0x80, 0xC9, 0x03,
+ 0x45, 0xCC, 0x81, 0xC9, 0x03, 0x45, 0xCC, 0x83,
+ 0xC9, 0x03, 0x45, 0xCC, 0x86, 0xC9, 0x03, 0x45,
+ 0xCC, 0x87, 0xC9, 0x03, 0x45, 0xCC, 0x88, 0xC9,
+ // Bytes 3000 - 303f
+ 0x03, 0x45, 0xCC, 0x89, 0xC9, 0x03, 0x45, 0xCC,
+ 0x8C, 0xC9, 0x03, 0x45, 0xCC, 0x8F, 0xC9, 0x03,
+ 0x45, 0xCC, 0x91, 0xC9, 0x03, 0x45, 0xCC, 0xA8,
+ 0xA5, 0x03, 0x45, 0xCC, 0xAD, 0xB5, 0x03, 0x45,
+ 0xCC, 0xB0, 0xB5, 0x03, 0x46, 0xCC, 0x87, 0xC9,
+ 0x03, 0x47, 0xCC, 0x81, 0xC9, 0x03, 0x47, 0xCC,
+ 0x82, 0xC9, 0x03, 0x47, 0xCC, 0x84, 0xC9, 0x03,
+ 0x47, 0xCC, 0x86, 0xC9, 0x03, 0x47, 0xCC, 0x87,
+ // Bytes 3040 - 307f
+ 0xC9, 0x03, 0x47, 0xCC, 0x8C, 0xC9, 0x03, 0x47,
+ 0xCC, 0xA7, 0xA5, 0x03, 0x48, 0xCC, 0x82, 0xC9,
+ 0x03, 0x48, 0xCC, 0x87, 0xC9, 0x03, 0x48, 0xCC,
+ 0x88, 0xC9, 0x03, 0x48, 0xCC, 0x8C, 0xC9, 0x03,
+ 0x48, 0xCC, 0xA3, 0xB5, 0x03, 0x48, 0xCC, 0xA7,
+ 0xA5, 0x03, 0x48, 0xCC, 0xAE, 0xB5, 0x03, 0x49,
+ 0xCC, 0x80, 0xC9, 0x03, 0x49, 0xCC, 0x81, 0xC9,
+ 0x03, 0x49, 0xCC, 0x82, 0xC9, 0x03, 0x49, 0xCC,
+ // Bytes 3080 - 30bf
+ 0x83, 0xC9, 0x03, 0x49, 0xCC, 0x84, 0xC9, 0x03,
+ 0x49, 0xCC, 0x86, 0xC9, 0x03, 0x49, 0xCC, 0x87,
+ 0xC9, 0x03, 0x49, 0xCC, 0x89, 0xC9, 0x03, 0x49,
+ 0xCC, 0x8C, 0xC9, 0x03, 0x49, 0xCC, 0x8F, 0xC9,
+ 0x03, 0x49, 0xCC, 0x91, 0xC9, 0x03, 0x49, 0xCC,
+ 0xA3, 0xB5, 0x03, 0x49, 0xCC, 0xA8, 0xA5, 0x03,
+ 0x49, 0xCC, 0xB0, 0xB5, 0x03, 0x4A, 0xCC, 0x82,
+ 0xC9, 0x03, 0x4B, 0xCC, 0x81, 0xC9, 0x03, 0x4B,
+ // Bytes 30c0 - 30ff
+ 0xCC, 0x8C, 0xC9, 0x03, 0x4B, 0xCC, 0xA3, 0xB5,
+ 0x03, 0x4B, 0xCC, 0xA7, 0xA5, 0x03, 0x4B, 0xCC,
+ 0xB1, 0xB5, 0x03, 0x4C, 0xCC, 0x81, 0xC9, 0x03,
+ 0x4C, 0xCC, 0x8C, 0xC9, 0x03, 0x4C, 0xCC, 0xA7,
+ 0xA5, 0x03, 0x4C, 0xCC, 0xAD, 0xB5, 0x03, 0x4C,
+ 0xCC, 0xB1, 0xB5, 0x03, 0x4D, 0xCC, 0x81, 0xC9,
+ 0x03, 0x4D, 0xCC, 0x87, 0xC9, 0x03, 0x4D, 0xCC,
+ 0xA3, 0xB5, 0x03, 0x4E, 0xCC, 0x80, 0xC9, 0x03,
+ // Bytes 3100 - 313f
+ 0x4E, 0xCC, 0x81, 0xC9, 0x03, 0x4E, 0xCC, 0x83,
+ 0xC9, 0x03, 0x4E, 0xCC, 0x87, 0xC9, 0x03, 0x4E,
+ 0xCC, 0x8C, 0xC9, 0x03, 0x4E, 0xCC, 0xA3, 0xB5,
+ 0x03, 0x4E, 0xCC, 0xA7, 0xA5, 0x03, 0x4E, 0xCC,
+ 0xAD, 0xB5, 0x03, 0x4E, 0xCC, 0xB1, 0xB5, 0x03,
+ 0x4F, 0xCC, 0x80, 0xC9, 0x03, 0x4F, 0xCC, 0x81,
+ 0xC9, 0x03, 0x4F, 0xCC, 0x86, 0xC9, 0x03, 0x4F,
+ 0xCC, 0x89, 0xC9, 0x03, 0x4F, 0xCC, 0x8B, 0xC9,
+ // Bytes 3140 - 317f
+ 0x03, 0x4F, 0xCC, 0x8C, 0xC9, 0x03, 0x4F, 0xCC,
+ 0x8F, 0xC9, 0x03, 0x4F, 0xCC, 0x91, 0xC9, 0x03,
+ 0x50, 0xCC, 0x81, 0xC9, 0x03, 0x50, 0xCC, 0x87,
+ 0xC9, 0x03, 0x52, 0xCC, 0x81, 0xC9, 0x03, 0x52,
+ 0xCC, 0x87, 0xC9, 0x03, 0x52, 0xCC, 0x8C, 0xC9,
+ 0x03, 0x52, 0xCC, 0x8F, 0xC9, 0x03, 0x52, 0xCC,
+ 0x91, 0xC9, 0x03, 0x52, 0xCC, 0xA7, 0xA5, 0x03,
+ 0x52, 0xCC, 0xB1, 0xB5, 0x03, 0x53, 0xCC, 0x82,
+ // Bytes 3180 - 31bf
+ 0xC9, 0x03, 0x53, 0xCC, 0x87, 0xC9, 0x03, 0x53,
+ 0xCC, 0xA6, 0xB5, 0x03, 0x53, 0xCC, 0xA7, 0xA5,
+ 0x03, 0x54, 0xCC, 0x87, 0xC9, 0x03, 0x54, 0xCC,
+ 0x8C, 0xC9, 0x03, 0x54, 0xCC, 0xA3, 0xB5, 0x03,
+ 0x54, 0xCC, 0xA6, 0xB5, 0x03, 0x54, 0xCC, 0xA7,
+ 0xA5, 0x03, 0x54, 0xCC, 0xAD, 0xB5, 0x03, 0x54,
+ 0xCC, 0xB1, 0xB5, 0x03, 0x55, 0xCC, 0x80, 0xC9,
+ 0x03, 0x55, 0xCC, 0x81, 0xC9, 0x03, 0x55, 0xCC,
+ // Bytes 31c0 - 31ff
+ 0x82, 0xC9, 0x03, 0x55, 0xCC, 0x86, 0xC9, 0x03,
+ 0x55, 0xCC, 0x89, 0xC9, 0x03, 0x55, 0xCC, 0x8A,
+ 0xC9, 0x03, 0x55, 0xCC, 0x8B, 0xC9, 0x03, 0x55,
+ 0xCC, 0x8C, 0xC9, 0x03, 0x55, 0xCC, 0x8F, 0xC9,
+ 0x03, 0x55, 0xCC, 0x91, 0xC9, 0x03, 0x55, 0xCC,
+ 0xA3, 0xB5, 0x03, 0x55, 0xCC, 0xA4, 0xB5, 0x03,
+ 0x55, 0xCC, 0xA8, 0xA5, 0x03, 0x55, 0xCC, 0xAD,
+ 0xB5, 0x03, 0x55, 0xCC, 0xB0, 0xB5, 0x03, 0x56,
+ // Bytes 3200 - 323f
+ 0xCC, 0x83, 0xC9, 0x03, 0x56, 0xCC, 0xA3, 0xB5,
+ 0x03, 0x57, 0xCC, 0x80, 0xC9, 0x03, 0x57, 0xCC,
+ 0x81, 0xC9, 0x03, 0x57, 0xCC, 0x82, 0xC9, 0x03,
+ 0x57, 0xCC, 0x87, 0xC9, 0x03, 0x57, 0xCC, 0x88,
+ 0xC9, 0x03, 0x57, 0xCC, 0xA3, 0xB5, 0x03, 0x58,
+ 0xCC, 0x87, 0xC9, 0x03, 0x58, 0xCC, 0x88, 0xC9,
+ 0x03, 0x59, 0xCC, 0x80, 0xC9, 0x03, 0x59, 0xCC,
+ 0x81, 0xC9, 0x03, 0x59, 0xCC, 0x82, 0xC9, 0x03,
+ // Bytes 3240 - 327f
+ 0x59, 0xCC, 0x83, 0xC9, 0x03, 0x59, 0xCC, 0x84,
+ 0xC9, 0x03, 0x59, 0xCC, 0x87, 0xC9, 0x03, 0x59,
+ 0xCC, 0x88, 0xC9, 0x03, 0x59, 0xCC, 0x89, 0xC9,
+ 0x03, 0x59, 0xCC, 0xA3, 0xB5, 0x03, 0x5A, 0xCC,
+ 0x81, 0xC9, 0x03, 0x5A, 0xCC, 0x82, 0xC9, 0x03,
+ 0x5A, 0xCC, 0x87, 0xC9, 0x03, 0x5A, 0xCC, 0x8C,
+ 0xC9, 0x03, 0x5A, 0xCC, 0xA3, 0xB5, 0x03, 0x5A,
+ 0xCC, 0xB1, 0xB5, 0x03, 0x61, 0xCC, 0x80, 0xC9,
+ // Bytes 3280 - 32bf
+ 0x03, 0x61, 0xCC, 0x81, 0xC9, 0x03, 0x61, 0xCC,
+ 0x83, 0xC9, 0x03, 0x61, 0xCC, 0x84, 0xC9, 0x03,
+ 0x61, 0xCC, 0x89, 0xC9, 0x03, 0x61, 0xCC, 0x8C,
+ 0xC9, 0x03, 0x61, 0xCC, 0x8F, 0xC9, 0x03, 0x61,
+ 0xCC, 0x91, 0xC9, 0x03, 0x61, 0xCC, 0xA5, 0xB5,
+ 0x03, 0x61, 0xCC, 0xA8, 0xA5, 0x03, 0x62, 0xCC,
+ 0x87, 0xC9, 0x03, 0x62, 0xCC, 0xA3, 0xB5, 0x03,
+ 0x62, 0xCC, 0xB1, 0xB5, 0x03, 0x63, 0xCC, 0x81,
+ // Bytes 32c0 - 32ff
+ 0xC9, 0x03, 0x63, 0xCC, 0x82, 0xC9, 0x03, 0x63,
+ 0xCC, 0x87, 0xC9, 0x03, 0x63, 0xCC, 0x8C, 0xC9,
+ 0x03, 0x64, 0xCC, 0x87, 0xC9, 0x03, 0x64, 0xCC,
+ 0x8C, 0xC9, 0x03, 0x64, 0xCC, 0xA3, 0xB5, 0x03,
+ 0x64, 0xCC, 0xA7, 0xA5, 0x03, 0x64, 0xCC, 0xAD,
+ 0xB5, 0x03, 0x64, 0xCC, 0xB1, 0xB5, 0x03, 0x65,
+ 0xCC, 0x80, 0xC9, 0x03, 0x65, 0xCC, 0x81, 0xC9,
+ 0x03, 0x65, 0xCC, 0x83, 0xC9, 0x03, 0x65, 0xCC,
+ // Bytes 3300 - 333f
+ 0x86, 0xC9, 0x03, 0x65, 0xCC, 0x87, 0xC9, 0x03,
+ 0x65, 0xCC, 0x88, 0xC9, 0x03, 0x65, 0xCC, 0x89,
+ 0xC9, 0x03, 0x65, 0xCC, 0x8C, 0xC9, 0x03, 0x65,
+ 0xCC, 0x8F, 0xC9, 0x03, 0x65, 0xCC, 0x91, 0xC9,
+ 0x03, 0x65, 0xCC, 0xA8, 0xA5, 0x03, 0x65, 0xCC,
+ 0xAD, 0xB5, 0x03, 0x65, 0xCC, 0xB0, 0xB5, 0x03,
+ 0x66, 0xCC, 0x87, 0xC9, 0x03, 0x67, 0xCC, 0x81,
+ 0xC9, 0x03, 0x67, 0xCC, 0x82, 0xC9, 0x03, 0x67,
+ // Bytes 3340 - 337f
+ 0xCC, 0x84, 0xC9, 0x03, 0x67, 0xCC, 0x86, 0xC9,
+ 0x03, 0x67, 0xCC, 0x87, 0xC9, 0x03, 0x67, 0xCC,
+ 0x8C, 0xC9, 0x03, 0x67, 0xCC, 0xA7, 0xA5, 0x03,
+ 0x68, 0xCC, 0x82, 0xC9, 0x03, 0x68, 0xCC, 0x87,
+ 0xC9, 0x03, 0x68, 0xCC, 0x88, 0xC9, 0x03, 0x68,
+ 0xCC, 0x8C, 0xC9, 0x03, 0x68, 0xCC, 0xA3, 0xB5,
+ 0x03, 0x68, 0xCC, 0xA7, 0xA5, 0x03, 0x68, 0xCC,
+ 0xAE, 0xB5, 0x03, 0x68, 0xCC, 0xB1, 0xB5, 0x03,
+ // Bytes 3380 - 33bf
+ 0x69, 0xCC, 0x80, 0xC9, 0x03, 0x69, 0xCC, 0x81,
+ 0xC9, 0x03, 0x69, 0xCC, 0x82, 0xC9, 0x03, 0x69,
+ 0xCC, 0x83, 0xC9, 0x03, 0x69, 0xCC, 0x84, 0xC9,
+ 0x03, 0x69, 0xCC, 0x86, 0xC9, 0x03, 0x69, 0xCC,
+ 0x89, 0xC9, 0x03, 0x69, 0xCC, 0x8C, 0xC9, 0x03,
+ 0x69, 0xCC, 0x8F, 0xC9, 0x03, 0x69, 0xCC, 0x91,
+ 0xC9, 0x03, 0x69, 0xCC, 0xA3, 0xB5, 0x03, 0x69,
+ 0xCC, 0xA8, 0xA5, 0x03, 0x69, 0xCC, 0xB0, 0xB5,
+ // Bytes 33c0 - 33ff
+ 0x03, 0x6A, 0xCC, 0x82, 0xC9, 0x03, 0x6A, 0xCC,
+ 0x8C, 0xC9, 0x03, 0x6B, 0xCC, 0x81, 0xC9, 0x03,
+ 0x6B, 0xCC, 0x8C, 0xC9, 0x03, 0x6B, 0xCC, 0xA3,
+ 0xB5, 0x03, 0x6B, 0xCC, 0xA7, 0xA5, 0x03, 0x6B,
+ 0xCC, 0xB1, 0xB5, 0x03, 0x6C, 0xCC, 0x81, 0xC9,
+ 0x03, 0x6C, 0xCC, 0x8C, 0xC9, 0x03, 0x6C, 0xCC,
+ 0xA7, 0xA5, 0x03, 0x6C, 0xCC, 0xAD, 0xB5, 0x03,
+ 0x6C, 0xCC, 0xB1, 0xB5, 0x03, 0x6D, 0xCC, 0x81,
+ // Bytes 3400 - 343f
+ 0xC9, 0x03, 0x6D, 0xCC, 0x87, 0xC9, 0x03, 0x6D,
+ 0xCC, 0xA3, 0xB5, 0x03, 0x6E, 0xCC, 0x80, 0xC9,
+ 0x03, 0x6E, 0xCC, 0x81, 0xC9, 0x03, 0x6E, 0xCC,
+ 0x83, 0xC9, 0x03, 0x6E, 0xCC, 0x87, 0xC9, 0x03,
+ 0x6E, 0xCC, 0x8C, 0xC9, 0x03, 0x6E, 0xCC, 0xA3,
+ 0xB5, 0x03, 0x6E, 0xCC, 0xA7, 0xA5, 0x03, 0x6E,
+ 0xCC, 0xAD, 0xB5, 0x03, 0x6E, 0xCC, 0xB1, 0xB5,
+ 0x03, 0x6F, 0xCC, 0x80, 0xC9, 0x03, 0x6F, 0xCC,
+ // Bytes 3440 - 347f
+ 0x81, 0xC9, 0x03, 0x6F, 0xCC, 0x86, 0xC9, 0x03,
+ 0x6F, 0xCC, 0x89, 0xC9, 0x03, 0x6F, 0xCC, 0x8B,
+ 0xC9, 0x03, 0x6F, 0xCC, 0x8C, 0xC9, 0x03, 0x6F,
+ 0xCC, 0x8F, 0xC9, 0x03, 0x6F, 0xCC, 0x91, 0xC9,
+ 0x03, 0x70, 0xCC, 0x81, 0xC9, 0x03, 0x70, 0xCC,
+ 0x87, 0xC9, 0x03, 0x72, 0xCC, 0x81, 0xC9, 0x03,
+ 0x72, 0xCC, 0x87, 0xC9, 0x03, 0x72, 0xCC, 0x8C,
+ 0xC9, 0x03, 0x72, 0xCC, 0x8F, 0xC9, 0x03, 0x72,
+ // Bytes 3480 - 34bf
+ 0xCC, 0x91, 0xC9, 0x03, 0x72, 0xCC, 0xA7, 0xA5,
+ 0x03, 0x72, 0xCC, 0xB1, 0xB5, 0x03, 0x73, 0xCC,
+ 0x82, 0xC9, 0x03, 0x73, 0xCC, 0x87, 0xC9, 0x03,
+ 0x73, 0xCC, 0xA6, 0xB5, 0x03, 0x73, 0xCC, 0xA7,
+ 0xA5, 0x03, 0x74, 0xCC, 0x87, 0xC9, 0x03, 0x74,
+ 0xCC, 0x88, 0xC9, 0x03, 0x74, 0xCC, 0x8C, 0xC9,
+ 0x03, 0x74, 0xCC, 0xA3, 0xB5, 0x03, 0x74, 0xCC,
+ 0xA6, 0xB5, 0x03, 0x74, 0xCC, 0xA7, 0xA5, 0x03,
+ // Bytes 34c0 - 34ff
+ 0x74, 0xCC, 0xAD, 0xB5, 0x03, 0x74, 0xCC, 0xB1,
+ 0xB5, 0x03, 0x75, 0xCC, 0x80, 0xC9, 0x03, 0x75,
+ 0xCC, 0x81, 0xC9, 0x03, 0x75, 0xCC, 0x82, 0xC9,
+ 0x03, 0x75, 0xCC, 0x86, 0xC9, 0x03, 0x75, 0xCC,
+ 0x89, 0xC9, 0x03, 0x75, 0xCC, 0x8A, 0xC9, 0x03,
+ 0x75, 0xCC, 0x8B, 0xC9, 0x03, 0x75, 0xCC, 0x8C,
+ 0xC9, 0x03, 0x75, 0xCC, 0x8F, 0xC9, 0x03, 0x75,
+ 0xCC, 0x91, 0xC9, 0x03, 0x75, 0xCC, 0xA3, 0xB5,
+ // Bytes 3500 - 353f
+ 0x03, 0x75, 0xCC, 0xA4, 0xB5, 0x03, 0x75, 0xCC,
+ 0xA8, 0xA5, 0x03, 0x75, 0xCC, 0xAD, 0xB5, 0x03,
+ 0x75, 0xCC, 0xB0, 0xB5, 0x03, 0x76, 0xCC, 0x83,
+ 0xC9, 0x03, 0x76, 0xCC, 0xA3, 0xB5, 0x03, 0x77,
+ 0xCC, 0x80, 0xC9, 0x03, 0x77, 0xCC, 0x81, 0xC9,
+ 0x03, 0x77, 0xCC, 0x82, 0xC9, 0x03, 0x77, 0xCC,
+ 0x87, 0xC9, 0x03, 0x77, 0xCC, 0x88, 0xC9, 0x03,
+ 0x77, 0xCC, 0x8A, 0xC9, 0x03, 0x77, 0xCC, 0xA3,
+ // Bytes 3540 - 357f
+ 0xB5, 0x03, 0x78, 0xCC, 0x87, 0xC9, 0x03, 0x78,
+ 0xCC, 0x88, 0xC9, 0x03, 0x79, 0xCC, 0x80, 0xC9,
+ 0x03, 0x79, 0xCC, 0x81, 0xC9, 0x03, 0x79, 0xCC,
+ 0x82, 0xC9, 0x03, 0x79, 0xCC, 0x83, 0xC9, 0x03,
+ 0x79, 0xCC, 0x84, 0xC9, 0x03, 0x79, 0xCC, 0x87,
+ 0xC9, 0x03, 0x79, 0xCC, 0x88, 0xC9, 0x03, 0x79,
+ 0xCC, 0x89, 0xC9, 0x03, 0x79, 0xCC, 0x8A, 0xC9,
+ 0x03, 0x79, 0xCC, 0xA3, 0xB5, 0x03, 0x7A, 0xCC,
+ // Bytes 3580 - 35bf
+ 0x81, 0xC9, 0x03, 0x7A, 0xCC, 0x82, 0xC9, 0x03,
+ 0x7A, 0xCC, 0x87, 0xC9, 0x03, 0x7A, 0xCC, 0x8C,
+ 0xC9, 0x03, 0x7A, 0xCC, 0xA3, 0xB5, 0x03, 0x7A,
+ 0xCC, 0xB1, 0xB5, 0x04, 0xC2, 0xA8, 0xCC, 0x80,
+ 0xCA, 0x04, 0xC2, 0xA8, 0xCC, 0x81, 0xCA, 0x04,
+ 0xC2, 0xA8, 0xCD, 0x82, 0xCA, 0x04, 0xC3, 0x86,
+ 0xCC, 0x81, 0xC9, 0x04, 0xC3, 0x86, 0xCC, 0x84,
+ 0xC9, 0x04, 0xC3, 0x98, 0xCC, 0x81, 0xC9, 0x04,
+ // Bytes 35c0 - 35ff
+ 0xC3, 0xA6, 0xCC, 0x81, 0xC9, 0x04, 0xC3, 0xA6,
+ 0xCC, 0x84, 0xC9, 0x04, 0xC3, 0xB8, 0xCC, 0x81,
+ 0xC9, 0x04, 0xC5, 0xBF, 0xCC, 0x87, 0xC9, 0x04,
+ 0xC6, 0xB7, 0xCC, 0x8C, 0xC9, 0x04, 0xCA, 0x92,
+ 0xCC, 0x8C, 0xC9, 0x04, 0xCE, 0x91, 0xCC, 0x80,
+ 0xC9, 0x04, 0xCE, 0x91, 0xCC, 0x81, 0xC9, 0x04,
+ 0xCE, 0x91, 0xCC, 0x84, 0xC9, 0x04, 0xCE, 0x91,
+ 0xCC, 0x86, 0xC9, 0x04, 0xCE, 0x91, 0xCD, 0x85,
+ // Bytes 3600 - 363f
+ 0xD9, 0x04, 0xCE, 0x95, 0xCC, 0x80, 0xC9, 0x04,
+ 0xCE, 0x95, 0xCC, 0x81, 0xC9, 0x04, 0xCE, 0x97,
+ 0xCC, 0x80, 0xC9, 0x04, 0xCE, 0x97, 0xCC, 0x81,
+ 0xC9, 0x04, 0xCE, 0x97, 0xCD, 0x85, 0xD9, 0x04,
+ 0xCE, 0x99, 0xCC, 0x80, 0xC9, 0x04, 0xCE, 0x99,
+ 0xCC, 0x81, 0xC9, 0x04, 0xCE, 0x99, 0xCC, 0x84,
+ 0xC9, 0x04, 0xCE, 0x99, 0xCC, 0x86, 0xC9, 0x04,
+ 0xCE, 0x99, 0xCC, 0x88, 0xC9, 0x04, 0xCE, 0x9F,
+ // Bytes 3640 - 367f
+ 0xCC, 0x80, 0xC9, 0x04, 0xCE, 0x9F, 0xCC, 0x81,
+ 0xC9, 0x04, 0xCE, 0xA1, 0xCC, 0x94, 0xC9, 0x04,
+ 0xCE, 0xA5, 0xCC, 0x80, 0xC9, 0x04, 0xCE, 0xA5,
+ 0xCC, 0x81, 0xC9, 0x04, 0xCE, 0xA5, 0xCC, 0x84,
+ 0xC9, 0x04, 0xCE, 0xA5, 0xCC, 0x86, 0xC9, 0x04,
+ 0xCE, 0xA5, 0xCC, 0x88, 0xC9, 0x04, 0xCE, 0xA9,
+ 0xCC, 0x80, 0xC9, 0x04, 0xCE, 0xA9, 0xCC, 0x81,
+ 0xC9, 0x04, 0xCE, 0xA9, 0xCD, 0x85, 0xD9, 0x04,
+ // Bytes 3680 - 36bf
+ 0xCE, 0xB1, 0xCC, 0x84, 0xC9, 0x04, 0xCE, 0xB1,
+ 0xCC, 0x86, 0xC9, 0x04, 0xCE, 0xB1, 0xCD, 0x85,
+ 0xD9, 0x04, 0xCE, 0xB5, 0xCC, 0x80, 0xC9, 0x04,
+ 0xCE, 0xB5, 0xCC, 0x81, 0xC9, 0x04, 0xCE, 0xB7,
+ 0xCD, 0x85, 0xD9, 0x04, 0xCE, 0xB9, 0xCC, 0x80,
+ 0xC9, 0x04, 0xCE, 0xB9, 0xCC, 0x81, 0xC9, 0x04,
+ 0xCE, 0xB9, 0xCC, 0x84, 0xC9, 0x04, 0xCE, 0xB9,
+ 0xCC, 0x86, 0xC9, 0x04, 0xCE, 0xB9, 0xCD, 0x82,
+ // Bytes 36c0 - 36ff
+ 0xC9, 0x04, 0xCE, 0xBF, 0xCC, 0x80, 0xC9, 0x04,
+ 0xCE, 0xBF, 0xCC, 0x81, 0xC9, 0x04, 0xCF, 0x81,
+ 0xCC, 0x93, 0xC9, 0x04, 0xCF, 0x81, 0xCC, 0x94,
+ 0xC9, 0x04, 0xCF, 0x85, 0xCC, 0x80, 0xC9, 0x04,
+ 0xCF, 0x85, 0xCC, 0x81, 0xC9, 0x04, 0xCF, 0x85,
+ 0xCC, 0x84, 0xC9, 0x04, 0xCF, 0x85, 0xCC, 0x86,
+ 0xC9, 0x04, 0xCF, 0x85, 0xCD, 0x82, 0xC9, 0x04,
+ 0xCF, 0x89, 0xCD, 0x85, 0xD9, 0x04, 0xCF, 0x92,
+ // Bytes 3700 - 373f
+ 0xCC, 0x81, 0xC9, 0x04, 0xCF, 0x92, 0xCC, 0x88,
+ 0xC9, 0x04, 0xD0, 0x86, 0xCC, 0x88, 0xC9, 0x04,
+ 0xD0, 0x90, 0xCC, 0x86, 0xC9, 0x04, 0xD0, 0x90,
+ 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0x93, 0xCC, 0x81,
+ 0xC9, 0x04, 0xD0, 0x95, 0xCC, 0x80, 0xC9, 0x04,
+ 0xD0, 0x95, 0xCC, 0x86, 0xC9, 0x04, 0xD0, 0x95,
+ 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0x96, 0xCC, 0x86,
+ 0xC9, 0x04, 0xD0, 0x96, 0xCC, 0x88, 0xC9, 0x04,
+ // Bytes 3740 - 377f
+ 0xD0, 0x97, 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0x98,
+ 0xCC, 0x80, 0xC9, 0x04, 0xD0, 0x98, 0xCC, 0x84,
+ 0xC9, 0x04, 0xD0, 0x98, 0xCC, 0x86, 0xC9, 0x04,
+ 0xD0, 0x98, 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0x9A,
+ 0xCC, 0x81, 0xC9, 0x04, 0xD0, 0x9E, 0xCC, 0x88,
+ 0xC9, 0x04, 0xD0, 0xA3, 0xCC, 0x84, 0xC9, 0x04,
+ 0xD0, 0xA3, 0xCC, 0x86, 0xC9, 0x04, 0xD0, 0xA3,
+ 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0xA3, 0xCC, 0x8B,
+ // Bytes 3780 - 37bf
+ 0xC9, 0x04, 0xD0, 0xA7, 0xCC, 0x88, 0xC9, 0x04,
+ 0xD0, 0xAB, 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0xAD,
+ 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0xB0, 0xCC, 0x86,
+ 0xC9, 0x04, 0xD0, 0xB0, 0xCC, 0x88, 0xC9, 0x04,
+ 0xD0, 0xB3, 0xCC, 0x81, 0xC9, 0x04, 0xD0, 0xB5,
+ 0xCC, 0x80, 0xC9, 0x04, 0xD0, 0xB5, 0xCC, 0x86,
+ 0xC9, 0x04, 0xD0, 0xB5, 0xCC, 0x88, 0xC9, 0x04,
+ 0xD0, 0xB6, 0xCC, 0x86, 0xC9, 0x04, 0xD0, 0xB6,
+ // Bytes 37c0 - 37ff
+ 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0xB7, 0xCC, 0x88,
+ 0xC9, 0x04, 0xD0, 0xB8, 0xCC, 0x80, 0xC9, 0x04,
+ 0xD0, 0xB8, 0xCC, 0x84, 0xC9, 0x04, 0xD0, 0xB8,
+ 0xCC, 0x86, 0xC9, 0x04, 0xD0, 0xB8, 0xCC, 0x88,
+ 0xC9, 0x04, 0xD0, 0xBA, 0xCC, 0x81, 0xC9, 0x04,
+ 0xD0, 0xBE, 0xCC, 0x88, 0xC9, 0x04, 0xD1, 0x83,
+ 0xCC, 0x84, 0xC9, 0x04, 0xD1, 0x83, 0xCC, 0x86,
+ 0xC9, 0x04, 0xD1, 0x83, 0xCC, 0x88, 0xC9, 0x04,
+ // Bytes 3800 - 383f
+ 0xD1, 0x83, 0xCC, 0x8B, 0xC9, 0x04, 0xD1, 0x87,
+ 0xCC, 0x88, 0xC9, 0x04, 0xD1, 0x8B, 0xCC, 0x88,
+ 0xC9, 0x04, 0xD1, 0x8D, 0xCC, 0x88, 0xC9, 0x04,
+ 0xD1, 0x96, 0xCC, 0x88, 0xC9, 0x04, 0xD1, 0xB4,
+ 0xCC, 0x8F, 0xC9, 0x04, 0xD1, 0xB5, 0xCC, 0x8F,
+ 0xC9, 0x04, 0xD3, 0x98, 0xCC, 0x88, 0xC9, 0x04,
+ 0xD3, 0x99, 0xCC, 0x88, 0xC9, 0x04, 0xD3, 0xA8,
+ 0xCC, 0x88, 0xC9, 0x04, 0xD3, 0xA9, 0xCC, 0x88,
+ // Bytes 3840 - 387f
+ 0xC9, 0x04, 0xD8, 0xA7, 0xD9, 0x93, 0xC9, 0x04,
+ 0xD8, 0xA7, 0xD9, 0x94, 0xC9, 0x04, 0xD8, 0xA7,
+ 0xD9, 0x95, 0xB5, 0x04, 0xD9, 0x88, 0xD9, 0x94,
+ 0xC9, 0x04, 0xD9, 0x8A, 0xD9, 0x94, 0xC9, 0x04,
+ 0xDB, 0x81, 0xD9, 0x94, 0xC9, 0x04, 0xDB, 0x92,
+ 0xD9, 0x94, 0xC9, 0x04, 0xDB, 0x95, 0xD9, 0x94,
+ 0xC9, 0x05, 0x41, 0xCC, 0x82, 0xCC, 0x80, 0xCA,
+ 0x05, 0x41, 0xCC, 0x82, 0xCC, 0x81, 0xCA, 0x05,
+ // Bytes 3880 - 38bf
+ 0x41, 0xCC, 0x82, 0xCC, 0x83, 0xCA, 0x05, 0x41,
+ 0xCC, 0x82, 0xCC, 0x89, 0xCA, 0x05, 0x41, 0xCC,
+ 0x86, 0xCC, 0x80, 0xCA, 0x05, 0x41, 0xCC, 0x86,
+ 0xCC, 0x81, 0xCA, 0x05, 0x41, 0xCC, 0x86, 0xCC,
+ 0x83, 0xCA, 0x05, 0x41, 0xCC, 0x86, 0xCC, 0x89,
+ 0xCA, 0x05, 0x41, 0xCC, 0x87, 0xCC, 0x84, 0xCA,
+ 0x05, 0x41, 0xCC, 0x88, 0xCC, 0x84, 0xCA, 0x05,
+ 0x41, 0xCC, 0x8A, 0xCC, 0x81, 0xCA, 0x05, 0x41,
+ // Bytes 38c0 - 38ff
+ 0xCC, 0xA3, 0xCC, 0x82, 0xCA, 0x05, 0x41, 0xCC,
+ 0xA3, 0xCC, 0x86, 0xCA, 0x05, 0x43, 0xCC, 0xA7,
+ 0xCC, 0x81, 0xCA, 0x05, 0x45, 0xCC, 0x82, 0xCC,
+ 0x80, 0xCA, 0x05, 0x45, 0xCC, 0x82, 0xCC, 0x81,
+ 0xCA, 0x05, 0x45, 0xCC, 0x82, 0xCC, 0x83, 0xCA,
+ 0x05, 0x45, 0xCC, 0x82, 0xCC, 0x89, 0xCA, 0x05,
+ 0x45, 0xCC, 0x84, 0xCC, 0x80, 0xCA, 0x05, 0x45,
+ 0xCC, 0x84, 0xCC, 0x81, 0xCA, 0x05, 0x45, 0xCC,
+ // Bytes 3900 - 393f
+ 0xA3, 0xCC, 0x82, 0xCA, 0x05, 0x45, 0xCC, 0xA7,
+ 0xCC, 0x86, 0xCA, 0x05, 0x49, 0xCC, 0x88, 0xCC,
+ 0x81, 0xCA, 0x05, 0x4C, 0xCC, 0xA3, 0xCC, 0x84,
+ 0xCA, 0x05, 0x4F, 0xCC, 0x82, 0xCC, 0x80, 0xCA,
+ 0x05, 0x4F, 0xCC, 0x82, 0xCC, 0x81, 0xCA, 0x05,
+ 0x4F, 0xCC, 0x82, 0xCC, 0x83, 0xCA, 0x05, 0x4F,
+ 0xCC, 0x82, 0xCC, 0x89, 0xCA, 0x05, 0x4F, 0xCC,
+ 0x83, 0xCC, 0x81, 0xCA, 0x05, 0x4F, 0xCC, 0x83,
+ // Bytes 3940 - 397f
+ 0xCC, 0x84, 0xCA, 0x05, 0x4F, 0xCC, 0x83, 0xCC,
+ 0x88, 0xCA, 0x05, 0x4F, 0xCC, 0x84, 0xCC, 0x80,
+ 0xCA, 0x05, 0x4F, 0xCC, 0x84, 0xCC, 0x81, 0xCA,
+ 0x05, 0x4F, 0xCC, 0x87, 0xCC, 0x84, 0xCA, 0x05,
+ 0x4F, 0xCC, 0x88, 0xCC, 0x84, 0xCA, 0x05, 0x4F,
+ 0xCC, 0x9B, 0xCC, 0x80, 0xCA, 0x05, 0x4F, 0xCC,
+ 0x9B, 0xCC, 0x81, 0xCA, 0x05, 0x4F, 0xCC, 0x9B,
+ 0xCC, 0x83, 0xCA, 0x05, 0x4F, 0xCC, 0x9B, 0xCC,
+ // Bytes 3980 - 39bf
+ 0x89, 0xCA, 0x05, 0x4F, 0xCC, 0x9B, 0xCC, 0xA3,
+ 0xB6, 0x05, 0x4F, 0xCC, 0xA3, 0xCC, 0x82, 0xCA,
+ 0x05, 0x4F, 0xCC, 0xA8, 0xCC, 0x84, 0xCA, 0x05,
+ 0x52, 0xCC, 0xA3, 0xCC, 0x84, 0xCA, 0x05, 0x53,
+ 0xCC, 0x81, 0xCC, 0x87, 0xCA, 0x05, 0x53, 0xCC,
+ 0x8C, 0xCC, 0x87, 0xCA, 0x05, 0x53, 0xCC, 0xA3,
+ 0xCC, 0x87, 0xCA, 0x05, 0x55, 0xCC, 0x83, 0xCC,
+ 0x81, 0xCA, 0x05, 0x55, 0xCC, 0x84, 0xCC, 0x88,
+ // Bytes 39c0 - 39ff
+ 0xCA, 0x05, 0x55, 0xCC, 0x88, 0xCC, 0x80, 0xCA,
+ 0x05, 0x55, 0xCC, 0x88, 0xCC, 0x81, 0xCA, 0x05,
+ 0x55, 0xCC, 0x88, 0xCC, 0x84, 0xCA, 0x05, 0x55,
+ 0xCC, 0x88, 0xCC, 0x8C, 0xCA, 0x05, 0x55, 0xCC,
+ 0x9B, 0xCC, 0x80, 0xCA, 0x05, 0x55, 0xCC, 0x9B,
+ 0xCC, 0x81, 0xCA, 0x05, 0x55, 0xCC, 0x9B, 0xCC,
+ 0x83, 0xCA, 0x05, 0x55, 0xCC, 0x9B, 0xCC, 0x89,
+ 0xCA, 0x05, 0x55, 0xCC, 0x9B, 0xCC, 0xA3, 0xB6,
+ // Bytes 3a00 - 3a3f
+ 0x05, 0x61, 0xCC, 0x82, 0xCC, 0x80, 0xCA, 0x05,
+ 0x61, 0xCC, 0x82, 0xCC, 0x81, 0xCA, 0x05, 0x61,
+ 0xCC, 0x82, 0xCC, 0x83, 0xCA, 0x05, 0x61, 0xCC,
+ 0x82, 0xCC, 0x89, 0xCA, 0x05, 0x61, 0xCC, 0x86,
+ 0xCC, 0x80, 0xCA, 0x05, 0x61, 0xCC, 0x86, 0xCC,
+ 0x81, 0xCA, 0x05, 0x61, 0xCC, 0x86, 0xCC, 0x83,
+ 0xCA, 0x05, 0x61, 0xCC, 0x86, 0xCC, 0x89, 0xCA,
+ 0x05, 0x61, 0xCC, 0x87, 0xCC, 0x84, 0xCA, 0x05,
+ // Bytes 3a40 - 3a7f
+ 0x61, 0xCC, 0x88, 0xCC, 0x84, 0xCA, 0x05, 0x61,
+ 0xCC, 0x8A, 0xCC, 0x81, 0xCA, 0x05, 0x61, 0xCC,
+ 0xA3, 0xCC, 0x82, 0xCA, 0x05, 0x61, 0xCC, 0xA3,
+ 0xCC, 0x86, 0xCA, 0x05, 0x63, 0xCC, 0xA7, 0xCC,
+ 0x81, 0xCA, 0x05, 0x65, 0xCC, 0x82, 0xCC, 0x80,
+ 0xCA, 0x05, 0x65, 0xCC, 0x82, 0xCC, 0x81, 0xCA,
+ 0x05, 0x65, 0xCC, 0x82, 0xCC, 0x83, 0xCA, 0x05,
+ 0x65, 0xCC, 0x82, 0xCC, 0x89, 0xCA, 0x05, 0x65,
+ // Bytes 3a80 - 3abf
+ 0xCC, 0x84, 0xCC, 0x80, 0xCA, 0x05, 0x65, 0xCC,
+ 0x84, 0xCC, 0x81, 0xCA, 0x05, 0x65, 0xCC, 0xA3,
+ 0xCC, 0x82, 0xCA, 0x05, 0x65, 0xCC, 0xA7, 0xCC,
+ 0x86, 0xCA, 0x05, 0x69, 0xCC, 0x88, 0xCC, 0x81,
+ 0xCA, 0x05, 0x6C, 0xCC, 0xA3, 0xCC, 0x84, 0xCA,
+ 0x05, 0x6F, 0xCC, 0x82, 0xCC, 0x80, 0xCA, 0x05,
+ 0x6F, 0xCC, 0x82, 0xCC, 0x81, 0xCA, 0x05, 0x6F,
+ 0xCC, 0x82, 0xCC, 0x83, 0xCA, 0x05, 0x6F, 0xCC,
+ // Bytes 3ac0 - 3aff
+ 0x82, 0xCC, 0x89, 0xCA, 0x05, 0x6F, 0xCC, 0x83,
+ 0xCC, 0x81, 0xCA, 0x05, 0x6F, 0xCC, 0x83, 0xCC,
+ 0x84, 0xCA, 0x05, 0x6F, 0xCC, 0x83, 0xCC, 0x88,
+ 0xCA, 0x05, 0x6F, 0xCC, 0x84, 0xCC, 0x80, 0xCA,
+ 0x05, 0x6F, 0xCC, 0x84, 0xCC, 0x81, 0xCA, 0x05,
+ 0x6F, 0xCC, 0x87, 0xCC, 0x84, 0xCA, 0x05, 0x6F,
+ 0xCC, 0x88, 0xCC, 0x84, 0xCA, 0x05, 0x6F, 0xCC,
+ 0x9B, 0xCC, 0x80, 0xCA, 0x05, 0x6F, 0xCC, 0x9B,
+ // Bytes 3b00 - 3b3f
+ 0xCC, 0x81, 0xCA, 0x05, 0x6F, 0xCC, 0x9B, 0xCC,
+ 0x83, 0xCA, 0x05, 0x6F, 0xCC, 0x9B, 0xCC, 0x89,
+ 0xCA, 0x05, 0x6F, 0xCC, 0x9B, 0xCC, 0xA3, 0xB6,
+ 0x05, 0x6F, 0xCC, 0xA3, 0xCC, 0x82, 0xCA, 0x05,
+ 0x6F, 0xCC, 0xA8, 0xCC, 0x84, 0xCA, 0x05, 0x72,
+ 0xCC, 0xA3, 0xCC, 0x84, 0xCA, 0x05, 0x73, 0xCC,
+ 0x81, 0xCC, 0x87, 0xCA, 0x05, 0x73, 0xCC, 0x8C,
+ 0xCC, 0x87, 0xCA, 0x05, 0x73, 0xCC, 0xA3, 0xCC,
+ // Bytes 3b40 - 3b7f
+ 0x87, 0xCA, 0x05, 0x75, 0xCC, 0x83, 0xCC, 0x81,
+ 0xCA, 0x05, 0x75, 0xCC, 0x84, 0xCC, 0x88, 0xCA,
+ 0x05, 0x75, 0xCC, 0x88, 0xCC, 0x80, 0xCA, 0x05,
+ 0x75, 0xCC, 0x88, 0xCC, 0x81, 0xCA, 0x05, 0x75,
+ 0xCC, 0x88, 0xCC, 0x84, 0xCA, 0x05, 0x75, 0xCC,
+ 0x88, 0xCC, 0x8C, 0xCA, 0x05, 0x75, 0xCC, 0x9B,
+ 0xCC, 0x80, 0xCA, 0x05, 0x75, 0xCC, 0x9B, 0xCC,
+ 0x81, 0xCA, 0x05, 0x75, 0xCC, 0x9B, 0xCC, 0x83,
+ // Bytes 3b80 - 3bbf
+ 0xCA, 0x05, 0x75, 0xCC, 0x9B, 0xCC, 0x89, 0xCA,
+ 0x05, 0x75, 0xCC, 0x9B, 0xCC, 0xA3, 0xB6, 0x05,
+ 0xE1, 0xBE, 0xBF, 0xCC, 0x80, 0xCA, 0x05, 0xE1,
+ 0xBE, 0xBF, 0xCC, 0x81, 0xCA, 0x05, 0xE1, 0xBE,
+ 0xBF, 0xCD, 0x82, 0xCA, 0x05, 0xE1, 0xBF, 0xBE,
+ 0xCC, 0x80, 0xCA, 0x05, 0xE1, 0xBF, 0xBE, 0xCC,
+ 0x81, 0xCA, 0x05, 0xE1, 0xBF, 0xBE, 0xCD, 0x82,
+ 0xCA, 0x05, 0xE2, 0x86, 0x90, 0xCC, 0xB8, 0x05,
+ // Bytes 3bc0 - 3bff
+ 0x05, 0xE2, 0x86, 0x92, 0xCC, 0xB8, 0x05, 0x05,
+ 0xE2, 0x86, 0x94, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+ 0x87, 0x90, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x87,
+ 0x92, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x87, 0x94,
+ 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x88, 0x83, 0xCC,
+ 0xB8, 0x05, 0x05, 0xE2, 0x88, 0x88, 0xCC, 0xB8,
+ 0x05, 0x05, 0xE2, 0x88, 0x8B, 0xCC, 0xB8, 0x05,
+ 0x05, 0xE2, 0x88, 0xA3, 0xCC, 0xB8, 0x05, 0x05,
+ // Bytes 3c00 - 3c3f
+ 0xE2, 0x88, 0xA5, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+ 0x88, 0xBC, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89,
+ 0x83, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89, 0x85,
+ 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89, 0x88, 0xCC,
+ 0xB8, 0x05, 0x05, 0xE2, 0x89, 0x8D, 0xCC, 0xB8,
+ 0x05, 0x05, 0xE2, 0x89, 0xA1, 0xCC, 0xB8, 0x05,
+ 0x05, 0xE2, 0x89, 0xA4, 0xCC, 0xB8, 0x05, 0x05,
+ 0xE2, 0x89, 0xA5, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+ // Bytes 3c40 - 3c7f
+ 0x89, 0xB2, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89,
+ 0xB3, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89, 0xB6,
+ 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89, 0xB7, 0xCC,
+ 0xB8, 0x05, 0x05, 0xE2, 0x89, 0xBA, 0xCC, 0xB8,
+ 0x05, 0x05, 0xE2, 0x89, 0xBB, 0xCC, 0xB8, 0x05,
+ 0x05, 0xE2, 0x89, 0xBC, 0xCC, 0xB8, 0x05, 0x05,
+ 0xE2, 0x89, 0xBD, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+ 0x8A, 0x82, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A,
+ // Bytes 3c80 - 3cbf
+ 0x83, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0x86,
+ 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0x87, 0xCC,
+ 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0x91, 0xCC, 0xB8,
+ 0x05, 0x05, 0xE2, 0x8A, 0x92, 0xCC, 0xB8, 0x05,
+ 0x05, 0xE2, 0x8A, 0xA2, 0xCC, 0xB8, 0x05, 0x05,
+ 0xE2, 0x8A, 0xA8, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+ 0x8A, 0xA9, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A,
+ 0xAB, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0xB2,
+ // Bytes 3cc0 - 3cff
+ 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0xB3, 0xCC,
+ 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0xB4, 0xCC, 0xB8,
+ 0x05, 0x05, 0xE2, 0x8A, 0xB5, 0xCC, 0xB8, 0x05,
+ 0x06, 0xCE, 0x91, 0xCC, 0x93, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0x91, 0xCC, 0x94, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0x95, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0x95, 0xCC, 0x93, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0x95, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ // Bytes 3d00 - 3d3f
+ 0x06, 0xCE, 0x95, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0x97, 0xCC, 0x93, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0x97, 0xCC, 0x94, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0x99, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0x99, 0xCC, 0x93, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0x99, 0xCC, 0x93, 0xCD, 0x82, 0xCA,
+ 0x06, 0xCE, 0x99, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0x99, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ // Bytes 3d40 - 3d7f
+ 0x06, 0xCE, 0x99, 0xCC, 0x94, 0xCD, 0x82, 0xCA,
+ 0x06, 0xCE, 0x9F, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0x9F, 0xCC, 0x93, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0x9F, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0x9F, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0xA5, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0xA5, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0xA5, 0xCC, 0x94, 0xCD, 0x82, 0xCA,
+ // Bytes 3d80 - 3dbf
+ 0x06, 0xCE, 0xA9, 0xCC, 0x93, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xA9, 0xCC, 0x94, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB1, 0xCC, 0x80, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB1, 0xCC, 0x81, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB1, 0xCC, 0x93, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB1, 0xCC, 0x94, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB1, 0xCD, 0x82, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB5, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ // Bytes 3dc0 - 3dff
+ 0x06, 0xCE, 0xB5, 0xCC, 0x93, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0xB5, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0xB5, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0xB7, 0xCC, 0x80, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB7, 0xCC, 0x81, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB7, 0xCC, 0x93, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB7, 0xCC, 0x94, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB7, 0xCD, 0x82, 0xCD, 0x85, 0xDA,
+ // Bytes 3e00 - 3e3f
+ 0x06, 0xCE, 0xB9, 0xCC, 0x88, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0xB9, 0xCC, 0x88, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0xB9, 0xCC, 0x88, 0xCD, 0x82, 0xCA,
+ 0x06, 0xCE, 0xB9, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0xB9, 0xCC, 0x93, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0xB9, 0xCC, 0x93, 0xCD, 0x82, 0xCA,
+ 0x06, 0xCE, 0xB9, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0xB9, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ // Bytes 3e40 - 3e7f
+ 0x06, 0xCE, 0xB9, 0xCC, 0x94, 0xCD, 0x82, 0xCA,
+ 0x06, 0xCE, 0xBF, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0xBF, 0xCC, 0x93, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0xBF, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0xBF, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x88, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x88, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x88, 0xCD, 0x82, 0xCA,
+ // Bytes 3e80 - 3ebf
+ 0x06, 0xCF, 0x85, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x93, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x93, 0xCD, 0x82, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x94, 0xCD, 0x82, 0xCA,
+ 0x06, 0xCF, 0x89, 0xCC, 0x80, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCF, 0x89, 0xCC, 0x81, 0xCD, 0x85, 0xDA,
+ // Bytes 3ec0 - 3eff
+ 0x06, 0xCF, 0x89, 0xCC, 0x93, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCF, 0x89, 0xCC, 0x94, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCF, 0x89, 0xCD, 0x82, 0xCD, 0x85, 0xDA,
+ 0x06, 0xE0, 0xA4, 0xA8, 0xE0, 0xA4, 0xBC, 0x09,
+ 0x06, 0xE0, 0xA4, 0xB0, 0xE0, 0xA4, 0xBC, 0x09,
+ 0x06, 0xE0, 0xA4, 0xB3, 0xE0, 0xA4, 0xBC, 0x09,
+ 0x06, 0xE0, 0xB1, 0x86, 0xE0, 0xB1, 0x96, 0x85,
+ 0x06, 0xE0, 0xB7, 0x99, 0xE0, 0xB7, 0x8A, 0x11,
+ // Bytes 3f00 - 3f3f
+ 0x06, 0xE3, 0x81, 0x86, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x8B, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x8D, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x8F, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x91, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x93, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x95, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x97, 0xE3, 0x82, 0x99, 0x0D,
+ // Bytes 3f40 - 3f7f
+ 0x06, 0xE3, 0x81, 0x99, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x9B, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x9D, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x9F, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xA1, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xA4, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xA6, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xA8, 0xE3, 0x82, 0x99, 0x0D,
+ // Bytes 3f80 - 3fbf
+ 0x06, 0xE3, 0x81, 0xAF, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xAF, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x81, 0xB2, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xB2, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x81, 0xB5, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xB5, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x81, 0xB8, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xB8, 0xE3, 0x82, 0x9A, 0x0D,
+ // Bytes 3fc0 - 3fff
+ 0x06, 0xE3, 0x81, 0xBB, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xBB, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x82, 0x9D, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xA6, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xAD, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xB1, 0xE3, 0x82, 0x99, 0x0D,
+ // Bytes 4000 - 403f
+ 0x06, 0xE3, 0x82, 0xB3, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xB5, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xB7, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xB9, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xBB, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xBD, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xBF, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x81, 0xE3, 0x82, 0x99, 0x0D,
+ // Bytes 4040 - 407f
+ 0x06, 0xE3, 0x83, 0x84, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x86, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x88, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x8F, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x8F, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x83, 0x95, 0xE3, 0x82, 0x99, 0x0D,
+ // Bytes 4080 - 40bf
+ 0x06, 0xE3, 0x83, 0x95, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x83, 0x98, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x98, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x83, 0x9B, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x9B, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x83, 0xAF, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0xB0, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0xB1, 0xE3, 0x82, 0x99, 0x0D,
+ // Bytes 40c0 - 40ff
+ 0x06, 0xE3, 0x83, 0xB2, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0xBD, 0xE3, 0x82, 0x99, 0x0D,
+ 0x08, 0xCE, 0x91, 0xCC, 0x93, 0xCC, 0x80, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCE, 0x91, 0xCC, 0x93, 0xCC,
+ 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0x91, 0xCC,
+ 0x93, 0xCD, 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCE,
+ 0x91, 0xCC, 0x94, 0xCC, 0x80, 0xCD, 0x85, 0xDB,
+ 0x08, 0xCE, 0x91, 0xCC, 0x94, 0xCC, 0x81, 0xCD,
+ // Bytes 4100 - 413f
+ 0x85, 0xDB, 0x08, 0xCE, 0x91, 0xCC, 0x94, 0xCD,
+ 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0x97, 0xCC,
+ 0x93, 0xCC, 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCE,
+ 0x97, 0xCC, 0x93, 0xCC, 0x81, 0xCD, 0x85, 0xDB,
+ 0x08, 0xCE, 0x97, 0xCC, 0x93, 0xCD, 0x82, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCE, 0x97, 0xCC, 0x94, 0xCC,
+ 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0x97, 0xCC,
+ 0x94, 0xCC, 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCE,
+ // Bytes 4140 - 417f
+ 0x97, 0xCC, 0x94, 0xCD, 0x82, 0xCD, 0x85, 0xDB,
+ 0x08, 0xCE, 0xA9, 0xCC, 0x93, 0xCC, 0x80, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCE, 0xA9, 0xCC, 0x93, 0xCC,
+ 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xA9, 0xCC,
+ 0x93, 0xCD, 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCE,
+ 0xA9, 0xCC, 0x94, 0xCC, 0x80, 0xCD, 0x85, 0xDB,
+ 0x08, 0xCE, 0xA9, 0xCC, 0x94, 0xCC, 0x81, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCE, 0xA9, 0xCC, 0x94, 0xCD,
+ // Bytes 4180 - 41bf
+ 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xB1, 0xCC,
+ 0x93, 0xCC, 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCE,
+ 0xB1, 0xCC, 0x93, 0xCC, 0x81, 0xCD, 0x85, 0xDB,
+ 0x08, 0xCE, 0xB1, 0xCC, 0x93, 0xCD, 0x82, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCE, 0xB1, 0xCC, 0x94, 0xCC,
+ 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xB1, 0xCC,
+ 0x94, 0xCC, 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCE,
+ 0xB1, 0xCC, 0x94, 0xCD, 0x82, 0xCD, 0x85, 0xDB,
+ // Bytes 41c0 - 41ff
+ 0x08, 0xCE, 0xB7, 0xCC, 0x93, 0xCC, 0x80, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCE, 0xB7, 0xCC, 0x93, 0xCC,
+ 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xB7, 0xCC,
+ 0x93, 0xCD, 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCE,
+ 0xB7, 0xCC, 0x94, 0xCC, 0x80, 0xCD, 0x85, 0xDB,
+ 0x08, 0xCE, 0xB7, 0xCC, 0x94, 0xCC, 0x81, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCE, 0xB7, 0xCC, 0x94, 0xCD,
+ 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCF, 0x89, 0xCC,
+ // Bytes 4200 - 423f
+ 0x93, 0xCC, 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCF,
+ 0x89, 0xCC, 0x93, 0xCC, 0x81, 0xCD, 0x85, 0xDB,
+ 0x08, 0xCF, 0x89, 0xCC, 0x93, 0xCD, 0x82, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCF, 0x89, 0xCC, 0x94, 0xCC,
+ 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCF, 0x89, 0xCC,
+ 0x94, 0xCC, 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCF,
+ 0x89, 0xCC, 0x94, 0xCD, 0x82, 0xCD, 0x85, 0xDB,
+ 0x08, 0xF0, 0x91, 0x82, 0x99, 0xF0, 0x91, 0x82,
+ // Bytes 4240 - 427f
+ 0xBA, 0x09, 0x08, 0xF0, 0x91, 0x82, 0x9B, 0xF0,
+ 0x91, 0x82, 0xBA, 0x09, 0x08, 0xF0, 0x91, 0x82,
+ 0xA5, 0xF0, 0x91, 0x82, 0xBA, 0x09, 0x42, 0xC2,
+ 0xB4, 0x01, 0x43, 0x20, 0xCC, 0x81, 0xC9, 0x43,
+ 0x20, 0xCC, 0x83, 0xC9, 0x43, 0x20, 0xCC, 0x84,
+ 0xC9, 0x43, 0x20, 0xCC, 0x85, 0xC9, 0x43, 0x20,
+ 0xCC, 0x86, 0xC9, 0x43, 0x20, 0xCC, 0x87, 0xC9,
+ 0x43, 0x20, 0xCC, 0x88, 0xC9, 0x43, 0x20, 0xCC,
+ // Bytes 4280 - 42bf
+ 0x8A, 0xC9, 0x43, 0x20, 0xCC, 0x8B, 0xC9, 0x43,
+ 0x20, 0xCC, 0x93, 0xC9, 0x43, 0x20, 0xCC, 0x94,
+ 0xC9, 0x43, 0x20, 0xCC, 0xA7, 0xA5, 0x43, 0x20,
+ 0xCC, 0xA8, 0xA5, 0x43, 0x20, 0xCC, 0xB3, 0xB5,
+ 0x43, 0x20, 0xCD, 0x82, 0xC9, 0x43, 0x20, 0xCD,
+ 0x85, 0xD9, 0x43, 0x20, 0xD9, 0x8B, 0x59, 0x43,
+ 0x20, 0xD9, 0x8C, 0x5D, 0x43, 0x20, 0xD9, 0x8D,
+ 0x61, 0x43, 0x20, 0xD9, 0x8E, 0x65, 0x43, 0x20,
+ // Bytes 42c0 - 42ff
+ 0xD9, 0x8F, 0x69, 0x43, 0x20, 0xD9, 0x90, 0x6D,
+ 0x43, 0x20, 0xD9, 0x91, 0x71, 0x43, 0x20, 0xD9,
+ 0x92, 0x75, 0x43, 0x41, 0xCC, 0x8A, 0xC9, 0x43,
+ 0x73, 0xCC, 0x87, 0xC9, 0x44, 0x20, 0xE3, 0x82,
+ 0x99, 0x0D, 0x44, 0x20, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x44, 0xC2, 0xA8, 0xCC, 0x81, 0xCA, 0x44, 0xCE,
+ 0x91, 0xCC, 0x81, 0xC9, 0x44, 0xCE, 0x95, 0xCC,
+ 0x81, 0xC9, 0x44, 0xCE, 0x97, 0xCC, 0x81, 0xC9,
+ // Bytes 4300 - 433f
+ 0x44, 0xCE, 0x99, 0xCC, 0x81, 0xC9, 0x44, 0xCE,
+ 0x9F, 0xCC, 0x81, 0xC9, 0x44, 0xCE, 0xA5, 0xCC,
+ 0x81, 0xC9, 0x44, 0xCE, 0xA5, 0xCC, 0x88, 0xC9,
+ 0x44, 0xCE, 0xA9, 0xCC, 0x81, 0xC9, 0x44, 0xCE,
+ 0xB1, 0xCC, 0x81, 0xC9, 0x44, 0xCE, 0xB5, 0xCC,
+ 0x81, 0xC9, 0x44, 0xCE, 0xB7, 0xCC, 0x81, 0xC9,
+ 0x44, 0xCE, 0xB9, 0xCC, 0x81, 0xC9, 0x44, 0xCE,
+ 0xBF, 0xCC, 0x81, 0xC9, 0x44, 0xCF, 0x85, 0xCC,
+ // Bytes 4340 - 437f
+ 0x81, 0xC9, 0x44, 0xCF, 0x89, 0xCC, 0x81, 0xC9,
+ 0x44, 0xD7, 0x90, 0xD6, 0xB7, 0x31, 0x44, 0xD7,
+ 0x90, 0xD6, 0xB8, 0x35, 0x44, 0xD7, 0x90, 0xD6,
+ 0xBC, 0x41, 0x44, 0xD7, 0x91, 0xD6, 0xBC, 0x41,
+ 0x44, 0xD7, 0x91, 0xD6, 0xBF, 0x49, 0x44, 0xD7,
+ 0x92, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0x93, 0xD6,
+ 0xBC, 0x41, 0x44, 0xD7, 0x94, 0xD6, 0xBC, 0x41,
+ 0x44, 0xD7, 0x95, 0xD6, 0xB9, 0x39, 0x44, 0xD7,
+ // Bytes 4380 - 43bf
+ 0x95, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0x96, 0xD6,
+ 0xBC, 0x41, 0x44, 0xD7, 0x98, 0xD6, 0xBC, 0x41,
+ 0x44, 0xD7, 0x99, 0xD6, 0xB4, 0x25, 0x44, 0xD7,
+ 0x99, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0x9A, 0xD6,
+ 0xBC, 0x41, 0x44, 0xD7, 0x9B, 0xD6, 0xBC, 0x41,
+ 0x44, 0xD7, 0x9B, 0xD6, 0xBF, 0x49, 0x44, 0xD7,
+ 0x9C, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0x9E, 0xD6,
+ 0xBC, 0x41, 0x44, 0xD7, 0xA0, 0xD6, 0xBC, 0x41,
+ // Bytes 43c0 - 43ff
+ 0x44, 0xD7, 0xA1, 0xD6, 0xBC, 0x41, 0x44, 0xD7,
+ 0xA3, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0xA4, 0xD6,
+ 0xBC, 0x41, 0x44, 0xD7, 0xA4, 0xD6, 0xBF, 0x49,
+ 0x44, 0xD7, 0xA6, 0xD6, 0xBC, 0x41, 0x44, 0xD7,
+ 0xA7, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0xA8, 0xD6,
+ 0xBC, 0x41, 0x44, 0xD7, 0xA9, 0xD6, 0xBC, 0x41,
+ 0x44, 0xD7, 0xA9, 0xD7, 0x81, 0x4D, 0x44, 0xD7,
+ 0xA9, 0xD7, 0x82, 0x51, 0x44, 0xD7, 0xAA, 0xD6,
+ // Bytes 4400 - 443f
+ 0xBC, 0x41, 0x44, 0xD7, 0xB2, 0xD6, 0xB7, 0x31,
+ 0x44, 0xD8, 0xA7, 0xD9, 0x8B, 0x59, 0x44, 0xD8,
+ 0xA7, 0xD9, 0x93, 0xC9, 0x44, 0xD8, 0xA7, 0xD9,
+ 0x94, 0xC9, 0x44, 0xD8, 0xA7, 0xD9, 0x95, 0xB5,
+ 0x44, 0xD8, 0xB0, 0xD9, 0xB0, 0x79, 0x44, 0xD8,
+ 0xB1, 0xD9, 0xB0, 0x79, 0x44, 0xD9, 0x80, 0xD9,
+ 0x8B, 0x59, 0x44, 0xD9, 0x80, 0xD9, 0x8E, 0x65,
+ 0x44, 0xD9, 0x80, 0xD9, 0x8F, 0x69, 0x44, 0xD9,
+ // Bytes 4440 - 447f
+ 0x80, 0xD9, 0x90, 0x6D, 0x44, 0xD9, 0x80, 0xD9,
+ 0x91, 0x71, 0x44, 0xD9, 0x80, 0xD9, 0x92, 0x75,
+ 0x44, 0xD9, 0x87, 0xD9, 0xB0, 0x79, 0x44, 0xD9,
+ 0x88, 0xD9, 0x94, 0xC9, 0x44, 0xD9, 0x89, 0xD9,
+ 0xB0, 0x79, 0x44, 0xD9, 0x8A, 0xD9, 0x94, 0xC9,
+ 0x44, 0xDB, 0x92, 0xD9, 0x94, 0xC9, 0x44, 0xDB,
+ 0x95, 0xD9, 0x94, 0xC9, 0x45, 0x20, 0xCC, 0x88,
+ 0xCC, 0x80, 0xCA, 0x45, 0x20, 0xCC, 0x88, 0xCC,
+ // Bytes 4480 - 44bf
+ 0x81, 0xCA, 0x45, 0x20, 0xCC, 0x88, 0xCD, 0x82,
+ 0xCA, 0x45, 0x20, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ 0x45, 0x20, 0xCC, 0x93, 0xCC, 0x81, 0xCA, 0x45,
+ 0x20, 0xCC, 0x93, 0xCD, 0x82, 0xCA, 0x45, 0x20,
+ 0xCC, 0x94, 0xCC, 0x80, 0xCA, 0x45, 0x20, 0xCC,
+ 0x94, 0xCC, 0x81, 0xCA, 0x45, 0x20, 0xCC, 0x94,
+ 0xCD, 0x82, 0xCA, 0x45, 0x20, 0xD9, 0x8C, 0xD9,
+ 0x91, 0x72, 0x45, 0x20, 0xD9, 0x8D, 0xD9, 0x91,
+ // Bytes 44c0 - 44ff
+ 0x72, 0x45, 0x20, 0xD9, 0x8E, 0xD9, 0x91, 0x72,
+ 0x45, 0x20, 0xD9, 0x8F, 0xD9, 0x91, 0x72, 0x45,
+ 0x20, 0xD9, 0x90, 0xD9, 0x91, 0x72, 0x45, 0x20,
+ 0xD9, 0x91, 0xD9, 0xB0, 0x7A, 0x45, 0xE2, 0xAB,
+ 0x9D, 0xCC, 0xB8, 0x05, 0x46, 0xCE, 0xB9, 0xCC,
+ 0x88, 0xCC, 0x81, 0xCA, 0x46, 0xCF, 0x85, 0xCC,
+ 0x88, 0xCC, 0x81, 0xCA, 0x46, 0xD7, 0xA9, 0xD6,
+ 0xBC, 0xD7, 0x81, 0x4E, 0x46, 0xD7, 0xA9, 0xD6,
+ // Bytes 4500 - 453f
+ 0xBC, 0xD7, 0x82, 0x52, 0x46, 0xD9, 0x80, 0xD9,
+ 0x8E, 0xD9, 0x91, 0x72, 0x46, 0xD9, 0x80, 0xD9,
+ 0x8F, 0xD9, 0x91, 0x72, 0x46, 0xD9, 0x80, 0xD9,
+ 0x90, 0xD9, 0x91, 0x72, 0x46, 0xE0, 0xA4, 0x95,
+ 0xE0, 0xA4, 0xBC, 0x09, 0x46, 0xE0, 0xA4, 0x96,
+ 0xE0, 0xA4, 0xBC, 0x09, 0x46, 0xE0, 0xA4, 0x97,
+ 0xE0, 0xA4, 0xBC, 0x09, 0x46, 0xE0, 0xA4, 0x9C,
+ 0xE0, 0xA4, 0xBC, 0x09, 0x46, 0xE0, 0xA4, 0xA1,
+ // Bytes 4540 - 457f
+ 0xE0, 0xA4, 0xBC, 0x09, 0x46, 0xE0, 0xA4, 0xA2,
+ 0xE0, 0xA4, 0xBC, 0x09, 0x46, 0xE0, 0xA4, 0xAB,
+ 0xE0, 0xA4, 0xBC, 0x09, 0x46, 0xE0, 0xA4, 0xAF,
+ 0xE0, 0xA4, 0xBC, 0x09, 0x46, 0xE0, 0xA6, 0xA1,
+ 0xE0, 0xA6, 0xBC, 0x09, 0x46, 0xE0, 0xA6, 0xA2,
+ 0xE0, 0xA6, 0xBC, 0x09, 0x46, 0xE0, 0xA6, 0xAF,
+ 0xE0, 0xA6, 0xBC, 0x09, 0x46, 0xE0, 0xA8, 0x96,
+ 0xE0, 0xA8, 0xBC, 0x09, 0x46, 0xE0, 0xA8, 0x97,
+ // Bytes 4580 - 45bf
+ 0xE0, 0xA8, 0xBC, 0x09, 0x46, 0xE0, 0xA8, 0x9C,
+ 0xE0, 0xA8, 0xBC, 0x09, 0x46, 0xE0, 0xA8, 0xAB,
+ 0xE0, 0xA8, 0xBC, 0x09, 0x46, 0xE0, 0xA8, 0xB2,
+ 0xE0, 0xA8, 0xBC, 0x09, 0x46, 0xE0, 0xA8, 0xB8,
+ 0xE0, 0xA8, 0xBC, 0x09, 0x46, 0xE0, 0xAC, 0xA1,
+ 0xE0, 0xAC, 0xBC, 0x09, 0x46, 0xE0, 0xAC, 0xA2,
+ 0xE0, 0xAC, 0xBC, 0x09, 0x46, 0xE0, 0xBE, 0xB2,
+ 0xE0, 0xBE, 0x80, 0x9D, 0x46, 0xE0, 0xBE, 0xB3,
+ // Bytes 45c0 - 45ff
+ 0xE0, 0xBE, 0x80, 0x9D, 0x46, 0xE3, 0x83, 0x86,
+ 0xE3, 0x82, 0x99, 0x0D, 0x48, 0xF0, 0x9D, 0x85,
+ 0x97, 0xF0, 0x9D, 0x85, 0xA5, 0xAD, 0x48, 0xF0,
+ 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xAD,
+ 0x48, 0xF0, 0x9D, 0x86, 0xB9, 0xF0, 0x9D, 0x85,
+ 0xA5, 0xAD, 0x48, 0xF0, 0x9D, 0x86, 0xBA, 0xF0,
+ 0x9D, 0x85, 0xA5, 0xAD, 0x49, 0xE0, 0xBE, 0xB2,
+ 0xE0, 0xBD, 0xB1, 0xE0, 0xBE, 0x80, 0x9E, 0x49,
+ // Bytes 4600 - 463f
+ 0xE0, 0xBE, 0xB3, 0xE0, 0xBD, 0xB1, 0xE0, 0xBE,
+ 0x80, 0x9E, 0x4C, 0xF0, 0x9D, 0x85, 0x98, 0xF0,
+ 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xAE, 0xAE,
+ 0x4C, 0xF0, 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85,
+ 0xA5, 0xF0, 0x9D, 0x85, 0xAF, 0xAE, 0x4C, 0xF0,
+ 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xF0,
+ 0x9D, 0x85, 0xB0, 0xAE, 0x4C, 0xF0, 0x9D, 0x85,
+ 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85,
+ // Bytes 4640 - 467f
+ 0xB1, 0xAE, 0x4C, 0xF0, 0x9D, 0x85, 0x98, 0xF0,
+ 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xB2, 0xAE,
+ 0x4C, 0xF0, 0x9D, 0x86, 0xB9, 0xF0, 0x9D, 0x85,
+ 0xA5, 0xF0, 0x9D, 0x85, 0xAE, 0xAE, 0x4C, 0xF0,
+ 0x9D, 0x86, 0xB9, 0xF0, 0x9D, 0x85, 0xA5, 0xF0,
+ 0x9D, 0x85, 0xAF, 0xAE, 0x4C, 0xF0, 0x9D, 0x86,
+ 0xBA, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85,
+ 0xAE, 0xAE, 0x4C, 0xF0, 0x9D, 0x86, 0xBA, 0xF0,
+ // Bytes 4680 - 46bf
+ 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xAF, 0xAE,
+ 0x83, 0x41, 0xCC, 0x82, 0xC9, 0x83, 0x41, 0xCC,
+ 0x86, 0xC9, 0x83, 0x41, 0xCC, 0x87, 0xC9, 0x83,
+ 0x41, 0xCC, 0x88, 0xC9, 0x83, 0x41, 0xCC, 0x8A,
+ 0xC9, 0x83, 0x41, 0xCC, 0xA3, 0xB5, 0x83, 0x43,
+ 0xCC, 0xA7, 0xA5, 0x83, 0x45, 0xCC, 0x82, 0xC9,
+ 0x83, 0x45, 0xCC, 0x84, 0xC9, 0x83, 0x45, 0xCC,
+ 0xA3, 0xB5, 0x83, 0x45, 0xCC, 0xA7, 0xA5, 0x83,
+ // Bytes 46c0 - 46ff
+ 0x49, 0xCC, 0x88, 0xC9, 0x83, 0x4C, 0xCC, 0xA3,
+ 0xB5, 0x83, 0x4F, 0xCC, 0x82, 0xC9, 0x83, 0x4F,
+ 0xCC, 0x83, 0xC9, 0x83, 0x4F, 0xCC, 0x84, 0xC9,
+ 0x83, 0x4F, 0xCC, 0x87, 0xC9, 0x83, 0x4F, 0xCC,
+ 0x88, 0xC9, 0x83, 0x4F, 0xCC, 0x9B, 0xAD, 0x83,
+ 0x4F, 0xCC, 0xA3, 0xB5, 0x83, 0x4F, 0xCC, 0xA8,
+ 0xA5, 0x83, 0x52, 0xCC, 0xA3, 0xB5, 0x83, 0x53,
+ 0xCC, 0x81, 0xC9, 0x83, 0x53, 0xCC, 0x8C, 0xC9,
+ // Bytes 4700 - 473f
+ 0x83, 0x53, 0xCC, 0xA3, 0xB5, 0x83, 0x55, 0xCC,
+ 0x83, 0xC9, 0x83, 0x55, 0xCC, 0x84, 0xC9, 0x83,
+ 0x55, 0xCC, 0x88, 0xC9, 0x83, 0x55, 0xCC, 0x9B,
+ 0xAD, 0x83, 0x61, 0xCC, 0x82, 0xC9, 0x83, 0x61,
+ 0xCC, 0x86, 0xC9, 0x83, 0x61, 0xCC, 0x87, 0xC9,
+ 0x83, 0x61, 0xCC, 0x88, 0xC9, 0x83, 0x61, 0xCC,
+ 0x8A, 0xC9, 0x83, 0x61, 0xCC, 0xA3, 0xB5, 0x83,
+ 0x63, 0xCC, 0xA7, 0xA5, 0x83, 0x65, 0xCC, 0x82,
+ // Bytes 4740 - 477f
+ 0xC9, 0x83, 0x65, 0xCC, 0x84, 0xC9, 0x83, 0x65,
+ 0xCC, 0xA3, 0xB5, 0x83, 0x65, 0xCC, 0xA7, 0xA5,
+ 0x83, 0x69, 0xCC, 0x88, 0xC9, 0x83, 0x6C, 0xCC,
+ 0xA3, 0xB5, 0x83, 0x6F, 0xCC, 0x82, 0xC9, 0x83,
+ 0x6F, 0xCC, 0x83, 0xC9, 0x83, 0x6F, 0xCC, 0x84,
+ 0xC9, 0x83, 0x6F, 0xCC, 0x87, 0xC9, 0x83, 0x6F,
+ 0xCC, 0x88, 0xC9, 0x83, 0x6F, 0xCC, 0x9B, 0xAD,
+ 0x83, 0x6F, 0xCC, 0xA3, 0xB5, 0x83, 0x6F, 0xCC,
+ // Bytes 4780 - 47bf
+ 0xA8, 0xA5, 0x83, 0x72, 0xCC, 0xA3, 0xB5, 0x83,
+ 0x73, 0xCC, 0x81, 0xC9, 0x83, 0x73, 0xCC, 0x8C,
+ 0xC9, 0x83, 0x73, 0xCC, 0xA3, 0xB5, 0x83, 0x75,
+ 0xCC, 0x83, 0xC9, 0x83, 0x75, 0xCC, 0x84, 0xC9,
+ 0x83, 0x75, 0xCC, 0x88, 0xC9, 0x83, 0x75, 0xCC,
+ 0x9B, 0xAD, 0x84, 0xCE, 0x91, 0xCC, 0x93, 0xC9,
+ 0x84, 0xCE, 0x91, 0xCC, 0x94, 0xC9, 0x84, 0xCE,
+ 0x95, 0xCC, 0x93, 0xC9, 0x84, 0xCE, 0x95, 0xCC,
+ // Bytes 47c0 - 47ff
+ 0x94, 0xC9, 0x84, 0xCE, 0x97, 0xCC, 0x93, 0xC9,
+ 0x84, 0xCE, 0x97, 0xCC, 0x94, 0xC9, 0x84, 0xCE,
+ 0x99, 0xCC, 0x93, 0xC9, 0x84, 0xCE, 0x99, 0xCC,
+ 0x94, 0xC9, 0x84, 0xCE, 0x9F, 0xCC, 0x93, 0xC9,
+ 0x84, 0xCE, 0x9F, 0xCC, 0x94, 0xC9, 0x84, 0xCE,
+ 0xA5, 0xCC, 0x94, 0xC9, 0x84, 0xCE, 0xA9, 0xCC,
+ 0x93, 0xC9, 0x84, 0xCE, 0xA9, 0xCC, 0x94, 0xC9,
+ 0x84, 0xCE, 0xB1, 0xCC, 0x80, 0xC9, 0x84, 0xCE,
+ // Bytes 4800 - 483f
+ 0xB1, 0xCC, 0x81, 0xC9, 0x84, 0xCE, 0xB1, 0xCC,
+ 0x93, 0xC9, 0x84, 0xCE, 0xB1, 0xCC, 0x94, 0xC9,
+ 0x84, 0xCE, 0xB1, 0xCD, 0x82, 0xC9, 0x84, 0xCE,
+ 0xB5, 0xCC, 0x93, 0xC9, 0x84, 0xCE, 0xB5, 0xCC,
+ 0x94, 0xC9, 0x84, 0xCE, 0xB7, 0xCC, 0x80, 0xC9,
+ 0x84, 0xCE, 0xB7, 0xCC, 0x81, 0xC9, 0x84, 0xCE,
+ 0xB7, 0xCC, 0x93, 0xC9, 0x84, 0xCE, 0xB7, 0xCC,
+ 0x94, 0xC9, 0x84, 0xCE, 0xB7, 0xCD, 0x82, 0xC9,
+ // Bytes 4840 - 487f
+ 0x84, 0xCE, 0xB9, 0xCC, 0x88, 0xC9, 0x84, 0xCE,
+ 0xB9, 0xCC, 0x93, 0xC9, 0x84, 0xCE, 0xB9, 0xCC,
+ 0x94, 0xC9, 0x84, 0xCE, 0xBF, 0xCC, 0x93, 0xC9,
+ 0x84, 0xCE, 0xBF, 0xCC, 0x94, 0xC9, 0x84, 0xCF,
+ 0x85, 0xCC, 0x88, 0xC9, 0x84, 0xCF, 0x85, 0xCC,
+ 0x93, 0xC9, 0x84, 0xCF, 0x85, 0xCC, 0x94, 0xC9,
+ 0x84, 0xCF, 0x89, 0xCC, 0x80, 0xC9, 0x84, 0xCF,
+ 0x89, 0xCC, 0x81, 0xC9, 0x84, 0xCF, 0x89, 0xCC,
+ // Bytes 4880 - 48bf
+ 0x93, 0xC9, 0x84, 0xCF, 0x89, 0xCC, 0x94, 0xC9,
+ 0x84, 0xCF, 0x89, 0xCD, 0x82, 0xC9, 0x86, 0xCE,
+ 0x91, 0xCC, 0x93, 0xCC, 0x80, 0xCA, 0x86, 0xCE,
+ 0x91, 0xCC, 0x93, 0xCC, 0x81, 0xCA, 0x86, 0xCE,
+ 0x91, 0xCC, 0x93, 0xCD, 0x82, 0xCA, 0x86, 0xCE,
+ 0x91, 0xCC, 0x94, 0xCC, 0x80, 0xCA, 0x86, 0xCE,
+ 0x91, 0xCC, 0x94, 0xCC, 0x81, 0xCA, 0x86, 0xCE,
+ 0x91, 0xCC, 0x94, 0xCD, 0x82, 0xCA, 0x86, 0xCE,
+ // Bytes 48c0 - 48ff
+ 0x97, 0xCC, 0x93, 0xCC, 0x80, 0xCA, 0x86, 0xCE,
+ 0x97, 0xCC, 0x93, 0xCC, 0x81, 0xCA, 0x86, 0xCE,
+ 0x97, 0xCC, 0x93, 0xCD, 0x82, 0xCA, 0x86, 0xCE,
+ 0x97, 0xCC, 0x94, 0xCC, 0x80, 0xCA, 0x86, 0xCE,
+ 0x97, 0xCC, 0x94, 0xCC, 0x81, 0xCA, 0x86, 0xCE,
+ 0x97, 0xCC, 0x94, 0xCD, 0x82, 0xCA, 0x86, 0xCE,
+ 0xA9, 0xCC, 0x93, 0xCC, 0x80, 0xCA, 0x86, 0xCE,
+ 0xA9, 0xCC, 0x93, 0xCC, 0x81, 0xCA, 0x86, 0xCE,
+ // Bytes 4900 - 493f
+ 0xA9, 0xCC, 0x93, 0xCD, 0x82, 0xCA, 0x86, 0xCE,
+ 0xA9, 0xCC, 0x94, 0xCC, 0x80, 0xCA, 0x86, 0xCE,
+ 0xA9, 0xCC, 0x94, 0xCC, 0x81, 0xCA, 0x86, 0xCE,
+ 0xA9, 0xCC, 0x94, 0xCD, 0x82, 0xCA, 0x86, 0xCE,
+ 0xB1, 0xCC, 0x93, 0xCC, 0x80, 0xCA, 0x86, 0xCE,
+ 0xB1, 0xCC, 0x93, 0xCC, 0x81, 0xCA, 0x86, 0xCE,
+ 0xB1, 0xCC, 0x93, 0xCD, 0x82, 0xCA, 0x86, 0xCE,
+ 0xB1, 0xCC, 0x94, 0xCC, 0x80, 0xCA, 0x86, 0xCE,
+ // Bytes 4940 - 497f
+ 0xB1, 0xCC, 0x94, 0xCC, 0x81, 0xCA, 0x86, 0xCE,
+ 0xB1, 0xCC, 0x94, 0xCD, 0x82, 0xCA, 0x86, 0xCE,
+ 0xB7, 0xCC, 0x93, 0xCC, 0x80, 0xCA, 0x86, 0xCE,
+ 0xB7, 0xCC, 0x93, 0xCC, 0x81, 0xCA, 0x86, 0xCE,
+ 0xB7, 0xCC, 0x93, 0xCD, 0x82, 0xCA, 0x86, 0xCE,
+ 0xB7, 0xCC, 0x94, 0xCC, 0x80, 0xCA, 0x86, 0xCE,
+ 0xB7, 0xCC, 0x94, 0xCC, 0x81, 0xCA, 0x86, 0xCE,
+ 0xB7, 0xCC, 0x94, 0xCD, 0x82, 0xCA, 0x86, 0xCF,
+ // Bytes 4980 - 49bf
+ 0x89, 0xCC, 0x93, 0xCC, 0x80, 0xCA, 0x86, 0xCF,
+ 0x89, 0xCC, 0x93, 0xCC, 0x81, 0xCA, 0x86, 0xCF,
+ 0x89, 0xCC, 0x93, 0xCD, 0x82, 0xCA, 0x86, 0xCF,
+ 0x89, 0xCC, 0x94, 0xCC, 0x80, 0xCA, 0x86, 0xCF,
+ 0x89, 0xCC, 0x94, 0xCC, 0x81, 0xCA, 0x86, 0xCF,
+ 0x89, 0xCC, 0x94, 0xCD, 0x82, 0xCA, 0x42, 0xCC,
+ 0x80, 0xC9, 0x32, 0x42, 0xCC, 0x81, 0xC9, 0x32,
+ 0x42, 0xCC, 0x93, 0xC9, 0x32, 0x43, 0xE1, 0x85,
+ // Bytes 49c0 - 49ff
+ 0xA1, 0x01, 0x00, 0x43, 0xE1, 0x85, 0xA2, 0x01,
+ 0x00, 0x43, 0xE1, 0x85, 0xA3, 0x01, 0x00, 0x43,
+ 0xE1, 0x85, 0xA4, 0x01, 0x00, 0x43, 0xE1, 0x85,
+ 0xA5, 0x01, 0x00, 0x43, 0xE1, 0x85, 0xA6, 0x01,
+ 0x00, 0x43, 0xE1, 0x85, 0xA7, 0x01, 0x00, 0x43,
+ 0xE1, 0x85, 0xA8, 0x01, 0x00, 0x43, 0xE1, 0x85,
+ 0xA9, 0x01, 0x00, 0x43, 0xE1, 0x85, 0xAA, 0x01,
+ 0x00, 0x43, 0xE1, 0x85, 0xAB, 0x01, 0x00, 0x43,
+ // Bytes 4a00 - 4a3f
+ 0xE1, 0x85, 0xAC, 0x01, 0x00, 0x43, 0xE1, 0x85,
+ 0xAD, 0x01, 0x00, 0x43, 0xE1, 0x85, 0xAE, 0x01,
+ 0x00, 0x43, 0xE1, 0x85, 0xAF, 0x01, 0x00, 0x43,
+ 0xE1, 0x85, 0xB0, 0x01, 0x00, 0x43, 0xE1, 0x85,
+ 0xB1, 0x01, 0x00, 0x43, 0xE1, 0x85, 0xB2, 0x01,
+ 0x00, 0x43, 0xE1, 0x85, 0xB3, 0x01, 0x00, 0x43,
+ 0xE1, 0x85, 0xB4, 0x01, 0x00, 0x43, 0xE1, 0x85,
+ 0xB5, 0x01, 0x00, 0x43, 0xE1, 0x86, 0xAA, 0x01,
+ // Bytes 4a40 - 4a7f
+ 0x00, 0x43, 0xE1, 0x86, 0xAC, 0x01, 0x00, 0x43,
+ 0xE1, 0x86, 0xAD, 0x01, 0x00, 0x43, 0xE1, 0x86,
+ 0xB0, 0x01, 0x00, 0x43, 0xE1, 0x86, 0xB1, 0x01,
+ 0x00, 0x43, 0xE1, 0x86, 0xB2, 0x01, 0x00, 0x43,
+ 0xE1, 0x86, 0xB3, 0x01, 0x00, 0x43, 0xE1, 0x86,
+ 0xB4, 0x01, 0x00, 0x43, 0xE1, 0x86, 0xB5, 0x01,
+ 0x00, 0x44, 0xCC, 0x88, 0xCC, 0x81, 0xCA, 0x32,
+ 0x43, 0xE3, 0x82, 0x99, 0x0D, 0x03, 0x43, 0xE3,
+ // Bytes 4a80 - 4abf
+ 0x82, 0x9A, 0x0D, 0x03, 0x46, 0xE0, 0xBD, 0xB1,
+ 0xE0, 0xBD, 0xB2, 0x9E, 0x26, 0x46, 0xE0, 0xBD,
+ 0xB1, 0xE0, 0xBD, 0xB4, 0xA2, 0x26, 0x46, 0xE0,
+ 0xBD, 0xB1, 0xE0, 0xBE, 0x80, 0x9E, 0x26, 0x00,
+ 0x01,
+}
+
+// lookup returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *nfcTrie) lookup(s []byte) (v uint16, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return nfcValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := nfcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := nfcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := nfcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = nfcIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *nfcTrie) lookupUnsafe(s []byte) uint16 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return nfcValues[c0]
+ }
+ i := nfcIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = nfcIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = nfcIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// lookupString returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *nfcTrie) lookupString(s string) (v uint16, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return nfcValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := nfcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := nfcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := nfcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = nfcIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *nfcTrie) lookupStringUnsafe(s string) uint16 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return nfcValues[c0]
+ }
+ i := nfcIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = nfcIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = nfcIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// nfcTrie. Total size: 10332 bytes (10.09 KiB). Checksum: 51cc525b297fc970.
+type nfcTrie struct{}
+
+func newNfcTrie(i int) *nfcTrie {
+ return &nfcTrie{}
+}
+
+// lookupValue determines the type of block n and looks up the value for b.
+func (t *nfcTrie) lookupValue(n uint32, b byte) uint16 {
+ switch {
+ case n < 44:
+ return uint16(nfcValues[n<<6+uint32(b)])
+ default:
+ n -= 44
+ return uint16(nfcSparse.lookup(n, b))
+ }
+}
+
+// nfcValues: 46 blocks, 2944 entries, 5888 bytes
+// The third block is the zero block.
+var nfcValues = [2944]uint16{
+ // Block 0x0, offset 0x0
+ 0x3c: 0xa000, 0x3d: 0xa000, 0x3e: 0xa000,
+ // Block 0x1, offset 0x40
+ 0x41: 0xa000, 0x42: 0xa000, 0x43: 0xa000, 0x44: 0xa000, 0x45: 0xa000,
+ 0x46: 0xa000, 0x47: 0xa000, 0x48: 0xa000, 0x49: 0xa000, 0x4a: 0xa000, 0x4b: 0xa000,
+ 0x4c: 0xa000, 0x4d: 0xa000, 0x4e: 0xa000, 0x4f: 0xa000, 0x50: 0xa000,
+ 0x52: 0xa000, 0x53: 0xa000, 0x54: 0xa000, 0x55: 0xa000, 0x56: 0xa000, 0x57: 0xa000,
+ 0x58: 0xa000, 0x59: 0xa000, 0x5a: 0xa000,
+ 0x61: 0xa000, 0x62: 0xa000, 0x63: 0xa000,
+ 0x64: 0xa000, 0x65: 0xa000, 0x66: 0xa000, 0x67: 0xa000, 0x68: 0xa000, 0x69: 0xa000,
+ 0x6a: 0xa000, 0x6b: 0xa000, 0x6c: 0xa000, 0x6d: 0xa000, 0x6e: 0xa000, 0x6f: 0xa000,
+ 0x70: 0xa000, 0x72: 0xa000, 0x73: 0xa000, 0x74: 0xa000, 0x75: 0xa000,
+ 0x76: 0xa000, 0x77: 0xa000, 0x78: 0xa000, 0x79: 0xa000, 0x7a: 0xa000,
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc0: 0x2f6f, 0xc1: 0x2f74, 0xc2: 0x4688, 0xc3: 0x2f79, 0xc4: 0x4697, 0xc5: 0x469c,
+ 0xc6: 0xa000, 0xc7: 0x46a6, 0xc8: 0x2fe2, 0xc9: 0x2fe7, 0xca: 0x46ab, 0xcb: 0x2ffb,
+ 0xcc: 0x306e, 0xcd: 0x3073, 0xce: 0x3078, 0xcf: 0x46bf, 0xd1: 0x3104,
+ 0xd2: 0x3127, 0xd3: 0x312c, 0xd4: 0x46c9, 0xd5: 0x46ce, 0xd6: 0x46dd,
+ 0xd8: 0xa000, 0xd9: 0x31b3, 0xda: 0x31b8, 0xdb: 0x31bd, 0xdc: 0x470f, 0xdd: 0x3235,
+ 0xe0: 0x327b, 0xe1: 0x3280, 0xe2: 0x4719, 0xe3: 0x3285,
+ 0xe4: 0x4728, 0xe5: 0x472d, 0xe6: 0xa000, 0xe7: 0x4737, 0xe8: 0x32ee, 0xe9: 0x32f3,
+ 0xea: 0x473c, 0xeb: 0x3307, 0xec: 0x337f, 0xed: 0x3384, 0xee: 0x3389, 0xef: 0x4750,
+ 0xf1: 0x3415, 0xf2: 0x3438, 0xf3: 0x343d, 0xf4: 0x475a, 0xf5: 0x475f,
+ 0xf6: 0x476e, 0xf8: 0xa000, 0xf9: 0x34c9, 0xfa: 0x34ce, 0xfb: 0x34d3,
+ 0xfc: 0x47a0, 0xfd: 0x3550, 0xff: 0x3569,
+ // Block 0x4, offset 0x100
+ 0x100: 0x2f7e, 0x101: 0x328a, 0x102: 0x468d, 0x103: 0x471e, 0x104: 0x2f9c, 0x105: 0x32a8,
+ 0x106: 0x2fb0, 0x107: 0x32bc, 0x108: 0x2fb5, 0x109: 0x32c1, 0x10a: 0x2fba, 0x10b: 0x32c6,
+ 0x10c: 0x2fbf, 0x10d: 0x32cb, 0x10e: 0x2fc9, 0x10f: 0x32d5,
+ 0x112: 0x46b0, 0x113: 0x4741, 0x114: 0x2ff1, 0x115: 0x32fd, 0x116: 0x2ff6, 0x117: 0x3302,
+ 0x118: 0x3014, 0x119: 0x3320, 0x11a: 0x3005, 0x11b: 0x3311, 0x11c: 0x302d, 0x11d: 0x3339,
+ 0x11e: 0x3037, 0x11f: 0x3343, 0x120: 0x303c, 0x121: 0x3348, 0x122: 0x3046, 0x123: 0x3352,
+ 0x124: 0x304b, 0x125: 0x3357, 0x128: 0x307d, 0x129: 0x338e,
+ 0x12a: 0x3082, 0x12b: 0x3393, 0x12c: 0x3087, 0x12d: 0x3398, 0x12e: 0x30aa, 0x12f: 0x33b6,
+ 0x130: 0x308c, 0x134: 0x30b4, 0x135: 0x33c0,
+ 0x136: 0x30c8, 0x137: 0x33d9, 0x139: 0x30d2, 0x13a: 0x33e3, 0x13b: 0x30dc,
+ 0x13c: 0x33ed, 0x13d: 0x30d7, 0x13e: 0x33e8,
+ // Block 0x5, offset 0x140
+ 0x143: 0x30ff, 0x144: 0x3410, 0x145: 0x3118,
+ 0x146: 0x3429, 0x147: 0x310e, 0x148: 0x341f,
+ 0x14c: 0x46d3, 0x14d: 0x4764, 0x14e: 0x3131, 0x14f: 0x3442, 0x150: 0x313b, 0x151: 0x344c,
+ 0x154: 0x3159, 0x155: 0x346a, 0x156: 0x3172, 0x157: 0x3483,
+ 0x158: 0x3163, 0x159: 0x3474, 0x15a: 0x46f6, 0x15b: 0x4787, 0x15c: 0x317c, 0x15d: 0x348d,
+ 0x15e: 0x318b, 0x15f: 0x349c, 0x160: 0x46fb, 0x161: 0x478c, 0x162: 0x31a4, 0x163: 0x34ba,
+ 0x164: 0x3195, 0x165: 0x34ab, 0x168: 0x4705, 0x169: 0x4796,
+ 0x16a: 0x470a, 0x16b: 0x479b, 0x16c: 0x31c2, 0x16d: 0x34d8, 0x16e: 0x31cc, 0x16f: 0x34e2,
+ 0x170: 0x31d1, 0x171: 0x34e7, 0x172: 0x31ef, 0x173: 0x3505, 0x174: 0x3212, 0x175: 0x3528,
+ 0x176: 0x323a, 0x177: 0x3555, 0x178: 0x324e, 0x179: 0x325d, 0x17a: 0x357d, 0x17b: 0x3267,
+ 0x17c: 0x3587, 0x17d: 0x326c, 0x17e: 0x358c, 0x17f: 0xa000,
+ // Block 0x6, offset 0x180
+ 0x184: 0x8100, 0x185: 0x8100,
+ 0x186: 0x8100,
+ 0x18d: 0x2f88, 0x18e: 0x3294, 0x18f: 0x3096, 0x190: 0x33a2, 0x191: 0x3140,
+ 0x192: 0x3451, 0x193: 0x31d6, 0x194: 0x34ec, 0x195: 0x39cf, 0x196: 0x3b5e, 0x197: 0x39c8,
+ 0x198: 0x3b57, 0x199: 0x39d6, 0x19a: 0x3b65, 0x19b: 0x39c1, 0x19c: 0x3b50,
+ 0x19e: 0x38b0, 0x19f: 0x3a3f, 0x1a0: 0x38a9, 0x1a1: 0x3a38, 0x1a2: 0x35b3, 0x1a3: 0x35c5,
+ 0x1a6: 0x3041, 0x1a7: 0x334d, 0x1a8: 0x30be, 0x1a9: 0x33cf,
+ 0x1aa: 0x46ec, 0x1ab: 0x477d, 0x1ac: 0x3990, 0x1ad: 0x3b1f, 0x1ae: 0x35d7, 0x1af: 0x35dd,
+ 0x1b0: 0x33c5, 0x1b4: 0x3028, 0x1b5: 0x3334,
+ 0x1b8: 0x30fa, 0x1b9: 0x340b, 0x1ba: 0x38b7, 0x1bb: 0x3a46,
+ 0x1bc: 0x35ad, 0x1bd: 0x35bf, 0x1be: 0x35b9, 0x1bf: 0x35cb,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x2f8d, 0x1c1: 0x3299, 0x1c2: 0x2f92, 0x1c3: 0x329e, 0x1c4: 0x300a, 0x1c5: 0x3316,
+ 0x1c6: 0x300f, 0x1c7: 0x331b, 0x1c8: 0x309b, 0x1c9: 0x33a7, 0x1ca: 0x30a0, 0x1cb: 0x33ac,
+ 0x1cc: 0x3145, 0x1cd: 0x3456, 0x1ce: 0x314a, 0x1cf: 0x345b, 0x1d0: 0x3168, 0x1d1: 0x3479,
+ 0x1d2: 0x316d, 0x1d3: 0x347e, 0x1d4: 0x31db, 0x1d5: 0x34f1, 0x1d6: 0x31e0, 0x1d7: 0x34f6,
+ 0x1d8: 0x3186, 0x1d9: 0x3497, 0x1da: 0x319f, 0x1db: 0x34b5,
+ 0x1de: 0x305a, 0x1df: 0x3366,
+ 0x1e6: 0x4692, 0x1e7: 0x4723, 0x1e8: 0x46ba, 0x1e9: 0x474b,
+ 0x1ea: 0x395f, 0x1eb: 0x3aee, 0x1ec: 0x393c, 0x1ed: 0x3acb, 0x1ee: 0x46d8, 0x1ef: 0x4769,
+ 0x1f0: 0x3958, 0x1f1: 0x3ae7, 0x1f2: 0x3244, 0x1f3: 0x355f,
+ // Block 0x8, offset 0x200
+ 0x200: 0x9932, 0x201: 0x9932, 0x202: 0x9932, 0x203: 0x9932, 0x204: 0x9932, 0x205: 0x8132,
+ 0x206: 0x9932, 0x207: 0x9932, 0x208: 0x9932, 0x209: 0x9932, 0x20a: 0x9932, 0x20b: 0x9932,
+ 0x20c: 0x9932, 0x20d: 0x8132, 0x20e: 0x8132, 0x20f: 0x9932, 0x210: 0x8132, 0x211: 0x9932,
+ 0x212: 0x8132, 0x213: 0x9932, 0x214: 0x9932, 0x215: 0x8133, 0x216: 0x812d, 0x217: 0x812d,
+ 0x218: 0x812d, 0x219: 0x812d, 0x21a: 0x8133, 0x21b: 0x992b, 0x21c: 0x812d, 0x21d: 0x812d,
+ 0x21e: 0x812d, 0x21f: 0x812d, 0x220: 0x812d, 0x221: 0x8129, 0x222: 0x8129, 0x223: 0x992d,
+ 0x224: 0x992d, 0x225: 0x992d, 0x226: 0x992d, 0x227: 0x9929, 0x228: 0x9929, 0x229: 0x812d,
+ 0x22a: 0x812d, 0x22b: 0x812d, 0x22c: 0x812d, 0x22d: 0x992d, 0x22e: 0x992d, 0x22f: 0x812d,
+ 0x230: 0x992d, 0x231: 0x992d, 0x232: 0x812d, 0x233: 0x812d, 0x234: 0x8101, 0x235: 0x8101,
+ 0x236: 0x8101, 0x237: 0x8101, 0x238: 0x9901, 0x239: 0x812d, 0x23a: 0x812d, 0x23b: 0x812d,
+ 0x23c: 0x812d, 0x23d: 0x8132, 0x23e: 0x8132, 0x23f: 0x8132,
+ // Block 0x9, offset 0x240
+ 0x240: 0x49ae, 0x241: 0x49b3, 0x242: 0x9932, 0x243: 0x49b8, 0x244: 0x4a71, 0x245: 0x9936,
+ 0x246: 0x8132, 0x247: 0x812d, 0x248: 0x812d, 0x249: 0x812d, 0x24a: 0x8132, 0x24b: 0x8132,
+ 0x24c: 0x8132, 0x24d: 0x812d, 0x24e: 0x812d, 0x250: 0x8132, 0x251: 0x8132,
+ 0x252: 0x8132, 0x253: 0x812d, 0x254: 0x812d, 0x255: 0x812d, 0x256: 0x812d, 0x257: 0x8132,
+ 0x258: 0x8133, 0x259: 0x812d, 0x25a: 0x812d, 0x25b: 0x8132, 0x25c: 0x8134, 0x25d: 0x8135,
+ 0x25e: 0x8135, 0x25f: 0x8134, 0x260: 0x8135, 0x261: 0x8135, 0x262: 0x8134, 0x263: 0x8132,
+ 0x264: 0x8132, 0x265: 0x8132, 0x266: 0x8132, 0x267: 0x8132, 0x268: 0x8132, 0x269: 0x8132,
+ 0x26a: 0x8132, 0x26b: 0x8132, 0x26c: 0x8132, 0x26d: 0x8132, 0x26e: 0x8132, 0x26f: 0x8132,
+ 0x274: 0x0170,
+ 0x27a: 0x8100,
+ 0x27e: 0x0037,
+ // Block 0xa, offset 0x280
+ 0x284: 0x8100, 0x285: 0x35a1,
+ 0x286: 0x35e9, 0x287: 0x00ce, 0x288: 0x3607, 0x289: 0x3613, 0x28a: 0x3625,
+ 0x28c: 0x3643, 0x28e: 0x3655, 0x28f: 0x3673, 0x290: 0x3e08, 0x291: 0xa000,
+ 0x295: 0xa000, 0x297: 0xa000,
+ 0x299: 0xa000,
+ 0x29f: 0xa000, 0x2a1: 0xa000,
+ 0x2a5: 0xa000, 0x2a9: 0xa000,
+ 0x2aa: 0x3637, 0x2ab: 0x3667, 0x2ac: 0x47fe, 0x2ad: 0x3697, 0x2ae: 0x4828, 0x2af: 0x36a9,
+ 0x2b0: 0x3e70, 0x2b1: 0xa000, 0x2b5: 0xa000,
+ 0x2b7: 0xa000, 0x2b9: 0xa000,
+ 0x2bf: 0xa000,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0x3721, 0x2c1: 0x372d, 0x2c3: 0x371b,
+ 0x2c6: 0xa000, 0x2c7: 0x3709,
+ 0x2cc: 0x375d, 0x2cd: 0x3745, 0x2ce: 0x376f, 0x2d0: 0xa000,
+ 0x2d3: 0xa000, 0x2d5: 0xa000, 0x2d6: 0xa000, 0x2d7: 0xa000,
+ 0x2d8: 0xa000, 0x2d9: 0x3751, 0x2da: 0xa000,
+ 0x2de: 0xa000, 0x2e3: 0xa000,
+ 0x2e7: 0xa000,
+ 0x2eb: 0xa000, 0x2ed: 0xa000,
+ 0x2f0: 0xa000, 0x2f3: 0xa000, 0x2f5: 0xa000,
+ 0x2f6: 0xa000, 0x2f7: 0xa000, 0x2f8: 0xa000, 0x2f9: 0x37d5, 0x2fa: 0xa000,
+ 0x2fe: 0xa000,
+ // Block 0xc, offset 0x300
+ 0x301: 0x3733, 0x302: 0x37b7,
+ 0x310: 0x370f, 0x311: 0x3793,
+ 0x312: 0x3715, 0x313: 0x3799, 0x316: 0x3727, 0x317: 0x37ab,
+ 0x318: 0xa000, 0x319: 0xa000, 0x31a: 0x3829, 0x31b: 0x382f, 0x31c: 0x3739, 0x31d: 0x37bd,
+ 0x31e: 0x373f, 0x31f: 0x37c3, 0x322: 0x374b, 0x323: 0x37cf,
+ 0x324: 0x3757, 0x325: 0x37db, 0x326: 0x3763, 0x327: 0x37e7, 0x328: 0xa000, 0x329: 0xa000,
+ 0x32a: 0x3835, 0x32b: 0x383b, 0x32c: 0x378d, 0x32d: 0x3811, 0x32e: 0x3769, 0x32f: 0x37ed,
+ 0x330: 0x3775, 0x331: 0x37f9, 0x332: 0x377b, 0x333: 0x37ff, 0x334: 0x3781, 0x335: 0x3805,
+ 0x338: 0x3787, 0x339: 0x380b,
+ // Block 0xd, offset 0x340
+ 0x351: 0x812d,
+ 0x352: 0x8132, 0x353: 0x8132, 0x354: 0x8132, 0x355: 0x8132, 0x356: 0x812d, 0x357: 0x8132,
+ 0x358: 0x8132, 0x359: 0x8132, 0x35a: 0x812e, 0x35b: 0x812d, 0x35c: 0x8132, 0x35d: 0x8132,
+ 0x35e: 0x8132, 0x35f: 0x8132, 0x360: 0x8132, 0x361: 0x8132, 0x362: 0x812d, 0x363: 0x812d,
+ 0x364: 0x812d, 0x365: 0x812d, 0x366: 0x812d, 0x367: 0x812d, 0x368: 0x8132, 0x369: 0x8132,
+ 0x36a: 0x812d, 0x36b: 0x8132, 0x36c: 0x8132, 0x36d: 0x812e, 0x36e: 0x8131, 0x36f: 0x8132,
+ 0x370: 0x8105, 0x371: 0x8106, 0x372: 0x8107, 0x373: 0x8108, 0x374: 0x8109, 0x375: 0x810a,
+ 0x376: 0x810b, 0x377: 0x810c, 0x378: 0x810d, 0x379: 0x810e, 0x37a: 0x810e, 0x37b: 0x810f,
+ 0x37c: 0x8110, 0x37d: 0x8111, 0x37f: 0x8112,
+ // Block 0xe, offset 0x380
+ 0x388: 0xa000, 0x38a: 0xa000, 0x38b: 0x8116,
+ 0x38c: 0x8117, 0x38d: 0x8118, 0x38e: 0x8119, 0x38f: 0x811a, 0x390: 0x811b, 0x391: 0x811c,
+ 0x392: 0x811d, 0x393: 0x9932, 0x394: 0x9932, 0x395: 0x992d, 0x396: 0x812d, 0x397: 0x8132,
+ 0x398: 0x8132, 0x399: 0x8132, 0x39a: 0x8132, 0x39b: 0x8132, 0x39c: 0x812d, 0x39d: 0x8132,
+ 0x39e: 0x8132, 0x39f: 0x812d,
+ 0x3b0: 0x811e,
+ // Block 0xf, offset 0x3c0
+ 0x3c5: 0xa000,
+ 0x3c6: 0x2d26, 0x3c7: 0xa000, 0x3c8: 0x2d2e, 0x3c9: 0xa000, 0x3ca: 0x2d36, 0x3cb: 0xa000,
+ 0x3cc: 0x2d3e, 0x3cd: 0xa000, 0x3ce: 0x2d46, 0x3d1: 0xa000,
+ 0x3d2: 0x2d4e,
+ 0x3f4: 0x8102, 0x3f5: 0x9900,
+ 0x3fa: 0xa000, 0x3fb: 0x2d56,
+ 0x3fc: 0xa000, 0x3fd: 0x2d5e, 0x3fe: 0xa000, 0x3ff: 0xa000,
+ // Block 0x10, offset 0x400
+ 0x400: 0x2f97, 0x401: 0x32a3, 0x402: 0x2fa1, 0x403: 0x32ad, 0x404: 0x2fa6, 0x405: 0x32b2,
+ 0x406: 0x2fab, 0x407: 0x32b7, 0x408: 0x38cc, 0x409: 0x3a5b, 0x40a: 0x2fc4, 0x40b: 0x32d0,
+ 0x40c: 0x2fce, 0x40d: 0x32da, 0x40e: 0x2fdd, 0x40f: 0x32e9, 0x410: 0x2fd3, 0x411: 0x32df,
+ 0x412: 0x2fd8, 0x413: 0x32e4, 0x414: 0x38ef, 0x415: 0x3a7e, 0x416: 0x38f6, 0x417: 0x3a85,
+ 0x418: 0x3019, 0x419: 0x3325, 0x41a: 0x301e, 0x41b: 0x332a, 0x41c: 0x3904, 0x41d: 0x3a93,
+ 0x41e: 0x3023, 0x41f: 0x332f, 0x420: 0x3032, 0x421: 0x333e, 0x422: 0x3050, 0x423: 0x335c,
+ 0x424: 0x305f, 0x425: 0x336b, 0x426: 0x3055, 0x427: 0x3361, 0x428: 0x3064, 0x429: 0x3370,
+ 0x42a: 0x3069, 0x42b: 0x3375, 0x42c: 0x30af, 0x42d: 0x33bb, 0x42e: 0x390b, 0x42f: 0x3a9a,
+ 0x430: 0x30b9, 0x431: 0x33ca, 0x432: 0x30c3, 0x433: 0x33d4, 0x434: 0x30cd, 0x435: 0x33de,
+ 0x436: 0x46c4, 0x437: 0x4755, 0x438: 0x3912, 0x439: 0x3aa1, 0x43a: 0x30e6, 0x43b: 0x33f7,
+ 0x43c: 0x30e1, 0x43d: 0x33f2, 0x43e: 0x30eb, 0x43f: 0x33fc,
+ // Block 0x11, offset 0x440
+ 0x440: 0x30f0, 0x441: 0x3401, 0x442: 0x30f5, 0x443: 0x3406, 0x444: 0x3109, 0x445: 0x341a,
+ 0x446: 0x3113, 0x447: 0x3424, 0x448: 0x3122, 0x449: 0x3433, 0x44a: 0x311d, 0x44b: 0x342e,
+ 0x44c: 0x3935, 0x44d: 0x3ac4, 0x44e: 0x3943, 0x44f: 0x3ad2, 0x450: 0x394a, 0x451: 0x3ad9,
+ 0x452: 0x3951, 0x453: 0x3ae0, 0x454: 0x314f, 0x455: 0x3460, 0x456: 0x3154, 0x457: 0x3465,
+ 0x458: 0x315e, 0x459: 0x346f, 0x45a: 0x46f1, 0x45b: 0x4782, 0x45c: 0x3997, 0x45d: 0x3b26,
+ 0x45e: 0x3177, 0x45f: 0x3488, 0x460: 0x3181, 0x461: 0x3492, 0x462: 0x4700, 0x463: 0x4791,
+ 0x464: 0x399e, 0x465: 0x3b2d, 0x466: 0x39a5, 0x467: 0x3b34, 0x468: 0x39ac, 0x469: 0x3b3b,
+ 0x46a: 0x3190, 0x46b: 0x34a1, 0x46c: 0x319a, 0x46d: 0x34b0, 0x46e: 0x31ae, 0x46f: 0x34c4,
+ 0x470: 0x31a9, 0x471: 0x34bf, 0x472: 0x31ea, 0x473: 0x3500, 0x474: 0x31f9, 0x475: 0x350f,
+ 0x476: 0x31f4, 0x477: 0x350a, 0x478: 0x39b3, 0x479: 0x3b42, 0x47a: 0x39ba, 0x47b: 0x3b49,
+ 0x47c: 0x31fe, 0x47d: 0x3514, 0x47e: 0x3203, 0x47f: 0x3519,
+ // Block 0x12, offset 0x480
+ 0x480: 0x3208, 0x481: 0x351e, 0x482: 0x320d, 0x483: 0x3523, 0x484: 0x321c, 0x485: 0x3532,
+ 0x486: 0x3217, 0x487: 0x352d, 0x488: 0x3221, 0x489: 0x353c, 0x48a: 0x3226, 0x48b: 0x3541,
+ 0x48c: 0x322b, 0x48d: 0x3546, 0x48e: 0x3249, 0x48f: 0x3564, 0x490: 0x3262, 0x491: 0x3582,
+ 0x492: 0x3271, 0x493: 0x3591, 0x494: 0x3276, 0x495: 0x3596, 0x496: 0x337a, 0x497: 0x34a6,
+ 0x498: 0x3537, 0x499: 0x3573, 0x49b: 0x35d1,
+ 0x4a0: 0x46a1, 0x4a1: 0x4732, 0x4a2: 0x2f83, 0x4a3: 0x328f,
+ 0x4a4: 0x3878, 0x4a5: 0x3a07, 0x4a6: 0x3871, 0x4a7: 0x3a00, 0x4a8: 0x3886, 0x4a9: 0x3a15,
+ 0x4aa: 0x387f, 0x4ab: 0x3a0e, 0x4ac: 0x38be, 0x4ad: 0x3a4d, 0x4ae: 0x3894, 0x4af: 0x3a23,
+ 0x4b0: 0x388d, 0x4b1: 0x3a1c, 0x4b2: 0x38a2, 0x4b3: 0x3a31, 0x4b4: 0x389b, 0x4b5: 0x3a2a,
+ 0x4b6: 0x38c5, 0x4b7: 0x3a54, 0x4b8: 0x46b5, 0x4b9: 0x4746, 0x4ba: 0x3000, 0x4bb: 0x330c,
+ 0x4bc: 0x2fec, 0x4bd: 0x32f8, 0x4be: 0x38da, 0x4bf: 0x3a69,
+ // Block 0x13, offset 0x4c0
+ 0x4c0: 0x38d3, 0x4c1: 0x3a62, 0x4c2: 0x38e8, 0x4c3: 0x3a77, 0x4c4: 0x38e1, 0x4c5: 0x3a70,
+ 0x4c6: 0x38fd, 0x4c7: 0x3a8c, 0x4c8: 0x3091, 0x4c9: 0x339d, 0x4ca: 0x30a5, 0x4cb: 0x33b1,
+ 0x4cc: 0x46e7, 0x4cd: 0x4778, 0x4ce: 0x3136, 0x4cf: 0x3447, 0x4d0: 0x3920, 0x4d1: 0x3aaf,
+ 0x4d2: 0x3919, 0x4d3: 0x3aa8, 0x4d4: 0x392e, 0x4d5: 0x3abd, 0x4d6: 0x3927, 0x4d7: 0x3ab6,
+ 0x4d8: 0x3989, 0x4d9: 0x3b18, 0x4da: 0x396d, 0x4db: 0x3afc, 0x4dc: 0x3966, 0x4dd: 0x3af5,
+ 0x4de: 0x397b, 0x4df: 0x3b0a, 0x4e0: 0x3974, 0x4e1: 0x3b03, 0x4e2: 0x3982, 0x4e3: 0x3b11,
+ 0x4e4: 0x31e5, 0x4e5: 0x34fb, 0x4e6: 0x31c7, 0x4e7: 0x34dd, 0x4e8: 0x39e4, 0x4e9: 0x3b73,
+ 0x4ea: 0x39dd, 0x4eb: 0x3b6c, 0x4ec: 0x39f2, 0x4ed: 0x3b81, 0x4ee: 0x39eb, 0x4ef: 0x3b7a,
+ 0x4f0: 0x39f9, 0x4f1: 0x3b88, 0x4f2: 0x3230, 0x4f3: 0x354b, 0x4f4: 0x3258, 0x4f5: 0x3578,
+ 0x4f6: 0x3253, 0x4f7: 0x356e, 0x4f8: 0x323f, 0x4f9: 0x355a,
+ // Block 0x14, offset 0x500
+ 0x500: 0x4804, 0x501: 0x480a, 0x502: 0x491e, 0x503: 0x4936, 0x504: 0x4926, 0x505: 0x493e,
+ 0x506: 0x492e, 0x507: 0x4946, 0x508: 0x47aa, 0x509: 0x47b0, 0x50a: 0x488e, 0x50b: 0x48a6,
+ 0x50c: 0x4896, 0x50d: 0x48ae, 0x50e: 0x489e, 0x50f: 0x48b6, 0x510: 0x4816, 0x511: 0x481c,
+ 0x512: 0x3db8, 0x513: 0x3dc8, 0x514: 0x3dc0, 0x515: 0x3dd0,
+ 0x518: 0x47b6, 0x519: 0x47bc, 0x51a: 0x3ce8, 0x51b: 0x3cf8, 0x51c: 0x3cf0, 0x51d: 0x3d00,
+ 0x520: 0x482e, 0x521: 0x4834, 0x522: 0x494e, 0x523: 0x4966,
+ 0x524: 0x4956, 0x525: 0x496e, 0x526: 0x495e, 0x527: 0x4976, 0x528: 0x47c2, 0x529: 0x47c8,
+ 0x52a: 0x48be, 0x52b: 0x48d6, 0x52c: 0x48c6, 0x52d: 0x48de, 0x52e: 0x48ce, 0x52f: 0x48e6,
+ 0x530: 0x4846, 0x531: 0x484c, 0x532: 0x3e18, 0x533: 0x3e30, 0x534: 0x3e20, 0x535: 0x3e38,
+ 0x536: 0x3e28, 0x537: 0x3e40, 0x538: 0x47ce, 0x539: 0x47d4, 0x53a: 0x3d18, 0x53b: 0x3d30,
+ 0x53c: 0x3d20, 0x53d: 0x3d38, 0x53e: 0x3d28, 0x53f: 0x3d40,
+ // Block 0x15, offset 0x540
+ 0x540: 0x4852, 0x541: 0x4858, 0x542: 0x3e48, 0x543: 0x3e58, 0x544: 0x3e50, 0x545: 0x3e60,
+ 0x548: 0x47da, 0x549: 0x47e0, 0x54a: 0x3d48, 0x54b: 0x3d58,
+ 0x54c: 0x3d50, 0x54d: 0x3d60, 0x550: 0x4864, 0x551: 0x486a,
+ 0x552: 0x3e80, 0x553: 0x3e98, 0x554: 0x3e88, 0x555: 0x3ea0, 0x556: 0x3e90, 0x557: 0x3ea8,
+ 0x559: 0x47e6, 0x55b: 0x3d68, 0x55d: 0x3d70,
+ 0x55f: 0x3d78, 0x560: 0x487c, 0x561: 0x4882, 0x562: 0x497e, 0x563: 0x4996,
+ 0x564: 0x4986, 0x565: 0x499e, 0x566: 0x498e, 0x567: 0x49a6, 0x568: 0x47ec, 0x569: 0x47f2,
+ 0x56a: 0x48ee, 0x56b: 0x4906, 0x56c: 0x48f6, 0x56d: 0x490e, 0x56e: 0x48fe, 0x56f: 0x4916,
+ 0x570: 0x47f8, 0x571: 0x431e, 0x572: 0x3691, 0x573: 0x4324, 0x574: 0x4822, 0x575: 0x432a,
+ 0x576: 0x36a3, 0x577: 0x4330, 0x578: 0x36c1, 0x579: 0x4336, 0x57a: 0x36d9, 0x57b: 0x433c,
+ 0x57c: 0x4870, 0x57d: 0x4342,
+ // Block 0x16, offset 0x580
+ 0x580: 0x3da0, 0x581: 0x3da8, 0x582: 0x4184, 0x583: 0x41a2, 0x584: 0x418e, 0x585: 0x41ac,
+ 0x586: 0x4198, 0x587: 0x41b6, 0x588: 0x3cd8, 0x589: 0x3ce0, 0x58a: 0x40d0, 0x58b: 0x40ee,
+ 0x58c: 0x40da, 0x58d: 0x40f8, 0x58e: 0x40e4, 0x58f: 0x4102, 0x590: 0x3de8, 0x591: 0x3df0,
+ 0x592: 0x41c0, 0x593: 0x41de, 0x594: 0x41ca, 0x595: 0x41e8, 0x596: 0x41d4, 0x597: 0x41f2,
+ 0x598: 0x3d08, 0x599: 0x3d10, 0x59a: 0x410c, 0x59b: 0x412a, 0x59c: 0x4116, 0x59d: 0x4134,
+ 0x59e: 0x4120, 0x59f: 0x413e, 0x5a0: 0x3ec0, 0x5a1: 0x3ec8, 0x5a2: 0x41fc, 0x5a3: 0x421a,
+ 0x5a4: 0x4206, 0x5a5: 0x4224, 0x5a6: 0x4210, 0x5a7: 0x422e, 0x5a8: 0x3d80, 0x5a9: 0x3d88,
+ 0x5aa: 0x4148, 0x5ab: 0x4166, 0x5ac: 0x4152, 0x5ad: 0x4170, 0x5ae: 0x415c, 0x5af: 0x417a,
+ 0x5b0: 0x3685, 0x5b1: 0x367f, 0x5b2: 0x3d90, 0x5b3: 0x368b, 0x5b4: 0x3d98,
+ 0x5b6: 0x4810, 0x5b7: 0x3db0, 0x5b8: 0x35f5, 0x5b9: 0x35ef, 0x5ba: 0x35e3, 0x5bb: 0x42ee,
+ 0x5bc: 0x35fb, 0x5bd: 0x8100, 0x5be: 0x01d3, 0x5bf: 0xa100,
+ // Block 0x17, offset 0x5c0
+ 0x5c0: 0x8100, 0x5c1: 0x35a7, 0x5c2: 0x3dd8, 0x5c3: 0x369d, 0x5c4: 0x3de0,
+ 0x5c6: 0x483a, 0x5c7: 0x3df8, 0x5c8: 0x3601, 0x5c9: 0x42f4, 0x5ca: 0x360d, 0x5cb: 0x42fa,
+ 0x5cc: 0x3619, 0x5cd: 0x3b8f, 0x5ce: 0x3b96, 0x5cf: 0x3b9d, 0x5d0: 0x36b5, 0x5d1: 0x36af,
+ 0x5d2: 0x3e00, 0x5d3: 0x44e4, 0x5d6: 0x36bb, 0x5d7: 0x3e10,
+ 0x5d8: 0x3631, 0x5d9: 0x362b, 0x5da: 0x361f, 0x5db: 0x4300, 0x5dd: 0x3ba4,
+ 0x5de: 0x3bab, 0x5df: 0x3bb2, 0x5e0: 0x36eb, 0x5e1: 0x36e5, 0x5e2: 0x3e68, 0x5e3: 0x44ec,
+ 0x5e4: 0x36cd, 0x5e5: 0x36d3, 0x5e6: 0x36f1, 0x5e7: 0x3e78, 0x5e8: 0x3661, 0x5e9: 0x365b,
+ 0x5ea: 0x364f, 0x5eb: 0x430c, 0x5ec: 0x3649, 0x5ed: 0x359b, 0x5ee: 0x42e8, 0x5ef: 0x0081,
+ 0x5f2: 0x3eb0, 0x5f3: 0x36f7, 0x5f4: 0x3eb8,
+ 0x5f6: 0x4888, 0x5f7: 0x3ed0, 0x5f8: 0x363d, 0x5f9: 0x4306, 0x5fa: 0x366d, 0x5fb: 0x4318,
+ 0x5fc: 0x3679, 0x5fd: 0x4256, 0x5fe: 0xa100,
+ // Block 0x18, offset 0x600
+ 0x601: 0x3c06, 0x603: 0xa000, 0x604: 0x3c0d, 0x605: 0xa000,
+ 0x607: 0x3c14, 0x608: 0xa000, 0x609: 0x3c1b,
+ 0x60d: 0xa000,
+ 0x620: 0x2f65, 0x621: 0xa000, 0x622: 0x3c29,
+ 0x624: 0xa000, 0x625: 0xa000,
+ 0x62d: 0x3c22, 0x62e: 0x2f60, 0x62f: 0x2f6a,
+ 0x630: 0x3c30, 0x631: 0x3c37, 0x632: 0xa000, 0x633: 0xa000, 0x634: 0x3c3e, 0x635: 0x3c45,
+ 0x636: 0xa000, 0x637: 0xa000, 0x638: 0x3c4c, 0x639: 0x3c53, 0x63a: 0xa000, 0x63b: 0xa000,
+ 0x63c: 0xa000, 0x63d: 0xa000,
+ // Block 0x19, offset 0x640
+ 0x640: 0x3c5a, 0x641: 0x3c61, 0x642: 0xa000, 0x643: 0xa000, 0x644: 0x3c76, 0x645: 0x3c7d,
+ 0x646: 0xa000, 0x647: 0xa000, 0x648: 0x3c84, 0x649: 0x3c8b,
+ 0x651: 0xa000,
+ 0x652: 0xa000,
+ 0x662: 0xa000,
+ 0x668: 0xa000, 0x669: 0xa000,
+ 0x66b: 0xa000, 0x66c: 0x3ca0, 0x66d: 0x3ca7, 0x66e: 0x3cae, 0x66f: 0x3cb5,
+ 0x672: 0xa000, 0x673: 0xa000, 0x674: 0xa000, 0x675: 0xa000,
+ // Block 0x1a, offset 0x680
+ 0x686: 0xa000, 0x68b: 0xa000,
+ 0x68c: 0x3f08, 0x68d: 0xa000, 0x68e: 0x3f10, 0x68f: 0xa000, 0x690: 0x3f18, 0x691: 0xa000,
+ 0x692: 0x3f20, 0x693: 0xa000, 0x694: 0x3f28, 0x695: 0xa000, 0x696: 0x3f30, 0x697: 0xa000,
+ 0x698: 0x3f38, 0x699: 0xa000, 0x69a: 0x3f40, 0x69b: 0xa000, 0x69c: 0x3f48, 0x69d: 0xa000,
+ 0x69e: 0x3f50, 0x69f: 0xa000, 0x6a0: 0x3f58, 0x6a1: 0xa000, 0x6a2: 0x3f60,
+ 0x6a4: 0xa000, 0x6a5: 0x3f68, 0x6a6: 0xa000, 0x6a7: 0x3f70, 0x6a8: 0xa000, 0x6a9: 0x3f78,
+ 0x6af: 0xa000,
+ 0x6b0: 0x3f80, 0x6b1: 0x3f88, 0x6b2: 0xa000, 0x6b3: 0x3f90, 0x6b4: 0x3f98, 0x6b5: 0xa000,
+ 0x6b6: 0x3fa0, 0x6b7: 0x3fa8, 0x6b8: 0xa000, 0x6b9: 0x3fb0, 0x6ba: 0x3fb8, 0x6bb: 0xa000,
+ 0x6bc: 0x3fc0, 0x6bd: 0x3fc8,
+ // Block 0x1b, offset 0x6c0
+ 0x6d4: 0x3f00,
+ 0x6d9: 0x9903, 0x6da: 0x9903, 0x6db: 0x8100, 0x6dc: 0x8100, 0x6dd: 0xa000,
+ 0x6de: 0x3fd0,
+ 0x6e6: 0xa000,
+ 0x6eb: 0xa000, 0x6ec: 0x3fe0, 0x6ed: 0xa000, 0x6ee: 0x3fe8, 0x6ef: 0xa000,
+ 0x6f0: 0x3ff0, 0x6f1: 0xa000, 0x6f2: 0x3ff8, 0x6f3: 0xa000, 0x6f4: 0x4000, 0x6f5: 0xa000,
+ 0x6f6: 0x4008, 0x6f7: 0xa000, 0x6f8: 0x4010, 0x6f9: 0xa000, 0x6fa: 0x4018, 0x6fb: 0xa000,
+ 0x6fc: 0x4020, 0x6fd: 0xa000, 0x6fe: 0x4028, 0x6ff: 0xa000,
+ // Block 0x1c, offset 0x700
+ 0x700: 0x4030, 0x701: 0xa000, 0x702: 0x4038, 0x704: 0xa000, 0x705: 0x4040,
+ 0x706: 0xa000, 0x707: 0x4048, 0x708: 0xa000, 0x709: 0x4050,
+ 0x70f: 0xa000, 0x710: 0x4058, 0x711: 0x4060,
+ 0x712: 0xa000, 0x713: 0x4068, 0x714: 0x4070, 0x715: 0xa000, 0x716: 0x4078, 0x717: 0x4080,
+ 0x718: 0xa000, 0x719: 0x4088, 0x71a: 0x4090, 0x71b: 0xa000, 0x71c: 0x4098, 0x71d: 0x40a0,
+ 0x72f: 0xa000,
+ 0x730: 0xa000, 0x731: 0xa000, 0x732: 0xa000, 0x734: 0x3fd8,
+ 0x737: 0x40a8, 0x738: 0x40b0, 0x739: 0x40b8, 0x73a: 0x40c0,
+ 0x73d: 0xa000, 0x73e: 0x40c8,
+ // Block 0x1d, offset 0x740
+ 0x740: 0x1377, 0x741: 0x0cfb, 0x742: 0x13d3, 0x743: 0x139f, 0x744: 0x0e57, 0x745: 0x06eb,
+ 0x746: 0x08df, 0x747: 0x162b, 0x748: 0x162b, 0x749: 0x0a0b, 0x74a: 0x145f, 0x74b: 0x0943,
+ 0x74c: 0x0a07, 0x74d: 0x0bef, 0x74e: 0x0fcf, 0x74f: 0x115f, 0x750: 0x1297, 0x751: 0x12d3,
+ 0x752: 0x1307, 0x753: 0x141b, 0x754: 0x0d73, 0x755: 0x0dff, 0x756: 0x0eab, 0x757: 0x0f43,
+ 0x758: 0x125f, 0x759: 0x1447, 0x75a: 0x1573, 0x75b: 0x070f, 0x75c: 0x08b3, 0x75d: 0x0d87,
+ 0x75e: 0x0ecf, 0x75f: 0x1293, 0x760: 0x15c3, 0x761: 0x0ab3, 0x762: 0x0e77, 0x763: 0x1283,
+ 0x764: 0x1317, 0x765: 0x0c23, 0x766: 0x11bb, 0x767: 0x12df, 0x768: 0x0b1f, 0x769: 0x0d0f,
+ 0x76a: 0x0e17, 0x76b: 0x0f1b, 0x76c: 0x1427, 0x76d: 0x074f, 0x76e: 0x07e7, 0x76f: 0x0853,
+ 0x770: 0x0c8b, 0x771: 0x0d7f, 0x772: 0x0ecb, 0x773: 0x0fef, 0x774: 0x1177, 0x775: 0x128b,
+ 0x776: 0x12a3, 0x777: 0x13c7, 0x778: 0x14ef, 0x779: 0x15a3, 0x77a: 0x15bf, 0x77b: 0x102b,
+ 0x77c: 0x106b, 0x77d: 0x1123, 0x77e: 0x1243, 0x77f: 0x147b,
+ // Block 0x1e, offset 0x780
+ 0x780: 0x15cb, 0x781: 0x134b, 0x782: 0x09c7, 0x783: 0x0b3b, 0x784: 0x10db, 0x785: 0x119b,
+ 0x786: 0x0eff, 0x787: 0x1033, 0x788: 0x1397, 0x789: 0x14e7, 0x78a: 0x09c3, 0x78b: 0x0a8f,
+ 0x78c: 0x0d77, 0x78d: 0x0e2b, 0x78e: 0x0e5f, 0x78f: 0x1113, 0x790: 0x113b, 0x791: 0x14a7,
+ 0x792: 0x084f, 0x793: 0x11a7, 0x794: 0x07f3, 0x795: 0x07ef, 0x796: 0x1097, 0x797: 0x1127,
+ 0x798: 0x125b, 0x799: 0x14af, 0x79a: 0x1367, 0x79b: 0x0c27, 0x79c: 0x0d73, 0x79d: 0x1357,
+ 0x79e: 0x06f7, 0x79f: 0x0a63, 0x7a0: 0x0b93, 0x7a1: 0x0f2f, 0x7a2: 0x0faf, 0x7a3: 0x0873,
+ 0x7a4: 0x103b, 0x7a5: 0x075f, 0x7a6: 0x0b77, 0x7a7: 0x06d7, 0x7a8: 0x0deb, 0x7a9: 0x0ca3,
+ 0x7aa: 0x110f, 0x7ab: 0x08c7, 0x7ac: 0x09b3, 0x7ad: 0x0ffb, 0x7ae: 0x1263, 0x7af: 0x133b,
+ 0x7b0: 0x0db7, 0x7b1: 0x13f7, 0x7b2: 0x0de3, 0x7b3: 0x0c37, 0x7b4: 0x121b, 0x7b5: 0x0c57,
+ 0x7b6: 0x0fab, 0x7b7: 0x072b, 0x7b8: 0x07a7, 0x7b9: 0x07eb, 0x7ba: 0x0d53, 0x7bb: 0x10fb,
+ 0x7bc: 0x11f3, 0x7bd: 0x1347, 0x7be: 0x145b, 0x7bf: 0x085b,
+ // Block 0x1f, offset 0x7c0
+ 0x7c0: 0x090f, 0x7c1: 0x0a17, 0x7c2: 0x0b2f, 0x7c3: 0x0cbf, 0x7c4: 0x0e7b, 0x7c5: 0x103f,
+ 0x7c6: 0x1497, 0x7c7: 0x157b, 0x7c8: 0x15cf, 0x7c9: 0x15e7, 0x7ca: 0x0837, 0x7cb: 0x0cf3,
+ 0x7cc: 0x0da3, 0x7cd: 0x13eb, 0x7ce: 0x0afb, 0x7cf: 0x0bd7, 0x7d0: 0x0bf3, 0x7d1: 0x0c83,
+ 0x7d2: 0x0e6b, 0x7d3: 0x0eb7, 0x7d4: 0x0f67, 0x7d5: 0x108b, 0x7d6: 0x112f, 0x7d7: 0x1193,
+ 0x7d8: 0x13db, 0x7d9: 0x126b, 0x7da: 0x1403, 0x7db: 0x147f, 0x7dc: 0x080f, 0x7dd: 0x083b,
+ 0x7de: 0x0923, 0x7df: 0x0ea7, 0x7e0: 0x12f3, 0x7e1: 0x133b, 0x7e2: 0x0b1b, 0x7e3: 0x0b8b,
+ 0x7e4: 0x0c4f, 0x7e5: 0x0daf, 0x7e6: 0x10d7, 0x7e7: 0x0f23, 0x7e8: 0x073b, 0x7e9: 0x097f,
+ 0x7ea: 0x0a63, 0x7eb: 0x0ac7, 0x7ec: 0x0b97, 0x7ed: 0x0f3f, 0x7ee: 0x0f5b, 0x7ef: 0x116b,
+ 0x7f0: 0x118b, 0x7f1: 0x1463, 0x7f2: 0x14e3, 0x7f3: 0x14f3, 0x7f4: 0x152f, 0x7f5: 0x0753,
+ 0x7f6: 0x107f, 0x7f7: 0x144f, 0x7f8: 0x14cb, 0x7f9: 0x0baf, 0x7fa: 0x0717, 0x7fb: 0x0777,
+ 0x7fc: 0x0a67, 0x7fd: 0x0a87, 0x7fe: 0x0caf, 0x7ff: 0x0d73,
+ // Block 0x20, offset 0x800
+ 0x800: 0x0ec3, 0x801: 0x0fcb, 0x802: 0x1277, 0x803: 0x1417, 0x804: 0x1623, 0x805: 0x0ce3,
+ 0x806: 0x14a3, 0x807: 0x0833, 0x808: 0x0d2f, 0x809: 0x0d3b, 0x80a: 0x0e0f, 0x80b: 0x0e47,
+ 0x80c: 0x0f4b, 0x80d: 0x0fa7, 0x80e: 0x1027, 0x80f: 0x110b, 0x810: 0x153b, 0x811: 0x07af,
+ 0x812: 0x0c03, 0x813: 0x14b3, 0x814: 0x0767, 0x815: 0x0aab, 0x816: 0x0e2f, 0x817: 0x13df,
+ 0x818: 0x0b67, 0x819: 0x0bb7, 0x81a: 0x0d43, 0x81b: 0x0f2f, 0x81c: 0x14bb, 0x81d: 0x0817,
+ 0x81e: 0x08ff, 0x81f: 0x0a97, 0x820: 0x0cd3, 0x821: 0x0d1f, 0x822: 0x0d5f, 0x823: 0x0df3,
+ 0x824: 0x0f47, 0x825: 0x0fbb, 0x826: 0x1157, 0x827: 0x12f7, 0x828: 0x1303, 0x829: 0x1457,
+ 0x82a: 0x14d7, 0x82b: 0x0883, 0x82c: 0x0e4b, 0x82d: 0x0903, 0x82e: 0x0ec7, 0x82f: 0x0f6b,
+ 0x830: 0x1287, 0x831: 0x14bf, 0x832: 0x15ab, 0x833: 0x15d3, 0x834: 0x0d37, 0x835: 0x0e27,
+ 0x836: 0x11c3, 0x837: 0x10b7, 0x838: 0x10c3, 0x839: 0x10e7, 0x83a: 0x0f17, 0x83b: 0x0e9f,
+ 0x83c: 0x1363, 0x83d: 0x0733, 0x83e: 0x122b, 0x83f: 0x081b,
+ // Block 0x21, offset 0x840
+ 0x840: 0x080b, 0x841: 0x0b0b, 0x842: 0x0c2b, 0x843: 0x10f3, 0x844: 0x0a53, 0x845: 0x0e03,
+ 0x846: 0x0cef, 0x847: 0x13e7, 0x848: 0x12e7, 0x849: 0x14ab, 0x84a: 0x1323, 0x84b: 0x0b27,
+ 0x84c: 0x0787, 0x84d: 0x095b, 0x850: 0x09af,
+ 0x852: 0x0cdf, 0x855: 0x07f7, 0x856: 0x0f1f, 0x857: 0x0fe3,
+ 0x858: 0x1047, 0x859: 0x1063, 0x85a: 0x1067, 0x85b: 0x107b, 0x85c: 0x14fb, 0x85d: 0x10eb,
+ 0x85e: 0x116f, 0x860: 0x128f, 0x862: 0x1353,
+ 0x865: 0x1407, 0x866: 0x1433,
+ 0x86a: 0x154f, 0x86b: 0x1553, 0x86c: 0x1557, 0x86d: 0x15bb, 0x86e: 0x142b, 0x86f: 0x14c7,
+ 0x870: 0x0757, 0x871: 0x077b, 0x872: 0x078f, 0x873: 0x084b, 0x874: 0x0857, 0x875: 0x0897,
+ 0x876: 0x094b, 0x877: 0x0967, 0x878: 0x096f, 0x879: 0x09ab, 0x87a: 0x09b7, 0x87b: 0x0a93,
+ 0x87c: 0x0a9b, 0x87d: 0x0ba3, 0x87e: 0x0bcb, 0x87f: 0x0bd3,
+ // Block 0x22, offset 0x880
+ 0x880: 0x0beb, 0x881: 0x0c97, 0x882: 0x0cc7, 0x883: 0x0ce7, 0x884: 0x0d57, 0x885: 0x0e1b,
+ 0x886: 0x0e37, 0x887: 0x0e67, 0x888: 0x0ebb, 0x889: 0x0edb, 0x88a: 0x0f4f, 0x88b: 0x102f,
+ 0x88c: 0x104b, 0x88d: 0x1053, 0x88e: 0x104f, 0x88f: 0x1057, 0x890: 0x105b, 0x891: 0x105f,
+ 0x892: 0x1073, 0x893: 0x1077, 0x894: 0x109b, 0x895: 0x10af, 0x896: 0x10cb, 0x897: 0x112f,
+ 0x898: 0x1137, 0x899: 0x113f, 0x89a: 0x1153, 0x89b: 0x117b, 0x89c: 0x11cb, 0x89d: 0x11ff,
+ 0x89e: 0x11ff, 0x89f: 0x1267, 0x8a0: 0x130f, 0x8a1: 0x1327, 0x8a2: 0x135b, 0x8a3: 0x135f,
+ 0x8a4: 0x13a3, 0x8a5: 0x13a7, 0x8a6: 0x13ff, 0x8a7: 0x1407, 0x8a8: 0x14db, 0x8a9: 0x151f,
+ 0x8aa: 0x1537, 0x8ab: 0x0b9b, 0x8ac: 0x171e, 0x8ad: 0x11e3,
+ 0x8b0: 0x06df, 0x8b1: 0x07e3, 0x8b2: 0x07a3, 0x8b3: 0x074b, 0x8b4: 0x078b, 0x8b5: 0x07b7,
+ 0x8b6: 0x0847, 0x8b7: 0x0863, 0x8b8: 0x094b, 0x8b9: 0x0937, 0x8ba: 0x0947, 0x8bb: 0x0963,
+ 0x8bc: 0x09af, 0x8bd: 0x09bf, 0x8be: 0x0a03, 0x8bf: 0x0a0f,
+ // Block 0x23, offset 0x8c0
+ 0x8c0: 0x0a2b, 0x8c1: 0x0a3b, 0x8c2: 0x0b23, 0x8c3: 0x0b2b, 0x8c4: 0x0b5b, 0x8c5: 0x0b7b,
+ 0x8c6: 0x0bab, 0x8c7: 0x0bc3, 0x8c8: 0x0bb3, 0x8c9: 0x0bd3, 0x8ca: 0x0bc7, 0x8cb: 0x0beb,
+ 0x8cc: 0x0c07, 0x8cd: 0x0c5f, 0x8ce: 0x0c6b, 0x8cf: 0x0c73, 0x8d0: 0x0c9b, 0x8d1: 0x0cdf,
+ 0x8d2: 0x0d0f, 0x8d3: 0x0d13, 0x8d4: 0x0d27, 0x8d5: 0x0da7, 0x8d6: 0x0db7, 0x8d7: 0x0e0f,
+ 0x8d8: 0x0e5b, 0x8d9: 0x0e53, 0x8da: 0x0e67, 0x8db: 0x0e83, 0x8dc: 0x0ebb, 0x8dd: 0x1013,
+ 0x8de: 0x0edf, 0x8df: 0x0f13, 0x8e0: 0x0f1f, 0x8e1: 0x0f5f, 0x8e2: 0x0f7b, 0x8e3: 0x0f9f,
+ 0x8e4: 0x0fc3, 0x8e5: 0x0fc7, 0x8e6: 0x0fe3, 0x8e7: 0x0fe7, 0x8e8: 0x0ff7, 0x8e9: 0x100b,
+ 0x8ea: 0x1007, 0x8eb: 0x1037, 0x8ec: 0x10b3, 0x8ed: 0x10cb, 0x8ee: 0x10e3, 0x8ef: 0x111b,
+ 0x8f0: 0x112f, 0x8f1: 0x114b, 0x8f2: 0x117b, 0x8f3: 0x122f, 0x8f4: 0x1257, 0x8f5: 0x12cb,
+ 0x8f6: 0x1313, 0x8f7: 0x131f, 0x8f8: 0x1327, 0x8f9: 0x133f, 0x8fa: 0x1353, 0x8fb: 0x1343,
+ 0x8fc: 0x135b, 0x8fd: 0x1357, 0x8fe: 0x134f, 0x8ff: 0x135f,
+ // Block 0x24, offset 0x900
+ 0x900: 0x136b, 0x901: 0x13a7, 0x902: 0x13e3, 0x903: 0x1413, 0x904: 0x144b, 0x905: 0x146b,
+ 0x906: 0x14b7, 0x907: 0x14db, 0x908: 0x14fb, 0x909: 0x150f, 0x90a: 0x151f, 0x90b: 0x152b,
+ 0x90c: 0x1537, 0x90d: 0x158b, 0x90e: 0x162b, 0x90f: 0x16b5, 0x910: 0x16b0, 0x911: 0x16e2,
+ 0x912: 0x0607, 0x913: 0x062f, 0x914: 0x0633, 0x915: 0x1764, 0x916: 0x1791, 0x917: 0x1809,
+ 0x918: 0x1617, 0x919: 0x1627,
+ // Block 0x25, offset 0x940
+ 0x940: 0x06fb, 0x941: 0x06f3, 0x942: 0x0703, 0x943: 0x1647, 0x944: 0x0747, 0x945: 0x0757,
+ 0x946: 0x075b, 0x947: 0x0763, 0x948: 0x076b, 0x949: 0x076f, 0x94a: 0x077b, 0x94b: 0x0773,
+ 0x94c: 0x05b3, 0x94d: 0x165b, 0x94e: 0x078f, 0x94f: 0x0793, 0x950: 0x0797, 0x951: 0x07b3,
+ 0x952: 0x164c, 0x953: 0x05b7, 0x954: 0x079f, 0x955: 0x07bf, 0x956: 0x1656, 0x957: 0x07cf,
+ 0x958: 0x07d7, 0x959: 0x0737, 0x95a: 0x07df, 0x95b: 0x07e3, 0x95c: 0x1831, 0x95d: 0x07ff,
+ 0x95e: 0x0807, 0x95f: 0x05bf, 0x960: 0x081f, 0x961: 0x0823, 0x962: 0x082b, 0x963: 0x082f,
+ 0x964: 0x05c3, 0x965: 0x0847, 0x966: 0x084b, 0x967: 0x0857, 0x968: 0x0863, 0x969: 0x0867,
+ 0x96a: 0x086b, 0x96b: 0x0873, 0x96c: 0x0893, 0x96d: 0x0897, 0x96e: 0x089f, 0x96f: 0x08af,
+ 0x970: 0x08b7, 0x971: 0x08bb, 0x972: 0x08bb, 0x973: 0x08bb, 0x974: 0x166a, 0x975: 0x0e93,
+ 0x976: 0x08cf, 0x977: 0x08d7, 0x978: 0x166f, 0x979: 0x08e3, 0x97a: 0x08eb, 0x97b: 0x08f3,
+ 0x97c: 0x091b, 0x97d: 0x0907, 0x97e: 0x0913, 0x97f: 0x0917,
+ // Block 0x26, offset 0x980
+ 0x980: 0x091f, 0x981: 0x0927, 0x982: 0x092b, 0x983: 0x0933, 0x984: 0x093b, 0x985: 0x093f,
+ 0x986: 0x093f, 0x987: 0x0947, 0x988: 0x094f, 0x989: 0x0953, 0x98a: 0x095f, 0x98b: 0x0983,
+ 0x98c: 0x0967, 0x98d: 0x0987, 0x98e: 0x096b, 0x98f: 0x0973, 0x990: 0x080b, 0x991: 0x09cf,
+ 0x992: 0x0997, 0x993: 0x099b, 0x994: 0x099f, 0x995: 0x0993, 0x996: 0x09a7, 0x997: 0x09a3,
+ 0x998: 0x09bb, 0x999: 0x1674, 0x99a: 0x09d7, 0x99b: 0x09db, 0x99c: 0x09e3, 0x99d: 0x09ef,
+ 0x99e: 0x09f7, 0x99f: 0x0a13, 0x9a0: 0x1679, 0x9a1: 0x167e, 0x9a2: 0x0a1f, 0x9a3: 0x0a23,
+ 0x9a4: 0x0a27, 0x9a5: 0x0a1b, 0x9a6: 0x0a2f, 0x9a7: 0x05c7, 0x9a8: 0x05cb, 0x9a9: 0x0a37,
+ 0x9aa: 0x0a3f, 0x9ab: 0x0a3f, 0x9ac: 0x1683, 0x9ad: 0x0a5b, 0x9ae: 0x0a5f, 0x9af: 0x0a63,
+ 0x9b0: 0x0a6b, 0x9b1: 0x1688, 0x9b2: 0x0a73, 0x9b3: 0x0a77, 0x9b4: 0x0b4f, 0x9b5: 0x0a7f,
+ 0x9b6: 0x05cf, 0x9b7: 0x0a8b, 0x9b8: 0x0a9b, 0x9b9: 0x0aa7, 0x9ba: 0x0aa3, 0x9bb: 0x1692,
+ 0x9bc: 0x0aaf, 0x9bd: 0x1697, 0x9be: 0x0abb, 0x9bf: 0x0ab7,
+ // Block 0x27, offset 0x9c0
+ 0x9c0: 0x0abf, 0x9c1: 0x0acf, 0x9c2: 0x0ad3, 0x9c3: 0x05d3, 0x9c4: 0x0ae3, 0x9c5: 0x0aeb,
+ 0x9c6: 0x0aef, 0x9c7: 0x0af3, 0x9c8: 0x05d7, 0x9c9: 0x169c, 0x9ca: 0x05db, 0x9cb: 0x0b0f,
+ 0x9cc: 0x0b13, 0x9cd: 0x0b17, 0x9ce: 0x0b1f, 0x9cf: 0x1863, 0x9d0: 0x0b37, 0x9d1: 0x16a6,
+ 0x9d2: 0x16a6, 0x9d3: 0x11d7, 0x9d4: 0x0b47, 0x9d5: 0x0b47, 0x9d6: 0x05df, 0x9d7: 0x16c9,
+ 0x9d8: 0x179b, 0x9d9: 0x0b57, 0x9da: 0x0b5f, 0x9db: 0x05e3, 0x9dc: 0x0b73, 0x9dd: 0x0b83,
+ 0x9de: 0x0b87, 0x9df: 0x0b8f, 0x9e0: 0x0b9f, 0x9e1: 0x05eb, 0x9e2: 0x05e7, 0x9e3: 0x0ba3,
+ 0x9e4: 0x16ab, 0x9e5: 0x0ba7, 0x9e6: 0x0bbb, 0x9e7: 0x0bbf, 0x9e8: 0x0bc3, 0x9e9: 0x0bbf,
+ 0x9ea: 0x0bcf, 0x9eb: 0x0bd3, 0x9ec: 0x0be3, 0x9ed: 0x0bdb, 0x9ee: 0x0bdf, 0x9ef: 0x0be7,
+ 0x9f0: 0x0beb, 0x9f1: 0x0bef, 0x9f2: 0x0bfb, 0x9f3: 0x0bff, 0x9f4: 0x0c17, 0x9f5: 0x0c1f,
+ 0x9f6: 0x0c2f, 0x9f7: 0x0c43, 0x9f8: 0x16ba, 0x9f9: 0x0c3f, 0x9fa: 0x0c33, 0x9fb: 0x0c4b,
+ 0x9fc: 0x0c53, 0x9fd: 0x0c67, 0x9fe: 0x16bf, 0x9ff: 0x0c6f,
+ // Block 0x28, offset 0xa00
+ 0xa00: 0x0c63, 0xa01: 0x0c5b, 0xa02: 0x05ef, 0xa03: 0x0c77, 0xa04: 0x0c7f, 0xa05: 0x0c87,
+ 0xa06: 0x0c7b, 0xa07: 0x05f3, 0xa08: 0x0c97, 0xa09: 0x0c9f, 0xa0a: 0x16c4, 0xa0b: 0x0ccb,
+ 0xa0c: 0x0cff, 0xa0d: 0x0cdb, 0xa0e: 0x05ff, 0xa0f: 0x0ce7, 0xa10: 0x05fb, 0xa11: 0x05f7,
+ 0xa12: 0x07c3, 0xa13: 0x07c7, 0xa14: 0x0d03, 0xa15: 0x0ceb, 0xa16: 0x11ab, 0xa17: 0x0663,
+ 0xa18: 0x0d0f, 0xa19: 0x0d13, 0xa1a: 0x0d17, 0xa1b: 0x0d2b, 0xa1c: 0x0d23, 0xa1d: 0x16dd,
+ 0xa1e: 0x0603, 0xa1f: 0x0d3f, 0xa20: 0x0d33, 0xa21: 0x0d4f, 0xa22: 0x0d57, 0xa23: 0x16e7,
+ 0xa24: 0x0d5b, 0xa25: 0x0d47, 0xa26: 0x0d63, 0xa27: 0x0607, 0xa28: 0x0d67, 0xa29: 0x0d6b,
+ 0xa2a: 0x0d6f, 0xa2b: 0x0d7b, 0xa2c: 0x16ec, 0xa2d: 0x0d83, 0xa2e: 0x060b, 0xa2f: 0x0d8f,
+ 0xa30: 0x16f1, 0xa31: 0x0d93, 0xa32: 0x060f, 0xa33: 0x0d9f, 0xa34: 0x0dab, 0xa35: 0x0db7,
+ 0xa36: 0x0dbb, 0xa37: 0x16f6, 0xa38: 0x168d, 0xa39: 0x16fb, 0xa3a: 0x0ddb, 0xa3b: 0x1700,
+ 0xa3c: 0x0de7, 0xa3d: 0x0def, 0xa3e: 0x0ddf, 0xa3f: 0x0dfb,
+ // Block 0x29, offset 0xa40
+ 0xa40: 0x0e0b, 0xa41: 0x0e1b, 0xa42: 0x0e0f, 0xa43: 0x0e13, 0xa44: 0x0e1f, 0xa45: 0x0e23,
+ 0xa46: 0x1705, 0xa47: 0x0e07, 0xa48: 0x0e3b, 0xa49: 0x0e3f, 0xa4a: 0x0613, 0xa4b: 0x0e53,
+ 0xa4c: 0x0e4f, 0xa4d: 0x170a, 0xa4e: 0x0e33, 0xa4f: 0x0e6f, 0xa50: 0x170f, 0xa51: 0x1714,
+ 0xa52: 0x0e73, 0xa53: 0x0e87, 0xa54: 0x0e83, 0xa55: 0x0e7f, 0xa56: 0x0617, 0xa57: 0x0e8b,
+ 0xa58: 0x0e9b, 0xa59: 0x0e97, 0xa5a: 0x0ea3, 0xa5b: 0x1651, 0xa5c: 0x0eb3, 0xa5d: 0x1719,
+ 0xa5e: 0x0ebf, 0xa5f: 0x1723, 0xa60: 0x0ed3, 0xa61: 0x0edf, 0xa62: 0x0ef3, 0xa63: 0x1728,
+ 0xa64: 0x0f07, 0xa65: 0x0f0b, 0xa66: 0x172d, 0xa67: 0x1732, 0xa68: 0x0f27, 0xa69: 0x0f37,
+ 0xa6a: 0x061b, 0xa6b: 0x0f3b, 0xa6c: 0x061f, 0xa6d: 0x061f, 0xa6e: 0x0f53, 0xa6f: 0x0f57,
+ 0xa70: 0x0f5f, 0xa71: 0x0f63, 0xa72: 0x0f6f, 0xa73: 0x0623, 0xa74: 0x0f87, 0xa75: 0x1737,
+ 0xa76: 0x0fa3, 0xa77: 0x173c, 0xa78: 0x0faf, 0xa79: 0x16a1, 0xa7a: 0x0fbf, 0xa7b: 0x1741,
+ 0xa7c: 0x1746, 0xa7d: 0x174b, 0xa7e: 0x0627, 0xa7f: 0x062b,
+ // Block 0x2a, offset 0xa80
+ 0xa80: 0x0ff7, 0xa81: 0x1755, 0xa82: 0x1750, 0xa83: 0x175a, 0xa84: 0x175f, 0xa85: 0x0fff,
+ 0xa86: 0x1003, 0xa87: 0x1003, 0xa88: 0x100b, 0xa89: 0x0633, 0xa8a: 0x100f, 0xa8b: 0x0637,
+ 0xa8c: 0x063b, 0xa8d: 0x1769, 0xa8e: 0x1023, 0xa8f: 0x102b, 0xa90: 0x1037, 0xa91: 0x063f,
+ 0xa92: 0x176e, 0xa93: 0x105b, 0xa94: 0x1773, 0xa95: 0x1778, 0xa96: 0x107b, 0xa97: 0x1093,
+ 0xa98: 0x0643, 0xa99: 0x109b, 0xa9a: 0x109f, 0xa9b: 0x10a3, 0xa9c: 0x177d, 0xa9d: 0x1782,
+ 0xa9e: 0x1782, 0xa9f: 0x10bb, 0xaa0: 0x0647, 0xaa1: 0x1787, 0xaa2: 0x10cf, 0xaa3: 0x10d3,
+ 0xaa4: 0x064b, 0xaa5: 0x178c, 0xaa6: 0x10ef, 0xaa7: 0x064f, 0xaa8: 0x10ff, 0xaa9: 0x10f7,
+ 0xaaa: 0x1107, 0xaab: 0x1796, 0xaac: 0x111f, 0xaad: 0x0653, 0xaae: 0x112b, 0xaaf: 0x1133,
+ 0xab0: 0x1143, 0xab1: 0x0657, 0xab2: 0x17a0, 0xab3: 0x17a5, 0xab4: 0x065b, 0xab5: 0x17aa,
+ 0xab6: 0x115b, 0xab7: 0x17af, 0xab8: 0x1167, 0xab9: 0x1173, 0xaba: 0x117b, 0xabb: 0x17b4,
+ 0xabc: 0x17b9, 0xabd: 0x118f, 0xabe: 0x17be, 0xabf: 0x1197,
+ // Block 0x2b, offset 0xac0
+ 0xac0: 0x16ce, 0xac1: 0x065f, 0xac2: 0x11af, 0xac3: 0x11b3, 0xac4: 0x0667, 0xac5: 0x11b7,
+ 0xac6: 0x0a33, 0xac7: 0x17c3, 0xac8: 0x17c8, 0xac9: 0x16d3, 0xaca: 0x16d8, 0xacb: 0x11d7,
+ 0xacc: 0x11db, 0xacd: 0x13f3, 0xace: 0x066b, 0xacf: 0x1207, 0xad0: 0x1203, 0xad1: 0x120b,
+ 0xad2: 0x083f, 0xad3: 0x120f, 0xad4: 0x1213, 0xad5: 0x1217, 0xad6: 0x121f, 0xad7: 0x17cd,
+ 0xad8: 0x121b, 0xad9: 0x1223, 0xada: 0x1237, 0xadb: 0x123b, 0xadc: 0x1227, 0xadd: 0x123f,
+ 0xade: 0x1253, 0xadf: 0x1267, 0xae0: 0x1233, 0xae1: 0x1247, 0xae2: 0x124b, 0xae3: 0x124f,
+ 0xae4: 0x17d2, 0xae5: 0x17dc, 0xae6: 0x17d7, 0xae7: 0x066f, 0xae8: 0x126f, 0xae9: 0x1273,
+ 0xaea: 0x127b, 0xaeb: 0x17f0, 0xaec: 0x127f, 0xaed: 0x17e1, 0xaee: 0x0673, 0xaef: 0x0677,
+ 0xaf0: 0x17e6, 0xaf1: 0x17eb, 0xaf2: 0x067b, 0xaf3: 0x129f, 0xaf4: 0x12a3, 0xaf5: 0x12a7,
+ 0xaf6: 0x12ab, 0xaf7: 0x12b7, 0xaf8: 0x12b3, 0xaf9: 0x12bf, 0xafa: 0x12bb, 0xafb: 0x12cb,
+ 0xafc: 0x12c3, 0xafd: 0x12c7, 0xafe: 0x12cf, 0xaff: 0x067f,
+ // Block 0x2c, offset 0xb00
+ 0xb00: 0x12d7, 0xb01: 0x12db, 0xb02: 0x0683, 0xb03: 0x12eb, 0xb04: 0x12ef, 0xb05: 0x17f5,
+ 0xb06: 0x12fb, 0xb07: 0x12ff, 0xb08: 0x0687, 0xb09: 0x130b, 0xb0a: 0x05bb, 0xb0b: 0x17fa,
+ 0xb0c: 0x17ff, 0xb0d: 0x068b, 0xb0e: 0x068f, 0xb0f: 0x1337, 0xb10: 0x134f, 0xb11: 0x136b,
+ 0xb12: 0x137b, 0xb13: 0x1804, 0xb14: 0x138f, 0xb15: 0x1393, 0xb16: 0x13ab, 0xb17: 0x13b7,
+ 0xb18: 0x180e, 0xb19: 0x1660, 0xb1a: 0x13c3, 0xb1b: 0x13bf, 0xb1c: 0x13cb, 0xb1d: 0x1665,
+ 0xb1e: 0x13d7, 0xb1f: 0x13e3, 0xb20: 0x1813, 0xb21: 0x1818, 0xb22: 0x1423, 0xb23: 0x142f,
+ 0xb24: 0x1437, 0xb25: 0x181d, 0xb26: 0x143b, 0xb27: 0x1467, 0xb28: 0x1473, 0xb29: 0x1477,
+ 0xb2a: 0x146f, 0xb2b: 0x1483, 0xb2c: 0x1487, 0xb2d: 0x1822, 0xb2e: 0x1493, 0xb2f: 0x0693,
+ 0xb30: 0x149b, 0xb31: 0x1827, 0xb32: 0x0697, 0xb33: 0x14d3, 0xb34: 0x0ac3, 0xb35: 0x14eb,
+ 0xb36: 0x182c, 0xb37: 0x1836, 0xb38: 0x069b, 0xb39: 0x069f, 0xb3a: 0x1513, 0xb3b: 0x183b,
+ 0xb3c: 0x06a3, 0xb3d: 0x1840, 0xb3e: 0x152b, 0xb3f: 0x152b,
+ // Block 0x2d, offset 0xb40
+ 0xb40: 0x1533, 0xb41: 0x1845, 0xb42: 0x154b, 0xb43: 0x06a7, 0xb44: 0x155b, 0xb45: 0x1567,
+ 0xb46: 0x156f, 0xb47: 0x1577, 0xb48: 0x06ab, 0xb49: 0x184a, 0xb4a: 0x158b, 0xb4b: 0x15a7,
+ 0xb4c: 0x15b3, 0xb4d: 0x06af, 0xb4e: 0x06b3, 0xb4f: 0x15b7, 0xb50: 0x184f, 0xb51: 0x06b7,
+ 0xb52: 0x1854, 0xb53: 0x1859, 0xb54: 0x185e, 0xb55: 0x15db, 0xb56: 0x06bb, 0xb57: 0x15ef,
+ 0xb58: 0x15f7, 0xb59: 0x15fb, 0xb5a: 0x1603, 0xb5b: 0x160b, 0xb5c: 0x1613, 0xb5d: 0x1868,
+}
+
+// nfcIndex: 22 blocks, 1408 entries, 1408 bytes
+// Block 0 is the zero block.
+var nfcIndex = [1408]uint8{
+ // Block 0x0, offset 0x0
+ // Block 0x1, offset 0x40
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc2: 0x2c, 0xc3: 0x01, 0xc4: 0x02, 0xc5: 0x03, 0xc6: 0x2d, 0xc7: 0x04,
+ 0xc8: 0x05, 0xca: 0x2e, 0xcb: 0x2f, 0xcc: 0x06, 0xcd: 0x07, 0xce: 0x08, 0xcf: 0x30,
+ 0xd0: 0x09, 0xd1: 0x31, 0xd2: 0x32, 0xd3: 0x0a, 0xd6: 0x0b, 0xd7: 0x33,
+ 0xd8: 0x34, 0xd9: 0x0c, 0xdb: 0x35, 0xdc: 0x36, 0xdd: 0x37, 0xdf: 0x38,
+ 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05,
+ 0xea: 0x06, 0xeb: 0x07, 0xec: 0x08, 0xed: 0x09, 0xef: 0x0a,
+ 0xf0: 0x13,
+ // Block 0x4, offset 0x100
+ 0x120: 0x39, 0x121: 0x3a, 0x123: 0x3b, 0x124: 0x3c, 0x125: 0x3d, 0x126: 0x3e, 0x127: 0x3f,
+ 0x128: 0x40, 0x129: 0x41, 0x12a: 0x42, 0x12b: 0x43, 0x12c: 0x3e, 0x12d: 0x44, 0x12e: 0x45, 0x12f: 0x46,
+ 0x131: 0x47, 0x132: 0x48, 0x133: 0x49, 0x134: 0x4a, 0x135: 0x4b, 0x137: 0x4c,
+ 0x138: 0x4d, 0x139: 0x4e, 0x13a: 0x4f, 0x13b: 0x50, 0x13c: 0x51, 0x13d: 0x52, 0x13e: 0x53, 0x13f: 0x54,
+ // Block 0x5, offset 0x140
+ 0x140: 0x55, 0x142: 0x56, 0x144: 0x57, 0x145: 0x58, 0x146: 0x59, 0x147: 0x5a,
+ 0x14d: 0x5b,
+ 0x15c: 0x5c, 0x15f: 0x5d,
+ 0x162: 0x5e, 0x164: 0x5f,
+ 0x168: 0x60, 0x169: 0x61, 0x16a: 0x62, 0x16c: 0x0d, 0x16d: 0x63, 0x16e: 0x64, 0x16f: 0x65,
+ 0x170: 0x66, 0x173: 0x67, 0x177: 0x68,
+ 0x178: 0x0e, 0x179: 0x0f, 0x17a: 0x10, 0x17b: 0x11, 0x17c: 0x12, 0x17d: 0x13, 0x17e: 0x14, 0x17f: 0x15,
+ // Block 0x6, offset 0x180
+ 0x180: 0x69, 0x183: 0x6a, 0x184: 0x6b, 0x186: 0x6c, 0x187: 0x6d,
+ 0x188: 0x6e, 0x189: 0x16, 0x18a: 0x17, 0x18b: 0x6f, 0x18c: 0x70,
+ 0x1ab: 0x71,
+ 0x1b3: 0x72, 0x1b5: 0x73, 0x1b7: 0x74,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x75, 0x1c1: 0x18, 0x1c2: 0x19, 0x1c3: 0x1a, 0x1c4: 0x76, 0x1c5: 0x77,
+ 0x1c9: 0x78, 0x1cc: 0x79, 0x1cd: 0x7a,
+ // Block 0x8, offset 0x200
+ 0x219: 0x7b, 0x21a: 0x7c, 0x21b: 0x7d,
+ 0x220: 0x7e, 0x223: 0x7f, 0x224: 0x80, 0x225: 0x81, 0x226: 0x82, 0x227: 0x83,
+ 0x22a: 0x84, 0x22b: 0x85, 0x22f: 0x86,
+ 0x230: 0x87, 0x231: 0x88, 0x232: 0x89, 0x233: 0x8a, 0x234: 0x8b, 0x235: 0x8c, 0x236: 0x8d, 0x237: 0x87,
+ 0x238: 0x88, 0x239: 0x89, 0x23a: 0x8a, 0x23b: 0x8b, 0x23c: 0x8c, 0x23d: 0x8d, 0x23e: 0x87, 0x23f: 0x88,
+ // Block 0x9, offset 0x240
+ 0x240: 0x89, 0x241: 0x8a, 0x242: 0x8b, 0x243: 0x8c, 0x244: 0x8d, 0x245: 0x87, 0x246: 0x88, 0x247: 0x89,
+ 0x248: 0x8a, 0x249: 0x8b, 0x24a: 0x8c, 0x24b: 0x8d, 0x24c: 0x87, 0x24d: 0x88, 0x24e: 0x89, 0x24f: 0x8a,
+ 0x250: 0x8b, 0x251: 0x8c, 0x252: 0x8d, 0x253: 0x87, 0x254: 0x88, 0x255: 0x89, 0x256: 0x8a, 0x257: 0x8b,
+ 0x258: 0x8c, 0x259: 0x8d, 0x25a: 0x87, 0x25b: 0x88, 0x25c: 0x89, 0x25d: 0x8a, 0x25e: 0x8b, 0x25f: 0x8c,
+ 0x260: 0x8d, 0x261: 0x87, 0x262: 0x88, 0x263: 0x89, 0x264: 0x8a, 0x265: 0x8b, 0x266: 0x8c, 0x267: 0x8d,
+ 0x268: 0x87, 0x269: 0x88, 0x26a: 0x89, 0x26b: 0x8a, 0x26c: 0x8b, 0x26d: 0x8c, 0x26e: 0x8d, 0x26f: 0x87,
+ 0x270: 0x88, 0x271: 0x89, 0x272: 0x8a, 0x273: 0x8b, 0x274: 0x8c, 0x275: 0x8d, 0x276: 0x87, 0x277: 0x88,
+ 0x278: 0x89, 0x279: 0x8a, 0x27a: 0x8b, 0x27b: 0x8c, 0x27c: 0x8d, 0x27d: 0x87, 0x27e: 0x88, 0x27f: 0x89,
+ // Block 0xa, offset 0x280
+ 0x280: 0x8a, 0x281: 0x8b, 0x282: 0x8c, 0x283: 0x8d, 0x284: 0x87, 0x285: 0x88, 0x286: 0x89, 0x287: 0x8a,
+ 0x288: 0x8b, 0x289: 0x8c, 0x28a: 0x8d, 0x28b: 0x87, 0x28c: 0x88, 0x28d: 0x89, 0x28e: 0x8a, 0x28f: 0x8b,
+ 0x290: 0x8c, 0x291: 0x8d, 0x292: 0x87, 0x293: 0x88, 0x294: 0x89, 0x295: 0x8a, 0x296: 0x8b, 0x297: 0x8c,
+ 0x298: 0x8d, 0x299: 0x87, 0x29a: 0x88, 0x29b: 0x89, 0x29c: 0x8a, 0x29d: 0x8b, 0x29e: 0x8c, 0x29f: 0x8d,
+ 0x2a0: 0x87, 0x2a1: 0x88, 0x2a2: 0x89, 0x2a3: 0x8a, 0x2a4: 0x8b, 0x2a5: 0x8c, 0x2a6: 0x8d, 0x2a7: 0x87,
+ 0x2a8: 0x88, 0x2a9: 0x89, 0x2aa: 0x8a, 0x2ab: 0x8b, 0x2ac: 0x8c, 0x2ad: 0x8d, 0x2ae: 0x87, 0x2af: 0x88,
+ 0x2b0: 0x89, 0x2b1: 0x8a, 0x2b2: 0x8b, 0x2b3: 0x8c, 0x2b4: 0x8d, 0x2b5: 0x87, 0x2b6: 0x88, 0x2b7: 0x89,
+ 0x2b8: 0x8a, 0x2b9: 0x8b, 0x2ba: 0x8c, 0x2bb: 0x8d, 0x2bc: 0x87, 0x2bd: 0x88, 0x2be: 0x89, 0x2bf: 0x8a,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0x8b, 0x2c1: 0x8c, 0x2c2: 0x8d, 0x2c3: 0x87, 0x2c4: 0x88, 0x2c5: 0x89, 0x2c6: 0x8a, 0x2c7: 0x8b,
+ 0x2c8: 0x8c, 0x2c9: 0x8d, 0x2ca: 0x87, 0x2cb: 0x88, 0x2cc: 0x89, 0x2cd: 0x8a, 0x2ce: 0x8b, 0x2cf: 0x8c,
+ 0x2d0: 0x8d, 0x2d1: 0x87, 0x2d2: 0x88, 0x2d3: 0x89, 0x2d4: 0x8a, 0x2d5: 0x8b, 0x2d6: 0x8c, 0x2d7: 0x8d,
+ 0x2d8: 0x87, 0x2d9: 0x88, 0x2da: 0x89, 0x2db: 0x8a, 0x2dc: 0x8b, 0x2dd: 0x8c, 0x2de: 0x8e,
+ // Block 0xc, offset 0x300
+ 0x324: 0x1b, 0x325: 0x1c, 0x326: 0x1d, 0x327: 0x1e,
+ 0x328: 0x1f, 0x329: 0x20, 0x32a: 0x21, 0x32b: 0x22, 0x32c: 0x8f, 0x32d: 0x90, 0x32e: 0x91,
+ 0x331: 0x92, 0x332: 0x93, 0x333: 0x94, 0x334: 0x95,
+ 0x338: 0x96, 0x339: 0x97, 0x33a: 0x98, 0x33b: 0x99, 0x33e: 0x9a, 0x33f: 0x9b,
+ // Block 0xd, offset 0x340
+ 0x347: 0x9c,
+ 0x34b: 0x9d, 0x34d: 0x9e,
+ 0x368: 0x9f, 0x36b: 0xa0,
+ // Block 0xe, offset 0x380
+ 0x381: 0xa1, 0x382: 0xa2, 0x384: 0xa3, 0x385: 0x82, 0x387: 0xa4,
+ 0x388: 0xa5, 0x38b: 0xa6, 0x38c: 0x3e, 0x38d: 0xa7,
+ 0x391: 0xa8, 0x392: 0xa9, 0x393: 0xaa, 0x396: 0xab, 0x397: 0xac,
+ 0x398: 0x73, 0x39a: 0xad, 0x39c: 0xae,
+ 0x3b0: 0x73,
+ // Block 0xf, offset 0x3c0
+ 0x3eb: 0xaf, 0x3ec: 0xb0,
+ // Block 0x10, offset 0x400
+ 0x432: 0xb1,
+ // Block 0x11, offset 0x440
+ 0x445: 0xb2, 0x446: 0xb3, 0x447: 0xb4,
+ 0x449: 0xb5,
+ // Block 0x12, offset 0x480
+ 0x480: 0xb6,
+ 0x4a3: 0xb7, 0x4a5: 0xb8,
+ // Block 0x13, offset 0x4c0
+ 0x4c8: 0xb9,
+ // Block 0x14, offset 0x500
+ 0x520: 0x23, 0x521: 0x24, 0x522: 0x25, 0x523: 0x26, 0x524: 0x27, 0x525: 0x28, 0x526: 0x29, 0x527: 0x2a,
+ 0x528: 0x2b,
+ // Block 0x15, offset 0x540
+ 0x550: 0x0b, 0x551: 0x0c, 0x556: 0x0d,
+ 0x55b: 0x0e, 0x55d: 0x0f, 0x55e: 0x10, 0x55f: 0x11,
+ 0x56f: 0x12,
+}
+
+// nfcSparseOffset: 142 entries, 284 bytes
+var nfcSparseOffset = []uint16{0x0, 0x5, 0x9, 0xb, 0xd, 0x18, 0x28, 0x2a, 0x2f, 0x3a, 0x49, 0x56, 0x5e, 0x62, 0x67, 0x69, 0x7a, 0x82, 0x89, 0x8c, 0x93, 0x97, 0x9b, 0x9d, 0x9f, 0xa8, 0xac, 0xb3, 0xb8, 0xbb, 0xc5, 0xc7, 0xce, 0xd6, 0xd9, 0xdb, 0xdd, 0xdf, 0xe4, 0xf5, 0x101, 0x103, 0x109, 0x10b, 0x10d, 0x10f, 0x111, 0x113, 0x115, 0x118, 0x11b, 0x11d, 0x120, 0x123, 0x127, 0x12c, 0x135, 0x137, 0x13a, 0x13c, 0x147, 0x157, 0x15b, 0x169, 0x16c, 0x172, 0x178, 0x183, 0x187, 0x189, 0x18b, 0x18d, 0x18f, 0x191, 0x197, 0x19b, 0x19d, 0x19f, 0x1a7, 0x1ab, 0x1ae, 0x1b0, 0x1b2, 0x1b4, 0x1b7, 0x1b9, 0x1bb, 0x1bd, 0x1bf, 0x1c5, 0x1c8, 0x1ca, 0x1d1, 0x1d7, 0x1dd, 0x1e5, 0x1eb, 0x1f1, 0x1f7, 0x1fb, 0x209, 0x212, 0x215, 0x218, 0x21a, 0x21d, 0x21f, 0x223, 0x228, 0x22a, 0x22c, 0x231, 0x237, 0x239, 0x23b, 0x23d, 0x243, 0x246, 0x249, 0x251, 0x258, 0x25b, 0x25e, 0x260, 0x268, 0x26b, 0x272, 0x275, 0x27b, 0x27d, 0x280, 0x282, 0x284, 0x286, 0x288, 0x295, 0x29f, 0x2a1, 0x2a3, 0x2a9, 0x2ab, 0x2ae}
+
+// nfcSparseValues: 688 entries, 2752 bytes
+var nfcSparseValues = [688]valueRange{
+ // Block 0x0, offset 0x0
+ {value: 0x0000, lo: 0x04},
+ {value: 0xa100, lo: 0xa8, hi: 0xa8},
+ {value: 0x8100, lo: 0xaf, hi: 0xaf},
+ {value: 0x8100, lo: 0xb4, hi: 0xb4},
+ {value: 0x8100, lo: 0xb8, hi: 0xb8},
+ // Block 0x1, offset 0x5
+ {value: 0x0091, lo: 0x03},
+ {value: 0x46e2, lo: 0xa0, hi: 0xa1},
+ {value: 0x4714, lo: 0xaf, hi: 0xb0},
+ {value: 0xa000, lo: 0xb7, hi: 0xb7},
+ // Block 0x2, offset 0x9
+ {value: 0x0000, lo: 0x01},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ // Block 0x3, offset 0xb
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0x98, hi: 0x9d},
+ // Block 0x4, offset 0xd
+ {value: 0x0006, lo: 0x0a},
+ {value: 0xa000, lo: 0x81, hi: 0x81},
+ {value: 0xa000, lo: 0x85, hi: 0x85},
+ {value: 0xa000, lo: 0x89, hi: 0x89},
+ {value: 0x4840, lo: 0x8a, hi: 0x8a},
+ {value: 0x485e, lo: 0x8b, hi: 0x8b},
+ {value: 0x36c7, lo: 0x8c, hi: 0x8c},
+ {value: 0x36df, lo: 0x8d, hi: 0x8d},
+ {value: 0x4876, lo: 0x8e, hi: 0x8e},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x36fd, lo: 0x93, hi: 0x94},
+ // Block 0x5, offset 0x18
+ {value: 0x0000, lo: 0x0f},
+ {value: 0xa000, lo: 0x83, hi: 0x83},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0xa000, lo: 0x8b, hi: 0x8b},
+ {value: 0xa000, lo: 0x8d, hi: 0x8d},
+ {value: 0x37a5, lo: 0x90, hi: 0x90},
+ {value: 0x37b1, lo: 0x91, hi: 0x91},
+ {value: 0x379f, lo: 0x93, hi: 0x93},
+ {value: 0xa000, lo: 0x96, hi: 0x96},
+ {value: 0x3817, lo: 0x97, hi: 0x97},
+ {value: 0x37e1, lo: 0x9c, hi: 0x9c},
+ {value: 0x37c9, lo: 0x9d, hi: 0x9d},
+ {value: 0x37f3, lo: 0x9e, hi: 0x9e},
+ {value: 0xa000, lo: 0xb4, hi: 0xb5},
+ {value: 0x381d, lo: 0xb6, hi: 0xb6},
+ {value: 0x3823, lo: 0xb7, hi: 0xb7},
+ // Block 0x6, offset 0x28
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x83, hi: 0x87},
+ // Block 0x7, offset 0x2a
+ {value: 0x0001, lo: 0x04},
+ {value: 0x8113, lo: 0x81, hi: 0x82},
+ {value: 0x8132, lo: 0x84, hi: 0x84},
+ {value: 0x812d, lo: 0x85, hi: 0x85},
+ {value: 0x810d, lo: 0x87, hi: 0x87},
+ // Block 0x8, offset 0x2f
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x8132, lo: 0x90, hi: 0x97},
+ {value: 0x8119, lo: 0x98, hi: 0x98},
+ {value: 0x811a, lo: 0x99, hi: 0x99},
+ {value: 0x811b, lo: 0x9a, hi: 0x9a},
+ {value: 0x3841, lo: 0xa2, hi: 0xa2},
+ {value: 0x3847, lo: 0xa3, hi: 0xa3},
+ {value: 0x3853, lo: 0xa4, hi: 0xa4},
+ {value: 0x384d, lo: 0xa5, hi: 0xa5},
+ {value: 0x3859, lo: 0xa6, hi: 0xa6},
+ {value: 0xa000, lo: 0xa7, hi: 0xa7},
+ // Block 0x9, offset 0x3a
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x386b, lo: 0x80, hi: 0x80},
+ {value: 0xa000, lo: 0x81, hi: 0x81},
+ {value: 0x385f, lo: 0x82, hi: 0x82},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x3865, lo: 0x93, hi: 0x93},
+ {value: 0xa000, lo: 0x95, hi: 0x95},
+ {value: 0x8132, lo: 0x96, hi: 0x9c},
+ {value: 0x8132, lo: 0x9f, hi: 0xa2},
+ {value: 0x812d, lo: 0xa3, hi: 0xa3},
+ {value: 0x8132, lo: 0xa4, hi: 0xa4},
+ {value: 0x8132, lo: 0xa7, hi: 0xa8},
+ {value: 0x812d, lo: 0xaa, hi: 0xaa},
+ {value: 0x8132, lo: 0xab, hi: 0xac},
+ {value: 0x812d, lo: 0xad, hi: 0xad},
+ // Block 0xa, offset 0x49
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x811f, lo: 0x91, hi: 0x91},
+ {value: 0x8132, lo: 0xb0, hi: 0xb0},
+ {value: 0x812d, lo: 0xb1, hi: 0xb1},
+ {value: 0x8132, lo: 0xb2, hi: 0xb3},
+ {value: 0x812d, lo: 0xb4, hi: 0xb4},
+ {value: 0x8132, lo: 0xb5, hi: 0xb6},
+ {value: 0x812d, lo: 0xb7, hi: 0xb9},
+ {value: 0x8132, lo: 0xba, hi: 0xba},
+ {value: 0x812d, lo: 0xbb, hi: 0xbc},
+ {value: 0x8132, lo: 0xbd, hi: 0xbd},
+ {value: 0x812d, lo: 0xbe, hi: 0xbe},
+ {value: 0x8132, lo: 0xbf, hi: 0xbf},
+ // Block 0xb, offset 0x56
+ {value: 0x0005, lo: 0x07},
+ {value: 0x8132, lo: 0x80, hi: 0x80},
+ {value: 0x8132, lo: 0x81, hi: 0x81},
+ {value: 0x812d, lo: 0x82, hi: 0x83},
+ {value: 0x812d, lo: 0x84, hi: 0x85},
+ {value: 0x812d, lo: 0x86, hi: 0x87},
+ {value: 0x812d, lo: 0x88, hi: 0x89},
+ {value: 0x8132, lo: 0x8a, hi: 0x8a},
+ // Block 0xc, offset 0x5e
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8132, lo: 0xab, hi: 0xb1},
+ {value: 0x812d, lo: 0xb2, hi: 0xb2},
+ {value: 0x8132, lo: 0xb3, hi: 0xb3},
+ // Block 0xd, offset 0x62
+ {value: 0x0000, lo: 0x04},
+ {value: 0x8132, lo: 0x96, hi: 0x99},
+ {value: 0x8132, lo: 0x9b, hi: 0xa3},
+ {value: 0x8132, lo: 0xa5, hi: 0xa7},
+ {value: 0x8132, lo: 0xa9, hi: 0xad},
+ // Block 0xe, offset 0x67
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x99, hi: 0x9b},
+ // Block 0xf, offset 0x69
+ {value: 0x0000, lo: 0x10},
+ {value: 0x8132, lo: 0x94, hi: 0xa1},
+ {value: 0x812d, lo: 0xa3, hi: 0xa3},
+ {value: 0x8132, lo: 0xa4, hi: 0xa5},
+ {value: 0x812d, lo: 0xa6, hi: 0xa6},
+ {value: 0x8132, lo: 0xa7, hi: 0xa8},
+ {value: 0x812d, lo: 0xa9, hi: 0xa9},
+ {value: 0x8132, lo: 0xaa, hi: 0xac},
+ {value: 0x812d, lo: 0xad, hi: 0xaf},
+ {value: 0x8116, lo: 0xb0, hi: 0xb0},
+ {value: 0x8117, lo: 0xb1, hi: 0xb1},
+ {value: 0x8118, lo: 0xb2, hi: 0xb2},
+ {value: 0x8132, lo: 0xb3, hi: 0xb5},
+ {value: 0x812d, lo: 0xb6, hi: 0xb6},
+ {value: 0x8132, lo: 0xb7, hi: 0xb8},
+ {value: 0x812d, lo: 0xb9, hi: 0xba},
+ {value: 0x8132, lo: 0xbb, hi: 0xbf},
+ // Block 0x10, offset 0x7a
+ {value: 0x0000, lo: 0x07},
+ {value: 0xa000, lo: 0xa8, hi: 0xa8},
+ {value: 0x3ed8, lo: 0xa9, hi: 0xa9},
+ {value: 0xa000, lo: 0xb0, hi: 0xb0},
+ {value: 0x3ee0, lo: 0xb1, hi: 0xb1},
+ {value: 0xa000, lo: 0xb3, hi: 0xb3},
+ {value: 0x3ee8, lo: 0xb4, hi: 0xb4},
+ {value: 0x9902, lo: 0xbc, hi: 0xbc},
+ // Block 0x11, offset 0x82
+ {value: 0x0008, lo: 0x06},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x8132, lo: 0x91, hi: 0x91},
+ {value: 0x812d, lo: 0x92, hi: 0x92},
+ {value: 0x8132, lo: 0x93, hi: 0x93},
+ {value: 0x8132, lo: 0x94, hi: 0x94},
+ {value: 0x451c, lo: 0x98, hi: 0x9f},
+ // Block 0x12, offset 0x89
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x13, offset 0x8c
+ {value: 0x0008, lo: 0x06},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2c9e, lo: 0x8b, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ {value: 0x455c, lo: 0x9c, hi: 0x9d},
+ {value: 0x456c, lo: 0x9f, hi: 0x9f},
+ // Block 0x14, offset 0x93
+ {value: 0x0000, lo: 0x03},
+ {value: 0x4594, lo: 0xb3, hi: 0xb3},
+ {value: 0x459c, lo: 0xb6, hi: 0xb6},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ // Block 0x15, offset 0x97
+ {value: 0x0008, lo: 0x03},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x4574, lo: 0x99, hi: 0x9b},
+ {value: 0x458c, lo: 0x9e, hi: 0x9e},
+ // Block 0x16, offset 0x9b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ // Block 0x17, offset 0x9d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ // Block 0x18, offset 0x9f
+ {value: 0x0000, lo: 0x08},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2cb6, lo: 0x88, hi: 0x88},
+ {value: 0x2cae, lo: 0x8b, hi: 0x8b},
+ {value: 0x2cbe, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x96, hi: 0x97},
+ {value: 0x45a4, lo: 0x9c, hi: 0x9c},
+ {value: 0x45ac, lo: 0x9d, hi: 0x9d},
+ // Block 0x19, offset 0xa8
+ {value: 0x0000, lo: 0x03},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x2cc6, lo: 0x94, hi: 0x94},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x1a, offset 0xac
+ {value: 0x0000, lo: 0x06},
+ {value: 0xa000, lo: 0x86, hi: 0x87},
+ {value: 0x2cce, lo: 0x8a, hi: 0x8a},
+ {value: 0x2cde, lo: 0x8b, hi: 0x8b},
+ {value: 0x2cd6, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ // Block 0x1b, offset 0xb3
+ {value: 0x1801, lo: 0x04},
+ {value: 0xa000, lo: 0x86, hi: 0x86},
+ {value: 0x3ef0, lo: 0x88, hi: 0x88},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x8120, lo: 0x95, hi: 0x96},
+ // Block 0x1c, offset 0xb8
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ {value: 0xa000, lo: 0xbf, hi: 0xbf},
+ // Block 0x1d, offset 0xbb
+ {value: 0x0000, lo: 0x09},
+ {value: 0x2ce6, lo: 0x80, hi: 0x80},
+ {value: 0x9900, lo: 0x82, hi: 0x82},
+ {value: 0xa000, lo: 0x86, hi: 0x86},
+ {value: 0x2cee, lo: 0x87, hi: 0x87},
+ {value: 0x2cf6, lo: 0x88, hi: 0x88},
+ {value: 0x2f50, lo: 0x8a, hi: 0x8a},
+ {value: 0x2dd8, lo: 0x8b, hi: 0x8b},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x95, hi: 0x96},
+ // Block 0x1e, offset 0xc5
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x1f, offset 0xc7
+ {value: 0x0000, lo: 0x06},
+ {value: 0xa000, lo: 0x86, hi: 0x87},
+ {value: 0x2cfe, lo: 0x8a, hi: 0x8a},
+ {value: 0x2d0e, lo: 0x8b, hi: 0x8b},
+ {value: 0x2d06, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ // Block 0x20, offset 0xce
+ {value: 0x6bea, lo: 0x07},
+ {value: 0x9904, lo: 0x8a, hi: 0x8a},
+ {value: 0x9900, lo: 0x8f, hi: 0x8f},
+ {value: 0xa000, lo: 0x99, hi: 0x99},
+ {value: 0x3ef8, lo: 0x9a, hi: 0x9a},
+ {value: 0x2f58, lo: 0x9c, hi: 0x9c},
+ {value: 0x2de3, lo: 0x9d, hi: 0x9d},
+ {value: 0x2d16, lo: 0x9e, hi: 0x9f},
+ // Block 0x21, offset 0xd6
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8122, lo: 0xb8, hi: 0xb9},
+ {value: 0x8104, lo: 0xba, hi: 0xba},
+ // Block 0x22, offset 0xd9
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8123, lo: 0x88, hi: 0x8b},
+ // Block 0x23, offset 0xdb
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8124, lo: 0xb8, hi: 0xb9},
+ // Block 0x24, offset 0xdd
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8125, lo: 0x88, hi: 0x8b},
+ // Block 0x25, offset 0xdf
+ {value: 0x0000, lo: 0x04},
+ {value: 0x812d, lo: 0x98, hi: 0x99},
+ {value: 0x812d, lo: 0xb5, hi: 0xb5},
+ {value: 0x812d, lo: 0xb7, hi: 0xb7},
+ {value: 0x812b, lo: 0xb9, hi: 0xb9},
+ // Block 0x26, offset 0xe4
+ {value: 0x0000, lo: 0x10},
+ {value: 0x2644, lo: 0x83, hi: 0x83},
+ {value: 0x264b, lo: 0x8d, hi: 0x8d},
+ {value: 0x2652, lo: 0x92, hi: 0x92},
+ {value: 0x2659, lo: 0x97, hi: 0x97},
+ {value: 0x2660, lo: 0x9c, hi: 0x9c},
+ {value: 0x263d, lo: 0xa9, hi: 0xa9},
+ {value: 0x8126, lo: 0xb1, hi: 0xb1},
+ {value: 0x8127, lo: 0xb2, hi: 0xb2},
+ {value: 0x4a84, lo: 0xb3, hi: 0xb3},
+ {value: 0x8128, lo: 0xb4, hi: 0xb4},
+ {value: 0x4a8d, lo: 0xb5, hi: 0xb5},
+ {value: 0x45b4, lo: 0xb6, hi: 0xb6},
+ {value: 0x8200, lo: 0xb7, hi: 0xb7},
+ {value: 0x45bc, lo: 0xb8, hi: 0xb8},
+ {value: 0x8200, lo: 0xb9, hi: 0xb9},
+ {value: 0x8127, lo: 0xba, hi: 0xbd},
+ // Block 0x27, offset 0xf5
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x8127, lo: 0x80, hi: 0x80},
+ {value: 0x4a96, lo: 0x81, hi: 0x81},
+ {value: 0x8132, lo: 0x82, hi: 0x83},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0x86, hi: 0x87},
+ {value: 0x266e, lo: 0x93, hi: 0x93},
+ {value: 0x2675, lo: 0x9d, hi: 0x9d},
+ {value: 0x267c, lo: 0xa2, hi: 0xa2},
+ {value: 0x2683, lo: 0xa7, hi: 0xa7},
+ {value: 0x268a, lo: 0xac, hi: 0xac},
+ {value: 0x2667, lo: 0xb9, hi: 0xb9},
+ // Block 0x28, offset 0x101
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x86, hi: 0x86},
+ // Block 0x29, offset 0x103
+ {value: 0x0000, lo: 0x05},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x2d1e, lo: 0xa6, hi: 0xa6},
+ {value: 0x9900, lo: 0xae, hi: 0xae},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ {value: 0x8104, lo: 0xb9, hi: 0xba},
+ // Block 0x2a, offset 0x109
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x8d, hi: 0x8d},
+ // Block 0x2b, offset 0x10b
+ {value: 0x0000, lo: 0x01},
+ {value: 0xa000, lo: 0x80, hi: 0x92},
+ // Block 0x2c, offset 0x10d
+ {value: 0x0000, lo: 0x01},
+ {value: 0xb900, lo: 0xa1, hi: 0xb5},
+ // Block 0x2d, offset 0x10f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0xa8, hi: 0xbf},
+ // Block 0x2e, offset 0x111
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0x80, hi: 0x82},
+ // Block 0x2f, offset 0x113
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x9d, hi: 0x9f},
+ // Block 0x30, offset 0x115
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x94, hi: 0x94},
+ {value: 0x8104, lo: 0xb4, hi: 0xb4},
+ // Block 0x31, offset 0x118
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x92, hi: 0x92},
+ {value: 0x8132, lo: 0x9d, hi: 0x9d},
+ // Block 0x32, offset 0x11b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8131, lo: 0xa9, hi: 0xa9},
+ // Block 0x33, offset 0x11d
+ {value: 0x0004, lo: 0x02},
+ {value: 0x812e, lo: 0xb9, hi: 0xba},
+ {value: 0x812d, lo: 0xbb, hi: 0xbb},
+ // Block 0x34, offset 0x120
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x97, hi: 0x97},
+ {value: 0x812d, lo: 0x98, hi: 0x98},
+ // Block 0x35, offset 0x123
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8104, lo: 0xa0, hi: 0xa0},
+ {value: 0x8132, lo: 0xb5, hi: 0xbc},
+ {value: 0x812d, lo: 0xbf, hi: 0xbf},
+ // Block 0x36, offset 0x127
+ {value: 0x0000, lo: 0x04},
+ {value: 0x8132, lo: 0xb0, hi: 0xb4},
+ {value: 0x812d, lo: 0xb5, hi: 0xba},
+ {value: 0x8132, lo: 0xbb, hi: 0xbc},
+ {value: 0x812d, lo: 0xbd, hi: 0xbd},
+ // Block 0x37, offset 0x12c
+ {value: 0x0000, lo: 0x08},
+ {value: 0x2d66, lo: 0x80, hi: 0x80},
+ {value: 0x2d6e, lo: 0x81, hi: 0x81},
+ {value: 0xa000, lo: 0x82, hi: 0x82},
+ {value: 0x2d76, lo: 0x83, hi: 0x83},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0xab, hi: 0xab},
+ {value: 0x812d, lo: 0xac, hi: 0xac},
+ {value: 0x8132, lo: 0xad, hi: 0xb3},
+ // Block 0x38, offset 0x135
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xaa, hi: 0xab},
+ // Block 0x39, offset 0x137
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xa6, hi: 0xa6},
+ {value: 0x8104, lo: 0xb2, hi: 0xb3},
+ // Block 0x3a, offset 0x13a
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ // Block 0x3b, offset 0x13c
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x8132, lo: 0x90, hi: 0x92},
+ {value: 0x8101, lo: 0x94, hi: 0x94},
+ {value: 0x812d, lo: 0x95, hi: 0x99},
+ {value: 0x8132, lo: 0x9a, hi: 0x9b},
+ {value: 0x812d, lo: 0x9c, hi: 0x9f},
+ {value: 0x8132, lo: 0xa0, hi: 0xa0},
+ {value: 0x8101, lo: 0xa2, hi: 0xa8},
+ {value: 0x812d, lo: 0xad, hi: 0xad},
+ {value: 0x8132, lo: 0xb4, hi: 0xb4},
+ {value: 0x8132, lo: 0xb8, hi: 0xb9},
+ // Block 0x3c, offset 0x147
+ {value: 0x0000, lo: 0x0f},
+ {value: 0x8132, lo: 0x80, hi: 0x81},
+ {value: 0x812d, lo: 0x82, hi: 0x82},
+ {value: 0x8132, lo: 0x83, hi: 0x89},
+ {value: 0x812d, lo: 0x8a, hi: 0x8a},
+ {value: 0x8132, lo: 0x8b, hi: 0x8c},
+ {value: 0x8135, lo: 0x8d, hi: 0x8d},
+ {value: 0x812a, lo: 0x8e, hi: 0x8e},
+ {value: 0x812d, lo: 0x8f, hi: 0x8f},
+ {value: 0x8129, lo: 0x90, hi: 0x90},
+ {value: 0x8132, lo: 0x91, hi: 0xb5},
+ {value: 0x8132, lo: 0xbb, hi: 0xbb},
+ {value: 0x8134, lo: 0xbc, hi: 0xbc},
+ {value: 0x812d, lo: 0xbd, hi: 0xbd},
+ {value: 0x8132, lo: 0xbe, hi: 0xbe},
+ {value: 0x812d, lo: 0xbf, hi: 0xbf},
+ // Block 0x3d, offset 0x157
+ {value: 0x0004, lo: 0x03},
+ {value: 0x0433, lo: 0x80, hi: 0x81},
+ {value: 0x8100, lo: 0x97, hi: 0x97},
+ {value: 0x8100, lo: 0xbe, hi: 0xbe},
+ // Block 0x3e, offset 0x15b
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x8132, lo: 0x90, hi: 0x91},
+ {value: 0x8101, lo: 0x92, hi: 0x93},
+ {value: 0x8132, lo: 0x94, hi: 0x97},
+ {value: 0x8101, lo: 0x98, hi: 0x9a},
+ {value: 0x8132, lo: 0x9b, hi: 0x9c},
+ {value: 0x8132, lo: 0xa1, hi: 0xa1},
+ {value: 0x8101, lo: 0xa5, hi: 0xa6},
+ {value: 0x8132, lo: 0xa7, hi: 0xa7},
+ {value: 0x812d, lo: 0xa8, hi: 0xa8},
+ {value: 0x8132, lo: 0xa9, hi: 0xa9},
+ {value: 0x8101, lo: 0xaa, hi: 0xab},
+ {value: 0x812d, lo: 0xac, hi: 0xaf},
+ {value: 0x8132, lo: 0xb0, hi: 0xb0},
+ // Block 0x3f, offset 0x169
+ {value: 0x427b, lo: 0x02},
+ {value: 0x01b8, lo: 0xa6, hi: 0xa6},
+ {value: 0x0057, lo: 0xaa, hi: 0xab},
+ // Block 0x40, offset 0x16c
+ {value: 0x0007, lo: 0x05},
+ {value: 0xa000, lo: 0x90, hi: 0x90},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0xa000, lo: 0x94, hi: 0x94},
+ {value: 0x3bb9, lo: 0x9a, hi: 0x9b},
+ {value: 0x3bc7, lo: 0xae, hi: 0xae},
+ // Block 0x41, offset 0x172
+ {value: 0x000e, lo: 0x05},
+ {value: 0x3bce, lo: 0x8d, hi: 0x8e},
+ {value: 0x3bd5, lo: 0x8f, hi: 0x8f},
+ {value: 0xa000, lo: 0x90, hi: 0x90},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0xa000, lo: 0x94, hi: 0x94},
+ // Block 0x42, offset 0x178
+ {value: 0x6408, lo: 0x0a},
+ {value: 0xa000, lo: 0x83, hi: 0x83},
+ {value: 0x3be3, lo: 0x84, hi: 0x84},
+ {value: 0xa000, lo: 0x88, hi: 0x88},
+ {value: 0x3bea, lo: 0x89, hi: 0x89},
+ {value: 0xa000, lo: 0x8b, hi: 0x8b},
+ {value: 0x3bf1, lo: 0x8c, hi: 0x8c},
+ {value: 0xa000, lo: 0xa3, hi: 0xa3},
+ {value: 0x3bf8, lo: 0xa4, hi: 0xa5},
+ {value: 0x3bff, lo: 0xa6, hi: 0xa6},
+ {value: 0xa000, lo: 0xbc, hi: 0xbc},
+ // Block 0x43, offset 0x183
+ {value: 0x0007, lo: 0x03},
+ {value: 0x3c68, lo: 0xa0, hi: 0xa1},
+ {value: 0x3c92, lo: 0xa2, hi: 0xa3},
+ {value: 0x3cbc, lo: 0xaa, hi: 0xad},
+ // Block 0x44, offset 0x187
+ {value: 0x0004, lo: 0x01},
+ {value: 0x048b, lo: 0xa9, hi: 0xaa},
+ // Block 0x45, offset 0x189
+ {value: 0x0000, lo: 0x01},
+ {value: 0x44dd, lo: 0x9c, hi: 0x9c},
+ // Block 0x46, offset 0x18b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xaf, hi: 0xb1},
+ // Block 0x47, offset 0x18d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x48, offset 0x18f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xa0, hi: 0xbf},
+ // Block 0x49, offset 0x191
+ {value: 0x0000, lo: 0x05},
+ {value: 0x812c, lo: 0xaa, hi: 0xaa},
+ {value: 0x8131, lo: 0xab, hi: 0xab},
+ {value: 0x8133, lo: 0xac, hi: 0xac},
+ {value: 0x812e, lo: 0xad, hi: 0xad},
+ {value: 0x812f, lo: 0xae, hi: 0xaf},
+ // Block 0x4a, offset 0x197
+ {value: 0x0000, lo: 0x03},
+ {value: 0x4a9f, lo: 0xb3, hi: 0xb3},
+ {value: 0x4a9f, lo: 0xb5, hi: 0xb6},
+ {value: 0x4a9f, lo: 0xba, hi: 0xbf},
+ // Block 0x4b, offset 0x19b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x4a9f, lo: 0x8f, hi: 0xa3},
+ // Block 0x4c, offset 0x19d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0xae, hi: 0xbe},
+ // Block 0x4d, offset 0x19f
+ {value: 0x0000, lo: 0x07},
+ {value: 0x8100, lo: 0x84, hi: 0x84},
+ {value: 0x8100, lo: 0x87, hi: 0x87},
+ {value: 0x8100, lo: 0x90, hi: 0x90},
+ {value: 0x8100, lo: 0x9e, hi: 0x9e},
+ {value: 0x8100, lo: 0xa1, hi: 0xa1},
+ {value: 0x8100, lo: 0xb2, hi: 0xb2},
+ {value: 0x8100, lo: 0xbb, hi: 0xbb},
+ // Block 0x4e, offset 0x1a7
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8100, lo: 0x80, hi: 0x80},
+ {value: 0x8100, lo: 0x8b, hi: 0x8b},
+ {value: 0x8100, lo: 0x8e, hi: 0x8e},
+ // Block 0x4f, offset 0x1ab
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0xaf, hi: 0xaf},
+ {value: 0x8132, lo: 0xb4, hi: 0xbd},
+ // Block 0x50, offset 0x1ae
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x9e, hi: 0x9f},
+ // Block 0x51, offset 0x1b0
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb0, hi: 0xb1},
+ // Block 0x52, offset 0x1b2
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x86, hi: 0x86},
+ // Block 0x53, offset 0x1b4
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0xa0, hi: 0xb1},
+ // Block 0x54, offset 0x1b7
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xab, hi: 0xad},
+ // Block 0x55, offset 0x1b9
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x93, hi: 0x93},
+ // Block 0x56, offset 0x1bb
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xb3, hi: 0xb3},
+ // Block 0x57, offset 0x1bd
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x80, hi: 0x80},
+ // Block 0x58, offset 0x1bf
+ {value: 0x0000, lo: 0x05},
+ {value: 0x8132, lo: 0xb0, hi: 0xb0},
+ {value: 0x8132, lo: 0xb2, hi: 0xb3},
+ {value: 0x812d, lo: 0xb4, hi: 0xb4},
+ {value: 0x8132, lo: 0xb7, hi: 0xb8},
+ {value: 0x8132, lo: 0xbe, hi: 0xbf},
+ // Block 0x59, offset 0x1c5
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x81, hi: 0x81},
+ {value: 0x8104, lo: 0xb6, hi: 0xb6},
+ // Block 0x5a, offset 0x1c8
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xad, hi: 0xad},
+ // Block 0x5b, offset 0x1ca
+ {value: 0x0000, lo: 0x06},
+ {value: 0xe500, lo: 0x80, hi: 0x80},
+ {value: 0xc600, lo: 0x81, hi: 0x9b},
+ {value: 0xe500, lo: 0x9c, hi: 0x9c},
+ {value: 0xc600, lo: 0x9d, hi: 0xb7},
+ {value: 0xe500, lo: 0xb8, hi: 0xb8},
+ {value: 0xc600, lo: 0xb9, hi: 0xbf},
+ // Block 0x5c, offset 0x1d1
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x93},
+ {value: 0xe500, lo: 0x94, hi: 0x94},
+ {value: 0xc600, lo: 0x95, hi: 0xaf},
+ {value: 0xe500, lo: 0xb0, hi: 0xb0},
+ {value: 0xc600, lo: 0xb1, hi: 0xbf},
+ // Block 0x5d, offset 0x1d7
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x8b},
+ {value: 0xe500, lo: 0x8c, hi: 0x8c},
+ {value: 0xc600, lo: 0x8d, hi: 0xa7},
+ {value: 0xe500, lo: 0xa8, hi: 0xa8},
+ {value: 0xc600, lo: 0xa9, hi: 0xbf},
+ // Block 0x5e, offset 0x1dd
+ {value: 0x0000, lo: 0x07},
+ {value: 0xc600, lo: 0x80, hi: 0x83},
+ {value: 0xe500, lo: 0x84, hi: 0x84},
+ {value: 0xc600, lo: 0x85, hi: 0x9f},
+ {value: 0xe500, lo: 0xa0, hi: 0xa0},
+ {value: 0xc600, lo: 0xa1, hi: 0xbb},
+ {value: 0xe500, lo: 0xbc, hi: 0xbc},
+ {value: 0xc600, lo: 0xbd, hi: 0xbf},
+ // Block 0x5f, offset 0x1e5
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x97},
+ {value: 0xe500, lo: 0x98, hi: 0x98},
+ {value: 0xc600, lo: 0x99, hi: 0xb3},
+ {value: 0xe500, lo: 0xb4, hi: 0xb4},
+ {value: 0xc600, lo: 0xb5, hi: 0xbf},
+ // Block 0x60, offset 0x1eb
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x8f},
+ {value: 0xe500, lo: 0x90, hi: 0x90},
+ {value: 0xc600, lo: 0x91, hi: 0xab},
+ {value: 0xe500, lo: 0xac, hi: 0xac},
+ {value: 0xc600, lo: 0xad, hi: 0xbf},
+ // Block 0x61, offset 0x1f1
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x87},
+ {value: 0xe500, lo: 0x88, hi: 0x88},
+ {value: 0xc600, lo: 0x89, hi: 0xa3},
+ {value: 0xe500, lo: 0xa4, hi: 0xa4},
+ {value: 0xc600, lo: 0xa5, hi: 0xbf},
+ // Block 0x62, offset 0x1f7
+ {value: 0x0000, lo: 0x03},
+ {value: 0xc600, lo: 0x80, hi: 0x87},
+ {value: 0xe500, lo: 0x88, hi: 0x88},
+ {value: 0xc600, lo: 0x89, hi: 0xa3},
+ // Block 0x63, offset 0x1fb
+ {value: 0x0006, lo: 0x0d},
+ {value: 0x4390, lo: 0x9d, hi: 0x9d},
+ {value: 0x8115, lo: 0x9e, hi: 0x9e},
+ {value: 0x4402, lo: 0x9f, hi: 0x9f},
+ {value: 0x43f0, lo: 0xaa, hi: 0xab},
+ {value: 0x44f4, lo: 0xac, hi: 0xac},
+ {value: 0x44fc, lo: 0xad, hi: 0xad},
+ {value: 0x4348, lo: 0xae, hi: 0xb1},
+ {value: 0x4366, lo: 0xb2, hi: 0xb4},
+ {value: 0x437e, lo: 0xb5, hi: 0xb6},
+ {value: 0x438a, lo: 0xb8, hi: 0xb8},
+ {value: 0x4396, lo: 0xb9, hi: 0xbb},
+ {value: 0x43ae, lo: 0xbc, hi: 0xbc},
+ {value: 0x43b4, lo: 0xbe, hi: 0xbe},
+ // Block 0x64, offset 0x209
+ {value: 0x0006, lo: 0x08},
+ {value: 0x43ba, lo: 0x80, hi: 0x81},
+ {value: 0x43c6, lo: 0x83, hi: 0x84},
+ {value: 0x43d8, lo: 0x86, hi: 0x89},
+ {value: 0x43fc, lo: 0x8a, hi: 0x8a},
+ {value: 0x4378, lo: 0x8b, hi: 0x8b},
+ {value: 0x4360, lo: 0x8c, hi: 0x8c},
+ {value: 0x43a8, lo: 0x8d, hi: 0x8d},
+ {value: 0x43d2, lo: 0x8e, hi: 0x8e},
+ // Block 0x65, offset 0x212
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8100, lo: 0xa4, hi: 0xa5},
+ {value: 0x8100, lo: 0xb0, hi: 0xb1},
+ // Block 0x66, offset 0x215
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8100, lo: 0x9b, hi: 0x9d},
+ {value: 0x8200, lo: 0x9e, hi: 0xa3},
+ // Block 0x67, offset 0x218
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0x90, hi: 0x90},
+ // Block 0x68, offset 0x21a
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8100, lo: 0x99, hi: 0x99},
+ {value: 0x8200, lo: 0xb2, hi: 0xb4},
+ // Block 0x69, offset 0x21d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0xbc, hi: 0xbd},
+ // Block 0x6a, offset 0x21f
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8132, lo: 0xa0, hi: 0xa6},
+ {value: 0x812d, lo: 0xa7, hi: 0xad},
+ {value: 0x8132, lo: 0xae, hi: 0xaf},
+ // Block 0x6b, offset 0x223
+ {value: 0x0000, lo: 0x04},
+ {value: 0x8100, lo: 0x89, hi: 0x8c},
+ {value: 0x8100, lo: 0xb0, hi: 0xb2},
+ {value: 0x8100, lo: 0xb4, hi: 0xb4},
+ {value: 0x8100, lo: 0xb6, hi: 0xbf},
+ // Block 0x6c, offset 0x228
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0x81, hi: 0x8c},
+ // Block 0x6d, offset 0x22a
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0xb5, hi: 0xba},
+ // Block 0x6e, offset 0x22c
+ {value: 0x0000, lo: 0x04},
+ {value: 0x4a9f, lo: 0x9e, hi: 0x9f},
+ {value: 0x4a9f, lo: 0xa3, hi: 0xa3},
+ {value: 0x4a9f, lo: 0xa5, hi: 0xa6},
+ {value: 0x4a9f, lo: 0xaa, hi: 0xaf},
+ // Block 0x6f, offset 0x231
+ {value: 0x0000, lo: 0x05},
+ {value: 0x4a9f, lo: 0x82, hi: 0x87},
+ {value: 0x4a9f, lo: 0x8a, hi: 0x8f},
+ {value: 0x4a9f, lo: 0x92, hi: 0x97},
+ {value: 0x4a9f, lo: 0x9a, hi: 0x9c},
+ {value: 0x8100, lo: 0xa3, hi: 0xa3},
+ // Block 0x70, offset 0x237
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xbd, hi: 0xbd},
+ // Block 0x71, offset 0x239
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xa0, hi: 0xa0},
+ // Block 0x72, offset 0x23b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb6, hi: 0xba},
+ // Block 0x73, offset 0x23d
+ {value: 0x002c, lo: 0x05},
+ {value: 0x812d, lo: 0x8d, hi: 0x8d},
+ {value: 0x8132, lo: 0x8f, hi: 0x8f},
+ {value: 0x8132, lo: 0xb8, hi: 0xb8},
+ {value: 0x8101, lo: 0xb9, hi: 0xba},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x74, offset 0x243
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0xa5, hi: 0xa5},
+ {value: 0x812d, lo: 0xa6, hi: 0xa6},
+ // Block 0x75, offset 0x246
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x86, hi: 0x86},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x76, offset 0x249
+ {value: 0x17fe, lo: 0x07},
+ {value: 0xa000, lo: 0x99, hi: 0x99},
+ {value: 0x4238, lo: 0x9a, hi: 0x9a},
+ {value: 0xa000, lo: 0x9b, hi: 0x9b},
+ {value: 0x4242, lo: 0x9c, hi: 0x9c},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x424c, lo: 0xab, hi: 0xab},
+ {value: 0x8104, lo: 0xb9, hi: 0xba},
+ // Block 0x77, offset 0x251
+ {value: 0x0000, lo: 0x06},
+ {value: 0x8132, lo: 0x80, hi: 0x82},
+ {value: 0x9900, lo: 0xa7, hi: 0xa7},
+ {value: 0x2d7e, lo: 0xae, hi: 0xae},
+ {value: 0x2d88, lo: 0xaf, hi: 0xaf},
+ {value: 0xa000, lo: 0xb1, hi: 0xb2},
+ {value: 0x8104, lo: 0xb3, hi: 0xb4},
+ // Block 0x78, offset 0x258
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x80, hi: 0x80},
+ {value: 0x8102, lo: 0x8a, hi: 0x8a},
+ // Block 0x79, offset 0x25b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0xb5, hi: 0xb5},
+ {value: 0x8102, lo: 0xb6, hi: 0xb6},
+ // Block 0x7a, offset 0x25e
+ {value: 0x0002, lo: 0x01},
+ {value: 0x8102, lo: 0xa9, hi: 0xaa},
+ // Block 0x7b, offset 0x260
+ {value: 0x0000, lo: 0x07},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2d92, lo: 0x8b, hi: 0x8b},
+ {value: 0x2d9c, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ {value: 0x8132, lo: 0xa6, hi: 0xac},
+ {value: 0x8132, lo: 0xb0, hi: 0xb4},
+ // Block 0x7c, offset 0x268
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x82, hi: 0x82},
+ {value: 0x8102, lo: 0x86, hi: 0x86},
+ // Block 0x7d, offset 0x26b
+ {value: 0x6b5a, lo: 0x06},
+ {value: 0x9900, lo: 0xb0, hi: 0xb0},
+ {value: 0xa000, lo: 0xb9, hi: 0xb9},
+ {value: 0x9900, lo: 0xba, hi: 0xba},
+ {value: 0x2db0, lo: 0xbb, hi: 0xbb},
+ {value: 0x2da6, lo: 0xbc, hi: 0xbd},
+ {value: 0x2dba, lo: 0xbe, hi: 0xbe},
+ // Block 0x7e, offset 0x272
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x82, hi: 0x82},
+ {value: 0x8102, lo: 0x83, hi: 0x83},
+ // Block 0x7f, offset 0x275
+ {value: 0x0000, lo: 0x05},
+ {value: 0x9900, lo: 0xaf, hi: 0xaf},
+ {value: 0xa000, lo: 0xb8, hi: 0xb9},
+ {value: 0x2dc4, lo: 0xba, hi: 0xba},
+ {value: 0x2dce, lo: 0xbb, hi: 0xbb},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x80, offset 0x27b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0x80, hi: 0x80},
+ // Block 0x81, offset 0x27d
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0xb6, hi: 0xb6},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ // Block 0x82, offset 0x280
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xab, hi: 0xab},
+ // Block 0x83, offset 0x282
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8101, lo: 0xb0, hi: 0xb4},
+ // Block 0x84, offset 0x284
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb0, hi: 0xb6},
+ // Block 0x85, offset 0x286
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8101, lo: 0x9e, hi: 0x9e},
+ // Block 0x86, offset 0x288
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x45cc, lo: 0x9e, hi: 0x9e},
+ {value: 0x45d6, lo: 0x9f, hi: 0x9f},
+ {value: 0x460a, lo: 0xa0, hi: 0xa0},
+ {value: 0x4618, lo: 0xa1, hi: 0xa1},
+ {value: 0x4626, lo: 0xa2, hi: 0xa2},
+ {value: 0x4634, lo: 0xa3, hi: 0xa3},
+ {value: 0x4642, lo: 0xa4, hi: 0xa4},
+ {value: 0x812b, lo: 0xa5, hi: 0xa6},
+ {value: 0x8101, lo: 0xa7, hi: 0xa9},
+ {value: 0x8130, lo: 0xad, hi: 0xad},
+ {value: 0x812b, lo: 0xae, hi: 0xb2},
+ {value: 0x812d, lo: 0xbb, hi: 0xbf},
+ // Block 0x87, offset 0x295
+ {value: 0x0000, lo: 0x09},
+ {value: 0x812d, lo: 0x80, hi: 0x82},
+ {value: 0x8132, lo: 0x85, hi: 0x89},
+ {value: 0x812d, lo: 0x8a, hi: 0x8b},
+ {value: 0x8132, lo: 0xaa, hi: 0xad},
+ {value: 0x45e0, lo: 0xbb, hi: 0xbb},
+ {value: 0x45ea, lo: 0xbc, hi: 0xbc},
+ {value: 0x4650, lo: 0xbd, hi: 0xbd},
+ {value: 0x466c, lo: 0xbe, hi: 0xbe},
+ {value: 0x465e, lo: 0xbf, hi: 0xbf},
+ // Block 0x88, offset 0x29f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x467a, lo: 0x80, hi: 0x80},
+ // Block 0x89, offset 0x2a1
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x82, hi: 0x84},
+ // Block 0x8a, offset 0x2a3
+ {value: 0x0000, lo: 0x05},
+ {value: 0x8132, lo: 0x80, hi: 0x86},
+ {value: 0x8132, lo: 0x88, hi: 0x98},
+ {value: 0x8132, lo: 0x9b, hi: 0xa1},
+ {value: 0x8132, lo: 0xa3, hi: 0xa4},
+ {value: 0x8132, lo: 0xa6, hi: 0xaa},
+ // Block 0x8b, offset 0x2a9
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x90, hi: 0x96},
+ // Block 0x8c, offset 0x2ab
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x84, hi: 0x89},
+ {value: 0x8102, lo: 0x8a, hi: 0x8a},
+ // Block 0x8d, offset 0x2ae
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0x93, hi: 0x93},
+}
+
+// lookup returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *nfkcTrie) lookup(s []byte) (v uint16, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return nfkcValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := nfkcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := nfkcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfkcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := nfkcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfkcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = nfkcIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *nfkcTrie) lookupUnsafe(s []byte) uint16 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return nfkcValues[c0]
+ }
+ i := nfkcIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = nfkcIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = nfkcIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// lookupString returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *nfkcTrie) lookupString(s string) (v uint16, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return nfkcValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := nfkcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := nfkcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfkcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := nfkcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfkcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = nfkcIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *nfkcTrie) lookupStringUnsafe(s string) uint16 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return nfkcValues[c0]
+ }
+ i := nfkcIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = nfkcIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = nfkcIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// nfkcTrie. Total size: 16994 bytes (16.60 KiB). Checksum: c3ed54ee046f3c46.
+type nfkcTrie struct{}
+
+func newNfkcTrie(i int) *nfkcTrie {
+ return &nfkcTrie{}
+}
+
+// lookupValue determines the type of block n and looks up the value for b.
+func (t *nfkcTrie) lookupValue(n uint32, b byte) uint16 {
+ switch {
+ case n < 90:
+ return uint16(nfkcValues[n<<6+uint32(b)])
+ default:
+ n -= 90
+ return uint16(nfkcSparse.lookup(n, b))
+ }
+}
+
+// nfkcValues: 92 blocks, 5888 entries, 11776 bytes
+// The third block is the zero block.
+var nfkcValues = [5888]uint16{
+ // Block 0x0, offset 0x0
+ 0x3c: 0xa000, 0x3d: 0xa000, 0x3e: 0xa000,
+ // Block 0x1, offset 0x40
+ 0x41: 0xa000, 0x42: 0xa000, 0x43: 0xa000, 0x44: 0xa000, 0x45: 0xa000,
+ 0x46: 0xa000, 0x47: 0xa000, 0x48: 0xa000, 0x49: 0xa000, 0x4a: 0xa000, 0x4b: 0xa000,
+ 0x4c: 0xa000, 0x4d: 0xa000, 0x4e: 0xa000, 0x4f: 0xa000, 0x50: 0xa000,
+ 0x52: 0xa000, 0x53: 0xa000, 0x54: 0xa000, 0x55: 0xa000, 0x56: 0xa000, 0x57: 0xa000,
+ 0x58: 0xa000, 0x59: 0xa000, 0x5a: 0xa000,
+ 0x61: 0xa000, 0x62: 0xa000, 0x63: 0xa000,
+ 0x64: 0xa000, 0x65: 0xa000, 0x66: 0xa000, 0x67: 0xa000, 0x68: 0xa000, 0x69: 0xa000,
+ 0x6a: 0xa000, 0x6b: 0xa000, 0x6c: 0xa000, 0x6d: 0xa000, 0x6e: 0xa000, 0x6f: 0xa000,
+ 0x70: 0xa000, 0x72: 0xa000, 0x73: 0xa000, 0x74: 0xa000, 0x75: 0xa000,
+ 0x76: 0xa000, 0x77: 0xa000, 0x78: 0xa000, 0x79: 0xa000, 0x7a: 0xa000,
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc0: 0x2f6f, 0xc1: 0x2f74, 0xc2: 0x4688, 0xc3: 0x2f79, 0xc4: 0x4697, 0xc5: 0x469c,
+ 0xc6: 0xa000, 0xc7: 0x46a6, 0xc8: 0x2fe2, 0xc9: 0x2fe7, 0xca: 0x46ab, 0xcb: 0x2ffb,
+ 0xcc: 0x306e, 0xcd: 0x3073, 0xce: 0x3078, 0xcf: 0x46bf, 0xd1: 0x3104,
+ 0xd2: 0x3127, 0xd3: 0x312c, 0xd4: 0x46c9, 0xd5: 0x46ce, 0xd6: 0x46dd,
+ 0xd8: 0xa000, 0xd9: 0x31b3, 0xda: 0x31b8, 0xdb: 0x31bd, 0xdc: 0x470f, 0xdd: 0x3235,
+ 0xe0: 0x327b, 0xe1: 0x3280, 0xe2: 0x4719, 0xe3: 0x3285,
+ 0xe4: 0x4728, 0xe5: 0x472d, 0xe6: 0xa000, 0xe7: 0x4737, 0xe8: 0x32ee, 0xe9: 0x32f3,
+ 0xea: 0x473c, 0xeb: 0x3307, 0xec: 0x337f, 0xed: 0x3384, 0xee: 0x3389, 0xef: 0x4750,
+ 0xf1: 0x3415, 0xf2: 0x3438, 0xf3: 0x343d, 0xf4: 0x475a, 0xf5: 0x475f,
+ 0xf6: 0x476e, 0xf8: 0xa000, 0xf9: 0x34c9, 0xfa: 0x34ce, 0xfb: 0x34d3,
+ 0xfc: 0x47a0, 0xfd: 0x3550, 0xff: 0x3569,
+ // Block 0x4, offset 0x100
+ 0x100: 0x2f7e, 0x101: 0x328a, 0x102: 0x468d, 0x103: 0x471e, 0x104: 0x2f9c, 0x105: 0x32a8,
+ 0x106: 0x2fb0, 0x107: 0x32bc, 0x108: 0x2fb5, 0x109: 0x32c1, 0x10a: 0x2fba, 0x10b: 0x32c6,
+ 0x10c: 0x2fbf, 0x10d: 0x32cb, 0x10e: 0x2fc9, 0x10f: 0x32d5,
+ 0x112: 0x46b0, 0x113: 0x4741, 0x114: 0x2ff1, 0x115: 0x32fd, 0x116: 0x2ff6, 0x117: 0x3302,
+ 0x118: 0x3014, 0x119: 0x3320, 0x11a: 0x3005, 0x11b: 0x3311, 0x11c: 0x302d, 0x11d: 0x3339,
+ 0x11e: 0x3037, 0x11f: 0x3343, 0x120: 0x303c, 0x121: 0x3348, 0x122: 0x3046, 0x123: 0x3352,
+ 0x124: 0x304b, 0x125: 0x3357, 0x128: 0x307d, 0x129: 0x338e,
+ 0x12a: 0x3082, 0x12b: 0x3393, 0x12c: 0x3087, 0x12d: 0x3398, 0x12e: 0x30aa, 0x12f: 0x33b6,
+ 0x130: 0x308c, 0x132: 0x195d, 0x133: 0x19e7, 0x134: 0x30b4, 0x135: 0x33c0,
+ 0x136: 0x30c8, 0x137: 0x33d9, 0x139: 0x30d2, 0x13a: 0x33e3, 0x13b: 0x30dc,
+ 0x13c: 0x33ed, 0x13d: 0x30d7, 0x13e: 0x33e8, 0x13f: 0x1bac,
+ // Block 0x5, offset 0x140
+ 0x140: 0x1c34, 0x143: 0x30ff, 0x144: 0x3410, 0x145: 0x3118,
+ 0x146: 0x3429, 0x147: 0x310e, 0x148: 0x341f, 0x149: 0x1c5c,
+ 0x14c: 0x46d3, 0x14d: 0x4764, 0x14e: 0x3131, 0x14f: 0x3442, 0x150: 0x313b, 0x151: 0x344c,
+ 0x154: 0x3159, 0x155: 0x346a, 0x156: 0x3172, 0x157: 0x3483,
+ 0x158: 0x3163, 0x159: 0x3474, 0x15a: 0x46f6, 0x15b: 0x4787, 0x15c: 0x317c, 0x15d: 0x348d,
+ 0x15e: 0x318b, 0x15f: 0x349c, 0x160: 0x46fb, 0x161: 0x478c, 0x162: 0x31a4, 0x163: 0x34ba,
+ 0x164: 0x3195, 0x165: 0x34ab, 0x168: 0x4705, 0x169: 0x4796,
+ 0x16a: 0x470a, 0x16b: 0x479b, 0x16c: 0x31c2, 0x16d: 0x34d8, 0x16e: 0x31cc, 0x16f: 0x34e2,
+ 0x170: 0x31d1, 0x171: 0x34e7, 0x172: 0x31ef, 0x173: 0x3505, 0x174: 0x3212, 0x175: 0x3528,
+ 0x176: 0x323a, 0x177: 0x3555, 0x178: 0x324e, 0x179: 0x325d, 0x17a: 0x357d, 0x17b: 0x3267,
+ 0x17c: 0x3587, 0x17d: 0x326c, 0x17e: 0x358c, 0x17f: 0x00a7,
+ // Block 0x6, offset 0x180
+ 0x184: 0x2dee, 0x185: 0x2df4,
+ 0x186: 0x2dfa, 0x187: 0x1972, 0x188: 0x1975, 0x189: 0x1a08, 0x18a: 0x1987, 0x18b: 0x198a,
+ 0x18c: 0x1a3e, 0x18d: 0x2f88, 0x18e: 0x3294, 0x18f: 0x3096, 0x190: 0x33a2, 0x191: 0x3140,
+ 0x192: 0x3451, 0x193: 0x31d6, 0x194: 0x34ec, 0x195: 0x39cf, 0x196: 0x3b5e, 0x197: 0x39c8,
+ 0x198: 0x3b57, 0x199: 0x39d6, 0x19a: 0x3b65, 0x19b: 0x39c1, 0x19c: 0x3b50,
+ 0x19e: 0x38b0, 0x19f: 0x3a3f, 0x1a0: 0x38a9, 0x1a1: 0x3a38, 0x1a2: 0x35b3, 0x1a3: 0x35c5,
+ 0x1a6: 0x3041, 0x1a7: 0x334d, 0x1a8: 0x30be, 0x1a9: 0x33cf,
+ 0x1aa: 0x46ec, 0x1ab: 0x477d, 0x1ac: 0x3990, 0x1ad: 0x3b1f, 0x1ae: 0x35d7, 0x1af: 0x35dd,
+ 0x1b0: 0x33c5, 0x1b1: 0x1942, 0x1b2: 0x1945, 0x1b3: 0x19cf, 0x1b4: 0x3028, 0x1b5: 0x3334,
+ 0x1b8: 0x30fa, 0x1b9: 0x340b, 0x1ba: 0x38b7, 0x1bb: 0x3a46,
+ 0x1bc: 0x35ad, 0x1bd: 0x35bf, 0x1be: 0x35b9, 0x1bf: 0x35cb,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x2f8d, 0x1c1: 0x3299, 0x1c2: 0x2f92, 0x1c3: 0x329e, 0x1c4: 0x300a, 0x1c5: 0x3316,
+ 0x1c6: 0x300f, 0x1c7: 0x331b, 0x1c8: 0x309b, 0x1c9: 0x33a7, 0x1ca: 0x30a0, 0x1cb: 0x33ac,
+ 0x1cc: 0x3145, 0x1cd: 0x3456, 0x1ce: 0x314a, 0x1cf: 0x345b, 0x1d0: 0x3168, 0x1d1: 0x3479,
+ 0x1d2: 0x316d, 0x1d3: 0x347e, 0x1d4: 0x31db, 0x1d5: 0x34f1, 0x1d6: 0x31e0, 0x1d7: 0x34f6,
+ 0x1d8: 0x3186, 0x1d9: 0x3497, 0x1da: 0x319f, 0x1db: 0x34b5,
+ 0x1de: 0x305a, 0x1df: 0x3366,
+ 0x1e6: 0x4692, 0x1e7: 0x4723, 0x1e8: 0x46ba, 0x1e9: 0x474b,
+ 0x1ea: 0x395f, 0x1eb: 0x3aee, 0x1ec: 0x393c, 0x1ed: 0x3acb, 0x1ee: 0x46d8, 0x1ef: 0x4769,
+ 0x1f0: 0x3958, 0x1f1: 0x3ae7, 0x1f2: 0x3244, 0x1f3: 0x355f,
+ // Block 0x8, offset 0x200
+ 0x200: 0x9932, 0x201: 0x9932, 0x202: 0x9932, 0x203: 0x9932, 0x204: 0x9932, 0x205: 0x8132,
+ 0x206: 0x9932, 0x207: 0x9932, 0x208: 0x9932, 0x209: 0x9932, 0x20a: 0x9932, 0x20b: 0x9932,
+ 0x20c: 0x9932, 0x20d: 0x8132, 0x20e: 0x8132, 0x20f: 0x9932, 0x210: 0x8132, 0x211: 0x9932,
+ 0x212: 0x8132, 0x213: 0x9932, 0x214: 0x9932, 0x215: 0x8133, 0x216: 0x812d, 0x217: 0x812d,
+ 0x218: 0x812d, 0x219: 0x812d, 0x21a: 0x8133, 0x21b: 0x992b, 0x21c: 0x812d, 0x21d: 0x812d,
+ 0x21e: 0x812d, 0x21f: 0x812d, 0x220: 0x812d, 0x221: 0x8129, 0x222: 0x8129, 0x223: 0x992d,
+ 0x224: 0x992d, 0x225: 0x992d, 0x226: 0x992d, 0x227: 0x9929, 0x228: 0x9929, 0x229: 0x812d,
+ 0x22a: 0x812d, 0x22b: 0x812d, 0x22c: 0x812d, 0x22d: 0x992d, 0x22e: 0x992d, 0x22f: 0x812d,
+ 0x230: 0x992d, 0x231: 0x992d, 0x232: 0x812d, 0x233: 0x812d, 0x234: 0x8101, 0x235: 0x8101,
+ 0x236: 0x8101, 0x237: 0x8101, 0x238: 0x9901, 0x239: 0x812d, 0x23a: 0x812d, 0x23b: 0x812d,
+ 0x23c: 0x812d, 0x23d: 0x8132, 0x23e: 0x8132, 0x23f: 0x8132,
+ // Block 0x9, offset 0x240
+ 0x240: 0x49ae, 0x241: 0x49b3, 0x242: 0x9932, 0x243: 0x49b8, 0x244: 0x4a71, 0x245: 0x9936,
+ 0x246: 0x8132, 0x247: 0x812d, 0x248: 0x812d, 0x249: 0x812d, 0x24a: 0x8132, 0x24b: 0x8132,
+ 0x24c: 0x8132, 0x24d: 0x812d, 0x24e: 0x812d, 0x250: 0x8132, 0x251: 0x8132,
+ 0x252: 0x8132, 0x253: 0x812d, 0x254: 0x812d, 0x255: 0x812d, 0x256: 0x812d, 0x257: 0x8132,
+ 0x258: 0x8133, 0x259: 0x812d, 0x25a: 0x812d, 0x25b: 0x8132, 0x25c: 0x8134, 0x25d: 0x8135,
+ 0x25e: 0x8135, 0x25f: 0x8134, 0x260: 0x8135, 0x261: 0x8135, 0x262: 0x8134, 0x263: 0x8132,
+ 0x264: 0x8132, 0x265: 0x8132, 0x266: 0x8132, 0x267: 0x8132, 0x268: 0x8132, 0x269: 0x8132,
+ 0x26a: 0x8132, 0x26b: 0x8132, 0x26c: 0x8132, 0x26d: 0x8132, 0x26e: 0x8132, 0x26f: 0x8132,
+ 0x274: 0x0170,
+ 0x27a: 0x42a5,
+ 0x27e: 0x0037,
+ // Block 0xa, offset 0x280
+ 0x284: 0x425a, 0x285: 0x447b,
+ 0x286: 0x35e9, 0x287: 0x00ce, 0x288: 0x3607, 0x289: 0x3613, 0x28a: 0x3625,
+ 0x28c: 0x3643, 0x28e: 0x3655, 0x28f: 0x3673, 0x290: 0x3e08, 0x291: 0xa000,
+ 0x295: 0xa000, 0x297: 0xa000,
+ 0x299: 0xa000,
+ 0x29f: 0xa000, 0x2a1: 0xa000,
+ 0x2a5: 0xa000, 0x2a9: 0xa000,
+ 0x2aa: 0x3637, 0x2ab: 0x3667, 0x2ac: 0x47fe, 0x2ad: 0x3697, 0x2ae: 0x4828, 0x2af: 0x36a9,
+ 0x2b0: 0x3e70, 0x2b1: 0xa000, 0x2b5: 0xa000,
+ 0x2b7: 0xa000, 0x2b9: 0xa000,
+ 0x2bf: 0xa000,
+ // Block 0xb, offset 0x2c0
+ 0x2c1: 0xa000, 0x2c5: 0xa000,
+ 0x2c9: 0xa000, 0x2ca: 0x4840, 0x2cb: 0x485e,
+ 0x2cc: 0x36c7, 0x2cd: 0x36df, 0x2ce: 0x4876, 0x2d0: 0x01be, 0x2d1: 0x01d0,
+ 0x2d2: 0x01ac, 0x2d3: 0x430c, 0x2d4: 0x4312, 0x2d5: 0x01fa, 0x2d6: 0x01e8,
+ 0x2f0: 0x01d6, 0x2f1: 0x01eb, 0x2f2: 0x01ee, 0x2f4: 0x0188, 0x2f5: 0x01c7,
+ 0x2f9: 0x01a6,
+ // Block 0xc, offset 0x300
+ 0x300: 0x3721, 0x301: 0x372d, 0x303: 0x371b,
+ 0x306: 0xa000, 0x307: 0x3709,
+ 0x30c: 0x375d, 0x30d: 0x3745, 0x30e: 0x376f, 0x310: 0xa000,
+ 0x313: 0xa000, 0x315: 0xa000, 0x316: 0xa000, 0x317: 0xa000,
+ 0x318: 0xa000, 0x319: 0x3751, 0x31a: 0xa000,
+ 0x31e: 0xa000, 0x323: 0xa000,
+ 0x327: 0xa000,
+ 0x32b: 0xa000, 0x32d: 0xa000,
+ 0x330: 0xa000, 0x333: 0xa000, 0x335: 0xa000,
+ 0x336: 0xa000, 0x337: 0xa000, 0x338: 0xa000, 0x339: 0x37d5, 0x33a: 0xa000,
+ 0x33e: 0xa000,
+ // Block 0xd, offset 0x340
+ 0x341: 0x3733, 0x342: 0x37b7,
+ 0x350: 0x370f, 0x351: 0x3793,
+ 0x352: 0x3715, 0x353: 0x3799, 0x356: 0x3727, 0x357: 0x37ab,
+ 0x358: 0xa000, 0x359: 0xa000, 0x35a: 0x3829, 0x35b: 0x382f, 0x35c: 0x3739, 0x35d: 0x37bd,
+ 0x35e: 0x373f, 0x35f: 0x37c3, 0x362: 0x374b, 0x363: 0x37cf,
+ 0x364: 0x3757, 0x365: 0x37db, 0x366: 0x3763, 0x367: 0x37e7, 0x368: 0xa000, 0x369: 0xa000,
+ 0x36a: 0x3835, 0x36b: 0x383b, 0x36c: 0x378d, 0x36d: 0x3811, 0x36e: 0x3769, 0x36f: 0x37ed,
+ 0x370: 0x3775, 0x371: 0x37f9, 0x372: 0x377b, 0x373: 0x37ff, 0x374: 0x3781, 0x375: 0x3805,
+ 0x378: 0x3787, 0x379: 0x380b,
+ // Block 0xe, offset 0x380
+ 0x387: 0x1d61,
+ 0x391: 0x812d,
+ 0x392: 0x8132, 0x393: 0x8132, 0x394: 0x8132, 0x395: 0x8132, 0x396: 0x812d, 0x397: 0x8132,
+ 0x398: 0x8132, 0x399: 0x8132, 0x39a: 0x812e, 0x39b: 0x812d, 0x39c: 0x8132, 0x39d: 0x8132,
+ 0x39e: 0x8132, 0x39f: 0x8132, 0x3a0: 0x8132, 0x3a1: 0x8132, 0x3a2: 0x812d, 0x3a3: 0x812d,
+ 0x3a4: 0x812d, 0x3a5: 0x812d, 0x3a6: 0x812d, 0x3a7: 0x812d, 0x3a8: 0x8132, 0x3a9: 0x8132,
+ 0x3aa: 0x812d, 0x3ab: 0x8132, 0x3ac: 0x8132, 0x3ad: 0x812e, 0x3ae: 0x8131, 0x3af: 0x8132,
+ 0x3b0: 0x8105, 0x3b1: 0x8106, 0x3b2: 0x8107, 0x3b3: 0x8108, 0x3b4: 0x8109, 0x3b5: 0x810a,
+ 0x3b6: 0x810b, 0x3b7: 0x810c, 0x3b8: 0x810d, 0x3b9: 0x810e, 0x3ba: 0x810e, 0x3bb: 0x810f,
+ 0x3bc: 0x8110, 0x3bd: 0x8111, 0x3bf: 0x8112,
+ // Block 0xf, offset 0x3c0
+ 0x3c8: 0xa000, 0x3ca: 0xa000, 0x3cb: 0x8116,
+ 0x3cc: 0x8117, 0x3cd: 0x8118, 0x3ce: 0x8119, 0x3cf: 0x811a, 0x3d0: 0x811b, 0x3d1: 0x811c,
+ 0x3d2: 0x811d, 0x3d3: 0x9932, 0x3d4: 0x9932, 0x3d5: 0x992d, 0x3d6: 0x812d, 0x3d7: 0x8132,
+ 0x3d8: 0x8132, 0x3d9: 0x8132, 0x3da: 0x8132, 0x3db: 0x8132, 0x3dc: 0x812d, 0x3dd: 0x8132,
+ 0x3de: 0x8132, 0x3df: 0x812d,
+ 0x3f0: 0x811e, 0x3f5: 0x1d84,
+ 0x3f6: 0x2013, 0x3f7: 0x204f, 0x3f8: 0x204a,
+ // Block 0x10, offset 0x400
+ 0x405: 0xa000,
+ 0x406: 0x2d26, 0x407: 0xa000, 0x408: 0x2d2e, 0x409: 0xa000, 0x40a: 0x2d36, 0x40b: 0xa000,
+ 0x40c: 0x2d3e, 0x40d: 0xa000, 0x40e: 0x2d46, 0x411: 0xa000,
+ 0x412: 0x2d4e,
+ 0x434: 0x8102, 0x435: 0x9900,
+ 0x43a: 0xa000, 0x43b: 0x2d56,
+ 0x43c: 0xa000, 0x43d: 0x2d5e, 0x43e: 0xa000, 0x43f: 0xa000,
+ // Block 0x11, offset 0x440
+ 0x440: 0x0069, 0x441: 0x006b, 0x442: 0x006f, 0x443: 0x0083, 0x444: 0x00f5, 0x445: 0x00f8,
+ 0x446: 0x0413, 0x447: 0x0085, 0x448: 0x0089, 0x449: 0x008b, 0x44a: 0x0104, 0x44b: 0x0107,
+ 0x44c: 0x010a, 0x44d: 0x008f, 0x44f: 0x0097, 0x450: 0x009b, 0x451: 0x00e0,
+ 0x452: 0x009f, 0x453: 0x00fe, 0x454: 0x0417, 0x455: 0x041b, 0x456: 0x00a1, 0x457: 0x00a9,
+ 0x458: 0x00ab, 0x459: 0x0423, 0x45a: 0x012b, 0x45b: 0x00ad, 0x45c: 0x0427, 0x45d: 0x01be,
+ 0x45e: 0x01c1, 0x45f: 0x01c4, 0x460: 0x01fa, 0x461: 0x01fd, 0x462: 0x0093, 0x463: 0x00a5,
+ 0x464: 0x00ab, 0x465: 0x00ad, 0x466: 0x01be, 0x467: 0x01c1, 0x468: 0x01eb, 0x469: 0x01fa,
+ 0x46a: 0x01fd,
+ 0x478: 0x020c,
+ // Block 0x12, offset 0x480
+ 0x49b: 0x00fb, 0x49c: 0x0087, 0x49d: 0x0101,
+ 0x49e: 0x00d4, 0x49f: 0x010a, 0x4a0: 0x008d, 0x4a1: 0x010d, 0x4a2: 0x0110, 0x4a3: 0x0116,
+ 0x4a4: 0x011c, 0x4a5: 0x011f, 0x4a6: 0x0122, 0x4a7: 0x042b, 0x4a8: 0x016a, 0x4a9: 0x0128,
+ 0x4aa: 0x042f, 0x4ab: 0x016d, 0x4ac: 0x0131, 0x4ad: 0x012e, 0x4ae: 0x0134, 0x4af: 0x0137,
+ 0x4b0: 0x013a, 0x4b1: 0x013d, 0x4b2: 0x0140, 0x4b3: 0x014c, 0x4b4: 0x014f, 0x4b5: 0x00ec,
+ 0x4b6: 0x0152, 0x4b7: 0x0155, 0x4b8: 0x041f, 0x4b9: 0x0158, 0x4ba: 0x015b, 0x4bb: 0x00b5,
+ 0x4bc: 0x015e, 0x4bd: 0x0161, 0x4be: 0x0164, 0x4bf: 0x01d0,
+ // Block 0x13, offset 0x4c0
+ 0x4c0: 0x2f97, 0x4c1: 0x32a3, 0x4c2: 0x2fa1, 0x4c3: 0x32ad, 0x4c4: 0x2fa6, 0x4c5: 0x32b2,
+ 0x4c6: 0x2fab, 0x4c7: 0x32b7, 0x4c8: 0x38cc, 0x4c9: 0x3a5b, 0x4ca: 0x2fc4, 0x4cb: 0x32d0,
+ 0x4cc: 0x2fce, 0x4cd: 0x32da, 0x4ce: 0x2fdd, 0x4cf: 0x32e9, 0x4d0: 0x2fd3, 0x4d1: 0x32df,
+ 0x4d2: 0x2fd8, 0x4d3: 0x32e4, 0x4d4: 0x38ef, 0x4d5: 0x3a7e, 0x4d6: 0x38f6, 0x4d7: 0x3a85,
+ 0x4d8: 0x3019, 0x4d9: 0x3325, 0x4da: 0x301e, 0x4db: 0x332a, 0x4dc: 0x3904, 0x4dd: 0x3a93,
+ 0x4de: 0x3023, 0x4df: 0x332f, 0x4e0: 0x3032, 0x4e1: 0x333e, 0x4e2: 0x3050, 0x4e3: 0x335c,
+ 0x4e4: 0x305f, 0x4e5: 0x336b, 0x4e6: 0x3055, 0x4e7: 0x3361, 0x4e8: 0x3064, 0x4e9: 0x3370,
+ 0x4ea: 0x3069, 0x4eb: 0x3375, 0x4ec: 0x30af, 0x4ed: 0x33bb, 0x4ee: 0x390b, 0x4ef: 0x3a9a,
+ 0x4f0: 0x30b9, 0x4f1: 0x33ca, 0x4f2: 0x30c3, 0x4f3: 0x33d4, 0x4f4: 0x30cd, 0x4f5: 0x33de,
+ 0x4f6: 0x46c4, 0x4f7: 0x4755, 0x4f8: 0x3912, 0x4f9: 0x3aa1, 0x4fa: 0x30e6, 0x4fb: 0x33f7,
+ 0x4fc: 0x30e1, 0x4fd: 0x33f2, 0x4fe: 0x30eb, 0x4ff: 0x33fc,
+ // Block 0x14, offset 0x500
+ 0x500: 0x30f0, 0x501: 0x3401, 0x502: 0x30f5, 0x503: 0x3406, 0x504: 0x3109, 0x505: 0x341a,
+ 0x506: 0x3113, 0x507: 0x3424, 0x508: 0x3122, 0x509: 0x3433, 0x50a: 0x311d, 0x50b: 0x342e,
+ 0x50c: 0x3935, 0x50d: 0x3ac4, 0x50e: 0x3943, 0x50f: 0x3ad2, 0x510: 0x394a, 0x511: 0x3ad9,
+ 0x512: 0x3951, 0x513: 0x3ae0, 0x514: 0x314f, 0x515: 0x3460, 0x516: 0x3154, 0x517: 0x3465,
+ 0x518: 0x315e, 0x519: 0x346f, 0x51a: 0x46f1, 0x51b: 0x4782, 0x51c: 0x3997, 0x51d: 0x3b26,
+ 0x51e: 0x3177, 0x51f: 0x3488, 0x520: 0x3181, 0x521: 0x3492, 0x522: 0x4700, 0x523: 0x4791,
+ 0x524: 0x399e, 0x525: 0x3b2d, 0x526: 0x39a5, 0x527: 0x3b34, 0x528: 0x39ac, 0x529: 0x3b3b,
+ 0x52a: 0x3190, 0x52b: 0x34a1, 0x52c: 0x319a, 0x52d: 0x34b0, 0x52e: 0x31ae, 0x52f: 0x34c4,
+ 0x530: 0x31a9, 0x531: 0x34bf, 0x532: 0x31ea, 0x533: 0x3500, 0x534: 0x31f9, 0x535: 0x350f,
+ 0x536: 0x31f4, 0x537: 0x350a, 0x538: 0x39b3, 0x539: 0x3b42, 0x53a: 0x39ba, 0x53b: 0x3b49,
+ 0x53c: 0x31fe, 0x53d: 0x3514, 0x53e: 0x3203, 0x53f: 0x3519,
+ // Block 0x15, offset 0x540
+ 0x540: 0x3208, 0x541: 0x351e, 0x542: 0x320d, 0x543: 0x3523, 0x544: 0x321c, 0x545: 0x3532,
+ 0x546: 0x3217, 0x547: 0x352d, 0x548: 0x3221, 0x549: 0x353c, 0x54a: 0x3226, 0x54b: 0x3541,
+ 0x54c: 0x322b, 0x54d: 0x3546, 0x54e: 0x3249, 0x54f: 0x3564, 0x550: 0x3262, 0x551: 0x3582,
+ 0x552: 0x3271, 0x553: 0x3591, 0x554: 0x3276, 0x555: 0x3596, 0x556: 0x337a, 0x557: 0x34a6,
+ 0x558: 0x3537, 0x559: 0x3573, 0x55a: 0x1be0, 0x55b: 0x42d7,
+ 0x560: 0x46a1, 0x561: 0x4732, 0x562: 0x2f83, 0x563: 0x328f,
+ 0x564: 0x3878, 0x565: 0x3a07, 0x566: 0x3871, 0x567: 0x3a00, 0x568: 0x3886, 0x569: 0x3a15,
+ 0x56a: 0x387f, 0x56b: 0x3a0e, 0x56c: 0x38be, 0x56d: 0x3a4d, 0x56e: 0x3894, 0x56f: 0x3a23,
+ 0x570: 0x388d, 0x571: 0x3a1c, 0x572: 0x38a2, 0x573: 0x3a31, 0x574: 0x389b, 0x575: 0x3a2a,
+ 0x576: 0x38c5, 0x577: 0x3a54, 0x578: 0x46b5, 0x579: 0x4746, 0x57a: 0x3000, 0x57b: 0x330c,
+ 0x57c: 0x2fec, 0x57d: 0x32f8, 0x57e: 0x38da, 0x57f: 0x3a69,
+ // Block 0x16, offset 0x580
+ 0x580: 0x38d3, 0x581: 0x3a62, 0x582: 0x38e8, 0x583: 0x3a77, 0x584: 0x38e1, 0x585: 0x3a70,
+ 0x586: 0x38fd, 0x587: 0x3a8c, 0x588: 0x3091, 0x589: 0x339d, 0x58a: 0x30a5, 0x58b: 0x33b1,
+ 0x58c: 0x46e7, 0x58d: 0x4778, 0x58e: 0x3136, 0x58f: 0x3447, 0x590: 0x3920, 0x591: 0x3aaf,
+ 0x592: 0x3919, 0x593: 0x3aa8, 0x594: 0x392e, 0x595: 0x3abd, 0x596: 0x3927, 0x597: 0x3ab6,
+ 0x598: 0x3989, 0x599: 0x3b18, 0x59a: 0x396d, 0x59b: 0x3afc, 0x59c: 0x3966, 0x59d: 0x3af5,
+ 0x59e: 0x397b, 0x59f: 0x3b0a, 0x5a0: 0x3974, 0x5a1: 0x3b03, 0x5a2: 0x3982, 0x5a3: 0x3b11,
+ 0x5a4: 0x31e5, 0x5a5: 0x34fb, 0x5a6: 0x31c7, 0x5a7: 0x34dd, 0x5a8: 0x39e4, 0x5a9: 0x3b73,
+ 0x5aa: 0x39dd, 0x5ab: 0x3b6c, 0x5ac: 0x39f2, 0x5ad: 0x3b81, 0x5ae: 0x39eb, 0x5af: 0x3b7a,
+ 0x5b0: 0x39f9, 0x5b1: 0x3b88, 0x5b2: 0x3230, 0x5b3: 0x354b, 0x5b4: 0x3258, 0x5b5: 0x3578,
+ 0x5b6: 0x3253, 0x5b7: 0x356e, 0x5b8: 0x323f, 0x5b9: 0x355a,
+ // Block 0x17, offset 0x5c0
+ 0x5c0: 0x4804, 0x5c1: 0x480a, 0x5c2: 0x491e, 0x5c3: 0x4936, 0x5c4: 0x4926, 0x5c5: 0x493e,
+ 0x5c6: 0x492e, 0x5c7: 0x4946, 0x5c8: 0x47aa, 0x5c9: 0x47b0, 0x5ca: 0x488e, 0x5cb: 0x48a6,
+ 0x5cc: 0x4896, 0x5cd: 0x48ae, 0x5ce: 0x489e, 0x5cf: 0x48b6, 0x5d0: 0x4816, 0x5d1: 0x481c,
+ 0x5d2: 0x3db8, 0x5d3: 0x3dc8, 0x5d4: 0x3dc0, 0x5d5: 0x3dd0,
+ 0x5d8: 0x47b6, 0x5d9: 0x47bc, 0x5da: 0x3ce8, 0x5db: 0x3cf8, 0x5dc: 0x3cf0, 0x5dd: 0x3d00,
+ 0x5e0: 0x482e, 0x5e1: 0x4834, 0x5e2: 0x494e, 0x5e3: 0x4966,
+ 0x5e4: 0x4956, 0x5e5: 0x496e, 0x5e6: 0x495e, 0x5e7: 0x4976, 0x5e8: 0x47c2, 0x5e9: 0x47c8,
+ 0x5ea: 0x48be, 0x5eb: 0x48d6, 0x5ec: 0x48c6, 0x5ed: 0x48de, 0x5ee: 0x48ce, 0x5ef: 0x48e6,
+ 0x5f0: 0x4846, 0x5f1: 0x484c, 0x5f2: 0x3e18, 0x5f3: 0x3e30, 0x5f4: 0x3e20, 0x5f5: 0x3e38,
+ 0x5f6: 0x3e28, 0x5f7: 0x3e40, 0x5f8: 0x47ce, 0x5f9: 0x47d4, 0x5fa: 0x3d18, 0x5fb: 0x3d30,
+ 0x5fc: 0x3d20, 0x5fd: 0x3d38, 0x5fe: 0x3d28, 0x5ff: 0x3d40,
+ // Block 0x18, offset 0x600
+ 0x600: 0x4852, 0x601: 0x4858, 0x602: 0x3e48, 0x603: 0x3e58, 0x604: 0x3e50, 0x605: 0x3e60,
+ 0x608: 0x47da, 0x609: 0x47e0, 0x60a: 0x3d48, 0x60b: 0x3d58,
+ 0x60c: 0x3d50, 0x60d: 0x3d60, 0x610: 0x4864, 0x611: 0x486a,
+ 0x612: 0x3e80, 0x613: 0x3e98, 0x614: 0x3e88, 0x615: 0x3ea0, 0x616: 0x3e90, 0x617: 0x3ea8,
+ 0x619: 0x47e6, 0x61b: 0x3d68, 0x61d: 0x3d70,
+ 0x61f: 0x3d78, 0x620: 0x487c, 0x621: 0x4882, 0x622: 0x497e, 0x623: 0x4996,
+ 0x624: 0x4986, 0x625: 0x499e, 0x626: 0x498e, 0x627: 0x49a6, 0x628: 0x47ec, 0x629: 0x47f2,
+ 0x62a: 0x48ee, 0x62b: 0x4906, 0x62c: 0x48f6, 0x62d: 0x490e, 0x62e: 0x48fe, 0x62f: 0x4916,
+ 0x630: 0x47f8, 0x631: 0x431e, 0x632: 0x3691, 0x633: 0x4324, 0x634: 0x4822, 0x635: 0x432a,
+ 0x636: 0x36a3, 0x637: 0x4330, 0x638: 0x36c1, 0x639: 0x4336, 0x63a: 0x36d9, 0x63b: 0x433c,
+ 0x63c: 0x4870, 0x63d: 0x4342,
+ // Block 0x19, offset 0x640
+ 0x640: 0x3da0, 0x641: 0x3da8, 0x642: 0x4184, 0x643: 0x41a2, 0x644: 0x418e, 0x645: 0x41ac,
+ 0x646: 0x4198, 0x647: 0x41b6, 0x648: 0x3cd8, 0x649: 0x3ce0, 0x64a: 0x40d0, 0x64b: 0x40ee,
+ 0x64c: 0x40da, 0x64d: 0x40f8, 0x64e: 0x40e4, 0x64f: 0x4102, 0x650: 0x3de8, 0x651: 0x3df0,
+ 0x652: 0x41c0, 0x653: 0x41de, 0x654: 0x41ca, 0x655: 0x41e8, 0x656: 0x41d4, 0x657: 0x41f2,
+ 0x658: 0x3d08, 0x659: 0x3d10, 0x65a: 0x410c, 0x65b: 0x412a, 0x65c: 0x4116, 0x65d: 0x4134,
+ 0x65e: 0x4120, 0x65f: 0x413e, 0x660: 0x3ec0, 0x661: 0x3ec8, 0x662: 0x41fc, 0x663: 0x421a,
+ 0x664: 0x4206, 0x665: 0x4224, 0x666: 0x4210, 0x667: 0x422e, 0x668: 0x3d80, 0x669: 0x3d88,
+ 0x66a: 0x4148, 0x66b: 0x4166, 0x66c: 0x4152, 0x66d: 0x4170, 0x66e: 0x415c, 0x66f: 0x417a,
+ 0x670: 0x3685, 0x671: 0x367f, 0x672: 0x3d90, 0x673: 0x368b, 0x674: 0x3d98,
+ 0x676: 0x4810, 0x677: 0x3db0, 0x678: 0x35f5, 0x679: 0x35ef, 0x67a: 0x35e3, 0x67b: 0x42ee,
+ 0x67c: 0x35fb, 0x67d: 0x4287, 0x67e: 0x01d3, 0x67f: 0x4287,
+ // Block 0x1a, offset 0x680
+ 0x680: 0x42a0, 0x681: 0x4482, 0x682: 0x3dd8, 0x683: 0x369d, 0x684: 0x3de0,
+ 0x686: 0x483a, 0x687: 0x3df8, 0x688: 0x3601, 0x689: 0x42f4, 0x68a: 0x360d, 0x68b: 0x42fa,
+ 0x68c: 0x3619, 0x68d: 0x4489, 0x68e: 0x4490, 0x68f: 0x4497, 0x690: 0x36b5, 0x691: 0x36af,
+ 0x692: 0x3e00, 0x693: 0x44e4, 0x696: 0x36bb, 0x697: 0x3e10,
+ 0x698: 0x3631, 0x699: 0x362b, 0x69a: 0x361f, 0x69b: 0x4300, 0x69d: 0x449e,
+ 0x69e: 0x44a5, 0x69f: 0x44ac, 0x6a0: 0x36eb, 0x6a1: 0x36e5, 0x6a2: 0x3e68, 0x6a3: 0x44ec,
+ 0x6a4: 0x36cd, 0x6a5: 0x36d3, 0x6a6: 0x36f1, 0x6a7: 0x3e78, 0x6a8: 0x3661, 0x6a9: 0x365b,
+ 0x6aa: 0x364f, 0x6ab: 0x430c, 0x6ac: 0x3649, 0x6ad: 0x4474, 0x6ae: 0x447b, 0x6af: 0x0081,
+ 0x6b2: 0x3eb0, 0x6b3: 0x36f7, 0x6b4: 0x3eb8,
+ 0x6b6: 0x4888, 0x6b7: 0x3ed0, 0x6b8: 0x363d, 0x6b9: 0x4306, 0x6ba: 0x366d, 0x6bb: 0x4318,
+ 0x6bc: 0x3679, 0x6bd: 0x425a, 0x6be: 0x428c,
+ // Block 0x1b, offset 0x6c0
+ 0x6c0: 0x1bd8, 0x6c1: 0x1bdc, 0x6c2: 0x0047, 0x6c3: 0x1c54, 0x6c5: 0x1be8,
+ 0x6c6: 0x1bec, 0x6c7: 0x00e9, 0x6c9: 0x1c58, 0x6ca: 0x008f, 0x6cb: 0x0051,
+ 0x6cc: 0x0051, 0x6cd: 0x0051, 0x6ce: 0x0091, 0x6cf: 0x00da, 0x6d0: 0x0053, 0x6d1: 0x0053,
+ 0x6d2: 0x0059, 0x6d3: 0x0099, 0x6d5: 0x005d, 0x6d6: 0x198d,
+ 0x6d9: 0x0061, 0x6da: 0x0063, 0x6db: 0x0065, 0x6dc: 0x0065, 0x6dd: 0x0065,
+ 0x6e0: 0x199f, 0x6e1: 0x1bc8, 0x6e2: 0x19a8,
+ 0x6e4: 0x0075, 0x6e6: 0x01b8, 0x6e8: 0x0075,
+ 0x6ea: 0x0057, 0x6eb: 0x42d2, 0x6ec: 0x0045, 0x6ed: 0x0047, 0x6ef: 0x008b,
+ 0x6f0: 0x004b, 0x6f1: 0x004d, 0x6f3: 0x005b, 0x6f4: 0x009f, 0x6f5: 0x0215,
+ 0x6f6: 0x0218, 0x6f7: 0x021b, 0x6f8: 0x021e, 0x6f9: 0x0093, 0x6fb: 0x1b98,
+ 0x6fc: 0x01e8, 0x6fd: 0x01c1, 0x6fe: 0x0179, 0x6ff: 0x01a0,
+ // Block 0x1c, offset 0x700
+ 0x700: 0x0463, 0x705: 0x0049,
+ 0x706: 0x0089, 0x707: 0x008b, 0x708: 0x0093, 0x709: 0x0095,
+ 0x710: 0x222e, 0x711: 0x223a,
+ 0x712: 0x22ee, 0x713: 0x2216, 0x714: 0x229a, 0x715: 0x2222, 0x716: 0x22a0, 0x717: 0x22b8,
+ 0x718: 0x22c4, 0x719: 0x2228, 0x71a: 0x22ca, 0x71b: 0x2234, 0x71c: 0x22be, 0x71d: 0x22d0,
+ 0x71e: 0x22d6, 0x71f: 0x1cbc, 0x720: 0x0053, 0x721: 0x195a, 0x722: 0x1ba4, 0x723: 0x1963,
+ 0x724: 0x006d, 0x725: 0x19ab, 0x726: 0x1bd0, 0x727: 0x1d48, 0x728: 0x1966, 0x729: 0x0071,
+ 0x72a: 0x19b7, 0x72b: 0x1bd4, 0x72c: 0x0059, 0x72d: 0x0047, 0x72e: 0x0049, 0x72f: 0x005b,
+ 0x730: 0x0093, 0x731: 0x19e4, 0x732: 0x1c18, 0x733: 0x19ed, 0x734: 0x00ad, 0x735: 0x1a62,
+ 0x736: 0x1c4c, 0x737: 0x1d5c, 0x738: 0x19f0, 0x739: 0x00b1, 0x73a: 0x1a65, 0x73b: 0x1c50,
+ 0x73c: 0x0099, 0x73d: 0x0087, 0x73e: 0x0089, 0x73f: 0x009b,
+ // Block 0x1d, offset 0x740
+ 0x741: 0x3c06, 0x743: 0xa000, 0x744: 0x3c0d, 0x745: 0xa000,
+ 0x747: 0x3c14, 0x748: 0xa000, 0x749: 0x3c1b,
+ 0x74d: 0xa000,
+ 0x760: 0x2f65, 0x761: 0xa000, 0x762: 0x3c29,
+ 0x764: 0xa000, 0x765: 0xa000,
+ 0x76d: 0x3c22, 0x76e: 0x2f60, 0x76f: 0x2f6a,
+ 0x770: 0x3c30, 0x771: 0x3c37, 0x772: 0xa000, 0x773: 0xa000, 0x774: 0x3c3e, 0x775: 0x3c45,
+ 0x776: 0xa000, 0x777: 0xa000, 0x778: 0x3c4c, 0x779: 0x3c53, 0x77a: 0xa000, 0x77b: 0xa000,
+ 0x77c: 0xa000, 0x77d: 0xa000,
+ // Block 0x1e, offset 0x780
+ 0x780: 0x3c5a, 0x781: 0x3c61, 0x782: 0xa000, 0x783: 0xa000, 0x784: 0x3c76, 0x785: 0x3c7d,
+ 0x786: 0xa000, 0x787: 0xa000, 0x788: 0x3c84, 0x789: 0x3c8b,
+ 0x791: 0xa000,
+ 0x792: 0xa000,
+ 0x7a2: 0xa000,
+ 0x7a8: 0xa000, 0x7a9: 0xa000,
+ 0x7ab: 0xa000, 0x7ac: 0x3ca0, 0x7ad: 0x3ca7, 0x7ae: 0x3cae, 0x7af: 0x3cb5,
+ 0x7b2: 0xa000, 0x7b3: 0xa000, 0x7b4: 0xa000, 0x7b5: 0xa000,
+ // Block 0x1f, offset 0x7c0
+ 0x7e0: 0x0023, 0x7e1: 0x0025, 0x7e2: 0x0027, 0x7e3: 0x0029,
+ 0x7e4: 0x002b, 0x7e5: 0x002d, 0x7e6: 0x002f, 0x7e7: 0x0031, 0x7e8: 0x0033, 0x7e9: 0x1882,
+ 0x7ea: 0x1885, 0x7eb: 0x1888, 0x7ec: 0x188b, 0x7ed: 0x188e, 0x7ee: 0x1891, 0x7ef: 0x1894,
+ 0x7f0: 0x1897, 0x7f1: 0x189a, 0x7f2: 0x189d, 0x7f3: 0x18a6, 0x7f4: 0x1a68, 0x7f5: 0x1a6c,
+ 0x7f6: 0x1a70, 0x7f7: 0x1a74, 0x7f8: 0x1a78, 0x7f9: 0x1a7c, 0x7fa: 0x1a80, 0x7fb: 0x1a84,
+ 0x7fc: 0x1a88, 0x7fd: 0x1c80, 0x7fe: 0x1c85, 0x7ff: 0x1c8a,
+ // Block 0x20, offset 0x800
+ 0x800: 0x1c8f, 0x801: 0x1c94, 0x802: 0x1c99, 0x803: 0x1c9e, 0x804: 0x1ca3, 0x805: 0x1ca8,
+ 0x806: 0x1cad, 0x807: 0x1cb2, 0x808: 0x187f, 0x809: 0x18a3, 0x80a: 0x18c7, 0x80b: 0x18eb,
+ 0x80c: 0x190f, 0x80d: 0x1918, 0x80e: 0x191e, 0x80f: 0x1924, 0x810: 0x192a, 0x811: 0x1b60,
+ 0x812: 0x1b64, 0x813: 0x1b68, 0x814: 0x1b6c, 0x815: 0x1b70, 0x816: 0x1b74, 0x817: 0x1b78,
+ 0x818: 0x1b7c, 0x819: 0x1b80, 0x81a: 0x1b84, 0x81b: 0x1b88, 0x81c: 0x1af4, 0x81d: 0x1af8,
+ 0x81e: 0x1afc, 0x81f: 0x1b00, 0x820: 0x1b04, 0x821: 0x1b08, 0x822: 0x1b0c, 0x823: 0x1b10,
+ 0x824: 0x1b14, 0x825: 0x1b18, 0x826: 0x1b1c, 0x827: 0x1b20, 0x828: 0x1b24, 0x829: 0x1b28,
+ 0x82a: 0x1b2c, 0x82b: 0x1b30, 0x82c: 0x1b34, 0x82d: 0x1b38, 0x82e: 0x1b3c, 0x82f: 0x1b40,
+ 0x830: 0x1b44, 0x831: 0x1b48, 0x832: 0x1b4c, 0x833: 0x1b50, 0x834: 0x1b54, 0x835: 0x1b58,
+ 0x836: 0x0043, 0x837: 0x0045, 0x838: 0x0047, 0x839: 0x0049, 0x83a: 0x004b, 0x83b: 0x004d,
+ 0x83c: 0x004f, 0x83d: 0x0051, 0x83e: 0x0053, 0x83f: 0x0055,
+ // Block 0x21, offset 0x840
+ 0x840: 0x06bf, 0x841: 0x06e3, 0x842: 0x06ef, 0x843: 0x06ff, 0x844: 0x0707, 0x845: 0x0713,
+ 0x846: 0x071b, 0x847: 0x0723, 0x848: 0x072f, 0x849: 0x0783, 0x84a: 0x079b, 0x84b: 0x07ab,
+ 0x84c: 0x07bb, 0x84d: 0x07cb, 0x84e: 0x07db, 0x84f: 0x07fb, 0x850: 0x07ff, 0x851: 0x0803,
+ 0x852: 0x0837, 0x853: 0x085f, 0x854: 0x086f, 0x855: 0x0877, 0x856: 0x087b, 0x857: 0x0887,
+ 0x858: 0x08a3, 0x859: 0x08a7, 0x85a: 0x08bf, 0x85b: 0x08c3, 0x85c: 0x08cb, 0x85d: 0x08db,
+ 0x85e: 0x0977, 0x85f: 0x098b, 0x860: 0x09cb, 0x861: 0x09df, 0x862: 0x09e7, 0x863: 0x09eb,
+ 0x864: 0x09fb, 0x865: 0x0a17, 0x866: 0x0a43, 0x867: 0x0a4f, 0x868: 0x0a6f, 0x869: 0x0a7b,
+ 0x86a: 0x0a7f, 0x86b: 0x0a83, 0x86c: 0x0a9b, 0x86d: 0x0a9f, 0x86e: 0x0acb, 0x86f: 0x0ad7,
+ 0x870: 0x0adf, 0x871: 0x0ae7, 0x872: 0x0af7, 0x873: 0x0aff, 0x874: 0x0b07, 0x875: 0x0b33,
+ 0x876: 0x0b37, 0x877: 0x0b3f, 0x878: 0x0b43, 0x879: 0x0b4b, 0x87a: 0x0b53, 0x87b: 0x0b63,
+ 0x87c: 0x0b7f, 0x87d: 0x0bf7, 0x87e: 0x0c0b, 0x87f: 0x0c0f,
+ // Block 0x22, offset 0x880
+ 0x880: 0x0c8f, 0x881: 0x0c93, 0x882: 0x0ca7, 0x883: 0x0cab, 0x884: 0x0cb3, 0x885: 0x0cbb,
+ 0x886: 0x0cc3, 0x887: 0x0ccf, 0x888: 0x0cf7, 0x889: 0x0d07, 0x88a: 0x0d1b, 0x88b: 0x0d8b,
+ 0x88c: 0x0d97, 0x88d: 0x0da7, 0x88e: 0x0db3, 0x88f: 0x0dbf, 0x890: 0x0dc7, 0x891: 0x0dcb,
+ 0x892: 0x0dcf, 0x893: 0x0dd3, 0x894: 0x0dd7, 0x895: 0x0e8f, 0x896: 0x0ed7, 0x897: 0x0ee3,
+ 0x898: 0x0ee7, 0x899: 0x0eeb, 0x89a: 0x0eef, 0x89b: 0x0ef7, 0x89c: 0x0efb, 0x89d: 0x0f0f,
+ 0x89e: 0x0f2b, 0x89f: 0x0f33, 0x8a0: 0x0f73, 0x8a1: 0x0f77, 0x8a2: 0x0f7f, 0x8a3: 0x0f83,
+ 0x8a4: 0x0f8b, 0x8a5: 0x0f8f, 0x8a6: 0x0fb3, 0x8a7: 0x0fb7, 0x8a8: 0x0fd3, 0x8a9: 0x0fd7,
+ 0x8aa: 0x0fdb, 0x8ab: 0x0fdf, 0x8ac: 0x0ff3, 0x8ad: 0x1017, 0x8ae: 0x101b, 0x8af: 0x101f,
+ 0x8b0: 0x1043, 0x8b1: 0x1083, 0x8b2: 0x1087, 0x8b3: 0x10a7, 0x8b4: 0x10b7, 0x8b5: 0x10bf,
+ 0x8b6: 0x10df, 0x8b7: 0x1103, 0x8b8: 0x1147, 0x8b9: 0x114f, 0x8ba: 0x1163, 0x8bb: 0x116f,
+ 0x8bc: 0x1177, 0x8bd: 0x117f, 0x8be: 0x1183, 0x8bf: 0x1187,
+ // Block 0x23, offset 0x8c0
+ 0x8c0: 0x119f, 0x8c1: 0x11a3, 0x8c2: 0x11bf, 0x8c3: 0x11c7, 0x8c4: 0x11cf, 0x8c5: 0x11d3,
+ 0x8c6: 0x11df, 0x8c7: 0x11e7, 0x8c8: 0x11eb, 0x8c9: 0x11ef, 0x8ca: 0x11f7, 0x8cb: 0x11fb,
+ 0x8cc: 0x129b, 0x8cd: 0x12af, 0x8ce: 0x12e3, 0x8cf: 0x12e7, 0x8d0: 0x12ef, 0x8d1: 0x131b,
+ 0x8d2: 0x1323, 0x8d3: 0x132b, 0x8d4: 0x1333, 0x8d5: 0x136f, 0x8d6: 0x1373, 0x8d7: 0x137b,
+ 0x8d8: 0x137f, 0x8d9: 0x1383, 0x8da: 0x13af, 0x8db: 0x13b3, 0x8dc: 0x13bb, 0x8dd: 0x13cf,
+ 0x8de: 0x13d3, 0x8df: 0x13ef, 0x8e0: 0x13f7, 0x8e1: 0x13fb, 0x8e2: 0x141f, 0x8e3: 0x143f,
+ 0x8e4: 0x1453, 0x8e5: 0x1457, 0x8e6: 0x145f, 0x8e7: 0x148b, 0x8e8: 0x148f, 0x8e9: 0x149f,
+ 0x8ea: 0x14c3, 0x8eb: 0x14cf, 0x8ec: 0x14df, 0x8ed: 0x14f7, 0x8ee: 0x14ff, 0x8ef: 0x1503,
+ 0x8f0: 0x1507, 0x8f1: 0x150b, 0x8f2: 0x1517, 0x8f3: 0x151b, 0x8f4: 0x1523, 0x8f5: 0x153f,
+ 0x8f6: 0x1543, 0x8f7: 0x1547, 0x8f8: 0x155f, 0x8f9: 0x1563, 0x8fa: 0x156b, 0x8fb: 0x157f,
+ 0x8fc: 0x1583, 0x8fd: 0x1587, 0x8fe: 0x158f, 0x8ff: 0x1593,
+ // Block 0x24, offset 0x900
+ 0x906: 0xa000, 0x90b: 0xa000,
+ 0x90c: 0x3f08, 0x90d: 0xa000, 0x90e: 0x3f10, 0x90f: 0xa000, 0x910: 0x3f18, 0x911: 0xa000,
+ 0x912: 0x3f20, 0x913: 0xa000, 0x914: 0x3f28, 0x915: 0xa000, 0x916: 0x3f30, 0x917: 0xa000,
+ 0x918: 0x3f38, 0x919: 0xa000, 0x91a: 0x3f40, 0x91b: 0xa000, 0x91c: 0x3f48, 0x91d: 0xa000,
+ 0x91e: 0x3f50, 0x91f: 0xa000, 0x920: 0x3f58, 0x921: 0xa000, 0x922: 0x3f60,
+ 0x924: 0xa000, 0x925: 0x3f68, 0x926: 0xa000, 0x927: 0x3f70, 0x928: 0xa000, 0x929: 0x3f78,
+ 0x92f: 0xa000,
+ 0x930: 0x3f80, 0x931: 0x3f88, 0x932: 0xa000, 0x933: 0x3f90, 0x934: 0x3f98, 0x935: 0xa000,
+ 0x936: 0x3fa0, 0x937: 0x3fa8, 0x938: 0xa000, 0x939: 0x3fb0, 0x93a: 0x3fb8, 0x93b: 0xa000,
+ 0x93c: 0x3fc0, 0x93d: 0x3fc8,
+ // Block 0x25, offset 0x940
+ 0x954: 0x3f00,
+ 0x959: 0x9903, 0x95a: 0x9903, 0x95b: 0x42dc, 0x95c: 0x42e2, 0x95d: 0xa000,
+ 0x95e: 0x3fd0, 0x95f: 0x26b4,
+ 0x966: 0xa000,
+ 0x96b: 0xa000, 0x96c: 0x3fe0, 0x96d: 0xa000, 0x96e: 0x3fe8, 0x96f: 0xa000,
+ 0x970: 0x3ff0, 0x971: 0xa000, 0x972: 0x3ff8, 0x973: 0xa000, 0x974: 0x4000, 0x975: 0xa000,
+ 0x976: 0x4008, 0x977: 0xa000, 0x978: 0x4010, 0x979: 0xa000, 0x97a: 0x4018, 0x97b: 0xa000,
+ 0x97c: 0x4020, 0x97d: 0xa000, 0x97e: 0x4028, 0x97f: 0xa000,
+ // Block 0x26, offset 0x980
+ 0x980: 0x4030, 0x981: 0xa000, 0x982: 0x4038, 0x984: 0xa000, 0x985: 0x4040,
+ 0x986: 0xa000, 0x987: 0x4048, 0x988: 0xa000, 0x989: 0x4050,
+ 0x98f: 0xa000, 0x990: 0x4058, 0x991: 0x4060,
+ 0x992: 0xa000, 0x993: 0x4068, 0x994: 0x4070, 0x995: 0xa000, 0x996: 0x4078, 0x997: 0x4080,
+ 0x998: 0xa000, 0x999: 0x4088, 0x99a: 0x4090, 0x99b: 0xa000, 0x99c: 0x4098, 0x99d: 0x40a0,
+ 0x9af: 0xa000,
+ 0x9b0: 0xa000, 0x9b1: 0xa000, 0x9b2: 0xa000, 0x9b4: 0x3fd8,
+ 0x9b7: 0x40a8, 0x9b8: 0x40b0, 0x9b9: 0x40b8, 0x9ba: 0x40c0,
+ 0x9bd: 0xa000, 0x9be: 0x40c8, 0x9bf: 0x26c9,
+ // Block 0x27, offset 0x9c0
+ 0x9c0: 0x0367, 0x9c1: 0x032b, 0x9c2: 0x032f, 0x9c3: 0x0333, 0x9c4: 0x037b, 0x9c5: 0x0337,
+ 0x9c6: 0x033b, 0x9c7: 0x033f, 0x9c8: 0x0343, 0x9c9: 0x0347, 0x9ca: 0x034b, 0x9cb: 0x034f,
+ 0x9cc: 0x0353, 0x9cd: 0x0357, 0x9ce: 0x035b, 0x9cf: 0x49bd, 0x9d0: 0x49c3, 0x9d1: 0x49c9,
+ 0x9d2: 0x49cf, 0x9d3: 0x49d5, 0x9d4: 0x49db, 0x9d5: 0x49e1, 0x9d6: 0x49e7, 0x9d7: 0x49ed,
+ 0x9d8: 0x49f3, 0x9d9: 0x49f9, 0x9da: 0x49ff, 0x9db: 0x4a05, 0x9dc: 0x4a0b, 0x9dd: 0x4a11,
+ 0x9de: 0x4a17, 0x9df: 0x4a1d, 0x9e0: 0x4a23, 0x9e1: 0x4a29, 0x9e2: 0x4a2f, 0x9e3: 0x4a35,
+ 0x9e4: 0x03c3, 0x9e5: 0x035f, 0x9e6: 0x0363, 0x9e7: 0x03e7, 0x9e8: 0x03eb, 0x9e9: 0x03ef,
+ 0x9ea: 0x03f3, 0x9eb: 0x03f7, 0x9ec: 0x03fb, 0x9ed: 0x03ff, 0x9ee: 0x036b, 0x9ef: 0x0403,
+ 0x9f0: 0x0407, 0x9f1: 0x036f, 0x9f2: 0x0373, 0x9f3: 0x0377, 0x9f4: 0x037f, 0x9f5: 0x0383,
+ 0x9f6: 0x0387, 0x9f7: 0x038b, 0x9f8: 0x038f, 0x9f9: 0x0393, 0x9fa: 0x0397, 0x9fb: 0x039b,
+ 0x9fc: 0x039f, 0x9fd: 0x03a3, 0x9fe: 0x03a7, 0x9ff: 0x03ab,
+ // Block 0x28, offset 0xa00
+ 0xa00: 0x03af, 0xa01: 0x03b3, 0xa02: 0x040b, 0xa03: 0x040f, 0xa04: 0x03b7, 0xa05: 0x03bb,
+ 0xa06: 0x03bf, 0xa07: 0x03c7, 0xa08: 0x03cb, 0xa09: 0x03cf, 0xa0a: 0x03d3, 0xa0b: 0x03d7,
+ 0xa0c: 0x03db, 0xa0d: 0x03df, 0xa0e: 0x03e3,
+ 0xa12: 0x06bf, 0xa13: 0x071b, 0xa14: 0x06cb, 0xa15: 0x097b, 0xa16: 0x06cf, 0xa17: 0x06e7,
+ 0xa18: 0x06d3, 0xa19: 0x0f93, 0xa1a: 0x0707, 0xa1b: 0x06db, 0xa1c: 0x06c3, 0xa1d: 0x09ff,
+ 0xa1e: 0x098f, 0xa1f: 0x072f,
+ // Block 0x29, offset 0xa40
+ 0xa40: 0x2054, 0xa41: 0x205a, 0xa42: 0x2060, 0xa43: 0x2066, 0xa44: 0x206c, 0xa45: 0x2072,
+ 0xa46: 0x2078, 0xa47: 0x207e, 0xa48: 0x2084, 0xa49: 0x208a, 0xa4a: 0x2090, 0xa4b: 0x2096,
+ 0xa4c: 0x209c, 0xa4d: 0x20a2, 0xa4e: 0x2726, 0xa4f: 0x272f, 0xa50: 0x2738, 0xa51: 0x2741,
+ 0xa52: 0x274a, 0xa53: 0x2753, 0xa54: 0x275c, 0xa55: 0x2765, 0xa56: 0x276e, 0xa57: 0x2780,
+ 0xa58: 0x2789, 0xa59: 0x2792, 0xa5a: 0x279b, 0xa5b: 0x27a4, 0xa5c: 0x2777, 0xa5d: 0x2bac,
+ 0xa5e: 0x2aed, 0xa60: 0x20a8, 0xa61: 0x20c0, 0xa62: 0x20b4, 0xa63: 0x2108,
+ 0xa64: 0x20c6, 0xa65: 0x20e4, 0xa66: 0x20ae, 0xa67: 0x20de, 0xa68: 0x20ba, 0xa69: 0x20f0,
+ 0xa6a: 0x2120, 0xa6b: 0x213e, 0xa6c: 0x2138, 0xa6d: 0x212c, 0xa6e: 0x217a, 0xa6f: 0x210e,
+ 0xa70: 0x211a, 0xa71: 0x2132, 0xa72: 0x2126, 0xa73: 0x2150, 0xa74: 0x20fc, 0xa75: 0x2144,
+ 0xa76: 0x216e, 0xa77: 0x2156, 0xa78: 0x20ea, 0xa79: 0x20cc, 0xa7a: 0x2102, 0xa7b: 0x2114,
+ 0xa7c: 0x214a, 0xa7d: 0x20d2, 0xa7e: 0x2174, 0xa7f: 0x20f6,
+ // Block 0x2a, offset 0xa80
+ 0xa80: 0x215c, 0xa81: 0x20d8, 0xa82: 0x2162, 0xa83: 0x2168, 0xa84: 0x092f, 0xa85: 0x0b03,
+ 0xa86: 0x0ca7, 0xa87: 0x10c7,
+ 0xa90: 0x1bc4, 0xa91: 0x18a9,
+ 0xa92: 0x18ac, 0xa93: 0x18af, 0xa94: 0x18b2, 0xa95: 0x18b5, 0xa96: 0x18b8, 0xa97: 0x18bb,
+ 0xa98: 0x18be, 0xa99: 0x18c1, 0xa9a: 0x18ca, 0xa9b: 0x18cd, 0xa9c: 0x18d0, 0xa9d: 0x18d3,
+ 0xa9e: 0x18d6, 0xa9f: 0x18d9, 0xaa0: 0x0313, 0xaa1: 0x031b, 0xaa2: 0x031f, 0xaa3: 0x0327,
+ 0xaa4: 0x032b, 0xaa5: 0x032f, 0xaa6: 0x0337, 0xaa7: 0x033f, 0xaa8: 0x0343, 0xaa9: 0x034b,
+ 0xaaa: 0x034f, 0xaab: 0x0353, 0xaac: 0x0357, 0xaad: 0x035b, 0xaae: 0x2e18, 0xaaf: 0x2e20,
+ 0xab0: 0x2e28, 0xab1: 0x2e30, 0xab2: 0x2e38, 0xab3: 0x2e40, 0xab4: 0x2e48, 0xab5: 0x2e50,
+ 0xab6: 0x2e60, 0xab7: 0x2e68, 0xab8: 0x2e70, 0xab9: 0x2e78, 0xaba: 0x2e80, 0xabb: 0x2e88,
+ 0xabc: 0x2ed3, 0xabd: 0x2e9b, 0xabe: 0x2e58,
+ // Block 0x2b, offset 0xac0
+ 0xac0: 0x06bf, 0xac1: 0x071b, 0xac2: 0x06cb, 0xac3: 0x097b, 0xac4: 0x071f, 0xac5: 0x07af,
+ 0xac6: 0x06c7, 0xac7: 0x07ab, 0xac8: 0x070b, 0xac9: 0x0887, 0xaca: 0x0d07, 0xacb: 0x0e8f,
+ 0xacc: 0x0dd7, 0xacd: 0x0d1b, 0xace: 0x145f, 0xacf: 0x098b, 0xad0: 0x0ccf, 0xad1: 0x0d4b,
+ 0xad2: 0x0d0b, 0xad3: 0x104b, 0xad4: 0x08fb, 0xad5: 0x0f03, 0xad6: 0x1387, 0xad7: 0x105f,
+ 0xad8: 0x0843, 0xad9: 0x108f, 0xada: 0x0f9b, 0xadb: 0x0a17, 0xadc: 0x140f, 0xadd: 0x077f,
+ 0xade: 0x08ab, 0xadf: 0x0df7, 0xae0: 0x1527, 0xae1: 0x0743, 0xae2: 0x07d3, 0xae3: 0x0d9b,
+ 0xae4: 0x06cf, 0xae5: 0x06e7, 0xae6: 0x06d3, 0xae7: 0x0adb, 0xae8: 0x08ef, 0xae9: 0x087f,
+ 0xaea: 0x0a57, 0xaeb: 0x0a4b, 0xaec: 0x0feb, 0xaed: 0x073f, 0xaee: 0x139b, 0xaef: 0x089b,
+ 0xaf0: 0x09f3, 0xaf1: 0x18dc, 0xaf2: 0x18df, 0xaf3: 0x18e2, 0xaf4: 0x18e5, 0xaf5: 0x18ee,
+ 0xaf6: 0x18f1, 0xaf7: 0x18f4, 0xaf8: 0x18f7, 0xaf9: 0x18fa, 0xafa: 0x18fd, 0xafb: 0x1900,
+ 0xafc: 0x1903, 0xafd: 0x1906, 0xafe: 0x1909, 0xaff: 0x1912,
+ // Block 0x2c, offset 0xb00
+ 0xb00: 0x1cc6, 0xb01: 0x1cd5, 0xb02: 0x1ce4, 0xb03: 0x1cf3, 0xb04: 0x1d02, 0xb05: 0x1d11,
+ 0xb06: 0x1d20, 0xb07: 0x1d2f, 0xb08: 0x1d3e, 0xb09: 0x218c, 0xb0a: 0x219e, 0xb0b: 0x21b0,
+ 0xb0c: 0x1954, 0xb0d: 0x1c04, 0xb0e: 0x19d2, 0xb0f: 0x1ba8, 0xb10: 0x04cb, 0xb11: 0x04d3,
+ 0xb12: 0x04db, 0xb13: 0x04e3, 0xb14: 0x04eb, 0xb15: 0x04ef, 0xb16: 0x04f3, 0xb17: 0x04f7,
+ 0xb18: 0x04fb, 0xb19: 0x04ff, 0xb1a: 0x0503, 0xb1b: 0x0507, 0xb1c: 0x050b, 0xb1d: 0x050f,
+ 0xb1e: 0x0513, 0xb1f: 0x0517, 0xb20: 0x051b, 0xb21: 0x0523, 0xb22: 0x0527, 0xb23: 0x052b,
+ 0xb24: 0x052f, 0xb25: 0x0533, 0xb26: 0x0537, 0xb27: 0x053b, 0xb28: 0x053f, 0xb29: 0x0543,
+ 0xb2a: 0x0547, 0xb2b: 0x054b, 0xb2c: 0x054f, 0xb2d: 0x0553, 0xb2e: 0x0557, 0xb2f: 0x055b,
+ 0xb30: 0x055f, 0xb31: 0x0563, 0xb32: 0x0567, 0xb33: 0x056f, 0xb34: 0x0577, 0xb35: 0x057f,
+ 0xb36: 0x0583, 0xb37: 0x0587, 0xb38: 0x058b, 0xb39: 0x058f, 0xb3a: 0x0593, 0xb3b: 0x0597,
+ 0xb3c: 0x059b, 0xb3d: 0x059f, 0xb3e: 0x05a3,
+ // Block 0x2d, offset 0xb40
+ 0xb40: 0x2b0c, 0xb41: 0x29a8, 0xb42: 0x2b1c, 0xb43: 0x2880, 0xb44: 0x2ee4, 0xb45: 0x288a,
+ 0xb46: 0x2894, 0xb47: 0x2f28, 0xb48: 0x29b5, 0xb49: 0x289e, 0xb4a: 0x28a8, 0xb4b: 0x28b2,
+ 0xb4c: 0x29dc, 0xb4d: 0x29e9, 0xb4e: 0x29c2, 0xb4f: 0x29cf, 0xb50: 0x2ea9, 0xb51: 0x29f6,
+ 0xb52: 0x2a03, 0xb53: 0x2bbe, 0xb54: 0x26bb, 0xb55: 0x2bd1, 0xb56: 0x2be4, 0xb57: 0x2b2c,
+ 0xb58: 0x2a10, 0xb59: 0x2bf7, 0xb5a: 0x2c0a, 0xb5b: 0x2a1d, 0xb5c: 0x28bc, 0xb5d: 0x28c6,
+ 0xb5e: 0x2eb7, 0xb5f: 0x2a2a, 0xb60: 0x2b3c, 0xb61: 0x2ef5, 0xb62: 0x28d0, 0xb63: 0x28da,
+ 0xb64: 0x2a37, 0xb65: 0x28e4, 0xb66: 0x28ee, 0xb67: 0x26d0, 0xb68: 0x26d7, 0xb69: 0x28f8,
+ 0xb6a: 0x2902, 0xb6b: 0x2c1d, 0xb6c: 0x2a44, 0xb6d: 0x2b4c, 0xb6e: 0x2c30, 0xb6f: 0x2a51,
+ 0xb70: 0x2916, 0xb71: 0x290c, 0xb72: 0x2f3c, 0xb73: 0x2a5e, 0xb74: 0x2c43, 0xb75: 0x2920,
+ 0xb76: 0x2b5c, 0xb77: 0x292a, 0xb78: 0x2a78, 0xb79: 0x2934, 0xb7a: 0x2a85, 0xb7b: 0x2f06,
+ 0xb7c: 0x2a6b, 0xb7d: 0x2b6c, 0xb7e: 0x2a92, 0xb7f: 0x26de,
+ // Block 0x2e, offset 0xb80
+ 0xb80: 0x2f17, 0xb81: 0x293e, 0xb82: 0x2948, 0xb83: 0x2a9f, 0xb84: 0x2952, 0xb85: 0x295c,
+ 0xb86: 0x2966, 0xb87: 0x2b7c, 0xb88: 0x2aac, 0xb89: 0x26e5, 0xb8a: 0x2c56, 0xb8b: 0x2e90,
+ 0xb8c: 0x2b8c, 0xb8d: 0x2ab9, 0xb8e: 0x2ec5, 0xb8f: 0x2970, 0xb90: 0x297a, 0xb91: 0x2ac6,
+ 0xb92: 0x26ec, 0xb93: 0x2ad3, 0xb94: 0x2b9c, 0xb95: 0x26f3, 0xb96: 0x2c69, 0xb97: 0x2984,
+ 0xb98: 0x1cb7, 0xb99: 0x1ccb, 0xb9a: 0x1cda, 0xb9b: 0x1ce9, 0xb9c: 0x1cf8, 0xb9d: 0x1d07,
+ 0xb9e: 0x1d16, 0xb9f: 0x1d25, 0xba0: 0x1d34, 0xba1: 0x1d43, 0xba2: 0x2192, 0xba3: 0x21a4,
+ 0xba4: 0x21b6, 0xba5: 0x21c2, 0xba6: 0x21ce, 0xba7: 0x21da, 0xba8: 0x21e6, 0xba9: 0x21f2,
+ 0xbaa: 0x21fe, 0xbab: 0x220a, 0xbac: 0x2246, 0xbad: 0x2252, 0xbae: 0x225e, 0xbaf: 0x226a,
+ 0xbb0: 0x2276, 0xbb1: 0x1c14, 0xbb2: 0x19c6, 0xbb3: 0x1936, 0xbb4: 0x1be4, 0xbb5: 0x1a47,
+ 0xbb6: 0x1a56, 0xbb7: 0x19cc, 0xbb8: 0x1bfc, 0xbb9: 0x1c00, 0xbba: 0x1960, 0xbbb: 0x2701,
+ 0xbbc: 0x270f, 0xbbd: 0x26fa, 0xbbe: 0x2708, 0xbbf: 0x2ae0,
+ // Block 0x2f, offset 0xbc0
+ 0xbc0: 0x1a4a, 0xbc1: 0x1a32, 0xbc2: 0x1c60, 0xbc3: 0x1a1a, 0xbc4: 0x19f3, 0xbc5: 0x1969,
+ 0xbc6: 0x1978, 0xbc7: 0x1948, 0xbc8: 0x1bf0, 0xbc9: 0x1d52, 0xbca: 0x1a4d, 0xbcb: 0x1a35,
+ 0xbcc: 0x1c64, 0xbcd: 0x1c70, 0xbce: 0x1a26, 0xbcf: 0x19fc, 0xbd0: 0x1957, 0xbd1: 0x1c1c,
+ 0xbd2: 0x1bb0, 0xbd3: 0x1b9c, 0xbd4: 0x1bcc, 0xbd5: 0x1c74, 0xbd6: 0x1a29, 0xbd7: 0x19c9,
+ 0xbd8: 0x19ff, 0xbd9: 0x19de, 0xbda: 0x1a41, 0xbdb: 0x1c78, 0xbdc: 0x1a2c, 0xbdd: 0x19c0,
+ 0xbde: 0x1a02, 0xbdf: 0x1c3c, 0xbe0: 0x1bf4, 0xbe1: 0x1a14, 0xbe2: 0x1c24, 0xbe3: 0x1c40,
+ 0xbe4: 0x1bf8, 0xbe5: 0x1a17, 0xbe6: 0x1c28, 0xbe7: 0x22e8, 0xbe8: 0x22fc, 0xbe9: 0x1996,
+ 0xbea: 0x1c20, 0xbeb: 0x1bb4, 0xbec: 0x1ba0, 0xbed: 0x1c48, 0xbee: 0x2716, 0xbef: 0x27ad,
+ 0xbf0: 0x1a59, 0xbf1: 0x1a44, 0xbf2: 0x1c7c, 0xbf3: 0x1a2f, 0xbf4: 0x1a50, 0xbf5: 0x1a38,
+ 0xbf6: 0x1c68, 0xbf7: 0x1a1d, 0xbf8: 0x19f6, 0xbf9: 0x1981, 0xbfa: 0x1a53, 0xbfb: 0x1a3b,
+ 0xbfc: 0x1c6c, 0xbfd: 0x1a20, 0xbfe: 0x19f9, 0xbff: 0x1984,
+ // Block 0x30, offset 0xc00
+ 0xc00: 0x1c2c, 0xc01: 0x1bb8, 0xc02: 0x1d4d, 0xc03: 0x1939, 0xc04: 0x19ba, 0xc05: 0x19bd,
+ 0xc06: 0x22f5, 0xc07: 0x1b94, 0xc08: 0x19c3, 0xc09: 0x194b, 0xc0a: 0x19e1, 0xc0b: 0x194e,
+ 0xc0c: 0x19ea, 0xc0d: 0x196c, 0xc0e: 0x196f, 0xc0f: 0x1a05, 0xc10: 0x1a0b, 0xc11: 0x1a0e,
+ 0xc12: 0x1c30, 0xc13: 0x1a11, 0xc14: 0x1a23, 0xc15: 0x1c38, 0xc16: 0x1c44, 0xc17: 0x1990,
+ 0xc18: 0x1d57, 0xc19: 0x1bbc, 0xc1a: 0x1993, 0xc1b: 0x1a5c, 0xc1c: 0x19a5, 0xc1d: 0x19b4,
+ 0xc1e: 0x22e2, 0xc1f: 0x22dc, 0xc20: 0x1cc1, 0xc21: 0x1cd0, 0xc22: 0x1cdf, 0xc23: 0x1cee,
+ 0xc24: 0x1cfd, 0xc25: 0x1d0c, 0xc26: 0x1d1b, 0xc27: 0x1d2a, 0xc28: 0x1d39, 0xc29: 0x2186,
+ 0xc2a: 0x2198, 0xc2b: 0x21aa, 0xc2c: 0x21bc, 0xc2d: 0x21c8, 0xc2e: 0x21d4, 0xc2f: 0x21e0,
+ 0xc30: 0x21ec, 0xc31: 0x21f8, 0xc32: 0x2204, 0xc33: 0x2240, 0xc34: 0x224c, 0xc35: 0x2258,
+ 0xc36: 0x2264, 0xc37: 0x2270, 0xc38: 0x227c, 0xc39: 0x2282, 0xc3a: 0x2288, 0xc3b: 0x228e,
+ 0xc3c: 0x2294, 0xc3d: 0x22a6, 0xc3e: 0x22ac, 0xc3f: 0x1c10,
+ // Block 0x31, offset 0xc40
+ 0xc40: 0x1377, 0xc41: 0x0cfb, 0xc42: 0x13d3, 0xc43: 0x139f, 0xc44: 0x0e57, 0xc45: 0x06eb,
+ 0xc46: 0x08df, 0xc47: 0x162b, 0xc48: 0x162b, 0xc49: 0x0a0b, 0xc4a: 0x145f, 0xc4b: 0x0943,
+ 0xc4c: 0x0a07, 0xc4d: 0x0bef, 0xc4e: 0x0fcf, 0xc4f: 0x115f, 0xc50: 0x1297, 0xc51: 0x12d3,
+ 0xc52: 0x1307, 0xc53: 0x141b, 0xc54: 0x0d73, 0xc55: 0x0dff, 0xc56: 0x0eab, 0xc57: 0x0f43,
+ 0xc58: 0x125f, 0xc59: 0x1447, 0xc5a: 0x1573, 0xc5b: 0x070f, 0xc5c: 0x08b3, 0xc5d: 0x0d87,
+ 0xc5e: 0x0ecf, 0xc5f: 0x1293, 0xc60: 0x15c3, 0xc61: 0x0ab3, 0xc62: 0x0e77, 0xc63: 0x1283,
+ 0xc64: 0x1317, 0xc65: 0x0c23, 0xc66: 0x11bb, 0xc67: 0x12df, 0xc68: 0x0b1f, 0xc69: 0x0d0f,
+ 0xc6a: 0x0e17, 0xc6b: 0x0f1b, 0xc6c: 0x1427, 0xc6d: 0x074f, 0xc6e: 0x07e7, 0xc6f: 0x0853,
+ 0xc70: 0x0c8b, 0xc71: 0x0d7f, 0xc72: 0x0ecb, 0xc73: 0x0fef, 0xc74: 0x1177, 0xc75: 0x128b,
+ 0xc76: 0x12a3, 0xc77: 0x13c7, 0xc78: 0x14ef, 0xc79: 0x15a3, 0xc7a: 0x15bf, 0xc7b: 0x102b,
+ 0xc7c: 0x106b, 0xc7d: 0x1123, 0xc7e: 0x1243, 0xc7f: 0x147b,
+ // Block 0x32, offset 0xc80
+ 0xc80: 0x15cb, 0xc81: 0x134b, 0xc82: 0x09c7, 0xc83: 0x0b3b, 0xc84: 0x10db, 0xc85: 0x119b,
+ 0xc86: 0x0eff, 0xc87: 0x1033, 0xc88: 0x1397, 0xc89: 0x14e7, 0xc8a: 0x09c3, 0xc8b: 0x0a8f,
+ 0xc8c: 0x0d77, 0xc8d: 0x0e2b, 0xc8e: 0x0e5f, 0xc8f: 0x1113, 0xc90: 0x113b, 0xc91: 0x14a7,
+ 0xc92: 0x084f, 0xc93: 0x11a7, 0xc94: 0x07f3, 0xc95: 0x07ef, 0xc96: 0x1097, 0xc97: 0x1127,
+ 0xc98: 0x125b, 0xc99: 0x14af, 0xc9a: 0x1367, 0xc9b: 0x0c27, 0xc9c: 0x0d73, 0xc9d: 0x1357,
+ 0xc9e: 0x06f7, 0xc9f: 0x0a63, 0xca0: 0x0b93, 0xca1: 0x0f2f, 0xca2: 0x0faf, 0xca3: 0x0873,
+ 0xca4: 0x103b, 0xca5: 0x075f, 0xca6: 0x0b77, 0xca7: 0x06d7, 0xca8: 0x0deb, 0xca9: 0x0ca3,
+ 0xcaa: 0x110f, 0xcab: 0x08c7, 0xcac: 0x09b3, 0xcad: 0x0ffb, 0xcae: 0x1263, 0xcaf: 0x133b,
+ 0xcb0: 0x0db7, 0xcb1: 0x13f7, 0xcb2: 0x0de3, 0xcb3: 0x0c37, 0xcb4: 0x121b, 0xcb5: 0x0c57,
+ 0xcb6: 0x0fab, 0xcb7: 0x072b, 0xcb8: 0x07a7, 0xcb9: 0x07eb, 0xcba: 0x0d53, 0xcbb: 0x10fb,
+ 0xcbc: 0x11f3, 0xcbd: 0x1347, 0xcbe: 0x145b, 0xcbf: 0x085b,
+ // Block 0x33, offset 0xcc0
+ 0xcc0: 0x090f, 0xcc1: 0x0a17, 0xcc2: 0x0b2f, 0xcc3: 0x0cbf, 0xcc4: 0x0e7b, 0xcc5: 0x103f,
+ 0xcc6: 0x1497, 0xcc7: 0x157b, 0xcc8: 0x15cf, 0xcc9: 0x15e7, 0xcca: 0x0837, 0xccb: 0x0cf3,
+ 0xccc: 0x0da3, 0xccd: 0x13eb, 0xcce: 0x0afb, 0xccf: 0x0bd7, 0xcd0: 0x0bf3, 0xcd1: 0x0c83,
+ 0xcd2: 0x0e6b, 0xcd3: 0x0eb7, 0xcd4: 0x0f67, 0xcd5: 0x108b, 0xcd6: 0x112f, 0xcd7: 0x1193,
+ 0xcd8: 0x13db, 0xcd9: 0x126b, 0xcda: 0x1403, 0xcdb: 0x147f, 0xcdc: 0x080f, 0xcdd: 0x083b,
+ 0xcde: 0x0923, 0xcdf: 0x0ea7, 0xce0: 0x12f3, 0xce1: 0x133b, 0xce2: 0x0b1b, 0xce3: 0x0b8b,
+ 0xce4: 0x0c4f, 0xce5: 0x0daf, 0xce6: 0x10d7, 0xce7: 0x0f23, 0xce8: 0x073b, 0xce9: 0x097f,
+ 0xcea: 0x0a63, 0xceb: 0x0ac7, 0xcec: 0x0b97, 0xced: 0x0f3f, 0xcee: 0x0f5b, 0xcef: 0x116b,
+ 0xcf0: 0x118b, 0xcf1: 0x1463, 0xcf2: 0x14e3, 0xcf3: 0x14f3, 0xcf4: 0x152f, 0xcf5: 0x0753,
+ 0xcf6: 0x107f, 0xcf7: 0x144f, 0xcf8: 0x14cb, 0xcf9: 0x0baf, 0xcfa: 0x0717, 0xcfb: 0x0777,
+ 0xcfc: 0x0a67, 0xcfd: 0x0a87, 0xcfe: 0x0caf, 0xcff: 0x0d73,
+ // Block 0x34, offset 0xd00
+ 0xd00: 0x0ec3, 0xd01: 0x0fcb, 0xd02: 0x1277, 0xd03: 0x1417, 0xd04: 0x1623, 0xd05: 0x0ce3,
+ 0xd06: 0x14a3, 0xd07: 0x0833, 0xd08: 0x0d2f, 0xd09: 0x0d3b, 0xd0a: 0x0e0f, 0xd0b: 0x0e47,
+ 0xd0c: 0x0f4b, 0xd0d: 0x0fa7, 0xd0e: 0x1027, 0xd0f: 0x110b, 0xd10: 0x153b, 0xd11: 0x07af,
+ 0xd12: 0x0c03, 0xd13: 0x14b3, 0xd14: 0x0767, 0xd15: 0x0aab, 0xd16: 0x0e2f, 0xd17: 0x13df,
+ 0xd18: 0x0b67, 0xd19: 0x0bb7, 0xd1a: 0x0d43, 0xd1b: 0x0f2f, 0xd1c: 0x14bb, 0xd1d: 0x0817,
+ 0xd1e: 0x08ff, 0xd1f: 0x0a97, 0xd20: 0x0cd3, 0xd21: 0x0d1f, 0xd22: 0x0d5f, 0xd23: 0x0df3,
+ 0xd24: 0x0f47, 0xd25: 0x0fbb, 0xd26: 0x1157, 0xd27: 0x12f7, 0xd28: 0x1303, 0xd29: 0x1457,
+ 0xd2a: 0x14d7, 0xd2b: 0x0883, 0xd2c: 0x0e4b, 0xd2d: 0x0903, 0xd2e: 0x0ec7, 0xd2f: 0x0f6b,
+ 0xd30: 0x1287, 0xd31: 0x14bf, 0xd32: 0x15ab, 0xd33: 0x15d3, 0xd34: 0x0d37, 0xd35: 0x0e27,
+ 0xd36: 0x11c3, 0xd37: 0x10b7, 0xd38: 0x10c3, 0xd39: 0x10e7, 0xd3a: 0x0f17, 0xd3b: 0x0e9f,
+ 0xd3c: 0x1363, 0xd3d: 0x0733, 0xd3e: 0x122b, 0xd3f: 0x081b,
+ // Block 0x35, offset 0xd40
+ 0xd40: 0x080b, 0xd41: 0x0b0b, 0xd42: 0x0c2b, 0xd43: 0x10f3, 0xd44: 0x0a53, 0xd45: 0x0e03,
+ 0xd46: 0x0cef, 0xd47: 0x13e7, 0xd48: 0x12e7, 0xd49: 0x14ab, 0xd4a: 0x1323, 0xd4b: 0x0b27,
+ 0xd4c: 0x0787, 0xd4d: 0x095b, 0xd50: 0x09af,
+ 0xd52: 0x0cdf, 0xd55: 0x07f7, 0xd56: 0x0f1f, 0xd57: 0x0fe3,
+ 0xd58: 0x1047, 0xd59: 0x1063, 0xd5a: 0x1067, 0xd5b: 0x107b, 0xd5c: 0x14fb, 0xd5d: 0x10eb,
+ 0xd5e: 0x116f, 0xd60: 0x128f, 0xd62: 0x1353,
+ 0xd65: 0x1407, 0xd66: 0x1433,
+ 0xd6a: 0x154f, 0xd6b: 0x1553, 0xd6c: 0x1557, 0xd6d: 0x15bb, 0xd6e: 0x142b, 0xd6f: 0x14c7,
+ 0xd70: 0x0757, 0xd71: 0x077b, 0xd72: 0x078f, 0xd73: 0x084b, 0xd74: 0x0857, 0xd75: 0x0897,
+ 0xd76: 0x094b, 0xd77: 0x0967, 0xd78: 0x096f, 0xd79: 0x09ab, 0xd7a: 0x09b7, 0xd7b: 0x0a93,
+ 0xd7c: 0x0a9b, 0xd7d: 0x0ba3, 0xd7e: 0x0bcb, 0xd7f: 0x0bd3,
+ // Block 0x36, offset 0xd80
+ 0xd80: 0x0beb, 0xd81: 0x0c97, 0xd82: 0x0cc7, 0xd83: 0x0ce7, 0xd84: 0x0d57, 0xd85: 0x0e1b,
+ 0xd86: 0x0e37, 0xd87: 0x0e67, 0xd88: 0x0ebb, 0xd89: 0x0edb, 0xd8a: 0x0f4f, 0xd8b: 0x102f,
+ 0xd8c: 0x104b, 0xd8d: 0x1053, 0xd8e: 0x104f, 0xd8f: 0x1057, 0xd90: 0x105b, 0xd91: 0x105f,
+ 0xd92: 0x1073, 0xd93: 0x1077, 0xd94: 0x109b, 0xd95: 0x10af, 0xd96: 0x10cb, 0xd97: 0x112f,
+ 0xd98: 0x1137, 0xd99: 0x113f, 0xd9a: 0x1153, 0xd9b: 0x117b, 0xd9c: 0x11cb, 0xd9d: 0x11ff,
+ 0xd9e: 0x11ff, 0xd9f: 0x1267, 0xda0: 0x130f, 0xda1: 0x1327, 0xda2: 0x135b, 0xda3: 0x135f,
+ 0xda4: 0x13a3, 0xda5: 0x13a7, 0xda6: 0x13ff, 0xda7: 0x1407, 0xda8: 0x14db, 0xda9: 0x151f,
+ 0xdaa: 0x1537, 0xdab: 0x0b9b, 0xdac: 0x171e, 0xdad: 0x11e3,
+ 0xdb0: 0x06df, 0xdb1: 0x07e3, 0xdb2: 0x07a3, 0xdb3: 0x074b, 0xdb4: 0x078b, 0xdb5: 0x07b7,
+ 0xdb6: 0x0847, 0xdb7: 0x0863, 0xdb8: 0x094b, 0xdb9: 0x0937, 0xdba: 0x0947, 0xdbb: 0x0963,
+ 0xdbc: 0x09af, 0xdbd: 0x09bf, 0xdbe: 0x0a03, 0xdbf: 0x0a0f,
+ // Block 0x37, offset 0xdc0
+ 0xdc0: 0x0a2b, 0xdc1: 0x0a3b, 0xdc2: 0x0b23, 0xdc3: 0x0b2b, 0xdc4: 0x0b5b, 0xdc5: 0x0b7b,
+ 0xdc6: 0x0bab, 0xdc7: 0x0bc3, 0xdc8: 0x0bb3, 0xdc9: 0x0bd3, 0xdca: 0x0bc7, 0xdcb: 0x0beb,
+ 0xdcc: 0x0c07, 0xdcd: 0x0c5f, 0xdce: 0x0c6b, 0xdcf: 0x0c73, 0xdd0: 0x0c9b, 0xdd1: 0x0cdf,
+ 0xdd2: 0x0d0f, 0xdd3: 0x0d13, 0xdd4: 0x0d27, 0xdd5: 0x0da7, 0xdd6: 0x0db7, 0xdd7: 0x0e0f,
+ 0xdd8: 0x0e5b, 0xdd9: 0x0e53, 0xdda: 0x0e67, 0xddb: 0x0e83, 0xddc: 0x0ebb, 0xddd: 0x1013,
+ 0xdde: 0x0edf, 0xddf: 0x0f13, 0xde0: 0x0f1f, 0xde1: 0x0f5f, 0xde2: 0x0f7b, 0xde3: 0x0f9f,
+ 0xde4: 0x0fc3, 0xde5: 0x0fc7, 0xde6: 0x0fe3, 0xde7: 0x0fe7, 0xde8: 0x0ff7, 0xde9: 0x100b,
+ 0xdea: 0x1007, 0xdeb: 0x1037, 0xdec: 0x10b3, 0xded: 0x10cb, 0xdee: 0x10e3, 0xdef: 0x111b,
+ 0xdf0: 0x112f, 0xdf1: 0x114b, 0xdf2: 0x117b, 0xdf3: 0x122f, 0xdf4: 0x1257, 0xdf5: 0x12cb,
+ 0xdf6: 0x1313, 0xdf7: 0x131f, 0xdf8: 0x1327, 0xdf9: 0x133f, 0xdfa: 0x1353, 0xdfb: 0x1343,
+ 0xdfc: 0x135b, 0xdfd: 0x1357, 0xdfe: 0x134f, 0xdff: 0x135f,
+ // Block 0x38, offset 0xe00
+ 0xe00: 0x136b, 0xe01: 0x13a7, 0xe02: 0x13e3, 0xe03: 0x1413, 0xe04: 0x144b, 0xe05: 0x146b,
+ 0xe06: 0x14b7, 0xe07: 0x14db, 0xe08: 0x14fb, 0xe09: 0x150f, 0xe0a: 0x151f, 0xe0b: 0x152b,
+ 0xe0c: 0x1537, 0xe0d: 0x158b, 0xe0e: 0x162b, 0xe0f: 0x16b5, 0xe10: 0x16b0, 0xe11: 0x16e2,
+ 0xe12: 0x0607, 0xe13: 0x062f, 0xe14: 0x0633, 0xe15: 0x1764, 0xe16: 0x1791, 0xe17: 0x1809,
+ 0xe18: 0x1617, 0xe19: 0x1627,
+ // Block 0x39, offset 0xe40
+ 0xe40: 0x19d5, 0xe41: 0x19d8, 0xe42: 0x19db, 0xe43: 0x1c08, 0xe44: 0x1c0c, 0xe45: 0x1a5f,
+ 0xe46: 0x1a5f,
+ 0xe53: 0x1d75, 0xe54: 0x1d66, 0xe55: 0x1d6b, 0xe56: 0x1d7a, 0xe57: 0x1d70,
+ 0xe5d: 0x4390,
+ 0xe5e: 0x8115, 0xe5f: 0x4402, 0xe60: 0x022d, 0xe61: 0x0215, 0xe62: 0x021e, 0xe63: 0x0221,
+ 0xe64: 0x0224, 0xe65: 0x0227, 0xe66: 0x022a, 0xe67: 0x0230, 0xe68: 0x0233, 0xe69: 0x0017,
+ 0xe6a: 0x43f0, 0xe6b: 0x43f6, 0xe6c: 0x44f4, 0xe6d: 0x44fc, 0xe6e: 0x4348, 0xe6f: 0x434e,
+ 0xe70: 0x4354, 0xe71: 0x435a, 0xe72: 0x4366, 0xe73: 0x436c, 0xe74: 0x4372, 0xe75: 0x437e,
+ 0xe76: 0x4384, 0xe78: 0x438a, 0xe79: 0x4396, 0xe7a: 0x439c, 0xe7b: 0x43a2,
+ 0xe7c: 0x43ae, 0xe7e: 0x43b4,
+ // Block 0x3a, offset 0xe80
+ 0xe80: 0x43ba, 0xe81: 0x43c0, 0xe83: 0x43c6, 0xe84: 0x43cc,
+ 0xe86: 0x43d8, 0xe87: 0x43de, 0xe88: 0x43e4, 0xe89: 0x43ea, 0xe8a: 0x43fc, 0xe8b: 0x4378,
+ 0xe8c: 0x4360, 0xe8d: 0x43a8, 0xe8e: 0x43d2, 0xe8f: 0x1d7f, 0xe90: 0x0299, 0xe91: 0x0299,
+ 0xe92: 0x02a2, 0xe93: 0x02a2, 0xe94: 0x02a2, 0xe95: 0x02a2, 0xe96: 0x02a5, 0xe97: 0x02a5,
+ 0xe98: 0x02a5, 0xe99: 0x02a5, 0xe9a: 0x02ab, 0xe9b: 0x02ab, 0xe9c: 0x02ab, 0xe9d: 0x02ab,
+ 0xe9e: 0x029f, 0xe9f: 0x029f, 0xea0: 0x029f, 0xea1: 0x029f, 0xea2: 0x02a8, 0xea3: 0x02a8,
+ 0xea4: 0x02a8, 0xea5: 0x02a8, 0xea6: 0x029c, 0xea7: 0x029c, 0xea8: 0x029c, 0xea9: 0x029c,
+ 0xeaa: 0x02cf, 0xeab: 0x02cf, 0xeac: 0x02cf, 0xead: 0x02cf, 0xeae: 0x02d2, 0xeaf: 0x02d2,
+ 0xeb0: 0x02d2, 0xeb1: 0x02d2, 0xeb2: 0x02b1, 0xeb3: 0x02b1, 0xeb4: 0x02b1, 0xeb5: 0x02b1,
+ 0xeb6: 0x02ae, 0xeb7: 0x02ae, 0xeb8: 0x02ae, 0xeb9: 0x02ae, 0xeba: 0x02b4, 0xebb: 0x02b4,
+ 0xebc: 0x02b4, 0xebd: 0x02b4, 0xebe: 0x02b7, 0xebf: 0x02b7,
+ // Block 0x3b, offset 0xec0
+ 0xec0: 0x02b7, 0xec1: 0x02b7, 0xec2: 0x02c0, 0xec3: 0x02c0, 0xec4: 0x02bd, 0xec5: 0x02bd,
+ 0xec6: 0x02c3, 0xec7: 0x02c3, 0xec8: 0x02ba, 0xec9: 0x02ba, 0xeca: 0x02c9, 0xecb: 0x02c9,
+ 0xecc: 0x02c6, 0xecd: 0x02c6, 0xece: 0x02d5, 0xecf: 0x02d5, 0xed0: 0x02d5, 0xed1: 0x02d5,
+ 0xed2: 0x02db, 0xed3: 0x02db, 0xed4: 0x02db, 0xed5: 0x02db, 0xed6: 0x02e1, 0xed7: 0x02e1,
+ 0xed8: 0x02e1, 0xed9: 0x02e1, 0xeda: 0x02de, 0xedb: 0x02de, 0xedc: 0x02de, 0xedd: 0x02de,
+ 0xede: 0x02e4, 0xedf: 0x02e4, 0xee0: 0x02e7, 0xee1: 0x02e7, 0xee2: 0x02e7, 0xee3: 0x02e7,
+ 0xee4: 0x446e, 0xee5: 0x446e, 0xee6: 0x02ed, 0xee7: 0x02ed, 0xee8: 0x02ed, 0xee9: 0x02ed,
+ 0xeea: 0x02ea, 0xeeb: 0x02ea, 0xeec: 0x02ea, 0xeed: 0x02ea, 0xeee: 0x0308, 0xeef: 0x0308,
+ 0xef0: 0x4468, 0xef1: 0x4468,
+ // Block 0x3c, offset 0xf00
+ 0xf13: 0x02d8, 0xf14: 0x02d8, 0xf15: 0x02d8, 0xf16: 0x02d8, 0xf17: 0x02f6,
+ 0xf18: 0x02f6, 0xf19: 0x02f3, 0xf1a: 0x02f3, 0xf1b: 0x02f9, 0xf1c: 0x02f9, 0xf1d: 0x204f,
+ 0xf1e: 0x02ff, 0xf1f: 0x02ff, 0xf20: 0x02f0, 0xf21: 0x02f0, 0xf22: 0x02fc, 0xf23: 0x02fc,
+ 0xf24: 0x0305, 0xf25: 0x0305, 0xf26: 0x0305, 0xf27: 0x0305, 0xf28: 0x028d, 0xf29: 0x028d,
+ 0xf2a: 0x25aa, 0xf2b: 0x25aa, 0xf2c: 0x261a, 0xf2d: 0x261a, 0xf2e: 0x25e9, 0xf2f: 0x25e9,
+ 0xf30: 0x2605, 0xf31: 0x2605, 0xf32: 0x25fe, 0xf33: 0x25fe, 0xf34: 0x260c, 0xf35: 0x260c,
+ 0xf36: 0x2613, 0xf37: 0x2613, 0xf38: 0x2613, 0xf39: 0x25f0, 0xf3a: 0x25f0, 0xf3b: 0x25f0,
+ 0xf3c: 0x0302, 0xf3d: 0x0302, 0xf3e: 0x0302, 0xf3f: 0x0302,
+ // Block 0x3d, offset 0xf40
+ 0xf40: 0x25b1, 0xf41: 0x25b8, 0xf42: 0x25d4, 0xf43: 0x25f0, 0xf44: 0x25f7, 0xf45: 0x1d89,
+ 0xf46: 0x1d8e, 0xf47: 0x1d93, 0xf48: 0x1da2, 0xf49: 0x1db1, 0xf4a: 0x1db6, 0xf4b: 0x1dbb,
+ 0xf4c: 0x1dc0, 0xf4d: 0x1dc5, 0xf4e: 0x1dd4, 0xf4f: 0x1de3, 0xf50: 0x1de8, 0xf51: 0x1ded,
+ 0xf52: 0x1dfc, 0xf53: 0x1e0b, 0xf54: 0x1e10, 0xf55: 0x1e15, 0xf56: 0x1e1a, 0xf57: 0x1e29,
+ 0xf58: 0x1e2e, 0xf59: 0x1e3d, 0xf5a: 0x1e42, 0xf5b: 0x1e47, 0xf5c: 0x1e56, 0xf5d: 0x1e5b,
+ 0xf5e: 0x1e60, 0xf5f: 0x1e6a, 0xf60: 0x1ea6, 0xf61: 0x1eb5, 0xf62: 0x1ec4, 0xf63: 0x1ec9,
+ 0xf64: 0x1ece, 0xf65: 0x1ed8, 0xf66: 0x1ee7, 0xf67: 0x1eec, 0xf68: 0x1efb, 0xf69: 0x1f00,
+ 0xf6a: 0x1f05, 0xf6b: 0x1f14, 0xf6c: 0x1f19, 0xf6d: 0x1f28, 0xf6e: 0x1f2d, 0xf6f: 0x1f32,
+ 0xf70: 0x1f37, 0xf71: 0x1f3c, 0xf72: 0x1f41, 0xf73: 0x1f46, 0xf74: 0x1f4b, 0xf75: 0x1f50,
+ 0xf76: 0x1f55, 0xf77: 0x1f5a, 0xf78: 0x1f5f, 0xf79: 0x1f64, 0xf7a: 0x1f69, 0xf7b: 0x1f6e,
+ 0xf7c: 0x1f73, 0xf7d: 0x1f78, 0xf7e: 0x1f7d, 0xf7f: 0x1f87,
+ // Block 0x3e, offset 0xf80
+ 0xf80: 0x1f8c, 0xf81: 0x1f91, 0xf82: 0x1f96, 0xf83: 0x1fa0, 0xf84: 0x1fa5, 0xf85: 0x1faf,
+ 0xf86: 0x1fb4, 0xf87: 0x1fb9, 0xf88: 0x1fbe, 0xf89: 0x1fc3, 0xf8a: 0x1fc8, 0xf8b: 0x1fcd,
+ 0xf8c: 0x1fd2, 0xf8d: 0x1fd7, 0xf8e: 0x1fe6, 0xf8f: 0x1ff5, 0xf90: 0x1ffa, 0xf91: 0x1fff,
+ 0xf92: 0x2004, 0xf93: 0x2009, 0xf94: 0x200e, 0xf95: 0x2018, 0xf96: 0x201d, 0xf97: 0x2022,
+ 0xf98: 0x2031, 0xf99: 0x2040, 0xf9a: 0x2045, 0xf9b: 0x4420, 0xf9c: 0x4426, 0xf9d: 0x445c,
+ 0xf9e: 0x44b3, 0xf9f: 0x44ba, 0xfa0: 0x44c1, 0xfa1: 0x44c8, 0xfa2: 0x44cf, 0xfa3: 0x44d6,
+ 0xfa4: 0x25c6, 0xfa5: 0x25cd, 0xfa6: 0x25d4, 0xfa7: 0x25db, 0xfa8: 0x25f0, 0xfa9: 0x25f7,
+ 0xfaa: 0x1d98, 0xfab: 0x1d9d, 0xfac: 0x1da2, 0xfad: 0x1da7, 0xfae: 0x1db1, 0xfaf: 0x1db6,
+ 0xfb0: 0x1dca, 0xfb1: 0x1dcf, 0xfb2: 0x1dd4, 0xfb3: 0x1dd9, 0xfb4: 0x1de3, 0xfb5: 0x1de8,
+ 0xfb6: 0x1df2, 0xfb7: 0x1df7, 0xfb8: 0x1dfc, 0xfb9: 0x1e01, 0xfba: 0x1e0b, 0xfbb: 0x1e10,
+ 0xfbc: 0x1f3c, 0xfbd: 0x1f41, 0xfbe: 0x1f50, 0xfbf: 0x1f55,
+ // Block 0x3f, offset 0xfc0
+ 0xfc0: 0x1f5a, 0xfc1: 0x1f6e, 0xfc2: 0x1f73, 0xfc3: 0x1f78, 0xfc4: 0x1f7d, 0xfc5: 0x1f96,
+ 0xfc6: 0x1fa0, 0xfc7: 0x1fa5, 0xfc8: 0x1faa, 0xfc9: 0x1fbe, 0xfca: 0x1fdc, 0xfcb: 0x1fe1,
+ 0xfcc: 0x1fe6, 0xfcd: 0x1feb, 0xfce: 0x1ff5, 0xfcf: 0x1ffa, 0xfd0: 0x445c, 0xfd1: 0x2027,
+ 0xfd2: 0x202c, 0xfd3: 0x2031, 0xfd4: 0x2036, 0xfd5: 0x2040, 0xfd6: 0x2045, 0xfd7: 0x25b1,
+ 0xfd8: 0x25b8, 0xfd9: 0x25bf, 0xfda: 0x25d4, 0xfdb: 0x25e2, 0xfdc: 0x1d89, 0xfdd: 0x1d8e,
+ 0xfde: 0x1d93, 0xfdf: 0x1da2, 0xfe0: 0x1dac, 0xfe1: 0x1dbb, 0xfe2: 0x1dc0, 0xfe3: 0x1dc5,
+ 0xfe4: 0x1dd4, 0xfe5: 0x1dde, 0xfe6: 0x1dfc, 0xfe7: 0x1e15, 0xfe8: 0x1e1a, 0xfe9: 0x1e29,
+ 0xfea: 0x1e2e, 0xfeb: 0x1e3d, 0xfec: 0x1e47, 0xfed: 0x1e56, 0xfee: 0x1e5b, 0xfef: 0x1e60,
+ 0xff0: 0x1e6a, 0xff1: 0x1ea6, 0xff2: 0x1eab, 0xff3: 0x1eb5, 0xff4: 0x1ec4, 0xff5: 0x1ec9,
+ 0xff6: 0x1ece, 0xff7: 0x1ed8, 0xff8: 0x1ee7, 0xff9: 0x1efb, 0xffa: 0x1f00, 0xffb: 0x1f05,
+ 0xffc: 0x1f14, 0xffd: 0x1f19, 0xffe: 0x1f28, 0xfff: 0x1f2d,
+ // Block 0x40, offset 0x1000
+ 0x1000: 0x1f32, 0x1001: 0x1f37, 0x1002: 0x1f46, 0x1003: 0x1f4b, 0x1004: 0x1f5f, 0x1005: 0x1f64,
+ 0x1006: 0x1f69, 0x1007: 0x1f6e, 0x1008: 0x1f73, 0x1009: 0x1f87, 0x100a: 0x1f8c, 0x100b: 0x1f91,
+ 0x100c: 0x1f96, 0x100d: 0x1f9b, 0x100e: 0x1faf, 0x100f: 0x1fb4, 0x1010: 0x1fb9, 0x1011: 0x1fbe,
+ 0x1012: 0x1fcd, 0x1013: 0x1fd2, 0x1014: 0x1fd7, 0x1015: 0x1fe6, 0x1016: 0x1ff0, 0x1017: 0x1fff,
+ 0x1018: 0x2004, 0x1019: 0x4450, 0x101a: 0x2018, 0x101b: 0x201d, 0x101c: 0x2022, 0x101d: 0x2031,
+ 0x101e: 0x203b, 0x101f: 0x25d4, 0x1020: 0x25e2, 0x1021: 0x1da2, 0x1022: 0x1dac, 0x1023: 0x1dd4,
+ 0x1024: 0x1dde, 0x1025: 0x1dfc, 0x1026: 0x1e06, 0x1027: 0x1e6a, 0x1028: 0x1e6f, 0x1029: 0x1e92,
+ 0x102a: 0x1e97, 0x102b: 0x1f6e, 0x102c: 0x1f73, 0x102d: 0x1f96, 0x102e: 0x1fe6, 0x102f: 0x1ff0,
+ 0x1030: 0x2031, 0x1031: 0x203b, 0x1032: 0x4504, 0x1033: 0x450c, 0x1034: 0x4514, 0x1035: 0x1ef1,
+ 0x1036: 0x1ef6, 0x1037: 0x1f0a, 0x1038: 0x1f0f, 0x1039: 0x1f1e, 0x103a: 0x1f23, 0x103b: 0x1e74,
+ 0x103c: 0x1e79, 0x103d: 0x1e9c, 0x103e: 0x1ea1, 0x103f: 0x1e33,
+ // Block 0x41, offset 0x1040
+ 0x1040: 0x1e38, 0x1041: 0x1e1f, 0x1042: 0x1e24, 0x1043: 0x1e4c, 0x1044: 0x1e51, 0x1045: 0x1eba,
+ 0x1046: 0x1ebf, 0x1047: 0x1edd, 0x1048: 0x1ee2, 0x1049: 0x1e7e, 0x104a: 0x1e83, 0x104b: 0x1e88,
+ 0x104c: 0x1e92, 0x104d: 0x1e8d, 0x104e: 0x1e65, 0x104f: 0x1eb0, 0x1050: 0x1ed3, 0x1051: 0x1ef1,
+ 0x1052: 0x1ef6, 0x1053: 0x1f0a, 0x1054: 0x1f0f, 0x1055: 0x1f1e, 0x1056: 0x1f23, 0x1057: 0x1e74,
+ 0x1058: 0x1e79, 0x1059: 0x1e9c, 0x105a: 0x1ea1, 0x105b: 0x1e33, 0x105c: 0x1e38, 0x105d: 0x1e1f,
+ 0x105e: 0x1e24, 0x105f: 0x1e4c, 0x1060: 0x1e51, 0x1061: 0x1eba, 0x1062: 0x1ebf, 0x1063: 0x1edd,
+ 0x1064: 0x1ee2, 0x1065: 0x1e7e, 0x1066: 0x1e83, 0x1067: 0x1e88, 0x1068: 0x1e92, 0x1069: 0x1e8d,
+ 0x106a: 0x1e65, 0x106b: 0x1eb0, 0x106c: 0x1ed3, 0x106d: 0x1e7e, 0x106e: 0x1e83, 0x106f: 0x1e88,
+ 0x1070: 0x1e92, 0x1071: 0x1e6f, 0x1072: 0x1e97, 0x1073: 0x1eec, 0x1074: 0x1e56, 0x1075: 0x1e5b,
+ 0x1076: 0x1e60, 0x1077: 0x1e7e, 0x1078: 0x1e83, 0x1079: 0x1e88, 0x107a: 0x1eec, 0x107b: 0x1efb,
+ 0x107c: 0x4408, 0x107d: 0x4408,
+ // Block 0x42, offset 0x1080
+ 0x1090: 0x2311, 0x1091: 0x2326,
+ 0x1092: 0x2326, 0x1093: 0x232d, 0x1094: 0x2334, 0x1095: 0x2349, 0x1096: 0x2350, 0x1097: 0x2357,
+ 0x1098: 0x237a, 0x1099: 0x237a, 0x109a: 0x239d, 0x109b: 0x2396, 0x109c: 0x23b2, 0x109d: 0x23a4,
+ 0x109e: 0x23ab, 0x109f: 0x23ce, 0x10a0: 0x23ce, 0x10a1: 0x23c7, 0x10a2: 0x23d5, 0x10a3: 0x23d5,
+ 0x10a4: 0x23ff, 0x10a5: 0x23ff, 0x10a6: 0x241b, 0x10a7: 0x23e3, 0x10a8: 0x23e3, 0x10a9: 0x23dc,
+ 0x10aa: 0x23f1, 0x10ab: 0x23f1, 0x10ac: 0x23f8, 0x10ad: 0x23f8, 0x10ae: 0x2422, 0x10af: 0x2430,
+ 0x10b0: 0x2430, 0x10b1: 0x2437, 0x10b2: 0x2437, 0x10b3: 0x243e, 0x10b4: 0x2445, 0x10b5: 0x244c,
+ 0x10b6: 0x2453, 0x10b7: 0x2453, 0x10b8: 0x245a, 0x10b9: 0x2468, 0x10ba: 0x2476, 0x10bb: 0x246f,
+ 0x10bc: 0x247d, 0x10bd: 0x247d, 0x10be: 0x2492, 0x10bf: 0x2499,
+ // Block 0x43, offset 0x10c0
+ 0x10c0: 0x24ca, 0x10c1: 0x24d8, 0x10c2: 0x24d1, 0x10c3: 0x24b5, 0x10c4: 0x24b5, 0x10c5: 0x24df,
+ 0x10c6: 0x24df, 0x10c7: 0x24e6, 0x10c8: 0x24e6, 0x10c9: 0x2510, 0x10ca: 0x2517, 0x10cb: 0x251e,
+ 0x10cc: 0x24f4, 0x10cd: 0x2502, 0x10ce: 0x2525, 0x10cf: 0x252c,
+ 0x10d2: 0x24fb, 0x10d3: 0x2580, 0x10d4: 0x2587, 0x10d5: 0x255d, 0x10d6: 0x2564, 0x10d7: 0x2548,
+ 0x10d8: 0x2548, 0x10d9: 0x254f, 0x10da: 0x2579, 0x10db: 0x2572, 0x10dc: 0x259c, 0x10dd: 0x259c,
+ 0x10de: 0x230a, 0x10df: 0x231f, 0x10e0: 0x2318, 0x10e1: 0x2342, 0x10e2: 0x233b, 0x10e3: 0x2365,
+ 0x10e4: 0x235e, 0x10e5: 0x2388, 0x10e6: 0x236c, 0x10e7: 0x2381, 0x10e8: 0x23b9, 0x10e9: 0x2406,
+ 0x10ea: 0x23ea, 0x10eb: 0x2429, 0x10ec: 0x24c3, 0x10ed: 0x24ed, 0x10ee: 0x2595, 0x10ef: 0x258e,
+ 0x10f0: 0x25a3, 0x10f1: 0x253a, 0x10f2: 0x24a0, 0x10f3: 0x256b, 0x10f4: 0x2492, 0x10f5: 0x24ca,
+ 0x10f6: 0x2461, 0x10f7: 0x24ae, 0x10f8: 0x2541, 0x10f9: 0x2533, 0x10fa: 0x24bc, 0x10fb: 0x24a7,
+ 0x10fc: 0x24bc, 0x10fd: 0x2541, 0x10fe: 0x2373, 0x10ff: 0x238f,
+ // Block 0x44, offset 0x1100
+ 0x1100: 0x2509, 0x1101: 0x2484, 0x1102: 0x2303, 0x1103: 0x24a7, 0x1104: 0x244c, 0x1105: 0x241b,
+ 0x1106: 0x23c0, 0x1107: 0x2556,
+ 0x1130: 0x2414, 0x1131: 0x248b, 0x1132: 0x27bf, 0x1133: 0x27b6, 0x1134: 0x27ec, 0x1135: 0x27da,
+ 0x1136: 0x27c8, 0x1137: 0x27e3, 0x1138: 0x27f5, 0x1139: 0x240d, 0x113a: 0x2c7c, 0x113b: 0x2afc,
+ 0x113c: 0x27d1,
+ // Block 0x45, offset 0x1140
+ 0x1150: 0x0019, 0x1151: 0x0483,
+ 0x1152: 0x0487, 0x1153: 0x0035, 0x1154: 0x0037, 0x1155: 0x0003, 0x1156: 0x003f, 0x1157: 0x04bf,
+ 0x1158: 0x04c3, 0x1159: 0x1b5c,
+ 0x1160: 0x8132, 0x1161: 0x8132, 0x1162: 0x8132, 0x1163: 0x8132,
+ 0x1164: 0x8132, 0x1165: 0x8132, 0x1166: 0x8132, 0x1167: 0x812d, 0x1168: 0x812d, 0x1169: 0x812d,
+ 0x116a: 0x812d, 0x116b: 0x812d, 0x116c: 0x812d, 0x116d: 0x812d, 0x116e: 0x8132, 0x116f: 0x8132,
+ 0x1170: 0x1873, 0x1171: 0x0443, 0x1172: 0x043f, 0x1173: 0x007f, 0x1174: 0x007f, 0x1175: 0x0011,
+ 0x1176: 0x0013, 0x1177: 0x00b7, 0x1178: 0x00bb, 0x1179: 0x04b7, 0x117a: 0x04bb, 0x117b: 0x04ab,
+ 0x117c: 0x04af, 0x117d: 0x0493, 0x117e: 0x0497, 0x117f: 0x048b,
+ // Block 0x46, offset 0x1180
+ 0x1180: 0x048f, 0x1181: 0x049b, 0x1182: 0x049f, 0x1183: 0x04a3, 0x1184: 0x04a7,
+ 0x1187: 0x0077, 0x1188: 0x007b, 0x1189: 0x4269, 0x118a: 0x4269, 0x118b: 0x4269,
+ 0x118c: 0x4269, 0x118d: 0x007f, 0x118e: 0x007f, 0x118f: 0x007f, 0x1190: 0x0019, 0x1191: 0x0483,
+ 0x1192: 0x001d, 0x1194: 0x0037, 0x1195: 0x0035, 0x1196: 0x003f, 0x1197: 0x0003,
+ 0x1198: 0x0443, 0x1199: 0x0011, 0x119a: 0x0013, 0x119b: 0x00b7, 0x119c: 0x00bb, 0x119d: 0x04b7,
+ 0x119e: 0x04bb, 0x119f: 0x0007, 0x11a0: 0x000d, 0x11a1: 0x0015, 0x11a2: 0x0017, 0x11a3: 0x001b,
+ 0x11a4: 0x0039, 0x11a5: 0x003d, 0x11a6: 0x003b, 0x11a8: 0x0079, 0x11a9: 0x0009,
+ 0x11aa: 0x000b, 0x11ab: 0x0041,
+ 0x11b0: 0x42aa, 0x11b1: 0x442c, 0x11b2: 0x42af, 0x11b4: 0x42b4,
+ 0x11b6: 0x42b9, 0x11b7: 0x4432, 0x11b8: 0x42be, 0x11b9: 0x4438, 0x11ba: 0x42c3, 0x11bb: 0x443e,
+ 0x11bc: 0x42c8, 0x11bd: 0x4444, 0x11be: 0x42cd, 0x11bf: 0x444a,
+ // Block 0x47, offset 0x11c0
+ 0x11c0: 0x0236, 0x11c1: 0x440e, 0x11c2: 0x440e, 0x11c3: 0x4414, 0x11c4: 0x4414, 0x11c5: 0x4456,
+ 0x11c6: 0x4456, 0x11c7: 0x441a, 0x11c8: 0x441a, 0x11c9: 0x4462, 0x11ca: 0x4462, 0x11cb: 0x4462,
+ 0x11cc: 0x4462, 0x11cd: 0x0239, 0x11ce: 0x0239, 0x11cf: 0x023c, 0x11d0: 0x023c, 0x11d1: 0x023c,
+ 0x11d2: 0x023c, 0x11d3: 0x023f, 0x11d4: 0x023f, 0x11d5: 0x0242, 0x11d6: 0x0242, 0x11d7: 0x0242,
+ 0x11d8: 0x0242, 0x11d9: 0x0245, 0x11da: 0x0245, 0x11db: 0x0245, 0x11dc: 0x0245, 0x11dd: 0x0248,
+ 0x11de: 0x0248, 0x11df: 0x0248, 0x11e0: 0x0248, 0x11e1: 0x024b, 0x11e2: 0x024b, 0x11e3: 0x024b,
+ 0x11e4: 0x024b, 0x11e5: 0x024e, 0x11e6: 0x024e, 0x11e7: 0x024e, 0x11e8: 0x024e, 0x11e9: 0x0251,
+ 0x11ea: 0x0251, 0x11eb: 0x0254, 0x11ec: 0x0254, 0x11ed: 0x0257, 0x11ee: 0x0257, 0x11ef: 0x025a,
+ 0x11f0: 0x025a, 0x11f1: 0x025d, 0x11f2: 0x025d, 0x11f3: 0x025d, 0x11f4: 0x025d, 0x11f5: 0x0260,
+ 0x11f6: 0x0260, 0x11f7: 0x0260, 0x11f8: 0x0260, 0x11f9: 0x0263, 0x11fa: 0x0263, 0x11fb: 0x0263,
+ 0x11fc: 0x0263, 0x11fd: 0x0266, 0x11fe: 0x0266, 0x11ff: 0x0266,
+ // Block 0x48, offset 0x1200
+ 0x1200: 0x0266, 0x1201: 0x0269, 0x1202: 0x0269, 0x1203: 0x0269, 0x1204: 0x0269, 0x1205: 0x026c,
+ 0x1206: 0x026c, 0x1207: 0x026c, 0x1208: 0x026c, 0x1209: 0x026f, 0x120a: 0x026f, 0x120b: 0x026f,
+ 0x120c: 0x026f, 0x120d: 0x0272, 0x120e: 0x0272, 0x120f: 0x0272, 0x1210: 0x0272, 0x1211: 0x0275,
+ 0x1212: 0x0275, 0x1213: 0x0275, 0x1214: 0x0275, 0x1215: 0x0278, 0x1216: 0x0278, 0x1217: 0x0278,
+ 0x1218: 0x0278, 0x1219: 0x027b, 0x121a: 0x027b, 0x121b: 0x027b, 0x121c: 0x027b, 0x121d: 0x027e,
+ 0x121e: 0x027e, 0x121f: 0x027e, 0x1220: 0x027e, 0x1221: 0x0281, 0x1222: 0x0281, 0x1223: 0x0281,
+ 0x1224: 0x0281, 0x1225: 0x0284, 0x1226: 0x0284, 0x1227: 0x0284, 0x1228: 0x0284, 0x1229: 0x0287,
+ 0x122a: 0x0287, 0x122b: 0x0287, 0x122c: 0x0287, 0x122d: 0x028a, 0x122e: 0x028a, 0x122f: 0x028d,
+ 0x1230: 0x028d, 0x1231: 0x0290, 0x1232: 0x0290, 0x1233: 0x0290, 0x1234: 0x0290, 0x1235: 0x2e00,
+ 0x1236: 0x2e00, 0x1237: 0x2e08, 0x1238: 0x2e08, 0x1239: 0x2e10, 0x123a: 0x2e10, 0x123b: 0x1f82,
+ 0x123c: 0x1f82,
+ // Block 0x49, offset 0x1240
+ 0x1240: 0x0081, 0x1241: 0x0083, 0x1242: 0x0085, 0x1243: 0x0087, 0x1244: 0x0089, 0x1245: 0x008b,
+ 0x1246: 0x008d, 0x1247: 0x008f, 0x1248: 0x0091, 0x1249: 0x0093, 0x124a: 0x0095, 0x124b: 0x0097,
+ 0x124c: 0x0099, 0x124d: 0x009b, 0x124e: 0x009d, 0x124f: 0x009f, 0x1250: 0x00a1, 0x1251: 0x00a3,
+ 0x1252: 0x00a5, 0x1253: 0x00a7, 0x1254: 0x00a9, 0x1255: 0x00ab, 0x1256: 0x00ad, 0x1257: 0x00af,
+ 0x1258: 0x00b1, 0x1259: 0x00b3, 0x125a: 0x00b5, 0x125b: 0x00b7, 0x125c: 0x00b9, 0x125d: 0x00bb,
+ 0x125e: 0x00bd, 0x125f: 0x0477, 0x1260: 0x047b, 0x1261: 0x0487, 0x1262: 0x049b, 0x1263: 0x049f,
+ 0x1264: 0x0483, 0x1265: 0x05ab, 0x1266: 0x05a3, 0x1267: 0x04c7, 0x1268: 0x04cf, 0x1269: 0x04d7,
+ 0x126a: 0x04df, 0x126b: 0x04e7, 0x126c: 0x056b, 0x126d: 0x0573, 0x126e: 0x057b, 0x126f: 0x051f,
+ 0x1270: 0x05af, 0x1271: 0x04cb, 0x1272: 0x04d3, 0x1273: 0x04db, 0x1274: 0x04e3, 0x1275: 0x04eb,
+ 0x1276: 0x04ef, 0x1277: 0x04f3, 0x1278: 0x04f7, 0x1279: 0x04fb, 0x127a: 0x04ff, 0x127b: 0x0503,
+ 0x127c: 0x0507, 0x127d: 0x050b, 0x127e: 0x050f, 0x127f: 0x0513,
+ // Block 0x4a, offset 0x1280
+ 0x1280: 0x0517, 0x1281: 0x051b, 0x1282: 0x0523, 0x1283: 0x0527, 0x1284: 0x052b, 0x1285: 0x052f,
+ 0x1286: 0x0533, 0x1287: 0x0537, 0x1288: 0x053b, 0x1289: 0x053f, 0x128a: 0x0543, 0x128b: 0x0547,
+ 0x128c: 0x054b, 0x128d: 0x054f, 0x128e: 0x0553, 0x128f: 0x0557, 0x1290: 0x055b, 0x1291: 0x055f,
+ 0x1292: 0x0563, 0x1293: 0x0567, 0x1294: 0x056f, 0x1295: 0x0577, 0x1296: 0x057f, 0x1297: 0x0583,
+ 0x1298: 0x0587, 0x1299: 0x058b, 0x129a: 0x058f, 0x129b: 0x0593, 0x129c: 0x0597, 0x129d: 0x05a7,
+ 0x129e: 0x4a78, 0x129f: 0x4a7e, 0x12a0: 0x03c3, 0x12a1: 0x0313, 0x12a2: 0x0317, 0x12a3: 0x4a3b,
+ 0x12a4: 0x031b, 0x12a5: 0x4a41, 0x12a6: 0x4a47, 0x12a7: 0x031f, 0x12a8: 0x0323, 0x12a9: 0x0327,
+ 0x12aa: 0x4a4d, 0x12ab: 0x4a53, 0x12ac: 0x4a59, 0x12ad: 0x4a5f, 0x12ae: 0x4a65, 0x12af: 0x4a6b,
+ 0x12b0: 0x0367, 0x12b1: 0x032b, 0x12b2: 0x032f, 0x12b3: 0x0333, 0x12b4: 0x037b, 0x12b5: 0x0337,
+ 0x12b6: 0x033b, 0x12b7: 0x033f, 0x12b8: 0x0343, 0x12b9: 0x0347, 0x12ba: 0x034b, 0x12bb: 0x034f,
+ 0x12bc: 0x0353, 0x12bd: 0x0357, 0x12be: 0x035b,
+ // Block 0x4b, offset 0x12c0
+ 0x12c2: 0x49bd, 0x12c3: 0x49c3, 0x12c4: 0x49c9, 0x12c5: 0x49cf,
+ 0x12c6: 0x49d5, 0x12c7: 0x49db, 0x12ca: 0x49e1, 0x12cb: 0x49e7,
+ 0x12cc: 0x49ed, 0x12cd: 0x49f3, 0x12ce: 0x49f9, 0x12cf: 0x49ff,
+ 0x12d2: 0x4a05, 0x12d3: 0x4a0b, 0x12d4: 0x4a11, 0x12d5: 0x4a17, 0x12d6: 0x4a1d, 0x12d7: 0x4a23,
+ 0x12da: 0x4a29, 0x12db: 0x4a2f, 0x12dc: 0x4a35,
+ 0x12e0: 0x00bf, 0x12e1: 0x00c2, 0x12e2: 0x00cb, 0x12e3: 0x4264,
+ 0x12e4: 0x00c8, 0x12e5: 0x00c5, 0x12e6: 0x0447, 0x12e8: 0x046b, 0x12e9: 0x044b,
+ 0x12ea: 0x044f, 0x12eb: 0x0453, 0x12ec: 0x0457, 0x12ed: 0x046f, 0x12ee: 0x0473,
+ // Block 0x4c, offset 0x1300
+ 0x1300: 0x0063, 0x1301: 0x0065, 0x1302: 0x0067, 0x1303: 0x0069, 0x1304: 0x006b, 0x1305: 0x006d,
+ 0x1306: 0x006f, 0x1307: 0x0071, 0x1308: 0x0073, 0x1309: 0x0075, 0x130a: 0x0083, 0x130b: 0x0085,
+ 0x130c: 0x0087, 0x130d: 0x0089, 0x130e: 0x008b, 0x130f: 0x008d, 0x1310: 0x008f, 0x1311: 0x0091,
+ 0x1312: 0x0093, 0x1313: 0x0095, 0x1314: 0x0097, 0x1315: 0x0099, 0x1316: 0x009b, 0x1317: 0x009d,
+ 0x1318: 0x009f, 0x1319: 0x00a1, 0x131a: 0x00a3, 0x131b: 0x00a5, 0x131c: 0x00a7, 0x131d: 0x00a9,
+ 0x131e: 0x00ab, 0x131f: 0x00ad, 0x1320: 0x00af, 0x1321: 0x00b1, 0x1322: 0x00b3, 0x1323: 0x00b5,
+ 0x1324: 0x00dd, 0x1325: 0x00f2, 0x1328: 0x0173, 0x1329: 0x0176,
+ 0x132a: 0x0179, 0x132b: 0x017c, 0x132c: 0x017f, 0x132d: 0x0182, 0x132e: 0x0185, 0x132f: 0x0188,
+ 0x1330: 0x018b, 0x1331: 0x018e, 0x1332: 0x0191, 0x1333: 0x0194, 0x1334: 0x0197, 0x1335: 0x019a,
+ 0x1336: 0x019d, 0x1337: 0x01a0, 0x1338: 0x01a3, 0x1339: 0x0188, 0x133a: 0x01a6, 0x133b: 0x01a9,
+ 0x133c: 0x01ac, 0x133d: 0x01af, 0x133e: 0x01b2, 0x133f: 0x01b5,
+ // Block 0x4d, offset 0x1340
+ 0x1340: 0x01fd, 0x1341: 0x0200, 0x1342: 0x0203, 0x1343: 0x045b, 0x1344: 0x01c7, 0x1345: 0x01d0,
+ 0x1346: 0x01d6, 0x1347: 0x01fa, 0x1348: 0x01eb, 0x1349: 0x01e8, 0x134a: 0x0206, 0x134b: 0x0209,
+ 0x134e: 0x0021, 0x134f: 0x0023, 0x1350: 0x0025, 0x1351: 0x0027,
+ 0x1352: 0x0029, 0x1353: 0x002b, 0x1354: 0x002d, 0x1355: 0x002f, 0x1356: 0x0031, 0x1357: 0x0033,
+ 0x1358: 0x0021, 0x1359: 0x0023, 0x135a: 0x0025, 0x135b: 0x0027, 0x135c: 0x0029, 0x135d: 0x002b,
+ 0x135e: 0x002d, 0x135f: 0x002f, 0x1360: 0x0031, 0x1361: 0x0033, 0x1362: 0x0021, 0x1363: 0x0023,
+ 0x1364: 0x0025, 0x1365: 0x0027, 0x1366: 0x0029, 0x1367: 0x002b, 0x1368: 0x002d, 0x1369: 0x002f,
+ 0x136a: 0x0031, 0x136b: 0x0033, 0x136c: 0x0021, 0x136d: 0x0023, 0x136e: 0x0025, 0x136f: 0x0027,
+ 0x1370: 0x0029, 0x1371: 0x002b, 0x1372: 0x002d, 0x1373: 0x002f, 0x1374: 0x0031, 0x1375: 0x0033,
+ 0x1376: 0x0021, 0x1377: 0x0023, 0x1378: 0x0025, 0x1379: 0x0027, 0x137a: 0x0029, 0x137b: 0x002b,
+ 0x137c: 0x002d, 0x137d: 0x002f, 0x137e: 0x0031, 0x137f: 0x0033,
+ // Block 0x4e, offset 0x1380
+ 0x1380: 0x0239, 0x1381: 0x023c, 0x1382: 0x0248, 0x1383: 0x0251, 0x1385: 0x028a,
+ 0x1386: 0x025a, 0x1387: 0x024b, 0x1388: 0x0269, 0x1389: 0x0290, 0x138a: 0x027b, 0x138b: 0x027e,
+ 0x138c: 0x0281, 0x138d: 0x0284, 0x138e: 0x025d, 0x138f: 0x026f, 0x1390: 0x0275, 0x1391: 0x0263,
+ 0x1392: 0x0278, 0x1393: 0x0257, 0x1394: 0x0260, 0x1395: 0x0242, 0x1396: 0x0245, 0x1397: 0x024e,
+ 0x1398: 0x0254, 0x1399: 0x0266, 0x139a: 0x026c, 0x139b: 0x0272, 0x139c: 0x0293, 0x139d: 0x02e4,
+ 0x139e: 0x02cc, 0x139f: 0x0296, 0x13a1: 0x023c, 0x13a2: 0x0248,
+ 0x13a4: 0x0287, 0x13a7: 0x024b, 0x13a9: 0x0290,
+ 0x13aa: 0x027b, 0x13ab: 0x027e, 0x13ac: 0x0281, 0x13ad: 0x0284, 0x13ae: 0x025d, 0x13af: 0x026f,
+ 0x13b0: 0x0275, 0x13b1: 0x0263, 0x13b2: 0x0278, 0x13b4: 0x0260, 0x13b5: 0x0242,
+ 0x13b6: 0x0245, 0x13b7: 0x024e, 0x13b9: 0x0266, 0x13bb: 0x0272,
+ // Block 0x4f, offset 0x13c0
+ 0x13c2: 0x0248,
+ 0x13c7: 0x024b, 0x13c9: 0x0290, 0x13cb: 0x027e,
+ 0x13cd: 0x0284, 0x13ce: 0x025d, 0x13cf: 0x026f, 0x13d1: 0x0263,
+ 0x13d2: 0x0278, 0x13d4: 0x0260, 0x13d7: 0x024e,
+ 0x13d9: 0x0266, 0x13db: 0x0272, 0x13dd: 0x02e4,
+ 0x13df: 0x0296, 0x13e1: 0x023c, 0x13e2: 0x0248,
+ 0x13e4: 0x0287, 0x13e7: 0x024b, 0x13e8: 0x0269, 0x13e9: 0x0290,
+ 0x13ea: 0x027b, 0x13ec: 0x0281, 0x13ed: 0x0284, 0x13ee: 0x025d, 0x13ef: 0x026f,
+ 0x13f0: 0x0275, 0x13f1: 0x0263, 0x13f2: 0x0278, 0x13f4: 0x0260, 0x13f5: 0x0242,
+ 0x13f6: 0x0245, 0x13f7: 0x024e, 0x13f9: 0x0266, 0x13fa: 0x026c, 0x13fb: 0x0272,
+ 0x13fc: 0x0293, 0x13fe: 0x02cc,
+ // Block 0x50, offset 0x1400
+ 0x1400: 0x0239, 0x1401: 0x023c, 0x1402: 0x0248, 0x1403: 0x0251, 0x1404: 0x0287, 0x1405: 0x028a,
+ 0x1406: 0x025a, 0x1407: 0x024b, 0x1408: 0x0269, 0x1409: 0x0290, 0x140b: 0x027e,
+ 0x140c: 0x0281, 0x140d: 0x0284, 0x140e: 0x025d, 0x140f: 0x026f, 0x1410: 0x0275, 0x1411: 0x0263,
+ 0x1412: 0x0278, 0x1413: 0x0257, 0x1414: 0x0260, 0x1415: 0x0242, 0x1416: 0x0245, 0x1417: 0x024e,
+ 0x1418: 0x0254, 0x1419: 0x0266, 0x141a: 0x026c, 0x141b: 0x0272,
+ 0x1421: 0x023c, 0x1422: 0x0248, 0x1423: 0x0251,
+ 0x1425: 0x028a, 0x1426: 0x025a, 0x1427: 0x024b, 0x1428: 0x0269, 0x1429: 0x0290,
+ 0x142b: 0x027e, 0x142c: 0x0281, 0x142d: 0x0284, 0x142e: 0x025d, 0x142f: 0x026f,
+ 0x1430: 0x0275, 0x1431: 0x0263, 0x1432: 0x0278, 0x1433: 0x0257, 0x1434: 0x0260, 0x1435: 0x0242,
+ 0x1436: 0x0245, 0x1437: 0x024e, 0x1438: 0x0254, 0x1439: 0x0266, 0x143a: 0x026c, 0x143b: 0x0272,
+ // Block 0x51, offset 0x1440
+ 0x1440: 0x1879, 0x1441: 0x1876, 0x1442: 0x187c, 0x1443: 0x18a0, 0x1444: 0x18c4, 0x1445: 0x18e8,
+ 0x1446: 0x190c, 0x1447: 0x1915, 0x1448: 0x191b, 0x1449: 0x1921, 0x144a: 0x1927,
+ 0x1450: 0x1a8c, 0x1451: 0x1a90,
+ 0x1452: 0x1a94, 0x1453: 0x1a98, 0x1454: 0x1a9c, 0x1455: 0x1aa0, 0x1456: 0x1aa4, 0x1457: 0x1aa8,
+ 0x1458: 0x1aac, 0x1459: 0x1ab0, 0x145a: 0x1ab4, 0x145b: 0x1ab8, 0x145c: 0x1abc, 0x145d: 0x1ac0,
+ 0x145e: 0x1ac4, 0x145f: 0x1ac8, 0x1460: 0x1acc, 0x1461: 0x1ad0, 0x1462: 0x1ad4, 0x1463: 0x1ad8,
+ 0x1464: 0x1adc, 0x1465: 0x1ae0, 0x1466: 0x1ae4, 0x1467: 0x1ae8, 0x1468: 0x1aec, 0x1469: 0x1af0,
+ 0x146a: 0x271e, 0x146b: 0x0047, 0x146c: 0x0065, 0x146d: 0x193c, 0x146e: 0x19b1,
+ 0x1470: 0x0043, 0x1471: 0x0045, 0x1472: 0x0047, 0x1473: 0x0049, 0x1474: 0x004b, 0x1475: 0x004d,
+ 0x1476: 0x004f, 0x1477: 0x0051, 0x1478: 0x0053, 0x1479: 0x0055, 0x147a: 0x0057, 0x147b: 0x0059,
+ 0x147c: 0x005b, 0x147d: 0x005d, 0x147e: 0x005f, 0x147f: 0x0061,
+ // Block 0x52, offset 0x1480
+ 0x1480: 0x26ad, 0x1481: 0x26c2, 0x1482: 0x0503,
+ 0x1490: 0x0c0f, 0x1491: 0x0a47,
+ 0x1492: 0x08d3, 0x1493: 0x45c4, 0x1494: 0x071b, 0x1495: 0x09ef, 0x1496: 0x132f, 0x1497: 0x09ff,
+ 0x1498: 0x0727, 0x1499: 0x0cd7, 0x149a: 0x0eaf, 0x149b: 0x0caf, 0x149c: 0x0827, 0x149d: 0x0b6b,
+ 0x149e: 0x07bf, 0x149f: 0x0cb7, 0x14a0: 0x0813, 0x14a1: 0x1117, 0x14a2: 0x0f83, 0x14a3: 0x138b,
+ 0x14a4: 0x09d3, 0x14a5: 0x090b, 0x14a6: 0x0e63, 0x14a7: 0x0c1b, 0x14a8: 0x0c47, 0x14a9: 0x06bf,
+ 0x14aa: 0x06cb, 0x14ab: 0x140b, 0x14ac: 0x0adb, 0x14ad: 0x06e7, 0x14ae: 0x08ef, 0x14af: 0x0c3b,
+ 0x14b0: 0x13b3, 0x14b1: 0x0c13, 0x14b2: 0x106f, 0x14b3: 0x10ab, 0x14b4: 0x08f7, 0x14b5: 0x0e43,
+ 0x14b6: 0x0d0b, 0x14b7: 0x0d07, 0x14b8: 0x0f97, 0x14b9: 0x082b, 0x14ba: 0x0957, 0x14bb: 0x1443,
+ // Block 0x53, offset 0x14c0
+ 0x14c0: 0x06fb, 0x14c1: 0x06f3, 0x14c2: 0x0703, 0x14c3: 0x1647, 0x14c4: 0x0747, 0x14c5: 0x0757,
+ 0x14c6: 0x075b, 0x14c7: 0x0763, 0x14c8: 0x076b, 0x14c9: 0x076f, 0x14ca: 0x077b, 0x14cb: 0x0773,
+ 0x14cc: 0x05b3, 0x14cd: 0x165b, 0x14ce: 0x078f, 0x14cf: 0x0793, 0x14d0: 0x0797, 0x14d1: 0x07b3,
+ 0x14d2: 0x164c, 0x14d3: 0x05b7, 0x14d4: 0x079f, 0x14d5: 0x07bf, 0x14d6: 0x1656, 0x14d7: 0x07cf,
+ 0x14d8: 0x07d7, 0x14d9: 0x0737, 0x14da: 0x07df, 0x14db: 0x07e3, 0x14dc: 0x1831, 0x14dd: 0x07ff,
+ 0x14de: 0x0807, 0x14df: 0x05bf, 0x14e0: 0x081f, 0x14e1: 0x0823, 0x14e2: 0x082b, 0x14e3: 0x082f,
+ 0x14e4: 0x05c3, 0x14e5: 0x0847, 0x14e6: 0x084b, 0x14e7: 0x0857, 0x14e8: 0x0863, 0x14e9: 0x0867,
+ 0x14ea: 0x086b, 0x14eb: 0x0873, 0x14ec: 0x0893, 0x14ed: 0x0897, 0x14ee: 0x089f, 0x14ef: 0x08af,
+ 0x14f0: 0x08b7, 0x14f1: 0x08bb, 0x14f2: 0x08bb, 0x14f3: 0x08bb, 0x14f4: 0x166a, 0x14f5: 0x0e93,
+ 0x14f6: 0x08cf, 0x14f7: 0x08d7, 0x14f8: 0x166f, 0x14f9: 0x08e3, 0x14fa: 0x08eb, 0x14fb: 0x08f3,
+ 0x14fc: 0x091b, 0x14fd: 0x0907, 0x14fe: 0x0913, 0x14ff: 0x0917,
+ // Block 0x54, offset 0x1500
+ 0x1500: 0x091f, 0x1501: 0x0927, 0x1502: 0x092b, 0x1503: 0x0933, 0x1504: 0x093b, 0x1505: 0x093f,
+ 0x1506: 0x093f, 0x1507: 0x0947, 0x1508: 0x094f, 0x1509: 0x0953, 0x150a: 0x095f, 0x150b: 0x0983,
+ 0x150c: 0x0967, 0x150d: 0x0987, 0x150e: 0x096b, 0x150f: 0x0973, 0x1510: 0x080b, 0x1511: 0x09cf,
+ 0x1512: 0x0997, 0x1513: 0x099b, 0x1514: 0x099f, 0x1515: 0x0993, 0x1516: 0x09a7, 0x1517: 0x09a3,
+ 0x1518: 0x09bb, 0x1519: 0x1674, 0x151a: 0x09d7, 0x151b: 0x09db, 0x151c: 0x09e3, 0x151d: 0x09ef,
+ 0x151e: 0x09f7, 0x151f: 0x0a13, 0x1520: 0x1679, 0x1521: 0x167e, 0x1522: 0x0a1f, 0x1523: 0x0a23,
+ 0x1524: 0x0a27, 0x1525: 0x0a1b, 0x1526: 0x0a2f, 0x1527: 0x05c7, 0x1528: 0x05cb, 0x1529: 0x0a37,
+ 0x152a: 0x0a3f, 0x152b: 0x0a3f, 0x152c: 0x1683, 0x152d: 0x0a5b, 0x152e: 0x0a5f, 0x152f: 0x0a63,
+ 0x1530: 0x0a6b, 0x1531: 0x1688, 0x1532: 0x0a73, 0x1533: 0x0a77, 0x1534: 0x0b4f, 0x1535: 0x0a7f,
+ 0x1536: 0x05cf, 0x1537: 0x0a8b, 0x1538: 0x0a9b, 0x1539: 0x0aa7, 0x153a: 0x0aa3, 0x153b: 0x1692,
+ 0x153c: 0x0aaf, 0x153d: 0x1697, 0x153e: 0x0abb, 0x153f: 0x0ab7,
+ // Block 0x55, offset 0x1540
+ 0x1540: 0x0abf, 0x1541: 0x0acf, 0x1542: 0x0ad3, 0x1543: 0x05d3, 0x1544: 0x0ae3, 0x1545: 0x0aeb,
+ 0x1546: 0x0aef, 0x1547: 0x0af3, 0x1548: 0x05d7, 0x1549: 0x169c, 0x154a: 0x05db, 0x154b: 0x0b0f,
+ 0x154c: 0x0b13, 0x154d: 0x0b17, 0x154e: 0x0b1f, 0x154f: 0x1863, 0x1550: 0x0b37, 0x1551: 0x16a6,
+ 0x1552: 0x16a6, 0x1553: 0x11d7, 0x1554: 0x0b47, 0x1555: 0x0b47, 0x1556: 0x05df, 0x1557: 0x16c9,
+ 0x1558: 0x179b, 0x1559: 0x0b57, 0x155a: 0x0b5f, 0x155b: 0x05e3, 0x155c: 0x0b73, 0x155d: 0x0b83,
+ 0x155e: 0x0b87, 0x155f: 0x0b8f, 0x1560: 0x0b9f, 0x1561: 0x05eb, 0x1562: 0x05e7, 0x1563: 0x0ba3,
+ 0x1564: 0x16ab, 0x1565: 0x0ba7, 0x1566: 0x0bbb, 0x1567: 0x0bbf, 0x1568: 0x0bc3, 0x1569: 0x0bbf,
+ 0x156a: 0x0bcf, 0x156b: 0x0bd3, 0x156c: 0x0be3, 0x156d: 0x0bdb, 0x156e: 0x0bdf, 0x156f: 0x0be7,
+ 0x1570: 0x0beb, 0x1571: 0x0bef, 0x1572: 0x0bfb, 0x1573: 0x0bff, 0x1574: 0x0c17, 0x1575: 0x0c1f,
+ 0x1576: 0x0c2f, 0x1577: 0x0c43, 0x1578: 0x16ba, 0x1579: 0x0c3f, 0x157a: 0x0c33, 0x157b: 0x0c4b,
+ 0x157c: 0x0c53, 0x157d: 0x0c67, 0x157e: 0x16bf, 0x157f: 0x0c6f,
+ // Block 0x56, offset 0x1580
+ 0x1580: 0x0c63, 0x1581: 0x0c5b, 0x1582: 0x05ef, 0x1583: 0x0c77, 0x1584: 0x0c7f, 0x1585: 0x0c87,
+ 0x1586: 0x0c7b, 0x1587: 0x05f3, 0x1588: 0x0c97, 0x1589: 0x0c9f, 0x158a: 0x16c4, 0x158b: 0x0ccb,
+ 0x158c: 0x0cff, 0x158d: 0x0cdb, 0x158e: 0x05ff, 0x158f: 0x0ce7, 0x1590: 0x05fb, 0x1591: 0x05f7,
+ 0x1592: 0x07c3, 0x1593: 0x07c7, 0x1594: 0x0d03, 0x1595: 0x0ceb, 0x1596: 0x11ab, 0x1597: 0x0663,
+ 0x1598: 0x0d0f, 0x1599: 0x0d13, 0x159a: 0x0d17, 0x159b: 0x0d2b, 0x159c: 0x0d23, 0x159d: 0x16dd,
+ 0x159e: 0x0603, 0x159f: 0x0d3f, 0x15a0: 0x0d33, 0x15a1: 0x0d4f, 0x15a2: 0x0d57, 0x15a3: 0x16e7,
+ 0x15a4: 0x0d5b, 0x15a5: 0x0d47, 0x15a6: 0x0d63, 0x15a7: 0x0607, 0x15a8: 0x0d67, 0x15a9: 0x0d6b,
+ 0x15aa: 0x0d6f, 0x15ab: 0x0d7b, 0x15ac: 0x16ec, 0x15ad: 0x0d83, 0x15ae: 0x060b, 0x15af: 0x0d8f,
+ 0x15b0: 0x16f1, 0x15b1: 0x0d93, 0x15b2: 0x060f, 0x15b3: 0x0d9f, 0x15b4: 0x0dab, 0x15b5: 0x0db7,
+ 0x15b6: 0x0dbb, 0x15b7: 0x16f6, 0x15b8: 0x168d, 0x15b9: 0x16fb, 0x15ba: 0x0ddb, 0x15bb: 0x1700,
+ 0x15bc: 0x0de7, 0x15bd: 0x0def, 0x15be: 0x0ddf, 0x15bf: 0x0dfb,
+ // Block 0x57, offset 0x15c0
+ 0x15c0: 0x0e0b, 0x15c1: 0x0e1b, 0x15c2: 0x0e0f, 0x15c3: 0x0e13, 0x15c4: 0x0e1f, 0x15c5: 0x0e23,
+ 0x15c6: 0x1705, 0x15c7: 0x0e07, 0x15c8: 0x0e3b, 0x15c9: 0x0e3f, 0x15ca: 0x0613, 0x15cb: 0x0e53,
+ 0x15cc: 0x0e4f, 0x15cd: 0x170a, 0x15ce: 0x0e33, 0x15cf: 0x0e6f, 0x15d0: 0x170f, 0x15d1: 0x1714,
+ 0x15d2: 0x0e73, 0x15d3: 0x0e87, 0x15d4: 0x0e83, 0x15d5: 0x0e7f, 0x15d6: 0x0617, 0x15d7: 0x0e8b,
+ 0x15d8: 0x0e9b, 0x15d9: 0x0e97, 0x15da: 0x0ea3, 0x15db: 0x1651, 0x15dc: 0x0eb3, 0x15dd: 0x1719,
+ 0x15de: 0x0ebf, 0x15df: 0x1723, 0x15e0: 0x0ed3, 0x15e1: 0x0edf, 0x15e2: 0x0ef3, 0x15e3: 0x1728,
+ 0x15e4: 0x0f07, 0x15e5: 0x0f0b, 0x15e6: 0x172d, 0x15e7: 0x1732, 0x15e8: 0x0f27, 0x15e9: 0x0f37,
+ 0x15ea: 0x061b, 0x15eb: 0x0f3b, 0x15ec: 0x061f, 0x15ed: 0x061f, 0x15ee: 0x0f53, 0x15ef: 0x0f57,
+ 0x15f0: 0x0f5f, 0x15f1: 0x0f63, 0x15f2: 0x0f6f, 0x15f3: 0x0623, 0x15f4: 0x0f87, 0x15f5: 0x1737,
+ 0x15f6: 0x0fa3, 0x15f7: 0x173c, 0x15f8: 0x0faf, 0x15f9: 0x16a1, 0x15fa: 0x0fbf, 0x15fb: 0x1741,
+ 0x15fc: 0x1746, 0x15fd: 0x174b, 0x15fe: 0x0627, 0x15ff: 0x062b,
+ // Block 0x58, offset 0x1600
+ 0x1600: 0x0ff7, 0x1601: 0x1755, 0x1602: 0x1750, 0x1603: 0x175a, 0x1604: 0x175f, 0x1605: 0x0fff,
+ 0x1606: 0x1003, 0x1607: 0x1003, 0x1608: 0x100b, 0x1609: 0x0633, 0x160a: 0x100f, 0x160b: 0x0637,
+ 0x160c: 0x063b, 0x160d: 0x1769, 0x160e: 0x1023, 0x160f: 0x102b, 0x1610: 0x1037, 0x1611: 0x063f,
+ 0x1612: 0x176e, 0x1613: 0x105b, 0x1614: 0x1773, 0x1615: 0x1778, 0x1616: 0x107b, 0x1617: 0x1093,
+ 0x1618: 0x0643, 0x1619: 0x109b, 0x161a: 0x109f, 0x161b: 0x10a3, 0x161c: 0x177d, 0x161d: 0x1782,
+ 0x161e: 0x1782, 0x161f: 0x10bb, 0x1620: 0x0647, 0x1621: 0x1787, 0x1622: 0x10cf, 0x1623: 0x10d3,
+ 0x1624: 0x064b, 0x1625: 0x178c, 0x1626: 0x10ef, 0x1627: 0x064f, 0x1628: 0x10ff, 0x1629: 0x10f7,
+ 0x162a: 0x1107, 0x162b: 0x1796, 0x162c: 0x111f, 0x162d: 0x0653, 0x162e: 0x112b, 0x162f: 0x1133,
+ 0x1630: 0x1143, 0x1631: 0x0657, 0x1632: 0x17a0, 0x1633: 0x17a5, 0x1634: 0x065b, 0x1635: 0x17aa,
+ 0x1636: 0x115b, 0x1637: 0x17af, 0x1638: 0x1167, 0x1639: 0x1173, 0x163a: 0x117b, 0x163b: 0x17b4,
+ 0x163c: 0x17b9, 0x163d: 0x118f, 0x163e: 0x17be, 0x163f: 0x1197,
+ // Block 0x59, offset 0x1640
+ 0x1640: 0x16ce, 0x1641: 0x065f, 0x1642: 0x11af, 0x1643: 0x11b3, 0x1644: 0x0667, 0x1645: 0x11b7,
+ 0x1646: 0x0a33, 0x1647: 0x17c3, 0x1648: 0x17c8, 0x1649: 0x16d3, 0x164a: 0x16d8, 0x164b: 0x11d7,
+ 0x164c: 0x11db, 0x164d: 0x13f3, 0x164e: 0x066b, 0x164f: 0x1207, 0x1650: 0x1203, 0x1651: 0x120b,
+ 0x1652: 0x083f, 0x1653: 0x120f, 0x1654: 0x1213, 0x1655: 0x1217, 0x1656: 0x121f, 0x1657: 0x17cd,
+ 0x1658: 0x121b, 0x1659: 0x1223, 0x165a: 0x1237, 0x165b: 0x123b, 0x165c: 0x1227, 0x165d: 0x123f,
+ 0x165e: 0x1253, 0x165f: 0x1267, 0x1660: 0x1233, 0x1661: 0x1247, 0x1662: 0x124b, 0x1663: 0x124f,
+ 0x1664: 0x17d2, 0x1665: 0x17dc, 0x1666: 0x17d7, 0x1667: 0x066f, 0x1668: 0x126f, 0x1669: 0x1273,
+ 0x166a: 0x127b, 0x166b: 0x17f0, 0x166c: 0x127f, 0x166d: 0x17e1, 0x166e: 0x0673, 0x166f: 0x0677,
+ 0x1670: 0x17e6, 0x1671: 0x17eb, 0x1672: 0x067b, 0x1673: 0x129f, 0x1674: 0x12a3, 0x1675: 0x12a7,
+ 0x1676: 0x12ab, 0x1677: 0x12b7, 0x1678: 0x12b3, 0x1679: 0x12bf, 0x167a: 0x12bb, 0x167b: 0x12cb,
+ 0x167c: 0x12c3, 0x167d: 0x12c7, 0x167e: 0x12cf, 0x167f: 0x067f,
+ // Block 0x5a, offset 0x1680
+ 0x1680: 0x12d7, 0x1681: 0x12db, 0x1682: 0x0683, 0x1683: 0x12eb, 0x1684: 0x12ef, 0x1685: 0x17f5,
+ 0x1686: 0x12fb, 0x1687: 0x12ff, 0x1688: 0x0687, 0x1689: 0x130b, 0x168a: 0x05bb, 0x168b: 0x17fa,
+ 0x168c: 0x17ff, 0x168d: 0x068b, 0x168e: 0x068f, 0x168f: 0x1337, 0x1690: 0x134f, 0x1691: 0x136b,
+ 0x1692: 0x137b, 0x1693: 0x1804, 0x1694: 0x138f, 0x1695: 0x1393, 0x1696: 0x13ab, 0x1697: 0x13b7,
+ 0x1698: 0x180e, 0x1699: 0x1660, 0x169a: 0x13c3, 0x169b: 0x13bf, 0x169c: 0x13cb, 0x169d: 0x1665,
+ 0x169e: 0x13d7, 0x169f: 0x13e3, 0x16a0: 0x1813, 0x16a1: 0x1818, 0x16a2: 0x1423, 0x16a3: 0x142f,
+ 0x16a4: 0x1437, 0x16a5: 0x181d, 0x16a6: 0x143b, 0x16a7: 0x1467, 0x16a8: 0x1473, 0x16a9: 0x1477,
+ 0x16aa: 0x146f, 0x16ab: 0x1483, 0x16ac: 0x1487, 0x16ad: 0x1822, 0x16ae: 0x1493, 0x16af: 0x0693,
+ 0x16b0: 0x149b, 0x16b1: 0x1827, 0x16b2: 0x0697, 0x16b3: 0x14d3, 0x16b4: 0x0ac3, 0x16b5: 0x14eb,
+ 0x16b6: 0x182c, 0x16b7: 0x1836, 0x16b8: 0x069b, 0x16b9: 0x069f, 0x16ba: 0x1513, 0x16bb: 0x183b,
+ 0x16bc: 0x06a3, 0x16bd: 0x1840, 0x16be: 0x152b, 0x16bf: 0x152b,
+ // Block 0x5b, offset 0x16c0
+ 0x16c0: 0x1533, 0x16c1: 0x1845, 0x16c2: 0x154b, 0x16c3: 0x06a7, 0x16c4: 0x155b, 0x16c5: 0x1567,
+ 0x16c6: 0x156f, 0x16c7: 0x1577, 0x16c8: 0x06ab, 0x16c9: 0x184a, 0x16ca: 0x158b, 0x16cb: 0x15a7,
+ 0x16cc: 0x15b3, 0x16cd: 0x06af, 0x16ce: 0x06b3, 0x16cf: 0x15b7, 0x16d0: 0x184f, 0x16d1: 0x06b7,
+ 0x16d2: 0x1854, 0x16d3: 0x1859, 0x16d4: 0x185e, 0x16d5: 0x15db, 0x16d6: 0x06bb, 0x16d7: 0x15ef,
+ 0x16d8: 0x15f7, 0x16d9: 0x15fb, 0x16da: 0x1603, 0x16db: 0x160b, 0x16dc: 0x1613, 0x16dd: 0x1868,
+}
+
+// nfkcIndex: 22 blocks, 1408 entries, 1408 bytes
+// Block 0 is the zero block.
+var nfkcIndex = [1408]uint8{
+ // Block 0x0, offset 0x0
+ // Block 0x1, offset 0x40
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc2: 0x5a, 0xc3: 0x01, 0xc4: 0x02, 0xc5: 0x03, 0xc6: 0x5b, 0xc7: 0x04,
+ 0xc8: 0x05, 0xca: 0x5c, 0xcb: 0x5d, 0xcc: 0x06, 0xcd: 0x07, 0xce: 0x08, 0xcf: 0x09,
+ 0xd0: 0x0a, 0xd1: 0x5e, 0xd2: 0x5f, 0xd3: 0x0b, 0xd6: 0x0c, 0xd7: 0x60,
+ 0xd8: 0x61, 0xd9: 0x0d, 0xdb: 0x62, 0xdc: 0x63, 0xdd: 0x64, 0xdf: 0x65,
+ 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05,
+ 0xea: 0x06, 0xeb: 0x07, 0xec: 0x08, 0xed: 0x09, 0xef: 0x0a,
+ 0xf0: 0x13,
+ // Block 0x4, offset 0x100
+ 0x120: 0x66, 0x121: 0x67, 0x123: 0x68, 0x124: 0x69, 0x125: 0x6a, 0x126: 0x6b, 0x127: 0x6c,
+ 0x128: 0x6d, 0x129: 0x6e, 0x12a: 0x6f, 0x12b: 0x70, 0x12c: 0x6b, 0x12d: 0x71, 0x12e: 0x72, 0x12f: 0x73,
+ 0x131: 0x74, 0x132: 0x75, 0x133: 0x76, 0x134: 0x77, 0x135: 0x78, 0x137: 0x79,
+ 0x138: 0x7a, 0x139: 0x7b, 0x13a: 0x7c, 0x13b: 0x7d, 0x13c: 0x7e, 0x13d: 0x7f, 0x13e: 0x80, 0x13f: 0x81,
+ // Block 0x5, offset 0x140
+ 0x140: 0x82, 0x142: 0x83, 0x143: 0x84, 0x144: 0x85, 0x145: 0x86, 0x146: 0x87, 0x147: 0x88,
+ 0x14d: 0x89,
+ 0x15c: 0x8a, 0x15f: 0x8b,
+ 0x162: 0x8c, 0x164: 0x8d,
+ 0x168: 0x8e, 0x169: 0x8f, 0x16a: 0x90, 0x16c: 0x0e, 0x16d: 0x91, 0x16e: 0x92, 0x16f: 0x93,
+ 0x170: 0x94, 0x173: 0x95, 0x174: 0x96, 0x175: 0x0f, 0x176: 0x10, 0x177: 0x97,
+ 0x178: 0x11, 0x179: 0x12, 0x17a: 0x13, 0x17b: 0x14, 0x17c: 0x15, 0x17d: 0x16, 0x17e: 0x17, 0x17f: 0x18,
+ // Block 0x6, offset 0x180
+ 0x180: 0x98, 0x181: 0x99, 0x182: 0x9a, 0x183: 0x9b, 0x184: 0x19, 0x185: 0x1a, 0x186: 0x9c, 0x187: 0x9d,
+ 0x188: 0x9e, 0x189: 0x1b, 0x18a: 0x1c, 0x18b: 0x9f, 0x18c: 0xa0,
+ 0x191: 0x1d, 0x192: 0x1e, 0x193: 0xa1,
+ 0x1a8: 0xa2, 0x1a9: 0xa3, 0x1ab: 0xa4,
+ 0x1b1: 0xa5, 0x1b3: 0xa6, 0x1b5: 0xa7, 0x1b7: 0xa8,
+ 0x1ba: 0xa9, 0x1bb: 0xaa, 0x1bc: 0x1f, 0x1bd: 0x20, 0x1be: 0x21, 0x1bf: 0xab,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0xac, 0x1c1: 0x22, 0x1c2: 0x23, 0x1c3: 0x24, 0x1c4: 0xad, 0x1c5: 0x25, 0x1c6: 0x26,
+ 0x1c8: 0x27, 0x1c9: 0x28, 0x1ca: 0x29, 0x1cb: 0x2a, 0x1cc: 0x2b, 0x1cd: 0x2c, 0x1ce: 0x2d, 0x1cf: 0x2e,
+ // Block 0x8, offset 0x200
+ 0x219: 0xae, 0x21a: 0xaf, 0x21b: 0xb0, 0x21d: 0xb1, 0x21f: 0xb2,
+ 0x220: 0xb3, 0x223: 0xb4, 0x224: 0xb5, 0x225: 0xb6, 0x226: 0xb7, 0x227: 0xb8,
+ 0x22a: 0xb9, 0x22b: 0xba, 0x22d: 0xbb, 0x22f: 0xbc,
+ 0x230: 0xbd, 0x231: 0xbe, 0x232: 0xbf, 0x233: 0xc0, 0x234: 0xc1, 0x235: 0xc2, 0x236: 0xc3, 0x237: 0xbd,
+ 0x238: 0xbe, 0x239: 0xbf, 0x23a: 0xc0, 0x23b: 0xc1, 0x23c: 0xc2, 0x23d: 0xc3, 0x23e: 0xbd, 0x23f: 0xbe,
+ // Block 0x9, offset 0x240
+ 0x240: 0xbf, 0x241: 0xc0, 0x242: 0xc1, 0x243: 0xc2, 0x244: 0xc3, 0x245: 0xbd, 0x246: 0xbe, 0x247: 0xbf,
+ 0x248: 0xc0, 0x249: 0xc1, 0x24a: 0xc2, 0x24b: 0xc3, 0x24c: 0xbd, 0x24d: 0xbe, 0x24e: 0xbf, 0x24f: 0xc0,
+ 0x250: 0xc1, 0x251: 0xc2, 0x252: 0xc3, 0x253: 0xbd, 0x254: 0xbe, 0x255: 0xbf, 0x256: 0xc0, 0x257: 0xc1,
+ 0x258: 0xc2, 0x259: 0xc3, 0x25a: 0xbd, 0x25b: 0xbe, 0x25c: 0xbf, 0x25d: 0xc0, 0x25e: 0xc1, 0x25f: 0xc2,
+ 0x260: 0xc3, 0x261: 0xbd, 0x262: 0xbe, 0x263: 0xbf, 0x264: 0xc0, 0x265: 0xc1, 0x266: 0xc2, 0x267: 0xc3,
+ 0x268: 0xbd, 0x269: 0xbe, 0x26a: 0xbf, 0x26b: 0xc0, 0x26c: 0xc1, 0x26d: 0xc2, 0x26e: 0xc3, 0x26f: 0xbd,
+ 0x270: 0xbe, 0x271: 0xbf, 0x272: 0xc0, 0x273: 0xc1, 0x274: 0xc2, 0x275: 0xc3, 0x276: 0xbd, 0x277: 0xbe,
+ 0x278: 0xbf, 0x279: 0xc0, 0x27a: 0xc1, 0x27b: 0xc2, 0x27c: 0xc3, 0x27d: 0xbd, 0x27e: 0xbe, 0x27f: 0xbf,
+ // Block 0xa, offset 0x280
+ 0x280: 0xc0, 0x281: 0xc1, 0x282: 0xc2, 0x283: 0xc3, 0x284: 0xbd, 0x285: 0xbe, 0x286: 0xbf, 0x287: 0xc0,
+ 0x288: 0xc1, 0x289: 0xc2, 0x28a: 0xc3, 0x28b: 0xbd, 0x28c: 0xbe, 0x28d: 0xbf, 0x28e: 0xc0, 0x28f: 0xc1,
+ 0x290: 0xc2, 0x291: 0xc3, 0x292: 0xbd, 0x293: 0xbe, 0x294: 0xbf, 0x295: 0xc0, 0x296: 0xc1, 0x297: 0xc2,
+ 0x298: 0xc3, 0x299: 0xbd, 0x29a: 0xbe, 0x29b: 0xbf, 0x29c: 0xc0, 0x29d: 0xc1, 0x29e: 0xc2, 0x29f: 0xc3,
+ 0x2a0: 0xbd, 0x2a1: 0xbe, 0x2a2: 0xbf, 0x2a3: 0xc0, 0x2a4: 0xc1, 0x2a5: 0xc2, 0x2a6: 0xc3, 0x2a7: 0xbd,
+ 0x2a8: 0xbe, 0x2a9: 0xbf, 0x2aa: 0xc0, 0x2ab: 0xc1, 0x2ac: 0xc2, 0x2ad: 0xc3, 0x2ae: 0xbd, 0x2af: 0xbe,
+ 0x2b0: 0xbf, 0x2b1: 0xc0, 0x2b2: 0xc1, 0x2b3: 0xc2, 0x2b4: 0xc3, 0x2b5: 0xbd, 0x2b6: 0xbe, 0x2b7: 0xbf,
+ 0x2b8: 0xc0, 0x2b9: 0xc1, 0x2ba: 0xc2, 0x2bb: 0xc3, 0x2bc: 0xbd, 0x2bd: 0xbe, 0x2be: 0xbf, 0x2bf: 0xc0,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0xc1, 0x2c1: 0xc2, 0x2c2: 0xc3, 0x2c3: 0xbd, 0x2c4: 0xbe, 0x2c5: 0xbf, 0x2c6: 0xc0, 0x2c7: 0xc1,
+ 0x2c8: 0xc2, 0x2c9: 0xc3, 0x2ca: 0xbd, 0x2cb: 0xbe, 0x2cc: 0xbf, 0x2cd: 0xc0, 0x2ce: 0xc1, 0x2cf: 0xc2,
+ 0x2d0: 0xc3, 0x2d1: 0xbd, 0x2d2: 0xbe, 0x2d3: 0xbf, 0x2d4: 0xc0, 0x2d5: 0xc1, 0x2d6: 0xc2, 0x2d7: 0xc3,
+ 0x2d8: 0xbd, 0x2d9: 0xbe, 0x2da: 0xbf, 0x2db: 0xc0, 0x2dc: 0xc1, 0x2dd: 0xc2, 0x2de: 0xc4,
+ // Block 0xc, offset 0x300
+ 0x324: 0x2f, 0x325: 0x30, 0x326: 0x31, 0x327: 0x32,
+ 0x328: 0x33, 0x329: 0x34, 0x32a: 0x35, 0x32b: 0x36, 0x32c: 0x37, 0x32d: 0x38, 0x32e: 0x39, 0x32f: 0x3a,
+ 0x330: 0x3b, 0x331: 0x3c, 0x332: 0x3d, 0x333: 0x3e, 0x334: 0x3f, 0x335: 0x40, 0x336: 0x41, 0x337: 0x42,
+ 0x338: 0x43, 0x339: 0x44, 0x33a: 0x45, 0x33b: 0x46, 0x33c: 0xc5, 0x33d: 0x47, 0x33e: 0x48, 0x33f: 0x49,
+ // Block 0xd, offset 0x340
+ 0x347: 0xc6,
+ 0x34b: 0xc7, 0x34d: 0xc8,
+ 0x368: 0xc9, 0x36b: 0xca,
+ // Block 0xe, offset 0x380
+ 0x381: 0xcb, 0x382: 0xcc, 0x384: 0xcd, 0x385: 0xb7, 0x387: 0xce,
+ 0x388: 0xcf, 0x38b: 0xd0, 0x38c: 0x6b, 0x38d: 0xd1,
+ 0x391: 0xd2, 0x392: 0xd3, 0x393: 0xd4, 0x396: 0xd5, 0x397: 0xd6,
+ 0x398: 0xd7, 0x39a: 0xd8, 0x39c: 0xd9,
+ 0x3b0: 0xd7,
+ // Block 0xf, offset 0x3c0
+ 0x3eb: 0xda, 0x3ec: 0xdb,
+ // Block 0x10, offset 0x400
+ 0x432: 0xdc,
+ // Block 0x11, offset 0x440
+ 0x445: 0xdd, 0x446: 0xde, 0x447: 0xdf,
+ 0x449: 0xe0,
+ 0x450: 0xe1, 0x451: 0xe2, 0x452: 0xe3, 0x453: 0xe4, 0x454: 0xe5, 0x455: 0xe6, 0x456: 0xe7, 0x457: 0xe8,
+ 0x458: 0xe9, 0x459: 0xea, 0x45a: 0x4a, 0x45b: 0xeb, 0x45c: 0xec, 0x45d: 0xed, 0x45e: 0xee, 0x45f: 0x4b,
+ // Block 0x12, offset 0x480
+ 0x480: 0xef,
+ 0x4a3: 0xf0, 0x4a5: 0xf1,
+ 0x4b8: 0x4c, 0x4b9: 0x4d, 0x4ba: 0x4e,
+ // Block 0x13, offset 0x4c0
+ 0x4c4: 0x4f, 0x4c5: 0xf2, 0x4c6: 0xf3,
+ 0x4c8: 0x50, 0x4c9: 0xf4,
+ // Block 0x14, offset 0x500
+ 0x520: 0x51, 0x521: 0x52, 0x522: 0x53, 0x523: 0x54, 0x524: 0x55, 0x525: 0x56, 0x526: 0x57, 0x527: 0x58,
+ 0x528: 0x59,
+ // Block 0x15, offset 0x540
+ 0x550: 0x0b, 0x551: 0x0c, 0x556: 0x0d,
+ 0x55b: 0x0e, 0x55d: 0x0f, 0x55e: 0x10, 0x55f: 0x11,
+ 0x56f: 0x12,
+}
+
+// nfkcSparseOffset: 155 entries, 310 bytes
+var nfkcSparseOffset = []uint16{0x0, 0xe, 0x12, 0x1b, 0x25, 0x35, 0x37, 0x3c, 0x47, 0x56, 0x63, 0x6b, 0x6f, 0x74, 0x76, 0x87, 0x8f, 0x96, 0x99, 0xa0, 0xa4, 0xa8, 0xaa, 0xac, 0xb5, 0xb9, 0xc0, 0xc5, 0xc8, 0xd2, 0xd4, 0xdb, 0xe3, 0xe7, 0xe9, 0xec, 0xf0, 0xf6, 0x107, 0x113, 0x115, 0x11b, 0x11d, 0x11f, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12c, 0x12f, 0x131, 0x134, 0x137, 0x13b, 0x140, 0x149, 0x14b, 0x14e, 0x150, 0x15b, 0x166, 0x176, 0x184, 0x192, 0x1a2, 0x1b0, 0x1b7, 0x1bd, 0x1cc, 0x1d0, 0x1d2, 0x1d6, 0x1d8, 0x1db, 0x1dd, 0x1e0, 0x1e2, 0x1e5, 0x1e7, 0x1e9, 0x1eb, 0x1f7, 0x201, 0x20b, 0x20e, 0x212, 0x214, 0x216, 0x218, 0x21a, 0x21d, 0x21f, 0x221, 0x223, 0x225, 0x22b, 0x22e, 0x232, 0x234, 0x23b, 0x241, 0x247, 0x24f, 0x255, 0x25b, 0x261, 0x265, 0x267, 0x269, 0x26b, 0x26d, 0x273, 0x276, 0x279, 0x281, 0x288, 0x28b, 0x28e, 0x290, 0x298, 0x29b, 0x2a2, 0x2a5, 0x2ab, 0x2ad, 0x2af, 0x2b2, 0x2b4, 0x2b6, 0x2b8, 0x2ba, 0x2c7, 0x2d1, 0x2d3, 0x2d5, 0x2d9, 0x2de, 0x2ea, 0x2ef, 0x2f8, 0x2fe, 0x303, 0x307, 0x30c, 0x310, 0x320, 0x32e, 0x33c, 0x34a, 0x350, 0x352, 0x355, 0x35f, 0x361}
+
+// nfkcSparseValues: 875 entries, 3500 bytes
+var nfkcSparseValues = [875]valueRange{
+ // Block 0x0, offset 0x0
+ {value: 0x0002, lo: 0x0d},
+ {value: 0x0001, lo: 0xa0, hi: 0xa0},
+ {value: 0x4278, lo: 0xa8, hi: 0xa8},
+ {value: 0x0083, lo: 0xaa, hi: 0xaa},
+ {value: 0x4264, lo: 0xaf, hi: 0xaf},
+ {value: 0x0025, lo: 0xb2, hi: 0xb3},
+ {value: 0x425a, lo: 0xb4, hi: 0xb4},
+ {value: 0x01dc, lo: 0xb5, hi: 0xb5},
+ {value: 0x4291, lo: 0xb8, hi: 0xb8},
+ {value: 0x0023, lo: 0xb9, hi: 0xb9},
+ {value: 0x009f, lo: 0xba, hi: 0xba},
+ {value: 0x221c, lo: 0xbc, hi: 0xbc},
+ {value: 0x2210, lo: 0xbd, hi: 0xbd},
+ {value: 0x22b2, lo: 0xbe, hi: 0xbe},
+ // Block 0x1, offset 0xe
+ {value: 0x0091, lo: 0x03},
+ {value: 0x46e2, lo: 0xa0, hi: 0xa1},
+ {value: 0x4714, lo: 0xaf, hi: 0xb0},
+ {value: 0xa000, lo: 0xb7, hi: 0xb7},
+ // Block 0x2, offset 0x12
+ {value: 0x0003, lo: 0x08},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x0091, lo: 0xb0, hi: 0xb0},
+ {value: 0x0119, lo: 0xb1, hi: 0xb1},
+ {value: 0x0095, lo: 0xb2, hi: 0xb2},
+ {value: 0x00a5, lo: 0xb3, hi: 0xb3},
+ {value: 0x0143, lo: 0xb4, hi: 0xb6},
+ {value: 0x00af, lo: 0xb7, hi: 0xb7},
+ {value: 0x00b3, lo: 0xb8, hi: 0xb8},
+ // Block 0x3, offset 0x1b
+ {value: 0x000a, lo: 0x09},
+ {value: 0x426e, lo: 0x98, hi: 0x98},
+ {value: 0x4273, lo: 0x99, hi: 0x9a},
+ {value: 0x4296, lo: 0x9b, hi: 0x9b},
+ {value: 0x425f, lo: 0x9c, hi: 0x9c},
+ {value: 0x4282, lo: 0x9d, hi: 0x9d},
+ {value: 0x0113, lo: 0xa0, hi: 0xa0},
+ {value: 0x0099, lo: 0xa1, hi: 0xa1},
+ {value: 0x00a7, lo: 0xa2, hi: 0xa3},
+ {value: 0x0167, lo: 0xa4, hi: 0xa4},
+ // Block 0x4, offset 0x25
+ {value: 0x0000, lo: 0x0f},
+ {value: 0xa000, lo: 0x83, hi: 0x83},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0xa000, lo: 0x8b, hi: 0x8b},
+ {value: 0xa000, lo: 0x8d, hi: 0x8d},
+ {value: 0x37a5, lo: 0x90, hi: 0x90},
+ {value: 0x37b1, lo: 0x91, hi: 0x91},
+ {value: 0x379f, lo: 0x93, hi: 0x93},
+ {value: 0xa000, lo: 0x96, hi: 0x96},
+ {value: 0x3817, lo: 0x97, hi: 0x97},
+ {value: 0x37e1, lo: 0x9c, hi: 0x9c},
+ {value: 0x37c9, lo: 0x9d, hi: 0x9d},
+ {value: 0x37f3, lo: 0x9e, hi: 0x9e},
+ {value: 0xa000, lo: 0xb4, hi: 0xb5},
+ {value: 0x381d, lo: 0xb6, hi: 0xb6},
+ {value: 0x3823, lo: 0xb7, hi: 0xb7},
+ // Block 0x5, offset 0x35
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x83, hi: 0x87},
+ // Block 0x6, offset 0x37
+ {value: 0x0001, lo: 0x04},
+ {value: 0x8113, lo: 0x81, hi: 0x82},
+ {value: 0x8132, lo: 0x84, hi: 0x84},
+ {value: 0x812d, lo: 0x85, hi: 0x85},
+ {value: 0x810d, lo: 0x87, hi: 0x87},
+ // Block 0x7, offset 0x3c
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x8132, lo: 0x90, hi: 0x97},
+ {value: 0x8119, lo: 0x98, hi: 0x98},
+ {value: 0x811a, lo: 0x99, hi: 0x99},
+ {value: 0x811b, lo: 0x9a, hi: 0x9a},
+ {value: 0x3841, lo: 0xa2, hi: 0xa2},
+ {value: 0x3847, lo: 0xa3, hi: 0xa3},
+ {value: 0x3853, lo: 0xa4, hi: 0xa4},
+ {value: 0x384d, lo: 0xa5, hi: 0xa5},
+ {value: 0x3859, lo: 0xa6, hi: 0xa6},
+ {value: 0xa000, lo: 0xa7, hi: 0xa7},
+ // Block 0x8, offset 0x47
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x386b, lo: 0x80, hi: 0x80},
+ {value: 0xa000, lo: 0x81, hi: 0x81},
+ {value: 0x385f, lo: 0x82, hi: 0x82},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x3865, lo: 0x93, hi: 0x93},
+ {value: 0xa000, lo: 0x95, hi: 0x95},
+ {value: 0x8132, lo: 0x96, hi: 0x9c},
+ {value: 0x8132, lo: 0x9f, hi: 0xa2},
+ {value: 0x812d, lo: 0xa3, hi: 0xa3},
+ {value: 0x8132, lo: 0xa4, hi: 0xa4},
+ {value: 0x8132, lo: 0xa7, hi: 0xa8},
+ {value: 0x812d, lo: 0xaa, hi: 0xaa},
+ {value: 0x8132, lo: 0xab, hi: 0xac},
+ {value: 0x812d, lo: 0xad, hi: 0xad},
+ // Block 0x9, offset 0x56
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x811f, lo: 0x91, hi: 0x91},
+ {value: 0x8132, lo: 0xb0, hi: 0xb0},
+ {value: 0x812d, lo: 0xb1, hi: 0xb1},
+ {value: 0x8132, lo: 0xb2, hi: 0xb3},
+ {value: 0x812d, lo: 0xb4, hi: 0xb4},
+ {value: 0x8132, lo: 0xb5, hi: 0xb6},
+ {value: 0x812d, lo: 0xb7, hi: 0xb9},
+ {value: 0x8132, lo: 0xba, hi: 0xba},
+ {value: 0x812d, lo: 0xbb, hi: 0xbc},
+ {value: 0x8132, lo: 0xbd, hi: 0xbd},
+ {value: 0x812d, lo: 0xbe, hi: 0xbe},
+ {value: 0x8132, lo: 0xbf, hi: 0xbf},
+ // Block 0xa, offset 0x63
+ {value: 0x0005, lo: 0x07},
+ {value: 0x8132, lo: 0x80, hi: 0x80},
+ {value: 0x8132, lo: 0x81, hi: 0x81},
+ {value: 0x812d, lo: 0x82, hi: 0x83},
+ {value: 0x812d, lo: 0x84, hi: 0x85},
+ {value: 0x812d, lo: 0x86, hi: 0x87},
+ {value: 0x812d, lo: 0x88, hi: 0x89},
+ {value: 0x8132, lo: 0x8a, hi: 0x8a},
+ // Block 0xb, offset 0x6b
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8132, lo: 0xab, hi: 0xb1},
+ {value: 0x812d, lo: 0xb2, hi: 0xb2},
+ {value: 0x8132, lo: 0xb3, hi: 0xb3},
+ // Block 0xc, offset 0x6f
+ {value: 0x0000, lo: 0x04},
+ {value: 0x8132, lo: 0x96, hi: 0x99},
+ {value: 0x8132, lo: 0x9b, hi: 0xa3},
+ {value: 0x8132, lo: 0xa5, hi: 0xa7},
+ {value: 0x8132, lo: 0xa9, hi: 0xad},
+ // Block 0xd, offset 0x74
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x99, hi: 0x9b},
+ // Block 0xe, offset 0x76
+ {value: 0x0000, lo: 0x10},
+ {value: 0x8132, lo: 0x94, hi: 0xa1},
+ {value: 0x812d, lo: 0xa3, hi: 0xa3},
+ {value: 0x8132, lo: 0xa4, hi: 0xa5},
+ {value: 0x812d, lo: 0xa6, hi: 0xa6},
+ {value: 0x8132, lo: 0xa7, hi: 0xa8},
+ {value: 0x812d, lo: 0xa9, hi: 0xa9},
+ {value: 0x8132, lo: 0xaa, hi: 0xac},
+ {value: 0x812d, lo: 0xad, hi: 0xaf},
+ {value: 0x8116, lo: 0xb0, hi: 0xb0},
+ {value: 0x8117, lo: 0xb1, hi: 0xb1},
+ {value: 0x8118, lo: 0xb2, hi: 0xb2},
+ {value: 0x8132, lo: 0xb3, hi: 0xb5},
+ {value: 0x812d, lo: 0xb6, hi: 0xb6},
+ {value: 0x8132, lo: 0xb7, hi: 0xb8},
+ {value: 0x812d, lo: 0xb9, hi: 0xba},
+ {value: 0x8132, lo: 0xbb, hi: 0xbf},
+ // Block 0xf, offset 0x87
+ {value: 0x0000, lo: 0x07},
+ {value: 0xa000, lo: 0xa8, hi: 0xa8},
+ {value: 0x3ed8, lo: 0xa9, hi: 0xa9},
+ {value: 0xa000, lo: 0xb0, hi: 0xb0},
+ {value: 0x3ee0, lo: 0xb1, hi: 0xb1},
+ {value: 0xa000, lo: 0xb3, hi: 0xb3},
+ {value: 0x3ee8, lo: 0xb4, hi: 0xb4},
+ {value: 0x9902, lo: 0xbc, hi: 0xbc},
+ // Block 0x10, offset 0x8f
+ {value: 0x0008, lo: 0x06},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x8132, lo: 0x91, hi: 0x91},
+ {value: 0x812d, lo: 0x92, hi: 0x92},
+ {value: 0x8132, lo: 0x93, hi: 0x93},
+ {value: 0x8132, lo: 0x94, hi: 0x94},
+ {value: 0x451c, lo: 0x98, hi: 0x9f},
+ // Block 0x11, offset 0x96
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x12, offset 0x99
+ {value: 0x0008, lo: 0x06},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2c9e, lo: 0x8b, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ {value: 0x455c, lo: 0x9c, hi: 0x9d},
+ {value: 0x456c, lo: 0x9f, hi: 0x9f},
+ // Block 0x13, offset 0xa0
+ {value: 0x0000, lo: 0x03},
+ {value: 0x4594, lo: 0xb3, hi: 0xb3},
+ {value: 0x459c, lo: 0xb6, hi: 0xb6},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ // Block 0x14, offset 0xa4
+ {value: 0x0008, lo: 0x03},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x4574, lo: 0x99, hi: 0x9b},
+ {value: 0x458c, lo: 0x9e, hi: 0x9e},
+ // Block 0x15, offset 0xa8
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ // Block 0x16, offset 0xaa
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ // Block 0x17, offset 0xac
+ {value: 0x0000, lo: 0x08},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2cb6, lo: 0x88, hi: 0x88},
+ {value: 0x2cae, lo: 0x8b, hi: 0x8b},
+ {value: 0x2cbe, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x96, hi: 0x97},
+ {value: 0x45a4, lo: 0x9c, hi: 0x9c},
+ {value: 0x45ac, lo: 0x9d, hi: 0x9d},
+ // Block 0x18, offset 0xb5
+ {value: 0x0000, lo: 0x03},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x2cc6, lo: 0x94, hi: 0x94},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x19, offset 0xb9
+ {value: 0x0000, lo: 0x06},
+ {value: 0xa000, lo: 0x86, hi: 0x87},
+ {value: 0x2cce, lo: 0x8a, hi: 0x8a},
+ {value: 0x2cde, lo: 0x8b, hi: 0x8b},
+ {value: 0x2cd6, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ // Block 0x1a, offset 0xc0
+ {value: 0x1801, lo: 0x04},
+ {value: 0xa000, lo: 0x86, hi: 0x86},
+ {value: 0x3ef0, lo: 0x88, hi: 0x88},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x8120, lo: 0x95, hi: 0x96},
+ // Block 0x1b, offset 0xc5
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ {value: 0xa000, lo: 0xbf, hi: 0xbf},
+ // Block 0x1c, offset 0xc8
+ {value: 0x0000, lo: 0x09},
+ {value: 0x2ce6, lo: 0x80, hi: 0x80},
+ {value: 0x9900, lo: 0x82, hi: 0x82},
+ {value: 0xa000, lo: 0x86, hi: 0x86},
+ {value: 0x2cee, lo: 0x87, hi: 0x87},
+ {value: 0x2cf6, lo: 0x88, hi: 0x88},
+ {value: 0x2f50, lo: 0x8a, hi: 0x8a},
+ {value: 0x2dd8, lo: 0x8b, hi: 0x8b},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x95, hi: 0x96},
+ // Block 0x1d, offset 0xd2
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x1e, offset 0xd4
+ {value: 0x0000, lo: 0x06},
+ {value: 0xa000, lo: 0x86, hi: 0x87},
+ {value: 0x2cfe, lo: 0x8a, hi: 0x8a},
+ {value: 0x2d0e, lo: 0x8b, hi: 0x8b},
+ {value: 0x2d06, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ // Block 0x1f, offset 0xdb
+ {value: 0x6bea, lo: 0x07},
+ {value: 0x9904, lo: 0x8a, hi: 0x8a},
+ {value: 0x9900, lo: 0x8f, hi: 0x8f},
+ {value: 0xa000, lo: 0x99, hi: 0x99},
+ {value: 0x3ef8, lo: 0x9a, hi: 0x9a},
+ {value: 0x2f58, lo: 0x9c, hi: 0x9c},
+ {value: 0x2de3, lo: 0x9d, hi: 0x9d},
+ {value: 0x2d16, lo: 0x9e, hi: 0x9f},
+ // Block 0x20, offset 0xe3
+ {value: 0x0000, lo: 0x03},
+ {value: 0x2621, lo: 0xb3, hi: 0xb3},
+ {value: 0x8122, lo: 0xb8, hi: 0xb9},
+ {value: 0x8104, lo: 0xba, hi: 0xba},
+ // Block 0x21, offset 0xe7
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8123, lo: 0x88, hi: 0x8b},
+ // Block 0x22, offset 0xe9
+ {value: 0x0000, lo: 0x02},
+ {value: 0x2636, lo: 0xb3, hi: 0xb3},
+ {value: 0x8124, lo: 0xb8, hi: 0xb9},
+ // Block 0x23, offset 0xec
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8125, lo: 0x88, hi: 0x8b},
+ {value: 0x2628, lo: 0x9c, hi: 0x9c},
+ {value: 0x262f, lo: 0x9d, hi: 0x9d},
+ // Block 0x24, offset 0xf0
+ {value: 0x0000, lo: 0x05},
+ {value: 0x030b, lo: 0x8c, hi: 0x8c},
+ {value: 0x812d, lo: 0x98, hi: 0x99},
+ {value: 0x812d, lo: 0xb5, hi: 0xb5},
+ {value: 0x812d, lo: 0xb7, hi: 0xb7},
+ {value: 0x812b, lo: 0xb9, hi: 0xb9},
+ // Block 0x25, offset 0xf6
+ {value: 0x0000, lo: 0x10},
+ {value: 0x2644, lo: 0x83, hi: 0x83},
+ {value: 0x264b, lo: 0x8d, hi: 0x8d},
+ {value: 0x2652, lo: 0x92, hi: 0x92},
+ {value: 0x2659, lo: 0x97, hi: 0x97},
+ {value: 0x2660, lo: 0x9c, hi: 0x9c},
+ {value: 0x263d, lo: 0xa9, hi: 0xa9},
+ {value: 0x8126, lo: 0xb1, hi: 0xb1},
+ {value: 0x8127, lo: 0xb2, hi: 0xb2},
+ {value: 0x4a84, lo: 0xb3, hi: 0xb3},
+ {value: 0x8128, lo: 0xb4, hi: 0xb4},
+ {value: 0x4a8d, lo: 0xb5, hi: 0xb5},
+ {value: 0x45b4, lo: 0xb6, hi: 0xb6},
+ {value: 0x45f4, lo: 0xb7, hi: 0xb7},
+ {value: 0x45bc, lo: 0xb8, hi: 0xb8},
+ {value: 0x45ff, lo: 0xb9, hi: 0xb9},
+ {value: 0x8127, lo: 0xba, hi: 0xbd},
+ // Block 0x26, offset 0x107
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x8127, lo: 0x80, hi: 0x80},
+ {value: 0x4a96, lo: 0x81, hi: 0x81},
+ {value: 0x8132, lo: 0x82, hi: 0x83},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0x86, hi: 0x87},
+ {value: 0x266e, lo: 0x93, hi: 0x93},
+ {value: 0x2675, lo: 0x9d, hi: 0x9d},
+ {value: 0x267c, lo: 0xa2, hi: 0xa2},
+ {value: 0x2683, lo: 0xa7, hi: 0xa7},
+ {value: 0x268a, lo: 0xac, hi: 0xac},
+ {value: 0x2667, lo: 0xb9, hi: 0xb9},
+ // Block 0x27, offset 0x113
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x86, hi: 0x86},
+ // Block 0x28, offset 0x115
+ {value: 0x0000, lo: 0x05},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x2d1e, lo: 0xa6, hi: 0xa6},
+ {value: 0x9900, lo: 0xae, hi: 0xae},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ {value: 0x8104, lo: 0xb9, hi: 0xba},
+ // Block 0x29, offset 0x11b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x8d, hi: 0x8d},
+ // Block 0x2a, offset 0x11d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x030f, lo: 0xbc, hi: 0xbc},
+ // Block 0x2b, offset 0x11f
+ {value: 0x0000, lo: 0x01},
+ {value: 0xa000, lo: 0x80, hi: 0x92},
+ // Block 0x2c, offset 0x121
+ {value: 0x0000, lo: 0x01},
+ {value: 0xb900, lo: 0xa1, hi: 0xb5},
+ // Block 0x2d, offset 0x123
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0xa8, hi: 0xbf},
+ // Block 0x2e, offset 0x125
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0x80, hi: 0x82},
+ // Block 0x2f, offset 0x127
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x9d, hi: 0x9f},
+ // Block 0x30, offset 0x129
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x94, hi: 0x94},
+ {value: 0x8104, lo: 0xb4, hi: 0xb4},
+ // Block 0x31, offset 0x12c
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x92, hi: 0x92},
+ {value: 0x8132, lo: 0x9d, hi: 0x9d},
+ // Block 0x32, offset 0x12f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8131, lo: 0xa9, hi: 0xa9},
+ // Block 0x33, offset 0x131
+ {value: 0x0004, lo: 0x02},
+ {value: 0x812e, lo: 0xb9, hi: 0xba},
+ {value: 0x812d, lo: 0xbb, hi: 0xbb},
+ // Block 0x34, offset 0x134
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x97, hi: 0x97},
+ {value: 0x812d, lo: 0x98, hi: 0x98},
+ // Block 0x35, offset 0x137
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8104, lo: 0xa0, hi: 0xa0},
+ {value: 0x8132, lo: 0xb5, hi: 0xbc},
+ {value: 0x812d, lo: 0xbf, hi: 0xbf},
+ // Block 0x36, offset 0x13b
+ {value: 0x0000, lo: 0x04},
+ {value: 0x8132, lo: 0xb0, hi: 0xb4},
+ {value: 0x812d, lo: 0xb5, hi: 0xba},
+ {value: 0x8132, lo: 0xbb, hi: 0xbc},
+ {value: 0x812d, lo: 0xbd, hi: 0xbd},
+ // Block 0x37, offset 0x140
+ {value: 0x0000, lo: 0x08},
+ {value: 0x2d66, lo: 0x80, hi: 0x80},
+ {value: 0x2d6e, lo: 0x81, hi: 0x81},
+ {value: 0xa000, lo: 0x82, hi: 0x82},
+ {value: 0x2d76, lo: 0x83, hi: 0x83},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0xab, hi: 0xab},
+ {value: 0x812d, lo: 0xac, hi: 0xac},
+ {value: 0x8132, lo: 0xad, hi: 0xb3},
+ // Block 0x38, offset 0x149
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xaa, hi: 0xab},
+ // Block 0x39, offset 0x14b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xa6, hi: 0xa6},
+ {value: 0x8104, lo: 0xb2, hi: 0xb3},
+ // Block 0x3a, offset 0x14e
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ // Block 0x3b, offset 0x150
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x8132, lo: 0x90, hi: 0x92},
+ {value: 0x8101, lo: 0x94, hi: 0x94},
+ {value: 0x812d, lo: 0x95, hi: 0x99},
+ {value: 0x8132, lo: 0x9a, hi: 0x9b},
+ {value: 0x812d, lo: 0x9c, hi: 0x9f},
+ {value: 0x8132, lo: 0xa0, hi: 0xa0},
+ {value: 0x8101, lo: 0xa2, hi: 0xa8},
+ {value: 0x812d, lo: 0xad, hi: 0xad},
+ {value: 0x8132, lo: 0xb4, hi: 0xb4},
+ {value: 0x8132, lo: 0xb8, hi: 0xb9},
+ // Block 0x3c, offset 0x15b
+ {value: 0x0002, lo: 0x0a},
+ {value: 0x0043, lo: 0xac, hi: 0xac},
+ {value: 0x00d1, lo: 0xad, hi: 0xad},
+ {value: 0x0045, lo: 0xae, hi: 0xae},
+ {value: 0x0049, lo: 0xb0, hi: 0xb1},
+ {value: 0x00e6, lo: 0xb2, hi: 0xb2},
+ {value: 0x004f, lo: 0xb3, hi: 0xba},
+ {value: 0x005f, lo: 0xbc, hi: 0xbc},
+ {value: 0x00ef, lo: 0xbd, hi: 0xbd},
+ {value: 0x0061, lo: 0xbe, hi: 0xbe},
+ {value: 0x0065, lo: 0xbf, hi: 0xbf},
+ // Block 0x3d, offset 0x166
+ {value: 0x0000, lo: 0x0f},
+ {value: 0x8132, lo: 0x80, hi: 0x81},
+ {value: 0x812d, lo: 0x82, hi: 0x82},
+ {value: 0x8132, lo: 0x83, hi: 0x89},
+ {value: 0x812d, lo: 0x8a, hi: 0x8a},
+ {value: 0x8132, lo: 0x8b, hi: 0x8c},
+ {value: 0x8135, lo: 0x8d, hi: 0x8d},
+ {value: 0x812a, lo: 0x8e, hi: 0x8e},
+ {value: 0x812d, lo: 0x8f, hi: 0x8f},
+ {value: 0x8129, lo: 0x90, hi: 0x90},
+ {value: 0x8132, lo: 0x91, hi: 0xb5},
+ {value: 0x8132, lo: 0xbb, hi: 0xbb},
+ {value: 0x8134, lo: 0xbc, hi: 0xbc},
+ {value: 0x812d, lo: 0xbd, hi: 0xbd},
+ {value: 0x8132, lo: 0xbe, hi: 0xbe},
+ {value: 0x812d, lo: 0xbf, hi: 0xbf},
+ // Block 0x3e, offset 0x176
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x0001, lo: 0x80, hi: 0x8a},
+ {value: 0x043b, lo: 0x91, hi: 0x91},
+ {value: 0x429b, lo: 0x97, hi: 0x97},
+ {value: 0x001d, lo: 0xa4, hi: 0xa4},
+ {value: 0x1873, lo: 0xa5, hi: 0xa5},
+ {value: 0x1b5c, lo: 0xa6, hi: 0xa6},
+ {value: 0x0001, lo: 0xaf, hi: 0xaf},
+ {value: 0x2691, lo: 0xb3, hi: 0xb3},
+ {value: 0x27fe, lo: 0xb4, hi: 0xb4},
+ {value: 0x2698, lo: 0xb6, hi: 0xb6},
+ {value: 0x2808, lo: 0xb7, hi: 0xb7},
+ {value: 0x186d, lo: 0xbc, hi: 0xbc},
+ {value: 0x4269, lo: 0xbe, hi: 0xbe},
+ // Block 0x3f, offset 0x184
+ {value: 0x0002, lo: 0x0d},
+ {value: 0x1933, lo: 0x87, hi: 0x87},
+ {value: 0x1930, lo: 0x88, hi: 0x88},
+ {value: 0x1870, lo: 0x89, hi: 0x89},
+ {value: 0x298e, lo: 0x97, hi: 0x97},
+ {value: 0x0001, lo: 0x9f, hi: 0x9f},
+ {value: 0x0021, lo: 0xb0, hi: 0xb0},
+ {value: 0x0093, lo: 0xb1, hi: 0xb1},
+ {value: 0x0029, lo: 0xb4, hi: 0xb9},
+ {value: 0x0017, lo: 0xba, hi: 0xba},
+ {value: 0x0467, lo: 0xbb, hi: 0xbb},
+ {value: 0x003b, lo: 0xbc, hi: 0xbc},
+ {value: 0x0011, lo: 0xbd, hi: 0xbe},
+ {value: 0x009d, lo: 0xbf, hi: 0xbf},
+ // Block 0x40, offset 0x192
+ {value: 0x0002, lo: 0x0f},
+ {value: 0x0021, lo: 0x80, hi: 0x89},
+ {value: 0x0017, lo: 0x8a, hi: 0x8a},
+ {value: 0x0467, lo: 0x8b, hi: 0x8b},
+ {value: 0x003b, lo: 0x8c, hi: 0x8c},
+ {value: 0x0011, lo: 0x8d, hi: 0x8e},
+ {value: 0x0083, lo: 0x90, hi: 0x90},
+ {value: 0x008b, lo: 0x91, hi: 0x91},
+ {value: 0x009f, lo: 0x92, hi: 0x92},
+ {value: 0x00b1, lo: 0x93, hi: 0x93},
+ {value: 0x0104, lo: 0x94, hi: 0x94},
+ {value: 0x0091, lo: 0x95, hi: 0x95},
+ {value: 0x0097, lo: 0x96, hi: 0x99},
+ {value: 0x00a1, lo: 0x9a, hi: 0x9a},
+ {value: 0x00a7, lo: 0x9b, hi: 0x9c},
+ {value: 0x1999, lo: 0xa8, hi: 0xa8},
+ // Block 0x41, offset 0x1a2
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x8132, lo: 0x90, hi: 0x91},
+ {value: 0x8101, lo: 0x92, hi: 0x93},
+ {value: 0x8132, lo: 0x94, hi: 0x97},
+ {value: 0x8101, lo: 0x98, hi: 0x9a},
+ {value: 0x8132, lo: 0x9b, hi: 0x9c},
+ {value: 0x8132, lo: 0xa1, hi: 0xa1},
+ {value: 0x8101, lo: 0xa5, hi: 0xa6},
+ {value: 0x8132, lo: 0xa7, hi: 0xa7},
+ {value: 0x812d, lo: 0xa8, hi: 0xa8},
+ {value: 0x8132, lo: 0xa9, hi: 0xa9},
+ {value: 0x8101, lo: 0xaa, hi: 0xab},
+ {value: 0x812d, lo: 0xac, hi: 0xaf},
+ {value: 0x8132, lo: 0xb0, hi: 0xb0},
+ // Block 0x42, offset 0x1b0
+ {value: 0x0007, lo: 0x06},
+ {value: 0x2180, lo: 0x89, hi: 0x89},
+ {value: 0xa000, lo: 0x90, hi: 0x90},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0xa000, lo: 0x94, hi: 0x94},
+ {value: 0x3bb9, lo: 0x9a, hi: 0x9b},
+ {value: 0x3bc7, lo: 0xae, hi: 0xae},
+ // Block 0x43, offset 0x1b7
+ {value: 0x000e, lo: 0x05},
+ {value: 0x3bce, lo: 0x8d, hi: 0x8e},
+ {value: 0x3bd5, lo: 0x8f, hi: 0x8f},
+ {value: 0xa000, lo: 0x90, hi: 0x90},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0xa000, lo: 0x94, hi: 0x94},
+ // Block 0x44, offset 0x1bd
+ {value: 0x0173, lo: 0x0e},
+ {value: 0xa000, lo: 0x83, hi: 0x83},
+ {value: 0x3be3, lo: 0x84, hi: 0x84},
+ {value: 0xa000, lo: 0x88, hi: 0x88},
+ {value: 0x3bea, lo: 0x89, hi: 0x89},
+ {value: 0xa000, lo: 0x8b, hi: 0x8b},
+ {value: 0x3bf1, lo: 0x8c, hi: 0x8c},
+ {value: 0xa000, lo: 0xa3, hi: 0xa3},
+ {value: 0x3bf8, lo: 0xa4, hi: 0xa4},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x3bff, lo: 0xa6, hi: 0xa6},
+ {value: 0x269f, lo: 0xac, hi: 0xad},
+ {value: 0x26a6, lo: 0xaf, hi: 0xaf},
+ {value: 0x281c, lo: 0xb0, hi: 0xb0},
+ {value: 0xa000, lo: 0xbc, hi: 0xbc},
+ // Block 0x45, offset 0x1cc
+ {value: 0x0007, lo: 0x03},
+ {value: 0x3c68, lo: 0xa0, hi: 0xa1},
+ {value: 0x3c92, lo: 0xa2, hi: 0xa3},
+ {value: 0x3cbc, lo: 0xaa, hi: 0xad},
+ // Block 0x46, offset 0x1d0
+ {value: 0x0004, lo: 0x01},
+ {value: 0x048b, lo: 0xa9, hi: 0xaa},
+ // Block 0x47, offset 0x1d2
+ {value: 0x0002, lo: 0x03},
+ {value: 0x0057, lo: 0x80, hi: 0x8f},
+ {value: 0x0083, lo: 0x90, hi: 0xa9},
+ {value: 0x0021, lo: 0xaa, hi: 0xaa},
+ // Block 0x48, offset 0x1d6
+ {value: 0x0000, lo: 0x01},
+ {value: 0x299b, lo: 0x8c, hi: 0x8c},
+ // Block 0x49, offset 0x1d8
+ {value: 0x0263, lo: 0x02},
+ {value: 0x1b8c, lo: 0xb4, hi: 0xb4},
+ {value: 0x192d, lo: 0xb5, hi: 0xb6},
+ // Block 0x4a, offset 0x1db
+ {value: 0x0000, lo: 0x01},
+ {value: 0x44dd, lo: 0x9c, hi: 0x9c},
+ // Block 0x4b, offset 0x1dd
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0095, lo: 0xbc, hi: 0xbc},
+ {value: 0x006d, lo: 0xbd, hi: 0xbd},
+ // Block 0x4c, offset 0x1e0
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xaf, hi: 0xb1},
+ // Block 0x4d, offset 0x1e2
+ {value: 0x0000, lo: 0x02},
+ {value: 0x047f, lo: 0xaf, hi: 0xaf},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x4e, offset 0x1e5
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xa0, hi: 0xbf},
+ // Block 0x4f, offset 0x1e7
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0dc3, lo: 0x9f, hi: 0x9f},
+ // Block 0x50, offset 0x1e9
+ {value: 0x0000, lo: 0x01},
+ {value: 0x162f, lo: 0xb3, hi: 0xb3},
+ // Block 0x51, offset 0x1eb
+ {value: 0x0004, lo: 0x0b},
+ {value: 0x1597, lo: 0x80, hi: 0x82},
+ {value: 0x15af, lo: 0x83, hi: 0x83},
+ {value: 0x15c7, lo: 0x84, hi: 0x85},
+ {value: 0x15d7, lo: 0x86, hi: 0x89},
+ {value: 0x15eb, lo: 0x8a, hi: 0x8c},
+ {value: 0x15ff, lo: 0x8d, hi: 0x8d},
+ {value: 0x1607, lo: 0x8e, hi: 0x8e},
+ {value: 0x160f, lo: 0x8f, hi: 0x90},
+ {value: 0x161b, lo: 0x91, hi: 0x93},
+ {value: 0x162b, lo: 0x94, hi: 0x94},
+ {value: 0x1633, lo: 0x95, hi: 0x95},
+ // Block 0x52, offset 0x1f7
+ {value: 0x0004, lo: 0x09},
+ {value: 0x0001, lo: 0x80, hi: 0x80},
+ {value: 0x812c, lo: 0xaa, hi: 0xaa},
+ {value: 0x8131, lo: 0xab, hi: 0xab},
+ {value: 0x8133, lo: 0xac, hi: 0xac},
+ {value: 0x812e, lo: 0xad, hi: 0xad},
+ {value: 0x812f, lo: 0xae, hi: 0xae},
+ {value: 0x812f, lo: 0xaf, hi: 0xaf},
+ {value: 0x04b3, lo: 0xb6, hi: 0xb6},
+ {value: 0x0887, lo: 0xb8, hi: 0xba},
+ // Block 0x53, offset 0x201
+ {value: 0x0006, lo: 0x09},
+ {value: 0x0313, lo: 0xb1, hi: 0xb1},
+ {value: 0x0317, lo: 0xb2, hi: 0xb2},
+ {value: 0x4a3b, lo: 0xb3, hi: 0xb3},
+ {value: 0x031b, lo: 0xb4, hi: 0xb4},
+ {value: 0x4a41, lo: 0xb5, hi: 0xb6},
+ {value: 0x031f, lo: 0xb7, hi: 0xb7},
+ {value: 0x0323, lo: 0xb8, hi: 0xb8},
+ {value: 0x0327, lo: 0xb9, hi: 0xb9},
+ {value: 0x4a4d, lo: 0xba, hi: 0xbf},
+ // Block 0x54, offset 0x20b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0xaf, hi: 0xaf},
+ {value: 0x8132, lo: 0xb4, hi: 0xbd},
+ // Block 0x55, offset 0x20e
+ {value: 0x0000, lo: 0x03},
+ {value: 0x020f, lo: 0x9c, hi: 0x9c},
+ {value: 0x0212, lo: 0x9d, hi: 0x9d},
+ {value: 0x8132, lo: 0x9e, hi: 0x9f},
+ // Block 0x56, offset 0x212
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb0, hi: 0xb1},
+ // Block 0x57, offset 0x214
+ {value: 0x0000, lo: 0x01},
+ {value: 0x163b, lo: 0xb0, hi: 0xb0},
+ // Block 0x58, offset 0x216
+ {value: 0x000c, lo: 0x01},
+ {value: 0x00d7, lo: 0xb8, hi: 0xb9},
+ // Block 0x59, offset 0x218
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x86, hi: 0x86},
+ // Block 0x5a, offset 0x21a
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0xa0, hi: 0xb1},
+ // Block 0x5b, offset 0x21d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xab, hi: 0xad},
+ // Block 0x5c, offset 0x21f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x93, hi: 0x93},
+ // Block 0x5d, offset 0x221
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xb3, hi: 0xb3},
+ // Block 0x5e, offset 0x223
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x80, hi: 0x80},
+ // Block 0x5f, offset 0x225
+ {value: 0x0000, lo: 0x05},
+ {value: 0x8132, lo: 0xb0, hi: 0xb0},
+ {value: 0x8132, lo: 0xb2, hi: 0xb3},
+ {value: 0x812d, lo: 0xb4, hi: 0xb4},
+ {value: 0x8132, lo: 0xb7, hi: 0xb8},
+ {value: 0x8132, lo: 0xbe, hi: 0xbf},
+ // Block 0x60, offset 0x22b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x81, hi: 0x81},
+ {value: 0x8104, lo: 0xb6, hi: 0xb6},
+ // Block 0x61, offset 0x22e
+ {value: 0x0008, lo: 0x03},
+ {value: 0x1637, lo: 0x9c, hi: 0x9d},
+ {value: 0x0125, lo: 0x9e, hi: 0x9e},
+ {value: 0x1643, lo: 0x9f, hi: 0x9f},
+ // Block 0x62, offset 0x232
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xad, hi: 0xad},
+ // Block 0x63, offset 0x234
+ {value: 0x0000, lo: 0x06},
+ {value: 0xe500, lo: 0x80, hi: 0x80},
+ {value: 0xc600, lo: 0x81, hi: 0x9b},
+ {value: 0xe500, lo: 0x9c, hi: 0x9c},
+ {value: 0xc600, lo: 0x9d, hi: 0xb7},
+ {value: 0xe500, lo: 0xb8, hi: 0xb8},
+ {value: 0xc600, lo: 0xb9, hi: 0xbf},
+ // Block 0x64, offset 0x23b
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x93},
+ {value: 0xe500, lo: 0x94, hi: 0x94},
+ {value: 0xc600, lo: 0x95, hi: 0xaf},
+ {value: 0xe500, lo: 0xb0, hi: 0xb0},
+ {value: 0xc600, lo: 0xb1, hi: 0xbf},
+ // Block 0x65, offset 0x241
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x8b},
+ {value: 0xe500, lo: 0x8c, hi: 0x8c},
+ {value: 0xc600, lo: 0x8d, hi: 0xa7},
+ {value: 0xe500, lo: 0xa8, hi: 0xa8},
+ {value: 0xc600, lo: 0xa9, hi: 0xbf},
+ // Block 0x66, offset 0x247
+ {value: 0x0000, lo: 0x07},
+ {value: 0xc600, lo: 0x80, hi: 0x83},
+ {value: 0xe500, lo: 0x84, hi: 0x84},
+ {value: 0xc600, lo: 0x85, hi: 0x9f},
+ {value: 0xe500, lo: 0xa0, hi: 0xa0},
+ {value: 0xc600, lo: 0xa1, hi: 0xbb},
+ {value: 0xe500, lo: 0xbc, hi: 0xbc},
+ {value: 0xc600, lo: 0xbd, hi: 0xbf},
+ // Block 0x67, offset 0x24f
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x97},
+ {value: 0xe500, lo: 0x98, hi: 0x98},
+ {value: 0xc600, lo: 0x99, hi: 0xb3},
+ {value: 0xe500, lo: 0xb4, hi: 0xb4},
+ {value: 0xc600, lo: 0xb5, hi: 0xbf},
+ // Block 0x68, offset 0x255
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x8f},
+ {value: 0xe500, lo: 0x90, hi: 0x90},
+ {value: 0xc600, lo: 0x91, hi: 0xab},
+ {value: 0xe500, lo: 0xac, hi: 0xac},
+ {value: 0xc600, lo: 0xad, hi: 0xbf},
+ // Block 0x69, offset 0x25b
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x87},
+ {value: 0xe500, lo: 0x88, hi: 0x88},
+ {value: 0xc600, lo: 0x89, hi: 0xa3},
+ {value: 0xe500, lo: 0xa4, hi: 0xa4},
+ {value: 0xc600, lo: 0xa5, hi: 0xbf},
+ // Block 0x6a, offset 0x261
+ {value: 0x0000, lo: 0x03},
+ {value: 0xc600, lo: 0x80, hi: 0x87},
+ {value: 0xe500, lo: 0x88, hi: 0x88},
+ {value: 0xc600, lo: 0x89, hi: 0xa3},
+ // Block 0x6b, offset 0x265
+ {value: 0x0002, lo: 0x01},
+ {value: 0x0003, lo: 0x81, hi: 0xbf},
+ // Block 0x6c, offset 0x267
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xbd, hi: 0xbd},
+ // Block 0x6d, offset 0x269
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xa0, hi: 0xa0},
+ // Block 0x6e, offset 0x26b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb6, hi: 0xba},
+ // Block 0x6f, offset 0x26d
+ {value: 0x002c, lo: 0x05},
+ {value: 0x812d, lo: 0x8d, hi: 0x8d},
+ {value: 0x8132, lo: 0x8f, hi: 0x8f},
+ {value: 0x8132, lo: 0xb8, hi: 0xb8},
+ {value: 0x8101, lo: 0xb9, hi: 0xba},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x70, offset 0x273
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0xa5, hi: 0xa5},
+ {value: 0x812d, lo: 0xa6, hi: 0xa6},
+ // Block 0x71, offset 0x276
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x86, hi: 0x86},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x72, offset 0x279
+ {value: 0x17fe, lo: 0x07},
+ {value: 0xa000, lo: 0x99, hi: 0x99},
+ {value: 0x4238, lo: 0x9a, hi: 0x9a},
+ {value: 0xa000, lo: 0x9b, hi: 0x9b},
+ {value: 0x4242, lo: 0x9c, hi: 0x9c},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x424c, lo: 0xab, hi: 0xab},
+ {value: 0x8104, lo: 0xb9, hi: 0xba},
+ // Block 0x73, offset 0x281
+ {value: 0x0000, lo: 0x06},
+ {value: 0x8132, lo: 0x80, hi: 0x82},
+ {value: 0x9900, lo: 0xa7, hi: 0xa7},
+ {value: 0x2d7e, lo: 0xae, hi: 0xae},
+ {value: 0x2d88, lo: 0xaf, hi: 0xaf},
+ {value: 0xa000, lo: 0xb1, hi: 0xb2},
+ {value: 0x8104, lo: 0xb3, hi: 0xb4},
+ // Block 0x74, offset 0x288
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x80, hi: 0x80},
+ {value: 0x8102, lo: 0x8a, hi: 0x8a},
+ // Block 0x75, offset 0x28b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0xb5, hi: 0xb5},
+ {value: 0x8102, lo: 0xb6, hi: 0xb6},
+ // Block 0x76, offset 0x28e
+ {value: 0x0002, lo: 0x01},
+ {value: 0x8102, lo: 0xa9, hi: 0xaa},
+ // Block 0x77, offset 0x290
+ {value: 0x0000, lo: 0x07},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2d92, lo: 0x8b, hi: 0x8b},
+ {value: 0x2d9c, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ {value: 0x8132, lo: 0xa6, hi: 0xac},
+ {value: 0x8132, lo: 0xb0, hi: 0xb4},
+ // Block 0x78, offset 0x298
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x82, hi: 0x82},
+ {value: 0x8102, lo: 0x86, hi: 0x86},
+ // Block 0x79, offset 0x29b
+ {value: 0x6b5a, lo: 0x06},
+ {value: 0x9900, lo: 0xb0, hi: 0xb0},
+ {value: 0xa000, lo: 0xb9, hi: 0xb9},
+ {value: 0x9900, lo: 0xba, hi: 0xba},
+ {value: 0x2db0, lo: 0xbb, hi: 0xbb},
+ {value: 0x2da6, lo: 0xbc, hi: 0xbd},
+ {value: 0x2dba, lo: 0xbe, hi: 0xbe},
+ // Block 0x7a, offset 0x2a2
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x82, hi: 0x82},
+ {value: 0x8102, lo: 0x83, hi: 0x83},
+ // Block 0x7b, offset 0x2a5
+ {value: 0x0000, lo: 0x05},
+ {value: 0x9900, lo: 0xaf, hi: 0xaf},
+ {value: 0xa000, lo: 0xb8, hi: 0xb9},
+ {value: 0x2dc4, lo: 0xba, hi: 0xba},
+ {value: 0x2dce, lo: 0xbb, hi: 0xbb},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x7c, offset 0x2ab
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0x80, hi: 0x80},
+ // Block 0x7d, offset 0x2ad
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x7e, offset 0x2af
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0xb6, hi: 0xb6},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ // Block 0x7f, offset 0x2b2
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xab, hi: 0xab},
+ // Block 0x80, offset 0x2b4
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8101, lo: 0xb0, hi: 0xb4},
+ // Block 0x81, offset 0x2b6
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb0, hi: 0xb6},
+ // Block 0x82, offset 0x2b8
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8101, lo: 0x9e, hi: 0x9e},
+ // Block 0x83, offset 0x2ba
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x45cc, lo: 0x9e, hi: 0x9e},
+ {value: 0x45d6, lo: 0x9f, hi: 0x9f},
+ {value: 0x460a, lo: 0xa0, hi: 0xa0},
+ {value: 0x4618, lo: 0xa1, hi: 0xa1},
+ {value: 0x4626, lo: 0xa2, hi: 0xa2},
+ {value: 0x4634, lo: 0xa3, hi: 0xa3},
+ {value: 0x4642, lo: 0xa4, hi: 0xa4},
+ {value: 0x812b, lo: 0xa5, hi: 0xa6},
+ {value: 0x8101, lo: 0xa7, hi: 0xa9},
+ {value: 0x8130, lo: 0xad, hi: 0xad},
+ {value: 0x812b, lo: 0xae, hi: 0xb2},
+ {value: 0x812d, lo: 0xbb, hi: 0xbf},
+ // Block 0x84, offset 0x2c7
+ {value: 0x0000, lo: 0x09},
+ {value: 0x812d, lo: 0x80, hi: 0x82},
+ {value: 0x8132, lo: 0x85, hi: 0x89},
+ {value: 0x812d, lo: 0x8a, hi: 0x8b},
+ {value: 0x8132, lo: 0xaa, hi: 0xad},
+ {value: 0x45e0, lo: 0xbb, hi: 0xbb},
+ {value: 0x45ea, lo: 0xbc, hi: 0xbc},
+ {value: 0x4650, lo: 0xbd, hi: 0xbd},
+ {value: 0x466c, lo: 0xbe, hi: 0xbe},
+ {value: 0x465e, lo: 0xbf, hi: 0xbf},
+ // Block 0x85, offset 0x2d1
+ {value: 0x0000, lo: 0x01},
+ {value: 0x467a, lo: 0x80, hi: 0x80},
+ // Block 0x86, offset 0x2d3
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x82, hi: 0x84},
+ // Block 0x87, offset 0x2d5
+ {value: 0x0002, lo: 0x03},
+ {value: 0x0043, lo: 0x80, hi: 0x99},
+ {value: 0x0083, lo: 0x9a, hi: 0xb3},
+ {value: 0x0043, lo: 0xb4, hi: 0xbf},
+ // Block 0x88, offset 0x2d9
+ {value: 0x0002, lo: 0x04},
+ {value: 0x005b, lo: 0x80, hi: 0x8d},
+ {value: 0x0083, lo: 0x8e, hi: 0x94},
+ {value: 0x0093, lo: 0x96, hi: 0xa7},
+ {value: 0x0043, lo: 0xa8, hi: 0xbf},
+ // Block 0x89, offset 0x2de
+ {value: 0x0002, lo: 0x0b},
+ {value: 0x0073, lo: 0x80, hi: 0x81},
+ {value: 0x0083, lo: 0x82, hi: 0x9b},
+ {value: 0x0043, lo: 0x9c, hi: 0x9c},
+ {value: 0x0047, lo: 0x9e, hi: 0x9f},
+ {value: 0x004f, lo: 0xa2, hi: 0xa2},
+ {value: 0x0055, lo: 0xa5, hi: 0xa6},
+ {value: 0x005d, lo: 0xa9, hi: 0xac},
+ {value: 0x0067, lo: 0xae, hi: 0xb5},
+ {value: 0x0083, lo: 0xb6, hi: 0xb9},
+ {value: 0x008d, lo: 0xbb, hi: 0xbb},
+ {value: 0x0091, lo: 0xbd, hi: 0xbf},
+ // Block 0x8a, offset 0x2ea
+ {value: 0x0002, lo: 0x04},
+ {value: 0x0097, lo: 0x80, hi: 0x83},
+ {value: 0x00a1, lo: 0x85, hi: 0x8f},
+ {value: 0x0043, lo: 0x90, hi: 0xa9},
+ {value: 0x0083, lo: 0xaa, hi: 0xbf},
+ // Block 0x8b, offset 0x2ef
+ {value: 0x0002, lo: 0x08},
+ {value: 0x00af, lo: 0x80, hi: 0x83},
+ {value: 0x0043, lo: 0x84, hi: 0x85},
+ {value: 0x0049, lo: 0x87, hi: 0x8a},
+ {value: 0x0055, lo: 0x8d, hi: 0x94},
+ {value: 0x0067, lo: 0x96, hi: 0x9c},
+ {value: 0x0083, lo: 0x9e, hi: 0xb7},
+ {value: 0x0043, lo: 0xb8, hi: 0xb9},
+ {value: 0x0049, lo: 0xbb, hi: 0xbe},
+ // Block 0x8c, offset 0x2f8
+ {value: 0x0002, lo: 0x05},
+ {value: 0x0053, lo: 0x80, hi: 0x84},
+ {value: 0x005f, lo: 0x86, hi: 0x86},
+ {value: 0x0067, lo: 0x8a, hi: 0x90},
+ {value: 0x0083, lo: 0x92, hi: 0xab},
+ {value: 0x0043, lo: 0xac, hi: 0xbf},
+ // Block 0x8d, offset 0x2fe
+ {value: 0x0002, lo: 0x04},
+ {value: 0x006b, lo: 0x80, hi: 0x85},
+ {value: 0x0083, lo: 0x86, hi: 0x9f},
+ {value: 0x0043, lo: 0xa0, hi: 0xb9},
+ {value: 0x0083, lo: 0xba, hi: 0xbf},
+ // Block 0x8e, offset 0x303
+ {value: 0x0002, lo: 0x03},
+ {value: 0x008f, lo: 0x80, hi: 0x93},
+ {value: 0x0043, lo: 0x94, hi: 0xad},
+ {value: 0x0083, lo: 0xae, hi: 0xbf},
+ // Block 0x8f, offset 0x307
+ {value: 0x0002, lo: 0x04},
+ {value: 0x00a7, lo: 0x80, hi: 0x87},
+ {value: 0x0043, lo: 0x88, hi: 0xa1},
+ {value: 0x0083, lo: 0xa2, hi: 0xbb},
+ {value: 0x0043, lo: 0xbc, hi: 0xbf},
+ // Block 0x90, offset 0x30c
+ {value: 0x0002, lo: 0x03},
+ {value: 0x004b, lo: 0x80, hi: 0x95},
+ {value: 0x0083, lo: 0x96, hi: 0xaf},
+ {value: 0x0043, lo: 0xb0, hi: 0xbf},
+ // Block 0x91, offset 0x310
+ {value: 0x0003, lo: 0x0f},
+ {value: 0x01b8, lo: 0x80, hi: 0x80},
+ {value: 0x045f, lo: 0x81, hi: 0x81},
+ {value: 0x01bb, lo: 0x82, hi: 0x9a},
+ {value: 0x045b, lo: 0x9b, hi: 0x9b},
+ {value: 0x01c7, lo: 0x9c, hi: 0x9c},
+ {value: 0x01d0, lo: 0x9d, hi: 0x9d},
+ {value: 0x01d6, lo: 0x9e, hi: 0x9e},
+ {value: 0x01fa, lo: 0x9f, hi: 0x9f},
+ {value: 0x01eb, lo: 0xa0, hi: 0xa0},
+ {value: 0x01e8, lo: 0xa1, hi: 0xa1},
+ {value: 0x0173, lo: 0xa2, hi: 0xb2},
+ {value: 0x0188, lo: 0xb3, hi: 0xb3},
+ {value: 0x01a6, lo: 0xb4, hi: 0xba},
+ {value: 0x045f, lo: 0xbb, hi: 0xbb},
+ {value: 0x01bb, lo: 0xbc, hi: 0xbf},
+ // Block 0x92, offset 0x320
+ {value: 0x0003, lo: 0x0d},
+ {value: 0x01c7, lo: 0x80, hi: 0x94},
+ {value: 0x045b, lo: 0x95, hi: 0x95},
+ {value: 0x01c7, lo: 0x96, hi: 0x96},
+ {value: 0x01d0, lo: 0x97, hi: 0x97},
+ {value: 0x01d6, lo: 0x98, hi: 0x98},
+ {value: 0x01fa, lo: 0x99, hi: 0x99},
+ {value: 0x01eb, lo: 0x9a, hi: 0x9a},
+ {value: 0x01e8, lo: 0x9b, hi: 0x9b},
+ {value: 0x0173, lo: 0x9c, hi: 0xac},
+ {value: 0x0188, lo: 0xad, hi: 0xad},
+ {value: 0x01a6, lo: 0xae, hi: 0xb4},
+ {value: 0x045f, lo: 0xb5, hi: 0xb5},
+ {value: 0x01bb, lo: 0xb6, hi: 0xbf},
+ // Block 0x93, offset 0x32e
+ {value: 0x0003, lo: 0x0d},
+ {value: 0x01d9, lo: 0x80, hi: 0x8e},
+ {value: 0x045b, lo: 0x8f, hi: 0x8f},
+ {value: 0x01c7, lo: 0x90, hi: 0x90},
+ {value: 0x01d0, lo: 0x91, hi: 0x91},
+ {value: 0x01d6, lo: 0x92, hi: 0x92},
+ {value: 0x01fa, lo: 0x93, hi: 0x93},
+ {value: 0x01eb, lo: 0x94, hi: 0x94},
+ {value: 0x01e8, lo: 0x95, hi: 0x95},
+ {value: 0x0173, lo: 0x96, hi: 0xa6},
+ {value: 0x0188, lo: 0xa7, hi: 0xa7},
+ {value: 0x01a6, lo: 0xa8, hi: 0xae},
+ {value: 0x045f, lo: 0xaf, hi: 0xaf},
+ {value: 0x01bb, lo: 0xb0, hi: 0xbf},
+ // Block 0x94, offset 0x33c
+ {value: 0x0003, lo: 0x0d},
+ {value: 0x01eb, lo: 0x80, hi: 0x88},
+ {value: 0x045b, lo: 0x89, hi: 0x89},
+ {value: 0x01c7, lo: 0x8a, hi: 0x8a},
+ {value: 0x01d0, lo: 0x8b, hi: 0x8b},
+ {value: 0x01d6, lo: 0x8c, hi: 0x8c},
+ {value: 0x01fa, lo: 0x8d, hi: 0x8d},
+ {value: 0x01eb, lo: 0x8e, hi: 0x8e},
+ {value: 0x01e8, lo: 0x8f, hi: 0x8f},
+ {value: 0x0173, lo: 0x90, hi: 0xa0},
+ {value: 0x0188, lo: 0xa1, hi: 0xa1},
+ {value: 0x01a6, lo: 0xa2, hi: 0xa8},
+ {value: 0x045f, lo: 0xa9, hi: 0xa9},
+ {value: 0x01bb, lo: 0xaa, hi: 0xbf},
+ // Block 0x95, offset 0x34a
+ {value: 0x0000, lo: 0x05},
+ {value: 0x8132, lo: 0x80, hi: 0x86},
+ {value: 0x8132, lo: 0x88, hi: 0x98},
+ {value: 0x8132, lo: 0x9b, hi: 0xa1},
+ {value: 0x8132, lo: 0xa3, hi: 0xa4},
+ {value: 0x8132, lo: 0xa6, hi: 0xaa},
+ // Block 0x96, offset 0x350
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x90, hi: 0x96},
+ // Block 0x97, offset 0x352
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x84, hi: 0x89},
+ {value: 0x8102, lo: 0x8a, hi: 0x8a},
+ // Block 0x98, offset 0x355
+ {value: 0x0002, lo: 0x09},
+ {value: 0x0063, lo: 0x80, hi: 0x89},
+ {value: 0x1951, lo: 0x8a, hi: 0x8a},
+ {value: 0x1981, lo: 0x8b, hi: 0x8b},
+ {value: 0x199c, lo: 0x8c, hi: 0x8c},
+ {value: 0x19a2, lo: 0x8d, hi: 0x8d},
+ {value: 0x1bc0, lo: 0x8e, hi: 0x8e},
+ {value: 0x19ae, lo: 0x8f, hi: 0x8f},
+ {value: 0x197b, lo: 0xaa, hi: 0xaa},
+ {value: 0x197e, lo: 0xab, hi: 0xab},
+ // Block 0x99, offset 0x35f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x193f, lo: 0x90, hi: 0x90},
+ // Block 0x9a, offset 0x361
+ {value: 0x0028, lo: 0x09},
+ {value: 0x2862, lo: 0x80, hi: 0x80},
+ {value: 0x2826, lo: 0x81, hi: 0x81},
+ {value: 0x2830, lo: 0x82, hi: 0x82},
+ {value: 0x2844, lo: 0x83, hi: 0x84},
+ {value: 0x284e, lo: 0x85, hi: 0x86},
+ {value: 0x283a, lo: 0x87, hi: 0x87},
+ {value: 0x2858, lo: 0x88, hi: 0x88},
+ {value: 0x0b6f, lo: 0x90, hi: 0x90},
+ {value: 0x08e7, lo: 0x91, hi: 0x91},
+}
+
+// recompMap: 7520 bytes (entries only)
+var recompMap = map[uint32]rune{
+ 0x00410300: 0x00C0,
+ 0x00410301: 0x00C1,
+ 0x00410302: 0x00C2,
+ 0x00410303: 0x00C3,
+ 0x00410308: 0x00C4,
+ 0x0041030A: 0x00C5,
+ 0x00430327: 0x00C7,
+ 0x00450300: 0x00C8,
+ 0x00450301: 0x00C9,
+ 0x00450302: 0x00CA,
+ 0x00450308: 0x00CB,
+ 0x00490300: 0x00CC,
+ 0x00490301: 0x00CD,
+ 0x00490302: 0x00CE,
+ 0x00490308: 0x00CF,
+ 0x004E0303: 0x00D1,
+ 0x004F0300: 0x00D2,
+ 0x004F0301: 0x00D3,
+ 0x004F0302: 0x00D4,
+ 0x004F0303: 0x00D5,
+ 0x004F0308: 0x00D6,
+ 0x00550300: 0x00D9,
+ 0x00550301: 0x00DA,
+ 0x00550302: 0x00DB,
+ 0x00550308: 0x00DC,
+ 0x00590301: 0x00DD,
+ 0x00610300: 0x00E0,
+ 0x00610301: 0x00E1,
+ 0x00610302: 0x00E2,
+ 0x00610303: 0x00E3,
+ 0x00610308: 0x00E4,
+ 0x0061030A: 0x00E5,
+ 0x00630327: 0x00E7,
+ 0x00650300: 0x00E8,
+ 0x00650301: 0x00E9,
+ 0x00650302: 0x00EA,
+ 0x00650308: 0x00EB,
+ 0x00690300: 0x00EC,
+ 0x00690301: 0x00ED,
+ 0x00690302: 0x00EE,
+ 0x00690308: 0x00EF,
+ 0x006E0303: 0x00F1,
+ 0x006F0300: 0x00F2,
+ 0x006F0301: 0x00F3,
+ 0x006F0302: 0x00F4,
+ 0x006F0303: 0x00F5,
+ 0x006F0308: 0x00F6,
+ 0x00750300: 0x00F9,
+ 0x00750301: 0x00FA,
+ 0x00750302: 0x00FB,
+ 0x00750308: 0x00FC,
+ 0x00790301: 0x00FD,
+ 0x00790308: 0x00FF,
+ 0x00410304: 0x0100,
+ 0x00610304: 0x0101,
+ 0x00410306: 0x0102,
+ 0x00610306: 0x0103,
+ 0x00410328: 0x0104,
+ 0x00610328: 0x0105,
+ 0x00430301: 0x0106,
+ 0x00630301: 0x0107,
+ 0x00430302: 0x0108,
+ 0x00630302: 0x0109,
+ 0x00430307: 0x010A,
+ 0x00630307: 0x010B,
+ 0x0043030C: 0x010C,
+ 0x0063030C: 0x010D,
+ 0x0044030C: 0x010E,
+ 0x0064030C: 0x010F,
+ 0x00450304: 0x0112,
+ 0x00650304: 0x0113,
+ 0x00450306: 0x0114,
+ 0x00650306: 0x0115,
+ 0x00450307: 0x0116,
+ 0x00650307: 0x0117,
+ 0x00450328: 0x0118,
+ 0x00650328: 0x0119,
+ 0x0045030C: 0x011A,
+ 0x0065030C: 0x011B,
+ 0x00470302: 0x011C,
+ 0x00670302: 0x011D,
+ 0x00470306: 0x011E,
+ 0x00670306: 0x011F,
+ 0x00470307: 0x0120,
+ 0x00670307: 0x0121,
+ 0x00470327: 0x0122,
+ 0x00670327: 0x0123,
+ 0x00480302: 0x0124,
+ 0x00680302: 0x0125,
+ 0x00490303: 0x0128,
+ 0x00690303: 0x0129,
+ 0x00490304: 0x012A,
+ 0x00690304: 0x012B,
+ 0x00490306: 0x012C,
+ 0x00690306: 0x012D,
+ 0x00490328: 0x012E,
+ 0x00690328: 0x012F,
+ 0x00490307: 0x0130,
+ 0x004A0302: 0x0134,
+ 0x006A0302: 0x0135,
+ 0x004B0327: 0x0136,
+ 0x006B0327: 0x0137,
+ 0x004C0301: 0x0139,
+ 0x006C0301: 0x013A,
+ 0x004C0327: 0x013B,
+ 0x006C0327: 0x013C,
+ 0x004C030C: 0x013D,
+ 0x006C030C: 0x013E,
+ 0x004E0301: 0x0143,
+ 0x006E0301: 0x0144,
+ 0x004E0327: 0x0145,
+ 0x006E0327: 0x0146,
+ 0x004E030C: 0x0147,
+ 0x006E030C: 0x0148,
+ 0x004F0304: 0x014C,
+ 0x006F0304: 0x014D,
+ 0x004F0306: 0x014E,
+ 0x006F0306: 0x014F,
+ 0x004F030B: 0x0150,
+ 0x006F030B: 0x0151,
+ 0x00520301: 0x0154,
+ 0x00720301: 0x0155,
+ 0x00520327: 0x0156,
+ 0x00720327: 0x0157,
+ 0x0052030C: 0x0158,
+ 0x0072030C: 0x0159,
+ 0x00530301: 0x015A,
+ 0x00730301: 0x015B,
+ 0x00530302: 0x015C,
+ 0x00730302: 0x015D,
+ 0x00530327: 0x015E,
+ 0x00730327: 0x015F,
+ 0x0053030C: 0x0160,
+ 0x0073030C: 0x0161,
+ 0x00540327: 0x0162,
+ 0x00740327: 0x0163,
+ 0x0054030C: 0x0164,
+ 0x0074030C: 0x0165,
+ 0x00550303: 0x0168,
+ 0x00750303: 0x0169,
+ 0x00550304: 0x016A,
+ 0x00750304: 0x016B,
+ 0x00550306: 0x016C,
+ 0x00750306: 0x016D,
+ 0x0055030A: 0x016E,
+ 0x0075030A: 0x016F,
+ 0x0055030B: 0x0170,
+ 0x0075030B: 0x0171,
+ 0x00550328: 0x0172,
+ 0x00750328: 0x0173,
+ 0x00570302: 0x0174,
+ 0x00770302: 0x0175,
+ 0x00590302: 0x0176,
+ 0x00790302: 0x0177,
+ 0x00590308: 0x0178,
+ 0x005A0301: 0x0179,
+ 0x007A0301: 0x017A,
+ 0x005A0307: 0x017B,
+ 0x007A0307: 0x017C,
+ 0x005A030C: 0x017D,
+ 0x007A030C: 0x017E,
+ 0x004F031B: 0x01A0,
+ 0x006F031B: 0x01A1,
+ 0x0055031B: 0x01AF,
+ 0x0075031B: 0x01B0,
+ 0x0041030C: 0x01CD,
+ 0x0061030C: 0x01CE,
+ 0x0049030C: 0x01CF,
+ 0x0069030C: 0x01D0,
+ 0x004F030C: 0x01D1,
+ 0x006F030C: 0x01D2,
+ 0x0055030C: 0x01D3,
+ 0x0075030C: 0x01D4,
+ 0x00DC0304: 0x01D5,
+ 0x00FC0304: 0x01D6,
+ 0x00DC0301: 0x01D7,
+ 0x00FC0301: 0x01D8,
+ 0x00DC030C: 0x01D9,
+ 0x00FC030C: 0x01DA,
+ 0x00DC0300: 0x01DB,
+ 0x00FC0300: 0x01DC,
+ 0x00C40304: 0x01DE,
+ 0x00E40304: 0x01DF,
+ 0x02260304: 0x01E0,
+ 0x02270304: 0x01E1,
+ 0x00C60304: 0x01E2,
+ 0x00E60304: 0x01E3,
+ 0x0047030C: 0x01E6,
+ 0x0067030C: 0x01E7,
+ 0x004B030C: 0x01E8,
+ 0x006B030C: 0x01E9,
+ 0x004F0328: 0x01EA,
+ 0x006F0328: 0x01EB,
+ 0x01EA0304: 0x01EC,
+ 0x01EB0304: 0x01ED,
+ 0x01B7030C: 0x01EE,
+ 0x0292030C: 0x01EF,
+ 0x006A030C: 0x01F0,
+ 0x00470301: 0x01F4,
+ 0x00670301: 0x01F5,
+ 0x004E0300: 0x01F8,
+ 0x006E0300: 0x01F9,
+ 0x00C50301: 0x01FA,
+ 0x00E50301: 0x01FB,
+ 0x00C60301: 0x01FC,
+ 0x00E60301: 0x01FD,
+ 0x00D80301: 0x01FE,
+ 0x00F80301: 0x01FF,
+ 0x0041030F: 0x0200,
+ 0x0061030F: 0x0201,
+ 0x00410311: 0x0202,
+ 0x00610311: 0x0203,
+ 0x0045030F: 0x0204,
+ 0x0065030F: 0x0205,
+ 0x00450311: 0x0206,
+ 0x00650311: 0x0207,
+ 0x0049030F: 0x0208,
+ 0x0069030F: 0x0209,
+ 0x00490311: 0x020A,
+ 0x00690311: 0x020B,
+ 0x004F030F: 0x020C,
+ 0x006F030F: 0x020D,
+ 0x004F0311: 0x020E,
+ 0x006F0311: 0x020F,
+ 0x0052030F: 0x0210,
+ 0x0072030F: 0x0211,
+ 0x00520311: 0x0212,
+ 0x00720311: 0x0213,
+ 0x0055030F: 0x0214,
+ 0x0075030F: 0x0215,
+ 0x00550311: 0x0216,
+ 0x00750311: 0x0217,
+ 0x00530326: 0x0218,
+ 0x00730326: 0x0219,
+ 0x00540326: 0x021A,
+ 0x00740326: 0x021B,
+ 0x0048030C: 0x021E,
+ 0x0068030C: 0x021F,
+ 0x00410307: 0x0226,
+ 0x00610307: 0x0227,
+ 0x00450327: 0x0228,
+ 0x00650327: 0x0229,
+ 0x00D60304: 0x022A,
+ 0x00F60304: 0x022B,
+ 0x00D50304: 0x022C,
+ 0x00F50304: 0x022D,
+ 0x004F0307: 0x022E,
+ 0x006F0307: 0x022F,
+ 0x022E0304: 0x0230,
+ 0x022F0304: 0x0231,
+ 0x00590304: 0x0232,
+ 0x00790304: 0x0233,
+ 0x00A80301: 0x0385,
+ 0x03910301: 0x0386,
+ 0x03950301: 0x0388,
+ 0x03970301: 0x0389,
+ 0x03990301: 0x038A,
+ 0x039F0301: 0x038C,
+ 0x03A50301: 0x038E,
+ 0x03A90301: 0x038F,
+ 0x03CA0301: 0x0390,
+ 0x03990308: 0x03AA,
+ 0x03A50308: 0x03AB,
+ 0x03B10301: 0x03AC,
+ 0x03B50301: 0x03AD,
+ 0x03B70301: 0x03AE,
+ 0x03B90301: 0x03AF,
+ 0x03CB0301: 0x03B0,
+ 0x03B90308: 0x03CA,
+ 0x03C50308: 0x03CB,
+ 0x03BF0301: 0x03CC,
+ 0x03C50301: 0x03CD,
+ 0x03C90301: 0x03CE,
+ 0x03D20301: 0x03D3,
+ 0x03D20308: 0x03D4,
+ 0x04150300: 0x0400,
+ 0x04150308: 0x0401,
+ 0x04130301: 0x0403,
+ 0x04060308: 0x0407,
+ 0x041A0301: 0x040C,
+ 0x04180300: 0x040D,
+ 0x04230306: 0x040E,
+ 0x04180306: 0x0419,
+ 0x04380306: 0x0439,
+ 0x04350300: 0x0450,
+ 0x04350308: 0x0451,
+ 0x04330301: 0x0453,
+ 0x04560308: 0x0457,
+ 0x043A0301: 0x045C,
+ 0x04380300: 0x045D,
+ 0x04430306: 0x045E,
+ 0x0474030F: 0x0476,
+ 0x0475030F: 0x0477,
+ 0x04160306: 0x04C1,
+ 0x04360306: 0x04C2,
+ 0x04100306: 0x04D0,
+ 0x04300306: 0x04D1,
+ 0x04100308: 0x04D2,
+ 0x04300308: 0x04D3,
+ 0x04150306: 0x04D6,
+ 0x04350306: 0x04D7,
+ 0x04D80308: 0x04DA,
+ 0x04D90308: 0x04DB,
+ 0x04160308: 0x04DC,
+ 0x04360308: 0x04DD,
+ 0x04170308: 0x04DE,
+ 0x04370308: 0x04DF,
+ 0x04180304: 0x04E2,
+ 0x04380304: 0x04E3,
+ 0x04180308: 0x04E4,
+ 0x04380308: 0x04E5,
+ 0x041E0308: 0x04E6,
+ 0x043E0308: 0x04E7,
+ 0x04E80308: 0x04EA,
+ 0x04E90308: 0x04EB,
+ 0x042D0308: 0x04EC,
+ 0x044D0308: 0x04ED,
+ 0x04230304: 0x04EE,
+ 0x04430304: 0x04EF,
+ 0x04230308: 0x04F0,
+ 0x04430308: 0x04F1,
+ 0x0423030B: 0x04F2,
+ 0x0443030B: 0x04F3,
+ 0x04270308: 0x04F4,
+ 0x04470308: 0x04F5,
+ 0x042B0308: 0x04F8,
+ 0x044B0308: 0x04F9,
+ 0x06270653: 0x0622,
+ 0x06270654: 0x0623,
+ 0x06480654: 0x0624,
+ 0x06270655: 0x0625,
+ 0x064A0654: 0x0626,
+ 0x06D50654: 0x06C0,
+ 0x06C10654: 0x06C2,
+ 0x06D20654: 0x06D3,
+ 0x0928093C: 0x0929,
+ 0x0930093C: 0x0931,
+ 0x0933093C: 0x0934,
+ 0x09C709BE: 0x09CB,
+ 0x09C709D7: 0x09CC,
+ 0x0B470B56: 0x0B48,
+ 0x0B470B3E: 0x0B4B,
+ 0x0B470B57: 0x0B4C,
+ 0x0B920BD7: 0x0B94,
+ 0x0BC60BBE: 0x0BCA,
+ 0x0BC70BBE: 0x0BCB,
+ 0x0BC60BD7: 0x0BCC,
+ 0x0C460C56: 0x0C48,
+ 0x0CBF0CD5: 0x0CC0,
+ 0x0CC60CD5: 0x0CC7,
+ 0x0CC60CD6: 0x0CC8,
+ 0x0CC60CC2: 0x0CCA,
+ 0x0CCA0CD5: 0x0CCB,
+ 0x0D460D3E: 0x0D4A,
+ 0x0D470D3E: 0x0D4B,
+ 0x0D460D57: 0x0D4C,
+ 0x0DD90DCA: 0x0DDA,
+ 0x0DD90DCF: 0x0DDC,
+ 0x0DDC0DCA: 0x0DDD,
+ 0x0DD90DDF: 0x0DDE,
+ 0x1025102E: 0x1026,
+ 0x1B051B35: 0x1B06,
+ 0x1B071B35: 0x1B08,
+ 0x1B091B35: 0x1B0A,
+ 0x1B0B1B35: 0x1B0C,
+ 0x1B0D1B35: 0x1B0E,
+ 0x1B111B35: 0x1B12,
+ 0x1B3A1B35: 0x1B3B,
+ 0x1B3C1B35: 0x1B3D,
+ 0x1B3E1B35: 0x1B40,
+ 0x1B3F1B35: 0x1B41,
+ 0x1B421B35: 0x1B43,
+ 0x00410325: 0x1E00,
+ 0x00610325: 0x1E01,
+ 0x00420307: 0x1E02,
+ 0x00620307: 0x1E03,
+ 0x00420323: 0x1E04,
+ 0x00620323: 0x1E05,
+ 0x00420331: 0x1E06,
+ 0x00620331: 0x1E07,
+ 0x00C70301: 0x1E08,
+ 0x00E70301: 0x1E09,
+ 0x00440307: 0x1E0A,
+ 0x00640307: 0x1E0B,
+ 0x00440323: 0x1E0C,
+ 0x00640323: 0x1E0D,
+ 0x00440331: 0x1E0E,
+ 0x00640331: 0x1E0F,
+ 0x00440327: 0x1E10,
+ 0x00640327: 0x1E11,
+ 0x0044032D: 0x1E12,
+ 0x0064032D: 0x1E13,
+ 0x01120300: 0x1E14,
+ 0x01130300: 0x1E15,
+ 0x01120301: 0x1E16,
+ 0x01130301: 0x1E17,
+ 0x0045032D: 0x1E18,
+ 0x0065032D: 0x1E19,
+ 0x00450330: 0x1E1A,
+ 0x00650330: 0x1E1B,
+ 0x02280306: 0x1E1C,
+ 0x02290306: 0x1E1D,
+ 0x00460307: 0x1E1E,
+ 0x00660307: 0x1E1F,
+ 0x00470304: 0x1E20,
+ 0x00670304: 0x1E21,
+ 0x00480307: 0x1E22,
+ 0x00680307: 0x1E23,
+ 0x00480323: 0x1E24,
+ 0x00680323: 0x1E25,
+ 0x00480308: 0x1E26,
+ 0x00680308: 0x1E27,
+ 0x00480327: 0x1E28,
+ 0x00680327: 0x1E29,
+ 0x0048032E: 0x1E2A,
+ 0x0068032E: 0x1E2B,
+ 0x00490330: 0x1E2C,
+ 0x00690330: 0x1E2D,
+ 0x00CF0301: 0x1E2E,
+ 0x00EF0301: 0x1E2F,
+ 0x004B0301: 0x1E30,
+ 0x006B0301: 0x1E31,
+ 0x004B0323: 0x1E32,
+ 0x006B0323: 0x1E33,
+ 0x004B0331: 0x1E34,
+ 0x006B0331: 0x1E35,
+ 0x004C0323: 0x1E36,
+ 0x006C0323: 0x1E37,
+ 0x1E360304: 0x1E38,
+ 0x1E370304: 0x1E39,
+ 0x004C0331: 0x1E3A,
+ 0x006C0331: 0x1E3B,
+ 0x004C032D: 0x1E3C,
+ 0x006C032D: 0x1E3D,
+ 0x004D0301: 0x1E3E,
+ 0x006D0301: 0x1E3F,
+ 0x004D0307: 0x1E40,
+ 0x006D0307: 0x1E41,
+ 0x004D0323: 0x1E42,
+ 0x006D0323: 0x1E43,
+ 0x004E0307: 0x1E44,
+ 0x006E0307: 0x1E45,
+ 0x004E0323: 0x1E46,
+ 0x006E0323: 0x1E47,
+ 0x004E0331: 0x1E48,
+ 0x006E0331: 0x1E49,
+ 0x004E032D: 0x1E4A,
+ 0x006E032D: 0x1E4B,
+ 0x00D50301: 0x1E4C,
+ 0x00F50301: 0x1E4D,
+ 0x00D50308: 0x1E4E,
+ 0x00F50308: 0x1E4F,
+ 0x014C0300: 0x1E50,
+ 0x014D0300: 0x1E51,
+ 0x014C0301: 0x1E52,
+ 0x014D0301: 0x1E53,
+ 0x00500301: 0x1E54,
+ 0x00700301: 0x1E55,
+ 0x00500307: 0x1E56,
+ 0x00700307: 0x1E57,
+ 0x00520307: 0x1E58,
+ 0x00720307: 0x1E59,
+ 0x00520323: 0x1E5A,
+ 0x00720323: 0x1E5B,
+ 0x1E5A0304: 0x1E5C,
+ 0x1E5B0304: 0x1E5D,
+ 0x00520331: 0x1E5E,
+ 0x00720331: 0x1E5F,
+ 0x00530307: 0x1E60,
+ 0x00730307: 0x1E61,
+ 0x00530323: 0x1E62,
+ 0x00730323: 0x1E63,
+ 0x015A0307: 0x1E64,
+ 0x015B0307: 0x1E65,
+ 0x01600307: 0x1E66,
+ 0x01610307: 0x1E67,
+ 0x1E620307: 0x1E68,
+ 0x1E630307: 0x1E69,
+ 0x00540307: 0x1E6A,
+ 0x00740307: 0x1E6B,
+ 0x00540323: 0x1E6C,
+ 0x00740323: 0x1E6D,
+ 0x00540331: 0x1E6E,
+ 0x00740331: 0x1E6F,
+ 0x0054032D: 0x1E70,
+ 0x0074032D: 0x1E71,
+ 0x00550324: 0x1E72,
+ 0x00750324: 0x1E73,
+ 0x00550330: 0x1E74,
+ 0x00750330: 0x1E75,
+ 0x0055032D: 0x1E76,
+ 0x0075032D: 0x1E77,
+ 0x01680301: 0x1E78,
+ 0x01690301: 0x1E79,
+ 0x016A0308: 0x1E7A,
+ 0x016B0308: 0x1E7B,
+ 0x00560303: 0x1E7C,
+ 0x00760303: 0x1E7D,
+ 0x00560323: 0x1E7E,
+ 0x00760323: 0x1E7F,
+ 0x00570300: 0x1E80,
+ 0x00770300: 0x1E81,
+ 0x00570301: 0x1E82,
+ 0x00770301: 0x1E83,
+ 0x00570308: 0x1E84,
+ 0x00770308: 0x1E85,
+ 0x00570307: 0x1E86,
+ 0x00770307: 0x1E87,
+ 0x00570323: 0x1E88,
+ 0x00770323: 0x1E89,
+ 0x00580307: 0x1E8A,
+ 0x00780307: 0x1E8B,
+ 0x00580308: 0x1E8C,
+ 0x00780308: 0x1E8D,
+ 0x00590307: 0x1E8E,
+ 0x00790307: 0x1E8F,
+ 0x005A0302: 0x1E90,
+ 0x007A0302: 0x1E91,
+ 0x005A0323: 0x1E92,
+ 0x007A0323: 0x1E93,
+ 0x005A0331: 0x1E94,
+ 0x007A0331: 0x1E95,
+ 0x00680331: 0x1E96,
+ 0x00740308: 0x1E97,
+ 0x0077030A: 0x1E98,
+ 0x0079030A: 0x1E99,
+ 0x017F0307: 0x1E9B,
+ 0x00410323: 0x1EA0,
+ 0x00610323: 0x1EA1,
+ 0x00410309: 0x1EA2,
+ 0x00610309: 0x1EA3,
+ 0x00C20301: 0x1EA4,
+ 0x00E20301: 0x1EA5,
+ 0x00C20300: 0x1EA6,
+ 0x00E20300: 0x1EA7,
+ 0x00C20309: 0x1EA8,
+ 0x00E20309: 0x1EA9,
+ 0x00C20303: 0x1EAA,
+ 0x00E20303: 0x1EAB,
+ 0x1EA00302: 0x1EAC,
+ 0x1EA10302: 0x1EAD,
+ 0x01020301: 0x1EAE,
+ 0x01030301: 0x1EAF,
+ 0x01020300: 0x1EB0,
+ 0x01030300: 0x1EB1,
+ 0x01020309: 0x1EB2,
+ 0x01030309: 0x1EB3,
+ 0x01020303: 0x1EB4,
+ 0x01030303: 0x1EB5,
+ 0x1EA00306: 0x1EB6,
+ 0x1EA10306: 0x1EB7,
+ 0x00450323: 0x1EB8,
+ 0x00650323: 0x1EB9,
+ 0x00450309: 0x1EBA,
+ 0x00650309: 0x1EBB,
+ 0x00450303: 0x1EBC,
+ 0x00650303: 0x1EBD,
+ 0x00CA0301: 0x1EBE,
+ 0x00EA0301: 0x1EBF,
+ 0x00CA0300: 0x1EC0,
+ 0x00EA0300: 0x1EC1,
+ 0x00CA0309: 0x1EC2,
+ 0x00EA0309: 0x1EC3,
+ 0x00CA0303: 0x1EC4,
+ 0x00EA0303: 0x1EC5,
+ 0x1EB80302: 0x1EC6,
+ 0x1EB90302: 0x1EC7,
+ 0x00490309: 0x1EC8,
+ 0x00690309: 0x1EC9,
+ 0x00490323: 0x1ECA,
+ 0x00690323: 0x1ECB,
+ 0x004F0323: 0x1ECC,
+ 0x006F0323: 0x1ECD,
+ 0x004F0309: 0x1ECE,
+ 0x006F0309: 0x1ECF,
+ 0x00D40301: 0x1ED0,
+ 0x00F40301: 0x1ED1,
+ 0x00D40300: 0x1ED2,
+ 0x00F40300: 0x1ED3,
+ 0x00D40309: 0x1ED4,
+ 0x00F40309: 0x1ED5,
+ 0x00D40303: 0x1ED6,
+ 0x00F40303: 0x1ED7,
+ 0x1ECC0302: 0x1ED8,
+ 0x1ECD0302: 0x1ED9,
+ 0x01A00301: 0x1EDA,
+ 0x01A10301: 0x1EDB,
+ 0x01A00300: 0x1EDC,
+ 0x01A10300: 0x1EDD,
+ 0x01A00309: 0x1EDE,
+ 0x01A10309: 0x1EDF,
+ 0x01A00303: 0x1EE0,
+ 0x01A10303: 0x1EE1,
+ 0x01A00323: 0x1EE2,
+ 0x01A10323: 0x1EE3,
+ 0x00550323: 0x1EE4,
+ 0x00750323: 0x1EE5,
+ 0x00550309: 0x1EE6,
+ 0x00750309: 0x1EE7,
+ 0x01AF0301: 0x1EE8,
+ 0x01B00301: 0x1EE9,
+ 0x01AF0300: 0x1EEA,
+ 0x01B00300: 0x1EEB,
+ 0x01AF0309: 0x1EEC,
+ 0x01B00309: 0x1EED,
+ 0x01AF0303: 0x1EEE,
+ 0x01B00303: 0x1EEF,
+ 0x01AF0323: 0x1EF0,
+ 0x01B00323: 0x1EF1,
+ 0x00590300: 0x1EF2,
+ 0x00790300: 0x1EF3,
+ 0x00590323: 0x1EF4,
+ 0x00790323: 0x1EF5,
+ 0x00590309: 0x1EF6,
+ 0x00790309: 0x1EF7,
+ 0x00590303: 0x1EF8,
+ 0x00790303: 0x1EF9,
+ 0x03B10313: 0x1F00,
+ 0x03B10314: 0x1F01,
+ 0x1F000300: 0x1F02,
+ 0x1F010300: 0x1F03,
+ 0x1F000301: 0x1F04,
+ 0x1F010301: 0x1F05,
+ 0x1F000342: 0x1F06,
+ 0x1F010342: 0x1F07,
+ 0x03910313: 0x1F08,
+ 0x03910314: 0x1F09,
+ 0x1F080300: 0x1F0A,
+ 0x1F090300: 0x1F0B,
+ 0x1F080301: 0x1F0C,
+ 0x1F090301: 0x1F0D,
+ 0x1F080342: 0x1F0E,
+ 0x1F090342: 0x1F0F,
+ 0x03B50313: 0x1F10,
+ 0x03B50314: 0x1F11,
+ 0x1F100300: 0x1F12,
+ 0x1F110300: 0x1F13,
+ 0x1F100301: 0x1F14,
+ 0x1F110301: 0x1F15,
+ 0x03950313: 0x1F18,
+ 0x03950314: 0x1F19,
+ 0x1F180300: 0x1F1A,
+ 0x1F190300: 0x1F1B,
+ 0x1F180301: 0x1F1C,
+ 0x1F190301: 0x1F1D,
+ 0x03B70313: 0x1F20,
+ 0x03B70314: 0x1F21,
+ 0x1F200300: 0x1F22,
+ 0x1F210300: 0x1F23,
+ 0x1F200301: 0x1F24,
+ 0x1F210301: 0x1F25,
+ 0x1F200342: 0x1F26,
+ 0x1F210342: 0x1F27,
+ 0x03970313: 0x1F28,
+ 0x03970314: 0x1F29,
+ 0x1F280300: 0x1F2A,
+ 0x1F290300: 0x1F2B,
+ 0x1F280301: 0x1F2C,
+ 0x1F290301: 0x1F2D,
+ 0x1F280342: 0x1F2E,
+ 0x1F290342: 0x1F2F,
+ 0x03B90313: 0x1F30,
+ 0x03B90314: 0x1F31,
+ 0x1F300300: 0x1F32,
+ 0x1F310300: 0x1F33,
+ 0x1F300301: 0x1F34,
+ 0x1F310301: 0x1F35,
+ 0x1F300342: 0x1F36,
+ 0x1F310342: 0x1F37,
+ 0x03990313: 0x1F38,
+ 0x03990314: 0x1F39,
+ 0x1F380300: 0x1F3A,
+ 0x1F390300: 0x1F3B,
+ 0x1F380301: 0x1F3C,
+ 0x1F390301: 0x1F3D,
+ 0x1F380342: 0x1F3E,
+ 0x1F390342: 0x1F3F,
+ 0x03BF0313: 0x1F40,
+ 0x03BF0314: 0x1F41,
+ 0x1F400300: 0x1F42,
+ 0x1F410300: 0x1F43,
+ 0x1F400301: 0x1F44,
+ 0x1F410301: 0x1F45,
+ 0x039F0313: 0x1F48,
+ 0x039F0314: 0x1F49,
+ 0x1F480300: 0x1F4A,
+ 0x1F490300: 0x1F4B,
+ 0x1F480301: 0x1F4C,
+ 0x1F490301: 0x1F4D,
+ 0x03C50313: 0x1F50,
+ 0x03C50314: 0x1F51,
+ 0x1F500300: 0x1F52,
+ 0x1F510300: 0x1F53,
+ 0x1F500301: 0x1F54,
+ 0x1F510301: 0x1F55,
+ 0x1F500342: 0x1F56,
+ 0x1F510342: 0x1F57,
+ 0x03A50314: 0x1F59,
+ 0x1F590300: 0x1F5B,
+ 0x1F590301: 0x1F5D,
+ 0x1F590342: 0x1F5F,
+ 0x03C90313: 0x1F60,
+ 0x03C90314: 0x1F61,
+ 0x1F600300: 0x1F62,
+ 0x1F610300: 0x1F63,
+ 0x1F600301: 0x1F64,
+ 0x1F610301: 0x1F65,
+ 0x1F600342: 0x1F66,
+ 0x1F610342: 0x1F67,
+ 0x03A90313: 0x1F68,
+ 0x03A90314: 0x1F69,
+ 0x1F680300: 0x1F6A,
+ 0x1F690300: 0x1F6B,
+ 0x1F680301: 0x1F6C,
+ 0x1F690301: 0x1F6D,
+ 0x1F680342: 0x1F6E,
+ 0x1F690342: 0x1F6F,
+ 0x03B10300: 0x1F70,
+ 0x03B50300: 0x1F72,
+ 0x03B70300: 0x1F74,
+ 0x03B90300: 0x1F76,
+ 0x03BF0300: 0x1F78,
+ 0x03C50300: 0x1F7A,
+ 0x03C90300: 0x1F7C,
+ 0x1F000345: 0x1F80,
+ 0x1F010345: 0x1F81,
+ 0x1F020345: 0x1F82,
+ 0x1F030345: 0x1F83,
+ 0x1F040345: 0x1F84,
+ 0x1F050345: 0x1F85,
+ 0x1F060345: 0x1F86,
+ 0x1F070345: 0x1F87,
+ 0x1F080345: 0x1F88,
+ 0x1F090345: 0x1F89,
+ 0x1F0A0345: 0x1F8A,
+ 0x1F0B0345: 0x1F8B,
+ 0x1F0C0345: 0x1F8C,
+ 0x1F0D0345: 0x1F8D,
+ 0x1F0E0345: 0x1F8E,
+ 0x1F0F0345: 0x1F8F,
+ 0x1F200345: 0x1F90,
+ 0x1F210345: 0x1F91,
+ 0x1F220345: 0x1F92,
+ 0x1F230345: 0x1F93,
+ 0x1F240345: 0x1F94,
+ 0x1F250345: 0x1F95,
+ 0x1F260345: 0x1F96,
+ 0x1F270345: 0x1F97,
+ 0x1F280345: 0x1F98,
+ 0x1F290345: 0x1F99,
+ 0x1F2A0345: 0x1F9A,
+ 0x1F2B0345: 0x1F9B,
+ 0x1F2C0345: 0x1F9C,
+ 0x1F2D0345: 0x1F9D,
+ 0x1F2E0345: 0x1F9E,
+ 0x1F2F0345: 0x1F9F,
+ 0x1F600345: 0x1FA0,
+ 0x1F610345: 0x1FA1,
+ 0x1F620345: 0x1FA2,
+ 0x1F630345: 0x1FA3,
+ 0x1F640345: 0x1FA4,
+ 0x1F650345: 0x1FA5,
+ 0x1F660345: 0x1FA6,
+ 0x1F670345: 0x1FA7,
+ 0x1F680345: 0x1FA8,
+ 0x1F690345: 0x1FA9,
+ 0x1F6A0345: 0x1FAA,
+ 0x1F6B0345: 0x1FAB,
+ 0x1F6C0345: 0x1FAC,
+ 0x1F6D0345: 0x1FAD,
+ 0x1F6E0345: 0x1FAE,
+ 0x1F6F0345: 0x1FAF,
+ 0x03B10306: 0x1FB0,
+ 0x03B10304: 0x1FB1,
+ 0x1F700345: 0x1FB2,
+ 0x03B10345: 0x1FB3,
+ 0x03AC0345: 0x1FB4,
+ 0x03B10342: 0x1FB6,
+ 0x1FB60345: 0x1FB7,
+ 0x03910306: 0x1FB8,
+ 0x03910304: 0x1FB9,
+ 0x03910300: 0x1FBA,
+ 0x03910345: 0x1FBC,
+ 0x00A80342: 0x1FC1,
+ 0x1F740345: 0x1FC2,
+ 0x03B70345: 0x1FC3,
+ 0x03AE0345: 0x1FC4,
+ 0x03B70342: 0x1FC6,
+ 0x1FC60345: 0x1FC7,
+ 0x03950300: 0x1FC8,
+ 0x03970300: 0x1FCA,
+ 0x03970345: 0x1FCC,
+ 0x1FBF0300: 0x1FCD,
+ 0x1FBF0301: 0x1FCE,
+ 0x1FBF0342: 0x1FCF,
+ 0x03B90306: 0x1FD0,
+ 0x03B90304: 0x1FD1,
+ 0x03CA0300: 0x1FD2,
+ 0x03B90342: 0x1FD6,
+ 0x03CA0342: 0x1FD7,
+ 0x03990306: 0x1FD8,
+ 0x03990304: 0x1FD9,
+ 0x03990300: 0x1FDA,
+ 0x1FFE0300: 0x1FDD,
+ 0x1FFE0301: 0x1FDE,
+ 0x1FFE0342: 0x1FDF,
+ 0x03C50306: 0x1FE0,
+ 0x03C50304: 0x1FE1,
+ 0x03CB0300: 0x1FE2,
+ 0x03C10313: 0x1FE4,
+ 0x03C10314: 0x1FE5,
+ 0x03C50342: 0x1FE6,
+ 0x03CB0342: 0x1FE7,
+ 0x03A50306: 0x1FE8,
+ 0x03A50304: 0x1FE9,
+ 0x03A50300: 0x1FEA,
+ 0x03A10314: 0x1FEC,
+ 0x00A80300: 0x1FED,
+ 0x1F7C0345: 0x1FF2,
+ 0x03C90345: 0x1FF3,
+ 0x03CE0345: 0x1FF4,
+ 0x03C90342: 0x1FF6,
+ 0x1FF60345: 0x1FF7,
+ 0x039F0300: 0x1FF8,
+ 0x03A90300: 0x1FFA,
+ 0x03A90345: 0x1FFC,
+ 0x21900338: 0x219A,
+ 0x21920338: 0x219B,
+ 0x21940338: 0x21AE,
+ 0x21D00338: 0x21CD,
+ 0x21D40338: 0x21CE,
+ 0x21D20338: 0x21CF,
+ 0x22030338: 0x2204,
+ 0x22080338: 0x2209,
+ 0x220B0338: 0x220C,
+ 0x22230338: 0x2224,
+ 0x22250338: 0x2226,
+ 0x223C0338: 0x2241,
+ 0x22430338: 0x2244,
+ 0x22450338: 0x2247,
+ 0x22480338: 0x2249,
+ 0x003D0338: 0x2260,
+ 0x22610338: 0x2262,
+ 0x224D0338: 0x226D,
+ 0x003C0338: 0x226E,
+ 0x003E0338: 0x226F,
+ 0x22640338: 0x2270,
+ 0x22650338: 0x2271,
+ 0x22720338: 0x2274,
+ 0x22730338: 0x2275,
+ 0x22760338: 0x2278,
+ 0x22770338: 0x2279,
+ 0x227A0338: 0x2280,
+ 0x227B0338: 0x2281,
+ 0x22820338: 0x2284,
+ 0x22830338: 0x2285,
+ 0x22860338: 0x2288,
+ 0x22870338: 0x2289,
+ 0x22A20338: 0x22AC,
+ 0x22A80338: 0x22AD,
+ 0x22A90338: 0x22AE,
+ 0x22AB0338: 0x22AF,
+ 0x227C0338: 0x22E0,
+ 0x227D0338: 0x22E1,
+ 0x22910338: 0x22E2,
+ 0x22920338: 0x22E3,
+ 0x22B20338: 0x22EA,
+ 0x22B30338: 0x22EB,
+ 0x22B40338: 0x22EC,
+ 0x22B50338: 0x22ED,
+ 0x304B3099: 0x304C,
+ 0x304D3099: 0x304E,
+ 0x304F3099: 0x3050,
+ 0x30513099: 0x3052,
+ 0x30533099: 0x3054,
+ 0x30553099: 0x3056,
+ 0x30573099: 0x3058,
+ 0x30593099: 0x305A,
+ 0x305B3099: 0x305C,
+ 0x305D3099: 0x305E,
+ 0x305F3099: 0x3060,
+ 0x30613099: 0x3062,
+ 0x30643099: 0x3065,
+ 0x30663099: 0x3067,
+ 0x30683099: 0x3069,
+ 0x306F3099: 0x3070,
+ 0x306F309A: 0x3071,
+ 0x30723099: 0x3073,
+ 0x3072309A: 0x3074,
+ 0x30753099: 0x3076,
+ 0x3075309A: 0x3077,
+ 0x30783099: 0x3079,
+ 0x3078309A: 0x307A,
+ 0x307B3099: 0x307C,
+ 0x307B309A: 0x307D,
+ 0x30463099: 0x3094,
+ 0x309D3099: 0x309E,
+ 0x30AB3099: 0x30AC,
+ 0x30AD3099: 0x30AE,
+ 0x30AF3099: 0x30B0,
+ 0x30B13099: 0x30B2,
+ 0x30B33099: 0x30B4,
+ 0x30B53099: 0x30B6,
+ 0x30B73099: 0x30B8,
+ 0x30B93099: 0x30BA,
+ 0x30BB3099: 0x30BC,
+ 0x30BD3099: 0x30BE,
+ 0x30BF3099: 0x30C0,
+ 0x30C13099: 0x30C2,
+ 0x30C43099: 0x30C5,
+ 0x30C63099: 0x30C7,
+ 0x30C83099: 0x30C9,
+ 0x30CF3099: 0x30D0,
+ 0x30CF309A: 0x30D1,
+ 0x30D23099: 0x30D3,
+ 0x30D2309A: 0x30D4,
+ 0x30D53099: 0x30D6,
+ 0x30D5309A: 0x30D7,
+ 0x30D83099: 0x30D9,
+ 0x30D8309A: 0x30DA,
+ 0x30DB3099: 0x30DC,
+ 0x30DB309A: 0x30DD,
+ 0x30A63099: 0x30F4,
+ 0x30EF3099: 0x30F7,
+ 0x30F03099: 0x30F8,
+ 0x30F13099: 0x30F9,
+ 0x30F23099: 0x30FA,
+ 0x30FD3099: 0x30FE,
+ 0x109910BA: 0x1109A,
+ 0x109B10BA: 0x1109C,
+ 0x10A510BA: 0x110AB,
+ 0x11311127: 0x1112E,
+ 0x11321127: 0x1112F,
+ 0x1347133E: 0x1134B,
+ 0x13471357: 0x1134C,
+ 0x14B914BA: 0x114BB,
+ 0x14B914B0: 0x114BC,
+ 0x14B914BD: 0x114BE,
+ 0x15B815AF: 0x115BA,
+ 0x15B915AF: 0x115BB,
+}
+
+// Total size of tables: 53KB (54006 bytes)
diff --git a/vendor/golang.org/x/text/unicode/norm/transform.go b/vendor/golang.org/x/text/unicode/norm/transform.go
new file mode 100644
index 0000000..8589067
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/norm/transform.go
@@ -0,0 +1,88 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package norm
+
+import (
+ "unicode/utf8"
+
+ "golang.org/x/text/transform"
+)
+
+// Reset implements the Reset method of the transform.Transformer interface.
+func (Form) Reset() {}
+
+// Transform implements the Transform method of the transform.Transformer
+// interface. It may need to write segments of up to MaxSegmentSize at once.
+// Users should either catch ErrShortDst and allow dst to grow or have dst be at
+// least of size MaxTransformChunkSize to be guaranteed of progress.
+func (f Form) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ n := 0
+ // Cap the maximum number of src bytes to check.
+ b := src
+ eof := atEOF
+ if ns := len(dst); ns < len(b) {
+ err = transform.ErrShortDst
+ eof = false
+ b = b[:ns]
+ }
+ i, ok := formTable[f].quickSpan(inputBytes(b), n, len(b), eof)
+ n += copy(dst[n:], b[n:i])
+ if !ok {
+ nDst, nSrc, err = f.transform(dst[n:], src[n:], atEOF)
+ return nDst + n, nSrc + n, err
+ }
+ if n < len(src) && !atEOF {
+ err = transform.ErrShortSrc
+ }
+ return n, n, err
+}
+
+func flushTransform(rb *reorderBuffer) bool {
+ // Write out (must fully fit in dst, or else it is a ErrShortDst).
+ if len(rb.out) < rb.nrune*utf8.UTFMax {
+ return false
+ }
+ rb.out = rb.out[rb.flushCopy(rb.out):]
+ return true
+}
+
+var errs = []error{nil, transform.ErrShortDst, transform.ErrShortSrc}
+
+// transform implements the transform.Transformer interface. It is only called
+// when quickSpan does not pass for a given string.
+func (f Form) transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ // TODO: get rid of reorderBuffer. See CL 23460044.
+ rb := reorderBuffer{}
+ rb.init(f, src)
+ for {
+ // Load segment into reorder buffer.
+ rb.setFlusher(dst[nDst:], flushTransform)
+ end := decomposeSegment(&rb, nSrc, atEOF)
+ if end < 0 {
+ return nDst, nSrc, errs[-end]
+ }
+ nDst = len(dst) - len(rb.out)
+ nSrc = end
+
+ // Next quickSpan.
+ end = rb.nsrc
+ eof := atEOF
+ if n := nSrc + len(dst) - nDst; n < end {
+ err = transform.ErrShortDst
+ end = n
+ eof = false
+ }
+ end, ok := rb.f.quickSpan(rb.src, nSrc, end, eof)
+ n := copy(dst[nDst:], rb.src.bytes[nSrc:end])
+ nSrc += n
+ nDst += n
+ if ok {
+ if n < rb.nsrc && !atEOF {
+ err = transform.ErrShortSrc
+ }
+ return nDst, nSrc, err
+ }
+ }
+}
diff --git a/vendor/golang.org/x/text/unicode/norm/trie.go b/vendor/golang.org/x/text/unicode/norm/trie.go
new file mode 100644
index 0000000..423386b
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/norm/trie.go
@@ -0,0 +1,54 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package norm
+
+type valueRange struct {
+ value uint16 // header: value:stride
+ lo, hi byte // header: lo:n
+}
+
+type sparseBlocks struct {
+ values []valueRange
+ offset []uint16
+}
+
+var nfcSparse = sparseBlocks{
+ values: nfcSparseValues[:],
+ offset: nfcSparseOffset[:],
+}
+
+var nfkcSparse = sparseBlocks{
+ values: nfkcSparseValues[:],
+ offset: nfkcSparseOffset[:],
+}
+
+var (
+ nfcData = newNfcTrie(0)
+ nfkcData = newNfkcTrie(0)
+)
+
+// lookupValue determines the type of block n and looks up the value for b.
+// For n < t.cutoff, the block is a simple lookup table. Otherwise, the block
+// is a list of ranges with an accompanying value. Given a matching range r,
+// the value for b is by r.value + (b - r.lo) * stride.
+func (t *sparseBlocks) lookup(n uint32, b byte) uint16 {
+ offset := t.offset[n]
+ header := t.values[offset]
+ lo := offset + 1
+ hi := lo + uint16(header.lo)
+ for lo < hi {
+ m := lo + (hi-lo)/2
+ r := t.values[m]
+ if r.lo <= b && b <= r.hi {
+ return r.value + uint16(b-r.lo)*header.value
+ }
+ if b < r.lo {
+ hi = m
+ } else {
+ lo = m + 1
+ }
+ }
+ return 0
+}
diff --git a/vendor/golang.org/x/text/unicode/norm/triegen.go b/vendor/golang.org/x/text/unicode/norm/triegen.go
new file mode 100644
index 0000000..45d7119
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/norm/triegen.go
@@ -0,0 +1,117 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// Trie table generator.
+// Used by make*tables tools to generate a go file with trie data structures
+// for mapping UTF-8 to a 16-bit value. All but the last byte in a UTF-8 byte
+// sequence are used to lookup offsets in the index table to be used for the
+// next byte. The last byte is used to index into a table with 16-bit values.
+
+package main
+
+import (
+ "fmt"
+ "io"
+)
+
+const maxSparseEntries = 16
+
+type normCompacter struct {
+ sparseBlocks [][]uint64
+ sparseOffset []uint16
+ sparseCount int
+ name string
+}
+
+func mostFrequentStride(a []uint64) int {
+ counts := make(map[int]int)
+ var v int
+ for _, x := range a {
+ if stride := int(x) - v; v != 0 && stride >= 0 {
+ counts[stride]++
+ }
+ v = int(x)
+ }
+ var maxs, maxc int
+ for stride, cnt := range counts {
+ if cnt > maxc || (cnt == maxc && stride < maxs) {
+ maxs, maxc = stride, cnt
+ }
+ }
+ return maxs
+}
+
+func countSparseEntries(a []uint64) int {
+ stride := mostFrequentStride(a)
+ var v, count int
+ for _, tv := range a {
+ if int(tv)-v != stride {
+ if tv != 0 {
+ count++
+ }
+ }
+ v = int(tv)
+ }
+ return count
+}
+
+func (c *normCompacter) Size(v []uint64) (sz int, ok bool) {
+ if n := countSparseEntries(v); n <= maxSparseEntries {
+ return (n+1)*4 + 2, true
+ }
+ return 0, false
+}
+
+func (c *normCompacter) Store(v []uint64) uint32 {
+ h := uint32(len(c.sparseOffset))
+ c.sparseBlocks = append(c.sparseBlocks, v)
+ c.sparseOffset = append(c.sparseOffset, uint16(c.sparseCount))
+ c.sparseCount += countSparseEntries(v) + 1
+ return h
+}
+
+func (c *normCompacter) Handler() string {
+ return c.name + "Sparse.lookup"
+}
+
+func (c *normCompacter) Print(w io.Writer) (retErr error) {
+ p := func(f string, x ...interface{}) {
+ if _, err := fmt.Fprintf(w, f, x...); retErr == nil && err != nil {
+ retErr = err
+ }
+ }
+
+ ls := len(c.sparseBlocks)
+ p("// %sSparseOffset: %d entries, %d bytes\n", c.name, ls, ls*2)
+ p("var %sSparseOffset = %#v\n\n", c.name, c.sparseOffset)
+
+ ns := c.sparseCount
+ p("// %sSparseValues: %d entries, %d bytes\n", c.name, ns, ns*4)
+ p("var %sSparseValues = [%d]valueRange {", c.name, ns)
+ for i, b := range c.sparseBlocks {
+ p("\n// Block %#x, offset %#x", i, c.sparseOffset[i])
+ var v int
+ stride := mostFrequentStride(b)
+ n := countSparseEntries(b)
+ p("\n{value:%#04x,lo:%#02x},", stride, uint8(n))
+ for i, nv := range b {
+ if int(nv)-v != stride {
+ if v != 0 {
+ p(",hi:%#02x},", 0x80+i-1)
+ }
+ if nv != 0 {
+ p("\n{value:%#04x,lo:%#02x", nv, 0x80+i)
+ }
+ }
+ v = int(nv)
+ }
+ if v != 0 {
+ p(",hi:%#02x},", 0x80+len(b)-1)
+ }
+ }
+ p("\n}\n\n")
+ return
+}
diff --git a/cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/AUTHORS b/vendor/gopkg.in/gorilla/websocket.v1/AUTHORS
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/AUTHORS
rename to vendor/gopkg.in/gorilla/websocket.v1/AUTHORS
diff --git a/cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/LICENSE b/vendor/gopkg.in/gorilla/websocket.v1/LICENSE
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/LICENSE
rename to vendor/gopkg.in/gorilla/websocket.v1/LICENSE
diff --git a/cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/README.md b/vendor/gopkg.in/gorilla/websocket.v1/README.md
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/README.md
rename to vendor/gopkg.in/gorilla/websocket.v1/README.md
diff --git a/cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/client.go b/vendor/gopkg.in/gorilla/websocket.v1/client.go
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/client.go
rename to vendor/gopkg.in/gorilla/websocket.v1/client.go
diff --git a/cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/compression.go b/vendor/gopkg.in/gorilla/websocket.v1/compression.go
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/compression.go
rename to vendor/gopkg.in/gorilla/websocket.v1/compression.go
diff --git a/cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/conn.go b/vendor/gopkg.in/gorilla/websocket.v1/conn.go
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/conn.go
rename to vendor/gopkg.in/gorilla/websocket.v1/conn.go
diff --git a/cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/conn_read.go b/vendor/gopkg.in/gorilla/websocket.v1/conn_read.go
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/conn_read.go
rename to vendor/gopkg.in/gorilla/websocket.v1/conn_read.go
diff --git a/cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/conn_read_legacy.go b/vendor/gopkg.in/gorilla/websocket.v1/conn_read_legacy.go
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/conn_read_legacy.go
rename to vendor/gopkg.in/gorilla/websocket.v1/conn_read_legacy.go
diff --git a/cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/doc.go b/vendor/gopkg.in/gorilla/websocket.v1/doc.go
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/doc.go
rename to vendor/gopkg.in/gorilla/websocket.v1/doc.go
diff --git a/cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/json.go b/vendor/gopkg.in/gorilla/websocket.v1/json.go
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/json.go
rename to vendor/gopkg.in/gorilla/websocket.v1/json.go
diff --git a/cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/mask.go b/vendor/gopkg.in/gorilla/websocket.v1/mask.go
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/mask.go
rename to vendor/gopkg.in/gorilla/websocket.v1/mask.go
diff --git a/cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/server.go b/vendor/gopkg.in/gorilla/websocket.v1/server.go
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/server.go
rename to vendor/gopkg.in/gorilla/websocket.v1/server.go
diff --git a/cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/util.go b/vendor/gopkg.in/gorilla/websocket.v1/util.go
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/gorilla/websocket.v1/util.go
rename to vendor/gopkg.in/gorilla/websocket.v1/util.go
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/LICENSE b/vendor/gopkg.in/xtaci/kcp-go.v2/LICENSE
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/LICENSE
rename to vendor/gopkg.in/xtaci/kcp-go.v2/LICENSE
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/README.md b/vendor/gopkg.in/xtaci/kcp-go.v2/README.md
similarity index 87%
rename from cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/README.md
rename to vendor/gopkg.in/xtaci/kcp-go.v2/README.md
index 3f34820..c8139b3 100644
--- a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/README.md
+++ b/vendor/gopkg.in/xtaci/kcp-go.v2/README.md
@@ -1,4 +1,5 @@
-# kcp-go
+
+
[![GoDoc][1]][2] [![Powered][9]][10] [![MIT licensed][11]][12] [![Build Status][3]][4] [![Go Report Card][5]][6] [![Coverage Statusd][7]][8]
@@ -19,12 +20,12 @@
## Introduction
-kcp-go is a full-featured ***reliable-UDP*** library for golang. It provides ***reliable, ordered, and error-checked*** delivery of a stream of octets between applications running on hosts communicating over an IP network.
+kcp-go is a full-featured ***Reliable-UDP*** library for golang. It provides ***reliable, ordered, and error-checked*** delivery of a stream of octets between applications running on hosts communicating over an IP network.
## Features
-1. Optimized for ***Real-Time Strategy Game***.
-1. Compatible with [skywind3000's](https://github.com/skywind3000) C version with modifications.
+1. Optimized for ***Online Games, Audio/Video Streaming***.
+1. Compatible with [skywind3000's](https://github.com/skywind3000) C version with optimizations.
1. ***Cache friendly*** and ***Memory optimized*** design in golang.
1. Compatible with [net.Conn](https://golang.org/pkg/net/#Conn) and [net.Listener](https://golang.org/pkg/net/#Listener).
1. [FEC(Forward Error Correction)](https://en.wikipedia.org/wiki/Forward_error_correction) Support with [Reed-Solomon Codes](https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction)
@@ -40,7 +41,7 @@ For complete documentation, see the associated [Godoc](https://godoc.org/github.
## Specification
-#
+
## Usage
@@ -75,14 +76,14 @@ PASS
ok github.com/xtaci/kcp-go 0.600s
```
+## Who is using this?
+
+1. https://github.com/xtaci/kcptun
+2. https://github.com/getlantern/lantern
+3. https://github.com/smallnest/rpcx
+
## Links
-1. https://github.com/xtaci/libkcp -- Official client library for iOS/Android(C++11)
+1. https://github.com/xtaci/libkcp -- FEC enhanced KCP session library for iOS/Android in C++
2. https://github.com/skywind3000/kcp -- A Fast and Reliable ARQ Protocol
3. https://github.com/klauspost/reedsolomon -- Reed-Solomon Erasure Coding in Go
-
-## Donation
-
-
-
-All donations on this project will be used to support the development of [gonet/2](http://gonet2.github.io/).
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/crypt.go b/vendor/gopkg.in/xtaci/kcp-go.v2/crypt.go
similarity index 56%
rename from cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/crypt.go
rename to vendor/gopkg.in/xtaci/kcp-go.v2/crypt.go
index df85278..2e456b8 100644
--- a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/crypt.go
+++ b/vendor/gopkg.in/xtaci/kcp-go.v2/crypt.go
@@ -20,7 +20,9 @@ var (
saltxor = `sH3CIVoF#rWLtJo6`
)
-// BlockCrypt defines encryption/decryption methods for a given byte slice
+// BlockCrypt defines encryption/decryption methods for a given byte slice.
+// Notes on implementing: the data to be encrypted contains a builtin
+// nonce at the first 16 bytes
type BlockCrypt interface {
// Encrypt encrypts the whole block in src into dst.
// Dst and src may point at the same memory.
@@ -31,40 +33,35 @@ type BlockCrypt interface {
Decrypt(dst, src []byte)
}
-// Salsa20BlockCrypt implements BlockCrypt
-type Salsa20BlockCrypt struct {
+type salsa20BlockCrypt struct {
key [32]byte
}
-// NewSalsa20BlockCrypt initates BlockCrypt by the given key
+// NewSalsa20BlockCrypt https://en.wikipedia.org/wiki/Salsa20
func NewSalsa20BlockCrypt(key []byte) (BlockCrypt, error) {
- c := new(Salsa20BlockCrypt)
+ c := new(salsa20BlockCrypt)
copy(c.key[:], key)
return c, nil
}
-// Encrypt implements Encrypt interface
-func (c *Salsa20BlockCrypt) Encrypt(dst, src []byte) {
+func (c *salsa20BlockCrypt) Encrypt(dst, src []byte) {
+ salsa20.XORKeyStream(dst[8:], src[8:], src[:8], &c.key)
+ copy(dst[:8], src[:8])
+}
+func (c *salsa20BlockCrypt) Decrypt(dst, src []byte) {
salsa20.XORKeyStream(dst[8:], src[8:], src[:8], &c.key)
copy(dst[:8], src[:8])
}
-// Decrypt implements Decrypt interface
-func (c *Salsa20BlockCrypt) Decrypt(dst, src []byte) {
- salsa20.XORKeyStream(dst[8:], src[8:], src[:8], &c.key)
- copy(dst[:8], src[:8])
-}
-
-// TwofishBlockCrypt implements BlockCrypt
-type TwofishBlockCrypt struct {
+type twofishBlockCrypt struct {
encbuf []byte
decbuf []byte
block cipher.Block
}
-// NewTwofishBlockCrypt initates BlockCrypt by the given key
+// NewTwofishBlockCrypt https://en.wikipedia.org/wiki/Twofish
func NewTwofishBlockCrypt(key []byte) (BlockCrypt, error) {
- c := new(TwofishBlockCrypt)
+ c := new(twofishBlockCrypt)
block, err := twofish.NewCipher(key)
if err != nil {
return nil, err
@@ -75,22 +72,18 @@ func NewTwofishBlockCrypt(key []byte) (BlockCrypt, error) {
return c, nil
}
-// Encrypt implements Encrypt interface
-func (c *TwofishBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
+func (c *twofishBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
+func (c *twofishBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-// Decrypt implements Decrypt interface
-func (c *TwofishBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-
-// TripleDESBlockCrypt implements BlockCrypt
-type TripleDESBlockCrypt struct {
+type tripleDESBlockCrypt struct {
encbuf []byte
decbuf []byte
block cipher.Block
}
-// NewTripleDESBlockCrypt initates BlockCrypt by the given key
+// NewTripleDESBlockCrypt https://en.wikipedia.org/wiki/Triple_DES
func NewTripleDESBlockCrypt(key []byte) (BlockCrypt, error) {
- c := new(TripleDESBlockCrypt)
+ c := new(tripleDESBlockCrypt)
block, err := des.NewTripleDESCipher(key)
if err != nil {
return nil, err
@@ -101,22 +94,18 @@ func NewTripleDESBlockCrypt(key []byte) (BlockCrypt, error) {
return c, nil
}
-// Encrypt implements Encrypt interface
-func (c *TripleDESBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
+func (c *tripleDESBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
+func (c *tripleDESBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-// Decrypt implements Decrypt interface
-func (c *TripleDESBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-
-// Cast5BlockCrypt implements BlockCrypt
-type Cast5BlockCrypt struct {
+type cast5BlockCrypt struct {
encbuf []byte
decbuf []byte
block cipher.Block
}
-// NewCast5BlockCrypt initates BlockCrypt by the given key
+// NewCast5BlockCrypt https://en.wikipedia.org/wiki/CAST-128
func NewCast5BlockCrypt(key []byte) (BlockCrypt, error) {
- c := new(Cast5BlockCrypt)
+ c := new(cast5BlockCrypt)
block, err := cast5.NewCipher(key)
if err != nil {
return nil, err
@@ -127,22 +116,18 @@ func NewCast5BlockCrypt(key []byte) (BlockCrypt, error) {
return c, nil
}
-// Encrypt implements Encrypt interface
-func (c *Cast5BlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
+func (c *cast5BlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
+func (c *cast5BlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-// Decrypt implements Decrypt interface
-func (c *Cast5BlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-
-// BlowfishBlockCrypt implements BlockCrypt
-type BlowfishBlockCrypt struct {
+type blowfishBlockCrypt struct {
encbuf []byte
decbuf []byte
block cipher.Block
}
-// NewBlowfishBlockCrypt initates BlockCrypt by the given key
+// NewBlowfishBlockCrypt https://en.wikipedia.org/wiki/Blowfish_(cipher)
func NewBlowfishBlockCrypt(key []byte) (BlockCrypt, error) {
- c := new(BlowfishBlockCrypt)
+ c := new(blowfishBlockCrypt)
block, err := blowfish.NewCipher(key)
if err != nil {
return nil, err
@@ -153,22 +138,18 @@ func NewBlowfishBlockCrypt(key []byte) (BlockCrypt, error) {
return c, nil
}
-// Encrypt implements Encrypt interface
-func (c *BlowfishBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
+func (c *blowfishBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
+func (c *blowfishBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-// Decrypt implements Decrypt interface
-func (c *BlowfishBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-
-// AESBlockCrypt implements BlockCrypt
-type AESBlockCrypt struct {
+type aesBlockCrypt struct {
encbuf []byte
decbuf []byte
block cipher.Block
}
-// NewAESBlockCrypt initates BlockCrypt by the given key
+// NewAESBlockCrypt https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
func NewAESBlockCrypt(key []byte) (BlockCrypt, error) {
- c := new(AESBlockCrypt)
+ c := new(aesBlockCrypt)
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
@@ -179,22 +160,18 @@ func NewAESBlockCrypt(key []byte) (BlockCrypt, error) {
return c, nil
}
-// Encrypt implements Encrypt interface
-func (c *AESBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
+func (c *aesBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
+func (c *aesBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-// Decrypt implements Decrypt interface
-func (c *AESBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-
-// TEABlockCrypt implements BlockCrypt
-type TEABlockCrypt struct {
+type teaBlockCrypt struct {
encbuf []byte
decbuf []byte
block cipher.Block
}
-// NewTEABlockCrypt initate BlockCrypt by the given key
+// NewTEABlockCrypt https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
func NewTEABlockCrypt(key []byte) (BlockCrypt, error) {
- c := new(TEABlockCrypt)
+ c := new(teaBlockCrypt)
block, err := tea.NewCipherWithRounds(key, 16)
if err != nil {
return nil, err
@@ -205,22 +182,18 @@ func NewTEABlockCrypt(key []byte) (BlockCrypt, error) {
return c, nil
}
-// Encrypt implements Encrypt interface
-func (c *TEABlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
+func (c *teaBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
+func (c *teaBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-// Decrypt implements Decrypt interface
-func (c *TEABlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-
-// XTEABlockCrypt implements BlockCrypt
-type XTEABlockCrypt struct {
+type xteaBlockCrypt struct {
encbuf []byte
decbuf []byte
block cipher.Block
}
-// NewXTEABlockCrypt initate BlockCrypt by the given key
+// NewXTEABlockCrypt https://en.wikipedia.org/wiki/XTEA
func NewXTEABlockCrypt(key []byte) (BlockCrypt, error) {
- c := new(XTEABlockCrypt)
+ c := new(xteaBlockCrypt)
block, err := xtea.NewCipher(key)
if err != nil {
return nil, err
@@ -231,43 +204,32 @@ func NewXTEABlockCrypt(key []byte) (BlockCrypt, error) {
return c, nil
}
-// Encrypt implements Encrypt interface
-func (c *XTEABlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
+func (c *xteaBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf) }
+func (c *xteaBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-// Decrypt implements Decrypt interface
-func (c *XTEABlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf) }
-
-// SimpleXORBlockCrypt implements BlockCrypt
-type SimpleXORBlockCrypt struct {
+type simpleXORBlockCrypt struct {
xortbl []byte
}
-// NewSimpleXORBlockCrypt initate BlockCrypt by the given key
+// NewSimpleXORBlockCrypt simple xor with key expanding
func NewSimpleXORBlockCrypt(key []byte) (BlockCrypt, error) {
- c := new(SimpleXORBlockCrypt)
+ c := new(simpleXORBlockCrypt)
c.xortbl = pbkdf2.Key(key, []byte(saltxor), 32, mtuLimit, sha1.New)
return c, nil
}
-// Encrypt implements Encrypt interface
-func (c *SimpleXORBlockCrypt) Encrypt(dst, src []byte) { xorBytes(dst, src, c.xortbl) }
+func (c *simpleXORBlockCrypt) Encrypt(dst, src []byte) { xorBytes(dst, src, c.xortbl) }
+func (c *simpleXORBlockCrypt) Decrypt(dst, src []byte) { xorBytes(dst, src, c.xortbl) }
-// Decrypt implements Decrypt interface
-func (c *SimpleXORBlockCrypt) Decrypt(dst, src []byte) { xorBytes(dst, src, c.xortbl) }
+type noneBlockCrypt struct{}
-// NoneBlockCrypt simple returns the plaintext
-type NoneBlockCrypt struct{}
-
-// NewNoneBlockCrypt initate by the given key
+// NewNoneBlockCrypt does nothing but copying
func NewNoneBlockCrypt(key []byte) (BlockCrypt, error) {
- return new(NoneBlockCrypt), nil
+ return new(noneBlockCrypt), nil
}
-// Encrypt implements Encrypt interface
-func (c *NoneBlockCrypt) Encrypt(dst, src []byte) { copy(dst, src) }
-
-// Decrypt implements Decrypt interface
-func (c *NoneBlockCrypt) Decrypt(dst, src []byte) { copy(dst, src) }
+func (c *noneBlockCrypt) Encrypt(dst, src []byte) { copy(dst, src) }
+func (c *noneBlockCrypt) Decrypt(dst, src []byte) { copy(dst, src) }
// packet encryption with local CFB mode
func encrypt(block cipher.Block, dst, src, buf []byte) {
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/donate.png b/vendor/gopkg.in/xtaci/kcp-go.v2/donate.png
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/donate.png
rename to vendor/gopkg.in/xtaci/kcp-go.v2/donate.png
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/fec.go b/vendor/gopkg.in/xtaci/kcp-go.v2/fec.go
similarity index 90%
rename from cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/fec.go
rename to vendor/gopkg.in/xtaci/kcp-go.v2/fec.go
index 10ad1c0..25201bb 100644
--- a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/fec.go
+++ b/vendor/gopkg.in/xtaci/kcp-go.v2/fec.go
@@ -2,7 +2,7 @@ package kcp
import (
"encoding/binary"
- "sync"
+ "sync/atomic"
"github.com/klauspost/reedsolomon"
)
@@ -26,10 +26,10 @@ type (
next uint32 // next seqid
enc reedsolomon.Encoder
shards [][]byte
+ shards2 [][]byte // for calcECC
shardsflag []bool
paws uint32 // Protect Against Wrapped Sequence numbers
lastCheck uint32
- xmitBuf sync.Pool
}
fecPacket struct {
@@ -60,11 +60,8 @@ func newFEC(rxlimit, dataShards, parityShards int) *FEC {
}
fec.enc = enc
fec.shards = make([][]byte, fec.shardSize)
+ fec.shards2 = make([][]byte, fec.shardSize)
fec.shardsflag = make([]bool, fec.shardSize)
- fec.xmitBuf.New = func() interface{} {
- return make([]byte, mtuLimit)
- }
-
return fec
}
@@ -75,9 +72,8 @@ func (fec *FEC) decode(data []byte) fecPacket {
pkt.flag = binary.LittleEndian.Uint16(data[4:])
pkt.ts = currentMs()
// allocate memory & copy
- buf := fec.xmitBuf.Get().([]byte)
- n := copy(buf, data[6:])
- xorBytes(buf[n:], buf[n:], buf[n:])
+ buf := xmitBuf.Get().([]byte)[:len(data)-6]
+ copy(buf, data[6:])
pkt.data = buf
return pkt
}
@@ -107,7 +103,7 @@ func (fec *FEC) input(pkt fecPacket) (recovered [][]byte) {
if now-fec.rx[k].ts < fecExpire {
rx = append(rx, fec.rx[k])
} else {
- fec.xmitBuf.Put(fec.rx[k].data)
+ xmitBuf.Put(fec.rx[k].data)
}
}
fec.rx = rx
@@ -119,7 +115,7 @@ func (fec *FEC) input(pkt fecPacket) (recovered [][]byte) {
insertIdx := 0
for i := n; i >= 0; i-- {
if pkt.seqid == fec.rx[i].seqid { // de-duplicate
- fec.xmitBuf.Put(pkt.data)
+ xmitBuf.Put(pkt.data)
return nil
} else if pkt.seqid > fec.rx[i].seqid { // insertion
insertIdx = i + 1
@@ -184,7 +180,7 @@ func (fec *FEC) input(pkt fecPacket) (recovered [][]byte) {
if numDataShard == fec.dataShards { // no lost
for i := first; i < first+numshard; i++ { // free
- fec.xmitBuf.Put(fec.rx[i].data)
+ xmitBuf.Put(fec.rx[i].data)
}
copy(fec.rx[first:], fec.rx[first+numshard:])
for i := 0; i < numshard; i++ { // dereference
@@ -194,7 +190,9 @@ func (fec *FEC) input(pkt fecPacket) (recovered [][]byte) {
} else if numshard >= fec.dataShards { // recoverable
for k := range shards {
if shards[k] != nil {
+ dlen := len(shards[k])
shards[k] = shards[k][:maxlen]
+ xorBytes(shards[k][dlen:], shards[k][dlen:], shards[k][dlen:])
}
}
if err := fec.enc.Reconstruct(shards); err == nil {
@@ -206,7 +204,7 @@ func (fec *FEC) input(pkt fecPacket) (recovered [][]byte) {
}
for i := first; i < first+numshard; i++ { // free
- fec.xmitBuf.Put(fec.rx[i].data)
+ xmitBuf.Put(fec.rx[i].data)
}
copy(fec.rx[first:], fec.rx[first+numshard:])
for i := 0; i < numshard; i++ { // dereference
@@ -218,7 +216,10 @@ func (fec *FEC) input(pkt fecPacket) (recovered [][]byte) {
// keep rxlimit
if len(fec.rx) > fec.rxlimit {
- fec.xmitBuf.Put(fec.rx[0].data) // free
+ if fec.rx[0].flag == typeData { // record unrecoverable data
+ atomic.AddUint64(&DefaultSnmp.FECShortShards, 1)
+ }
+ xmitBuf.Put(fec.rx[0].data) // free
fec.rx[0].data = nil
fec.rx = fec.rx[1:]
}
@@ -229,7 +230,7 @@ func (fec *FEC) calcECC(data [][]byte, offset, maxlen int) (ecc [][]byte) {
if len(data) != fec.shardSize {
return nil
}
- shards := make([][]byte, fec.shardSize)
+ shards := fec.shards2
for k := range shards {
shards[k] = data[k][offset:maxlen]
}
diff --git a/vendor/gopkg.in/xtaci/kcp-go.v2/frame.png b/vendor/gopkg.in/xtaci/kcp-go.v2/frame.png
new file mode 100644
index 0000000..0b0aefd
Binary files /dev/null and b/vendor/gopkg.in/xtaci/kcp-go.v2/frame.png differ
diff --git a/vendor/gopkg.in/xtaci/kcp-go.v2/kcp-go.png b/vendor/gopkg.in/xtaci/kcp-go.v2/kcp-go.png
new file mode 100644
index 0000000..151b7c4
Binary files /dev/null and b/vendor/gopkg.in/xtaci/kcp-go.v2/kcp-go.png differ
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/kcp.go b/vendor/gopkg.in/xtaci/kcp-go.v2/kcp.go
similarity index 87%
rename from cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/kcp.go
rename to vendor/gopkg.in/xtaci/kcp-go.v2/kcp.go
index 78ccf26..f53e834 100644
--- a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/kcp.go
+++ b/vendor/gopkg.in/xtaci/kcp-go.v2/kcp.go
@@ -2,7 +2,6 @@
package kcp
import (
- "container/heap"
"encoding/binary"
"sync/atomic"
)
@@ -123,13 +122,6 @@ func (seg *Segment) encode(ptr []byte) []byte {
return ptr
}
-// NewSegment creates a KCP segment
-func NewSegment(size int) *Segment {
- seg := new(Segment)
- seg.data = make([]byte, size)
- return seg
-}
-
// KCP defines a single KCP connection
type KCP struct {
conv, mtu, mss, state uint32
@@ -137,7 +129,7 @@ type KCP struct {
ssthresh uint32
rx_rttval, rx_srtt, rx_rto, rx_minrto uint32
snd_wnd, rcv_wnd, rmt_wnd, cwnd, probe uint32
- current, interval, ts_flush, xmit uint32
+ interval, ts_flush, xmit uint32
nodelay, updated uint32
ts_probe, probe_wait uint32
dead_link, incr uint32
@@ -150,33 +142,17 @@ type KCP struct {
snd_buf []Segment
rcv_buf []Segment
- acklist ACKList
+ acklist []ackItem
buffer []byte
output Output
}
-// ACK packet to return
-type ACK struct {
+type ackItem struct {
sn uint32
ts uint32
}
-// ACKList is heapified
-type ACKList []ACK
-
-func (l ACKList) Len() int { return len(l) }
-func (l ACKList) Less(i, j int) bool { return l[i].sn < l[j].sn }
-func (l ACKList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
-func (l *ACKList) Push(x interface{}) { *l = append(*l, x.(ACK)) }
-func (l *ACKList) Pop() interface{} {
- old := *l
- n := len(old)
- x := old[n-1]
- *l = old[0 : n-1]
- return x
-}
-
// NewKCP create a new kcp control object, 'conv' must equal in two endpoint
// from the same connection.
func NewKCP(conv uint32, output Output) *KCP {
@@ -198,6 +174,18 @@ func NewKCP(conv uint32, output Output) *KCP {
return kcp
}
+// newSegment creates a KCP segment
+func (kcp *KCP) newSegment(size int) *Segment {
+ seg := new(Segment)
+ seg.data = xmitBuf.Get().([]byte)[:size]
+ return seg
+}
+
+// delSegment recycles a KCP segment
+func (kcp *KCP) delSegment(seg *Segment) {
+ xmitBuf.Put(seg.data)
+}
+
// PeekSize checks the size of next message in the recv queue
func (kcp *KCP) PeekSize() (length int) {
if len(kcp.rcv_queue) == 0 {
@@ -251,7 +239,7 @@ func (kcp *KCP) Recv(buffer []byte) (n int) {
buffer = buffer[len(seg.data):]
n += len(seg.data)
count++
- seg.data = nil
+ kcp.delSegment(seg)
if seg.frg == 0 {
break
}
@@ -263,14 +251,13 @@ func (kcp *KCP) Recv(buffer []byte) (n int) {
for k := range kcp.rcv_buf {
seg := &kcp.rcv_buf[k]
if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue) < int(kcp.rcv_wnd) {
- kcp.rcv_queue = append(kcp.rcv_queue, *seg)
kcp.rcv_nxt++
count++
- seg.data = nil
} else {
break
}
}
+ kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcv_buf[:count]...)
kcp.rcv_buf = kcp.rcv_buf[count:]
// fast recover
@@ -300,11 +287,12 @@ func (kcp *KCP) Send(buffer []byte) int {
if len(buffer) < capacity {
extend = len(buffer)
}
- seg := NewSegment(len(old.data) + extend)
+ seg := kcp.newSegment(len(old.data) + extend)
seg.frg = 0
copy(seg.data, old.data)
copy(seg.data[len(old.data):], buffer)
buffer = buffer[extend:]
+ kcp.delSegment(old)
kcp.snd_queue[n-1] = *seg
}
}
@@ -335,7 +323,7 @@ func (kcp *KCP) Send(buffer []byte) int {
} else {
size = len(buffer)
}
- seg := NewSegment(size)
+ seg := kcp.newSegment(size)
copy(seg.data, buffer[:size])
if kcp.stream == 0 { // message mode
seg.frg = uint32(count - i - 1)
@@ -348,8 +336,8 @@ func (kcp *KCP) Send(buffer []byte) int {
return 0
}
-// https://tools.ietf.org/html/rfc6298
func (kcp *KCP) update_ack(rtt int32) {
+ // https://tools.ietf.org/html/rfc6298
var rto uint32
if kcp.rx_srtt == 0 {
kcp.rx_srtt = uint32(rtt)
@@ -365,7 +353,7 @@ func (kcp *KCP) update_ack(rtt int32) {
kcp.rx_srtt = 1
}
}
- rto = kcp.rx_srtt + _imax_(1, 4*kcp.rx_rttval)
+ rto = kcp.rx_srtt + _imax_(kcp.interval, 4*kcp.rx_rttval)
kcp.rx_rto = _ibound_(kcp.rx_minrto, rto, IKCP_RTO_MAX)
}
@@ -386,6 +374,7 @@ func (kcp *KCP) parse_ack(sn uint32) {
for k := range kcp.snd_buf {
seg := &kcp.snd_buf[k]
if sn == seg.sn {
+ kcp.delSegment(seg)
copy(kcp.snd_buf[k:], kcp.snd_buf[k+1:])
kcp.snd_buf[len(kcp.snd_buf)-1] = Segment{}
kcp.snd_buf = kcp.snd_buf[:len(kcp.snd_buf)-1]
@@ -417,8 +406,8 @@ func (kcp *KCP) parse_una(una uint32) {
for k := range kcp.snd_buf {
seg := &kcp.snd_buf[k]
if _itimediff(una, seg.sn) > 0 {
+ kcp.delSegment(seg)
count++
- seg.data = nil
} else {
break
}
@@ -428,14 +417,14 @@ func (kcp *KCP) parse_una(una uint32) {
// ack append
func (kcp *KCP) ack_push(sn, ts uint32) {
- heap.Push(&kcp.acklist, ACK{sn, ts})
+ kcp.acklist = append(kcp.acklist, ackItem{sn, ts})
}
func (kcp *KCP) parse_data(newseg *Segment) {
sn := newseg.sn
if _itimediff(sn, kcp.rcv_nxt+kcp.rcv_wnd) >= 0 ||
_itimediff(sn, kcp.rcv_nxt) < 0 {
- atomic.AddUint64(&DefaultSnmp.RepeatSegs, 1)
+ kcp.delSegment(newseg)
return
}
@@ -463,6 +452,8 @@ func (kcp *KCP) parse_data(newseg *Segment) {
copy(kcp.rcv_buf[insert_idx+1:], kcp.rcv_buf[insert_idx:])
kcp.rcv_buf[insert_idx] = *newseg
}
+ } else {
+ kcp.delSegment(newseg)
}
// move available data from rcv_buf -> rcv_queue
@@ -470,14 +461,13 @@ func (kcp *KCP) parse_data(newseg *Segment) {
for k := range kcp.rcv_buf {
seg := &kcp.rcv_buf[k]
if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue) < int(kcp.rcv_wnd) {
- kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcv_buf[k])
kcp.rcv_nxt++
count++
- seg.data = nil
} else {
break
}
}
+ kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcv_buf[:count]...)
kcp.rcv_buf = kcp.rcv_buf[count:]
}
@@ -489,7 +479,9 @@ func (kcp *KCP) Input(data []byte, update_ack bool) int {
}
var maxack uint32
+ var recentack uint32
var flag int
+
for {
var ts, sn, length, una, conv uint32
var wnd uint16
@@ -525,9 +517,6 @@ func (kcp *KCP) Input(data []byte, update_ack bool) int {
kcp.shrink_buf()
if cmd == IKCP_CMD_ACK {
- if update_ack && _itimediff(kcp.current, ts) >= 0 {
- kcp.update_ack(_itimediff(kcp.current, ts))
- }
kcp.parse_ack(sn)
kcp.shrink_buf()
if flag == 0 {
@@ -536,11 +525,12 @@ func (kcp *KCP) Input(data []byte, update_ack bool) int {
} else if _itimediff(sn, maxack) > 0 {
maxack = sn
}
+ recentack = ts
} else if cmd == IKCP_CMD_PUSH {
if _itimediff(sn, kcp.rcv_nxt+kcp.rcv_wnd) < 0 {
kcp.ack_push(sn, ts)
if _itimediff(sn, kcp.rcv_nxt) >= 0 {
- seg := NewSegment(int(length))
+ seg := kcp.newSegment(int(length))
seg.conv = conv
seg.cmd = uint32(cmd)
seg.frg = uint32(frg)
@@ -550,7 +540,11 @@ func (kcp *KCP) Input(data []byte, update_ack bool) int {
seg.una = una
copy(seg.data, data[:length])
kcp.parse_data(seg)
+ } else {
+ atomic.AddUint64(&DefaultSnmp.RepeatSegs, 1)
}
+ } else {
+ atomic.AddUint64(&DefaultSnmp.RepeatSegs, 1)
}
} else if cmd == IKCP_CMD_WASK {
// ready to send back IKCP_CMD_WINS in Ikcp_flush
@@ -565,8 +559,12 @@ func (kcp *KCP) Input(data []byte, update_ack bool) int {
data = data[length:]
}
+ current := currentMs()
if flag != 0 && update_ack {
kcp.parse_fastack(maxack)
+ if _itimediff(current, recentack) >= 0 {
+ kcp.update_ack(_itimediff(current, recentack))
+ }
}
if _itimediff(kcp.snd_una, una) > 0 {
@@ -603,14 +601,10 @@ func (kcp *KCP) wnd_unused() int32 {
// flush pending data
func (kcp *KCP) flush() {
- current := kcp.current
buffer := kcp.buffer
change := 0
lost := false
- if kcp.updated == 0 {
- return
- }
var seg Segment
seg.conv = kcp.conv
seg.cmd = IKCP_CMD_ACK
@@ -619,25 +613,28 @@ func (kcp *KCP) flush() {
// flush acknowledges
ptr := buffer
- for kcp.acklist.Len() > 0 {
+ for i, ack := range kcp.acklist {
size := len(buffer) - len(ptr)
if size+IKCP_OVERHEAD > int(kcp.mtu) {
kcp.output(buffer, size)
ptr = buffer
}
- ack := heap.Pop(&kcp.acklist).(ACK)
- seg.sn, seg.ts = ack.sn, ack.ts
- ptr = seg.encode(ptr)
+ // filter jitters caused by bufferbloat
+ if ack.sn >= kcp.rcv_nxt || len(kcp.acklist)-1 == i {
+ seg.sn, seg.ts = ack.sn, ack.ts
+ ptr = seg.encode(ptr)
+ }
}
kcp.acklist = nil
+ current := currentMs()
// probe window size (if remote window size equals zero)
if kcp.rmt_wnd == 0 {
if kcp.probe_wait == 0 {
kcp.probe_wait = IKCP_PROBE_INIT
- kcp.ts_probe = kcp.current + kcp.probe_wait
+ kcp.ts_probe = current + kcp.probe_wait
} else {
- if _itimediff(kcp.current, kcp.ts_probe) >= 0 {
+ if _itimediff(current, kcp.ts_probe) >= 0 {
if kcp.probe_wait < IKCP_PROBE_INIT {
kcp.probe_wait = IKCP_PROBE_INIT
}
@@ -645,7 +642,7 @@ func (kcp *KCP) flush() {
if kcp.probe_wait > IKCP_PROBE_LIMIT {
kcp.probe_wait = IKCP_PROBE_LIMIT
}
- kcp.ts_probe = kcp.current + kcp.probe_wait
+ kcp.ts_probe = current + kcp.probe_wait
kcp.probe |= IKCP_ASK_SEND
}
}
@@ -684,6 +681,7 @@ func (kcp *KCP) flush() {
cwnd = _imin_(kcp.cwnd, cwnd)
}
+ // sliding window, controlled by snd_nxt && sna_una+cwnd
count := 0
for k := range kcp.snd_queue {
if _itimediff(kcp.snd_nxt, kcp.snd_una+cwnd) >= 0 {
@@ -696,10 +694,8 @@ func (kcp *KCP) flush() {
newseg.ts = current
newseg.sn = kcp.snd_nxt
newseg.una = kcp.rcv_nxt
- newseg.resendts = current
+ newseg.resendts = newseg.ts
newseg.rto = kcp.rx_rto
- newseg.fastack = 0
- newseg.xmit = 0
kcp.snd_buf = append(kcp.snd_buf, newseg)
kcp.snd_nxt++
count++
@@ -707,27 +703,29 @@ func (kcp *KCP) flush() {
}
kcp.snd_queue = kcp.snd_queue[count:]
+ // flag pending data
+ hasPending := false
+ if count > 0 {
+ hasPending = true
+ }
+
// calculate resent
resent := uint32(kcp.fastresend)
if kcp.fastresend <= 0 {
resent = 0xffffffff
}
- rtomin := (kcp.rx_rto >> 3)
- if kcp.nodelay != 0 {
- rtomin = 0
- }
// flush data segments
- nque := len(kcp.snd_queue)
var lostSegs, fastRetransSegs, earlyRetransSegs uint64
for k := range kcp.snd_buf {
+ current := currentMs()
segment := &kcp.snd_buf[k]
needsend := false
if segment.xmit == 0 {
needsend = true
segment.xmit++
segment.rto = kcp.rx_rto
- segment.resendts = current + segment.rto + rtomin
+ segment.resendts = current + segment.rto
} else if _itimediff(current, segment.resendts) >= 0 {
needsend = true
segment.xmit++
@@ -740,21 +738,26 @@ func (kcp *KCP) flush() {
segment.resendts = current + segment.rto
lost = true
lostSegs++
- } else if segment.fastack >= resent {
- needsend = true
- segment.xmit++
- segment.fastack = 0
- segment.resendts = current + segment.rto
- change++
- fastRetransSegs++
- } else if segment.fastack > 0 && nque == 0 {
- // early retransmit
- needsend = true
- segment.xmit++
- segment.fastack = 0
- segment.resendts = current + segment.rto
- change++
- earlyRetransSegs++
+ } else if segment.fastack >= resent { // fast retransmit
+ lastsend := segment.resendts - segment.rto
+ if _itimediff(current, lastsend) >= int32(kcp.rx_rto/4) {
+ needsend = true
+ segment.xmit++
+ segment.fastack = 0
+ segment.resendts = current + segment.rto
+ change++
+ fastRetransSegs++
+ }
+ } else if segment.fastack > 0 && !hasPending { // early retransmit
+ lastsend := segment.resendts - segment.rto
+ if _itimediff(current, lastsend) >= int32(kcp.rx_rto/4) {
+ needsend = true
+ segment.xmit++
+ segment.fastack = 0
+ segment.resendts = current + segment.rto
+ change++
+ earlyRetransSegs++
+ }
}
if needsend {
@@ -822,27 +825,26 @@ func (kcp *KCP) flush() {
// Update updates state (call it repeatedly, every 10ms-100ms), or you can ask
// ikcp_check when to call it again (without ikcp_input/_send calling).
// 'current' - current timestamp in millisec.
-func (kcp *KCP) Update(current uint32) {
+func (kcp *KCP) Update() {
var slap int32
- kcp.current = current
-
+ current := currentMs()
if kcp.updated == 0 {
kcp.updated = 1
- kcp.ts_flush = kcp.current
+ kcp.ts_flush = current
}
- slap = _itimediff(kcp.current, kcp.ts_flush)
+ slap = _itimediff(current, kcp.ts_flush)
if slap >= 10000 || slap < -10000 {
- kcp.ts_flush = kcp.current
+ kcp.ts_flush = current
slap = 0
}
if slap >= 0 {
kcp.ts_flush += kcp.interval
- if _itimediff(kcp.current, kcp.ts_flush) >= 0 {
- kcp.ts_flush = kcp.current + kcp.interval
+ if _itimediff(current, kcp.ts_flush) >= 0 {
+ kcp.ts_flush = current + kcp.interval
}
kcp.flush()
}
@@ -855,7 +857,8 @@ func (kcp *KCP) Update(current uint32) {
// Important to reduce unnacessary ikcp_update invoking. use it to
// schedule ikcp_update (eg. implementing an epoll-like mechanism,
// or optimize ikcp_update when handling massive kcp connections)
-func (kcp *KCP) Check(current uint32) uint32 {
+func (kcp *KCP) Check() uint32 {
+ current := currentMs()
ts_flush := kcp.ts_flush
tm_flush := int32(0x7fffffff)
tm_packet := int32(0x7fffffff)
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/sess.go b/vendor/gopkg.in/xtaci/kcp-go.v2/sess.go
similarity index 74%
rename from cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/sess.go
rename to vendor/gopkg.in/xtaci/kcp-go.v2/sess.go
index 737b99d..4879e2a 100644
--- a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/sess.go
+++ b/vendor/gopkg.in/xtaci/kcp-go.v2/sess.go
@@ -3,6 +3,7 @@ package kcp
import (
"crypto/rand"
"encoding/binary"
+ "hash/crc32"
"io"
"net"
"sync"
@@ -10,20 +11,9 @@ import (
"time"
"github.com/pkg/errors"
-
- "github.com/klauspost/crc32"
-
"golang.org/x/net/ipv4"
)
-// Option defines extra options
-type Option interface{}
-
-// OptionWithConvId defines conversation id
-type OptionWithConvId struct {
- Id uint32
-}
-
type errTimeout struct {
error
}
@@ -38,11 +28,26 @@ const (
crcSize = 4 // 4bytes packet checksum
cryptHeaderSize = nonceSize + crcSize
mtuLimit = 2048
- txQueueLimit = 8192
- rxFecLimit = 8192
- defaultKeepAliveInterval = 10 * time.Second
+ rxQueueLimit = 8192
+ rxFECMulti = 3 // FEC keeps rxFECMulti* (dataShard+parityShard) ordered packets in memory
+ defaultKeepAliveInterval = 10
)
+const (
+ errBrokenPipe = "broken pipe"
+ errInvalidOperation = "invalid operation"
+)
+
+var (
+ xmitBuf sync.Pool
+)
+
+func init() {
+ xmitBuf.New = func() interface{} {
+ return make([]byte, mtuLimit)
+ }
+}
+
type (
// UDPSession defines a KCP session implemented by UDP
UDPSession struct {
@@ -58,14 +63,13 @@ type (
die chan struct{}
chReadEvent chan struct{}
chWriteEvent chan struct{}
- chTicker chan time.Time
chUDPOutput chan []byte
headerSize int
ackNoDelay bool
isClosed bool
- keepAliveInterval time.Duration
- xmitBuf sync.Pool
+ keepAliveInterval int32
mu sync.Mutex
+ updateInterval int32
}
setReadBuffer interface {
@@ -80,8 +84,7 @@ type (
// newUDPSession create a new udp session for client or server
func newUDPSession(conv uint32, dataShards, parityShards int, l *Listener, conn net.PacketConn, remote net.Addr, block BlockCrypt) *UDPSession {
sess := new(UDPSession)
- sess.chTicker = make(chan time.Time, 1)
- sess.chUDPOutput = make(chan []byte, txQueueLimit)
+ sess.chUDPOutput = make(chan []byte)
sess.die = make(chan struct{})
sess.chReadEvent = make(chan struct{}, 1)
sess.chWriteEvent = make(chan struct{}, 1)
@@ -90,10 +93,7 @@ func newUDPSession(conv uint32, dataShards, parityShards int, l *Listener, conn
sess.keepAliveInterval = defaultKeepAliveInterval
sess.l = l
sess.block = block
- sess.fec = newFEC(rxFecLimit, dataShards, parityShards)
- sess.xmitBuf.New = func() interface{} {
- return make([]byte, mtuLimit)
- }
+ sess.fec = newFEC(rxFECMulti*(dataShards+parityShards), dataShards, parityShards)
// calculate header size
if sess.block != nil {
sess.headerSize += cryptHeaderSize
@@ -104,7 +104,7 @@ func newUDPSession(conv uint32, dataShards, parityShards int, l *Listener, conn
sess.kcp = NewKCP(conv, func(buf []byte, size int) {
if size >= IKCP_OVERHEAD {
- ext := sess.xmitBuf.Get().([]byte)[:sess.headerSize+size]
+ ext := xmitBuf.Get().([]byte)[:sess.headerSize+size]
copy(ext[sess.headerSize:], buf)
select {
case sess.chUDPOutput <- ext:
@@ -145,7 +145,7 @@ func (s *UDPSession) Read(b []byte) (n int, err error) {
if s.isClosed {
s.mu.Unlock()
- return 0, errors.New("broken pipe")
+ return 0, errors.New(errBrokenPipe)
}
if !s.rd.IsZero() {
@@ -169,19 +169,25 @@ func (s *UDPSession) Read(b []byte) (n int, err error) {
return n, nil
}
- var timeout <-chan time.Time
+ var timeout *time.Timer
+ var c <-chan time.Time
if !s.rd.IsZero() {
delay := s.rd.Sub(time.Now())
- timeout = time.After(delay)
+ timeout = time.NewTimer(delay)
+ c = timeout.C
}
s.mu.Unlock()
// wait for read event or timeout
select {
case <-s.chReadEvent:
- case <-timeout:
+ case <-c:
case <-s.die:
}
+
+ if timeout != nil {
+ timeout.Stop()
+ }
}
}
@@ -191,7 +197,7 @@ func (s *UDPSession) Write(b []byte) (n int, err error) {
s.mu.Lock()
if s.isClosed {
s.mu.Unlock()
- return 0, errors.New("broken pipe")
+ return 0, errors.New(errBrokenPipe)
}
if !s.wd.IsZero() {
@@ -201,7 +207,7 @@ func (s *UDPSession) Write(b []byte) (n int, err error) {
}
}
- if s.kcp.WaitSnd() < 2*int(s.kcp.snd_wnd) {
+ if s.kcp.WaitSnd() < int(s.kcp.snd_wnd) {
n = len(b)
max := s.kcp.mss << 8
for {
@@ -213,26 +219,31 @@ func (s *UDPSession) Write(b []byte) (n int, err error) {
b = b[max:]
}
}
- s.kcp.current = currentMs()
s.kcp.flush()
s.mu.Unlock()
atomic.AddUint64(&DefaultSnmp.BytesSent, uint64(n))
return n, nil
}
- var timeout <-chan time.Time
+ var timeout *time.Timer
+ var c <-chan time.Time
if !s.wd.IsZero() {
delay := s.wd.Sub(time.Now())
- timeout = time.After(delay)
+ timeout = time.NewTimer(delay)
+ c = timeout.C
}
s.mu.Unlock()
// wait for write event or timeout
select {
case <-s.chWriteEvent:
- case <-timeout:
+ case <-c:
case <-s.die:
}
+
+ if timeout != nil {
+ timeout.Stop()
+ }
}
}
@@ -241,7 +252,7 @@ func (s *UDPSession) Close() error {
s.mu.Lock()
defer s.mu.Unlock()
if s.isClosed {
- return errors.New("broken pipe")
+ return errors.New(errBrokenPipe)
}
close(s.die)
s.isClosed = true
@@ -321,6 +332,7 @@ func (s *UDPSession) SetNoDelay(nodelay, interval, resend, nc int) {
s.mu.Lock()
defer s.mu.Unlock()
s.kcp.NoDelay(nodelay, interval, resend, nc)
+ atomic.StoreInt32(&s.updateInterval, int32(interval))
}
// SetDSCP sets the 6bit DSCP field of IP header, no effect if it's accepted from Listener
@@ -328,11 +340,13 @@ func (s *UDPSession) SetDSCP(dscp int) error {
s.mu.Lock()
defer s.mu.Unlock()
if s.l == nil {
- if nc, ok := s.conn.(net.Conn); ok {
+ if nc, ok := s.conn.(*ConnectedUDPConn); ok {
+ return ipv4.NewConn(nc.Conn).SetTOS(dscp << 2)
+ } else if nc, ok := s.conn.(net.Conn); ok {
return ipv4.NewConn(nc).SetTOS(dscp << 2)
}
}
- return nil
+ return errors.New(errInvalidOperation)
}
// SetReadBuffer sets the socket read buffer, no effect if it's accepted from Listener
@@ -344,7 +358,7 @@ func (s *UDPSession) SetReadBuffer(bytes int) error {
return nc.SetReadBuffer(bytes)
}
}
- return nil
+ return errors.New(errInvalidOperation)
}
// SetWriteBuffer sets the socket write buffer, no effect if it's accepted from Listener
@@ -356,24 +370,12 @@ func (s *UDPSession) SetWriteBuffer(bytes int) error {
return nc.SetWriteBuffer(bytes)
}
}
- return nil
+ return errors.New(errInvalidOperation)
}
// SetKeepAlive changes per-connection NAT keepalive interval; 0 to disable, default to 10s
func (s *UDPSession) SetKeepAlive(interval int) {
- s.mu.Lock()
- defer s.mu.Unlock()
- s.keepAliveInterval = time.Duration(interval) * time.Second
-}
-
-// writeTo wraps write method for client & listener
-func (s *UDPSession) writeTo(b []byte, addr net.Addr) (int, error) {
- if s.l == nil {
- if nc, ok := s.conn.(io.Writer); ok {
- return nc.Write(b)
- }
- }
- return s.conn.WriteTo(b, addr)
+ atomic.StoreInt32(&s.keepAliveInterval, int32(interval))
}
func (s *UDPSession) outputTask() {
@@ -385,13 +387,15 @@ func (s *UDPSession) outputTask() {
szOffset := fecOffset + fecHeaderSize
// fec data group
+ var cacheLine []byte
var fecGroup [][]byte
var fecCnt int
var fecMaxSize int
if s.fec != nil {
+ cacheLine = make([]byte, s.fec.shardSize*mtuLimit)
fecGroup = make([][]byte, s.fec.shardSize)
for k := range fecGroup {
- fecGroup[k] = make([]byte, mtuLimit)
+ fecGroup[k] = cacheLine[k*mtuLimit : (k+1)*mtuLimit]
}
}
@@ -402,23 +406,31 @@ func (s *UDPSession) outputTask() {
for {
select {
+ // receive from a synchronous channel
+ // buffered channel must be avoided, because of "bufferbloat"
case ext := <-s.chUDPOutput:
var ecc [][]byte
if s.fec != nil {
s.fec.markData(ext[fecOffset:])
- // explicit size
+ // explicit size, including 2bytes size itself.
binary.LittleEndian.PutUint16(ext[szOffset:], uint16(len(ext[szOffset:])))
// copy data to fec group
- xorBytes(fecGroup[fecCnt], fecGroup[fecCnt], fecGroup[fecCnt])
+ sz := len(ext)
+ fecGroup[fecCnt] = fecGroup[fecCnt][:sz]
copy(fecGroup[fecCnt], ext)
fecCnt++
- if len(ext) > fecMaxSize {
- fecMaxSize = len(ext)
+ if sz > fecMaxSize {
+ fecMaxSize = sz
}
// calculate Reed-Solomon Erasure Code
if fecCnt == s.fec.dataShards {
+ for i := 0; i < s.fec.dataShards; i++ {
+ shard := fecGroup[i]
+ slen := len(shard)
+ xorBytes(shard[slen:fecMaxSize], shard[slen:fecMaxSize], shard[slen:fecMaxSize])
+ }
ecc = s.fec.calcECC(fecGroup, szOffset, fecMaxSize)
for k := range ecc {
s.fec.markFEC(ecc[k][fecOffset:])
@@ -445,38 +457,36 @@ func (s *UDPSession) outputTask() {
}
}
- //if rand.Intn(100) < 80 {
- if n, err := s.writeTo(ext, s.remote); err == nil {
- atomic.AddUint64(&DefaultSnmp.OutSegs, 1)
- atomic.AddUint64(&DefaultSnmp.OutBytes, uint64(n))
+ nbytes := 0
+ nsegs := 0
+ // if mrand.Intn(100) < 50 {
+ if n, err := s.conn.WriteTo(ext, s.remote); err == nil {
+ nbytes += n
+ nsegs++
}
- //}
+ // }
if ecc != nil {
for k := range ecc {
- if n, err := s.writeTo(ecc[k], s.remote); err == nil {
- atomic.AddUint64(&DefaultSnmp.OutSegs, 1)
- atomic.AddUint64(&DefaultSnmp.OutBytes, uint64(n))
+ if n, err := s.conn.WriteTo(ecc[k], s.remote); err == nil {
+ nbytes += n
+ nsegs++
}
}
}
- xorBytes(ext, ext, ext)
- s.xmitBuf.Put(ext)
+ atomic.AddUint64(&DefaultSnmp.OutSegs, uint64(nsegs))
+ atomic.AddUint64(&DefaultSnmp.OutBytes, uint64(nbytes))
+ xmitBuf.Put(ext)
case <-ticker.C: // NAT keep-alive
- if len(s.chUDPOutput) == 0 {
- s.mu.Lock()
- interval := s.keepAliveInterval
- s.mu.Unlock()
- if interval > 0 && time.Now().After(lastPing.Add(interval)) {
- buf := make([]byte, 2)
- io.ReadFull(rand.Reader, buf)
- rnd := int(binary.LittleEndian.Uint16(buf))
- sz := rnd%(IKCP_MTU_DEF-s.headerSize-IKCP_OVERHEAD) + s.headerSize + IKCP_OVERHEAD
- ping := make([]byte, sz)
- io.ReadFull(rand.Reader, ping)
- s.writeTo(ping, s.remote)
- lastPing = time.Now()
- }
+ interval := time.Duration(atomic.LoadInt32(&s.keepAliveInterval)) * time.Second
+ if interval > 0 && time.Now().After(lastPing.Add(interval)) {
+ var rnd uint16
+ binary.Read(rand.Reader, binary.LittleEndian, &rnd)
+ sz := int(rnd)%(IKCP_MTU_DEF-s.headerSize-IKCP_OVERHEAD) + s.headerSize + IKCP_OVERHEAD
+ ping := make([]byte, sz) // randomized ping packet
+ io.ReadFull(rand.Reader, ping)
+ s.conn.WriteTo(ping, s.remote)
+ lastPing = time.Now()
}
case <-s.die:
return
@@ -486,25 +496,18 @@ func (s *UDPSession) outputTask() {
// kcp update, input loop
func (s *UDPSession) updateTask() {
- var tc <-chan time.Time
- if s.l == nil { // client
- ticker := time.NewTicker(10 * time.Millisecond)
- tc = ticker.C
- defer ticker.Stop()
- } else {
- tc = s.chTicker
- }
+ tc := time.After(time.Duration(atomic.LoadInt32(&s.updateInterval)) * time.Millisecond)
for {
select {
case <-tc:
s.mu.Lock()
- current := currentMs()
- s.kcp.Update(current)
- if s.kcp.WaitSnd() < 2*int(s.kcp.snd_wnd) {
+ s.kcp.flush()
+ if s.kcp.WaitSnd() < int(s.kcp.snd_wnd) {
s.notifyWriteEvent()
}
s.mu.Unlock()
+ tc = time.After(time.Duration(atomic.LoadInt32(&s.updateInterval)) * time.Millisecond)
case <-s.die:
if s.l != nil { // has listener
select {
@@ -537,58 +540,84 @@ func (s *UDPSession) notifyWriteEvent() {
}
func (s *UDPSession) kcpInput(data []byte) {
- current := currentMs()
+ var kcpInErrors, fecErrs, fecRecovered, fecSegs uint64
+
if s.fec != nil {
f := s.fec.decode(data)
+ s.mu.Lock()
+ if f.flag == typeData {
+ if ret := s.kcp.Input(data[fecHeaderSizePlus2:], true); ret != 0 {
+ kcpInErrors++
+ }
+ }
+
if f.flag == typeData || f.flag == typeFEC {
if f.flag == typeFEC {
- atomic.AddUint64(&DefaultSnmp.FECSegs, 1)
+ fecSegs++
}
if recovers := s.fec.input(f); recovers != nil {
- s.mu.Lock()
- s.kcp.current = current
- for k := range recovers {
- sz := binary.LittleEndian.Uint16(recovers[k])
- if int(sz) <= len(recovers[k]) && sz >= 2 {
- s.kcp.Input(recovers[k][2:sz], false)
+ for _, r := range recovers {
+ if len(r) >= 2 { // must be larger than 2bytes
+ sz := binary.LittleEndian.Uint16(r)
+ if int(sz) <= len(r) && sz >= 2 {
+ if ret := s.kcp.Input(r[2:sz], false); ret == 0 {
+ fecRecovered++
+ } else {
+ kcpInErrors++
+ }
+ } else {
+ fecErrs++
+ }
} else {
- atomic.AddUint64(&DefaultSnmp.FECErrs, 1)
+ fecErrs++
}
}
- s.mu.Unlock()
- atomic.AddUint64(&DefaultSnmp.FECRecovered, uint64(len(recovers)))
}
}
- if f.flag == typeData {
- s.mu.Lock()
- s.kcp.current = current
- s.kcp.Input(data[fecHeaderSizePlus2:], true)
- s.mu.Unlock()
+
+ // notify reader
+ if n := s.kcp.PeekSize(); n > 0 {
+ s.notifyReadEvent()
}
+ if s.ackNoDelay {
+ s.kcp.flush()
+ }
+ s.mu.Unlock()
} else {
s.mu.Lock()
- s.kcp.current = current
- s.kcp.Input(data, true)
+ if ret := s.kcp.Input(data, true); ret != 0 {
+ kcpInErrors++
+ }
+ // notify reader
+ if n := s.kcp.PeekSize(); n > 0 {
+ s.notifyReadEvent()
+ }
+ if s.ackNoDelay {
+ s.kcp.flush()
+ }
s.mu.Unlock()
}
- // notify reader
- s.mu.Lock()
- if n := s.kcp.PeekSize(); n > 0 {
- s.notifyReadEvent()
- }
- if s.ackNoDelay {
- s.kcp.current = current
- s.kcp.flush()
- }
- s.mu.Unlock()
atomic.AddUint64(&DefaultSnmp.InSegs, 1)
+ atomic.AddUint64(&DefaultSnmp.InBytes, uint64(len(data)))
+ if fecSegs > 0 {
+ atomic.AddUint64(&DefaultSnmp.FECSegs, fecSegs)
+ }
+ if kcpInErrors > 0 {
+ atomic.AddUint64(&DefaultSnmp.KCPInErrors, kcpInErrors)
+ }
+ if fecErrs > 0 {
+ atomic.AddUint64(&DefaultSnmp.FECErrs, fecErrs)
+ }
+ if fecRecovered > 0 {
+ atomic.AddUint64(&DefaultSnmp.FECRecovered, fecRecovered)
+ }
}
func (s *UDPSession) receiver(ch chan []byte) {
for {
- data := s.xmitBuf.Get().([]byte)[:mtuLimit]
+ data := xmitBuf.Get().([]byte)[:mtuLimit]
if n, _, err := s.conn.ReadFrom(data); err == nil && n >= s.headerSize+IKCP_OVERHEAD {
select {
case ch <- data[:n]:
@@ -604,7 +633,7 @@ func (s *UDPSession) receiver(ch chan []byte) {
// read loop for client session
func (s *UDPSession) readLoop() {
- chPacket := make(chan []byte, txQueueLimit)
+ chPacket := make(chan []byte, rxQueueLimit)
go s.receiver(chPacket)
for {
@@ -629,8 +658,7 @@ func (s *UDPSession) readLoop() {
if dataValid {
s.kcpInput(data)
}
- xorBytes(raw, raw, raw)
- s.xmitBuf.Put(raw)
+ xmitBuf.Put(raw)
case <-s.die:
return
}
@@ -662,10 +690,8 @@ type (
// monitor incoming data for all connections of server
func (l *Listener) monitor() {
- chPacket := make(chan packet, txQueueLimit)
+ chPacket := make(chan packet, rxQueueLimit)
go l.receiver(chPacket)
- ticker := time.NewTicker(10 * time.Millisecond)
- defer ticker.Stop()
for {
select {
case p := <-chPacket:
@@ -715,20 +741,11 @@ func (l *Listener) monitor() {
}
}
- xorBytes(raw, raw, raw)
l.rxbuf.Put(raw)
case deadlink := <-l.chDeadlinks:
delete(l.sessions, deadlink.String())
case <-l.die:
return
- case <-ticker.C:
- now := time.Now()
- for _, s := range l.sessions {
- select {
- case s.chTicker <- now:
- default:
- }
- }
}
}
}
@@ -751,7 +768,7 @@ func (l *Listener) SetReadBuffer(bytes int) error {
if nc, ok := l.conn.(setReadBuffer); ok {
return nc.SetReadBuffer(bytes)
}
- return nil
+ return errors.New(errInvalidOperation)
}
// SetWriteBuffer sets the socket write buffer for the Listener
@@ -759,7 +776,7 @@ func (l *Listener) SetWriteBuffer(bytes int) error {
if nc, ok := l.conn.(setWriteBuffer); ok {
return nc.SetWriteBuffer(bytes)
}
- return nil
+ return errors.New(errInvalidOperation)
}
// SetDSCP sets the 6bit DSCP field of IP header
@@ -767,7 +784,7 @@ func (l *Listener) SetDSCP(dscp int) error {
if nc, ok := l.conn.(net.Conn); ok {
return ipv4.NewConn(nc).SetTOS(dscp << 2)
}
- return nil
+ return errors.New(errInvalidOperation)
}
// Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn.
@@ -788,7 +805,7 @@ func (l *Listener) AcceptKCP() (*UDPSession, error) {
case c := <-l.chAccepts:
return c, nil
case <-l.die:
- return nil, errors.New("listener stopped")
+ return nil, errors.New(errBrokenPipe)
}
}
@@ -823,7 +840,7 @@ func (l *Listener) Addr() net.Addr {
}
// Listen listens for incoming KCP packets addressed to the local address laddr on the network "udp",
-func Listen(laddr string) (*Listener, error) {
+func Listen(laddr string) (net.Listener, error) {
return ListenWithOptions(laddr, nil, 0, 0)
}
@@ -839,6 +856,11 @@ func ListenWithOptions(laddr string, block BlockCrypt, dataShards, parityShards
return nil, errors.Wrap(err, "net.ListenUDP")
}
+ return ServeConn(block, dataShards, parityShards, conn)
+}
+
+// ServeConn serves KCP protocol for a single packet connection.
+func ServeConn(block BlockCrypt, dataShards, parityShards int, conn net.PacketConn) (*Listener, error) {
l := new(Listener)
l.conn = conn
l.sessions = make(map[string]*UDPSession)
@@ -848,7 +870,7 @@ func ListenWithOptions(laddr string, block BlockCrypt, dataShards, parityShards
l.dataShards = dataShards
l.parityShards = parityShards
l.block = block
- l.fec = newFEC(rxFecLimit, dataShards, parityShards)
+ l.fec = newFEC(rxFECMulti*(dataShards+parityShards), dataShards, parityShards)
l.rxbuf.New = func() interface{} {
return make([]byte, mtuLimit)
}
@@ -866,12 +888,12 @@ func ListenWithOptions(laddr string, block BlockCrypt, dataShards, parityShards
}
// Dial connects to the remote address "raddr" on the network "udp"
-func Dial(raddr string) (*UDPSession, error) {
+func Dial(raddr string) (net.Conn, error) {
return DialWithOptions(raddr, nil, 0, 0)
}
// DialWithOptions connects to the remote address "raddr" on the network "udp" with packet encryption
-func DialWithOptions(raddr string, block BlockCrypt, dataShards, parityShards int, opts ...Option) (*UDPSession, error) {
+func DialWithOptions(raddr string, block BlockCrypt, dataShards, parityShards int) (*UDPSession, error) {
udpaddr, err := net.ResolveUDPAddr("udp", raddr)
if err != nil {
return nil, errors.Wrap(err, "net.ResolveUDPAddr")
@@ -882,20 +904,34 @@ func DialWithOptions(raddr string, block BlockCrypt, dataShards, parityShards in
return nil, errors.Wrap(err, "net.DialUDP")
}
- buf := make([]byte, 4)
- io.ReadFull(rand.Reader, buf)
- convid := binary.LittleEndian.Uint32(buf)
- for k := range opts {
- switch opt := opts[k].(type) {
- case OptionWithConvId:
- convid = opt.Id
- default:
- return nil, errors.New("unrecognized option")
- }
+ return NewConn(raddr, block, dataShards, parityShards, &ConnectedUDPConn{udpconn, udpconn})
+}
+
+// NewConn establishes a session and talks KCP protocol over a packet connection.
+func NewConn(raddr string, block BlockCrypt, dataShards, parityShards int, conn net.PacketConn) (*UDPSession, error) {
+ udpaddr, err := net.ResolveUDPAddr("udp", raddr)
+ if err != nil {
+ return nil, errors.Wrap(err, "net.ResolveUDPAddr")
}
- return newUDPSession(convid, dataShards, parityShards, nil, udpconn, udpaddr, block), nil
+
+ var convid uint32
+ binary.Read(rand.Reader, binary.LittleEndian, &convid)
+ return newUDPSession(convid, dataShards, parityShards, nil, conn, udpaddr, block), nil
}
func currentMs() uint32 {
return uint32(time.Now().UnixNano() / int64(time.Millisecond))
}
+
+// ConnectedUDPConn is a wrapper for net.UDPConn which converts WriteTo syscalls
+// to Write syscalls that are 4 times faster on some OS'es. This should only be
+// used for connections that were produced by a net.Dial* call.
+type ConnectedUDPConn struct {
+ *net.UDPConn
+ Conn net.Conn // underlying connection if any
+}
+
+// WriteTo redirects all writes to the Write syscall, which is 4 times faster.
+func (c *ConnectedUDPConn) WriteTo(b []byte, addr net.Addr) (int, error) {
+ return c.Write(b)
+}
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/shannon.jpg b/vendor/gopkg.in/xtaci/kcp-go.v2/shannon.jpg
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/shannon.jpg
rename to vendor/gopkg.in/xtaci/kcp-go.v2/shannon.jpg
diff --git a/vendor/gopkg.in/xtaci/kcp-go.v2/snmp.go b/vendor/gopkg.in/xtaci/kcp-go.v2/snmp.go
new file mode 100644
index 0000000..e8ab194
--- /dev/null
+++ b/vendor/gopkg.in/xtaci/kcp-go.v2/snmp.go
@@ -0,0 +1,152 @@
+package kcp
+
+import (
+ "fmt"
+ "sync/atomic"
+)
+
+// Snmp defines network statistics indicator
+type Snmp struct {
+ BytesSent uint64 // raw bytes sent
+ BytesReceived uint64
+ MaxConn uint64
+ ActiveOpens uint64
+ PassiveOpens uint64
+ CurrEstab uint64 // count of connections for now
+ InErrs uint64 // udp read errors
+ InCsumErrors uint64 // checksum errors from CRC32
+ KCPInErrors uint64 // packet iput errors from kcp
+ InSegs uint64
+ OutSegs uint64
+ InBytes uint64 // udp bytes received
+ OutBytes uint64 // udp bytes sent
+ RetransSegs uint64
+ FastRetransSegs uint64
+ EarlyRetransSegs uint64
+ LostSegs uint64 // number of segs infered as lost
+ RepeatSegs uint64 // number of segs duplicated
+ FECRecovered uint64 // correct packets recovered from FEC
+ FECErrs uint64 // incorrect packets recovered from FEC
+ FECSegs uint64 // FEC segments received
+ FECShortShards uint64 // number of data shards that's not enough for recovery
+}
+
+func newSnmp() *Snmp {
+ return new(Snmp)
+}
+
+func (s *Snmp) Header() []string {
+ return []string{
+ "BytesSent",
+ "BytesReceived",
+ "MaxConn",
+ "ActiveOpens",
+ "PassiveOpens",
+ "CurrEstab",
+ "InErrs",
+ "InCsumErrors",
+ "KCPInErrors",
+ "InSegs",
+ "OutSegs",
+ "InBytes",
+ "OutBytes",
+ "RetransSegs",
+ "FastRetransSegs",
+ "EarlyRetransSegs",
+ "LostSegs",
+ "RepeatSegs",
+ "FECSegs",
+ "FECErrs",
+ "FECRecovered",
+ "FECShortShards",
+ }
+}
+
+func (s *Snmp) ToSlice() []string {
+ snmp := s.Copy()
+ return []string{
+ fmt.Sprint(snmp.BytesSent),
+ fmt.Sprint(snmp.BytesReceived),
+ fmt.Sprint(snmp.MaxConn),
+ fmt.Sprint(snmp.ActiveOpens),
+ fmt.Sprint(snmp.PassiveOpens),
+ fmt.Sprint(snmp.CurrEstab),
+ fmt.Sprint(snmp.InErrs),
+ fmt.Sprint(snmp.InCsumErrors),
+ fmt.Sprint(snmp.KCPInErrors),
+ fmt.Sprint(snmp.InSegs),
+ fmt.Sprint(snmp.OutSegs),
+ fmt.Sprint(snmp.InBytes),
+ fmt.Sprint(snmp.OutBytes),
+ fmt.Sprint(snmp.RetransSegs),
+ fmt.Sprint(snmp.FastRetransSegs),
+ fmt.Sprint(snmp.EarlyRetransSegs),
+ fmt.Sprint(snmp.LostSegs),
+ fmt.Sprint(snmp.RepeatSegs),
+ fmt.Sprint(snmp.FECSegs),
+ fmt.Sprint(snmp.FECErrs),
+ fmt.Sprint(snmp.FECRecovered),
+ fmt.Sprint(snmp.FECShortShards),
+ }
+}
+
+// Copy make a copy of current snmp snapshot
+func (s *Snmp) Copy() *Snmp {
+ d := newSnmp()
+ d.BytesSent = atomic.LoadUint64(&s.BytesSent)
+ d.BytesReceived = atomic.LoadUint64(&s.BytesReceived)
+ d.MaxConn = atomic.LoadUint64(&s.MaxConn)
+ d.ActiveOpens = atomic.LoadUint64(&s.ActiveOpens)
+ d.PassiveOpens = atomic.LoadUint64(&s.PassiveOpens)
+ d.CurrEstab = atomic.LoadUint64(&s.CurrEstab)
+ d.InErrs = atomic.LoadUint64(&s.InErrs)
+ d.InCsumErrors = atomic.LoadUint64(&s.InCsumErrors)
+ d.KCPInErrors = atomic.LoadUint64(&s.KCPInErrors)
+ d.InSegs = atomic.LoadUint64(&s.InSegs)
+ d.OutSegs = atomic.LoadUint64(&s.OutSegs)
+ d.InBytes = atomic.LoadUint64(&s.InBytes)
+ d.OutBytes = atomic.LoadUint64(&s.OutBytes)
+ d.RetransSegs = atomic.LoadUint64(&s.RetransSegs)
+ d.FastRetransSegs = atomic.LoadUint64(&s.FastRetransSegs)
+ d.EarlyRetransSegs = atomic.LoadUint64(&s.EarlyRetransSegs)
+ d.LostSegs = atomic.LoadUint64(&s.LostSegs)
+ d.RepeatSegs = atomic.LoadUint64(&s.RepeatSegs)
+ d.FECSegs = atomic.LoadUint64(&s.FECSegs)
+ d.FECErrs = atomic.LoadUint64(&s.FECErrs)
+ d.FECRecovered = atomic.LoadUint64(&s.FECRecovered)
+ d.FECShortShards = atomic.LoadUint64(&s.FECShortShards)
+ return d
+}
+
+// Reset values to zero
+func (s *Snmp) Reset() {
+ atomic.StoreUint64(&s.BytesSent, 0)
+ atomic.StoreUint64(&s.BytesReceived, 0)
+ atomic.StoreUint64(&s.MaxConn, 0)
+ atomic.StoreUint64(&s.ActiveOpens, 0)
+ atomic.StoreUint64(&s.PassiveOpens, 0)
+ atomic.StoreUint64(&s.CurrEstab, 0)
+ atomic.StoreUint64(&s.InErrs, 0)
+ atomic.StoreUint64(&s.InCsumErrors, 0)
+ atomic.StoreUint64(&s.KCPInErrors, 0)
+ atomic.StoreUint64(&s.InSegs, 0)
+ atomic.StoreUint64(&s.OutSegs, 0)
+ atomic.StoreUint64(&s.InBytes, 0)
+ atomic.StoreUint64(&s.OutBytes, 0)
+ atomic.StoreUint64(&s.RetransSegs, 0)
+ atomic.StoreUint64(&s.FastRetransSegs, 0)
+ atomic.StoreUint64(&s.EarlyRetransSegs, 0)
+ atomic.StoreUint64(&s.LostSegs, 0)
+ atomic.StoreUint64(&s.RepeatSegs, 0)
+ atomic.StoreUint64(&s.FECSegs, 0)
+ atomic.StoreUint64(&s.FECErrs, 0)
+ atomic.StoreUint64(&s.FECRecovered, 0)
+ atomic.StoreUint64(&s.FECShortShards, 0)
+}
+
+// DefaultSnmp is the global KCP connection statistics collector
+var DefaultSnmp *Snmp
+
+func init() {
+ DefaultSnmp = newSnmp()
+}
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/xor.go b/vendor/gopkg.in/xtaci/kcp-go.v2/xor.go
similarity index 79%
rename from cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/xor.go
rename to vendor/gopkg.in/xtaci/kcp-go.v2/xor.go
index 5d21095..20fa2e4 100644
--- a/cmd/gost/vendor/gopkg.in/xtaci/kcp-go.v2/xor.go
+++ b/vendor/gopkg.in/xtaci/kcp-go.v2/xor.go
@@ -44,15 +44,18 @@ func safeXORBytes(dst, a, b []byte) int {
}
for i := ex; i < n; i += 8 {
- dst[i] = a[i] ^ b[i]
- dst[i+1] = a[i+1] ^ b[i+1]
- dst[i+2] = a[i+2] ^ b[i+2]
- dst[i+3] = a[i+3] ^ b[i+3]
+ _dst := dst[i : i+8]
+ _a := a[i : i+8]
+ _b := b[i : i+8]
+ _dst[0] = _a[0] ^ _b[0]
+ _dst[1] = _a[1] ^ _b[1]
+ _dst[2] = _a[2] ^ _b[2]
+ _dst[3] = _a[3] ^ _b[3]
- dst[i+4] = a[i+4] ^ b[i+4]
- dst[i+5] = a[i+5] ^ b[i+5]
- dst[i+6] = a[i+6] ^ b[i+6]
- dst[i+7] = a[i+7] ^ b[i+7]
+ _dst[4] = _a[4] ^ _b[4]
+ _dst[5] = _a[5] ^ _b[5]
+ _dst[6] = _a[6] ^ _b[6]
+ _dst[7] = _a[7] ^ _b[7]
}
return n
}
@@ -85,14 +88,17 @@ func fastXORWords(dst, a, b []byte) {
}
for i := ex; i < n; i += 8 {
- dw[i] = aw[i] ^ bw[i]
- dw[i+1] = aw[i+1] ^ bw[i+1]
- dw[i+2] = aw[i+2] ^ bw[i+2]
- dw[i+3] = aw[i+3] ^ bw[i+3]
- dw[i+4] = aw[i+4] ^ bw[i+4]
- dw[i+5] = aw[i+5] ^ bw[i+5]
- dw[i+6] = aw[i+6] ^ bw[i+6]
- dw[i+7] = aw[i+7] ^ bw[i+7]
+ _dw := dw[i : i+8]
+ _aw := aw[i : i+8]
+ _bw := bw[i : i+8]
+ _dw[0] = _aw[0] ^ _bw[0]
+ _dw[1] = _aw[1] ^ _bw[1]
+ _dw[2] = _aw[2] ^ _bw[2]
+ _dw[3] = _aw[3] ^ _bw[3]
+ _dw[4] = _aw[4] ^ _bw[4]
+ _dw[5] = _aw[5] ^ _bw[5]
+ _dw[6] = _aw[6] ^ _bw[6]
+ _dw[7] = _aw[7] ^ _bw[7]
}
}
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/smux.v1/LICENSE b/vendor/gopkg.in/xtaci/smux.v1/LICENSE
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/xtaci/smux.v1/LICENSE
rename to vendor/gopkg.in/xtaci/smux.v1/LICENSE
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/smux.v1/README.md b/vendor/gopkg.in/xtaci/smux.v1/README.md
similarity index 97%
rename from cmd/gost/vendor/gopkg.in/xtaci/smux.v1/README.md
rename to vendor/gopkg.in/xtaci/smux.v1/README.md
index 15e9871..9a760d2 100644
--- a/cmd/gost/vendor/gopkg.in/xtaci/smux.v1/README.md
+++ b/vendor/gopkg.in/xtaci/smux.v1/README.md
@@ -62,7 +62,7 @@ func client() {
panic(err)
}
- // Stream implements net.Conn
+ // Stream implements io.ReadWriteCloser
stream.Write([]byte("ping"))
}
@@ -94,4 +94,4 @@ func server() {
## Status
-Beta
+Stable
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/smux.v1/curve.jpg b/vendor/gopkg.in/xtaci/smux.v1/curve.jpg
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/xtaci/smux.v1/curve.jpg
rename to vendor/gopkg.in/xtaci/smux.v1/curve.jpg
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/smux.v1/frame.go b/vendor/gopkg.in/xtaci/smux.v1/frame.go
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/xtaci/smux.v1/frame.go
rename to vendor/gopkg.in/xtaci/smux.v1/frame.go
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/smux.v1/mux.go b/vendor/gopkg.in/xtaci/smux.v1/mux.go
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/xtaci/smux.v1/mux.go
rename to vendor/gopkg.in/xtaci/smux.v1/mux.go
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/smux.v1/mux.jpg b/vendor/gopkg.in/xtaci/smux.v1/mux.jpg
similarity index 100%
rename from cmd/gost/vendor/gopkg.in/xtaci/smux.v1/mux.jpg
rename to vendor/gopkg.in/xtaci/smux.v1/mux.jpg
diff --git a/cmd/gost/vendor/gopkg.in/xtaci/smux.v1/session.go b/vendor/gopkg.in/xtaci/smux.v1/session.go
similarity index 75%
rename from cmd/gost/vendor/gopkg.in/xtaci/smux.v1/session.go
rename to vendor/gopkg.in/xtaci/smux.v1/session.go
index a06f2ec..5c759c0 100644
--- a/cmd/gost/vendor/gopkg.in/xtaci/smux.v1/session.go
+++ b/vendor/gopkg.in/xtaci/smux.v1/session.go
@@ -16,10 +16,19 @@ const (
const (
errBrokenPipe = "broken pipe"
- errConnReset = "connection reset by peer"
errInvalidProtocol = "invalid protocol version"
)
+type writeRequest struct {
+ frame Frame
+ result chan writeResult
+}
+
+type writeResult struct {
+ n int
+ err error
+}
+
// Session defines a multiplexed connection for streams
type Session struct {
conn io.ReadWriteCloser
@@ -38,7 +47,12 @@ type Session struct {
dieLock sync.Mutex
chAccepts chan *Stream
+ xmitPool sync.Pool
dataReady int32 // flag data has arrived
+
+ deadline atomic.Value
+
+ writes chan writeRequest
}
func newSession(config *Config, conn io.ReadWriteCloser, client bool) *Session {
@@ -50,12 +64,18 @@ func newSession(config *Config, conn io.ReadWriteCloser, client bool) *Session {
s.chAccepts = make(chan *Stream, defaultAcceptBacklog)
s.bucket = int32(config.MaxReceiveBuffer)
s.bucketCond = sync.NewCond(&sync.Mutex{})
+ s.xmitPool.New = func() interface{} {
+ return make([]byte, (1<<16)+headerSize)
+ }
+ s.writes = make(chan writeRequest)
+
if client {
s.nextStreamID = 1
} else {
s.nextStreamID = 2
}
go s.recvLoop()
+ go s.sendLoop()
go s.keepalive()
return s
}
@@ -82,9 +102,17 @@ func (s *Session) OpenStream() (*Stream, error) {
// AcceptStream is used to block until the next available stream
// is ready to be accepted.
func (s *Session) AcceptStream() (*Stream, error) {
+ var deadline <-chan time.Time
+ if d, ok := s.deadline.Load().(time.Time); ok && !d.IsZero() {
+ timer := time.NewTimer(d.Sub(time.Now()))
+ defer timer.Stop()
+ deadline = timer.C
+ }
select {
case stream := <-s.chAccepts:
return stream, nil
+ case <-deadline:
+ return nil, errTimeout
case <-s.die:
return nil, errors.New(errBrokenPipe)
}
@@ -93,13 +121,14 @@ func (s *Session) AcceptStream() (*Stream, error) {
// Close is used to close the session and all streams.
func (s *Session) Close() (err error) {
s.dieLock.Lock()
- defer s.dieLock.Unlock()
select {
case <-s.die:
+ s.dieLock.Unlock()
return errors.New(errBrokenPipe)
default:
close(s.die)
+ s.dieLock.Unlock()
s.streamLock.Lock()
for k := range s.streams {
s.streams[k].sessionClose()
@@ -130,6 +159,13 @@ func (s *Session) NumStreams() int {
return len(s.streams)
}
+// SetDeadline sets a deadline used by Accept* calls.
+// A zero time value disables the deadline.
+func (s *Session) SetDeadline(t time.Time) error {
+ s.deadline.Store(t)
+ return nil
+}
+
// notify the session that a stream has closed
func (s *Session) streamClosed(sid uint32) {
s.streamLock.Lock()
@@ -144,9 +180,12 @@ func (s *Session) streamClosed(sid uint32) {
// returnTokens is called by stream to return token after read
func (s *Session) returnTokens(n int) {
- if atomic.AddInt32(&s.bucket, int32(n)) > 0 {
+ oldvalue := atomic.LoadInt32(&s.bucket)
+ newvalue := atomic.AddInt32(&s.bucket, int32(n))
+ if oldvalue <= 0 && newvalue > 0 {
s.bucketCond.Signal()
}
+
}
// session read a frame from underlying connection
@@ -250,26 +289,56 @@ func (s *Session) keepalive() {
}
}
+func (s *Session) sendLoop() {
+ for {
+ select {
+ case <-s.die:
+ return
+ case request, ok := <-s.writes:
+ if !ok {
+ continue
+ }
+ buf := s.xmitPool.Get().([]byte)
+ buf[0] = request.frame.ver
+ buf[1] = request.frame.cmd
+ binary.LittleEndian.PutUint16(buf[2:], uint16(len(request.frame.data)))
+ binary.LittleEndian.PutUint32(buf[4:], request.frame.sid)
+ copy(buf[headerSize:], request.frame.data)
+
+ s.writeLock.Lock()
+ n, err := s.conn.Write(buf[:headerSize+len(request.frame.data)])
+ s.writeLock.Unlock()
+ s.xmitPool.Put(buf)
+
+ n -= headerSize
+ if n < 0 {
+ n = 0
+ }
+
+ result := writeResult{
+ n: n,
+ err: err,
+ }
+
+ request.result <- result
+ close(request.result)
+ }
+ }
+}
+
// writeFrame writes the frame to the underlying connection
// and returns the number of bytes written if successful
func (s *Session) writeFrame(f Frame) (n int, err error) {
- buf := make([]byte, headerSize+len(f.data))
- buf[0] = f.ver
- buf[1] = f.cmd
- binary.LittleEndian.PutUint16(buf[2:], uint16(len(f.data)))
- binary.LittleEndian.PutUint32(buf[4:], f.sid)
- copy(buf[headerSize:], f.data)
+ req := writeRequest{
+ frame: f,
+ result: make(chan writeResult, 1),
+ }
+ select {
+ case <-s.die:
+ return 0, errors.New(errBrokenPipe)
+ case s.writes <- req:
+ }
- s.writeLock.Lock()
- n, err = s.conn.Write(buf)
- s.writeLock.Unlock()
- return n, err
-}
-
-// writeBinary writes the byte slice to the underlying connection
-func (s *Session) writeBinary(bts []byte) (n int, err error) {
- s.writeLock.Lock()
- n, err = s.conn.Write(bts)
- s.writeLock.Unlock()
- return n, err
+ result := <-req.result
+ return result.n, result.err
}
diff --git a/vendor/gopkg.in/xtaci/smux.v1/stream.go b/vendor/gopkg.in/xtaci/smux.v1/stream.go
new file mode 100644
index 0000000..34e4abb
--- /dev/null
+++ b/vendor/gopkg.in/xtaci/smux.v1/stream.go
@@ -0,0 +1,256 @@
+package smux
+
+import (
+ "bytes"
+ "io"
+ "net"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/pkg/errors"
+)
+
+// Stream implements io.ReadWriteCloser
+type Stream struct {
+ id uint32
+ rstflag int32
+ sess *Session
+ buffer bytes.Buffer
+ bufferLock sync.Mutex
+ frameSize int
+ chReadEvent chan struct{} // notify a read event
+ die chan struct{} // flag the stream has closed
+ dieLock sync.Mutex
+ readDeadline atomic.Value
+ writeDeadline atomic.Value
+}
+
+// newStream initiates a Stream struct
+func newStream(id uint32, frameSize int, sess *Session) *Stream {
+ s := new(Stream)
+ s.id = id
+ s.chReadEvent = make(chan struct{}, 1)
+ s.frameSize = frameSize
+ s.sess = sess
+ s.die = make(chan struct{})
+ return s
+}
+
+// Read implements io.ReadWriteCloser
+func (s *Stream) Read(b []byte) (n int, err error) {
+ var deadline <-chan time.Time
+ if d, ok := s.readDeadline.Load().(time.Time); ok && !d.IsZero() {
+ timer := time.NewTimer(d.Sub(time.Now()))
+ defer timer.Stop()
+ deadline = timer.C
+ }
+
+READ:
+ select {
+ case <-s.die:
+ return 0, errors.New(errBrokenPipe)
+ case <-deadline:
+ return n, errTimeout
+ default:
+ }
+
+ s.bufferLock.Lock()
+ n, err = s.buffer.Read(b)
+ s.bufferLock.Unlock()
+
+ if n > 0 {
+ s.sess.returnTokens(n)
+ return n, nil
+ } else if atomic.LoadInt32(&s.rstflag) == 1 {
+ _ = s.Close()
+ return 0, io.EOF
+ }
+
+ select {
+ case <-s.chReadEvent:
+ goto READ
+ case <-deadline:
+ return n, errTimeout
+ case <-s.die:
+ return 0, errors.New(errBrokenPipe)
+ }
+}
+
+// Write implements io.ReadWriteCloser
+func (s *Stream) Write(b []byte) (n int, err error) {
+ var deadline <-chan time.Time
+ if d, ok := s.writeDeadline.Load().(time.Time); ok && !d.IsZero() {
+ timer := time.NewTimer(d.Sub(time.Now()))
+ defer timer.Stop()
+ deadline = timer.C
+ }
+
+ select {
+ case <-s.die:
+ return 0, errors.New(errBrokenPipe)
+ default:
+ }
+
+ frames := s.split(b, cmdPSH, s.id)
+ sent := 0
+ for k := range frames {
+ req := writeRequest{
+ frame: frames[k],
+ result: make(chan writeResult, 1),
+ }
+
+ select {
+ case s.sess.writes <- req:
+ case <-s.die:
+ return sent, errors.New(errBrokenPipe)
+ case <-deadline:
+ return sent, errTimeout
+ }
+
+ select {
+ case result := <-req.result:
+ sent += result.n
+ if result.err != nil {
+ return sent, result.err
+ }
+ case <-s.die:
+ return sent, errors.New(errBrokenPipe)
+ case <-deadline:
+ return sent, errTimeout
+ }
+ }
+ return sent, nil
+}
+
+// Close implements io.ReadWriteCloser
+func (s *Stream) Close() error {
+ s.dieLock.Lock()
+
+ select {
+ case <-s.die:
+ s.dieLock.Unlock()
+ return errors.New(errBrokenPipe)
+ default:
+ close(s.die)
+ s.dieLock.Unlock()
+ s.sess.streamClosed(s.id)
+ _, err := s.sess.writeFrame(newFrame(cmdRST, s.id))
+ return err
+ }
+}
+
+// SetReadDeadline sets the read deadline as defined by
+// net.Conn.SetReadDeadline.
+// A zero time value disables the deadline.
+func (s *Stream) SetReadDeadline(t time.Time) error {
+ s.readDeadline.Store(t)
+ return nil
+}
+
+// SetWriteDeadline sets the write deadline as defined by
+// net.Conn.SetWriteDeadline.
+// A zero time value disables the deadline.
+func (s *Stream) SetWriteDeadline(t time.Time) error {
+ s.writeDeadline.Store(t)
+ return nil
+}
+
+// SetDeadline sets both read and write deadlines as defined by
+// net.Conn.SetDeadline.
+// A zero time value disables the deadlines.
+func (s *Stream) SetDeadline(t time.Time) error {
+ if err := s.SetReadDeadline(t); err != nil {
+ return err
+ }
+ if err := s.SetWriteDeadline(t); err != nil {
+ return err
+ }
+ return nil
+}
+
+// session closes the stream
+func (s *Stream) sessionClose() {
+ s.dieLock.Lock()
+ defer s.dieLock.Unlock()
+
+ select {
+ case <-s.die:
+ default:
+ close(s.die)
+ }
+}
+
+// LocalAddr satisfies net.Conn interface
+func (s *Stream) LocalAddr() net.Addr {
+ if ts, ok := s.sess.conn.(interface {
+ LocalAddr() net.Addr
+ }); ok {
+ return ts.LocalAddr()
+ }
+ return nil
+}
+
+// RemoteAddr satisfies net.Conn interface
+func (s *Stream) RemoteAddr() net.Addr {
+ if ts, ok := s.sess.conn.(interface {
+ RemoteAddr() net.Addr
+ }); ok {
+ return ts.RemoteAddr()
+ }
+ return nil
+}
+
+// pushBytes a slice into buffer
+func (s *Stream) pushBytes(p []byte) {
+ s.bufferLock.Lock()
+ s.buffer.Write(p)
+ s.bufferLock.Unlock()
+}
+
+// recycleTokens transform remaining bytes to tokens(will truncate buffer)
+func (s *Stream) recycleTokens() (n int) {
+ s.bufferLock.Lock()
+ n = s.buffer.Len()
+ s.buffer.Reset()
+ s.bufferLock.Unlock()
+ return
+}
+
+// split large byte buffer into smaller frames, reference only
+func (s *Stream) split(bts []byte, cmd byte, sid uint32) []Frame {
+ var frames []Frame
+ for len(bts) > s.frameSize {
+ frame := newFrame(cmd, sid)
+ frame.data = bts[:s.frameSize]
+ bts = bts[s.frameSize:]
+ frames = append(frames, frame)
+ }
+ if len(bts) > 0 {
+ frame := newFrame(cmd, sid)
+ frame.data = bts
+ frames = append(frames, frame)
+ }
+ return frames
+}
+
+// notify read event
+func (s *Stream) notifyReadEvent() {
+ select {
+ case s.chReadEvent <- struct{}{}:
+ default:
+ }
+}
+
+// mark this stream has been reset
+func (s *Stream) markRST() {
+ atomic.StoreInt32(&s.rstflag, 1)
+}
+
+var errTimeout error = &timeoutError{}
+
+type timeoutError struct{}
+
+func (e *timeoutError) Error() string { return "i/o timeout" }
+func (e *timeoutError) Timeout() bool { return true }
+func (e *timeoutError) Temporary() bool { return true }
diff --git a/vendor/vendor.json b/vendor/vendor.json
new file mode 100644
index 0000000..3691d4f
--- /dev/null
+++ b/vendor/vendor.json
@@ -0,0 +1,427 @@
+{
+ "comment": "",
+ "ignore": "test",
+ "package": [
+ {
+ "checksumSHA1": "Ntd/jdOFlzTpccS67XPoN8P+GvA=",
+ "path": "git.torproject.org/pluggable-transports/goptlib.git",
+ "revision": "a3ad5df6c9e7dc8117f55958b4ce99bf1e0fe291",
+ "revisionTime": "2017-06-26T23:50:26Z"
+ },
+ {
+ "checksumSHA1": "9FjAFzCl4t9s2I/2LrLcmTqprJc=",
+ "path": "git.torproject.org/pluggable-transports/obfs4.git/common/csrand",
+ "revision": "97a875ec3c0afa629405c78e750d27e4e1f851ca",
+ "revisionTime": "2016-11-15T19:21:38Z"
+ },
+ {
+ "checksumSHA1": "QcRA+Vo62wjolAdMtjWmtyE+j2g=",
+ "path": "git.torproject.org/pluggable-transports/obfs4.git/common/drbg",
+ "revision": "97a875ec3c0afa629405c78e750d27e4e1f851ca",
+ "revisionTime": "2016-11-15T19:21:38Z"
+ },
+ {
+ "checksumSHA1": "aAkBnDAHUvUpyX4G1PmedxQQpx4=",
+ "path": "git.torproject.org/pluggable-transports/obfs4.git/common/ntor",
+ "revision": "97a875ec3c0afa629405c78e750d27e4e1f851ca",
+ "revisionTime": "2016-11-15T19:21:38Z"
+ },
+ {
+ "checksumSHA1": "MNwh5v3DYMhxJQHgwCubElx5hjk=",
+ "path": "git.torproject.org/pluggable-transports/obfs4.git/common/probdist",
+ "revision": "97a875ec3c0afa629405c78e750d27e4e1f851ca",
+ "revisionTime": "2016-11-15T19:21:38Z"
+ },
+ {
+ "checksumSHA1": "g0e9BbYKC/ToxZ+GVh77L0QA8Eg=",
+ "path": "git.torproject.org/pluggable-transports/obfs4.git/common/replayfilter",
+ "revision": "97a875ec3c0afa629405c78e750d27e4e1f851ca",
+ "revisionTime": "2016-11-15T19:21:38Z"
+ },
+ {
+ "checksumSHA1": "bLggyj50IADuEWoWSoyYdU6MaFo=",
+ "path": "git.torproject.org/pluggable-transports/obfs4.git/transports/base",
+ "revision": "97a875ec3c0afa629405c78e750d27e4e1f851ca",
+ "revisionTime": "2016-11-15T19:21:38Z"
+ },
+ {
+ "checksumSHA1": "0WJ//uEKORueVXb9DDrZ7t1v00s=",
+ "path": "git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4",
+ "revision": "97a875ec3c0afa629405c78e750d27e4e1f851ca",
+ "revisionTime": "2016-11-15T19:21:38Z"
+ },
+ {
+ "checksumSHA1": "EuNvu7iIjtIWStjBSXSvaRNa76M=",
+ "path": "git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4/framing",
+ "revision": "97a875ec3c0afa629405c78e750d27e4e1f851ca",
+ "revisionTime": "2016-11-15T19:21:38Z"
+ },
+ {
+ "checksumSHA1": "IFJyJgPCjumDG37lEb0lyRBBGZE=",
+ "path": "github.com/Yawning/chacha20",
+ "revision": "c91e78db502ff629614837aacb7aa4efa61c651a",
+ "revisionTime": "2016-04-30T09:49:23Z"
+ },
+ {
+ "checksumSHA1": "30PBqj9BW03KCVqASvLg3bR+xYc=",
+ "path": "github.com/agl/ed25519/edwards25519",
+ "revision": "5312a61534124124185d41f09206b9fef1d88403",
+ "revisionTime": "2017-01-16T20:05:12Z"
+ },
+ {
+ "checksumSHA1": "wHBvnCJG9bkZdtxFFefU+8/WDSE=",
+ "path": "github.com/agl/ed25519/extra25519",
+ "revision": "5312a61534124124185d41f09206b9fef1d88403",
+ "revisionTime": "2017-01-16T20:05:12Z"
+ },
+ {
+ "checksumSHA1": "xqVDKHGnakGlcRhmWd1j9JYmfLc=",
+ "path": "github.com/dchest/siphash",
+ "revision": "4ebf1de738443ea7f45f02dc394c4df1942a126d",
+ "revisionTime": "2016-08-31T15:17:26Z"
+ },
+ {
+ "checksumSHA1": "aIhLeVAIrsjs63CwqmU3+GU8yT4=",
+ "path": "github.com/ginuerzh/gosocks4",
+ "revision": "fc196f9d34e35f19a813bff2f092a275131c23bc",
+ "revisionTime": "2017-02-09T14:09:51Z"
+ },
+ {
+ "checksumSHA1": "4JEexBJToQeQm7fAo2PHVdCU3zM=",
+ "path": "github.com/ginuerzh/gosocks5",
+ "revision": "cb895c2f7a2cdceaf74ac6497f709b71a999168a",
+ "revisionTime": "2017-08-01T04:47:37Z"
+ },
+ {
+ "checksumSHA1": "9e9tjPDTESeCEdUMElph250lurs=",
+ "path": "github.com/ginuerzh/pht",
+ "revision": "8acf34a91f436364fadb82a630ab3c7e938e1d0f",
+ "revisionTime": "2017-02-05T06:52:49Z"
+ },
+ {
+ "checksumSHA1": "fBx0fqiyrl26gkGo14J9pJ8zB2Y=",
+ "path": "github.com/go-log/log",
+ "revision": "37e2e1f19306361e1fc152a1839f1236149cb4e4",
+ "revisionTime": "2017-05-15T17:08:25Z"
+ },
+ {
+ "checksumSHA1": "HmbftipkadrLlCfzzVQ+iFHbl6g=",
+ "path": "github.com/golang/glog",
+ "revision": "23def4e6c14b4da8ac2ed8007337bc5eb5007998",
+ "revisionTime": "2016-01-25T20:49:56Z"
+ },
+ {
+ "checksumSHA1": "d9PxF1XQGLMJZRct2R8qVM/eYlE=",
+ "path": "github.com/hashicorp/golang-lru",
+ "revision": "0a025b7e63adc15a622f29b0b2c4c3848243bbf6",
+ "revisionTime": "2016-08-13T22:13:03Z"
+ },
+ {
+ "checksumSHA1": "9hffs0bAIU6CquiRhKQdzjHnKt0=",
+ "path": "github.com/hashicorp/golang-lru/simplelru",
+ "revision": "0a025b7e63adc15a622f29b0b2c4c3848243bbf6",
+ "revisionTime": "2016-08-13T22:13:03Z"
+ },
+ {
+ "checksumSHA1": "/EgCTbjJkJh2yi9lqEgzmau8O4I=",
+ "path": "github.com/klauspost/compress/snappy",
+ "revision": "461e8fd8397ae84a23f56e385801e4feda2048ce",
+ "revisionTime": "2017-01-14T13:08:32Z"
+ },
+ {
+ "checksumSHA1": "iKPMvbAueGfdyHcWCgzwKzm8WVo=",
+ "path": "github.com/klauspost/cpuid",
+ "revision": "09cded8978dc9e80714c4d85b0322337b0a1e5e0",
+ "revisionTime": "2016-03-02T07:53:16Z"
+ },
+ {
+ "checksumSHA1": "dwSGkUfh3A2h0VkXndzBX/27hVc=",
+ "path": "github.com/klauspost/reedsolomon",
+ "revision": "c54154da9e35cab25232314cf69ab9d78447f9a5",
+ "revisionTime": "2016-09-12T19:31:07Z"
+ },
+ {
+ "checksumSHA1": "hUI9uYDnlXeOY+SEAPViyVpgq6I=",
+ "path": "github.com/lucas-clemente/aes12",
+ "revision": "25700e67be5c860bcc999137275b9ef8b65932bd",
+ "revisionTime": "2016-12-15T15:22:28Z"
+ },
+ {
+ "checksumSHA1": "ne1X+frkx5fJcpz9FaZPuUZ7amM=",
+ "path": "github.com/lucas-clemente/fnv128a",
+ "revision": "393af48d391698c6ae4219566bfbdfef67269997",
+ "revisionTime": "2016-05-04T15:23:51Z"
+ },
+ {
+ "checksumSHA1": "Z/PMIFIZ3o0/HabtyLwTHKKdvb4=",
+ "path": "github.com/lucas-clemente/quic-go",
+ "revision": "811315e31a0c190e7a9e86c84102e86c9ed2a072",
+ "revisionTime": "2017-07-29T00:10:52Z"
+ },
+ {
+ "checksumSHA1": "OA9E+y7g05x/mWJJHmA7oPxWKQo=",
+ "path": "github.com/lucas-clemente/quic-go-certificates",
+ "revision": "d2f86524cced5186554df90d92529757d22c1cb6",
+ "revisionTime": "2016-08-23T09:51:56Z"
+ },
+ {
+ "checksumSHA1": "quVHUmzDMdxO14W2xY1PizK1GME=",
+ "path": "github.com/lucas-clemente/quic-go/ackhandler",
+ "revision": "811315e31a0c190e7a9e86c84102e86c9ed2a072",
+ "revisionTime": "2017-07-29T00:10:52Z"
+ },
+ {
+ "checksumSHA1": "bHgFCrGrrdQLBrDN/iwhWnTY5c8=",
+ "path": "github.com/lucas-clemente/quic-go/congestion",
+ "revision": "811315e31a0c190e7a9e86c84102e86c9ed2a072",
+ "revisionTime": "2017-07-29T00:10:52Z"
+ },
+ {
+ "checksumSHA1": "mOdxhLhYusZpEUM4XYweq6/e7wc=",
+ "path": "github.com/lucas-clemente/quic-go/crypto",
+ "revision": "811315e31a0c190e7a9e86c84102e86c9ed2a072",
+ "revisionTime": "2017-07-29T00:10:52Z"
+ },
+ {
+ "checksumSHA1": "IjJn3XeLM+MZ0vWkl2RxK+8y7ac=",
+ "path": "github.com/lucas-clemente/quic-go/flowcontrol",
+ "revision": "811315e31a0c190e7a9e86c84102e86c9ed2a072",
+ "revisionTime": "2017-07-29T00:10:52Z"
+ },
+ {
+ "checksumSHA1": "BvjNmqw285B/O0u9CapEiOG6nNU=",
+ "path": "github.com/lucas-clemente/quic-go/frames",
+ "revision": "811315e31a0c190e7a9e86c84102e86c9ed2a072",
+ "revisionTime": "2017-07-29T00:10:52Z"
+ },
+ {
+ "checksumSHA1": "T6xXdLavEsHmF+yhvMOjKn/1RJU=",
+ "path": "github.com/lucas-clemente/quic-go/h2quic",
+ "revision": "811315e31a0c190e7a9e86c84102e86c9ed2a072",
+ "revisionTime": "2017-07-29T00:10:52Z"
+ },
+ {
+ "checksumSHA1": "dnDC7JMEhC/8UtQnkExChY+zIeY=",
+ "path": "github.com/lucas-clemente/quic-go/handshake",
+ "revision": "811315e31a0c190e7a9e86c84102e86c9ed2a072",
+ "revisionTime": "2017-07-29T00:10:52Z"
+ },
+ {
+ "checksumSHA1": "I106jIrBkNesQcoPrgUJ8e2JUNY=",
+ "path": "github.com/lucas-clemente/quic-go/internal/utils",
+ "revision": "811315e31a0c190e7a9e86c84102e86c9ed2a072",
+ "revisionTime": "2017-07-29T00:10:52Z"
+ },
+ {
+ "checksumSHA1": "UoLAi6qeJrVxnEWxEyRs7VKLp78=",
+ "path": "github.com/lucas-clemente/quic-go/protocol",
+ "revision": "811315e31a0c190e7a9e86c84102e86c9ed2a072",
+ "revisionTime": "2017-07-29T00:10:52Z"
+ },
+ {
+ "checksumSHA1": "RaG0jfP+lFzgedW98Bfp0Uri7EY=",
+ "path": "github.com/lucas-clemente/quic-go/qerr",
+ "revision": "811315e31a0c190e7a9e86c84102e86c9ed2a072",
+ "revisionTime": "2017-07-29T00:10:52Z"
+ },
+ {
+ "checksumSHA1": "ynJSWoF6v+3zMnh9R0QmmG6iGV8=",
+ "path": "github.com/pkg/errors",
+ "revision": "248dadf4e9068a0b3e79f02ed0a610d935de5302",
+ "revisionTime": "2016-10-29T09:36:37Z"
+ },
+ {
+ "checksumSHA1": "6JP37UqrI0H80Gpk0Y2P+KXgn5M=",
+ "path": "github.com/ryanuber/go-glob",
+ "revision": "256dc444b735e061061cf46c809487313d5b0065",
+ "revisionTime": "2017-01-28T01:21:29Z"
+ },
+ {
+ "checksumSHA1": "MRsfMrdZwnnCTfIzT3czcj0lb0s=",
+ "path": "github.com/shadowsocks/shadowsocks-go/shadowsocks",
+ "revision": "97a5c71f80ba5f5b3e549f14a619fe557ff4f3c9",
+ "revisionTime": "2017-01-21T20:35:16Z"
+ },
+ {
+ "checksumSHA1": "oVPHWesOmZ02vLq2fglGvf+AMgk=",
+ "path": "golang.org/x/crypto/blowfish",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "TT1rac6kpQp2vz24m5yDGUNQ/QQ=",
+ "path": "golang.org/x/crypto/cast5",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "MlEHIE/60sB86Lmf0MPTIXHzKzE=",
+ "path": "golang.org/x/crypto/curve25519",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "i3dNaI+oCYeDGIsNj7LwecTsIAs=",
+ "path": "golang.org/x/crypto/ed25519",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "LXFcVx8I587SnWmKycSDEq9yvK8=",
+ "path": "golang.org/x/crypto/ed25519/internal/edwards25519",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "4D8hxMIaSDEW5pCQk22Xj4DcDh4=",
+ "path": "golang.org/x/crypto/hkdf",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "Y/FcWB2/xSfX1rRp7HYhktHNw8s=",
+ "path": "golang.org/x/crypto/nacl/secretbox",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "1MGpGDQqnUoRpv7VEcQrXOBydXE=",
+ "path": "golang.org/x/crypto/pbkdf2",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "kVKE0OX1Xdw5mG7XKT86DLLKE2I=",
+ "path": "golang.org/x/crypto/poly1305",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "qsacnnq6zmaoRpDJeTX2YDpIo6U=",
+ "path": "golang.org/x/crypto/salsa20",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "RUr1Owi1/hTpuAqKeeus6YuEyz8=",
+ "path": "golang.org/x/crypto/salsa20/salsa",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "+cJ5DMdWg6q//21EKgxcaQ5vZaI=",
+ "path": "golang.org/x/crypto/ssh",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "Iwv89z1aXYKaB936lnsmE2NcfqA=",
+ "path": "golang.org/x/crypto/tea",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "fgKd/+IO854XgYSrwOQJ5jG8WdI=",
+ "path": "golang.org/x/crypto/twofish",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "d37eTFvbbuPQcKt5vkgsx+6C4c0=",
+ "path": "golang.org/x/crypto/xtea",
+ "revision": "558b6879de74bc843225cde5686419267ff707ca",
+ "revisionTime": "2017-07-28T12:36:07Z"
+ },
+ {
+ "checksumSHA1": "9Pcc1IiRqPxEcxU2KMpkrcEGb3k=",
+ "path": "golang.org/x/net/bpf",
+ "revision": "84f0e6f92b10139f986b1756e149a7d9de270cdc",
+ "revisionTime": "2017-05-12T21:27:43Z"
+ },
+ {
+ "checksumSHA1": "Wl71V4Lh2iajiRnVAMPtd276vTg=",
+ "path": "golang.org/x/net/http2",
+ "revision": "84f0e6f92b10139f986b1756e149a7d9de270cdc",
+ "revisionTime": "2017-05-12T21:27:43Z"
+ },
+ {
+ "checksumSHA1": "4n0osCZJbirWKtbcyAg+Mb5PQ0k=",
+ "path": "golang.org/x/net/http2/hpack",
+ "revision": "84f0e6f92b10139f986b1756e149a7d9de270cdc",
+ "revisionTime": "2017-05-12T21:27:43Z"
+ },
+ {
+ "checksumSHA1": "VrzPJyWI6disCgYuVEQzkjqUsJk=",
+ "path": "golang.org/x/net/idna",
+ "revision": "84f0e6f92b10139f986b1756e149a7d9de270cdc",
+ "revisionTime": "2017-05-12T21:27:43Z"
+ },
+ {
+ "checksumSHA1": "ph4zMZHCWvSjVOZwoxbks+nG0/M=",
+ "path": "golang.org/x/net/internal/iana",
+ "revision": "84f0e6f92b10139f986b1756e149a7d9de270cdc",
+ "revisionTime": "2017-05-12T21:27:43Z"
+ },
+ {
+ "checksumSHA1": "5IbL5aAZfu+FMhrkv1soqQejTr4=",
+ "path": "golang.org/x/net/internal/netreflect",
+ "revision": "84f0e6f92b10139f986b1756e149a7d9de270cdc",
+ "revisionTime": "2017-05-12T21:27:43Z"
+ },
+ {
+ "checksumSHA1": "DVuL0YTpk4E8bRxkr2KXgzoCxw8=",
+ "path": "golang.org/x/net/ipv4",
+ "revision": "84f0e6f92b10139f986b1756e149a7d9de270cdc",
+ "revisionTime": "2017-05-12T21:27:43Z"
+ },
+ {
+ "checksumSHA1": "3xyuaSNmClqG4YWC7g0isQIbUTc=",
+ "path": "golang.org/x/net/lex/httplex",
+ "revision": "84f0e6f92b10139f986b1756e149a7d9de270cdc",
+ "revisionTime": "2017-05-12T21:27:43Z"
+ },
+ {
+ "checksumSHA1": "faFDXp++cLjLBlvsr+izZ+go1WU=",
+ "path": "golang.org/x/text/secure/bidirule",
+ "revision": "19e51611da83d6be54ddafce4a4af510cb3e9ea4",
+ "revisionTime": "2017-04-21T08:09:44Z"
+ },
+ {
+ "checksumSHA1": "ziMb9+ANGRJSSIuxYdRbA+cDRBQ=",
+ "path": "golang.org/x/text/transform",
+ "revision": "19e51611da83d6be54ddafce4a4af510cb3e9ea4",
+ "revisionTime": "2017-04-21T08:09:44Z"
+ },
+ {
+ "checksumSHA1": "KG+XZAbxdkpBm3Fa3bJ3Ylq8CKI=",
+ "path": "golang.org/x/text/unicode/bidi",
+ "revision": "19e51611da83d6be54ddafce4a4af510cb3e9ea4",
+ "revisionTime": "2017-04-21T08:09:44Z"
+ },
+ {
+ "checksumSHA1": "Anof4bt0AU+Sa3R8Rq0KBnlpbaQ=",
+ "path": "golang.org/x/text/unicode/norm",
+ "revision": "19e51611da83d6be54ddafce4a4af510cb3e9ea4",
+ "revisionTime": "2017-04-21T08:09:44Z"
+ },
+ {
+ "checksumSHA1": "G/v7O8ukxRnqPUrKYmf+niQ+JNU=",
+ "path": "gopkg.in/gorilla/websocket.v1",
+ "revision": "3ab3a8b8831546bd18fd182c20687ca853b2bb13",
+ "revisionTime": "2016-12-15T22:53:35Z"
+ },
+ {
+ "checksumSHA1": "FJUY4FAPSimDxXpnlZM8ou26ztE=",
+ "path": "gopkg.in/xtaci/kcp-go.v2",
+ "revision": "bf95749e1be2a3f152ba0004eae0c4f47fbf1251",
+ "revisionTime": "2017-03-04T10:43:02Z"
+ },
+ {
+ "checksumSHA1": "EutBuLS2elfcDCMifXNMGj9farQ=",
+ "path": "gopkg.in/xtaci/smux.v1",
+ "revision": "427dd804ce9fb0a9e7b27a628f68a124fb0d67a6",
+ "revisionTime": "2016-11-29T15:03:00Z"
+ }
+ ],
+ "rootPath": "github.com/ginuerzh/gost"
+}
diff --git a/ws.go b/ws.go
index da902e6..fb74845 100644
--- a/ws.go
+++ b/ws.go
@@ -2,105 +2,60 @@ package gost
import (
"crypto/tls"
- "github.com/golang/glog"
- "gopkg.in/gorilla/websocket.v1"
"net"
"net/http"
"net/http/httputil"
"time"
+
+ "net/url"
+
+ "github.com/go-log/log"
+ "gopkg.in/gorilla/websocket.v1"
)
-type WebsocketServer struct {
- Addr string
- Base *ProxyServer
- Handler http.Handler
- upgrader websocket.Upgrader
+// WSOptions describes the options for websocket.
+type WSOptions struct {
+ ReadBufferSize int
+ WriteBufferSize int
+ HandshakeTimeout time.Duration
+ EnableCompression bool
}
-func NewWebsocketServer(base *ProxyServer) *WebsocketServer {
- return &WebsocketServer{
- Addr: base.Node.Addr,
- Base: base,
- upgrader: websocket.Upgrader{
- ReadBufferSize: 1024,
- WriteBufferSize: 1024,
- CheckOrigin: func(r *http.Request) bool { return true },
- EnableCompression: true,
- },
- }
-}
-
-// Default websocket server handler
-func (s *WebsocketServer) HandleRequest(w http.ResponseWriter, r *http.Request) {
- glog.V(LINFO).Infof("[ws] %s - %s", r.RemoteAddr, s.Addr)
- if glog.V(LDEBUG) {
- dump, _ := httputil.DumpRequest(r, false)
- glog.V(LDEBUG).Infof("[ws] %s - %s\n%s", r.RemoteAddr, s.Addr, string(dump))
- }
- conn, err := s.upgrader.Upgrade(w, r, nil)
- if err != nil {
- glog.V(LERROR).Infof("[ws] %s - %s : %s", r.RemoteAddr, s.Addr, err)
- return
- }
- s.Base.handleConn(WebsocketServerConn(conn))
-}
-
-func (s *WebsocketServer) ListenAndServe() error {
- mux := http.NewServeMux()
- if s.Handler == nil {
- s.Handler = http.HandlerFunc(s.HandleRequest)
- }
- mux.Handle("/ws", s.Handler)
- return http.ListenAndServe(s.Addr, mux)
-}
-
-func (s *WebsocketServer) ListenAndServeTLS(config *tls.Config) error {
- mux := http.NewServeMux()
- if s.Handler == nil {
- s.Handler = http.HandlerFunc(s.HandleRequest)
- }
- mux.Handle("/ws", s.Handler)
- server := &http.Server{
- Addr: s.Addr,
- Handler: mux,
- TLSConfig: config,
- }
- return server.ListenAndServeTLS("", "")
-}
-
-type WebsocketConn struct {
+type websocketConn struct {
conn *websocket.Conn
rb []byte
}
-func WebsocketClientConn(url string, conn net.Conn, config *tls.Config) (*WebsocketConn, error) {
+func websocketClientConn(url string, conn net.Conn, tlsConfig *tls.Config, options *WSOptions) (net.Conn, error) {
+ if options == nil {
+ options = &WSOptions{}
+ }
dialer := websocket.Dialer{
- ReadBufferSize: 1024,
- WriteBufferSize: 1024,
- TLSClientConfig: config,
- HandshakeTimeout: DialTimeout,
- EnableCompression: true,
+ ReadBufferSize: options.ReadBufferSize,
+ WriteBufferSize: options.WriteBufferSize,
+ TLSClientConfig: tlsConfig,
+ HandshakeTimeout: options.HandshakeTimeout,
+ EnableCompression: options.EnableCompression,
NetDial: func(net, addr string) (net.Conn, error) {
return conn, nil
},
}
-
c, resp, err := dialer.Dial(url, nil)
if err != nil {
return nil, err
}
resp.Body.Close()
- return &WebsocketConn{conn: c}, nil
+ return &websocketConn{conn: c}, nil
}
-func WebsocketServerConn(conn *websocket.Conn) *WebsocketConn {
- conn.EnableWriteCompression(true)
- return &WebsocketConn{
+func websocketServerConn(conn *websocket.Conn) net.Conn {
+ // conn.EnableWriteCompression(true)
+ return &websocketConn{
conn: conn,
}
}
-func (c *WebsocketConn) Read(b []byte) (n int, err error) {
+func (c *websocketConn) Read(b []byte) (n int, err error) {
if len(c.rb) == 0 {
_, c.rb, err = c.conn.ReadMessage()
}
@@ -109,34 +64,236 @@ func (c *WebsocketConn) Read(b []byte) (n int, err error) {
return
}
-func (c *WebsocketConn) Write(b []byte) (n int, err error) {
+func (c *websocketConn) Write(b []byte) (n int, err error) {
err = c.conn.WriteMessage(websocket.BinaryMessage, b)
n = len(b)
return
}
-func (c *WebsocketConn) Close() error {
+func (c *websocketConn) Close() error {
return c.conn.Close()
}
-func (c *WebsocketConn) LocalAddr() net.Addr {
+func (c *websocketConn) LocalAddr() net.Addr {
return c.conn.LocalAddr()
}
-func (c *WebsocketConn) RemoteAddr() net.Addr {
+func (c *websocketConn) RemoteAddr() net.Addr {
return c.conn.RemoteAddr()
}
-func (conn *WebsocketConn) SetDeadline(t time.Time) error {
- if err := conn.SetReadDeadline(t); err != nil {
+func (c *websocketConn) SetDeadline(t time.Time) error {
+ if err := c.SetReadDeadline(t); err != nil {
return err
}
- return conn.SetWriteDeadline(t)
+ return c.SetWriteDeadline(t)
}
-func (c *WebsocketConn) SetReadDeadline(t time.Time) error {
+func (c *websocketConn) SetReadDeadline(t time.Time) error {
return c.conn.SetReadDeadline(t)
}
-func (c *WebsocketConn) SetWriteDeadline(t time.Time) error {
+func (c *websocketConn) SetWriteDeadline(t time.Time) error {
return c.conn.SetWriteDeadline(t)
}
+
+type wsTransporter struct {
+ tcpTransporter
+ options *WSOptions
+}
+
+// WSTransporter creates a Transporter that is used by websocket proxy client.
+func WSTransporter(opts *WSOptions) Transporter {
+ return &wsTransporter{
+ options: opts,
+ }
+}
+
+func (tr *wsTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
+ opts := &HandshakeOptions{}
+ for _, option := range options {
+ option(opts)
+ }
+ wsOptions := tr.options
+ if opts.WSOptions != nil {
+ wsOptions = opts.WSOptions
+ }
+ url := url.URL{Scheme: "ws", Host: opts.Addr, Path: "/ws"}
+ return websocketClientConn(url.String(), conn, nil, wsOptions)
+}
+
+type wssTransporter struct {
+ tcpTransporter
+ options *WSOptions
+}
+
+// WSSTransporter creates a Transporter that is used by websocket secure proxy client.
+func WSSTransporter(opts *WSOptions) Transporter {
+ return &wssTransporter{
+ options: opts,
+ }
+}
+
+func (tr *wssTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) {
+ opts := &HandshakeOptions{}
+ for _, option := range options {
+ option(opts)
+ }
+ wsOptions := tr.options
+ if opts.WSOptions != nil {
+ wsOptions = opts.WSOptions
+ }
+ if opts.TLSConfig == nil {
+ opts.TLSConfig = &tls.Config{InsecureSkipVerify: true}
+ }
+ url := url.URL{Scheme: "wss", Host: opts.Addr, Path: "/ws"}
+ return websocketClientConn(url.String(), conn, opts.TLSConfig, wsOptions)
+}
+
+type wsListener struct {
+ addr net.Addr
+ upgrader *websocket.Upgrader
+ srv *http.Server
+ connChan chan net.Conn
+ errChan chan error
+}
+
+// WSListener creates a Listener for websocket proxy server.
+func WSListener(addr string, options *WSOptions) (Listener, error) {
+ tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
+ if err != nil {
+ return nil, err
+ }
+ if options == nil {
+ options = &WSOptions{}
+ }
+ l := &wsListener{
+ addr: tcpAddr,
+ upgrader: &websocket.Upgrader{
+ ReadBufferSize: options.ReadBufferSize,
+ WriteBufferSize: options.WriteBufferSize,
+ CheckOrigin: func(r *http.Request) bool { return true },
+ EnableCompression: options.EnableCompression,
+ },
+ connChan: make(chan net.Conn, 1024),
+ errChan: make(chan error, 1),
+ }
+
+ mux := http.NewServeMux()
+ mux.Handle("/ws", http.HandlerFunc(l.upgrade))
+ l.srv = &http.Server{Addr: addr, Handler: mux}
+
+ ln, err := net.ListenTCP("tcp", tcpAddr)
+ if err != nil {
+ return nil, err
+ }
+
+ go func() {
+ err := l.srv.Serve(tcpKeepAliveListener{ln})
+ if err != nil {
+ l.errChan <- err
+ }
+ close(l.errChan)
+ }()
+ select {
+ case err := <-l.errChan:
+ return nil, err
+ default:
+ }
+
+ return l, nil
+}
+
+func (l *wsListener) upgrade(w http.ResponseWriter, r *http.Request) {
+ log.Logf("[ws] %s -> %s", r.RemoteAddr, l.addr)
+ if Debug {
+ dump, _ := httputil.DumpRequest(r, false)
+ log.Log(string(dump))
+ }
+ conn, err := l.upgrader.Upgrade(w, r, nil)
+ if err != nil {
+ log.Logf("[ws] %s - %s : %s", r.RemoteAddr, l.addr, err)
+ return
+ }
+ select {
+ case l.connChan <- websocketServerConn(conn):
+ default:
+ conn.Close()
+ log.Logf("[ws] %s - %s: connection queue is full", r.RemoteAddr, l.addr)
+ }
+}
+
+func (l *wsListener) Accept() (conn net.Conn, err error) {
+ select {
+ case conn = <-l.connChan:
+ case err = <-l.errChan:
+ }
+ return
+}
+
+func (l *wsListener) Close() error {
+ return l.srv.Close()
+}
+
+func (l *wsListener) Addr() net.Addr {
+ return l.addr
+}
+
+type wssListener struct {
+ *wsListener
+}
+
+// WSSListener creates a Listener for websocket secure proxy server.
+func WSSListener(addr string, tlsConfig *tls.Config, options *WSOptions) (Listener, error) {
+ tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
+ if err != nil {
+ return nil, err
+ }
+ if options == nil {
+ options = &WSOptions{}
+ }
+ l := &wssListener{
+ wsListener: &wsListener{
+ addr: tcpAddr,
+ upgrader: &websocket.Upgrader{
+ ReadBufferSize: options.ReadBufferSize,
+ WriteBufferSize: options.WriteBufferSize,
+ CheckOrigin: func(r *http.Request) bool { return true },
+ EnableCompression: options.EnableCompression,
+ },
+ connChan: make(chan net.Conn, 1024),
+ errChan: make(chan error, 1),
+ },
+ }
+
+ if tlsConfig == nil {
+ tlsConfig = DefaultTLSConfig
+ }
+
+ mux := http.NewServeMux()
+ mux.Handle("/ws", http.HandlerFunc(l.upgrade))
+ l.srv = &http.Server{
+ Addr: addr,
+ TLSConfig: tlsConfig,
+ Handler: mux,
+ }
+
+ ln, err := net.ListenTCP("tcp", tcpAddr)
+ if err != nil {
+ return nil, err
+ }
+
+ go func() {
+ err := l.srv.Serve(tls.NewListener(tcpKeepAliveListener{ln}, tlsConfig))
+ if err != nil {
+ l.errChan <- err
+ }
+ close(l.errChan)
+ }()
+ select {
+ case err := <-l.errChan:
+ return nil, err
+ default:
+ }
+
+ return l, nil
+}